2728d0618e15ee3a2ecc5f6d15acd7898e6de85aTinderbox User * Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * PKCS#3 DH keys:
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * mechanisms:
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * CKM_DH_PKCS_PARAMETER_GEN,
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * CKM_DH_PKCS_KEY_PAIR_GEN,
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * CKM_DH_PKCS_DERIVE
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * domain parameters:
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * object class CKO_DOMAIN_PARAMETERS
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * key type CKK_DH
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * attribute CKA_PRIME (prime p)
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * attribute CKA_BASE (base g)
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * optional attribute CKA_PRIME_BITS (p length in bits)
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * public key:
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * object class CKO_PUBLIC_KEY
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * key type CKK_DH
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * attribute CKA_PRIME (prime p)
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * attribute CKA_BASE (base g)
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * attribute CKA_VALUE (public value y)
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * private key:
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * object class CKO_PRIVATE_KEY
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * key type CKK_DH
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * attribute CKA_PRIME (prime p)
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * attribute CKA_BASE (base g)
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * attribute CKA_VALUE (private value x)
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * optional attribute CKA_VALUE_BITS (x length in bits)
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * reuse CKA_PRIVATE_EXPONENT for key pair private value
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Huntstatic isc_result_t pkcs11dh_todns(const dst_key_t *key, isc_buffer_t *data);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_DERIVE, &truevalue, (CK_ULONG) sizeof(truevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt unsigned int i;
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt if ((priv->object != CK_INVALID_HANDLE) && priv->ontoken) {
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt keyTemplate[6].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
1b255a0c4eaccf0feff70328a8c108a22abfbf3cEvan Hunt memmove(keyTemplate[6].pValue, attr->pValue, attr->ulValueLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt keyTemplate[7].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
1b255a0c4eaccf0feff70328a8c108a22abfbf3cEvan Hunt memmove(keyTemplate[7].pValue, attr->pValue, attr->ulValueLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt keyTemplate[8].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
1b255a0c4eaccf0feff70328a8c108a22abfbf3cEvan Hunt memmove(keyTemplate[8].pValue, attr->pValue, attr->ulValueLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Huntpkcs11dh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt CK_MECHANISM mech = { CKM_DH_PKCS_DERIVE, NULL, 0 };
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_VALUE_LEN, &secLen, (CK_ULONG) sizeof(secLen) }
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt unsigned int i;
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt attr = pk11_attribute_bytype(pub->keydata.pkey, CKA_PRIME);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt attr = pk11_attribute_bytype(pub->keydata.pkey, CKA_VALUE);
f5c17a057fc5974bb51d7bc8c5827a7fd6dc9aeeEvan Hunt ret = pk11_get_session(&ctx, OP_DH, ISC_TRUE, ISC_FALSE,
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt mech.pParameter = isc_mem_get(pub->mctx, mech.ulParameterLen);
1b255a0c4eaccf0feff70328a8c108a22abfbf3cEvan Hunt memmove(mech.pParameter, attr->pValue, mech.ulParameterLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt ret = pkcs11dh_loadpriv(priv, ctx.session, &hKey);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt attr->pValue = isc_mem_get(pub->mctx, attr->ulValueLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt /* strip leading zeros */
1b255a0c4eaccf0feff70328a8c108a22abfbf3cEvan Hunt memmove(r.base, secValue + i, attr->ulValueLen - i);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt (void) pkcs_C_DestroyObject(ctx.session, hDerived);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt if ((hKey != CK_INVALID_HANDLE) && !priv->keydata.pkey->ontoken)
b5252fcde512405a68dd4becfe683d9763bd0feaMukund Sivaraman isc_safe_memwipe(mech.pParameter, mech.ulParameterLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt isc_mem_put(pub->mctx, mech.pParameter, mech.ulParameterLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Huntpkcs11dh_compare(const dst_key_t *key1, const dst_key_t *key2) {
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Huntpkcs11dh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Huntpkcs11dh_generate(dst_key_t *key, int generator, void (*callback)(int)) {
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt CK_MECHANISM mech = { CKM_DH_PKCS_PARAMETER_GEN, NULL, 0 };
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt CK_OBJECT_HANDLE domainparams = CK_INVALID_HANDLE;
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_CLASS, &dClass, (CK_ULONG) sizeof(dClass) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_PRIME_BITS, &bits, (CK_ULONG) sizeof(bits) }
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_KEY_TYPE,&keyType, (CK_ULONG) sizeof(keyType) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt { CKA_DERIVE, &truevalue, (CK_ULONG) sizeof(truevalue) },
dbb012765c735ee0d82dedb116cdc7cf18957814Evan Hunt pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
acbb301e648b82fcc38b876a44403cf0fe539cc9Evan Hunt ret = pk11_get_session(pk11_ctx, OP_DH, ISC_TRUE, ISC_FALSE,
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt if ((generator == 0) &&
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt ((bits == 768) || (bits == 1024) || (bits == 1536))) {
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn768);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn1024);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn1536);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt memset(pTemplate[0].pValue, 0, pTemplate[0].ulValueLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt memset(pTemplate[1].pValue, 0, pTemplate[1].ulValueLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt pubTemplate[4].ulValueLen = pTemplate[0].ulValueLen;
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt pubTemplate[5].ulValueLen = pTemplate[1].ulValueLen;
dbb012765c735ee0d82dedb116cdc7cf18957814Evan Hunt dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh));
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 4);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt (void) pkcs_C_DestroyObject(pk11_ctx->session, domainparams);
b5252fcde512405a68dd4becfe683d9763bd0feaMukund Sivaraman isc_safe_memwipe(pk11_ctx, sizeof(*pk11_ctx));
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt (void) pkcs_C_DestroyObject(pk11_ctx->session, domainparams);
b5252fcde512405a68dd4becfe683d9763bd0feaMukund Sivaraman isc_safe_memwipe(pk11_ctx, sizeof(*pk11_ctx));
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt INSIST((dh->object == CK_INVALID_HANDLE) || dh->ontoken);
b5252fcde512405a68dd4becfe683d9763bd0feaMukund Sivaraman isc_safe_memwipe(dh->repr, dh->attrcnt * sizeof(*attr));
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt isc_mem_put(key->mctx, dh->repr, dh->attrcnt * sizeof(*attr));
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Huntuint16_toregion(isc_uint16_t val, isc_region_t *region) {
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Huntpkcs11dh_todns(const dst_key_t *key, isc_buffer_t *data) {
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt isc_uint16_t dnslen, plen = 0, glen = 0, publen = 0;
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt REQUIRE((prime != NULL) && (base != NULL) && (pub != NULL));
420a43c8d8028992a4e9c170022f97bfac689025Evan Hunt if ((glen == 1) && isc_safe_memequal(pk11_dh_bn2, base, glen) &&
420a43c8d8028992a4e9c170022f97bfac689025Evan Hunt isc_safe_memequal(pk11_dh_bn1024, prime, plen)) ||
420a43c8d8028992a4e9c170022f97bfac689025Evan Hunt isc_safe_memequal(pk11_dh_bn1536, prime, plen)))) {
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Huntpkcs11dh_fromdns(dst_key_t *key, isc_buffer_t *data) {
dbb012765c735ee0d82dedb116cdc7cf18957814Evan Hunt dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh));
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * Read the prime length. 1 & 2 are table entries, > 16 means a
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * prime follows, otherwise an error.
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * Read the generator length. This should be 0 if the prime was
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * special, but it might not be. If it's 0 and the prime is not
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt * special, we have a problem.
b5252fcde512405a68dd4becfe683d9763bd0feaMukund Sivaraman if (!isc_safe_memequal(base, pk11_dh_bn2, glen))
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt isc_buffer_forward(data, plen + glen + publen + 6);
b5252fcde512405a68dd4becfe683d9763bd0feaMukund Sivaraman isc_safe_memwipe(dh->repr, dh->attrcnt * sizeof(*attr));
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt isc_mem_put(key->mctx, dh->repr, dh->attrcnt * sizeof(*attr));
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Huntpkcs11dh_tofile(const dst_key_t *key, const char *directory) {
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt CK_ATTRIBUTE *prime = NULL, *base = NULL, *pub = NULL, *prv = NULL;
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt for (i = 0; i < 4; i++) {
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt bufs[i] = isc_mem_get(key->mctx, prime->ulValueLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt priv.elements[i].length = (unsigned short) prime->ulValueLen;
1b255a0c4eaccf0feff70328a8c108a22abfbf3cEvan Hunt memmove(bufs[i], prime->pValue, prime->ulValueLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt priv.elements[i].length = (unsigned short) base->ulValueLen;
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt priv.elements[i].length = (unsigned short) prv->ulValueLen;
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt priv.elements[i].length = (unsigned short) pub->ulValueLen;
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt result = dst__privstruct_writefile(key, &priv, directory);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt for (i = 0; i < 4; i++) {
b5252fcde512405a68dd4becfe683d9763bd0feaMukund Sivaraman isc_safe_memwipe(bufs[i], prime->ulValueLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt isc_mem_put(key->mctx, bufs[i], prime->ulValueLen);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Huntpkcs11dh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt /* read private key file */
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt ret = dst__privstruct_parse(key, DST_ALG_DH, lexer, mctx, &priv);
dbb012765c735ee0d82dedb116cdc7cf18957814Evan Hunt dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh));
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 4);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt bn = isc_mem_get(key->mctx, priv.elements[i].length);
1b255a0c4eaccf0feff70328a8c108a22abfbf3cEvan Hunt memmove(bn, priv.elements[i].data, priv.elements[i].length);
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
c40906dfad6dd6e3a3e3c94b8c8847bc9bc064e5Mark Andrews#endif /* !PK11_DH_DISABLE */
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt#else /* PKCS11CRYPTO */
ba751492fcc4f161a18b983d4f018a1a52938cb9Evan Hunt#endif /* PKCS11CRYPTO */