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; }
int pkcs11_getattr_s(PKCS11_TOKEN * token, CK_OBJECT_HANDLE object, unsigned int type, void *value, size_t size) { memset(value, 0, size); return pkcs11_getattr_var(token, object, type, value, &size); }
int pkcs11_getattr_bn(PKCS11_TOKEN * token, CK_OBJECT_HANDLE object, unsigned int type, BIGNUM ** bn) { CK_BYTE binary[4196 / 8]; size_t size = sizeof(binary); if (pkcs11_getattr_var(token, object, type, binary, &size)) return -1; if (size == -1) { PKCS11err(PKCS11_F_PKCS11_GETATTR, pkcs11_map_err(CKR_ATTRIBUTE_TYPE_INVALID)); return -1; } *bn = BN_bin2bn(binary, size, *bn); return *bn ? 0 : -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; }
/* 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. */ int pkcs11_ecdh_derive_internal(unsigned char **out, size_t *outlen, const unsigned long ecdh_mechanism, const void * ec_params, void *outnewkey, PKCS11_KEY * key) { int rv; int ret = -1; unsigned char * buf = NULL; size_t buflen; PKCS11_KEY_private *priv; PKCS11_SLOT *slot; PKCS11_CTX *ctx; PKCS11_TOKEN *token; CK_SESSION_HANDLE session; CK_MECHANISM mechanism; 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)} }; ctx = KEY2CTX(key); priv = PRIVKEY(key); token = KEY2TOKEN(key); slot = KEY2SLOT(key); CHECK_KEY_FORK(key); session = PRIVSLOT(slot)->session; 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; // case CK_ECMQV_DERIVE_PARAMS: // mechanism.ulParameterLen = sizeof(CK_ECMQV_DERIVE_PARAMS); // break; default: PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, PKCS11_NOT_SUPPORTED); goto err; } CRYPTO_w_lock(PRIVSLOT(slot)->lockid); rv = CRYPTOKI_call(ctx, C_DeriveKey(session, &mechanism, priv->object, newkey_template, 5, &newkey)); if (rv) { PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, pkcs11_map_err(rv)); goto err; } /* Return the value of the secret key and/or the object handle of the secret key */ /* pkcs11_ec_ckey only asks for the value */ if (out && outlen) { /* get size of secret key value */ if (!pkcs11_getattr_var(token, newkey, CKA_VALUE, NULL, &buflen) && buflen > 0) { buf = OPENSSL_malloc(buflen); if (buf == NULL) { PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, pkcs11_map_err(CKR_HOST_MEMORY)); goto err; } } else { PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, pkcs11_map_err(CKR_ATTRIBUTE_VALUE_INVALID)); goto err; } pkcs11_getattr_var(token, newkey, CKA_VALUE, buf, &buflen); *out = buf; *outlen = buflen; buf = NULL; } /* not used by pkcs11_ec_ckey for future use */ if (tmpnewkey) { *tmpnewkey = newkey; newkey = CK_INVALID_HANDLE; } ret = 1; err: if (buf) OPENSSL_free(buf); if (newkey != CK_INVALID_HANDLE && session != CK_INVALID_HANDLE) CRYPTOKI_call(ctx, C_DestroyObject(session, newkey)); return ret; }