/* * sc-pkcs11.h: OpenSC project's PKCS#11 implementation header * * Copyright (C) 2002 Timo Teräs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __sc_pkcs11_h__ #define __sc_pkcs11_h__ #include "config.h" #include "libopensc/opensc.h" #include "libopensc/pkcs15.h" #include "libopensc/log.h" #define CRYPTOKI_EXPORTS #include "pkcs11.h" #include "pkcs11-opensc.h" #include "pkcs11-display.h" #ifdef __cplusplus extern "C" { #endif #define SC_PKCS11_PIN_UNBLOCK_NOT_ALLOWED 0 #define SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN 1 #define SC_PKCS11_PIN_UNBLOCK_SCONTEXT_SETPIN 2 #define SC_PKCS11_PIN_UNBLOCK_SO_LOGGED_INITPIN 3 #define SC_PKCS11_SLOT_FOR_PIN_USER 1 #define SC_PKCS11_SLOT_FOR_PIN_SIGN 2 #define SC_PKCS11_SLOT_CREATE_ALL 8 #define SC_PKCS11_SLOT_FOR_PINS (SC_PKCS11_SLOT_FOR_PIN_USER | SC_PKCS11_SLOT_FOR_PIN_SIGN) #ifdef __cplusplus } #endif /* Decide whether to use pkcs11 for initialization support */ #ifdef ENABLE_OPENSSL #define USE_PKCS15_INIT #endif #ifdef __cplusplus extern "C" { #endif struct sc_pkcs11_session; struct sc_pkcs11_slot; struct sc_pkcs11_card; struct sc_pkcs11_config { unsigned int max_virtual_slots; unsigned int slots_per_card; unsigned char lock_login; unsigned char atomic; unsigned char init_sloppy; unsigned int pin_unblock_style; unsigned int create_puk_slot; unsigned int create_slots_flags; unsigned char ignore_pin_length; }; /* * PKCS#11 Object abstraction layer */ struct sc_pkcs11_object_ops { /* Generic operations */ void (*release)(void *); /* Management methods */ CK_RV (*set_attribute)(struct sc_pkcs11_session *, void *, CK_ATTRIBUTE_PTR); CK_RV (*get_attribute)(struct sc_pkcs11_session *, void *, CK_ATTRIBUTE_PTR); CK_RV (*cmp_attribute)(struct sc_pkcs11_session *, void *, CK_ATTRIBUTE_PTR); CK_RV (*destroy_object)(struct sc_pkcs11_session *, void *); CK_RV (*get_size)(struct sc_pkcs11_session *, void *); /* Cryptographic methods */ CK_RV (*sign)(struct sc_pkcs11_session *, void *, CK_MECHANISM_PTR, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulDataLen); CK_RV (*unwrap_key)(struct sc_pkcs11_session *, void *, CK_MECHANISM_PTR, CK_BYTE_PTR pData, CK_ULONG ulDataLen, void *targetKey); CK_RV (*decrypt)(struct sc_pkcs11_session *, void *, CK_MECHANISM_PTR, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen); CK_RV (*derive)(struct sc_pkcs11_session *, void *, CK_MECHANISM_PTR, CK_BYTE_PTR pSeedData, CK_ULONG ulSeedDataLen, CK_BYTE_PTR pDerived, CK_ULONG_PTR pulDerivedLen); /* Check compatibility of PKCS#15 object usage and an asked PKCS#11 mechanism. */ CK_RV (*can_do)(struct sc_pkcs11_session *, void *, CK_MECHANISM_TYPE, unsigned int); /* General validation of mechanism parameters (sign, encrypt, etc) */ CK_RV (*init_params)(struct sc_pkcs11_session *, CK_MECHANISM_PTR); CK_RV (*wrap_key)(struct sc_pkcs11_session *, void *, CK_MECHANISM_PTR, void*, CK_BYTE_PTR pData, CK_ULONG_PTR ulDataLen); /* Others to be added when implemented */ }; struct sc_pkcs11_object { CK_OBJECT_HANDLE handle; int flags; struct sc_pkcs11_object_ops *ops; }; #define SC_PKCS11_OBJECT_SEEN 0x0001 #define SC_PKCS11_OBJECT_HIDDEN 0x0002 #define SC_PKCS11_OBJECT_RECURS 0x8000 /* * PKCS#11 smart card Framework abstraction */ struct sc_pkcs11_framework_ops { /* Detect and bind card to framework */ CK_RV (*bind)(struct sc_pkcs11_card *, struct sc_app_info *); /* Unbind and release allocated resources */ CK_RV (*unbind)(struct sc_pkcs11_card *); /* Create tokens to virtual slots and * objects in tokens; called after bind */ CK_RV (*create_tokens)(struct sc_pkcs11_card *, struct sc_app_info *); CK_RV (*release_token)(struct sc_pkcs11_card *, void *); /* Login and logout */ CK_RV (*login)(struct sc_pkcs11_slot *, CK_USER_TYPE, CK_CHAR_PTR, CK_ULONG); CK_RV (*logout)(struct sc_pkcs11_slot *); CK_RV (*change_pin)(struct sc_pkcs11_slot *, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR, CK_ULONG); /* * In future: functions to create new objects (i.e. certificates, private keys) */ CK_RV (*init_token)(struct sc_pkcs11_slot *, void *, CK_UTF8CHAR_PTR, CK_ULONG, CK_UTF8CHAR_PTR); CK_RV (*init_pin)(struct sc_pkcs11_slot *, CK_UTF8CHAR_PTR, CK_ULONG); CK_RV (*create_object)(struct sc_pkcs11_slot *, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR); CK_RV (*gen_keypair)(struct sc_pkcs11_slot *, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR, CK_OBJECT_HANDLE_PTR); CK_RV (*get_random)(struct sc_pkcs11_slot *, CK_BYTE_PTR, CK_ULONG); }; /* * PKCS#11 Slot (used to access card with specific framework data) */ #ifndef _WIN32 typedef unsigned long long sc_timestamp_t; #else typedef unsigned __int64 sc_timestamp_t; #endif #define SC_PKCS11_FRAMEWORK_DATA_MAX_NUM 4 struct sc_pkcs11_card { sc_reader_t *reader; sc_card_t *card; struct sc_pkcs11_framework_ops *framework; void *fws_data[SC_PKCS11_FRAMEWORK_DATA_MAX_NUM]; /* List of supported mechanisms */ struct sc_pkcs11_mechanism_type **mechanisms; unsigned int nmechanisms; }; /* If the slot did already show with `C_GetSlotList`, then we need to keep this * slot alive. PKCS#11 2.30 allows allows adding but not removing slots until * the application calls `C_GetSlotList` with `NULL`. This flag tracks the * visibility to the application */ #define SC_PKCS11_SLOT_FLAG_SEEN 1 struct sc_pkcs11_slot { CK_SLOT_ID id; /* ID of the slot */ int login_user; /* Currently logged in user */ CK_SLOT_INFO slot_info; /* Slot specific information (information about reader) */ CK_TOKEN_INFO token_info; /* Token specific information (information about card) */ sc_reader_t *reader; /* same as card->reader if there's a card present */ struct sc_pkcs11_card *p11card; /* The card associated with this slot */ unsigned int events; /* Card events SC_EVENT_CARD_{INSERTED,REMOVED} */ void *fw_data; /* Framework specific data */ /* TODO: get know how it used */ list_t objects; /* Objects in this slot */ unsigned int nsessions; /* Number of sessions using this slot */ sc_timestamp_t slot_state_expires; int fw_data_idx; /* Index of framework data */ struct sc_app_info *app_info; /* Application associated to slot */ list_t logins; /* tracks all calls to C_Login if atomic operations are requested */ int flags; }; typedef struct sc_pkcs11_slot sc_pkcs11_slot_t; /* Debug virtual slots. S is slot to be highlighted or NULL * C is a comment format string and args It will be preceded by "VSS " */ #define DEBUG_VSS(S, ...) do { sc_log(context,"VSS " __VA_ARGS__); _debug_virtual_slots(S); } while (0) /* called by DEBUG_VSS to print table of virtual slots */ void _debug_virtual_slots(sc_pkcs11_slot_t *p); /* Forward decl */ typedef struct sc_pkcs11_operation sc_pkcs11_operation_t; enum { SC_PKCS11_OPERATION_FIND = 0, SC_PKCS11_OPERATION_SIGN, SC_PKCS11_OPERATION_VERIFY, SC_PKCS11_OPERATION_DIGEST, SC_PKCS11_OPERATION_DECRYPT, SC_PKCS11_OPERATION_DERIVE, SC_PKCS11_OPERATION_WRAP, SC_PKCS11_OPERATION_UNWRAP, SC_PKCS11_OPERATION_MAX }; /* This describes a PKCS11 mechanism */ struct sc_pkcs11_mechanism_type { CK_MECHANISM_TYPE mech; /* algorithm: md5, sha1, ... */ CK_MECHANISM_INFO mech_info; /* mechanism info */ CK_MECHANISM_TYPE key_type; /* for sign/decipher ops */ unsigned int obj_size; /* General management */ void (*release)(sc_pkcs11_operation_t *); /* Digest/sign Operations */ CK_RV (*md_init)(sc_pkcs11_operation_t *); CK_RV (*md_update)(sc_pkcs11_operation_t *, CK_BYTE_PTR, CK_ULONG); CK_RV (*md_final)(sc_pkcs11_operation_t *, CK_BYTE_PTR, CK_ULONG_PTR); CK_RV (*sign_init)(sc_pkcs11_operation_t *, struct sc_pkcs11_object *); CK_RV (*sign_update)(sc_pkcs11_operation_t *, CK_BYTE_PTR, CK_ULONG); CK_RV (*sign_final)(sc_pkcs11_operation_t *, CK_BYTE_PTR, CK_ULONG_PTR); CK_RV (*sign_size)(sc_pkcs11_operation_t *, CK_ULONG_PTR); CK_RV (*verif_init)(sc_pkcs11_operation_t *, struct sc_pkcs11_object *); CK_RV (*verif_update)(sc_pkcs11_operation_t *, CK_BYTE_PTR, CK_ULONG); CK_RV (*verif_final)(sc_pkcs11_operation_t *, CK_BYTE_PTR, CK_ULONG); CK_RV (*decrypt_init)(sc_pkcs11_operation_t *, struct sc_pkcs11_object *); CK_RV (*decrypt)(sc_pkcs11_operation_t *, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR); CK_RV (*derive)(sc_pkcs11_operation_t *, struct sc_pkcs11_object *, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR); CK_RV (*wrap)(sc_pkcs11_operation_t *, struct sc_pkcs11_object *, struct sc_pkcs11_object *, CK_BYTE_PTR, CK_ULONG_PTR); CK_RV (*unwrap)(sc_pkcs11_operation_t *, struct sc_pkcs11_object *, CK_BYTE_PTR, CK_ULONG, struct sc_pkcs11_object *); /* mechanism specific data */ const void * mech_data; /* free mechanism specific data */ void (*free_mech_data)(const void *mech_data); }; typedef struct sc_pkcs11_mechanism_type sc_pkcs11_mechanism_type_t; /* * Generic operation */ struct sc_pkcs11_operation { sc_pkcs11_mechanism_type_t *type; CK_MECHANISM mechanism; union { CK_RSA_PKCS_PSS_PARAMS pss; CK_RSA_PKCS_OAEP_PARAMS oaep; } mechanism_params; struct sc_pkcs11_session *session; void * priv_data; }; /* Find Operation */ #define SC_PKCS11_FIND_INC_HANDLES 32 struct sc_pkcs11_find_operation { struct sc_pkcs11_operation operation; int num_handles, current_handle, allocated_handles; CK_OBJECT_HANDLE *handles; }; /* * PKCS#11 Session */ struct sc_pkcs11_session { CK_SESSION_HANDLE handle; /* Session to this slot */ struct sc_pkcs11_slot *slot; CK_FLAGS flags; /* Notifications */ CK_NOTIFY notify_callback; CK_VOID_PTR notify_data; /* Active operations - one per type */ struct sc_pkcs11_operation *operation[SC_PKCS11_OPERATION_MAX]; }; typedef struct sc_pkcs11_session sc_pkcs11_session_t; /* Module variables */ extern struct sc_context *context; extern struct sc_pkcs11_config sc_pkcs11_conf; extern list_t sessions; extern list_t virtual_slots; extern list_t cards; /* Framework definitions */ extern struct sc_pkcs11_framework_ops framework_pkcs15; extern struct sc_pkcs11_framework_ops framework_pkcs15init; void strcpy_bp(u8 *dst, const char *src, size_t dstsize); CK_RV sc_to_cryptoki_error(int rc, const char *ctx); void sc_pkcs11_print_attrs(int level, const char *file, unsigned int line, const char *function, const char *info, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); #define dump_template(level, info, pTemplate, ulCount) \ sc_pkcs11_print_attrs(level, __FILE__, __LINE__, __FUNCTION__, \ info, pTemplate, ulCount) /* Slot and card handling functions */ CK_RV card_removed(sc_reader_t *reader); CK_RV card_detect_all(void); CK_RV create_slot(sc_reader_t *reader); void init_slot_info(CK_SLOT_INFO_PTR pInfo, sc_reader_t *reader); CK_RV card_detect(sc_reader_t *reader); CK_RV slot_get_slot(CK_SLOT_ID id, struct sc_pkcs11_slot **); CK_RV slot_get_token(CK_SLOT_ID id, struct sc_pkcs11_slot **); CK_RV slot_token_removed(CK_SLOT_ID id); CK_RV slot_allocate(struct sc_pkcs11_slot **, struct sc_pkcs11_card *); CK_RV slot_find_changed(CK_SLOT_ID_PTR idp, int mask); int slot_get_logged_in_state(struct sc_pkcs11_slot *slot); /* Login tracking functions */ CK_RV restore_login_state(struct sc_pkcs11_slot *slot); CK_RV reset_login_state(struct sc_pkcs11_slot *slot, CK_RV rv); CK_RV push_login_state(struct sc_pkcs11_slot *slot, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen); void pop_login_state(struct sc_pkcs11_slot *slot); void pop_all_login_states(struct sc_pkcs11_slot *slot); /* Session manipulation */ CK_RV get_session(CK_SESSION_HANDLE hSession, struct sc_pkcs11_session ** session); CK_RV session_start_operation(struct sc_pkcs11_session *, int, sc_pkcs11_mechanism_type_t *, struct sc_pkcs11_operation **); CK_RV session_get_operation(struct sc_pkcs11_session *, int, struct sc_pkcs11_operation **); CK_RV session_stop_operation(struct sc_pkcs11_session *, int); CK_RV sc_pkcs11_close_all_sessions(CK_SLOT_ID); /* Generic secret key stuff */ CK_RV sc_pkcs11_create_secret_key(struct sc_pkcs11_session *, const u8 *, size_t, CK_ATTRIBUTE_PTR, CK_ULONG, struct sc_pkcs11_object **); /* Generic object handling */ CK_RV sc_pkcs11_any_cmp_attribute(struct sc_pkcs11_session *, void *, CK_ATTRIBUTE_PTR); /* Get attributes from template (misc.c) */ CK_RV attr_find(CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, void *, size_t *); CK_RV attr_find2(CK_ATTRIBUTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, void *, size_t *); CK_RV attr_find_ptr(CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, void **, size_t *); CK_RV attr_find_ptr2(CK_ATTRIBUTE_PTR pTemp1, CK_ULONG ulCount1, CK_ATTRIBUTE_PTR pTemp2, CK_ULONG ulCount2, CK_ULONG type, void **ptr, size_t * sizep); CK_RV attr_find_and_allocate_ptr(CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, void **, size_t *); CK_RV attr_find_var(CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, void *, size_t *); CK_RV attr_extract(CK_ATTRIBUTE_PTR, void *, size_t *); /* Generic Mechanism functions */ CK_RV sc_pkcs11_register_mechanism(struct sc_pkcs11_card *, sc_pkcs11_mechanism_type_t *); CK_RV sc_pkcs11_get_mechanism_list(struct sc_pkcs11_card *, CK_MECHANISM_TYPE_PTR, CK_ULONG_PTR); CK_RV sc_pkcs11_get_mechanism_info(struct sc_pkcs11_card *, CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR); CK_RV sc_pkcs11_md_init(struct sc_pkcs11_session *, CK_MECHANISM_PTR); CK_RV sc_pkcs11_md_update(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG); CK_RV sc_pkcs11_md_final(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG_PTR); CK_RV sc_pkcs11_sign_init(struct sc_pkcs11_session *, CK_MECHANISM_PTR, struct sc_pkcs11_object *, CK_MECHANISM_TYPE); CK_RV sc_pkcs11_sign_update(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG); CK_RV sc_pkcs11_sign_final(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG_PTR); CK_RV sc_pkcs11_sign_size(struct sc_pkcs11_session *, CK_ULONG_PTR); #ifdef ENABLE_OPENSSL CK_RV sc_pkcs11_verif_init(struct sc_pkcs11_session *, CK_MECHANISM_PTR, struct sc_pkcs11_object *, CK_MECHANISM_TYPE); CK_RV sc_pkcs11_verif_update(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG); CK_RV sc_pkcs11_verif_final(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG); #endif CK_RV sc_pkcs11_decr_init(struct sc_pkcs11_session *, CK_MECHANISM_PTR, struct sc_pkcs11_object *, CK_MECHANISM_TYPE); CK_RV sc_pkcs11_decr(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR); CK_RV sc_pkcs11_wrap(struct sc_pkcs11_session *,CK_MECHANISM_PTR, struct sc_pkcs11_object *, CK_KEY_TYPE, struct sc_pkcs11_object *, CK_BYTE_PTR, CK_ULONG_PTR); CK_RV sc_pkcs11_unwrap(struct sc_pkcs11_session *,CK_MECHANISM_PTR, struct sc_pkcs11_object *, CK_KEY_TYPE, CK_BYTE_PTR, CK_ULONG, struct sc_pkcs11_object *); CK_RV sc_pkcs11_deri(struct sc_pkcs11_session *, CK_MECHANISM_PTR, struct sc_pkcs11_object *, CK_KEY_TYPE, CK_SESSION_HANDLE, CK_OBJECT_HANDLE, struct sc_pkcs11_object *); sc_pkcs11_mechanism_type_t *sc_pkcs11_find_mechanism(struct sc_pkcs11_card *, CK_MECHANISM_TYPE, unsigned int); sc_pkcs11_mechanism_type_t *sc_pkcs11_new_fw_mechanism(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR, CK_KEY_TYPE, const void *, void (*)(const void *)); sc_pkcs11_operation_t *sc_pkcs11_new_operation(sc_pkcs11_session_t *, sc_pkcs11_mechanism_type_t *); void sc_pkcs11_release_operation(sc_pkcs11_operation_t **); CK_RV sc_pkcs11_register_generic_mechanisms(struct sc_pkcs11_card *); #ifdef ENABLE_OPENSSL void sc_pkcs11_register_openssl_mechanisms(struct sc_pkcs11_card *); #endif CK_RV sc_pkcs11_register_sign_and_hash_mechanism(struct sc_pkcs11_card *, CK_MECHANISM_TYPE, CK_MECHANISM_TYPE, sc_pkcs11_mechanism_type_t *); #ifdef ENABLE_OPENSSL CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, unsigned int pubkey_len, const unsigned char *pubkey_params, unsigned int pubkey_params_len, CK_MECHANISM_PTR mech, sc_pkcs11_operation_t *md, unsigned char *inp, unsigned int inp_len, unsigned char *signat, unsigned int signat_len); #endif /* Load configuration defaults */ void load_pkcs11_parameters(struct sc_pkcs11_config *, struct sc_context *); /* Locking primitives at the pkcs11 level */ CK_RV sc_pkcs11_init_lock(CK_C_INITIALIZE_ARGS_PTR); CK_RV sc_pkcs11_lock(void); void sc_pkcs11_unlock(void); void sc_pkcs11_free_lock(void); #ifdef __cplusplus } #endif #endif /* __sc_pkcs11_h__ */