static isc_result_t opensslecdsa_todns(const dst_key_t *key, isc_buffer_t *data) { isc_result_t ret; EVP_PKEY *pkey; EC_KEY *eckey = NULL; isc_region_t r; int len; unsigned char *cp; unsigned char buf[DNS_KEY_ECDSA384SIZE + 1]; REQUIRE(key->keydata.pkey != NULL); pkey = key->keydata.pkey; eckey = EVP_PKEY_get1_EC_KEY(pkey); if (eckey == NULL) return (dst__openssl_toresult(ISC_R_FAILURE)); len = i2o_ECPublicKey(eckey, NULL); /* skip form */ len--; isc_buffer_availableregion(data, &r); if (r.length < (unsigned int) len) DST_RET (ISC_R_NOSPACE); cp = buf; if (!i2o_ECPublicKey(eckey, &cp)) DST_RET (dst__openssl_toresult(ISC_R_FAILURE)); memmove(r.base, buf + 1, len); isc_buffer_add(data, len); ret = ISC_R_SUCCESS; err: if (eckey != NULL) EC_KEY_free(eckey); return (ret); }
static isc_result_t ecdsa_check(EC_KEY *eckey, dst_key_t *pub) { isc_result_t ret = ISC_R_FAILURE; EVP_PKEY *pkey; EC_KEY *pubeckey = NULL; const EC_POINT *pubkey; if (pub == NULL) return (ISC_R_SUCCESS); pkey = pub->keydata.pkey; if (pkey == NULL) return (ISC_R_SUCCESS); pubeckey = EVP_PKEY_get1_EC_KEY(pkey); if (pubeckey == NULL) return (ISC_R_SUCCESS); pubkey = EC_KEY_get0_public_key(pubeckey); if (pubkey == NULL) DST_RET (ISC_R_SUCCESS); if (EC_KEY_set_public_key(eckey, pubkey) != 1) DST_RET (ISC_R_SUCCESS); if (EC_KEY_check_key(eckey) == 1) DST_RET (ISC_R_SUCCESS); err: if (pubeckey != NULL) EC_KEY_free(pubeckey); return (ret); }
static isc_result_t opensslecdsa_fromdns(dst_key_t *key, isc_buffer_t *data) { isc_result_t ret; EVP_PKEY *pkey; EC_KEY *eckey = NULL; isc_region_t r; int group_nid; unsigned int len; const unsigned char *cp; unsigned char buf[DNS_KEY_ECDSA384SIZE + 1]; REQUIRE(key->key_alg == DST_ALG_ECDSA256 || key->key_alg == DST_ALG_ECDSA384); if (key->key_alg == DST_ALG_ECDSA256) { len = DNS_KEY_ECDSA256SIZE; group_nid = NID_X9_62_prime256v1; } else { len = DNS_KEY_ECDSA384SIZE; group_nid = NID_secp384r1; } isc_buffer_remainingregion(data, &r); if (r.length == 0) return (ISC_R_SUCCESS); if (r.length < len) return (DST_R_INVALIDPUBLICKEY); eckey = EC_KEY_new_by_curve_name(group_nid); if (eckey == NULL) return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); buf[0] = POINT_CONVERSION_UNCOMPRESSED; memmove(buf + 1, r.base, len); cp = buf; if (o2i_ECPublicKey(&eckey, (const unsigned char **) &cp, (long) len + 1) == NULL) DST_RET (dst__openssl_toresult(DST_R_INVALIDPUBLICKEY)); if (EC_KEY_check_key(eckey) != 1) DST_RET (dst__openssl_toresult(DST_R_INVALIDPUBLICKEY)); pkey = EVP_PKEY_new(); if (pkey == NULL) DST_RET (ISC_R_NOMEMORY); if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { EVP_PKEY_free(pkey); DST_RET (dst__openssl_toresult(ISC_R_FAILURE)); } isc_buffer_forward(data, len); key->keydata.pkey = pkey; key->key_size = len * 4; ret = ISC_R_SUCCESS; err: if (eckey != NULL) EC_KEY_free(eckey); return (ret); }
static isc_result_t openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t ret; int i; DSA *dsa = NULL; isc_mem_t *mctx = key->mctx; #define DST_RET(a) {ret = a; goto err;} UNUSED(pub); /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv); if (ret != ISC_R_SUCCESS) return (ret); dsa = DSA_new(); if (dsa == NULL) DST_RET(ISC_R_NOMEMORY); dsa->flags &= ~DSA_FLAG_CACHE_MONT_P; key->keydata.dsa = dsa; for (i=0; i < priv.nelements; i++) { BIGNUM *bn; bn = BN_bin2bn(priv.elements[i].data, priv.elements[i].length, NULL); if (bn == NULL) DST_RET(ISC_R_NOMEMORY); switch (priv.elements[i].tag) { case TAG_DSA_PRIME: dsa->p = bn; break; case TAG_DSA_SUBPRIME: dsa->q = bn; break; case TAG_DSA_BASE: dsa->g = bn; break; case TAG_DSA_PRIVATE: dsa->priv_key = bn; break; case TAG_DSA_PUBLIC: dsa->pub_key = bn; break; } } dst__privstruct_free(&priv, mctx); key->key_size = BN_num_bits(dsa->p); return (ISC_R_SUCCESS); err: openssldsa_destroy(key); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ret); }
static isc_result_t opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t ret; EVP_PKEY *pkey; EC_KEY *eckey = NULL; BIGNUM *privkey; int group_nid; isc_mem_t *mctx = key->mctx; REQUIRE(key->key_alg == DST_ALG_ECDSA256 || key->key_alg == DST_ALG_ECDSA384); if (key->key_alg == DST_ALG_ECDSA256) group_nid = NID_X9_62_prime256v1; else group_nid = NID_secp384r1; eckey = EC_KEY_new_by_curve_name(group_nid); if (eckey == NULL) return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv); if (ret != ISC_R_SUCCESS) goto err; privkey = BN_bin2bn(priv.elements[0].data, priv.elements[0].length, NULL); if (privkey == NULL) DST_RET(ISC_R_NOMEMORY); if (!EC_KEY_set_private_key(eckey, privkey)) DST_RET(ISC_R_NOMEMORY); if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS) DST_RET(DST_R_INVALIDPRIVATEKEY); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); pkey = EVP_PKEY_new(); if (pkey == NULL) DST_RET (ISC_R_NOMEMORY); if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { EVP_PKEY_free(pkey); DST_RET (ISC_R_FAILURE); } key->keydata.pkey = pkey; ret = ISC_R_SUCCESS; err: if (eckey != NULL) EC_KEY_free(eckey); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ret); }
static isc_result_t opensslecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { isc_result_t ret; dst_key_t *key = dctx->key; isc_region_t r; ECDSA_SIG *ecdsasig; EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; EVP_PKEY *pkey = key->keydata.pkey; EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey); unsigned int dgstlen, siglen; unsigned char digest[EVP_MAX_MD_SIZE]; REQUIRE(key->key_alg == DST_ALG_ECDSA256 || key->key_alg == DST_ALG_ECDSA384); if (eckey == NULL) return (ISC_R_FAILURE); if (key->key_alg == DST_ALG_ECDSA256) siglen = DNS_SIG_ECDSA256SIZE; else siglen = DNS_SIG_ECDSA384SIZE; isc_buffer_availableregion(sig, &r); if (r.length < siglen) DST_RET(ISC_R_NOSPACE); if (!EVP_DigestFinal(evp_md_ctx, digest, &dgstlen)) DST_RET(dst__openssl_toresult3(dctx->category, "EVP_DigestFinal", ISC_R_FAILURE)); ecdsasig = ECDSA_do_sign(digest, dgstlen, eckey); if (ecdsasig == NULL) DST_RET(dst__openssl_toresult3(dctx->category, "ECDSA_do_sign", DST_R_SIGNFAILURE)); BN_bn2bin_fixed(ecdsasig->r, r.base, siglen / 2); r.base += siglen / 2; BN_bn2bin_fixed(ecdsasig->s, r.base, siglen / 2); r.base += siglen / 2; ECDSA_SIG_free(ecdsasig); isc_buffer_add(sig, siglen); ret = ISC_R_SUCCESS; err: if (eckey != NULL) EC_KEY_free(eckey); return (ret); }
static isc_result_t opensslecdsa_verify(dst_context_t *dctx, const isc_region_t *sig) { isc_result_t ret; dst_key_t *key = dctx->key; int status; unsigned char *cp = sig->base; ECDSA_SIG *ecdsasig = NULL; EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; EVP_PKEY *pkey = key->keydata.pkey; EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey); unsigned int dgstlen, siglen; unsigned char digest[EVP_MAX_MD_SIZE]; REQUIRE(key->key_alg == DST_ALG_ECDSA256 || key->key_alg == DST_ALG_ECDSA384); if (eckey == NULL) return (ISC_R_FAILURE); if (key->key_alg == DST_ALG_ECDSA256) siglen = DNS_SIG_ECDSA256SIZE; else siglen = DNS_SIG_ECDSA384SIZE; if (sig->length != siglen) return (DST_R_VERIFYFAILURE); if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &dgstlen)) DST_RET (ISC_R_FAILURE); ecdsasig = ECDSA_SIG_new(); if (ecdsasig == NULL) DST_RET (ISC_R_NOMEMORY); ecdsasig->r = BN_bin2bn(cp, siglen / 2, NULL); cp += siglen / 2; ecdsasig->s = BN_bin2bn(cp, siglen / 2, NULL); /* cp += siglen / 2; */ status = ECDSA_do_verify(digest, dgstlen, ecdsasig, eckey); if (status != 1) DST_RET (dst__openssl_toresult(DST_R_VERIFYFAILURE)); ret = ISC_R_SUCCESS; err: if (ecdsasig != NULL) ECDSA_SIG_free(ecdsasig); if (eckey != NULL) EC_KEY_free(eckey); return (ret); }
static isc_result_t opensslgost_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t ret; isc_mem_t *mctx = key->mctx; EVP_PKEY *pkey = NULL; const unsigned char *p; UNUSED(pub); /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_ECCGOST, lexer, mctx, &priv); if (ret != ISC_R_SUCCESS) return (ret); INSIST(priv.elements[0].tag == TAG_GOST_PRIVASN1); p = priv.elements[0].data; if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p, (long) priv.elements[0].length) == NULL) DST_RET(dst__openssl_toresult2("d2i_PrivateKey", DST_R_INVALIDPRIVATEKEY)); key->keydata.pkey = pkey; key->key_size = EVP_PKEY_bits(pkey); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ISC_R_SUCCESS); err: if (pkey != NULL) EVP_PKEY_free(pkey); opensslgost_destroy(key); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ret); }
static isc_result_t opensslecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) { isc_result_t ret; EVP_PKEY *pkey; EC_KEY *eckey = NULL; int group_nid; REQUIRE(key->key_alg == DST_ALG_ECDSA256 || key->key_alg == DST_ALG_ECDSA384); UNUSED(unused); UNUSED(callback); if (key->key_alg == DST_ALG_ECDSA256) { group_nid = NID_X9_62_prime256v1; key->key_size = DNS_KEY_ECDSA256SIZE * 4; } else { group_nid = NID_secp384r1; key->key_size = DNS_KEY_ECDSA384SIZE * 4; } eckey = EC_KEY_new_by_curve_name(group_nid); if (eckey == NULL) return (dst__openssl_toresult2("EC_KEY_new_by_curve_name", DST_R_OPENSSLFAILURE)); if (EC_KEY_generate_key(eckey) != 1) DST_RET (dst__openssl_toresult2("EC_KEY_generate_key", DST_R_OPENSSLFAILURE)); pkey = EVP_PKEY_new(); if (pkey == NULL) DST_RET (ISC_R_NOMEMORY); if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { EVP_PKEY_free(pkey); DST_RET (ISC_R_FAILURE); } key->keydata.pkey = pkey; ret = ISC_R_SUCCESS; err: if (eckey != NULL) EC_KEY_free(eckey); return (ret); }
isc_result_t dst__opensslgost_init(dst_func_t **funcp) { isc_result_t ret; REQUIRE(funcp != NULL); /* check if the gost engine works properly */ e = ENGINE_by_id("gost"); if (e == NULL) return (dst__openssl_toresult2("ENGINE_by_id", DST_R_OPENSSLFAILURE)); if (ENGINE_init(e) <= 0) { ENGINE_free(e); e = NULL; return (dst__openssl_toresult2("ENGINE_init", DST_R_OPENSSLFAILURE)); } /* better than to rely on digest_gost symbol */ opensslgost_digest = ENGINE_get_digest(e, NID_id_GostR3411_94); if (opensslgost_digest == NULL) DST_RET(dst__openssl_toresult2("ENGINE_get_digest", DST_R_OPENSSLFAILURE)); /* from openssl.cnf */ if (ENGINE_register_pkey_asn1_meths(e) <= 0) DST_RET(dst__openssl_toresult2( "ENGINE_register_pkey_asn1_meths", DST_R_OPENSSLFAILURE)); if (ENGINE_ctrl_cmd_string(e, "CRYPT_PARAMS", "id-Gost28147-89-CryptoPro-A-ParamSet", 0) <= 0) DST_RET(dst__openssl_toresult2("ENGINE_ctrl_cmd_string", DST_R_OPENSSLFAILURE)); if (*funcp == NULL) *funcp = &opensslgost_functions; return (ISC_R_SUCCESS); err: ENGINE_finish(e); ENGINE_free(e); e = NULL; return (ret); }
static isc_result_t opensslecdsa_tofile(const dst_key_t *key, const char *directory) { isc_result_t ret; EVP_PKEY *pkey; EC_KEY *eckey = NULL; const BIGNUM *privkey; dst_private_t priv; unsigned char *buf = NULL; if (key->keydata.pkey == NULL) return (DST_R_NULLKEY); if (key->external) { priv.nelements = 0; return (dst__privstruct_writefile(key, &priv, directory)); } pkey = key->keydata.pkey; eckey = EVP_PKEY_get1_EC_KEY(pkey); if (eckey == NULL) return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); privkey = EC_KEY_get0_private_key(eckey); if (privkey == NULL) DST_RET (ISC_R_FAILURE); buf = isc_mem_get(key->mctx, BN_num_bytes(privkey)); if (buf == NULL) DST_RET (ISC_R_NOMEMORY); priv.elements[0].tag = TAG_ECDSA_PRIVATEKEY; priv.elements[0].length = BN_num_bytes(privkey); BN_bn2bin(privkey, buf); priv.elements[0].data = buf; priv.nelements = 1; ret = dst__privstruct_writefile(key, &priv, directory); err: if (eckey != NULL) EC_KEY_free(eckey); if (buf != NULL) isc_mem_put(key->mctx, buf, BN_num_bytes(privkey)); return (ret); }
static isc_boolean_t opensslecdsa_compare(const dst_key_t *key1, const dst_key_t *key2) { isc_boolean_t ret; int status; EVP_PKEY *pkey1 = key1->keydata.pkey; EVP_PKEY *pkey2 = key2->keydata.pkey; EC_KEY *eckey1 = NULL; EC_KEY *eckey2 = NULL; const BIGNUM *priv1, *priv2; if (pkey1 == NULL && pkey2 == NULL) return (ISC_TRUE); else if (pkey1 == NULL || pkey2 == NULL) return (ISC_FALSE); eckey1 = EVP_PKEY_get1_EC_KEY(pkey1); eckey2 = EVP_PKEY_get1_EC_KEY(pkey2); if (eckey1 == NULL && eckey2 == NULL) { DST_RET (ISC_TRUE); } else if (eckey1 == NULL || eckey2 == NULL) DST_RET (ISC_FALSE); status = EVP_PKEY_cmp(pkey1, pkey2); if (status != 1) DST_RET (ISC_FALSE); priv1 = EC_KEY_get0_private_key(eckey1); priv2 = EC_KEY_get0_private_key(eckey2); if (priv1 != NULL || priv2 != NULL) { if (priv1 == NULL || priv2 == NULL) DST_RET (ISC_FALSE); if (BN_cmp(priv1, priv2) != 0) DST_RET (ISC_FALSE); } ret = ISC_TRUE; err: if (eckey1 != NULL) EC_KEY_free(eckey1); if (eckey2 != NULL) EC_KEY_free(eckey2); return (ret); }
static isc_result_t opensslgost_generate(dst_key_t *key, int unused, void (*callback)(int)) { EVP_PKEY_CTX *ctx; union { void *dptr; void (*fptr)(int); } u; EVP_PKEY *pkey = NULL; isc_result_t ret; UNUSED(unused); ctx = EVP_PKEY_CTX_new_id(NID_id_GostR3410_2001, NULL); if (ctx == NULL) DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_new_id", DST_R_OPENSSLFAILURE)); if (callback != NULL) { u.fptr = callback; EVP_PKEY_CTX_set_app_data(ctx, u.dptr); EVP_PKEY_CTX_set_cb(ctx, &progress_cb); } if (EVP_PKEY_keygen_init(ctx) <= 0) DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen_init", DST_R_OPENSSLFAILURE)); if (EVP_PKEY_CTX_ctrl_str(ctx, "paramset", "A") <= 0) DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_ctrl_str", DST_R_OPENSSLFAILURE)); if (EVP_PKEY_keygen(ctx, &pkey) <= 0) DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen", DST_R_OPENSSLFAILURE)); key->keydata.pkey = pkey; key->key_size = EVP_PKEY_bits(pkey); EVP_PKEY_CTX_free(ctx); return (ISC_R_SUCCESS); err: if (pkey != NULL) EVP_PKEY_free(pkey); if (ctx != NULL) EVP_PKEY_CTX_free(ctx); return (ret); }
static isc_result_t pkcs11rsa_generate(dst_key_t *key, int exp, void (*callback)(int)) { CK_RV rv; CK_MECHANISM mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 }; CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; CK_ULONG bits = 0; CK_BYTE pubexp[5]; CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; CK_KEY_TYPE keyType = CKK_RSA; CK_ATTRIBUTE pubTemplate[] = { { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) }, { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, { CKA_MODULUS_BITS, &bits, (CK_ULONG) sizeof(bits) }, { CKA_PUBLIC_EXPONENT, &pubexp, (CK_ULONG) sizeof(pubexp) } }; CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; CK_ATTRIBUTE privTemplate[] = { { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) }, { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) }, { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, }; CK_ATTRIBUTE *attr; pk11_object_t *rsa; pk11_context_t *pk11_ctx; isc_result_t ret; unsigned int i; UNUSED(callback); pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, sizeof(*pk11_ctx)); if (pk11_ctx == NULL) return (ISC_R_NOMEMORY); ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE, ISC_FALSE, NULL, pk11_get_best_token(OP_RSA)); if (ret != ISC_R_SUCCESS) goto err; bits = key->key_size; if (exp == 0) { /* RSA_F4 0x10001 */ pubexp[0] = 1; pubexp[1] = 0; pubexp[2] = 1; pubTemplate[6].ulValueLen = 3; } else { /* F5 0x100000001 */ pubexp[0] = 1; pubexp[1] = 0; pubexp[2] = 0; pubexp[3] = 0; pubexp[4] = 1; pubTemplate[6].ulValueLen = 5; } PK11_RET(pkcs_C_GenerateKeyPair, (pk11_ctx->session, &mech, pubTemplate, (CK_ULONG) 7, privTemplate, (CK_ULONG) 7, &pub, &priv), DST_R_CRYPTOFAILURE); rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa)); if (rsa == NULL) DST_RET(ISC_R_NOMEMORY); memset(rsa, 0, sizeof(*rsa)); key->keydata.pkey = rsa; rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 8); if (rsa->repr == NULL) DST_RET(ISC_R_NOMEMORY); memset(rsa->repr, 0, sizeof(*attr) * 8); rsa->attrcnt = 8; attr = rsa->repr; attr[0].type = CKA_MODULUS; attr[1].type = CKA_PUBLIC_EXPONENT; attr[2].type = CKA_PRIVATE_EXPONENT; attr[3].type = CKA_PRIME_1; attr[4].type = CKA_PRIME_2; attr[5].type = CKA_EXPONENT_1; attr[6].type = CKA_EXPONENT_2; attr[7].type = CKA_COEFFICIENT; PK11_RET(pkcs_C_GetAttributeValue, (pk11_ctx->session, pub, attr, 2), DST_R_CRYPTOFAILURE); for (i = 0; i <= 1; i++) { attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen); if (attr[i].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memset(attr[i].pValue, 0, attr[i].ulValueLen); } PK11_RET(pkcs_C_GetAttributeValue, (pk11_ctx->session, pub, attr, 2), DST_R_CRYPTOFAILURE); attr += 2; PK11_RET(pkcs_C_GetAttributeValue, (pk11_ctx->session, priv, attr, 6), DST_R_CRYPTOFAILURE); for (i = 0; i <= 5; i++) { attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen); if (attr[i].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memset(attr[i].pValue, 0, attr[i].ulValueLen); } PK11_RET(pkcs_C_GetAttributeValue, (pk11_ctx->session, priv, attr, 6), DST_R_CRYPTOFAILURE); (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); return (ISC_R_SUCCESS); err: pkcs11rsa_destroy(key); if (priv != CK_INVALID_HANDLE) (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); if (pub != CK_INVALID_HANDLE) (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); return (ret); }
static isc_result_t pkcs11rsa_createctx_sign(dst_key_t *key, dst_context_t *dctx) { CK_RV rv; CK_MECHANISM mech = { 0, NULL, 0 }; CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; CK_KEY_TYPE keyType = CKK_RSA; CK_ATTRIBUTE keyTemplate[] = { { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, { CKA_MODULUS, NULL, 0 }, { CKA_PUBLIC_EXPONENT, NULL, 0 }, { CKA_PRIVATE_EXPONENT, NULL, 0 }, { CKA_PRIME_1, NULL, 0 }, { CKA_PRIME_2, NULL, 0 }, { CKA_EXPONENT_1, NULL, 0 }, { CKA_EXPONENT_2, NULL, 0 }, { CKA_COEFFICIENT, NULL, 0 } }; CK_ATTRIBUTE *attr; CK_SLOT_ID slotid; pk11_object_t *rsa; pk11_context_t *pk11_ctx; isc_result_t ret; unsigned int i; REQUIRE(key->key_alg == DST_ALG_RSAMD5 || key->key_alg == DST_ALG_RSASHA1 || key->key_alg == DST_ALG_NSEC3RSASHA1 || key->key_alg == DST_ALG_RSASHA256 || key->key_alg == DST_ALG_RSASHA512); rsa = key->keydata.pkey; pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx, sizeof(*pk11_ctx)); if (pk11_ctx == NULL) return (ISC_R_NOMEMORY); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); if (rsa->ontoken) slotid = rsa->slot; else slotid = pk11_get_best_token(OP_RSA); ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE, rsa->reqlogon, NULL, slotid); if (ret != ISC_R_SUCCESS) goto err; if (rsa->ontoken && (rsa->object != CK_INVALID_HANDLE)) { pk11_ctx->ontoken = rsa->ontoken; pk11_ctx->object = rsa->object; goto token_key; } for (attr = pk11_attribute_first(rsa); attr != NULL; attr = pk11_attribute_next(rsa, attr)) switch (attr->type) { case CKA_MODULUS: INSIST(keyTemplate[6].type == attr->type); keyTemplate[6].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[6].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[6].pValue, attr->pValue, attr->ulValueLen); keyTemplate[6].ulValueLen = attr->ulValueLen; break; case CKA_PUBLIC_EXPONENT: INSIST(keyTemplate[7].type == attr->type); keyTemplate[7].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[7].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[7].pValue, attr->pValue, attr->ulValueLen); keyTemplate[7].ulValueLen = attr->ulValueLen; break; case CKA_PRIVATE_EXPONENT: INSIST(keyTemplate[8].type == attr->type); keyTemplate[8].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[8].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[8].pValue, attr->pValue, attr->ulValueLen); keyTemplate[8].ulValueLen = attr->ulValueLen; break; case CKA_PRIME_1: INSIST(keyTemplate[9].type == attr->type); keyTemplate[9].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[9].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[9].pValue, attr->pValue, attr->ulValueLen); keyTemplate[9].ulValueLen = attr->ulValueLen; break; case CKA_PRIME_2: INSIST(keyTemplate[10].type == attr->type); keyTemplate[10].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[10].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[10].pValue, attr->pValue, attr->ulValueLen); keyTemplate[10].ulValueLen = attr->ulValueLen; break; case CKA_EXPONENT_1: INSIST(keyTemplate[11].type == attr->type); keyTemplate[11].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[11].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[11].pValue, attr->pValue, attr->ulValueLen); keyTemplate[11].ulValueLen = attr->ulValueLen; break; case CKA_EXPONENT_2: INSIST(keyTemplate[12].type == attr->type); keyTemplate[12].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[12].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[12].pValue, attr->pValue, attr->ulValueLen); keyTemplate[12].ulValueLen = attr->ulValueLen; break; case CKA_COEFFICIENT: INSIST(keyTemplate[13].type == attr->type); keyTemplate[13].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[13].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[13].pValue, attr->pValue, attr->ulValueLen); keyTemplate[13].ulValueLen = attr->ulValueLen; break; } pk11_ctx->object = CK_INVALID_HANDLE; pk11_ctx->ontoken = ISC_FALSE; PK11_RET(pkcs_C_CreateObject, (pk11_ctx->session, keyTemplate, (CK_ULONG) 14, &pk11_ctx->object), ISC_R_FAILURE); token_key: switch (dctx->key->key_alg) { case DST_ALG_RSAMD5: mech.mechanism = CKM_MD5_RSA_PKCS; break; case DST_ALG_RSASHA1: case DST_ALG_NSEC3RSASHA1: mech.mechanism = CKM_SHA1_RSA_PKCS; break; case DST_ALG_RSASHA256: mech.mechanism = CKM_SHA256_RSA_PKCS; break; case DST_ALG_RSASHA512: mech.mechanism = CKM_SHA512_RSA_PKCS; break; default: INSIST(0); } PK11_RET(pkcs_C_SignInit, (pk11_ctx->session, &mech, pk11_ctx->object), ISC_R_FAILURE); dctx->ctxdata.pk11_ctx = pk11_ctx; for (i = 6; i <= 13; i++) if (keyTemplate[i].pValue != NULL) { memset(keyTemplate[i].pValue, 0, keyTemplate[i].ulValueLen); isc_mem_put(dctx->mctx, keyTemplate[i].pValue, keyTemplate[i].ulValueLen); } return (ISC_R_SUCCESS); err: if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE)) (void) pkcs_C_DestroyObject(pk11_ctx->session, pk11_ctx->object); for (i = 6; i <= 13; i++) if (keyTemplate[i].pValue != NULL) { memset(keyTemplate[i].pValue, 0, keyTemplate[i].ulValueLen); isc_mem_put(dctx->mctx, keyTemplate[i].pValue, keyTemplate[i].ulValueLen); } pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); return (ret); }
static isc_result_t pkcs11rsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t ret; int i; pk11_object_t *rsa; CK_ATTRIBUTE *attr; isc_mem_t *mctx = key->mctx; const char *engine = NULL, *label = NULL; /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv); if (ret != ISC_R_SUCCESS) return (ret); if (key->external) { if (priv.nelements != 0) DST_RET(DST_R_INVALIDPRIVATEKEY); if (pub == NULL) DST_RET(DST_R_INVALIDPRIVATEKEY); key->keydata.pkey = pub->keydata.pkey; pub->keydata.pkey = NULL; key->key_size = pub->key_size; dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ISC_R_SUCCESS); } for (i = 0; i < priv.nelements; i++) { switch (priv.elements[i].tag) { case TAG_RSA_ENGINE: engine = (char *)priv.elements[i].data; break; case TAG_RSA_LABEL: label = (char *)priv.elements[i].data; break; default: break; } } rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa)); if (rsa == NULL) DST_RET(ISC_R_NOMEMORY); memset(rsa, 0, sizeof(*rsa)); key->keydata.pkey = rsa; /* Is this key is stored in a HSM? See if we can fetch it. */ if ((label != NULL) || (engine != NULL)) { ret = pkcs11rsa_fetch(key, engine, label, pub); if (ret != ISC_R_SUCCESS) goto err; dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ret); } rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 8); if (rsa->repr == NULL) DST_RET(ISC_R_NOMEMORY); memset(rsa->repr, 0, sizeof(*attr) * 8); rsa->attrcnt = 8; attr = rsa->repr; attr[0].type = CKA_MODULUS; attr[1].type = CKA_PUBLIC_EXPONENT; attr[2].type = CKA_PRIVATE_EXPONENT; attr[3].type = CKA_PRIME_1; attr[4].type = CKA_PRIME_2; attr[5].type = CKA_EXPONENT_1; attr[6].type = CKA_EXPONENT_2; attr[7].type = CKA_COEFFICIENT; for (i = 0; i < priv.nelements; i++) { CK_BYTE *bn; switch (priv.elements[i].tag) { case TAG_RSA_ENGINE: continue; case TAG_RSA_LABEL: continue; default: bn = isc_mem_get(key->mctx, priv.elements[i].length); if (bn == NULL) DST_RET(ISC_R_NOMEMORY); memmove(bn, priv.elements[i].data, priv.elements[i].length); } switch (priv.elements[i].tag) { case TAG_RSA_MODULUS: attr = pk11_attribute_bytype(rsa, CKA_MODULUS); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_RSA_PUBLICEXPONENT: attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_RSA_PRIVATEEXPONENT: attr = pk11_attribute_bytype(rsa, CKA_PRIVATE_EXPONENT); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_RSA_PRIME1: attr = pk11_attribute_bytype(rsa, CKA_PRIME_1); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_RSA_PRIME2: attr = pk11_attribute_bytype(rsa, CKA_PRIME_2); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_RSA_EXPONENT1: attr = pk11_attribute_bytype(rsa, CKA_EXPONENT_1); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_RSA_EXPONENT2: attr = pk11_attribute_bytype(rsa, CKA_EXPONENT_2); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_RSA_COEFFICIENT: attr = pk11_attribute_bytype(rsa, CKA_COEFFICIENT); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; } } if (rsa_check(rsa, pub->keydata.pkey) != ISC_R_SUCCESS) DST_RET(DST_R_INVALIDPRIVATEKEY); attr = pk11_attribute_bytype(rsa, CKA_MODULUS); INSIST(attr != NULL); key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT); INSIST(attr != NULL); if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS) DST_RET(ISC_R_RANGE); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ISC_R_SUCCESS); err: pkcs11rsa_destroy(key); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ret); }
static isc_result_t pkcs11rsa_fromlabel(dst_key_t *key, const char *engine, const char *label, const char *pin) { CK_RV rv; CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE; CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY; CK_KEY_TYPE keyType = CKK_RSA; CK_ATTRIBUTE searchTemplate[] = { { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) }, { CKA_LABEL, NULL, 0 } }; CK_ULONG cnt; CK_ATTRIBUTE *attr; pk11_object_t *rsa; pk11_context_t *pk11_ctx = NULL; isc_result_t ret; unsigned int i; UNUSED(pin); rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa)); if (rsa == NULL) return (ISC_R_NOMEMORY); memset(rsa, 0, sizeof(*rsa)); rsa->object = CK_INVALID_HANDLE; rsa->ontoken = ISC_TRUE; rsa->reqlogon = ISC_TRUE; key->keydata.pkey = rsa; rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2); if (rsa->repr == NULL) DST_RET(ISC_R_NOMEMORY); memset(rsa->repr, 0, sizeof(*attr) * 2); rsa->attrcnt = 2; attr = rsa->repr; attr[0].type = CKA_MODULUS; attr[1].type = CKA_PUBLIC_EXPONENT; ret = pk11_parse_uri(rsa, label, key->mctx, OP_RSA); if (ret != ISC_R_SUCCESS) goto err; pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, sizeof(*pk11_ctx)); if (pk11_ctx == NULL) DST_RET(ISC_R_NOMEMORY); ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE, rsa->reqlogon, NULL, rsa->slot); if (ret != ISC_R_SUCCESS) goto err; attr = pk11_attribute_bytype(rsa, CKA_LABEL); if (attr == NULL) { attr = pk11_attribute_bytype(rsa, CKA_ID); INSIST(attr != NULL); searchTemplate[3].type = CKA_ID; } searchTemplate[3].pValue = attr->pValue; searchTemplate[3].ulValueLen = attr->ulValueLen; PK11_RET(pkcs_C_FindObjectsInit, (pk11_ctx->session, searchTemplate, (CK_ULONG) 4), DST_R_CRYPTOFAILURE); PK11_RET(pkcs_C_FindObjects, (pk11_ctx->session, &hKey, (CK_ULONG) 1, &cnt), DST_R_CRYPTOFAILURE); (void) pkcs_C_FindObjectsFinal(pk11_ctx->session); if (cnt == 0) DST_RET(ISC_R_NOTFOUND); if (cnt > 1) DST_RET(ISC_R_EXISTS); attr = rsa->repr; PK11_RET(pkcs_C_GetAttributeValue, (pk11_ctx->session, hKey, attr, 2), DST_R_CRYPTOFAILURE); for (i = 0; i <= 1; i++) { attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen); if (attr[i].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memset(attr[i].pValue, 0, attr[i].ulValueLen); } PK11_RET(pkcs_C_GetAttributeValue, (pk11_ctx->session, hKey, attr, 2), DST_R_CRYPTOFAILURE); keyClass = CKO_PRIVATE_KEY; PK11_RET(pkcs_C_FindObjectsInit, (pk11_ctx->session, searchTemplate, (CK_ULONG) 4), DST_R_CRYPTOFAILURE); PK11_RET(pkcs_C_FindObjects, (pk11_ctx->session, &rsa->object, (CK_ULONG) 1, &cnt), DST_R_CRYPTOFAILURE); (void) pkcs_C_FindObjectsFinal(pk11_ctx->session); if (cnt == 0) DST_RET(ISC_R_NOTFOUND); if (cnt > 1) DST_RET(ISC_R_EXISTS); if (engine != NULL) { key->engine = isc_mem_strdup(key->mctx, engine); if (key->engine == NULL) DST_RET(ISC_R_NOMEMORY); } key->label = isc_mem_strdup(key->mctx, label); if (key->label == NULL) DST_RET(ISC_R_NOMEMORY); attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT); INSIST(attr != NULL); if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS) DST_RET(ISC_R_RANGE); attr = pk11_attribute_bytype(rsa, CKA_MODULUS); INSIST(attr != NULL); key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); return (ISC_R_SUCCESS); err: pkcs11rsa_destroy(key); if (pk11_ctx != NULL) { pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); } return (ret); }
static isc_result_t pkcs11gost_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t ret; pk11_object_t *gost = NULL; CK_ATTRIBUTE *attr, *pattr; isc_mem_t *mctx = key->mctx; if ((pub == NULL) || (pub->keydata.pkey == NULL)) DST_RET(DST_R_INVALIDPRIVATEKEY); /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv); if (ret != ISC_R_SUCCESS) return (ret); if (key->external) { if (priv.nelements != 0) DST_RET(DST_R_INVALIDPRIVATEKEY); key->keydata.pkey = pub->keydata.pkey; pub->keydata.pkey = NULL; key->key_size = pub->key_size; dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ISC_R_SUCCESS); } if (priv.elements[0].tag == TAG_GOST_PRIVASN1) { int adj = (int) priv.elements[0].length - (39 + 32); unsigned char buf[39]; if ((adj > 0) || (adj < -31)) DST_RET(DST_R_INVALIDPRIVATEKEY); memmove(buf, gost_private_der, 39); if (adj != 0) { buf[1] += adj; buf[36] += adj; buf[38] += adj; } if (memcmp(priv.elements[0].data, buf, 39) != 0) DST_RET(DST_R_INVALIDPRIVATEKEY); priv.elements[0].tag = TAG_GOST_PRIVRAW; priv.elements[0].length -= 39; memmove(priv.elements[0].data, priv.elements[0].data + 39, 32 + adj); } gost = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*gost)); if (gost == NULL) DST_RET(ISC_R_NOMEMORY); memset(gost, 0, sizeof(*gost)); key->keydata.pkey = gost; gost->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2); if (gost->repr == NULL) DST_RET(ISC_R_NOMEMORY); memset(gost->repr, 0, sizeof(*attr) * 2); gost->attrcnt = 2; attr = gost->repr; attr->type = CKA_VALUE; pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_VALUE); INSIST(pattr != NULL); attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen); if (attr->pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(attr->pValue, pattr->pValue, pattr->ulValueLen); attr->ulValueLen = pattr->ulValueLen; attr++; attr->type = CKA_VALUE2; attr->pValue = isc_mem_get(key->mctx, priv.elements[0].length); if (attr->pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(attr->pValue, priv.elements[0].data, priv.elements[0].length); attr->ulValueLen = priv.elements[0].length; dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ISC_R_SUCCESS); err: pkcs11gost_destroy(key); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ret); }
static isc_result_t pkcs11rsa_fetch(dst_key_t *key, const char *engine, const char *label, dst_key_t *pub) { CK_RV rv; CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; CK_KEY_TYPE keyType = CKK_RSA; CK_ATTRIBUTE searchTemplate[] = { { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) }, { CKA_LABEL, NULL, 0 } }; CK_ULONG cnt; CK_ATTRIBUTE *attr; CK_ATTRIBUTE *pubattr; pk11_object_t *rsa; pk11_object_t *pubrsa; pk11_context_t *pk11_ctx = NULL; isc_result_t ret; if (label == NULL) return (DST_R_NOENGINE); rsa = key->keydata.pkey; pubrsa = pub->keydata.pkey; rsa->object = CK_INVALID_HANDLE; rsa->ontoken = ISC_TRUE; rsa->reqlogon = ISC_TRUE; rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2); if (rsa->repr == NULL) return (ISC_R_NOMEMORY); memset(rsa->repr, 0, sizeof(*attr) * 2); rsa->attrcnt = 2; attr = rsa->repr; attr->type = CKA_MODULUS; pubattr = pk11_attribute_bytype(pubrsa, CKA_MODULUS); attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen); if (attr->pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(attr->pValue, pubattr->pValue, pubattr->ulValueLen); attr->ulValueLen = pubattr->ulValueLen; attr++; attr->type = CKA_PUBLIC_EXPONENT; pubattr = pk11_attribute_bytype(pubrsa, CKA_PUBLIC_EXPONENT); attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen); if (attr->pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(attr->pValue, pubattr->pValue, pubattr->ulValueLen); attr->ulValueLen = pubattr->ulValueLen; ret = pk11_parse_uri(rsa, label, key->mctx, OP_RSA); if (ret != ISC_R_SUCCESS) goto err; pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, sizeof(*pk11_ctx)); if (pk11_ctx == NULL) DST_RET(ISC_R_NOMEMORY); ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE, rsa->reqlogon, NULL, rsa->slot); if (ret != ISC_R_SUCCESS) goto err; attr = pk11_attribute_bytype(rsa, CKA_LABEL); if (attr == NULL) { attr = pk11_attribute_bytype(rsa, CKA_ID); INSIST(attr != NULL); searchTemplate[3].type = CKA_ID; } searchTemplate[3].pValue = attr->pValue; searchTemplate[3].ulValueLen = attr->ulValueLen; PK11_RET(pkcs_C_FindObjectsInit, (pk11_ctx->session, searchTemplate, (CK_ULONG) 4), DST_R_CRYPTOFAILURE); PK11_RET(pkcs_C_FindObjects, (pk11_ctx->session, &rsa->object, (CK_ULONG) 1, &cnt), DST_R_CRYPTOFAILURE); (void) pkcs_C_FindObjectsFinal(pk11_ctx->session); if (cnt == 0) DST_RET(ISC_R_NOTFOUND); if (cnt > 1) DST_RET(ISC_R_EXISTS); if (engine != NULL) { key->engine = isc_mem_strdup(key->mctx, engine); if (key->engine == NULL) DST_RET(ISC_R_NOMEMORY); } key->label = isc_mem_strdup(key->mctx, label); if (key->label == NULL) DST_RET(ISC_R_NOMEMORY); pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); attr = pk11_attribute_bytype(rsa, CKA_MODULUS); INSIST(attr != NULL); key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); return (ISC_R_SUCCESS); err: if (pk11_ctx != NULL) { pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); } return (ret); }
static isc_result_t pkcs11gost_createctx_verify(dst_key_t *key, dst_context_t *dctx) { CK_RV rv; CK_MECHANISM mech = { CKM_GOSTR3410_WITH_GOSTR3411, NULL, 0 }; CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY; CK_KEY_TYPE keyType = CKK_GOSTR3410; CK_ATTRIBUTE keyTemplate[] = { { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, { CKA_VALUE, NULL, 0 }, { CKA_GOSTR3410_PARAMS, pk11_gost_a_paramset, (CK_ULONG) sizeof(pk11_gost_a_paramset) }, { CKA_GOSTR3411_PARAMS, pk11_gost_paramset, (CK_ULONG) sizeof(pk11_gost_paramset) } }; CK_ATTRIBUTE *attr; pk11_object_t *gost; pk11_context_t *pk11_ctx; isc_result_t ret; unsigned int i; pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx, sizeof(*pk11_ctx)); if (pk11_ctx == NULL) return (ISC_R_NOMEMORY); ret = pk11_get_session(pk11_ctx, OP_GOST, ISC_FALSE, ISC_FALSE, NULL, pk11_get_best_token(OP_GOST)); if (ret != ISC_R_SUCCESS) goto err; gost = key->keydata.pkey; if (gost->ontoken && (gost->object != CK_INVALID_HANDLE)) { pk11_ctx->ontoken = gost->ontoken; pk11_ctx->object = gost->object; goto token_key; } for (attr = pk11_attribute_first(gost); attr != NULL; attr = pk11_attribute_next(gost, attr)) switch (attr->type) { case CKA_VALUE: INSIST(keyTemplate[5].type == attr->type); keyTemplate[5].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[5].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[5].pValue, attr->pValue, attr->ulValueLen); keyTemplate[5].ulValueLen = attr->ulValueLen; break; } pk11_ctx->object = CK_INVALID_HANDLE; pk11_ctx->ontoken = ISC_FALSE; PK11_RET(pkcs_C_CreateObject, (pk11_ctx->session, keyTemplate, (CK_ULONG) 8, &pk11_ctx->object), ISC_R_FAILURE); token_key: PK11_RET(pkcs_C_VerifyInit, (pk11_ctx->session, &mech, pk11_ctx->object), ISC_R_FAILURE); dctx->ctxdata.pk11_ctx = pk11_ctx; for (i = 5; i <= 5; i++) if (keyTemplate[i].pValue != NULL) { memset(keyTemplate[i].pValue, 0, keyTemplate[i].ulValueLen); isc_mem_put(dctx->mctx, keyTemplate[i].pValue, keyTemplate[i].ulValueLen); } return (ISC_R_SUCCESS); err: if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE)) (void) pkcs_C_DestroyObject(pk11_ctx->session, pk11_ctx->object); for (i = 5; i <= 5; i++) if (keyTemplate[i].pValue != NULL) { memset(keyTemplate[i].pValue, 0, keyTemplate[i].ulValueLen); isc_mem_put(dctx->mctx, keyTemplate[i].pValue, keyTemplate[i].ulValueLen); } pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); return (ret); }
static isc_result_t pkcs11ecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) { CK_RV rv; CK_MECHANISM mech = { CKM_EC_KEY_PAIR_GEN, NULL, 0 }; CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; CK_KEY_TYPE keyType = CKK_EC; CK_ATTRIBUTE pubTemplate[] = { { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) }, { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, { CKA_EC_PARAMS, NULL, 0 } }; CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY; CK_ATTRIBUTE privTemplate[] = { { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) }, { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) }, { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) } }; CK_ATTRIBUTE *attr; pk11_object_t *ec; pk11_context_t *pk11_ctx; isc_result_t ret; REQUIRE(key->key_alg == DST_ALG_ECDSA256 || key->key_alg == DST_ALG_ECDSA384); UNUSED(unused); UNUSED(callback); pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, sizeof(*pk11_ctx)); if (pk11_ctx == NULL) return (ISC_R_NOMEMORY); ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE, ISC_FALSE, NULL, pk11_get_best_token(OP_EC)); if (ret != ISC_R_SUCCESS) goto err; ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec)); if (ec == NULL) DST_RET(ISC_R_NOMEMORY); memset(ec, 0, sizeof(*ec)); key->keydata.pkey = ec; ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3); if (ec->repr == NULL) DST_RET(ISC_R_NOMEMORY); memset(ec->repr, 0, sizeof(*attr) * 3); ec->attrcnt = 3; attr = ec->repr; attr[0].type = CKA_EC_PARAMS; attr[1].type = CKA_EC_POINT; attr[2].type = CKA_VALUE; attr = &pubTemplate[5]; SETCURVE(); PK11_RET(pkcs_C_GenerateKeyPair, (pk11_ctx->session, &mech, pubTemplate, (CK_ULONG) 6, privTemplate, (CK_ULONG) 7, &pub, &priv), DST_R_CRYPTOFAILURE); attr = &pubTemplate[5]; FREECURVE(); attr = ec->repr; SETCURVE(); attr++; PK11_RET(pkcs_C_GetAttributeValue, (pk11_ctx->session, pub, attr, 1), DST_R_CRYPTOFAILURE); attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen); if (attr->pValue == NULL) DST_RET(ISC_R_NOMEMORY); memset(attr->pValue, 0, attr->ulValueLen); PK11_RET(pkcs_C_GetAttributeValue, (pk11_ctx->session, pub, attr, 1), DST_R_CRYPTOFAILURE); attr++; PK11_RET(pkcs_C_GetAttributeValue, (pk11_ctx->session, priv, attr, 1), DST_R_CRYPTOFAILURE); attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen); if (attr->pValue == NULL) DST_RET(ISC_R_NOMEMORY); memset(attr->pValue, 0, attr->ulValueLen); PK11_RET(pkcs_C_GetAttributeValue, (pk11_ctx->session, priv, attr, 1), DST_R_CRYPTOFAILURE); (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); if (key->key_alg == DST_ALG_ECDSA256) key->key_size = DNS_KEY_ECDSA256SIZE * 4; else key->key_size = DNS_KEY_ECDSA384SIZE * 4; return (ISC_R_SUCCESS); err: pkcs11ecdsa_destroy(key); if (priv != CK_INVALID_HANDLE) (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); if (pub != CK_INVALID_HANDLE) (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); return (ret); }
static isc_result_t opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label, const char *pin) { #ifdef USE_ENGINE ENGINE *e = NULL; isc_result_t ret; EVP_PKEY *pkey = NULL; RSA *rsa = NULL, *pubrsa = NULL; char *colon; UNUSED(pin); if (engine == NULL) DST_RET(DST_R_NOENGINE); e = dst__openssl_getengine(engine); if (e == NULL) DST_RET(DST_R_NOENGINE); pkey = ENGINE_load_public_key(e, label, NULL, NULL); if (pkey != NULL) { pubrsa = EVP_PKEY_get1_RSA(pkey); EVP_PKEY_free(pkey); if (pubrsa == NULL) DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); } pkey = ENGINE_load_private_key(e, label, NULL, NULL); if (pkey == NULL) DST_RET(dst__openssl_toresult2("ENGINE_load_private_key", ISC_R_NOTFOUND)); if (engine != NULL) { key->engine = isc_mem_strdup(key->mctx, engine); if (key->engine == NULL) DST_RET(ISC_R_NOMEMORY); } else { key->engine = isc_mem_strdup(key->mctx, label); if (key->engine == NULL) DST_RET(ISC_R_NOMEMORY); colon = strchr(key->engine, ':'); if (colon != NULL) *colon = '\0'; } key->label = isc_mem_strdup(key->mctx, label); if (key->label == NULL) DST_RET(ISC_R_NOMEMORY); rsa = EVP_PKEY_get1_RSA(pkey); if (rsa == NULL) DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) DST_RET(DST_R_INVALIDPRIVATEKEY); if (pubrsa != NULL) RSA_free(pubrsa); key->key_size = EVP_PKEY_bits(pkey); #if USE_EVP key->keydata.pkey = pkey; RSA_free(rsa); #else key->keydata.rsa = rsa; EVP_PKEY_free(pkey); #endif return (ISC_R_SUCCESS); err: if (rsa != NULL) RSA_free(rsa); if (pubrsa != NULL) RSA_free(pubrsa); if (pkey != NULL) EVP_PKEY_free(pkey); return (ret); #else UNUSED(key); UNUSED(engine); UNUSED(label); UNUSED(pin); return(DST_R_NOENGINE); #endif }
static isc_result_t opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) { isc_region_t r; unsigned int e_bytes; unsigned int mod_bytes; isc_result_t ret; RSA *rsa; #if USE_EVP EVP_PKEY *pkey; #endif #if USE_EVP REQUIRE(key->keydata.pkey != NULL); #else REQUIRE(key->keydata.rsa != NULL); #endif #if USE_EVP pkey = key->keydata.pkey; rsa = EVP_PKEY_get1_RSA(pkey); if (rsa == NULL) return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); #else rsa = key->keydata.rsa; #endif isc_buffer_availableregion(data, &r); e_bytes = BN_num_bytes(rsa->e); mod_bytes = BN_num_bytes(rsa->n); if (e_bytes < 256) { /*%< key exponent is <= 2040 bits */ if (r.length < 1) DST_RET(ISC_R_NOSPACE); isc_buffer_putuint8(data, (isc_uint8_t) e_bytes); isc_region_consume(&r, 1); } else { if (r.length < 3) DST_RET(ISC_R_NOSPACE); isc_buffer_putuint8(data, 0); isc_buffer_putuint16(data, (isc_uint16_t) e_bytes); isc_region_consume(&r, 3); } if (r.length < e_bytes + mod_bytes) DST_RET(ISC_R_NOSPACE); BN_bn2bin(rsa->e, r.base); isc_region_consume(&r, e_bytes); BN_bn2bin(rsa->n, r.base); isc_buffer_add(data, e_bytes + mod_bytes); ret = ISC_R_SUCCESS; err: #if USE_EVP if (rsa != NULL) RSA_free(rsa); #endif return (ret); }
static isc_result_t opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t ret; int i; RSA *rsa = NULL, *pubrsa = NULL; #ifdef USE_ENGINE ENGINE *e = NULL; #endif isc_mem_t *mctx = key->mctx; const char *engine = NULL, *label = NULL; #if defined(USE_ENGINE) || USE_EVP EVP_PKEY *pkey = NULL; #endif #if USE_EVP if (pub != NULL && pub->keydata.pkey != NULL) pubrsa = EVP_PKEY_get1_RSA(pub->keydata.pkey); #else if (pub != NULL && pub->keydata.rsa != NULL) { pubrsa = pub->keydata.rsa; pub->keydata.rsa = NULL; } #endif /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv); if (ret != ISC_R_SUCCESS) goto err; for (i = 0; i < priv.nelements; i++) { switch (priv.elements[i].tag) { case TAG_RSA_ENGINE: engine = (char *)priv.elements[i].data; break; case TAG_RSA_LABEL: label = (char *)priv.elements[i].data; break; default: break; } } /* * Is this key is stored in a HSM? * See if we can fetch it. */ if (label != NULL) { #ifdef USE_ENGINE if (engine == NULL) DST_RET(DST_R_NOENGINE); e = dst__openssl_getengine(engine); if (e == NULL) DST_RET(DST_R_NOENGINE); pkey = ENGINE_load_private_key(e, label, NULL, NULL); if (pkey == NULL) DST_RET(dst__openssl_toresult2( "ENGINE_load_private_key", ISC_R_NOTFOUND)); key->engine = isc_mem_strdup(key->mctx, engine); if (key->engine == NULL) DST_RET(ISC_R_NOMEMORY); key->label = isc_mem_strdup(key->mctx, label); if (key->label == NULL) DST_RET(ISC_R_NOMEMORY); rsa = EVP_PKEY_get1_RSA(pkey); if (rsa == NULL) DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) DST_RET(DST_R_INVALIDPRIVATEKEY); if (pubrsa != NULL) RSA_free(pubrsa); key->key_size = EVP_PKEY_bits(pkey); #if USE_EVP key->keydata.pkey = pkey; RSA_free(rsa); #else key->keydata.rsa = rsa; EVP_PKEY_free(pkey); #endif dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ISC_R_SUCCESS); #else DST_RET(DST_R_NOENGINE); #endif } rsa = RSA_new(); if (rsa == NULL) DST_RET(ISC_R_NOMEMORY); SET_FLAGS(rsa); #if USE_EVP pkey = EVP_PKEY_new(); if (pkey == NULL) DST_RET(ISC_R_NOMEMORY); if (!EVP_PKEY_set1_RSA(pkey, rsa)) DST_RET(ISC_R_FAILURE); key->keydata.pkey = pkey; #else key->keydata.rsa = rsa; #endif for (i = 0; i < priv.nelements; i++) { BIGNUM *bn; switch (priv.elements[i].tag) { case TAG_RSA_ENGINE: continue; case TAG_RSA_LABEL: continue; case TAG_RSA_PIN: continue; default: bn = BN_bin2bn(priv.elements[i].data, priv.elements[i].length, NULL); if (bn == NULL) DST_RET(ISC_R_NOMEMORY); } switch (priv.elements[i].tag) { case TAG_RSA_MODULUS: rsa->n = bn; break; case TAG_RSA_PUBLICEXPONENT: rsa->e = bn; break; case TAG_RSA_PRIVATEEXPONENT: rsa->d = bn; break; case TAG_RSA_PRIME1: rsa->p = bn; break; case TAG_RSA_PRIME2: rsa->q = bn; break; case TAG_RSA_EXPONENT1: rsa->dmp1 = bn; break; case TAG_RSA_EXPONENT2: rsa->dmq1 = bn; break; case TAG_RSA_COEFFICIENT: rsa->iqmp = bn; break; } } dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) DST_RET(DST_R_INVALIDPRIVATEKEY); key->key_size = BN_num_bits(rsa->n); if (pubrsa != NULL) RSA_free(pubrsa); #if USE_EVP RSA_free(rsa); #endif return (ISC_R_SUCCESS); err: #if USE_EVP if (pkey != NULL) EVP_PKEY_free(pkey); #endif if (rsa != NULL) RSA_free(rsa); if (pubrsa != NULL) RSA_free(pubrsa); opensslrsa_destroy(key); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ret); }
isc_result_t pk11_parse_uri(pk11_object_t *obj, const char *label, isc_mem_t *mctx, pk11_optype_t optype) { CK_ATTRIBUTE *attr; pk11_token_t *token = NULL; char *uri, *p, *a, *na, *v; size_t len, l; FILE *stream = NULL; char pin[PINLEN + 1]; isc_boolean_t gotpin = ISC_FALSE; isc_result_t ret; /* get values to work on */ len = strlen(label) + 1; uri = isc_mem_get(mctx, len); if (uri == NULL) return (ISC_R_NOMEMORY); memmove(uri, label, len); /* get the URI scheme */ p = strchr(uri, ':'); if (p == NULL) DST_RET(PK11_R_NOPROVIDER); *p++ = '\0'; if (strcmp(uri, "pkcs11") != 0) DST_RET(PK11_R_NOPROVIDER); /* get attributes */ for (na = p; na != NULL;) { a = na; p = strchr(a, ';'); if (p == NULL) { /* last attribute */ na = NULL; } else { *p++ = '\0'; na = p; } p = strchr(a, '='); if (p != NULL) { *p++ = '\0'; v = p; } else v = a; l = 0; v = percent_decode(v, &l); if (v == NULL) DST_RET(PK11_R_NOPROVIDER); if ((a == v) || (strcmp(a, "object") == 0)) { /* object: CKA_LABEL */ attr = pk11_attribute_bytype(obj, CKA_LABEL); if (attr != NULL) DST_RET(PK11_R_NOPROVIDER); attr = push_attribute(obj, mctx, l); if (attr == NULL) DST_RET(ISC_R_NOMEMORY); attr->type = CKA_LABEL; memmove(attr->pValue, v, l); } else if (strcmp(a, "token") == 0) { /* token: CK_TOKEN_INFO label */ if (token == NULL) for (token = ISC_LIST_HEAD(tokens); token != NULL; token = ISC_LIST_NEXT(token, link)) if (pk11strcmp(v, l, token->name, 32)) break; } else if (strcmp(a, "manufacturer") == 0) { /* manufacturer: CK_TOKEN_INFO manufacturerID */ if (token == NULL) for (token = ISC_LIST_HEAD(tokens); token != NULL; token = ISC_LIST_NEXT(token, link)) if (pk11strcmp(v, l, token->manuf, 32)) break; } else if (strcmp(a, "serial") == 0) { /* serial: CK_TOKEN_INFO serialNumber */ if (token == NULL) for (token = ISC_LIST_HEAD(tokens); token != NULL; token = ISC_LIST_NEXT(token, link)) if (pk11strcmp(v, l, token->serial, 16)) break; } else if (strcmp(a, "model") == 0) { /* model: CK_TOKEN_INFO model */ if (token == NULL) for (token = ISC_LIST_HEAD(tokens); token != NULL; token = ISC_LIST_NEXT(token, link)) if (pk11strcmp(v, l, token->model, 16)) break; } else if (strcmp(a, "library-manufacturer") == 0) { /* ignored */ } else if (strcmp(a, "library-description") == 0) { /* ignored */ } else if (strcmp(a, "library-version") == 0) { /* ignored */ } else if (strcmp(a, "object-type") == 0) { /* object-type: CKA_CLASS */ /* only private makes sense */ if (strcmp(v, "private") != 0) DST_RET(PK11_R_NOPROVIDER); } else if (strcmp(a, "id") == 0) { /* id: CKA_ID */ attr = pk11_attribute_bytype(obj, CKA_ID); if (attr != NULL) DST_RET(PK11_R_NOPROVIDER); attr = push_attribute(obj, mctx, l); if (attr == NULL) DST_RET(ISC_R_NOMEMORY); attr->type = CKA_ID; memmove(attr->pValue, v, l); } else if (strcmp(a, "pin-source") == 0) { /* pin-source: PIN */ ret = isc_stdio_open(v, "r", &stream); if (ret != ISC_R_SUCCESS) goto err; memset(pin, 0, PINLEN + 1); ret = isc_stdio_read(pin, 1, PINLEN + 1, stream, &l); if ((ret != ISC_R_SUCCESS) && (ret != ISC_R_EOF)) goto err; if (l > PINLEN) DST_RET(ISC_R_RANGE); ret = isc_stdio_close(stream); stream = NULL; if (ret != ISC_R_SUCCESS) goto err; gotpin = ISC_TRUE; } else DST_RET(PK11_R_NOPROVIDER); } if ((pk11_attribute_bytype(obj, CKA_LABEL) == NULL) && (pk11_attribute_bytype(obj, CKA_ID) == NULL)) DST_RET(ISC_R_NOTFOUND); if (token == NULL) { if (optype == OP_RSA) token = best_rsa_token; else if (optype == OP_DSA) token = best_dsa_token; else if (optype == OP_DH) token = best_dh_token; else if (optype == OP_EC) token = best_ec_token; } if (token == NULL) DST_RET(ISC_R_NOTFOUND); obj->slot = token->slotid; if (gotpin) { memmove(token->pin, pin, PINLEN + 1); obj->reqlogon = ISC_TRUE; } ret = ISC_R_SUCCESS; err: if (stream != NULL) (void) isc_stdio_close(stream); isc_mem_put(mctx, uri, len); return (ret); }
static isc_result_t pkcs11ecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { CK_RV rv; CK_MECHANISM mech = { CKM_ECDSA, NULL, 0 }; CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE; CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; CK_KEY_TYPE keyType = CKK_EC; CK_ATTRIBUTE keyTemplate[] = { { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, { CKA_EC_PARAMS, NULL, 0 }, { CKA_VALUE, NULL, 0 } }; CK_ATTRIBUTE *attr; CK_BYTE digest[ISC_SHA384_DIGESTLENGTH]; CK_ULONG dgstlen; CK_ULONG siglen; pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; dst_key_t *key = dctx->key; pk11_object_t *ec = key->keydata.pkey; isc_region_t r; isc_result_t ret = ISC_R_SUCCESS; unsigned int i; REQUIRE(key->key_alg == DST_ALG_ECDSA256 || key->key_alg == DST_ALG_ECDSA384); REQUIRE(ec != NULL); if (key->key_alg == DST_ALG_ECDSA256) { dgstlen = ISC_SHA256_DIGESTLENGTH; siglen = DNS_SIG_ECDSA256SIZE; } else { siglen = DNS_SIG_ECDSA384SIZE; dgstlen = ISC_SHA384_DIGESTLENGTH; } PK11_RET(pkcs_C_DigestFinal, (pk11_ctx->session, digest, &dgstlen), ISC_R_FAILURE); isc_buffer_availableregion(sig, &r); if (r.length < siglen) DST_RET(ISC_R_NOSPACE); if (ec->ontoken && (ec->object != CK_INVALID_HANDLE)) { pk11_ctx->ontoken = ec->ontoken; pk11_ctx->object = ec->object; goto token_key; } for (attr = pk11_attribute_first(ec); attr != NULL; attr = pk11_attribute_next(ec, attr)) switch (attr->type) { case CKA_EC_PARAMS: INSIST(keyTemplate[5].type == attr->type); keyTemplate[5].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[5].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[5].pValue, attr->pValue, attr->ulValueLen); keyTemplate[5].ulValueLen = attr->ulValueLen; break; case CKA_VALUE: INSIST(keyTemplate[6].type == attr->type); keyTemplate[6].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[6].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[6].pValue, attr->pValue, attr->ulValueLen); keyTemplate[6].ulValueLen = attr->ulValueLen; break; } pk11_ctx->object = CK_INVALID_HANDLE; pk11_ctx->ontoken = ISC_FALSE; PK11_RET(pkcs_C_CreateObject, (pk11_ctx->session, keyTemplate, (CK_ULONG) 7, &hKey), ISC_R_FAILURE); token_key: PK11_RET(pkcs_C_SignInit, (pk11_ctx->session, &mech, pk11_ctx->ontoken ? pk11_ctx->object : hKey), ISC_R_FAILURE); PK11_RET(pkcs_C_Sign, (pk11_ctx->session, digest, dgstlen, (CK_BYTE_PTR) r.base, &siglen), DST_R_SIGNFAILURE); isc_buffer_add(sig, (unsigned int) siglen); err: if (hKey != CK_INVALID_HANDLE) (void) pkcs_C_DestroyObject(pk11_ctx->session, hKey); for (i = 5; i <= 6; i++) if (keyTemplate[i].pValue != NULL) { memset(keyTemplate[i].pValue, 0, keyTemplate[i].ulValueLen); isc_mem_put(dctx->mctx, keyTemplate[i].pValue, keyTemplate[i].ulValueLen); } pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); dctx->ctxdata.pk11_ctx = NULL; return (ret); }
static isc_result_t pkcs11dh_loadpriv(const dst_key_t *key, CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey) { CK_RV rv; CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; CK_KEY_TYPE keyType = CKK_DH; CK_ATTRIBUTE keyTemplate[] = { { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_DERIVE, &truevalue, (CK_ULONG) sizeof(truevalue) }, { CKA_PRIME, NULL, 0 }, { CKA_BASE, NULL, 0 }, { CKA_VALUE, NULL, 0 } }; CK_ATTRIBUTE *attr; const pk11_object_t *priv; isc_result_t ret; unsigned int i; priv = key->keydata.pkey; if ((priv->object != CK_INVALID_HANDLE) && priv->ontoken) { *hKey = priv->object; return (ISC_R_SUCCESS); } attr = pk11_attribute_bytype(priv, CKA_PRIME); if (attr == NULL) return (DST_R_INVALIDPRIVATEKEY); keyTemplate[6].pValue = isc_mem_get(key->mctx, attr->ulValueLen); if (keyTemplate[6].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[6].pValue, attr->pValue, attr->ulValueLen); keyTemplate[6].ulValueLen = attr->ulValueLen; attr = pk11_attribute_bytype(priv, CKA_BASE); if (attr == NULL) DST_RET(DST_R_INVALIDPRIVATEKEY); keyTemplate[7].pValue = isc_mem_get(key->mctx, attr->ulValueLen); if (keyTemplate[7].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[7].pValue, attr->pValue, attr->ulValueLen); keyTemplate[7].ulValueLen = attr->ulValueLen; attr = pk11_attribute_bytype(priv, CKA_VALUE2); if (attr == NULL) DST_RET(DST_R_INVALIDPRIVATEKEY); keyTemplate[8].pValue = isc_mem_get(key->mctx, attr->ulValueLen); if (keyTemplate[8].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[8].pValue, attr->pValue, attr->ulValueLen); keyTemplate[8].ulValueLen = attr->ulValueLen; PK11_CALL(pkcs_C_CreateObject, (session, keyTemplate, (CK_ULONG) 9, hKey), DST_R_COMPUTESECRETFAILURE); if (rv == CKR_OK) ret = ISC_R_SUCCESS; err: for (i = 6; i <= 8; i++) if (keyTemplate[i].pValue != NULL) { memset(keyTemplate[i].pValue, 0, keyTemplate[i].ulValueLen); isc_mem_put(key->mctx, keyTemplate[i].pValue, keyTemplate[i].ulValueLen); } return (ret); }
static isc_result_t pkcs11gost_generate(dst_key_t *key, int unused, void (*callback)(int)) { CK_RV rv; CK_MECHANISM mech = { CKM_GOSTR3410_KEY_PAIR_GEN, NULL, 0 }; CK_KEY_TYPE keyType = CKK_GOSTR3410; CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE; CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; CK_ATTRIBUTE pubTemplate[] = { { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) }, { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, { CKA_GOSTR3410_PARAMS, pk11_gost_a_paramset, (CK_ULONG) sizeof(pk11_gost_a_paramset) }, { CKA_GOSTR3411_PARAMS, pk11_gost_paramset, (CK_ULONG) sizeof(pk11_gost_paramset) } }; CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE; CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY; CK_ATTRIBUTE privTemplate[] = { { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) }, { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) }, { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }, }; CK_ATTRIBUTE *attr; pk11_object_t *gost; pk11_context_t *pk11_ctx; isc_result_t ret; UNUSED(unused); UNUSED(callback); pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx, sizeof(*pk11_ctx)); if (pk11_ctx == NULL) return (ISC_R_NOMEMORY); ret = pk11_get_session(pk11_ctx, OP_GOST, ISC_FALSE, ISC_FALSE, NULL, pk11_get_best_token(OP_GOST)); if (ret != ISC_R_SUCCESS) goto err; PK11_RET(pkcs_C_GenerateKeyPair, (pk11_ctx->session, &mech, pubTemplate, (CK_ULONG) 7, privTemplate, (CK_ULONG) 7, &pub, &priv), DST_R_CRYPTOFAILURE); gost = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*gost)); if (gost == NULL) DST_RET(ISC_R_NOMEMORY); memset(gost, 0, sizeof(*gost)); key->keydata.pkey = gost; gost->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2); if (gost->repr == NULL) DST_RET(ISC_R_NOMEMORY); memset(gost->repr, 0, sizeof(*attr) * 2); gost->attrcnt = 2; attr = gost->repr; attr[0].type = CKA_VALUE; attr[1].type = CKA_VALUE2; attr = gost->repr; PK11_RET(pkcs_C_GetAttributeValue, (pk11_ctx->session, pub, attr, 1), DST_R_CRYPTOFAILURE); attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen); if (attr->pValue == NULL) DST_RET(ISC_R_NOMEMORY); memset(attr->pValue, 0, attr->ulValueLen); PK11_RET(pkcs_C_GetAttributeValue, (pk11_ctx->session, pub, attr, 1), DST_R_CRYPTOFAILURE); attr++; attr->type = CKA_VALUE; PK11_RET(pkcs_C_GetAttributeValue, (pk11_ctx->session, priv, attr, 1), DST_R_CRYPTOFAILURE); attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen); if (attr->pValue == NULL) DST_RET(ISC_R_NOMEMORY); memset(attr->pValue, 0, attr->ulValueLen); PK11_RET(pkcs_C_GetAttributeValue, (pk11_ctx->session, priv, attr, 1), DST_R_CRYPTOFAILURE); attr->type = CKA_VALUE2; (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); return (ISC_R_SUCCESS); err: pkcs11gost_destroy(key); if (priv != CK_INVALID_HANDLE) (void) pkcs_C_DestroyObject(pk11_ctx->session, priv); if (pub != CK_INVALID_HANDLE) (void) pkcs_C_DestroyObject(pk11_ctx->session, pub); pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx)); return (ret); }
static isc_result_t pkcs11ecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { dst_private_t priv; isc_result_t ret; pk11_object_t *ec = NULL; CK_ATTRIBUTE *attr, *pattr; isc_mem_t *mctx = key->mctx; unsigned int i; const char *engine = NULL, *label = NULL; REQUIRE(key->key_alg == DST_ALG_ECDSA256 || key->key_alg == DST_ALG_ECDSA384); if ((pub == NULL) || (pub->keydata.pkey == NULL)) DST_RET(DST_R_INVALIDPRIVATEKEY); /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv); if (ret != ISC_R_SUCCESS) return (ret); if (key->external) { if (priv.nelements != 0) DST_RET(DST_R_INVALIDPRIVATEKEY); key->keydata.pkey = pub->keydata.pkey; pub->keydata.pkey = NULL; key->key_size = pub->key_size; dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ISC_R_SUCCESS); } for (i = 0; i < priv.nelements; i++) { switch (priv.elements[i].tag) { case TAG_ECDSA_ENGINE: engine = (char *)priv.elements[i].data; break; case TAG_ECDSA_LABEL: label = (char *)priv.elements[i].data; break; default: break; } } ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec)); if (ec == NULL) DST_RET(ISC_R_NOMEMORY); memset(ec, 0, sizeof(*ec)); key->keydata.pkey = ec; /* Is this key is stored in a HSM? See if we can fetch it. */ if ((label != NULL) || (engine != NULL)) { ret = pkcs11ecdsa_fetch(key, engine, label, pub); if (ret != ISC_R_SUCCESS) goto err; dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ret); } ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3); if (ec->repr == NULL) DST_RET(ISC_R_NOMEMORY); memset(ec->repr, 0, sizeof(*attr) * 3); ec->attrcnt = 3; attr = ec->repr; attr->type = CKA_EC_PARAMS; pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_EC_PARAMS); INSIST(pattr != NULL); attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen); if (attr->pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(attr->pValue, pattr->pValue, pattr->ulValueLen); attr->ulValueLen = pattr->ulValueLen; attr++; attr->type = CKA_EC_POINT; pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_EC_POINT); INSIST(pattr != NULL); attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen); if (attr->pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(attr->pValue, pattr->pValue, pattr->ulValueLen); attr->ulValueLen = pattr->ulValueLen; attr++; attr->type = CKA_VALUE; attr->pValue = isc_mem_get(key->mctx, priv.elements[0].length); if (attr->pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(attr->pValue, priv.elements[0].data, priv.elements[0].length); attr->ulValueLen = priv.elements[0].length; dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); if (key->key_alg == DST_ALG_ECDSA256) key->key_size = DNS_KEY_ECDSA256SIZE * 4; else key->key_size = DNS_KEY_ECDSA384SIZE * 4; return (ISC_R_SUCCESS); err: pkcs11ecdsa_destroy(key); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ret); }
static isc_result_t pkcs11ecdsa_verify(dst_context_t *dctx, const isc_region_t *sig) { CK_RV rv; CK_MECHANISM mech = { CKM_ECDSA, NULL, 0 }; CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE; CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY; CK_KEY_TYPE keyType = CKK_EC; CK_ATTRIBUTE keyTemplate[] = { { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) }, { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) }, { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) }, { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) }, { CKA_EC_PARAMS, NULL, 0 }, { CKA_EC_POINT, NULL, 0 } }; CK_ATTRIBUTE *attr; CK_BYTE digest[ISC_SHA384_DIGESTLENGTH]; CK_ULONG dgstlen; pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx; dst_key_t *key = dctx->key; pk11_object_t *ec = key->keydata.pkey; isc_result_t ret = ISC_R_SUCCESS; unsigned int i; REQUIRE(key->key_alg == DST_ALG_ECDSA256 || key->key_alg == DST_ALG_ECDSA384); REQUIRE(ec != NULL); if (key->key_alg == DST_ALG_ECDSA256) dgstlen = ISC_SHA256_DIGESTLENGTH; else dgstlen = ISC_SHA384_DIGESTLENGTH; PK11_RET(pkcs_C_DigestFinal, (pk11_ctx->session, digest, &dgstlen), ISC_R_FAILURE); for (attr = pk11_attribute_first(ec); attr != NULL; attr = pk11_attribute_next(ec, attr)) switch (attr->type) { case CKA_EC_PARAMS: INSIST(keyTemplate[5].type == attr->type); keyTemplate[5].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[5].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[5].pValue, attr->pValue, attr->ulValueLen); keyTemplate[5].ulValueLen = attr->ulValueLen; break; case CKA_EC_POINT: INSIST(keyTemplate[6].type == attr->type); keyTemplate[6].pValue = isc_mem_get(dctx->mctx, attr->ulValueLen); if (keyTemplate[6].pValue == NULL) DST_RET(ISC_R_NOMEMORY); memmove(keyTemplate[6].pValue, attr->pValue, attr->ulValueLen); keyTemplate[6].ulValueLen = attr->ulValueLen; break; } pk11_ctx->object = CK_INVALID_HANDLE; pk11_ctx->ontoken = ISC_FALSE; PK11_RET(pkcs_C_CreateObject, (pk11_ctx->session, keyTemplate, (CK_ULONG) 7, &hKey), ISC_R_FAILURE); PK11_RET(pkcs_C_VerifyInit, (pk11_ctx->session, &mech, hKey), ISC_R_FAILURE); PK11_RET(pkcs_C_Verify, (pk11_ctx->session, digest, dgstlen, (CK_BYTE_PTR) sig->base, (CK_ULONG) sig->length), DST_R_VERIFYFAILURE); err: if (hKey != CK_INVALID_HANDLE) (void) pkcs_C_DestroyObject(pk11_ctx->session, hKey); for (i = 5; i <= 6; i++) if (keyTemplate[i].pValue != NULL) { memset(keyTemplate[i].pValue, 0, keyTemplate[i].ulValueLen); isc_mem_put(dctx->mctx, keyTemplate[i].pValue, keyTemplate[i].ulValueLen); } pk11_return_session(pk11_ctx); memset(pk11_ctx, 0, sizeof(*pk11_ctx)); isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx)); dctx->ctxdata.pk11_ctx = NULL; return (ret); }