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; }
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; }
/* initial code will only support what is needed for pkcs11_ec_ckey * i.e. CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE * and CK_EC_KDF_TYPE supported by token * The secret key object is deleted * * In future CKM_ECMQV_DERIVE with CK_ECMQV_DERIVE_PARAMS * could also be supported, and the secret key object could be returned. */ static int pkcs11_ecdh_derive(unsigned char **out, size_t *outlen, const unsigned long ecdh_mechanism, const void * ec_params, void *outnewkey, PKCS11_KEY * key) { PKCS11_SLOT *slot = KEY2SLOT(key); PKCS11_CTX *ctx = KEY2CTX(key); PKCS11_TOKEN *token = KEY2TOKEN(key); PKCS11_KEY_private *kpriv = PRIVKEY(key); PKCS11_SLOT_private *spriv = PRIVSLOT(slot); CK_MECHANISM mechanism; int rv; CK_BBOOL true = TRUE; CK_BBOOL false = FALSE; CK_OBJECT_HANDLE newkey = CK_INVALID_HANDLE; CK_OBJECT_CLASS newkey_class= CKO_SECRET_KEY; CK_KEY_TYPE newkey_type = CKK_GENERIC_SECRET; CK_OBJECT_HANDLE * tmpnewkey = (CK_OBJECT_HANDLE *)outnewkey; CK_ATTRIBUTE newkey_template[] = { {CKA_TOKEN, &false, sizeof(false)}, /* session only object */ {CKA_CLASS, &newkey_class, sizeof(newkey_class)}, {CKA_KEY_TYPE, &newkey_type, sizeof(newkey_type)}, {CKA_ENCRYPT, &true, sizeof(true)}, {CKA_DECRYPT, &true, sizeof(true)} }; memset(&mechanism, 0, sizeof(mechanism)); mechanism.mechanism = ecdh_mechanism; mechanism.pParameter = (void*)ec_params; switch (ecdh_mechanism) { case CKM_ECDH1_DERIVE: case CKM_ECDH1_COFACTOR_DERIVE: mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS); break; #if 0 /* TODO */ case CK_ECMQV_DERIVE_PARAMS: mechanism.ulParameterLen = sizeof(CK_ECMQV_DERIVE_PARAMS); break; #endif default: PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, pkcs11_map_err(PKCS11_NOT_SUPPORTED)); return -1; } rv = CRYPTOKI_call(ctx, C_DeriveKey(spriv->session, &mechanism, kpriv->object, newkey_template, 5, &newkey)); CRYPTOKI_checkerr(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, rv); /* Return the value of the secret key and/or the object handle of the secret key */ if (out && outlen) { /* pkcs11_ec_ckey only asks for the value */ if (pkcs11_getattr_alloc(token, newkey, CKA_VALUE, out, outlen)) { PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, pkcs11_map_err(CKR_ATTRIBUTE_VALUE_INVALID)); CRYPTOKI_call(ctx, C_DestroyObject(spriv->session, newkey)); return -1; } } if (tmpnewkey) /* For future use (not used by pkcs11_ec_ckey) */ *tmpnewkey = newkey; else /* Destroy the temporary key */ CRYPTOKI_call(ctx, C_DestroyObject(spriv->session, newkey)); return 0; }