/* No padding or other stuff needed. We can call PKCS11 from here */ static int pkcs11_ecdsa_sign(const unsigned char *msg, unsigned int msg_len, unsigned char *sigret, unsigned int *siglen, PKCS11_KEY *key) { int rv; PKCS11_SLOT *slot = KEY2SLOT(key); PKCS11_CTX *ctx = KEY2CTX(key); PKCS11_KEY_private *kpriv = PRIVKEY(key); PKCS11_SLOT_private *spriv = PRIVSLOT(slot); CK_MECHANISM mechanism; CK_ULONG ck_sigsize; ck_sigsize = *siglen; memset(&mechanism, 0, sizeof(mechanism)); mechanism.mechanism = CKM_ECDSA; CRYPTO_THREAD_write_lock(PRIVCTX(ctx)->rwlock); rv = CRYPTOKI_call(ctx, C_SignInit(spriv->session, &mechanism, kpriv->object)); if (!rv && kpriv->always_authenticate == CK_TRUE) rv = pkcs11_authenticate(key); if (!rv) rv = CRYPTOKI_call(ctx, C_Sign(spriv->session, (CK_BYTE *)msg, msg_len, sigret, &ck_sigsize)); CRYPTO_THREAD_unlock(PRIVCTX(ctx)->rwlock); if (rv) { CKRerr(CKR_F_PKCS11_ECDSA_SIGN, rv); return -1; } *siglen = ck_sigsize; return ck_sigsize; }
/* * Return keys of a given type (public or private) * Use the cached values if available */ int pkcs11_enumerate_keys(PKCS11_TOKEN *token, unsigned int type, PKCS11_KEY ** keyp, unsigned int *countp) { PKCS11_SLOT *slot = TOKEN2SLOT(token); PKCS11_CTX *ctx = TOKEN2CTX(token); PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token); PKCS11_SLOT_private *spriv = PRIVSLOT(slot); PKCS11_CTX_private *cpriv = PRIVCTX(ctx); PKCS11_keys *keys = (type == CKO_PRIVATE_KEY) ? &tpriv->prv : &tpriv->pub; int rv; if (keys->num < 0) { /* No cache was built for the specified type */ /* Make sure we have a session */ if (!spriv->haveSession && PKCS11_open_session(slot, 0)) return -1; CRYPTO_THREAD_write_lock(cpriv->rwlock); rv = pkcs11_find_keys(token, type); CRYPTO_THREAD_unlock(cpriv->rwlock); if (rv < 0) { pkcs11_destroy_keys(token, type); return -1; } } if (keyp) *keyp = keys->keys; if (countp) *countp = keys->num; return 0; }
/* * Helper functions */ static int pkcs11_init_slot(PKCS11_CTX * ctx, PKCS11_SLOT * slot, CK_SLOT_ID id) { PKCS11_SLOT_private *priv; CK_SLOT_INFO info; int rv; rv = CRYPTOKI_call(ctx, C_GetSlotInfo(id, &info)); CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_SLOTS, rv); priv = OPENSSL_malloc(sizeof(PKCS11_SLOT_private)); if (priv == NULL) return -1; memset(priv, 0, sizeof(PKCS11_SLOT_private)); priv->parent = ctx; priv->id = id; priv->forkid = PRIVCTX(ctx)->forkid; priv->prev_rw = 0; priv->prev_pin = NULL; priv->prev_so = 0; priv->lockid = CRYPTO_get_new_dynlockid(); slot->description = PKCS11_DUP(info.slotDescription); slot->manufacturer = PKCS11_DUP(info.manufacturerID); slot->removable = (info.flags & CKF_REMOVABLE_DEVICE) ? 1 : 0; slot->_private = priv; if ((info.flags & CKF_TOKEN_PRESENT) && pkcs11_check_token(ctx, slot)) return -1; return 0; }
/* * Enumerate all certs on the card */ int pkcs11_enumerate_certs(PKCS11_TOKEN *token, PKCS11_CERT **certp, unsigned int *countp) { PKCS11_SLOT *slot = TOKEN2SLOT(token); PKCS11_CTX *ctx = SLOT2CTX(slot); PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token); PKCS11_SLOT_private *spriv = PRIVSLOT(slot); PKCS11_CTX_private *cpriv = PRIVCTX(ctx); int rv; if (tpriv->ncerts < 0) { /* Make sure we have a session */ if (!spriv->haveSession && PKCS11_open_session(slot, 0)) return -1; CRYPTO_THREAD_write_lock(cpriv->rwlock); rv = pkcs11_find_certs(token); CRYPTO_THREAD_unlock(cpriv->rwlock); if (rv < 0) { pkcs11_destroy_certs(token); return -1; } } if (certp) *certp = tpriv->certs; if (countp) *countp = tpriv->ncerts; return 0; }
/* * Reinitialize (e.g., after a fork). */ int pkcs11_CTX_reload(PKCS11_CTX * ctx) { PKCS11_CTX_private *cpriv = PRIVCTX(ctx); CK_C_INITIALIZE_ARGS _args; CK_C_INITIALIZE_ARGS *args = NULL; int rv; if (cpriv->method == NULL) /* Module not loaded */ return 0; /* Tell the PKCS11 to initialize itself */ if (cpriv->init_args != NULL) { memset(&_args, 0, sizeof(_args)); args = &_args; args->pReserved = cpriv->init_args; } rv = cpriv->method->C_Initialize(args); if (rv && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) { PKCS11err(PKCS11_F_PKCS11_CTX_LOAD, rv); return -1; } /* Reinitialize the PKCS11 internal slot table */ return pkcs11_enumerate_slots(ctx, NULL, NULL); }
/* * Load the shared library, and initialize it. */ int PKCS11_CTX_load(PKCS11_CTX * ctx, const char *name) { PKCS11_CTX_private *priv = PRIVCTX(ctx); CK_C_INITIALIZE_ARGS args; CK_INFO ck_info; int rv; if (priv->libinfo != NULL) { PKCS11err(PKCS11_F_PKCS11_CTX_LOAD, PKCS11_MODULE_LOADED_ERROR); return -1; } handle = C_LoadModule(name, &priv->method); if (!handle) { PKCS11err(PKCS11_F_PKCS11_CTX_LOAD, PKCS11_LOAD_MODULE_ERROR); return -1; } /* Tell the PKCS11 to initialize itself */ memset(&args, 0, sizeof(args)); args.pReserved = priv->init_args; rv = priv->method->C_Initialize(&args); if (rv && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) { PKCS11err(PKCS11_F_PKCS11_CTX_LOAD, rv); return -1; } /* Get info on the library */ rv = priv->method->C_GetInfo(&ck_info); CRYPTOKI_checkerr(PKCS11_F_PKCS11_CTX_LOAD, rv); ctx->manufacturer = PKCS11_DUP(ck_info.manufacturerID); ctx->description = PKCS11_DUP(ck_info.libraryDescription); return 0; }
/* * Set private init args for module */ void pkcs11_CTX_init_args(PKCS11_CTX * ctx, const char *init_args) { PKCS11_CTX_private *cpriv = PRIVCTX(ctx); /* Free previously duplicated string */ if (cpriv->init_args) { OPENSSL_free(cpriv->init_args); } cpriv->init_args = init_args ? OPENSSL_strdup(init_args) : NULL; }
/* * Unload the shared library */ void PKCS11_CTX_unload(PKCS11_CTX * ctx) { PKCS11_CTX_private *priv; priv = PRIVCTX(ctx); /* Tell the PKCS11 library to shut down */ priv->method->C_Finalize(NULL); /* Unload the module */ C_UnloadModule(handle); }
/* * Unload the shared library */ void pkcs11_CTX_unload(PKCS11_CTX * ctx) { PKCS11_CTX_private *cpriv; cpriv = PRIVCTX(ctx); /* Tell the PKCS11 library to shut down */ if (cpriv->forkid == _P11_get_forkid()) cpriv->method->C_Finalize(NULL); /* Unload the module */ C_UnloadModule(cpriv->handle); }
/* * Free a context */ void pkcs11_CTX_free(PKCS11_CTX * ctx) { PKCS11_CTX_private *cpriv = PRIVCTX(ctx); /* TODO: Move the global methods and ex_data indexes into * the ctx structure, so they can be safely deallocated here: PKCS11_rsa_method_free(ctx); PKCS11_ecdsa_method_free(ctx); */ if (cpriv->init_args) { OPENSSL_free(cpriv->init_args); } CRYPTO_THREAD_lock_free(cpriv->rwlock); OPENSSL_free(ctx->manufacturer); OPENSSL_free(ctx->description); OPENSSL_free(ctx->_private); OPENSSL_free(ctx); }
int pkcs11_enumerate_slots(PKCS11_CTX * ctx, PKCS11_SLOT ** slotp, unsigned int *countp) { PKCS11_CTX_private *priv; CK_SLOT_ID *slotid; CK_ULONG nslots, n; PKCS11_SLOT *slots; int rv; priv = PRIVCTX(ctx); rv = priv->method->C_GetSlotList(FALSE, NULL_PTR, &nslots); CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_SLOTS, rv); slotid = OPENSSL_malloc(nslots * sizeof(CK_SLOT_ID)); if (slotid == NULL) return -1; rv = priv->method->C_GetSlotList(FALSE, slotid, &nslots); CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_SLOTS, rv); slots = OPENSSL_malloc(nslots * sizeof(PKCS11_SLOT)); if (slots == NULL) return -1; memset(slots, 0, nslots * sizeof(PKCS11_SLOT)); for (n = 0; n < nslots; n++) { if (pkcs11_init_slot(ctx, &slots[n], slotid[n])) { while (n--) pkcs11_release_slot(ctx, slots + n); OPENSSL_free(slotid); OPENSSL_free(slots); return -1; } } if (slotp) *slotp = slots; else OPENSSL_free(slots); if (countp) *countp = nslots; OPENSSL_free(slotid); return 0; }
/* * Load the shared library, and initialize it. */ int pkcs11_CTX_load(PKCS11_CTX * ctx, const char *name) { PKCS11_CTX_private *cpriv = PRIVCTX(ctx); CK_C_INITIALIZE_ARGS _args; CK_C_INITIALIZE_ARGS *args = NULL; CK_INFO ck_info; int rv; cpriv->handle = C_LoadModule(name, &cpriv->method); if (cpriv->handle == NULL) { PKCS11err(PKCS11_F_PKCS11_CTX_LOAD, PKCS11_LOAD_MODULE_ERROR); return -1; } /* Tell the PKCS11 to initialize itself */ if (cpriv->init_args != NULL) { memset(&_args, 0, sizeof(_args)); args = &_args; /* Unconditionally say using OS locking primitives is OK */ args->flags |= CKF_OS_LOCKING_OK; args->pReserved = cpriv->init_args; } rv = cpriv->method->C_Initialize(args); if (rv && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) { PKCS11err(PKCS11_F_PKCS11_CTX_LOAD, rv); return -1; } /* Get info on the library */ rv = cpriv->method->C_GetInfo(&ck_info); CRYPTOKI_checkerr(PKCS11_F_PKCS11_CTX_LOAD, rv); ctx->manufacturer = PKCS11_DUP(ck_info.manufacturerID); ctx->description = PKCS11_DUP(ck_info.libraryDescription); return 0; }
/* * Set private init args for module */ void PKCS11_CTX_init_args(PKCS11_CTX * ctx, const char *init_args) { PKCS11_CTX_private *priv = PRIVCTX(ctx); priv->init_args = init_args ? strdup(init_args) : NULL; }