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 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 hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer) { dst_private_t priv; isc_result_t ret; isc_buffer_t b; isc_mem_t *mctx = key->mctx; /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_HMACMD5, lexer, mctx, &priv); if (ret != ISC_R_SUCCESS) return (ret); isc_buffer_init(&b, priv.elements[0].data, priv.elements[0].length); isc_buffer_add(&b, priv.elements[0].length); ret = hmacmd5_fromdns(key, &b); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); 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); }
int dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, isc_mem_t *mctx, dst_private_t *priv) { int n = 0, major, minor; isc_buffer_t b; isc_token_t token; unsigned char *data = NULL; unsigned int opt = ISC_LEXOPT_EOL; isc_result_t ret; REQUIRE(priv != NULL); priv->nelements = 0; #define NEXTTOKEN(lex, opt, token) \ do { \ ret = isc_lex_gettoken(lex, opt, token); \ if (ret != ISC_R_SUCCESS) \ goto fail; \ } while (0) #define READLINE(lex, opt, token) \ do { \ ret = isc_lex_gettoken(lex, opt, token); \ if (ret == ISC_R_EOF) \ break; \ else if (ret != ISC_R_SUCCESS) \ goto fail; \ } while ((*token).type != isc_tokentype_eol) /* * Read the description line. */ NEXTTOKEN(lex, opt, &token); if (token.type != isc_tokentype_string || strcmp(DST_AS_STR(token), PRIVATE_KEY_STR) != 0) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } NEXTTOKEN(lex, opt, &token); if (token.type != isc_tokentype_string || (DST_AS_STR(token))[0] != 'v') { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } if (sscanf(DST_AS_STR(token), "v%d.%d", &major, &minor) != 2) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } if (major > MAJOR_VERSION || (major == MAJOR_VERSION && minor > MINOR_VERSION)) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } READLINE(lex, opt, &token); /* * Read the algorithm line. */ NEXTTOKEN(lex, opt, &token); if (token.type != isc_tokentype_string || strcmp(DST_AS_STR(token), ALGORITHM_STR) != 0) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token); if (token.type != isc_tokentype_number || token.value.as_ulong != (unsigned long) dst_key_alg(key)) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } READLINE(lex, opt, &token); /* * Read the key data. */ for (n = 0; n < MAXFIELDS; n++) { int tag; isc_region_t r; do { ret = isc_lex_gettoken(lex, opt, &token); if (ret == ISC_R_EOF) goto done; if (ret != ISC_R_SUCCESS) goto fail; } while (token.type == isc_tokentype_eol); if (token.type != isc_tokentype_string) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } memset(&priv->elements[n], 0, sizeof(dst_private_element_t)); tag = find_value(DST_AS_STR(token), alg); if (tag < 0 || TAG_ALG(tag) != alg) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } priv->elements[n].tag = tag; data = (unsigned char *) isc_mem_get(mctx, MAXFIELDSIZE); if (data == NULL) goto fail; isc_buffer_init(&b, data, MAXFIELDSIZE); ret = isc_base64_tobuffer(lex, &b, -1); if (ret != ISC_R_SUCCESS) goto fail; isc_buffer_usedregion(&b, &r); priv->elements[n].length = r.length; priv->elements[n].data = r.base; READLINE(lex, opt, &token); data = NULL; } done: priv->nelements = n; if (check_data(priv, alg) < 0) goto fail; return (ISC_R_SUCCESS); fail: priv->nelements = n; dst__privstruct_free(priv, mctx); if (data != NULL) isc_mem_put(mctx, data, MAXFIELDSIZE); 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 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 dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex, isc_mem_t *mctx, dst_private_t *priv) { int n = 0, major, minor, check; isc_buffer_t b; isc_token_t token; unsigned char *data = NULL; unsigned int opt = ISC_LEXOPT_EOL; isc_stdtime_t when; isc_result_t ret; isc_boolean_t external = ISC_FALSE; REQUIRE(priv != NULL); priv->nelements = 0; memset(priv->elements, 0, sizeof(priv->elements)); #define NEXTTOKEN(lex, opt, token) \ do { \ ret = isc_lex_gettoken(lex, opt, token); \ if (ret != ISC_R_SUCCESS) \ goto fail; \ } while (/*CONSTCOND*/0) #define READLINE(lex, opt, token) \ do { \ ret = isc_lex_gettoken(lex, opt, token); \ if (ret == ISC_R_EOF) \ break; \ else if (ret != ISC_R_SUCCESS) \ goto fail; \ } while ((*token).type != isc_tokentype_eol) /* * Read the description line. */ NEXTTOKEN(lex, opt, &token); if (token.type != isc_tokentype_string || strcmp(DST_AS_STR(token), PRIVATE_KEY_STR) != 0) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } NEXTTOKEN(lex, opt, &token); if (token.type != isc_tokentype_string || (DST_AS_STR(token))[0] != 'v') { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } if (sscanf(DST_AS_STR(token), "v%d.%d", &major, &minor) != 2) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } if (major > DST_MAJOR_VERSION) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } /* * Store the private key format version number */ dst_key_setprivateformat(key, major, minor); READLINE(lex, opt, &token); /* * Read the algorithm line. */ NEXTTOKEN(lex, opt, &token); if (token.type != isc_tokentype_string || strcmp(DST_AS_STR(token), ALGORITHM_STR) != 0) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token); if (token.type != isc_tokentype_number || token.value.as_ulong != (unsigned long) dst_key_alg(key)) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } READLINE(lex, opt, &token); /* * Read the key data. */ for (n = 0; n < MAXFIELDS; n++) { int tag; isc_region_t r; do { ret = isc_lex_gettoken(lex, opt, &token); if (ret == ISC_R_EOF) goto done; if (ret != ISC_R_SUCCESS) goto fail; } while (token.type == isc_tokentype_eol); if (token.type != isc_tokentype_string) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } if (strcmp(DST_AS_STR(token), "External:") == 0) { external = ISC_TRUE; goto next; } /* Numeric metadata */ tag = find_numericdata(DST_AS_STR(token)); if (tag >= 0) { INSIST(tag < NUMERIC_NTAGS); NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token); if (token.type != isc_tokentype_number) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } dst_key_setnum(key, tag, token.value.as_ulong); goto next; } /* Timing metadata */ tag = find_timedata(DST_AS_STR(token)); if (tag >= 0) { INSIST(tag < TIMING_NTAGS); NEXTTOKEN(lex, opt, &token); if (token.type != isc_tokentype_string) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } ret = dns_time32_fromtext(DST_AS_STR(token), &when); if (ret != ISC_R_SUCCESS) goto fail; dst_key_settime(key, tag, when); goto next; } /* Key data */ tag = find_value(DST_AS_STR(token), alg); if (tag < 0 && minor > DST_MINOR_VERSION) goto next; else if (tag < 0) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } priv->elements[n].tag = tag; data = (unsigned char *) isc_mem_get(mctx, MAXFIELDSIZE); if (data == NULL) goto fail; isc_buffer_init(&b, data, MAXFIELDSIZE); ret = isc_base64_tobuffer(lex, &b, -1); if (ret != ISC_R_SUCCESS) goto fail; isc_buffer_usedregion(&b, &r); priv->elements[n].length = r.length; priv->elements[n].data = r.base; priv->nelements++; next: READLINE(lex, opt, &token); data = NULL; } done: if (external && priv->nelements != 0) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } check = check_data(priv, alg, ISC_TRUE, external); if (check < 0) { ret = DST_R_INVALIDPRIVATEKEY; goto fail; } else if (check != ISC_R_SUCCESS) { ret = check; goto fail; } key->external = external; return (ISC_R_SUCCESS); fail: dst__privstruct_free(priv, mctx); if (data != NULL) isc_mem_put(mctx, data, MAXFIELDSIZE); 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 opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) { dst_private_t priv; isc_result_t ret; int i; RSA *rsa = NULL; isc_mem_t *mctx = key->mctx; #define DST_RET(a) {ret = a; goto err;} /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv); if (ret != ISC_R_SUCCESS) return (ret); rsa = RSA_new(); if (rsa == NULL) DST_RET(ISC_R_NOMEMORY); SET_FLAGS(rsa); key->opaque = rsa; 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_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); key->key_size = BN_num_bits(rsa->n); return (ISC_R_SUCCESS); err: opensslrsa_destroy(key); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); 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; EC_KEY *eckey; const EC_POINT *pubkey = NULL; BIGNUM *privkey = NULL; const unsigned char *p; /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_ECCGOST, 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); } INSIST((priv.elements[0].tag == TAG_GOST_PRIVASN1) || (priv.elements[0].tag == TAG_GOST_PRIVRAW)); if (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)); } else { if ((pub != NULL) && (pub->keydata.pkey != NULL)) { eckey = EVP_PKEY_get0(pub->keydata.pkey); pubkey = EC_KEY_get0_public_key(eckey); } privkey = BN_bin2bn(priv.elements[0].data, priv.elements[0].length, NULL); if (privkey == NULL) DST_RET(ISC_R_NOMEMORY); /* can't create directly the whole key */ p = gost_dummy_key; if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p, (long) sizeof(gost_dummy_key)) == NULL) DST_RET(dst__openssl_toresult2( "d2i_PrivateKey", DST_R_INVALIDPRIVATEKEY)); eckey = EVP_PKEY_get0(pkey); if (eckey == NULL) return (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); if (!EC_KEY_set_private_key(eckey, privkey)) DST_RET(ISC_R_NOMEMORY); /* have to (re)set the public key */ #ifdef notyet (void) gost2001_compute_public(eckey); #else if ((pubkey != NULL) && !EC_KEY_set_public_key(eckey, pubkey)) DST_RET(ISC_R_NOMEMORY); #endif BN_clear_free(privkey); privkey = NULL; } 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 (privkey != NULL) BN_clear_free(privkey); 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 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 *ep = NULL; const BIGNUM *ex = 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 BIGNUM *n = NULL, *e = NULL, *d = NULL; BIGNUM *p = NULL, *q = NULL; BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv); if (ret != ISC_R_SUCCESS) goto err; 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); } #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 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); ep = dst__openssl_getengine(engine); if (ep == NULL) DST_RET(DST_R_NOENGINE); pkey = ENGINE_load_private_key(ep, 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); RSA_get0_key(rsa, NULL, &ex, NULL); if (BN_num_bits(ex) > RSA_MAX_PUBEXP_BITS) DST_RET(ISC_R_RANGE); 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; 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: n = bn; break; case TAG_RSA_PUBLICEXPONENT: e = bn; break; case TAG_RSA_PRIVATEEXPONENT: d = bn; break; case TAG_RSA_PRIME1: p = bn; break; case TAG_RSA_PRIME2: q = bn; break; case TAG_RSA_EXPONENT1: dmp1 = bn; break; case TAG_RSA_EXPONENT2: dmq1 = bn; break; case TAG_RSA_COEFFICIENT: iqmp = bn; break; } } } dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); if (RSA_set0_key(rsa, n, e, d) == 0) { if (n != NULL) BN_free(n); if (e != NULL) BN_free(e); if (d != NULL) BN_free(d); } if (RSA_set0_factors(rsa, p, q) == 0) { if (p != NULL) BN_free(p); if (q != NULL) BN_free(q); } if (RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp) == 0) { if (dmp1 != NULL) BN_free(dmp1); if (dmq1 != NULL) BN_free(dmq1); if (iqmp != NULL) BN_free(iqmp); } if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) DST_RET(DST_R_INVALIDPRIVATEKEY); if (BN_num_bits(e) > RSA_MAX_PUBEXP_BITS) DST_RET(ISC_R_RANGE); key->key_size = BN_num_bits(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); key->keydata.generic = NULL; dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ret); }
static isc_result_t pkcs11dsa_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 *dsa = NULL; CK_ATTRIBUTE *attr; isc_mem_t *mctx = key->mctx; /* read private key file */ ret = dst__privstruct_parse(key, DST_ALG_DSA, 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); } dsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dsa)); if (dsa == NULL) DST_RET(ISC_R_NOMEMORY); memset(dsa, 0, sizeof(*dsa)); key->keydata.pkey = dsa; dsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 5); if (dsa->repr == NULL) DST_RET(ISC_R_NOMEMORY); memset(dsa->repr, 0, sizeof(*attr) * 5); dsa->attrcnt = 5; attr = dsa->repr; attr[0].type = CKA_PRIME; attr[1].type = CKA_SUBPRIME; attr[2].type = CKA_BASE; attr[3].type = CKA_VALUE; attr[4].type = CKA_VALUE2; for (i = 0; i < priv.nelements; i++) { CK_BYTE *bn; 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_DSA_PRIME: attr = pk11_attribute_bytype(dsa, CKA_PRIME); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_DSA_SUBPRIME: attr = pk11_attribute_bytype(dsa, CKA_SUBPRIME); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_DSA_BASE: attr = pk11_attribute_bytype(dsa, CKA_BASE); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_DSA_PRIVATE: attr = pk11_attribute_bytype(dsa, CKA_VALUE2); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; case TAG_DSA_PUBLIC: attr = pk11_attribute_bytype(dsa, CKA_VALUE); INSIST(attr != NULL); attr->pValue = bn; attr->ulValueLen = priv.elements[i].length; break; } } dst__privstruct_free(&priv, mctx); attr = pk11_attribute_bytype(dsa, CKA_PRIME); INSIST(attr != NULL); key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen); return (ISC_R_SUCCESS); err: pkcs11dsa_destroy(key); dst__privstruct_free(&priv, mctx); memset(&priv, 0, sizeof(priv)); return (ret); }