/* * Find all keys of a given type (public or private) */ static int pkcs11_find_keys(PKCS11_TOKEN *token, unsigned int type) { PKCS11_SLOT *slot = TOKEN2SLOT(token); PKCS11_CTX *ctx = TOKEN2CTX(token); PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token); PKCS11_SLOT_private *spriv = PRIVSLOT(slot); PKCS11_keys *keys = (type == CKO_PRIVATE_KEY) ? &tpriv->prv : &tpriv->pub; CK_OBJECT_CLASS key_search_class; CK_ATTRIBUTE key_search_attrs[1] = { {CKA_CLASS, &key_search_class, sizeof(key_search_class)}, }; int rv, res = -1; /* Tell the PKCS11 lib to enumerate all matching objects */ key_search_class = type; rv = CRYPTOKI_call(ctx, C_FindObjectsInit(spriv->session, key_search_attrs, 1)); CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_KEYS, rv); keys->num = 0; do { res = pkcs11_next_key(ctx, token, spriv->session, type); } while (res == 0); CRYPTOKI_call(ctx, C_FindObjectsFinal(spriv->session)); return (res < 0) ? -1 : 0; }
/* * 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; }
/* * Find all certs of a given type (public or private) */ static int pkcs11_find_certs(PKCS11_TOKEN *token) { PKCS11_SLOT *slot = TOKEN2SLOT(token); PKCS11_CTX *ctx = SLOT2CTX(slot); PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token); PKCS11_SLOT_private *spriv = PRIVSLOT(slot); CK_OBJECT_CLASS cert_search_class; CK_ATTRIBUTE cert_search_attrs[] = { {CKA_CLASS, &cert_search_class, sizeof(cert_search_class)}, }; int rv, res = -1; /* Tell the PKCS11 lib to enumerate all matching objects */ cert_search_class = CKO_CERTIFICATE; rv = CRYPTOKI_call(ctx, C_FindObjectsInit(spriv->session, cert_search_attrs, 1)); CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_CERTS, rv); tpriv->ncerts = 0; do { res = pkcs11_next_cert(ctx, token, spriv->session); } while (res == 0); CRYPTOKI_call(ctx, C_FindObjectsFinal(spriv->session)); return (res < 0) ? -1 : 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; }
static int pkcs11_init_cert(PKCS11_CTX * ctx, PKCS11_TOKEN * token, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, PKCS11_CERT ** ret) { PKCS11_TOKEN_private *tpriv; PKCS11_CERT_private *kpriv; PKCS11_CERT *cert, *tmp; char label[256], data[2048]; unsigned char id[256]; CK_CERTIFICATE_TYPE cert_type; size_t size; size = sizeof(cert_type); if (pkcs11_getattr_var(token, obj, CKA_CERTIFICATE_TYPE, &cert_type, &size)) return -1; /* Ignore any certs we don't understand */ if (cert_type != CKC_X_509) return 0; tpriv = PRIVTOKEN(token); tmp = (PKCS11_CERT *) OPENSSL_realloc(tpriv->certs, (tpriv->ncerts + 1) * sizeof(PKCS11_CERT)); if (!tmp) { free(tpriv->certs); tpriv->certs = NULL; return -1; } tpriv->certs = tmp; cert = tpriv->certs + tpriv->ncerts++; memset(cert, 0, sizeof(*cert)); cert->_private = kpriv = PKCS11_NEW(PKCS11_CERT_private); kpriv->object = obj; kpriv->parent = token; if (!pkcs11_getattr_s(token, obj, CKA_LABEL, label, sizeof(label))) cert->label = BUF_strdup(label); size = sizeof(data); if (!pkcs11_getattr_var(token, obj, CKA_VALUE, data, &size)) { const unsigned char *p = (unsigned char *) data; cert->x509 = d2i_X509(NULL, &p, size); } cert->id_len = sizeof(id); if (!pkcs11_getattr_var(token, obj, CKA_ID, id, &cert->id_len)) { cert->id = (unsigned char *) malloc(cert->id_len); memcpy(cert->id, id, cert->id_len); } /* Initialize internal information */ kpriv->id_len = sizeof(kpriv->id); if (pkcs11_getattr_var(token, obj, CKA_ID, kpriv->id, &kpriv->id_len)) kpriv->id_len = 0; if (ret) *ret = cert; return 0; }
/* * Enumerate all certs on the card */ int PKCS11_enumerate_certs(PKCS11_TOKEN * token, PKCS11_CERT ** certp, unsigned int *countp) { PKCS11_TOKEN_private *priv = PRIVTOKEN(token); if (priv->ncerts < 0) { priv->ncerts = 0; if (pkcs11_find_certs(token)) { pkcs11_destroy_certs(token); return -1; } } *certp = priv->certs; *countp = priv->ncerts; return 0; }
/* * Destroy all certs */ void pkcs11_destroy_certs(PKCS11_TOKEN * token) { PKCS11_TOKEN_private *priv = PRIVTOKEN(token); while (priv->ncerts > 0) { PKCS11_CERT *cert = &priv->certs[--(priv->ncerts)]; if (cert->x509) X509_free(cert->x509); OPENSSL_free(cert->label); if (cert->id) free(cert->id); if (cert->_private != NULL) OPENSSL_free(cert->_private); } if (priv->certs) OPENSSL_free(priv->certs); priv->ncerts = -1; priv->certs = NULL; }
/* * Destroy all keys of a given type (public or private) */ void pkcs11_destroy_keys(PKCS11_TOKEN *token, unsigned int type) { PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token); PKCS11_keys *keys = (type == CKO_PRIVATE_KEY) ? &tpriv->prv : &tpriv->pub; while (keys->num > 0) { PKCS11_KEY *key = &keys->keys[--(keys->num)]; if (key->evp_key) EVP_PKEY_free(key->evp_key); OPENSSL_free(key->label); if (key->id) OPENSSL_free(key->id); if (key->_private != NULL) OPENSSL_free(key->_private); } if (keys->keys) OPENSSL_free(keys->keys); keys->keys = NULL; keys->num = -1; }
static int pkcs11_init_key(PKCS11_CTX *ctx, PKCS11_TOKEN *token, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, CK_OBJECT_CLASS type, PKCS11_KEY ** ret) { PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token); PKCS11_keys *keys = (type == CKO_PRIVATE_KEY) ? &tpriv->prv : &tpriv->pub; PKCS11_KEY_private *kpriv; PKCS11_KEY *key, *tmp; CK_KEY_TYPE key_type; PKCS11_KEY_ops *ops; size_t size; (void)ctx; (void)session; size = sizeof(key_type); if (pkcs11_getattr_var(token, obj, CKA_KEY_TYPE, (CK_BYTE *)&key_type, &size)) return -1; switch (key_type) { case CKK_RSA: ops = &pkcs11_rsa_ops; break; case CKK_EC: ops = pkcs11_ec_ops; if (ops == NULL) return 0; /* not supported */ break; default: /* Ignore any keys we don't understand */ return 0; } tmp = OPENSSL_realloc(keys->keys, (keys->num + 1) * sizeof(PKCS11_KEY)); if (tmp == NULL) { OPENSSL_free(keys->keys); keys->keys = NULL; return -1; } keys->keys = tmp; key = keys->keys + keys->num++; memset(key, 0, sizeof(PKCS11_KEY)); kpriv = OPENSSL_malloc(sizeof(PKCS11_KEY_private)); if (kpriv) memset(kpriv, 0, sizeof(PKCS11_KEY_private)); key->_private = kpriv; kpriv->object = obj; kpriv->parent = token; pkcs11_getattr_alloc(token, obj, CKA_LABEL, (CK_BYTE **)&key->label, NULL); key->id_len = 0; pkcs11_getattr_alloc(token, obj, CKA_ID, &key->id, &key->id_len); key->isPrivate = (type == CKO_PRIVATE_KEY); /* Initialize internal information */ kpriv->id_len = sizeof(kpriv->id); if (pkcs11_getattr_var(token, obj, CKA_ID, kpriv->id, &kpriv->id_len)) kpriv->id_len = 0; kpriv->ops = ops; kpriv->forkid = _P11_get_forkid(); if (ret) *ret = key; return 0; }
static int pkcs11_init_cert(PKCS11_CTX *ctx, PKCS11_TOKEN *token, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, PKCS11_CERT ** ret) { PKCS11_TOKEN_private *tpriv; PKCS11_CERT_private *cpriv; PKCS11_CERT *cert, *tmp; unsigned char *data; CK_CERTIFICATE_TYPE cert_type; size_t size; (void)ctx; (void)session; size = sizeof(cert_type); if (pkcs11_getattr_var(token, obj, CKA_CERTIFICATE_TYPE, (CK_BYTE *)&cert_type, &size)) return -1; /* Ignore any certs we don't understand */ if (cert_type != CKC_X_509) return 0; tpriv = PRIVTOKEN(token); tmp = OPENSSL_realloc(tpriv->certs, (tpriv->ncerts + 1) * sizeof(PKCS11_CERT)); if (tmp == NULL) { OPENSSL_free(tpriv->certs); tpriv->certs = NULL; return -1; } tpriv->certs = tmp; cert = tpriv->certs + tpriv->ncerts++; memset(cert, 0, sizeof(*cert)); cpriv = OPENSSL_malloc(sizeof(PKCS11_CERT_private)); if (cpriv == NULL) return -1; memset(cpriv, 0, sizeof(PKCS11_CERT_private)); cert->_private = cpriv; cpriv->object = obj; cpriv->parent = token; pkcs11_getattr_alloc(token, obj, CKA_LABEL, (CK_BYTE **)&cert->label, NULL); size = 0; if (!pkcs11_getattr_alloc(token, obj, CKA_VALUE, &data, &size)) { const unsigned char *p = data; cert->x509 = d2i_X509(NULL, &p, (long)size); OPENSSL_free(data); } cert->id_len = 0; pkcs11_getattr_alloc(token, obj, CKA_ID, &cert->id, &cert->id_len); /* Initialize internal information */ cpriv->id_len = sizeof(cpriv->id); if (pkcs11_getattr_var(token, obj, CKA_ID, cpriv->id, &cpriv->id_len)) cpriv->id_len = 0; if (ret) *ret = cert; return 0; }