static void pkcs11_destroy_token(PKCS11_TOKEN * token) { pkcs11_destroy_keys(token, CKO_PRIVATE_KEY); pkcs11_destroy_keys(token, CKO_PUBLIC_KEY); pkcs11_destroy_certs(token); OPENSSL_free(token->label); OPENSSL_free(token->manufacturer); OPENSSL_free(token->model); OPENSSL_free(token->serialnr); OPENSSL_free(token->_private); memset(token, 0, sizeof(*token)); }
/* * 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; }
/* * Authenticate with the card. relogin should be set if we automatically * relogin after a fork. */ static int pkcs11_login(PKCS11_SLOT * slot, int so, const char *pin, int relogin) { PKCS11_SLOT_private *priv = PRIVSLOT(slot); PKCS11_CTX *ctx = priv->parent; int rv; if (relogin == 0) { CHECK_SLOT_FORK(slot); /* Calling PKCS11_login invalidates all cached * keys we have */ if (slot->token) { pkcs11_destroy_keys(slot->token, CKO_PRIVATE_KEY); pkcs11_destroy_keys(slot->token, CKO_PUBLIC_KEY); } if (priv->loggedIn) { /* already logged in, log out first */ if (PKCS11_logout(slot)) return -1; } } if (!priv->haveSession) { /* SO gets a r/w session by default, * user gets a r/o session by default. */ if (pkcs11_open_session(slot, so, relogin)) return -1; } rv = CRYPTOKI_call(ctx, C_Login(priv->session, so ? CKU_SO : CKU_USER, (CK_UTF8CHAR *) pin, pin ? strlen(pin) : 0)); if (rv && rv != CKR_USER_ALREADY_LOGGED_IN) /* logged in -> OK */ CRYPTOKI_checkerr(PKCS11_F_PKCS11_LOGIN, rv); priv->loggedIn = 1; if (priv->prev_pin != pin) { if (priv->prev_pin) { OPENSSL_cleanse(priv->prev_pin, strlen(priv->prev_pin)); OPENSSL_free(priv->prev_pin); } priv->prev_pin = BUF_strdup(pin); } priv->prev_so = so; return 0; }
/* * Log out */ int PKCS11_logout(PKCS11_SLOT * slot) { PKCS11_SLOT_private *priv = PRIVSLOT(slot); PKCS11_CTX *ctx = priv->parent; int rv; CHECK_SLOT_FORK(slot); /* Calling PKCS11_logout invalidates all cached * keys we have */ if (slot->token) { pkcs11_destroy_keys(slot->token, CKO_PRIVATE_KEY); pkcs11_destroy_keys(slot->token, CKO_PUBLIC_KEY); } if (!priv->haveSession) { PKCS11err(PKCS11_F_PKCS11_LOGOUT, PKCS11_NO_SESSION); return -1; } rv = CRYPTOKI_call(ctx, C_Logout(priv->session)); CRYPTOKI_checkerr(PKCS11_F_PKCS11_LOGOUT, rv); priv->loggedIn = 0; return 0; }