xref: /freebsd/contrib/ldns/keys.c (revision 17d15b251108ff09e632ed4812f7c66999a6b69b)
17b5038d7SDag-Erling Smørgrav /*
27b5038d7SDag-Erling Smørgrav  * keys.c handle private keys for use in DNSSEC
37b5038d7SDag-Erling Smørgrav  *
47b5038d7SDag-Erling Smørgrav  * This module should hide some of the openSSL complexities
57b5038d7SDag-Erling Smørgrav  * and give a general interface for private keys and hmac
67b5038d7SDag-Erling Smørgrav  * handling
77b5038d7SDag-Erling Smørgrav  *
87b5038d7SDag-Erling Smørgrav  * (c) NLnet Labs, 2004-2006
97b5038d7SDag-Erling Smørgrav  *
107b5038d7SDag-Erling Smørgrav  * See the file LICENSE for the license
117b5038d7SDag-Erling Smørgrav  */
127b5038d7SDag-Erling Smørgrav 
137b5038d7SDag-Erling Smørgrav #include <ldns/config.h>
147b5038d7SDag-Erling Smørgrav 
157b5038d7SDag-Erling Smørgrav #include <ldns/ldns.h>
167b5038d7SDag-Erling Smørgrav 
177b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
187b5038d7SDag-Erling Smørgrav #include <openssl/ssl.h>
197b5038d7SDag-Erling Smørgrav #include <openssl/engine.h>
207b5038d7SDag-Erling Smørgrav #include <openssl/rand.h>
217b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
227b5038d7SDag-Erling Smørgrav 
237b5038d7SDag-Erling Smørgrav ldns_lookup_table ldns_signing_algorithms[] = {
247b5038d7SDag-Erling Smørgrav         { LDNS_SIGN_RSAMD5, "RSAMD5" },
257b5038d7SDag-Erling Smørgrav         { LDNS_SIGN_RSASHA1, "RSASHA1" },
267b5038d7SDag-Erling Smørgrav         { LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
277b5038d7SDag-Erling Smørgrav #ifdef USE_SHA2
287b5038d7SDag-Erling Smørgrav         { LDNS_SIGN_RSASHA256, "RSASHA256" },
297b5038d7SDag-Erling Smørgrav         { LDNS_SIGN_RSASHA512, "RSASHA512" },
307b5038d7SDag-Erling Smørgrav #endif
317b5038d7SDag-Erling Smørgrav #ifdef USE_GOST
327b5038d7SDag-Erling Smørgrav         { LDNS_SIGN_ECC_GOST, "ECC-GOST" },
337b5038d7SDag-Erling Smørgrav #endif
347b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA
357b5038d7SDag-Erling Smørgrav         { LDNS_SIGN_ECDSAP256SHA256, "ECDSAP256SHA256" },
367b5038d7SDag-Erling Smørgrav         { LDNS_SIGN_ECDSAP384SHA384, "ECDSAP384SHA384" },
377b5038d7SDag-Erling Smørgrav #endif
387b5038d7SDag-Erling Smørgrav         { LDNS_SIGN_DSA, "DSA" },
397b5038d7SDag-Erling Smørgrav         { LDNS_SIGN_DSA_NSEC3, "DSA-NSEC3-SHA1" },
407b5038d7SDag-Erling Smørgrav         { LDNS_SIGN_HMACMD5, "hmac-md5.sig-alg.reg.int" },
417b5038d7SDag-Erling Smørgrav         { LDNS_SIGN_HMACSHA1, "hmac-sha1" },
427b5038d7SDag-Erling Smørgrav         { LDNS_SIGN_HMACSHA256, "hmac-sha256" },
437b5038d7SDag-Erling Smørgrav         { 0, NULL }
447b5038d7SDag-Erling Smørgrav };
457b5038d7SDag-Erling Smørgrav 
467b5038d7SDag-Erling Smørgrav ldns_key_list *
477b5038d7SDag-Erling Smørgrav ldns_key_list_new(void)
487b5038d7SDag-Erling Smørgrav {
497b5038d7SDag-Erling Smørgrav 	ldns_key_list *key_list = LDNS_MALLOC(ldns_key_list);
507b5038d7SDag-Erling Smørgrav 	if (!key_list) {
517b5038d7SDag-Erling Smørgrav 		return NULL;
527b5038d7SDag-Erling Smørgrav 	} else {
537b5038d7SDag-Erling Smørgrav 		key_list->_key_count = 0;
547b5038d7SDag-Erling Smørgrav 		key_list->_keys = NULL;
557b5038d7SDag-Erling Smørgrav 		return key_list;
567b5038d7SDag-Erling Smørgrav 	}
577b5038d7SDag-Erling Smørgrav }
587b5038d7SDag-Erling Smørgrav 
597b5038d7SDag-Erling Smørgrav ldns_key *
607b5038d7SDag-Erling Smørgrav ldns_key_new(void)
617b5038d7SDag-Erling Smørgrav {
627b5038d7SDag-Erling Smørgrav 	ldns_key *newkey;
637b5038d7SDag-Erling Smørgrav 
647b5038d7SDag-Erling Smørgrav 	newkey = LDNS_MALLOC(ldns_key);
657b5038d7SDag-Erling Smørgrav 	if (!newkey) {
667b5038d7SDag-Erling Smørgrav 		return NULL;
677b5038d7SDag-Erling Smørgrav 	} else {
687b5038d7SDag-Erling Smørgrav 		/* some defaults - not sure wether to do this */
697b5038d7SDag-Erling Smørgrav 		ldns_key_set_use(newkey, true);
707b5038d7SDag-Erling Smørgrav 		ldns_key_set_flags(newkey, LDNS_KEY_ZONE_KEY);
717b5038d7SDag-Erling Smørgrav 		ldns_key_set_origttl(newkey, 0);
727b5038d7SDag-Erling Smørgrav 		ldns_key_set_keytag(newkey, 0);
737b5038d7SDag-Erling Smørgrav 		ldns_key_set_inception(newkey, 0);
747b5038d7SDag-Erling Smørgrav 		ldns_key_set_expiration(newkey, 0);
757b5038d7SDag-Erling Smørgrav 		ldns_key_set_pubkey_owner(newkey, NULL);
767b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
777b5038d7SDag-Erling Smørgrav 		ldns_key_set_evp_key(newkey, NULL);
787b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
797b5038d7SDag-Erling Smørgrav 		ldns_key_set_hmac_key(newkey, NULL);
807b5038d7SDag-Erling Smørgrav 		ldns_key_set_external_key(newkey, NULL);
817b5038d7SDag-Erling Smørgrav 		return newkey;
827b5038d7SDag-Erling Smørgrav 	}
837b5038d7SDag-Erling Smørgrav }
847b5038d7SDag-Erling Smørgrav 
857b5038d7SDag-Erling Smørgrav ldns_status
867b5038d7SDag-Erling Smørgrav ldns_key_new_frm_fp(ldns_key **k, FILE *fp)
877b5038d7SDag-Erling Smørgrav {
887b5038d7SDag-Erling Smørgrav 	return ldns_key_new_frm_fp_l(k, fp, NULL);
897b5038d7SDag-Erling Smørgrav }
907b5038d7SDag-Erling Smørgrav 
917b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
927b5038d7SDag-Erling Smørgrav ldns_status
937b5038d7SDag-Erling Smørgrav ldns_key_new_frm_engine(ldns_key **key, ENGINE *e, char *key_id, ldns_algorithm alg)
947b5038d7SDag-Erling Smørgrav {
957b5038d7SDag-Erling Smørgrav 	ldns_key *k;
967b5038d7SDag-Erling Smørgrav 
977b5038d7SDag-Erling Smørgrav 	k = ldns_key_new();
987b5038d7SDag-Erling Smørgrav         if(!k) return LDNS_STATUS_MEM_ERR;
997b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
1007b5038d7SDag-Erling Smørgrav 	k->_key.key = ENGINE_load_private_key(e, key_id, UI_OpenSSL(), NULL);
1017b5038d7SDag-Erling Smørgrav         if(!k->_key.key) {
1027b5038d7SDag-Erling Smørgrav                 ldns_key_free(k);
1037b5038d7SDag-Erling Smørgrav                 return LDNS_STATUS_ERR;
1047b5038d7SDag-Erling Smørgrav         }
1057b5038d7SDag-Erling Smørgrav 	ldns_key_set_algorithm(k, (ldns_signing_algorithm) alg);
1067b5038d7SDag-Erling Smørgrav 	if (!k->_key.key) {
1077b5038d7SDag-Erling Smørgrav                 ldns_key_free(k);
1087b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_ENGINE_KEY_NOT_LOADED;
1097b5038d7SDag-Erling Smørgrav 	}
1107b5038d7SDag-Erling Smørgrav #endif /* splint */
1117b5038d7SDag-Erling Smørgrav 	*key = k;
1127b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_OK;
1137b5038d7SDag-Erling Smørgrav }
1147b5038d7SDag-Erling Smørgrav #endif
1157b5038d7SDag-Erling Smørgrav 
1167b5038d7SDag-Erling Smørgrav #ifdef USE_GOST
1177b5038d7SDag-Erling Smørgrav /** store GOST engine reference loaded into OpenSSL library */
1187b5038d7SDag-Erling Smørgrav ENGINE* ldns_gost_engine = NULL;
1197b5038d7SDag-Erling Smørgrav 
1207b5038d7SDag-Erling Smørgrav int
1217b5038d7SDag-Erling Smørgrav ldns_key_EVP_load_gost_id(void)
1227b5038d7SDag-Erling Smørgrav {
1237b5038d7SDag-Erling Smørgrav 	static int gost_id = 0;
1247b5038d7SDag-Erling Smørgrav 	const EVP_PKEY_ASN1_METHOD* meth;
1257b5038d7SDag-Erling Smørgrav 	ENGINE* e;
1267b5038d7SDag-Erling Smørgrav 
1277b5038d7SDag-Erling Smørgrav 	if(gost_id) return gost_id;
1287b5038d7SDag-Erling Smørgrav 
1297b5038d7SDag-Erling Smørgrav 	/* see if configuration loaded gost implementation from other engine*/
1307b5038d7SDag-Erling Smørgrav 	meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
1317b5038d7SDag-Erling Smørgrav 	if(meth) {
1327b5038d7SDag-Erling Smørgrav 		EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
1337b5038d7SDag-Erling Smørgrav 		return gost_id;
1347b5038d7SDag-Erling Smørgrav 	}
1357b5038d7SDag-Erling Smørgrav 
1367b5038d7SDag-Erling Smørgrav 	/* see if engine can be loaded already */
1377b5038d7SDag-Erling Smørgrav 	e = ENGINE_by_id("gost");
1387b5038d7SDag-Erling Smørgrav 	if(!e) {
1397b5038d7SDag-Erling Smørgrav 		/* load it ourself, in case statically linked */
1407b5038d7SDag-Erling Smørgrav 		ENGINE_load_builtin_engines();
1417b5038d7SDag-Erling Smørgrav 		ENGINE_load_dynamic();
1427b5038d7SDag-Erling Smørgrav 		e = ENGINE_by_id("gost");
1437b5038d7SDag-Erling Smørgrav 	}
1447b5038d7SDag-Erling Smørgrav 	if(!e) {
1457b5038d7SDag-Erling Smørgrav 		/* no gost engine in openssl */
1467b5038d7SDag-Erling Smørgrav 		return 0;
1477b5038d7SDag-Erling Smørgrav 	}
1487b5038d7SDag-Erling Smørgrav 	if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
1497b5038d7SDag-Erling Smørgrav 		ENGINE_finish(e);
1507b5038d7SDag-Erling Smørgrav 		ENGINE_free(e);
1517b5038d7SDag-Erling Smørgrav 		return 0;
1527b5038d7SDag-Erling Smørgrav 	}
1537b5038d7SDag-Erling Smørgrav 
1547b5038d7SDag-Erling Smørgrav 	meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
1557b5038d7SDag-Erling Smørgrav 	if(!meth) {
1567b5038d7SDag-Erling Smørgrav 		/* algo not found */
1577b5038d7SDag-Erling Smørgrav 		ENGINE_finish(e);
1587b5038d7SDag-Erling Smørgrav 		ENGINE_free(e);
1597b5038d7SDag-Erling Smørgrav 		return 0;
1607b5038d7SDag-Erling Smørgrav 	}
1617b5038d7SDag-Erling Smørgrav         /* Note: do not ENGINE_finish and ENGINE_free the acquired engine
1627b5038d7SDag-Erling Smørgrav          * on some platforms this frees up the meth and unloads gost stuff */
1637b5038d7SDag-Erling Smørgrav         ldns_gost_engine = e;
1647b5038d7SDag-Erling Smørgrav 
1657b5038d7SDag-Erling Smørgrav 	EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
1667b5038d7SDag-Erling Smørgrav 	return gost_id;
1677b5038d7SDag-Erling Smørgrav }
1687b5038d7SDag-Erling Smørgrav 
1697b5038d7SDag-Erling Smørgrav void ldns_key_EVP_unload_gost(void)
1707b5038d7SDag-Erling Smørgrav {
1717b5038d7SDag-Erling Smørgrav         if(ldns_gost_engine) {
1727b5038d7SDag-Erling Smørgrav                 ENGINE_finish(ldns_gost_engine);
1737b5038d7SDag-Erling Smørgrav                 ENGINE_free(ldns_gost_engine);
1747b5038d7SDag-Erling Smørgrav                 ldns_gost_engine = NULL;
1757b5038d7SDag-Erling Smørgrav         }
1767b5038d7SDag-Erling Smørgrav }
1777b5038d7SDag-Erling Smørgrav 
1787b5038d7SDag-Erling Smørgrav /** read GOST private key */
1797b5038d7SDag-Erling Smørgrav static EVP_PKEY*
1807b5038d7SDag-Erling Smørgrav ldns_key_new_frm_fp_gost_l(FILE* fp, int* line_nr)
1817b5038d7SDag-Erling Smørgrav {
1827b5038d7SDag-Erling Smørgrav 	char token[16384];
1837b5038d7SDag-Erling Smørgrav 	const unsigned char* pp;
1847b5038d7SDag-Erling Smørgrav 	int gost_id;
1857b5038d7SDag-Erling Smørgrav 	EVP_PKEY* pkey;
1867b5038d7SDag-Erling Smørgrav 	ldns_rdf* b64rdf = NULL;
1877b5038d7SDag-Erling Smørgrav 
1887b5038d7SDag-Erling Smørgrav 	gost_id = ldns_key_EVP_load_gost_id();
1897b5038d7SDag-Erling Smørgrav 	if(!gost_id)
1907b5038d7SDag-Erling Smørgrav 		return NULL;
1917b5038d7SDag-Erling Smørgrav 
1927b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(fp, "GostAsn1", ": ", token, "\n",
1937b5038d7SDag-Erling Smørgrav 		sizeof(token), line_nr) == -1)
1947b5038d7SDag-Erling Smørgrav 		return NULL;
1957b5038d7SDag-Erling Smørgrav 	while(strlen(token) < 96) {
1967b5038d7SDag-Erling Smørgrav 		/* read more b64 from the file, b64 split on multiple lines */
1977b5038d7SDag-Erling Smørgrav 		if(ldns_fget_token_l(fp, token+strlen(token), "\n",
1987b5038d7SDag-Erling Smørgrav 			sizeof(token)-strlen(token), line_nr) == -1)
1997b5038d7SDag-Erling Smørgrav 			return NULL;
2007b5038d7SDag-Erling Smørgrav 	}
2017b5038d7SDag-Erling Smørgrav 	if(ldns_str2rdf_b64(&b64rdf, token) != LDNS_STATUS_OK)
2027b5038d7SDag-Erling Smørgrav 		return NULL;
2037b5038d7SDag-Erling Smørgrav 	pp = (unsigned char*)ldns_rdf_data(b64rdf);
2047b5038d7SDag-Erling Smørgrav 	pkey = d2i_PrivateKey(gost_id, NULL, &pp, (int)ldns_rdf_size(b64rdf));
2057b5038d7SDag-Erling Smørgrav 	ldns_rdf_deep_free(b64rdf);
2067b5038d7SDag-Erling Smørgrav 	return pkey;
2077b5038d7SDag-Erling Smørgrav }
2087b5038d7SDag-Erling Smørgrav #endif
2097b5038d7SDag-Erling Smørgrav 
2107b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA
2117b5038d7SDag-Erling Smørgrav /** calculate public key from private key */
2127b5038d7SDag-Erling Smørgrav static int
2137b5038d7SDag-Erling Smørgrav ldns_EC_KEY_calc_public(EC_KEY* ec)
2147b5038d7SDag-Erling Smørgrav {
2157b5038d7SDag-Erling Smørgrav         EC_POINT* pub_key;
2167b5038d7SDag-Erling Smørgrav         const EC_GROUP* group;
2177b5038d7SDag-Erling Smørgrav         group = EC_KEY_get0_group(ec);
2187b5038d7SDag-Erling Smørgrav         pub_key = EC_POINT_new(group);
2197b5038d7SDag-Erling Smørgrav         if(!pub_key) return 0;
2207b5038d7SDag-Erling Smørgrav         if(!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) {
2217b5038d7SDag-Erling Smørgrav                 EC_POINT_free(pub_key);
2227b5038d7SDag-Erling Smørgrav                 return 0;
2237b5038d7SDag-Erling Smørgrav         }
2247b5038d7SDag-Erling Smørgrav         if(!EC_POINT_mul(group, pub_key, EC_KEY_get0_private_key(ec),
2257b5038d7SDag-Erling Smørgrav                 NULL, NULL, NULL)) {
2267b5038d7SDag-Erling Smørgrav                 EC_POINT_free(pub_key);
2277b5038d7SDag-Erling Smørgrav                 return 0;
2287b5038d7SDag-Erling Smørgrav         }
2297b5038d7SDag-Erling Smørgrav         if(EC_KEY_set_public_key(ec, pub_key) == 0) {
2307b5038d7SDag-Erling Smørgrav                 EC_POINT_free(pub_key);
2317b5038d7SDag-Erling Smørgrav                 return 0;
2327b5038d7SDag-Erling Smørgrav         }
2337b5038d7SDag-Erling Smørgrav         EC_POINT_free(pub_key);
2347b5038d7SDag-Erling Smørgrav         return 1;
2357b5038d7SDag-Erling Smørgrav }
2367b5038d7SDag-Erling Smørgrav 
2377b5038d7SDag-Erling Smørgrav /** read ECDSA private key */
2387b5038d7SDag-Erling Smørgrav static EVP_PKEY*
2397b5038d7SDag-Erling Smørgrav ldns_key_new_frm_fp_ecdsa_l(FILE* fp, ldns_algorithm alg, int* line_nr)
2407b5038d7SDag-Erling Smørgrav {
2417b5038d7SDag-Erling Smørgrav 	char token[16384];
2427b5038d7SDag-Erling Smørgrav         ldns_rdf* b64rdf = NULL;
2437b5038d7SDag-Erling Smørgrav         unsigned char* pp;
2447b5038d7SDag-Erling Smørgrav         BIGNUM* bn;
2457b5038d7SDag-Erling Smørgrav         EVP_PKEY* evp_key;
2467b5038d7SDag-Erling Smørgrav         EC_KEY* ec;
2477b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(fp, "PrivateKey", ": ", token, "\n",
2487b5038d7SDag-Erling Smørgrav 		sizeof(token), line_nr) == -1)
2497b5038d7SDag-Erling Smørgrav 		return NULL;
2507b5038d7SDag-Erling Smørgrav 	if(ldns_str2rdf_b64(&b64rdf, token) != LDNS_STATUS_OK)
2517b5038d7SDag-Erling Smørgrav 		return NULL;
2527b5038d7SDag-Erling Smørgrav         pp = (unsigned char*)ldns_rdf_data(b64rdf);
2537b5038d7SDag-Erling Smørgrav 
2547b5038d7SDag-Erling Smørgrav         if(alg == LDNS_ECDSAP256SHA256)
2557b5038d7SDag-Erling Smørgrav                 ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
2567b5038d7SDag-Erling Smørgrav         else if(alg == LDNS_ECDSAP384SHA384)
2577b5038d7SDag-Erling Smørgrav                 ec = EC_KEY_new_by_curve_name(NID_secp384r1);
2587b5038d7SDag-Erling Smørgrav         else    ec = NULL;
2597b5038d7SDag-Erling Smørgrav         if(!ec) {
2607b5038d7SDag-Erling Smørgrav 	        ldns_rdf_deep_free(b64rdf);
2617b5038d7SDag-Erling Smørgrav                 return NULL;
2627b5038d7SDag-Erling Smørgrav         }
2637b5038d7SDag-Erling Smørgrav 	bn = BN_bin2bn(pp, (int)ldns_rdf_size(b64rdf), NULL);
2647b5038d7SDag-Erling Smørgrav 	ldns_rdf_deep_free(b64rdf);
2657b5038d7SDag-Erling Smørgrav         if(!bn) {
2667b5038d7SDag-Erling Smørgrav                 EC_KEY_free(ec);
2677b5038d7SDag-Erling Smørgrav                 return NULL;
2687b5038d7SDag-Erling Smørgrav         }
2697b5038d7SDag-Erling Smørgrav         EC_KEY_set_private_key(ec, bn);
2707b5038d7SDag-Erling Smørgrav         BN_free(bn);
2717b5038d7SDag-Erling Smørgrav         if(!ldns_EC_KEY_calc_public(ec)) {
2727b5038d7SDag-Erling Smørgrav                 EC_KEY_free(ec);
2737b5038d7SDag-Erling Smørgrav                 return NULL;
2747b5038d7SDag-Erling Smørgrav         }
2757b5038d7SDag-Erling Smørgrav 
2767b5038d7SDag-Erling Smørgrav         evp_key = EVP_PKEY_new();
2777b5038d7SDag-Erling Smørgrav         if(!evp_key) {
2787b5038d7SDag-Erling Smørgrav                 EC_KEY_free(ec);
2797b5038d7SDag-Erling Smørgrav                 return NULL;
2807b5038d7SDag-Erling Smørgrav         }
2817b5038d7SDag-Erling Smørgrav         if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
2827b5038d7SDag-Erling Smørgrav 		EVP_PKEY_free(evp_key);
2837b5038d7SDag-Erling Smørgrav                 EC_KEY_free(ec);
2847b5038d7SDag-Erling Smørgrav                 return NULL;
2857b5038d7SDag-Erling Smørgrav 	}
2867b5038d7SDag-Erling Smørgrav         return evp_key;
2877b5038d7SDag-Erling Smørgrav }
2887b5038d7SDag-Erling Smørgrav #endif
2897b5038d7SDag-Erling Smørgrav 
2907b5038d7SDag-Erling Smørgrav ldns_status
2917b5038d7SDag-Erling Smørgrav ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
2927b5038d7SDag-Erling Smørgrav {
2937b5038d7SDag-Erling Smørgrav 	ldns_key *k;
2947b5038d7SDag-Erling Smørgrav 	char *d;
2957b5038d7SDag-Erling Smørgrav 	ldns_signing_algorithm alg;
2967b5038d7SDag-Erling Smørgrav 	ldns_rr *key_rr;
2977b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
2987b5038d7SDag-Erling Smørgrav 	RSA *rsa;
2997b5038d7SDag-Erling Smørgrav 	DSA *dsa;
3007b5038d7SDag-Erling Smørgrav 	unsigned char *hmac;
3017b5038d7SDag-Erling Smørgrav 	size_t hmac_size;
3027b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
3037b5038d7SDag-Erling Smørgrav 
3047b5038d7SDag-Erling Smørgrav 	k = ldns_key_new();
3057b5038d7SDag-Erling Smørgrav 
3067b5038d7SDag-Erling Smørgrav 	d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
3077b5038d7SDag-Erling Smørgrav 	if (!k || !d) {
3087b5038d7SDag-Erling Smørgrav                 ldns_key_free(k);
3097b5038d7SDag-Erling Smørgrav                 LDNS_FREE(d);
3107b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_MEM_ERR;
3117b5038d7SDag-Erling Smørgrav 	}
3127b5038d7SDag-Erling Smørgrav 
3137b5038d7SDag-Erling Smørgrav 	alg = 0;
3147b5038d7SDag-Erling Smørgrav 
3157b5038d7SDag-Erling Smørgrav 	/* the file is highly structured. Do this in sequence */
3167b5038d7SDag-Erling Smørgrav 	/* RSA:
3177b5038d7SDag-Erling Smørgrav 	 * Private-key-format: v1.x.
3187b5038d7SDag-Erling Smørgrav  	 * Algorithm: 1 (RSA)
3197b5038d7SDag-Erling Smørgrav 
3207b5038d7SDag-Erling Smørgrav 	 */
3217b5038d7SDag-Erling Smørgrav 	/* get the key format version number */
3227b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(fp, "Private-key-format", ": ", d, "\n",
3237b5038d7SDag-Erling Smørgrav 				LDNS_MAX_LINELEN, line_nr) == -1) {
3247b5038d7SDag-Erling Smørgrav 		/* no version information */
3257b5038d7SDag-Erling Smørgrav                 ldns_key_free(k);
3267b5038d7SDag-Erling Smørgrav                 LDNS_FREE(d);
3277b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_SYNTAX_ERR;
3287b5038d7SDag-Erling Smørgrav 	}
3297b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "v1.", 3) != 0) {
3307b5038d7SDag-Erling Smørgrav                 ldns_key_free(k);
3317b5038d7SDag-Erling Smørgrav                 LDNS_FREE(d);
3327b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_SYNTAX_VERSION_ERR;
3337b5038d7SDag-Erling Smørgrav 	}
3347b5038d7SDag-Erling Smørgrav 
3357b5038d7SDag-Erling Smørgrav 	/* get the algorithm type, our file function strip ( ) so there are
3367b5038d7SDag-Erling Smørgrav 	 * not in the return string! */
3377b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(fp, "Algorithm", ": ", d, "\n",
3387b5038d7SDag-Erling Smørgrav 				LDNS_MAX_LINELEN, line_nr) == -1) {
3397b5038d7SDag-Erling Smørgrav 		/* no alg information */
3407b5038d7SDag-Erling Smørgrav                 ldns_key_free(k);
3417b5038d7SDag-Erling Smørgrav                 LDNS_FREE(d);
3427b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_SYNTAX_ALG_ERR;
3437b5038d7SDag-Erling Smørgrav 	}
3447b5038d7SDag-Erling Smørgrav 
3457b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "1 RSA", 2) == 0) {
3467b5038d7SDag-Erling Smørgrav 		alg = LDNS_SIGN_RSAMD5;
3477b5038d7SDag-Erling Smørgrav 	}
3487b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "2 DH", 2) == 0) {
3497b5038d7SDag-Erling Smørgrav 		alg = (ldns_signing_algorithm)LDNS_DH;
3507b5038d7SDag-Erling Smørgrav 	}
3517b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "3 DSA", 2) == 0) {
3527b5038d7SDag-Erling Smørgrav 		alg = LDNS_SIGN_DSA;
3537b5038d7SDag-Erling Smørgrav 	}
3547b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "4 ECC", 2) == 0) {
3557b5038d7SDag-Erling Smørgrav 		alg = (ldns_signing_algorithm)LDNS_ECC;
3567b5038d7SDag-Erling Smørgrav 	}
3577b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "5 RSASHA1", 2) == 0) {
3587b5038d7SDag-Erling Smørgrav 		alg = LDNS_SIGN_RSASHA1;
3597b5038d7SDag-Erling Smørgrav 	}
3607b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "6 DSA", 2) == 0) {
3617b5038d7SDag-Erling Smørgrav 		alg = LDNS_SIGN_DSA_NSEC3;
3627b5038d7SDag-Erling Smørgrav 	}
3637b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "7 RSASHA1", 2) == 0) {
3647b5038d7SDag-Erling Smørgrav 		alg = LDNS_SIGN_RSASHA1_NSEC3;
3657b5038d7SDag-Erling Smørgrav 	}
3667b5038d7SDag-Erling Smørgrav 
3677b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "8 RSASHA256", 2) == 0) {
3687b5038d7SDag-Erling Smørgrav #ifdef USE_SHA2
3697b5038d7SDag-Erling Smørgrav 		alg = LDNS_SIGN_RSASHA256;
3707b5038d7SDag-Erling Smørgrav #else
371*17d15b25SDag-Erling Smørgrav # ifdef STDERR_MSGS
3727b5038d7SDag-Erling Smørgrav 		fprintf(stderr, "Warning: SHA256 not compiled into this ");
3737b5038d7SDag-Erling Smørgrav 		fprintf(stderr, "version of ldns\n");
3747b5038d7SDag-Erling Smørgrav # endif
375*17d15b25SDag-Erling Smørgrav #endif
3767b5038d7SDag-Erling Smørgrav 	}
3777b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "10 RSASHA512", 3) == 0) {
3787b5038d7SDag-Erling Smørgrav #ifdef USE_SHA2
3797b5038d7SDag-Erling Smørgrav 		alg = LDNS_SIGN_RSASHA512;
3807b5038d7SDag-Erling Smørgrav #else
381*17d15b25SDag-Erling Smørgrav # ifdef STDERR_MSGS
3827b5038d7SDag-Erling Smørgrav 		fprintf(stderr, "Warning: SHA512 not compiled into this ");
3837b5038d7SDag-Erling Smørgrav 		fprintf(stderr, "version of ldns\n");
3847b5038d7SDag-Erling Smørgrav # endif
385*17d15b25SDag-Erling Smørgrav #endif
3867b5038d7SDag-Erling Smørgrav 	}
3877b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "12 ECC-GOST", 3) == 0) {
3887b5038d7SDag-Erling Smørgrav #ifdef USE_GOST
3897b5038d7SDag-Erling Smørgrav 		alg = LDNS_SIGN_ECC_GOST;
3907b5038d7SDag-Erling Smørgrav #else
391*17d15b25SDag-Erling Smørgrav # ifdef STDERR_MSGS
3927b5038d7SDag-Erling Smørgrav 		fprintf(stderr, "Warning: ECC-GOST not compiled into this ");
3937b5038d7SDag-Erling Smørgrav 		fprintf(stderr, "version of ldns, use --enable-gost\n");
3947b5038d7SDag-Erling Smørgrav # endif
395*17d15b25SDag-Erling Smørgrav #endif
3967b5038d7SDag-Erling Smørgrav 	}
3977b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "13 ECDSAP256SHA256", 3) == 0) {
3987b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA
3997b5038d7SDag-Erling Smørgrav                 alg = LDNS_SIGN_ECDSAP256SHA256;
4007b5038d7SDag-Erling Smørgrav #else
401*17d15b25SDag-Erling Smørgrav # ifdef STDERR_MSGS
4027b5038d7SDag-Erling Smørgrav 		fprintf(stderr, "Warning: ECDSA not compiled into this ");
4037b5038d7SDag-Erling Smørgrav 		fprintf(stderr, "version of ldns, use --enable-ecdsa\n");
4047b5038d7SDag-Erling Smørgrav # endif
405*17d15b25SDag-Erling Smørgrav #endif
4067b5038d7SDag-Erling Smørgrav         }
4077b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "14 ECDSAP384SHA384", 3) == 0) {
4087b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA
4097b5038d7SDag-Erling Smørgrav                 alg = LDNS_SIGN_ECDSAP384SHA384;
4107b5038d7SDag-Erling Smørgrav #else
411*17d15b25SDag-Erling Smørgrav # ifdef STDERR_MSGS
4127b5038d7SDag-Erling Smørgrav 		fprintf(stderr, "Warning: ECDSA not compiled into this ");
4137b5038d7SDag-Erling Smørgrav 		fprintf(stderr, "version of ldns, use --enable-ecdsa\n");
4147b5038d7SDag-Erling Smørgrav # endif
415*17d15b25SDag-Erling Smørgrav #endif
4167b5038d7SDag-Erling Smørgrav         }
4177b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "157 HMAC-MD5", 4) == 0) {
4187b5038d7SDag-Erling Smørgrav 		alg = LDNS_SIGN_HMACMD5;
4197b5038d7SDag-Erling Smørgrav 	}
4207b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "158 HMAC-SHA1", 4) == 0) {
4217b5038d7SDag-Erling Smørgrav 		alg = LDNS_SIGN_HMACSHA1;
4227b5038d7SDag-Erling Smørgrav 	}
4237b5038d7SDag-Erling Smørgrav 	if (strncmp(d, "159 HMAC-SHA256", 4) == 0) {
4247b5038d7SDag-Erling Smørgrav 		alg = LDNS_SIGN_HMACSHA256;
4257b5038d7SDag-Erling Smørgrav 	}
4267b5038d7SDag-Erling Smørgrav 
4277b5038d7SDag-Erling Smørgrav 	LDNS_FREE(d);
4287b5038d7SDag-Erling Smørgrav 
4297b5038d7SDag-Erling Smørgrav 	switch(alg) {
4307b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSAMD5:
4317b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSASHA1:
4327b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSASHA1_NSEC3:
4337b5038d7SDag-Erling Smørgrav #ifdef USE_SHA2
4347b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSASHA256:
4357b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSASHA512:
4367b5038d7SDag-Erling Smørgrav #endif
4377b5038d7SDag-Erling Smørgrav 			ldns_key_set_algorithm(k, alg);
4387b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
4397b5038d7SDag-Erling Smørgrav 			rsa = ldns_key_new_frm_fp_rsa_l(fp, line_nr);
4407b5038d7SDag-Erling Smørgrav 			if (!rsa) {
4417b5038d7SDag-Erling Smørgrav 				ldns_key_free(k);
4427b5038d7SDag-Erling Smørgrav 				return LDNS_STATUS_ERR;
4437b5038d7SDag-Erling Smørgrav 			}
4442787e39aSDag-Erling Smørgrav 			ldns_key_assign_rsa_key(k, rsa);
4457b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
4467b5038d7SDag-Erling Smørgrav 			break;
4477b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_DSA:
4487b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_DSA_NSEC3:
4497b5038d7SDag-Erling Smørgrav 			ldns_key_set_algorithm(k, alg);
4507b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
4517b5038d7SDag-Erling Smørgrav 			dsa = ldns_key_new_frm_fp_dsa_l(fp, line_nr);
4527b5038d7SDag-Erling Smørgrav 			if (!dsa) {
4537b5038d7SDag-Erling Smørgrav 				ldns_key_free(k);
4547b5038d7SDag-Erling Smørgrav 				return LDNS_STATUS_ERR;
4557b5038d7SDag-Erling Smørgrav 			}
4562787e39aSDag-Erling Smørgrav 			ldns_key_assign_dsa_key(k, dsa);
4577b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
4587b5038d7SDag-Erling Smørgrav 			break;
4597b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_HMACMD5:
4607b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_HMACSHA1:
4617b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_HMACSHA256:
4627b5038d7SDag-Erling Smørgrav 			ldns_key_set_algorithm(k, alg);
4637b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
4647b5038d7SDag-Erling Smørgrav 			hmac = ldns_key_new_frm_fp_hmac_l(fp, line_nr, &hmac_size);
4657b5038d7SDag-Erling Smørgrav 			if (!hmac) {
4667b5038d7SDag-Erling Smørgrav 				ldns_key_free(k);
4677b5038d7SDag-Erling Smørgrav 				return LDNS_STATUS_ERR;
4687b5038d7SDag-Erling Smørgrav 			}
4697b5038d7SDag-Erling Smørgrav 			ldns_key_set_hmac_size(k, hmac_size);
4707b5038d7SDag-Erling Smørgrav 			ldns_key_set_hmac_key(k, hmac);
4717b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
4727b5038d7SDag-Erling Smørgrav 			break;
4737b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_ECC_GOST:
4747b5038d7SDag-Erling Smørgrav 			ldns_key_set_algorithm(k, alg);
4757b5038d7SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(USE_GOST)
4767b5038d7SDag-Erling Smørgrav                         if(!ldns_key_EVP_load_gost_id()) {
4777b5038d7SDag-Erling Smørgrav 				ldns_key_free(k);
4787b5038d7SDag-Erling Smørgrav                                 return LDNS_STATUS_CRYPTO_ALGO_NOT_IMPL;
4797b5038d7SDag-Erling Smørgrav                         }
4807b5038d7SDag-Erling Smørgrav 			ldns_key_set_evp_key(k,
4817b5038d7SDag-Erling Smørgrav 				ldns_key_new_frm_fp_gost_l(fp, line_nr));
4827b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
4837b5038d7SDag-Erling Smørgrav 			if(!k->_key.key) {
4847b5038d7SDag-Erling Smørgrav 				ldns_key_free(k);
4857b5038d7SDag-Erling Smørgrav 				return LDNS_STATUS_ERR;
4867b5038d7SDag-Erling Smørgrav 			}
4877b5038d7SDag-Erling Smørgrav #endif /* splint */
4887b5038d7SDag-Erling Smørgrav #endif
4897b5038d7SDag-Erling Smørgrav 			break;
4907b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA
4917b5038d7SDag-Erling Smørgrav                case LDNS_SIGN_ECDSAP256SHA256:
4927b5038d7SDag-Erling Smørgrav                case LDNS_SIGN_ECDSAP384SHA384:
4937b5038d7SDag-Erling Smørgrav                         ldns_key_set_algorithm(k, alg);
4947b5038d7SDag-Erling Smørgrav                         ldns_key_set_evp_key(k,
4957b5038d7SDag-Erling Smørgrav                                 ldns_key_new_frm_fp_ecdsa_l(fp, (ldns_algorithm)alg, line_nr));
4967b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
4977b5038d7SDag-Erling Smørgrav 			if(!k->_key.key) {
4987b5038d7SDag-Erling Smørgrav 				ldns_key_free(k);
4997b5038d7SDag-Erling Smørgrav 				return LDNS_STATUS_ERR;
5007b5038d7SDag-Erling Smørgrav 			}
5017b5038d7SDag-Erling Smørgrav #endif /* splint */
5027b5038d7SDag-Erling Smørgrav 			break;
5037b5038d7SDag-Erling Smørgrav #endif
5047b5038d7SDag-Erling Smørgrav 		default:
5057b5038d7SDag-Erling Smørgrav 			ldns_key_free(k);
5067b5038d7SDag-Erling Smørgrav 			return LDNS_STATUS_SYNTAX_ALG_ERR;
5077b5038d7SDag-Erling Smørgrav 	}
5087b5038d7SDag-Erling Smørgrav 	key_rr = ldns_key2rr(k);
5097b5038d7SDag-Erling Smørgrav 	ldns_key_set_keytag(k, ldns_calc_keytag(key_rr));
5107b5038d7SDag-Erling Smørgrav 	ldns_rr_free(key_rr);
5117b5038d7SDag-Erling Smørgrav 
5127b5038d7SDag-Erling Smørgrav 	if (key) {
5137b5038d7SDag-Erling Smørgrav 		*key = k;
5147b5038d7SDag-Erling Smørgrav 		return LDNS_STATUS_OK;
5157b5038d7SDag-Erling Smørgrav 	}
5162787e39aSDag-Erling Smørgrav 	ldns_key_free(k);
5177b5038d7SDag-Erling Smørgrav 	return LDNS_STATUS_ERR;
5187b5038d7SDag-Erling Smørgrav }
5197b5038d7SDag-Erling Smørgrav 
5207b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
5217b5038d7SDag-Erling Smørgrav RSA *
5227b5038d7SDag-Erling Smørgrav ldns_key_new_frm_fp_rsa(FILE *f)
5237b5038d7SDag-Erling Smørgrav {
5247b5038d7SDag-Erling Smørgrav 	return ldns_key_new_frm_fp_rsa_l(f, NULL);
5257b5038d7SDag-Erling Smørgrav }
5267b5038d7SDag-Erling Smørgrav 
5277b5038d7SDag-Erling Smørgrav RSA *
5287b5038d7SDag-Erling Smørgrav ldns_key_new_frm_fp_rsa_l(FILE *f, int *line_nr)
5297b5038d7SDag-Erling Smørgrav {
5307b5038d7SDag-Erling Smørgrav 	/* we parse
5317b5038d7SDag-Erling Smørgrav  	 * Modulus:
5327b5038d7SDag-Erling Smørgrav  	 * PublicExponent:
5337b5038d7SDag-Erling Smørgrav  	 * PrivateExponent:
5347b5038d7SDag-Erling Smørgrav  	 * Prime1:
5357b5038d7SDag-Erling Smørgrav  	 * Prime2:
5367b5038d7SDag-Erling Smørgrav  	 * Exponent1:
5377b5038d7SDag-Erling Smørgrav  	 * Exponent2:
5387b5038d7SDag-Erling Smørgrav  	 * Coefficient:
5397b5038d7SDag-Erling Smørgrav 	 *
5407b5038d7SDag-Erling Smørgrav 	 * man 3 RSA:
5417b5038d7SDag-Erling Smørgrav 	 *
5427b5038d7SDag-Erling Smørgrav 	 * struct
5437b5038d7SDag-Erling Smørgrav          *     {
5447b5038d7SDag-Erling Smørgrav          *     BIGNUM *n;              // public modulus
5457b5038d7SDag-Erling Smørgrav          *     BIGNUM *e;              // public exponent
5467b5038d7SDag-Erling Smørgrav          *     BIGNUM *d;              // private exponent
5477b5038d7SDag-Erling Smørgrav          *     BIGNUM *p;              // secret prime factor
5487b5038d7SDag-Erling Smørgrav          *     BIGNUM *q;              // secret prime factor
5497b5038d7SDag-Erling Smørgrav          *     BIGNUM *dmp1;           // d mod (p-1)
5507b5038d7SDag-Erling Smørgrav          *     BIGNUM *dmq1;           // d mod (q-1)
5517b5038d7SDag-Erling Smørgrav          *     BIGNUM *iqmp;           // q^-1 mod p
5527b5038d7SDag-Erling Smørgrav          *     // ...
5537b5038d7SDag-Erling Smørgrav 	 *
5547b5038d7SDag-Erling Smørgrav 	 */
5557b5038d7SDag-Erling Smørgrav 	char *d;
5567b5038d7SDag-Erling Smørgrav 	RSA *rsa;
5577b5038d7SDag-Erling Smørgrav 	uint8_t *buf;
5587b5038d7SDag-Erling Smørgrav 	int i;
5597b5038d7SDag-Erling Smørgrav 
5607b5038d7SDag-Erling Smørgrav 	d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
5617b5038d7SDag-Erling Smørgrav 	buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN);
5627b5038d7SDag-Erling Smørgrav 	rsa = RSA_new();
5637b5038d7SDag-Erling Smørgrav 	if (!d || !rsa || !buf) {
5647b5038d7SDag-Erling Smørgrav                 goto error;
5657b5038d7SDag-Erling Smørgrav 	}
5667b5038d7SDag-Erling Smørgrav 
5677b5038d7SDag-Erling Smørgrav 	/* I could use functions again, but that seems an overkill,
5687b5038d7SDag-Erling Smørgrav 	 * allthough this also looks tedious
5697b5038d7SDag-Erling Smørgrav 	 */
5707b5038d7SDag-Erling Smørgrav 
5717b5038d7SDag-Erling Smørgrav 	/* Modules, rsa->n */
5727b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(f, "Modulus", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
5737b5038d7SDag-Erling Smørgrav 		goto error;
5747b5038d7SDag-Erling Smørgrav 	}
5757b5038d7SDag-Erling Smørgrav 	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
5767b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
5777b5038d7SDag-Erling Smørgrav 	rsa->n = BN_bin2bn((const char unsigned*)buf, i, NULL);
5787b5038d7SDag-Erling Smørgrav 	if (!rsa->n) {
5797b5038d7SDag-Erling Smørgrav 		goto error;
5807b5038d7SDag-Erling Smørgrav 	}
5817b5038d7SDag-Erling Smørgrav 
5827b5038d7SDag-Erling Smørgrav 	/* PublicExponent, rsa->e */
5837b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(f, "PublicExponent", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
5847b5038d7SDag-Erling Smørgrav 		goto error;
5857b5038d7SDag-Erling Smørgrav 	}
5867b5038d7SDag-Erling Smørgrav 	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
5877b5038d7SDag-Erling Smørgrav 	rsa->e = BN_bin2bn((const char unsigned*)buf, i, NULL);
5887b5038d7SDag-Erling Smørgrav 	if (!rsa->e) {
5897b5038d7SDag-Erling Smørgrav 		goto error;
5907b5038d7SDag-Erling Smørgrav 	}
5917b5038d7SDag-Erling Smørgrav 
5927b5038d7SDag-Erling Smørgrav 	/* PrivateExponent, rsa->d */
5937b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(f, "PrivateExponent", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
5947b5038d7SDag-Erling Smørgrav 		goto error;
5957b5038d7SDag-Erling Smørgrav 	}
5967b5038d7SDag-Erling Smørgrav 	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
5977b5038d7SDag-Erling Smørgrav 	rsa->d = BN_bin2bn((const char unsigned*)buf, i, NULL);
5987b5038d7SDag-Erling Smørgrav 	if (!rsa->d) {
5997b5038d7SDag-Erling Smørgrav 		goto error;
6007b5038d7SDag-Erling Smørgrav 	}
6017b5038d7SDag-Erling Smørgrav 
6027b5038d7SDag-Erling Smørgrav 	/* Prime1, rsa->p */
6037b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(f, "Prime1", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
6047b5038d7SDag-Erling Smørgrav 		goto error;
6057b5038d7SDag-Erling Smørgrav 	}
6067b5038d7SDag-Erling Smørgrav 	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
6077b5038d7SDag-Erling Smørgrav 	rsa->p = BN_bin2bn((const char unsigned*)buf, i, NULL);
6087b5038d7SDag-Erling Smørgrav 	if (!rsa->p) {
6097b5038d7SDag-Erling Smørgrav 		goto error;
6107b5038d7SDag-Erling Smørgrav 	}
6117b5038d7SDag-Erling Smørgrav 
6127b5038d7SDag-Erling Smørgrav 	/* Prime2, rsa->q */
6137b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(f, "Prime2", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
6147b5038d7SDag-Erling Smørgrav 		goto error;
6157b5038d7SDag-Erling Smørgrav 	}
6167b5038d7SDag-Erling Smørgrav 	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
6177b5038d7SDag-Erling Smørgrav 	rsa->q = BN_bin2bn((const char unsigned*)buf, i, NULL);
6187b5038d7SDag-Erling Smørgrav 	if (!rsa->q) {
6197b5038d7SDag-Erling Smørgrav 		goto error;
6207b5038d7SDag-Erling Smørgrav 	}
6217b5038d7SDag-Erling Smørgrav 
6227b5038d7SDag-Erling Smørgrav 	/* Exponent1, rsa->dmp1 */
6237b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(f, "Exponent1", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
6247b5038d7SDag-Erling Smørgrav 		goto error;
6257b5038d7SDag-Erling Smørgrav 	}
6267b5038d7SDag-Erling Smørgrav 	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
6277b5038d7SDag-Erling Smørgrav 	rsa->dmp1 = BN_bin2bn((const char unsigned*)buf, i, NULL);
6287b5038d7SDag-Erling Smørgrav 	if (!rsa->dmp1) {
6297b5038d7SDag-Erling Smørgrav 		goto error;
6307b5038d7SDag-Erling Smørgrav 	}
6317b5038d7SDag-Erling Smørgrav 
6327b5038d7SDag-Erling Smørgrav 	/* Exponent2, rsa->dmq1 */
6337b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(f, "Exponent2", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
6347b5038d7SDag-Erling Smørgrav 		goto error;
6357b5038d7SDag-Erling Smørgrav 	}
6367b5038d7SDag-Erling Smørgrav 	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
6377b5038d7SDag-Erling Smørgrav 	rsa->dmq1 = BN_bin2bn((const char unsigned*)buf, i, NULL);
6387b5038d7SDag-Erling Smørgrav 	if (!rsa->dmq1) {
6397b5038d7SDag-Erling Smørgrav 		goto error;
6407b5038d7SDag-Erling Smørgrav 	}
6417b5038d7SDag-Erling Smørgrav 
6427b5038d7SDag-Erling Smørgrav 	/* Coefficient, rsa->iqmp */
6437b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(f, "Coefficient", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
6447b5038d7SDag-Erling Smørgrav 		goto error;
6457b5038d7SDag-Erling Smørgrav 	}
6467b5038d7SDag-Erling Smørgrav 	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
6477b5038d7SDag-Erling Smørgrav 	rsa->iqmp = BN_bin2bn((const char unsigned*)buf, i, NULL);
6487b5038d7SDag-Erling Smørgrav 	if (!rsa->iqmp) {
6497b5038d7SDag-Erling Smørgrav 		goto error;
6507b5038d7SDag-Erling Smørgrav 	}
6517b5038d7SDag-Erling Smørgrav #endif /* splint */
6527b5038d7SDag-Erling Smørgrav 
6537b5038d7SDag-Erling Smørgrav 	LDNS_FREE(buf);
6547b5038d7SDag-Erling Smørgrav 	LDNS_FREE(d);
6557b5038d7SDag-Erling Smørgrav 	return rsa;
6567b5038d7SDag-Erling Smørgrav 
6577b5038d7SDag-Erling Smørgrav error:
6587b5038d7SDag-Erling Smørgrav 	RSA_free(rsa);
6597b5038d7SDag-Erling Smørgrav 	LDNS_FREE(d);
6607b5038d7SDag-Erling Smørgrav 	LDNS_FREE(buf);
6617b5038d7SDag-Erling Smørgrav 	return NULL;
6627b5038d7SDag-Erling Smørgrav }
6637b5038d7SDag-Erling Smørgrav 
6647b5038d7SDag-Erling Smørgrav DSA *
6657b5038d7SDag-Erling Smørgrav ldns_key_new_frm_fp_dsa(FILE *f)
6667b5038d7SDag-Erling Smørgrav {
6677b5038d7SDag-Erling Smørgrav 	return ldns_key_new_frm_fp_dsa_l(f, NULL);
6687b5038d7SDag-Erling Smørgrav }
6697b5038d7SDag-Erling Smørgrav 
6707b5038d7SDag-Erling Smørgrav DSA *
6717b5038d7SDag-Erling Smørgrav ldns_key_new_frm_fp_dsa_l(FILE *f, ATTR_UNUSED(int *line_nr))
6727b5038d7SDag-Erling Smørgrav {
6737b5038d7SDag-Erling Smørgrav 	int i;
6747b5038d7SDag-Erling Smørgrav 	char *d;
6757b5038d7SDag-Erling Smørgrav 	DSA *dsa;
6767b5038d7SDag-Erling Smørgrav 	uint8_t *buf;
6777b5038d7SDag-Erling Smørgrav 
6787b5038d7SDag-Erling Smørgrav 	d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
6797b5038d7SDag-Erling Smørgrav 	buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN);
6807b5038d7SDag-Erling Smørgrav 	dsa = DSA_new();
6817b5038d7SDag-Erling Smørgrav 	if (!d || !dsa || !buf) {
6827b5038d7SDag-Erling Smørgrav                 goto error;
6837b5038d7SDag-Erling Smørgrav 	}
6847b5038d7SDag-Erling Smørgrav 
6857b5038d7SDag-Erling Smørgrav 	/* the line parser removes the () from the input... */
6867b5038d7SDag-Erling Smørgrav 
6877b5038d7SDag-Erling Smørgrav 	/* Prime, dsa->p */
6887b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(f, "Primep", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
6897b5038d7SDag-Erling Smørgrav 		goto error;
6907b5038d7SDag-Erling Smørgrav 	}
6917b5038d7SDag-Erling Smørgrav 	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
6927b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
6937b5038d7SDag-Erling Smørgrav 	dsa->p = BN_bin2bn((const char unsigned*)buf, i, NULL);
6947b5038d7SDag-Erling Smørgrav 	if (!dsa->p) {
6957b5038d7SDag-Erling Smørgrav 		goto error;
6967b5038d7SDag-Erling Smørgrav 	}
6977b5038d7SDag-Erling Smørgrav 
6987b5038d7SDag-Erling Smørgrav 	/* Subprime, dsa->q */
6997b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(f, "Subprimeq", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
7007b5038d7SDag-Erling Smørgrav 		goto error;
7017b5038d7SDag-Erling Smørgrav 	}
7027b5038d7SDag-Erling Smørgrav 	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
7037b5038d7SDag-Erling Smørgrav 	dsa->q = BN_bin2bn((const char unsigned*)buf, i, NULL);
7047b5038d7SDag-Erling Smørgrav 	if (!dsa->q) {
7057b5038d7SDag-Erling Smørgrav 		goto error;
7067b5038d7SDag-Erling Smørgrav 	}
7077b5038d7SDag-Erling Smørgrav 
7087b5038d7SDag-Erling Smørgrav 	/* Base, dsa->g */
7097b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(f, "Baseg", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
7107b5038d7SDag-Erling Smørgrav 		goto error;
7117b5038d7SDag-Erling Smørgrav 	}
7127b5038d7SDag-Erling Smørgrav 	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
7137b5038d7SDag-Erling Smørgrav 	dsa->g = BN_bin2bn((const char unsigned*)buf, i, NULL);
7147b5038d7SDag-Erling Smørgrav 	if (!dsa->g) {
7157b5038d7SDag-Erling Smørgrav 		goto error;
7167b5038d7SDag-Erling Smørgrav 	}
7177b5038d7SDag-Erling Smørgrav 
7187b5038d7SDag-Erling Smørgrav 	/* Private key, dsa->priv_key */
7197b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(f, "Private_valuex", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
7207b5038d7SDag-Erling Smørgrav 		goto error;
7217b5038d7SDag-Erling Smørgrav 	}
7227b5038d7SDag-Erling Smørgrav 	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
7237b5038d7SDag-Erling Smørgrav 	dsa->priv_key = BN_bin2bn((const char unsigned*)buf, i, NULL);
7247b5038d7SDag-Erling Smørgrav 	if (!dsa->priv_key) {
7257b5038d7SDag-Erling Smørgrav 		goto error;
7267b5038d7SDag-Erling Smørgrav 	}
7277b5038d7SDag-Erling Smørgrav 
7287b5038d7SDag-Erling Smørgrav 	/* Public key, dsa->priv_key */
7297b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(f, "Public_valuey", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
7307b5038d7SDag-Erling Smørgrav 		goto error;
7317b5038d7SDag-Erling Smørgrav 	}
7327b5038d7SDag-Erling Smørgrav 	i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
7337b5038d7SDag-Erling Smørgrav 	dsa->pub_key = BN_bin2bn((const char unsigned*)buf, i, NULL);
7347b5038d7SDag-Erling Smørgrav 	if (!dsa->pub_key) {
7357b5038d7SDag-Erling Smørgrav 		goto error;
7367b5038d7SDag-Erling Smørgrav 	}
7377b5038d7SDag-Erling Smørgrav #endif /* splint */
7387b5038d7SDag-Erling Smørgrav 
7397b5038d7SDag-Erling Smørgrav 	LDNS_FREE(buf);
7407b5038d7SDag-Erling Smørgrav 	LDNS_FREE(d);
7417b5038d7SDag-Erling Smørgrav 
7427b5038d7SDag-Erling Smørgrav 	return dsa;
7437b5038d7SDag-Erling Smørgrav 
7447b5038d7SDag-Erling Smørgrav error:
7457b5038d7SDag-Erling Smørgrav 	LDNS_FREE(d);
7467b5038d7SDag-Erling Smørgrav 	LDNS_FREE(buf);
7477b5038d7SDag-Erling Smørgrav         DSA_free(dsa);
7487b5038d7SDag-Erling Smørgrav 	return NULL;
7497b5038d7SDag-Erling Smørgrav }
7507b5038d7SDag-Erling Smørgrav 
7517b5038d7SDag-Erling Smørgrav unsigned char *
7527b5038d7SDag-Erling Smørgrav ldns_key_new_frm_fp_hmac(FILE *f, size_t *hmac_size)
7537b5038d7SDag-Erling Smørgrav {
7547b5038d7SDag-Erling Smørgrav 	return ldns_key_new_frm_fp_hmac_l(f, NULL, hmac_size);
7557b5038d7SDag-Erling Smørgrav }
7567b5038d7SDag-Erling Smørgrav 
7577b5038d7SDag-Erling Smørgrav unsigned char *
7587b5038d7SDag-Erling Smørgrav ldns_key_new_frm_fp_hmac_l( FILE *f
7597b5038d7SDag-Erling Smørgrav 			  , ATTR_UNUSED(int *line_nr)
7607b5038d7SDag-Erling Smørgrav 			  , size_t *hmac_size
7617b5038d7SDag-Erling Smørgrav 			  )
7627b5038d7SDag-Erling Smørgrav {
7632787e39aSDag-Erling Smørgrav 	size_t i, bufsz;
7642787e39aSDag-Erling Smørgrav 	char d[LDNS_MAX_LINELEN];
7652787e39aSDag-Erling Smørgrav 	unsigned char *buf = NULL;
7667b5038d7SDag-Erling Smørgrav 
7677b5038d7SDag-Erling Smørgrav 	if (ldns_fget_keyword_data_l(f, "Key", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
7687b5038d7SDag-Erling Smørgrav 		goto error;
7697b5038d7SDag-Erling Smørgrav 	}
7702787e39aSDag-Erling Smørgrav 	bufsz = ldns_b64_ntop_calculate_size(strlen(d));
7712787e39aSDag-Erling Smørgrav 	buf = LDNS_XMALLOC(unsigned char, bufsz);
7722787e39aSDag-Erling Smørgrav 	i = (size_t) ldns_b64_pton((const char*)d, buf, bufsz);
7737b5038d7SDag-Erling Smørgrav 
7747b5038d7SDag-Erling Smørgrav 	*hmac_size = i;
7757b5038d7SDag-Erling Smørgrav 	return buf;
7767b5038d7SDag-Erling Smørgrav 
7777b5038d7SDag-Erling Smørgrav 	error:
7787b5038d7SDag-Erling Smørgrav 	LDNS_FREE(buf);
7797b5038d7SDag-Erling Smørgrav 	*hmac_size = 0;
7807b5038d7SDag-Erling Smørgrav 	return NULL;
7817b5038d7SDag-Erling Smørgrav }
7827b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
7837b5038d7SDag-Erling Smørgrav 
7847b5038d7SDag-Erling Smørgrav #ifdef USE_GOST
7857b5038d7SDag-Erling Smørgrav static EVP_PKEY*
7867b5038d7SDag-Erling Smørgrav ldns_gen_gost_key(void)
7877b5038d7SDag-Erling Smørgrav {
7887b5038d7SDag-Erling Smørgrav 	EVP_PKEY_CTX* ctx;
7897b5038d7SDag-Erling Smørgrav 	EVP_PKEY* p = NULL;
7907b5038d7SDag-Erling Smørgrav 	int gost_id = ldns_key_EVP_load_gost_id();
7917b5038d7SDag-Erling Smørgrav 	if(!gost_id)
7927b5038d7SDag-Erling Smørgrav 		return NULL;
7937b5038d7SDag-Erling Smørgrav 	ctx = EVP_PKEY_CTX_new_id(gost_id, NULL);
7947b5038d7SDag-Erling Smørgrav 	if(!ctx) {
7957b5038d7SDag-Erling Smørgrav 		/* the id should be available now */
7967b5038d7SDag-Erling Smørgrav 		return NULL;
7977b5038d7SDag-Erling Smørgrav 	}
7987b5038d7SDag-Erling Smørgrav 	if(EVP_PKEY_CTX_ctrl_str(ctx, "paramset", "A") <= 0) {
7997b5038d7SDag-Erling Smørgrav 		/* cannot set paramset */
8007b5038d7SDag-Erling Smørgrav 		EVP_PKEY_CTX_free(ctx);
8017b5038d7SDag-Erling Smørgrav 		return NULL;
8027b5038d7SDag-Erling Smørgrav 	}
8037b5038d7SDag-Erling Smørgrav 
8047b5038d7SDag-Erling Smørgrav 	if(EVP_PKEY_keygen_init(ctx) <= 0) {
8057b5038d7SDag-Erling Smørgrav 		EVP_PKEY_CTX_free(ctx);
8067b5038d7SDag-Erling Smørgrav 		return NULL;
8077b5038d7SDag-Erling Smørgrav 	}
8087b5038d7SDag-Erling Smørgrav 	if(EVP_PKEY_keygen(ctx, &p) <= 0) {
8097b5038d7SDag-Erling Smørgrav 		EVP_PKEY_free(p);
8107b5038d7SDag-Erling Smørgrav 		EVP_PKEY_CTX_free(ctx);
8117b5038d7SDag-Erling Smørgrav 		return NULL;
8127b5038d7SDag-Erling Smørgrav 	}
8137b5038d7SDag-Erling Smørgrav 	EVP_PKEY_CTX_free(ctx);
8147b5038d7SDag-Erling Smørgrav 	return p;
8157b5038d7SDag-Erling Smørgrav }
8167b5038d7SDag-Erling Smørgrav #endif
8177b5038d7SDag-Erling Smørgrav 
8187b5038d7SDag-Erling Smørgrav ldns_key *
8197b5038d7SDag-Erling Smørgrav ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
8207b5038d7SDag-Erling Smørgrav {
8217b5038d7SDag-Erling Smørgrav 	ldns_key *k;
8227b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
8237b5038d7SDag-Erling Smørgrav 	DSA *d;
8247b5038d7SDag-Erling Smørgrav 	RSA *r;
8257b5038d7SDag-Erling Smørgrav #  ifdef USE_ECDSA
8267b5038d7SDag-Erling Smørgrav         EC_KEY *ec = NULL;
8277b5038d7SDag-Erling Smørgrav #  endif
8287b5038d7SDag-Erling Smørgrav #else
8297b5038d7SDag-Erling Smørgrav 	int i;
8307b5038d7SDag-Erling Smørgrav 	uint16_t offset = 0;
8317b5038d7SDag-Erling Smørgrav #endif
8327b5038d7SDag-Erling Smørgrav 	unsigned char *hmac;
8337b5038d7SDag-Erling Smørgrav 
8347b5038d7SDag-Erling Smørgrav 	k = ldns_key_new();
8357b5038d7SDag-Erling Smørgrav 	if (!k) {
8367b5038d7SDag-Erling Smørgrav 		return NULL;
8377b5038d7SDag-Erling Smørgrav 	}
8387b5038d7SDag-Erling Smørgrav 	switch(alg) {
8397b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSAMD5:
8407b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSASHA1:
8417b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSASHA1_NSEC3:
8427b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSASHA256:
8437b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSASHA512:
8447b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
8457b5038d7SDag-Erling Smørgrav 			r = RSA_generate_key((int)size, RSA_F4, NULL, NULL);
8467b5038d7SDag-Erling Smørgrav                         if(!r) {
8477b5038d7SDag-Erling Smørgrav 				ldns_key_free(k);
8487b5038d7SDag-Erling Smørgrav 				return NULL;
8497b5038d7SDag-Erling Smørgrav 			}
8507b5038d7SDag-Erling Smørgrav 			if (RSA_check_key(r) != 1) {
8517b5038d7SDag-Erling Smørgrav 				ldns_key_free(k);
8527b5038d7SDag-Erling Smørgrav 				return NULL;
8537b5038d7SDag-Erling Smørgrav 			}
8547b5038d7SDag-Erling Smørgrav 			ldns_key_set_rsa_key(k, r);
8552787e39aSDag-Erling Smørgrav 			RSA_free(r);
8567b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
8577b5038d7SDag-Erling Smørgrav 			break;
8587b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_DSA:
8597b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_DSA_NSEC3:
8607b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
8617b5038d7SDag-Erling Smørgrav 			d = DSA_generate_parameters((int)size, NULL, 0, NULL, NULL, NULL, NULL);
8627b5038d7SDag-Erling Smørgrav 			if (!d) {
8637b5038d7SDag-Erling Smørgrav 				ldns_key_free(k);
8647b5038d7SDag-Erling Smørgrav 				return NULL;
8657b5038d7SDag-Erling Smørgrav 			}
8667b5038d7SDag-Erling Smørgrav 			if (DSA_generate_key(d) != 1) {
8677b5038d7SDag-Erling Smørgrav 				ldns_key_free(k);
8687b5038d7SDag-Erling Smørgrav 				return NULL;
8697b5038d7SDag-Erling Smørgrav 			}
8707b5038d7SDag-Erling Smørgrav 			ldns_key_set_dsa_key(k, d);
8712787e39aSDag-Erling Smørgrav 			DSA_free(d);
8727b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
8737b5038d7SDag-Erling Smørgrav 			break;
8747b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_HMACMD5:
8757b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_HMACSHA1:
8767b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_HMACSHA256:
8777b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
8787b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
8797b5038d7SDag-Erling Smørgrav 			k->_key.key = NULL;
8807b5038d7SDag-Erling Smørgrav #endif /* splint */
8817b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
8827b5038d7SDag-Erling Smørgrav 			size = size / 8;
8837b5038d7SDag-Erling Smørgrav 			ldns_key_set_hmac_size(k, size);
8847b5038d7SDag-Erling Smørgrav 
8857b5038d7SDag-Erling Smørgrav 			hmac = LDNS_XMALLOC(unsigned char, size);
8867b5038d7SDag-Erling Smørgrav                         if(!hmac) {
8877b5038d7SDag-Erling Smørgrav 				ldns_key_free(k);
8887b5038d7SDag-Erling Smørgrav 				return NULL;
8897b5038d7SDag-Erling Smørgrav                         }
8907b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
8917b5038d7SDag-Erling Smørgrav 			if (RAND_bytes(hmac, (int) size) != 1) {
8927b5038d7SDag-Erling Smørgrav 				LDNS_FREE(hmac);
8937b5038d7SDag-Erling Smørgrav 				ldns_key_free(k);
8947b5038d7SDag-Erling Smørgrav 				return NULL;
8957b5038d7SDag-Erling Smørgrav 			}
8967b5038d7SDag-Erling Smørgrav #else
8977b5038d7SDag-Erling Smørgrav 			while (offset + sizeof(i) < size) {
8987b5038d7SDag-Erling Smørgrav 			  i = random();
8997b5038d7SDag-Erling Smørgrav 			  memcpy(&hmac[offset], &i, sizeof(i));
9007b5038d7SDag-Erling Smørgrav 			  offset += sizeof(i);
9017b5038d7SDag-Erling Smørgrav 			}
9027b5038d7SDag-Erling Smørgrav 			if (offset < size) {
9037b5038d7SDag-Erling Smørgrav 			  i = random();
9047b5038d7SDag-Erling Smørgrav 			  memcpy(&hmac[offset], &i, size - offset);
9057b5038d7SDag-Erling Smørgrav 			}
9067b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
9077b5038d7SDag-Erling Smørgrav 			ldns_key_set_hmac_key(k, hmac);
9087b5038d7SDag-Erling Smørgrav 
9097b5038d7SDag-Erling Smørgrav 			ldns_key_set_flags(k, 0);
9107b5038d7SDag-Erling Smørgrav 			break;
9117b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_ECC_GOST:
9127b5038d7SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(USE_GOST)
9137b5038d7SDag-Erling Smørgrav 			ldns_key_set_evp_key(k, ldns_gen_gost_key());
9147b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
9157b5038d7SDag-Erling Smørgrav                         if(!k->_key.key) {
9167b5038d7SDag-Erling Smørgrav                                 ldns_key_free(k);
9177b5038d7SDag-Erling Smørgrav                                 return NULL;
9187b5038d7SDag-Erling Smørgrav                         }
9197b5038d7SDag-Erling Smørgrav #endif /* splint */
9207b5038d7SDag-Erling Smørgrav #else
9217b5038d7SDag-Erling Smørgrav 			ldns_key_free(k);
9227b5038d7SDag-Erling Smørgrav 			return NULL;
9237b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL and USE_GOST */
9247b5038d7SDag-Erling Smørgrav                         break;
9257b5038d7SDag-Erling Smørgrav                 case LDNS_SIGN_ECDSAP256SHA256:
9267b5038d7SDag-Erling Smørgrav                 case LDNS_SIGN_ECDSAP384SHA384:
9277b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA
9287b5038d7SDag-Erling Smørgrav                         if(alg == LDNS_SIGN_ECDSAP256SHA256)
9297b5038d7SDag-Erling Smørgrav                                 ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
9307b5038d7SDag-Erling Smørgrav                         else if(alg == LDNS_SIGN_ECDSAP384SHA384)
9317b5038d7SDag-Erling Smørgrav                                 ec = EC_KEY_new_by_curve_name(NID_secp384r1);
9327b5038d7SDag-Erling Smørgrav                         if(!ec) {
9337b5038d7SDag-Erling Smørgrav                                 ldns_key_free(k);
9347b5038d7SDag-Erling Smørgrav                                 return NULL;
9357b5038d7SDag-Erling Smørgrav                         }
9367b5038d7SDag-Erling Smørgrav                         if(!EC_KEY_generate_key(ec)) {
9377b5038d7SDag-Erling Smørgrav                                 ldns_key_free(k);
9387b5038d7SDag-Erling Smørgrav                                 EC_KEY_free(ec);
9397b5038d7SDag-Erling Smørgrav                                 return NULL;
9407b5038d7SDag-Erling Smørgrav                         }
9417b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
9427b5038d7SDag-Erling Smørgrav                         k->_key.key = EVP_PKEY_new();
9437b5038d7SDag-Erling Smørgrav                         if(!k->_key.key) {
9447b5038d7SDag-Erling Smørgrav                                 ldns_key_free(k);
9457b5038d7SDag-Erling Smørgrav                                 EC_KEY_free(ec);
9467b5038d7SDag-Erling Smørgrav                                 return NULL;
9477b5038d7SDag-Erling Smørgrav                         }
9487b5038d7SDag-Erling Smørgrav                         if (!EVP_PKEY_assign_EC_KEY(k->_key.key, ec)) {
9497b5038d7SDag-Erling Smørgrav                                 ldns_key_free(k);
9507b5038d7SDag-Erling Smørgrav                                 EC_KEY_free(ec);
9517b5038d7SDag-Erling Smørgrav                                 return NULL;
9527b5038d7SDag-Erling Smørgrav 			}
9537b5038d7SDag-Erling Smørgrav #endif /* splint */
9547b5038d7SDag-Erling Smørgrav #else
9557b5038d7SDag-Erling Smørgrav 			ldns_key_free(k);
9567b5038d7SDag-Erling Smørgrav 			return NULL;
9577b5038d7SDag-Erling Smørgrav #endif /* ECDSA */
9587b5038d7SDag-Erling Smørgrav 			break;
9597b5038d7SDag-Erling Smørgrav 	}
9607b5038d7SDag-Erling Smørgrav 	ldns_key_set_algorithm(k, alg);
9617b5038d7SDag-Erling Smørgrav 	return k;
9627b5038d7SDag-Erling Smørgrav }
9637b5038d7SDag-Erling Smørgrav 
9647b5038d7SDag-Erling Smørgrav void
9657b5038d7SDag-Erling Smørgrav ldns_key_print(FILE *output, const ldns_key *k)
9667b5038d7SDag-Erling Smørgrav {
9677b5038d7SDag-Erling Smørgrav 	char *str = ldns_key2str(k);
9687b5038d7SDag-Erling Smørgrav 	if (str) {
9697b5038d7SDag-Erling Smørgrav                 fprintf(output, "%s", str);
9707b5038d7SDag-Erling Smørgrav         } else {
9717b5038d7SDag-Erling Smørgrav                 fprintf(output, "Unable to convert private key to string\n");
9727b5038d7SDag-Erling Smørgrav         }
9737b5038d7SDag-Erling Smørgrav         LDNS_FREE(str);
9747b5038d7SDag-Erling Smørgrav }
9757b5038d7SDag-Erling Smørgrav 
9767b5038d7SDag-Erling Smørgrav 
9777b5038d7SDag-Erling Smørgrav void
9787b5038d7SDag-Erling Smørgrav ldns_key_set_algorithm(ldns_key *k, ldns_signing_algorithm l)
9797b5038d7SDag-Erling Smørgrav {
9807b5038d7SDag-Erling Smørgrav 	k->_alg = l;
9817b5038d7SDag-Erling Smørgrav }
9827b5038d7SDag-Erling Smørgrav 
9837b5038d7SDag-Erling Smørgrav void
9847b5038d7SDag-Erling Smørgrav ldns_key_set_flags(ldns_key *k, uint16_t f)
9857b5038d7SDag-Erling Smørgrav {
9867b5038d7SDag-Erling Smørgrav 	k->_extra.dnssec.flags = f;
9877b5038d7SDag-Erling Smørgrav }
9887b5038d7SDag-Erling Smørgrav 
9897b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
9907b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
9917b5038d7SDag-Erling Smørgrav void
9927b5038d7SDag-Erling Smørgrav ldns_key_set_evp_key(ldns_key *k, EVP_PKEY *e)
9937b5038d7SDag-Erling Smørgrav {
9947b5038d7SDag-Erling Smørgrav 	k->_key.key = e;
9957b5038d7SDag-Erling Smørgrav }
9967b5038d7SDag-Erling Smørgrav 
9977b5038d7SDag-Erling Smørgrav void
9987b5038d7SDag-Erling Smørgrav ldns_key_set_rsa_key(ldns_key *k, RSA *r)
9997b5038d7SDag-Erling Smørgrav {
10007b5038d7SDag-Erling Smørgrav 	EVP_PKEY *key = EVP_PKEY_new();
10017b5038d7SDag-Erling Smørgrav 	EVP_PKEY_set1_RSA(key, r);
10027b5038d7SDag-Erling Smørgrav 	k->_key.key = key;
10037b5038d7SDag-Erling Smørgrav }
10047b5038d7SDag-Erling Smørgrav 
10057b5038d7SDag-Erling Smørgrav void
10067b5038d7SDag-Erling Smørgrav ldns_key_set_dsa_key(ldns_key *k, DSA *d)
10077b5038d7SDag-Erling Smørgrav {
10087b5038d7SDag-Erling Smørgrav 	EVP_PKEY *key = EVP_PKEY_new();
10097b5038d7SDag-Erling Smørgrav 	EVP_PKEY_set1_DSA(key, d);
10107b5038d7SDag-Erling Smørgrav 	k->_key.key  = key;
10117b5038d7SDag-Erling Smørgrav }
10122787e39aSDag-Erling Smørgrav 
10132787e39aSDag-Erling Smørgrav void
10142787e39aSDag-Erling Smørgrav ldns_key_assign_rsa_key(ldns_key *k, RSA *r)
10152787e39aSDag-Erling Smørgrav {
10162787e39aSDag-Erling Smørgrav 	EVP_PKEY *key = EVP_PKEY_new();
10172787e39aSDag-Erling Smørgrav 	EVP_PKEY_assign_RSA(key, r);
10182787e39aSDag-Erling Smørgrav 	k->_key.key = key;
10192787e39aSDag-Erling Smørgrav }
10202787e39aSDag-Erling Smørgrav 
10212787e39aSDag-Erling Smørgrav void
10222787e39aSDag-Erling Smørgrav ldns_key_assign_dsa_key(ldns_key *k, DSA *d)
10232787e39aSDag-Erling Smørgrav {
10242787e39aSDag-Erling Smørgrav 	EVP_PKEY *key = EVP_PKEY_new();
10252787e39aSDag-Erling Smørgrav 	EVP_PKEY_assign_DSA(key, d);
10262787e39aSDag-Erling Smørgrav 	k->_key.key  = key;
10272787e39aSDag-Erling Smørgrav }
10287b5038d7SDag-Erling Smørgrav #endif /* splint */
10297b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
10307b5038d7SDag-Erling Smørgrav 
10317b5038d7SDag-Erling Smørgrav void
10327b5038d7SDag-Erling Smørgrav ldns_key_set_hmac_key(ldns_key *k, unsigned char *hmac)
10337b5038d7SDag-Erling Smørgrav {
10347b5038d7SDag-Erling Smørgrav 	k->_key.hmac.key = hmac;
10357b5038d7SDag-Erling Smørgrav }
10367b5038d7SDag-Erling Smørgrav 
10377b5038d7SDag-Erling Smørgrav void
10387b5038d7SDag-Erling Smørgrav ldns_key_set_hmac_size(ldns_key *k, size_t hmac_size)
10397b5038d7SDag-Erling Smørgrav {
10407b5038d7SDag-Erling Smørgrav 	k->_key.hmac.size = hmac_size;
10417b5038d7SDag-Erling Smørgrav }
10427b5038d7SDag-Erling Smørgrav 
10437b5038d7SDag-Erling Smørgrav void
10447b5038d7SDag-Erling Smørgrav ldns_key_set_external_key(ldns_key *k, void *external_key)
10457b5038d7SDag-Erling Smørgrav {
10467b5038d7SDag-Erling Smørgrav 	k->_key.external_key = external_key;
10477b5038d7SDag-Erling Smørgrav }
10487b5038d7SDag-Erling Smørgrav 
10497b5038d7SDag-Erling Smørgrav void
10507b5038d7SDag-Erling Smørgrav ldns_key_set_origttl(ldns_key *k, uint32_t t)
10517b5038d7SDag-Erling Smørgrav {
10527b5038d7SDag-Erling Smørgrav 	k->_extra.dnssec.orig_ttl = t;
10537b5038d7SDag-Erling Smørgrav }
10547b5038d7SDag-Erling Smørgrav 
10557b5038d7SDag-Erling Smørgrav void
10567b5038d7SDag-Erling Smørgrav ldns_key_set_inception(ldns_key *k, uint32_t i)
10577b5038d7SDag-Erling Smørgrav {
10587b5038d7SDag-Erling Smørgrav 	k->_extra.dnssec.inception = i;
10597b5038d7SDag-Erling Smørgrav }
10607b5038d7SDag-Erling Smørgrav 
10617b5038d7SDag-Erling Smørgrav void
10627b5038d7SDag-Erling Smørgrav ldns_key_set_expiration(ldns_key *k, uint32_t e)
10637b5038d7SDag-Erling Smørgrav {
10647b5038d7SDag-Erling Smørgrav 	k->_extra.dnssec.expiration = e;
10657b5038d7SDag-Erling Smørgrav }
10667b5038d7SDag-Erling Smørgrav 
10677b5038d7SDag-Erling Smørgrav void
10687b5038d7SDag-Erling Smørgrav ldns_key_set_pubkey_owner(ldns_key *k, ldns_rdf *r)
10697b5038d7SDag-Erling Smørgrav {
10707b5038d7SDag-Erling Smørgrav 	k->_pubkey_owner = r;
10717b5038d7SDag-Erling Smørgrav }
10727b5038d7SDag-Erling Smørgrav 
10737b5038d7SDag-Erling Smørgrav void
10747b5038d7SDag-Erling Smørgrav ldns_key_set_keytag(ldns_key *k, uint16_t tag)
10757b5038d7SDag-Erling Smørgrav {
10767b5038d7SDag-Erling Smørgrav 	k->_extra.dnssec.keytag = tag;
10777b5038d7SDag-Erling Smørgrav }
10787b5038d7SDag-Erling Smørgrav 
10797b5038d7SDag-Erling Smørgrav /* read */
10807b5038d7SDag-Erling Smørgrav size_t
10817b5038d7SDag-Erling Smørgrav ldns_key_list_key_count(const ldns_key_list *key_list)
10827b5038d7SDag-Erling Smørgrav {
10837b5038d7SDag-Erling Smørgrav 	        return key_list->_key_count;
10847b5038d7SDag-Erling Smørgrav }
10857b5038d7SDag-Erling Smørgrav 
10867b5038d7SDag-Erling Smørgrav ldns_key *
10877b5038d7SDag-Erling Smørgrav ldns_key_list_key(const ldns_key_list *key, size_t nr)
10887b5038d7SDag-Erling Smørgrav {
10897b5038d7SDag-Erling Smørgrav 	if (nr < ldns_key_list_key_count(key)) {
10907b5038d7SDag-Erling Smørgrav 		return key->_keys[nr];
10917b5038d7SDag-Erling Smørgrav 	} else {
10927b5038d7SDag-Erling Smørgrav 		return NULL;
10937b5038d7SDag-Erling Smørgrav 	}
10947b5038d7SDag-Erling Smørgrav }
10957b5038d7SDag-Erling Smørgrav 
10967b5038d7SDag-Erling Smørgrav ldns_signing_algorithm
10977b5038d7SDag-Erling Smørgrav ldns_key_algorithm(const ldns_key *k)
10987b5038d7SDag-Erling Smørgrav {
10997b5038d7SDag-Erling Smørgrav 	return k->_alg;
11007b5038d7SDag-Erling Smørgrav }
11017b5038d7SDag-Erling Smørgrav 
11027b5038d7SDag-Erling Smørgrav void
11037b5038d7SDag-Erling Smørgrav ldns_key_set_use(ldns_key *k, bool v)
11047b5038d7SDag-Erling Smørgrav {
11057b5038d7SDag-Erling Smørgrav 	if (k) {
11067b5038d7SDag-Erling Smørgrav 		k->_use = v;
11077b5038d7SDag-Erling Smørgrav 	}
11087b5038d7SDag-Erling Smørgrav }
11097b5038d7SDag-Erling Smørgrav 
11107b5038d7SDag-Erling Smørgrav bool
11117b5038d7SDag-Erling Smørgrav ldns_key_use(const ldns_key *k)
11127b5038d7SDag-Erling Smørgrav {
11137b5038d7SDag-Erling Smørgrav 	if (k) {
11147b5038d7SDag-Erling Smørgrav 		return k->_use;
11157b5038d7SDag-Erling Smørgrav 	}
11167b5038d7SDag-Erling Smørgrav 	return false;
11177b5038d7SDag-Erling Smørgrav }
11187b5038d7SDag-Erling Smørgrav 
11197b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
11207b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
11217b5038d7SDag-Erling Smørgrav EVP_PKEY *
11227b5038d7SDag-Erling Smørgrav ldns_key_evp_key(const ldns_key *k)
11237b5038d7SDag-Erling Smørgrav {
11247b5038d7SDag-Erling Smørgrav 	return k->_key.key;
11257b5038d7SDag-Erling Smørgrav }
11267b5038d7SDag-Erling Smørgrav 
11277b5038d7SDag-Erling Smørgrav RSA *
11287b5038d7SDag-Erling Smørgrav ldns_key_rsa_key(const ldns_key *k)
11297b5038d7SDag-Erling Smørgrav {
11307b5038d7SDag-Erling Smørgrav 	if (k->_key.key) {
11317b5038d7SDag-Erling Smørgrav 		return EVP_PKEY_get1_RSA(k->_key.key);
11327b5038d7SDag-Erling Smørgrav 	} else {
11337b5038d7SDag-Erling Smørgrav 		return NULL;
11347b5038d7SDag-Erling Smørgrav 	}
11357b5038d7SDag-Erling Smørgrav }
11367b5038d7SDag-Erling Smørgrav 
11377b5038d7SDag-Erling Smørgrav DSA *
11387b5038d7SDag-Erling Smørgrav ldns_key_dsa_key(const ldns_key *k)
11397b5038d7SDag-Erling Smørgrav {
11407b5038d7SDag-Erling Smørgrav 	if (k->_key.key) {
11417b5038d7SDag-Erling Smørgrav 		return EVP_PKEY_get1_DSA(k->_key.key);
11427b5038d7SDag-Erling Smørgrav 	} else {
11437b5038d7SDag-Erling Smørgrav 		return NULL;
11447b5038d7SDag-Erling Smørgrav 	}
11457b5038d7SDag-Erling Smørgrav }
11467b5038d7SDag-Erling Smørgrav #endif /* splint */
11477b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
11487b5038d7SDag-Erling Smørgrav 
11497b5038d7SDag-Erling Smørgrav unsigned char *
11507b5038d7SDag-Erling Smørgrav ldns_key_hmac_key(const ldns_key *k)
11517b5038d7SDag-Erling Smørgrav {
11527b5038d7SDag-Erling Smørgrav 	if (k->_key.hmac.key) {
11537b5038d7SDag-Erling Smørgrav 		return k->_key.hmac.key;
11547b5038d7SDag-Erling Smørgrav 	} else {
11557b5038d7SDag-Erling Smørgrav 		return NULL;
11567b5038d7SDag-Erling Smørgrav 	}
11577b5038d7SDag-Erling Smørgrav }
11587b5038d7SDag-Erling Smørgrav 
11597b5038d7SDag-Erling Smørgrav size_t
11607b5038d7SDag-Erling Smørgrav ldns_key_hmac_size(const ldns_key *k)
11617b5038d7SDag-Erling Smørgrav {
11627b5038d7SDag-Erling Smørgrav 	if (k->_key.hmac.size) {
11637b5038d7SDag-Erling Smørgrav 		return k->_key.hmac.size;
11647b5038d7SDag-Erling Smørgrav 	} else {
11657b5038d7SDag-Erling Smørgrav 		return 0;
11667b5038d7SDag-Erling Smørgrav 	}
11677b5038d7SDag-Erling Smørgrav }
11687b5038d7SDag-Erling Smørgrav 
11697b5038d7SDag-Erling Smørgrav void *
11707b5038d7SDag-Erling Smørgrav ldns_key_external_key(const ldns_key *k)
11717b5038d7SDag-Erling Smørgrav {
11727b5038d7SDag-Erling Smørgrav 	return k->_key.external_key;
11737b5038d7SDag-Erling Smørgrav }
11747b5038d7SDag-Erling Smørgrav 
11757b5038d7SDag-Erling Smørgrav uint32_t
11767b5038d7SDag-Erling Smørgrav ldns_key_origttl(const ldns_key *k)
11777b5038d7SDag-Erling Smørgrav {
11787b5038d7SDag-Erling Smørgrav 	return k->_extra.dnssec.orig_ttl;
11797b5038d7SDag-Erling Smørgrav }
11807b5038d7SDag-Erling Smørgrav 
11817b5038d7SDag-Erling Smørgrav uint16_t
11827b5038d7SDag-Erling Smørgrav ldns_key_flags(const ldns_key *k)
11837b5038d7SDag-Erling Smørgrav {
11847b5038d7SDag-Erling Smørgrav 	return k->_extra.dnssec.flags;
11857b5038d7SDag-Erling Smørgrav }
11867b5038d7SDag-Erling Smørgrav 
11877b5038d7SDag-Erling Smørgrav uint32_t
11887b5038d7SDag-Erling Smørgrav ldns_key_inception(const ldns_key *k)
11897b5038d7SDag-Erling Smørgrav {
11907b5038d7SDag-Erling Smørgrav 	return k->_extra.dnssec.inception;
11917b5038d7SDag-Erling Smørgrav }
11927b5038d7SDag-Erling Smørgrav 
11937b5038d7SDag-Erling Smørgrav uint32_t
11947b5038d7SDag-Erling Smørgrav ldns_key_expiration(const ldns_key *k)
11957b5038d7SDag-Erling Smørgrav {
11967b5038d7SDag-Erling Smørgrav 	return k->_extra.dnssec.expiration;
11977b5038d7SDag-Erling Smørgrav }
11987b5038d7SDag-Erling Smørgrav 
11997b5038d7SDag-Erling Smørgrav uint16_t
12007b5038d7SDag-Erling Smørgrav ldns_key_keytag(const ldns_key *k)
12017b5038d7SDag-Erling Smørgrav {
12027b5038d7SDag-Erling Smørgrav 	return k->_extra.dnssec.keytag;
12037b5038d7SDag-Erling Smørgrav }
12047b5038d7SDag-Erling Smørgrav 
12057b5038d7SDag-Erling Smørgrav ldns_rdf *
12067b5038d7SDag-Erling Smørgrav ldns_key_pubkey_owner(const ldns_key *k)
12077b5038d7SDag-Erling Smørgrav {
12087b5038d7SDag-Erling Smørgrav 	return k->_pubkey_owner;
12097b5038d7SDag-Erling Smørgrav }
12107b5038d7SDag-Erling Smørgrav 
12117b5038d7SDag-Erling Smørgrav /* write */
12127b5038d7SDag-Erling Smørgrav void
12137b5038d7SDag-Erling Smørgrav ldns_key_list_set_use(ldns_key_list *keys, bool v)
12147b5038d7SDag-Erling Smørgrav {
12157b5038d7SDag-Erling Smørgrav 	size_t i;
12167b5038d7SDag-Erling Smørgrav 
12177b5038d7SDag-Erling Smørgrav 	for (i = 0; i < ldns_key_list_key_count(keys); i++) {
12187b5038d7SDag-Erling Smørgrav 		ldns_key_set_use(ldns_key_list_key(keys, i), v);
12197b5038d7SDag-Erling Smørgrav 	}
12207b5038d7SDag-Erling Smørgrav }
12217b5038d7SDag-Erling Smørgrav 
12227b5038d7SDag-Erling Smørgrav void
12237b5038d7SDag-Erling Smørgrav ldns_key_list_set_key_count(ldns_key_list *key, size_t count)
12247b5038d7SDag-Erling Smørgrav {
12257b5038d7SDag-Erling Smørgrav 	        key->_key_count = count;
12267b5038d7SDag-Erling Smørgrav }
12277b5038d7SDag-Erling Smørgrav 
12287b5038d7SDag-Erling Smørgrav bool
12297b5038d7SDag-Erling Smørgrav ldns_key_list_push_key(ldns_key_list *key_list, ldns_key *key)
12307b5038d7SDag-Erling Smørgrav {
12317b5038d7SDag-Erling Smørgrav         size_t key_count;
12327b5038d7SDag-Erling Smørgrav         ldns_key **keys;
12337b5038d7SDag-Erling Smørgrav 
12347b5038d7SDag-Erling Smørgrav         key_count = ldns_key_list_key_count(key_list);
12357b5038d7SDag-Erling Smørgrav 
12367b5038d7SDag-Erling Smørgrav         /* grow the array */
12377b5038d7SDag-Erling Smørgrav         keys = LDNS_XREALLOC(
12387b5038d7SDag-Erling Smørgrav                 key_list->_keys, ldns_key *, key_count + 1);
12397b5038d7SDag-Erling Smørgrav         if (!keys) {
12407b5038d7SDag-Erling Smørgrav                 return false;
12417b5038d7SDag-Erling Smørgrav         }
12427b5038d7SDag-Erling Smørgrav 
12437b5038d7SDag-Erling Smørgrav         /* add the new member */
12447b5038d7SDag-Erling Smørgrav         key_list->_keys = keys;
12457b5038d7SDag-Erling Smørgrav         key_list->_keys[key_count] = key;
12467b5038d7SDag-Erling Smørgrav 
12477b5038d7SDag-Erling Smørgrav         ldns_key_list_set_key_count(key_list, key_count + 1);
12487b5038d7SDag-Erling Smørgrav         return true;
12497b5038d7SDag-Erling Smørgrav }
12507b5038d7SDag-Erling Smørgrav 
12517b5038d7SDag-Erling Smørgrav ldns_key *
12527b5038d7SDag-Erling Smørgrav ldns_key_list_pop_key(ldns_key_list *key_list)
12537b5038d7SDag-Erling Smørgrav {
12547b5038d7SDag-Erling Smørgrav         size_t key_count;
12557b5038d7SDag-Erling Smørgrav         ldns_key** a;
12567b5038d7SDag-Erling Smørgrav         ldns_key *pop;
12577b5038d7SDag-Erling Smørgrav 
12587b5038d7SDag-Erling Smørgrav 	if (!key_list) {
12597b5038d7SDag-Erling Smørgrav 		return NULL;
12607b5038d7SDag-Erling Smørgrav 	}
12617b5038d7SDag-Erling Smørgrav 
12627b5038d7SDag-Erling Smørgrav         key_count = ldns_key_list_key_count(key_list);
12637b5038d7SDag-Erling Smørgrav         if (key_count == 0) {
12647b5038d7SDag-Erling Smørgrav                 return NULL;
12657b5038d7SDag-Erling Smørgrav         }
12667b5038d7SDag-Erling Smørgrav 
12677b5038d7SDag-Erling Smørgrav         pop = ldns_key_list_key(key_list, key_count);
12687b5038d7SDag-Erling Smørgrav 
12697b5038d7SDag-Erling Smørgrav         /* shrink the array */
12707b5038d7SDag-Erling Smørgrav         a = LDNS_XREALLOC(key_list->_keys, ldns_key *, key_count - 1);
12717b5038d7SDag-Erling Smørgrav         if(a) {
12727b5038d7SDag-Erling Smørgrav                 key_list->_keys = a;
12737b5038d7SDag-Erling Smørgrav         }
12747b5038d7SDag-Erling Smørgrav 
12757b5038d7SDag-Erling Smørgrav         ldns_key_list_set_key_count(key_list, key_count - 1);
12767b5038d7SDag-Erling Smørgrav 
12777b5038d7SDag-Erling Smørgrav         return pop;
12787b5038d7SDag-Erling Smørgrav }
12797b5038d7SDag-Erling Smørgrav 
12807b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
12817b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
12827b5038d7SDag-Erling Smørgrav /* data pointer must be large enough (LDNS_MAX_KEYLEN) */
12837b5038d7SDag-Erling Smørgrav static bool
12847b5038d7SDag-Erling Smørgrav ldns_key_rsa2bin(unsigned char *data, RSA *k, uint16_t *size)
12857b5038d7SDag-Erling Smørgrav {
12867b5038d7SDag-Erling Smørgrav 	int i,j;
12877b5038d7SDag-Erling Smørgrav 
12887b5038d7SDag-Erling Smørgrav 	if (!k) {
12897b5038d7SDag-Erling Smørgrav 		return false;
12907b5038d7SDag-Erling Smørgrav 	}
12917b5038d7SDag-Erling Smørgrav 
12927b5038d7SDag-Erling Smørgrav 	if (BN_num_bytes(k->e) <= 256) {
12937b5038d7SDag-Erling Smørgrav 		/* normally only this path is executed (small factors are
12947b5038d7SDag-Erling Smørgrav 		 * more common
12957b5038d7SDag-Erling Smørgrav 		 */
12967b5038d7SDag-Erling Smørgrav 		data[0] = (unsigned char) BN_num_bytes(k->e);
12977b5038d7SDag-Erling Smørgrav 		i = BN_bn2bin(k->e, data + 1);
12987b5038d7SDag-Erling Smørgrav 		j = BN_bn2bin(k->n, data + i + 1);
12997b5038d7SDag-Erling Smørgrav 		*size = (uint16_t) i + j;
13007b5038d7SDag-Erling Smørgrav 	} else if (BN_num_bytes(k->e) <= 65536) {
13017b5038d7SDag-Erling Smørgrav 		data[0] = 0;
13027b5038d7SDag-Erling Smørgrav 		/* BN_bn2bin does bigendian, _uint16 also */
13037b5038d7SDag-Erling Smørgrav 		ldns_write_uint16(data + 1, (uint16_t) BN_num_bytes(k->e));
13047b5038d7SDag-Erling Smørgrav 
13057b5038d7SDag-Erling Smørgrav 		BN_bn2bin(k->e, data + 3);
13067b5038d7SDag-Erling Smørgrav 		BN_bn2bin(k->n, data + 4 + BN_num_bytes(k->e));
13077b5038d7SDag-Erling Smørgrav 		*size = (uint16_t) BN_num_bytes(k->n) + 6;
13087b5038d7SDag-Erling Smørgrav 	} else {
13097b5038d7SDag-Erling Smørgrav 		return false;
13107b5038d7SDag-Erling Smørgrav 	}
13117b5038d7SDag-Erling Smørgrav 	return true;
13127b5038d7SDag-Erling Smørgrav }
13137b5038d7SDag-Erling Smørgrav 
13147b5038d7SDag-Erling Smørgrav /* data pointer must be large enough (LDNS_MAX_KEYLEN) */
13157b5038d7SDag-Erling Smørgrav static bool
13167b5038d7SDag-Erling Smørgrav ldns_key_dsa2bin(unsigned char *data, DSA *k, uint16_t *size)
13177b5038d7SDag-Erling Smørgrav {
13187b5038d7SDag-Erling Smørgrav 	uint8_t T;
13197b5038d7SDag-Erling Smørgrav 
13207b5038d7SDag-Erling Smørgrav 	if (!k) {
13217b5038d7SDag-Erling Smørgrav 		return false;
13227b5038d7SDag-Erling Smørgrav 	}
13237b5038d7SDag-Erling Smørgrav 
13247b5038d7SDag-Erling Smørgrav 	/* See RFC2536 */
13252787e39aSDag-Erling Smørgrav 	*size = (uint16_t)BN_num_bytes(k->p);
13267b5038d7SDag-Erling Smørgrav 	T = (*size - 64) / 8;
13277b5038d7SDag-Erling Smørgrav 	memcpy(data, &T, 1);
13287b5038d7SDag-Erling Smørgrav 
13297b5038d7SDag-Erling Smørgrav 	if (T > 8) {
1330*17d15b25SDag-Erling Smørgrav #ifdef STDERR_MSGS
13317b5038d7SDag-Erling Smørgrav 		fprintf(stderr, "DSA key with T > 8 (ie. > 1024 bits)");
13327b5038d7SDag-Erling Smørgrav 		fprintf(stderr, " not implemented\n");
1333*17d15b25SDag-Erling Smørgrav #endif
13347b5038d7SDag-Erling Smørgrav 		return false;
13357b5038d7SDag-Erling Smørgrav 	}
13367b5038d7SDag-Erling Smørgrav 
13377b5038d7SDag-Erling Smørgrav 	/* size = 64 + (T * 8); */
13387b5038d7SDag-Erling Smørgrav 	data[0] = (unsigned char)T;
13397b5038d7SDag-Erling Smørgrav 	BN_bn2bin(k->q, data + 1 ); 		/* 20 octects */
13407b5038d7SDag-Erling Smørgrav 	BN_bn2bin(k->p, data + 21 ); 		/* offset octects */
13417b5038d7SDag-Erling Smørgrav 	BN_bn2bin(k->g, data + 21 + *size); 	/* offset octets */
13427b5038d7SDag-Erling Smørgrav 	BN_bn2bin(k->pub_key, data + 21 + *size + *size); /* offset octets */
13437b5038d7SDag-Erling Smørgrav 	*size = 21 + (*size * 3);
13447b5038d7SDag-Erling Smørgrav 	return true;
13457b5038d7SDag-Erling Smørgrav }
13467b5038d7SDag-Erling Smørgrav 
13477b5038d7SDag-Erling Smørgrav #ifdef USE_GOST
13487b5038d7SDag-Erling Smørgrav static bool
13497b5038d7SDag-Erling Smørgrav ldns_key_gost2bin(unsigned char* data, EVP_PKEY* k, uint16_t* size)
13507b5038d7SDag-Erling Smørgrav {
13517b5038d7SDag-Erling Smørgrav 	int i;
13527b5038d7SDag-Erling Smørgrav 	unsigned char* pp = NULL;
13537b5038d7SDag-Erling Smørgrav 	if(i2d_PUBKEY(k, &pp) != 37 + 64) {
13547b5038d7SDag-Erling Smørgrav 		/* expect 37 byte(ASN header) and 64 byte(X and Y) */
13557b5038d7SDag-Erling Smørgrav 		CRYPTO_free(pp);
13567b5038d7SDag-Erling Smørgrav 		return false;
13577b5038d7SDag-Erling Smørgrav 	}
13587b5038d7SDag-Erling Smørgrav 	/* omit ASN header */
13597b5038d7SDag-Erling Smørgrav 	for(i=0; i<64; i++)
13607b5038d7SDag-Erling Smørgrav 		data[i] = pp[i+37];
13617b5038d7SDag-Erling Smørgrav 	CRYPTO_free(pp);
13627b5038d7SDag-Erling Smørgrav 	*size = 64;
13637b5038d7SDag-Erling Smørgrav 	return true;
13647b5038d7SDag-Erling Smørgrav }
13657b5038d7SDag-Erling Smørgrav #endif /* USE_GOST */
13667b5038d7SDag-Erling Smørgrav #endif /* splint */
13677b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
13687b5038d7SDag-Erling Smørgrav 
13697b5038d7SDag-Erling Smørgrav ldns_rr *
13707b5038d7SDag-Erling Smørgrav ldns_key2rr(const ldns_key *k)
13717b5038d7SDag-Erling Smørgrav {
13727b5038d7SDag-Erling Smørgrav 	/* this function will convert a the keydata contained in
13737b5038d7SDag-Erling Smørgrav 	 * rsa/dsa pointers to a DNSKEY rr. It will fill in as
13747b5038d7SDag-Erling Smørgrav 	 * much as it can, but it does not know about key-flags
13757b5038d7SDag-Erling Smørgrav 	 * for instance
13767b5038d7SDag-Erling Smørgrav 	 */
13777b5038d7SDag-Erling Smørgrav 	ldns_rr *pubkey;
13787b5038d7SDag-Erling Smørgrav 	ldns_rdf *keybin;
13797b5038d7SDag-Erling Smørgrav 	unsigned char *bin = NULL;
13807b5038d7SDag-Erling Smørgrav 	uint16_t size = 0;
13817b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
13827b5038d7SDag-Erling Smørgrav 	RSA *rsa = NULL;
13837b5038d7SDag-Erling Smørgrav 	DSA *dsa = NULL;
13847b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
13857b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA
13867b5038d7SDag-Erling Smørgrav         EC_KEY* ec;
13877b5038d7SDag-Erling Smørgrav #endif
13887b5038d7SDag-Erling Smørgrav 	int internal_data = 0;
13897b5038d7SDag-Erling Smørgrav 
13907b5038d7SDag-Erling Smørgrav 	if (!k) {
13917b5038d7SDag-Erling Smørgrav 		return NULL;
13927b5038d7SDag-Erling Smørgrav 	}
13932787e39aSDag-Erling Smørgrav 	pubkey = ldns_rr_new();
13947b5038d7SDag-Erling Smørgrav 
13957b5038d7SDag-Erling Smørgrav 	switch (ldns_key_algorithm(k)) {
13967b5038d7SDag-Erling Smørgrav 	case LDNS_SIGN_HMACMD5:
13977b5038d7SDag-Erling Smørgrav 	case LDNS_SIGN_HMACSHA1:
13987b5038d7SDag-Erling Smørgrav 	case LDNS_SIGN_HMACSHA256:
13997b5038d7SDag-Erling Smørgrav 		ldns_rr_set_type(pubkey, LDNS_RR_TYPE_KEY);
14007b5038d7SDag-Erling Smørgrav         	break;
14017b5038d7SDag-Erling Smørgrav 	default:
14027b5038d7SDag-Erling Smørgrav 		ldns_rr_set_type(pubkey, LDNS_RR_TYPE_DNSKEY);
14037b5038d7SDag-Erling Smørgrav 		break;
14047b5038d7SDag-Erling Smørgrav         }
14057b5038d7SDag-Erling Smørgrav 	/* zero-th rdf - flags */
14067b5038d7SDag-Erling Smørgrav 	ldns_rr_push_rdf(pubkey,
14077b5038d7SDag-Erling Smørgrav 			ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16,
14087b5038d7SDag-Erling Smørgrav 				ldns_key_flags(k)));
14097b5038d7SDag-Erling Smørgrav 	/* first - proto */
14107b5038d7SDag-Erling Smørgrav 	ldns_rr_push_rdf(pubkey,
14117b5038d7SDag-Erling Smørgrav 			ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, LDNS_DNSSEC_KEYPROTO));
14127b5038d7SDag-Erling Smørgrav 
14137b5038d7SDag-Erling Smørgrav 	if (ldns_key_pubkey_owner(k)) {
14147b5038d7SDag-Erling Smørgrav 		ldns_rr_set_owner(pubkey, ldns_rdf_clone(ldns_key_pubkey_owner(k)));
14157b5038d7SDag-Erling Smørgrav 	}
14167b5038d7SDag-Erling Smørgrav 
14177b5038d7SDag-Erling Smørgrav 	/* third - da algorithm */
14187b5038d7SDag-Erling Smørgrav 	switch(ldns_key_algorithm(k)) {
14197b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSAMD5:
14207b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSASHA1:
14217b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSASHA1_NSEC3:
14227b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSASHA256:
14237b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_RSASHA512:
14247b5038d7SDag-Erling Smørgrav 			ldns_rr_push_rdf(pubkey,
14257b5038d7SDag-Erling Smørgrav 						  ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k)));
14267b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
14277b5038d7SDag-Erling Smørgrav 			rsa =  ldns_key_rsa_key(k);
14287b5038d7SDag-Erling Smørgrav 			if (rsa) {
14297b5038d7SDag-Erling Smørgrav 				bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
14307b5038d7SDag-Erling Smørgrav 				if (!bin) {
14317b5038d7SDag-Erling Smørgrav                                         ldns_rr_free(pubkey);
14327b5038d7SDag-Erling Smørgrav 					return NULL;
14337b5038d7SDag-Erling Smørgrav 				}
14347b5038d7SDag-Erling Smørgrav 				if (!ldns_key_rsa2bin(bin, rsa, &size)) {
14357b5038d7SDag-Erling Smørgrav 		                        LDNS_FREE(bin);
14367b5038d7SDag-Erling Smørgrav                                         ldns_rr_free(pubkey);
14377b5038d7SDag-Erling Smørgrav 					return NULL;
14387b5038d7SDag-Erling Smørgrav 				}
14397b5038d7SDag-Erling Smørgrav 				RSA_free(rsa);
14407b5038d7SDag-Erling Smørgrav 				internal_data = 1;
14417b5038d7SDag-Erling Smørgrav 			}
14427b5038d7SDag-Erling Smørgrav #endif
14437b5038d7SDag-Erling Smørgrav 			size++;
14447b5038d7SDag-Erling Smørgrav 			break;
14457b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_DSA:
14467b5038d7SDag-Erling Smørgrav 			ldns_rr_push_rdf(pubkey,
14477b5038d7SDag-Erling Smørgrav 					ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA));
14487b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
14497b5038d7SDag-Erling Smørgrav 			dsa = ldns_key_dsa_key(k);
14507b5038d7SDag-Erling Smørgrav 			if (dsa) {
14517b5038d7SDag-Erling Smørgrav 				bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
14527b5038d7SDag-Erling Smørgrav 				if (!bin) {
14537b5038d7SDag-Erling Smørgrav                                         ldns_rr_free(pubkey);
14547b5038d7SDag-Erling Smørgrav 					return NULL;
14557b5038d7SDag-Erling Smørgrav 				}
14567b5038d7SDag-Erling Smørgrav 				if (!ldns_key_dsa2bin(bin, dsa, &size)) {
14577b5038d7SDag-Erling Smørgrav 		                        LDNS_FREE(bin);
14587b5038d7SDag-Erling Smørgrav                                         ldns_rr_free(pubkey);
14597b5038d7SDag-Erling Smørgrav 					return NULL;
14607b5038d7SDag-Erling Smørgrav 				}
14617b5038d7SDag-Erling Smørgrav 				DSA_free(dsa);
14627b5038d7SDag-Erling Smørgrav 				internal_data = 1;
14637b5038d7SDag-Erling Smørgrav 			}
14647b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
14657b5038d7SDag-Erling Smørgrav 			break;
14667b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_DSA_NSEC3:
14677b5038d7SDag-Erling Smørgrav 			ldns_rr_push_rdf(pubkey,
14687b5038d7SDag-Erling Smørgrav 					ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA_NSEC3));
14697b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
14707b5038d7SDag-Erling Smørgrav 			dsa = ldns_key_dsa_key(k);
14717b5038d7SDag-Erling Smørgrav 			if (dsa) {
14727b5038d7SDag-Erling Smørgrav 				bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
14737b5038d7SDag-Erling Smørgrav 				if (!bin) {
14747b5038d7SDag-Erling Smørgrav                                         ldns_rr_free(pubkey);
14757b5038d7SDag-Erling Smørgrav 					return NULL;
14767b5038d7SDag-Erling Smørgrav 				}
14777b5038d7SDag-Erling Smørgrav 				if (!ldns_key_dsa2bin(bin, dsa, &size)) {
14787b5038d7SDag-Erling Smørgrav 		                        LDNS_FREE(bin);
14797b5038d7SDag-Erling Smørgrav                                         ldns_rr_free(pubkey);
14807b5038d7SDag-Erling Smørgrav 					return NULL;
14817b5038d7SDag-Erling Smørgrav 				}
14827b5038d7SDag-Erling Smørgrav 				DSA_free(dsa);
14837b5038d7SDag-Erling Smørgrav 				internal_data = 1;
14847b5038d7SDag-Erling Smørgrav 			}
14857b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
14867b5038d7SDag-Erling Smørgrav 			break;
14877b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_ECC_GOST:
14887b5038d7SDag-Erling Smørgrav 			ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(
14897b5038d7SDag-Erling Smørgrav 				LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k)));
14907b5038d7SDag-Erling Smørgrav #if defined(HAVE_SSL) && defined(USE_GOST)
14917b5038d7SDag-Erling Smørgrav 			bin = LDNS_XMALLOC(unsigned char, LDNS_MAX_KEYLEN);
14927b5038d7SDag-Erling Smørgrav 			if (!bin) {
14937b5038d7SDag-Erling Smørgrav                                 ldns_rr_free(pubkey);
14947b5038d7SDag-Erling Smørgrav 				return NULL;
14957b5038d7SDag-Erling Smørgrav                         }
14967b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
14977b5038d7SDag-Erling Smørgrav 			if (!ldns_key_gost2bin(bin, k->_key.key, &size)) {
14987b5038d7SDag-Erling Smørgrav 		                LDNS_FREE(bin);
14997b5038d7SDag-Erling Smørgrav                                 ldns_rr_free(pubkey);
15007b5038d7SDag-Erling Smørgrav 				return NULL;
15017b5038d7SDag-Erling Smørgrav 			}
15027b5038d7SDag-Erling Smørgrav #endif /* splint */
15037b5038d7SDag-Erling Smørgrav 			internal_data = 1;
15047b5038d7SDag-Erling Smørgrav #else
15057b5038d7SDag-Erling Smørgrav                         ldns_rr_free(pubkey);
15067b5038d7SDag-Erling Smørgrav 			return NULL;
15077b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL and USE_GOST */
15087b5038d7SDag-Erling Smørgrav 			break;
15097b5038d7SDag-Erling Smørgrav                 case LDNS_SIGN_ECDSAP256SHA256:
15107b5038d7SDag-Erling Smørgrav                 case LDNS_SIGN_ECDSAP384SHA384:
15117b5038d7SDag-Erling Smørgrav #ifdef USE_ECDSA
15127b5038d7SDag-Erling Smørgrav 			ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(
15137b5038d7SDag-Erling Smørgrav 				LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k)));
15147b5038d7SDag-Erling Smørgrav                         bin = NULL;
15157b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S
15167b5038d7SDag-Erling Smørgrav                         ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
15177b5038d7SDag-Erling Smørgrav #endif
15187b5038d7SDag-Erling Smørgrav                         EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
15197b5038d7SDag-Erling Smørgrav                         size = (uint16_t)i2o_ECPublicKey(ec, NULL);
15207b5038d7SDag-Erling Smørgrav                         if(!i2o_ECPublicKey(ec, &bin)) {
15217b5038d7SDag-Erling Smørgrav                                 EC_KEY_free(ec);
15227b5038d7SDag-Erling Smørgrav                                 ldns_rr_free(pubkey);
15237b5038d7SDag-Erling Smørgrav                                 return NULL;
15247b5038d7SDag-Erling Smørgrav                         }
15257b5038d7SDag-Erling Smørgrav 			if(size > 1) {
15267b5038d7SDag-Erling Smørgrav 				/* move back one byte to shave off the 0x02
15277b5038d7SDag-Erling Smørgrav 				 * 'uncompressed' indicator that openssl made
15287b5038d7SDag-Erling Smørgrav 				 * Actually its 0x04 (from implementation).
15297b5038d7SDag-Erling Smørgrav 				 */
15307b5038d7SDag-Erling Smørgrav 				assert(bin[0] == POINT_CONVERSION_UNCOMPRESSED);
15317b5038d7SDag-Erling Smørgrav 				size -= 1;
15327b5038d7SDag-Erling Smørgrav 				memmove(bin, bin+1, size);
15337b5038d7SDag-Erling Smørgrav 			}
15347b5038d7SDag-Erling Smørgrav                         /* down the reference count for ec, its still assigned
15357b5038d7SDag-Erling Smørgrav                          * to the pkey */
15367b5038d7SDag-Erling Smørgrav                         EC_KEY_free(ec);
15377b5038d7SDag-Erling Smørgrav 			internal_data = 1;
15387b5038d7SDag-Erling Smørgrav #else
15397b5038d7SDag-Erling Smørgrav                         ldns_rr_free(pubkey);
15407b5038d7SDag-Erling Smørgrav 			return NULL;
15417b5038d7SDag-Erling Smørgrav #endif /* ECDSA */
15427b5038d7SDag-Erling Smørgrav                         break;
15437b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_HMACMD5:
15447b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_HMACSHA1:
15457b5038d7SDag-Erling Smørgrav 		case LDNS_SIGN_HMACSHA256:
15467b5038d7SDag-Erling Smørgrav 			bin = LDNS_XMALLOC(unsigned char, ldns_key_hmac_size(k));
15477b5038d7SDag-Erling Smørgrav 			if (!bin) {
15487b5038d7SDag-Erling Smørgrav                                 ldns_rr_free(pubkey);
15497b5038d7SDag-Erling Smørgrav 				return NULL;
15507b5038d7SDag-Erling Smørgrav 			}
15517b5038d7SDag-Erling Smørgrav 			ldns_rr_push_rdf(pubkey,
15527b5038d7SDag-Erling Smørgrav 			                 ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG,
15537b5038d7SDag-Erling Smørgrav 			                 ldns_key_algorithm(k)));
15547b5038d7SDag-Erling Smørgrav 			size = ldns_key_hmac_size(k);
15557b5038d7SDag-Erling Smørgrav 			memcpy(bin, ldns_key_hmac_key(k), size);
15567b5038d7SDag-Erling Smørgrav 			internal_data = 1;
15577b5038d7SDag-Erling Smørgrav 			break;
15587b5038d7SDag-Erling Smørgrav 	}
15597b5038d7SDag-Erling Smørgrav 	/* fourth the key bin material */
15607b5038d7SDag-Erling Smørgrav 	if (internal_data) {
15617b5038d7SDag-Erling Smørgrav 		keybin = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, size, bin);
15627b5038d7SDag-Erling Smørgrav 		LDNS_FREE(bin);
15637b5038d7SDag-Erling Smørgrav 		ldns_rr_push_rdf(pubkey, keybin);
15647b5038d7SDag-Erling Smørgrav 	}
15657b5038d7SDag-Erling Smørgrav 	return pubkey;
15667b5038d7SDag-Erling Smørgrav }
15677b5038d7SDag-Erling Smørgrav 
15687b5038d7SDag-Erling Smørgrav void
15697b5038d7SDag-Erling Smørgrav ldns_key_free(ldns_key *key)
15707b5038d7SDag-Erling Smørgrav {
15717b5038d7SDag-Erling Smørgrav 	LDNS_FREE(key);
15727b5038d7SDag-Erling Smørgrav }
15737b5038d7SDag-Erling Smørgrav 
15747b5038d7SDag-Erling Smørgrav void
15757b5038d7SDag-Erling Smørgrav ldns_key_deep_free(ldns_key *key)
15767b5038d7SDag-Erling Smørgrav {
15777b5038d7SDag-Erling Smørgrav 	unsigned char* hmac;
15787b5038d7SDag-Erling Smørgrav 	if (ldns_key_pubkey_owner(key)) {
15797b5038d7SDag-Erling Smørgrav 		ldns_rdf_deep_free(ldns_key_pubkey_owner(key));
15807b5038d7SDag-Erling Smørgrav 	}
15817b5038d7SDag-Erling Smørgrav #ifdef HAVE_SSL
15827b5038d7SDag-Erling Smørgrav 	if (ldns_key_evp_key(key)) {
15837b5038d7SDag-Erling Smørgrav 		EVP_PKEY_free(ldns_key_evp_key(key));
15847b5038d7SDag-Erling Smørgrav 	}
15857b5038d7SDag-Erling Smørgrav #endif /* HAVE_SSL */
15867b5038d7SDag-Erling Smørgrav 	if (ldns_key_hmac_key(key)) {
15877b5038d7SDag-Erling Smørgrav 		hmac = ldns_key_hmac_key(key);
15887b5038d7SDag-Erling Smørgrav 		LDNS_FREE(hmac);
15897b5038d7SDag-Erling Smørgrav 	}
15907b5038d7SDag-Erling Smørgrav 	LDNS_FREE(key);
15917b5038d7SDag-Erling Smørgrav }
15927b5038d7SDag-Erling Smørgrav 
15937b5038d7SDag-Erling Smørgrav void
15947b5038d7SDag-Erling Smørgrav ldns_key_list_free(ldns_key_list *key_list)
15957b5038d7SDag-Erling Smørgrav {
15967b5038d7SDag-Erling Smørgrav 	size_t i;
15977b5038d7SDag-Erling Smørgrav 	for (i = 0; i < ldns_key_list_key_count(key_list); i++) {
15987b5038d7SDag-Erling Smørgrav 		ldns_key_deep_free(ldns_key_list_key(key_list, i));
15997b5038d7SDag-Erling Smørgrav 	}
16007b5038d7SDag-Erling Smørgrav 	LDNS_FREE(key_list->_keys);
16017b5038d7SDag-Erling Smørgrav 	LDNS_FREE(key_list);
16027b5038d7SDag-Erling Smørgrav }
16037b5038d7SDag-Erling Smørgrav 
16047b5038d7SDag-Erling Smørgrav ldns_rr *
16057b5038d7SDag-Erling Smørgrav ldns_read_anchor_file(const char *filename)
16067b5038d7SDag-Erling Smørgrav {
16077b5038d7SDag-Erling Smørgrav 	FILE *fp;
16087b5038d7SDag-Erling Smørgrav 	/*char line[LDNS_MAX_PACKETLEN];*/
16097b5038d7SDag-Erling Smørgrav 	char *line = LDNS_XMALLOC(char, LDNS_MAX_PACKETLEN);
16107b5038d7SDag-Erling Smørgrav 	int c;
16117b5038d7SDag-Erling Smørgrav 	size_t i = 0;
16127b5038d7SDag-Erling Smørgrav 	ldns_rr *r;
16137b5038d7SDag-Erling Smørgrav 	ldns_status status;
16147b5038d7SDag-Erling Smørgrav         if(!line) {
16157b5038d7SDag-Erling Smørgrav                 return NULL;
16167b5038d7SDag-Erling Smørgrav         }
16177b5038d7SDag-Erling Smørgrav 
16187b5038d7SDag-Erling Smørgrav 	fp = fopen(filename, "r");
16197b5038d7SDag-Erling Smørgrav 	if (!fp) {
1620*17d15b25SDag-Erling Smørgrav #ifdef STDERR_MSGS
16217b5038d7SDag-Erling Smørgrav 		fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno));
1622*17d15b25SDag-Erling Smørgrav #endif
16237b5038d7SDag-Erling Smørgrav 		LDNS_FREE(line);
16247b5038d7SDag-Erling Smørgrav 		return NULL;
16257b5038d7SDag-Erling Smørgrav 	}
16267b5038d7SDag-Erling Smørgrav 
16277b5038d7SDag-Erling Smørgrav 	while ((c = fgetc(fp)) && i+1 < LDNS_MAX_PACKETLEN && c != EOF) {
16287b5038d7SDag-Erling Smørgrav 		line[i] = c;
16297b5038d7SDag-Erling Smørgrav 		i++;
16307b5038d7SDag-Erling Smørgrav 	}
16317b5038d7SDag-Erling Smørgrav 	line[i] = '\0';
16327b5038d7SDag-Erling Smørgrav 
16337b5038d7SDag-Erling Smørgrav 	fclose(fp);
16347b5038d7SDag-Erling Smørgrav 
16357b5038d7SDag-Erling Smørgrav 	if (i <= 0) {
1636*17d15b25SDag-Erling Smørgrav #ifdef STDERR_MSGS
16377b5038d7SDag-Erling Smørgrav 		fprintf(stderr, "nothing read from %s", filename);
1638*17d15b25SDag-Erling Smørgrav #endif
16397b5038d7SDag-Erling Smørgrav 		LDNS_FREE(line);
16407b5038d7SDag-Erling Smørgrav 		return NULL;
16417b5038d7SDag-Erling Smørgrav 	} else {
16427b5038d7SDag-Erling Smørgrav 		status = ldns_rr_new_frm_str(&r, line, 0, NULL, NULL);
16437b5038d7SDag-Erling Smørgrav 		if (status == LDNS_STATUS_OK && (ldns_rr_get_type(r) == LDNS_RR_TYPE_DNSKEY || ldns_rr_get_type(r) == LDNS_RR_TYPE_DS)) {
16447b5038d7SDag-Erling Smørgrav 			LDNS_FREE(line);
16457b5038d7SDag-Erling Smørgrav 			return r;
16467b5038d7SDag-Erling Smørgrav 		} else {
1647*17d15b25SDag-Erling Smørgrav #ifdef STDERR_MSGS
16487b5038d7SDag-Erling Smørgrav 			fprintf(stderr, "Error creating DNSKEY or DS rr from %s: %s\n", filename, ldns_get_errorstr_by_id(status));
1649*17d15b25SDag-Erling Smørgrav #endif
16507b5038d7SDag-Erling Smørgrav 			LDNS_FREE(line);
16517b5038d7SDag-Erling Smørgrav 			return NULL;
16527b5038d7SDag-Erling Smørgrav 		}
16537b5038d7SDag-Erling Smørgrav 	}
16547b5038d7SDag-Erling Smørgrav }
16557b5038d7SDag-Erling Smørgrav 
16567b5038d7SDag-Erling Smørgrav char *
16577b5038d7SDag-Erling Smørgrav ldns_key_get_file_base_name(ldns_key *key)
16587b5038d7SDag-Erling Smørgrav {
16597b5038d7SDag-Erling Smørgrav 	ldns_buffer *buffer;
16607b5038d7SDag-Erling Smørgrav 	char *file_base_name;
16617b5038d7SDag-Erling Smørgrav 
16627b5038d7SDag-Erling Smørgrav 	buffer = ldns_buffer_new(255);
16637b5038d7SDag-Erling Smørgrav 	ldns_buffer_printf(buffer, "K");
16647b5038d7SDag-Erling Smørgrav 	(void)ldns_rdf2buffer_str_dname(buffer, ldns_key_pubkey_owner(key));
16657b5038d7SDag-Erling Smørgrav 	ldns_buffer_printf(buffer,
16667b5038d7SDag-Erling Smørgrav 	                   "+%03u+%05u",
16677b5038d7SDag-Erling Smørgrav 			   ldns_key_algorithm(key),
16687b5038d7SDag-Erling Smørgrav 			   ldns_key_keytag(key));
16692787e39aSDag-Erling Smørgrav 	file_base_name = ldns_buffer_export(buffer);
16707b5038d7SDag-Erling Smørgrav 	ldns_buffer_free(buffer);
16717b5038d7SDag-Erling Smørgrav 	return file_base_name;
16727b5038d7SDag-Erling Smørgrav }
16737b5038d7SDag-Erling Smørgrav 
16747b5038d7SDag-Erling Smørgrav int ldns_key_algo_supported(int algo)
16757b5038d7SDag-Erling Smørgrav {
16767b5038d7SDag-Erling Smørgrav 	ldns_lookup_table *lt = ldns_signing_algorithms;
16777b5038d7SDag-Erling Smørgrav 	while(lt->name) {
16787b5038d7SDag-Erling Smørgrav 		if(lt->id == algo)
16797b5038d7SDag-Erling Smørgrav 			return 1;
16807b5038d7SDag-Erling Smørgrav 		lt++;
16817b5038d7SDag-Erling Smørgrav 	}
16827b5038d7SDag-Erling Smørgrav 	return 0;
16837b5038d7SDag-Erling Smørgrav }
16847b5038d7SDag-Erling Smørgrav 
16857b5038d7SDag-Erling Smørgrav ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name)
16867b5038d7SDag-Erling Smørgrav {
16877b5038d7SDag-Erling Smørgrav         /* list of (signing algorithm id, alias_name) */
16887b5038d7SDag-Erling Smørgrav         ldns_lookup_table aliases[] = {
16897b5038d7SDag-Erling Smørgrav                 /* from bind dnssec-keygen */
16907b5038d7SDag-Erling Smørgrav                 {LDNS_SIGN_HMACMD5, "HMAC-MD5"},
16917b5038d7SDag-Erling Smørgrav                 {LDNS_SIGN_DSA_NSEC3, "NSEC3DSA"},
16927b5038d7SDag-Erling Smørgrav                 {LDNS_SIGN_RSASHA1_NSEC3, "NSEC3RSASHA1"},
16937b5038d7SDag-Erling Smørgrav                 /* old ldns usage, now RFC names */
16947b5038d7SDag-Erling Smørgrav                 {LDNS_SIGN_DSA_NSEC3, "DSA_NSEC3" },
16957b5038d7SDag-Erling Smørgrav                 {LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1_NSEC3" },
16967b5038d7SDag-Erling Smørgrav #ifdef USE_GOST
16977b5038d7SDag-Erling Smørgrav                 {LDNS_SIGN_ECC_GOST, "GOST"},
16987b5038d7SDag-Erling Smørgrav #endif
16997b5038d7SDag-Erling Smørgrav                 /* compat with possible output */
17007b5038d7SDag-Erling Smørgrav                 {LDNS_DH, "DH"},
17017b5038d7SDag-Erling Smørgrav                 {LDNS_ECC, "ECC"},
17027b5038d7SDag-Erling Smørgrav                 {LDNS_INDIRECT, "INDIRECT"},
17037b5038d7SDag-Erling Smørgrav                 {LDNS_PRIVATEDNS, "PRIVATEDNS"},
17047b5038d7SDag-Erling Smørgrav                 {LDNS_PRIVATEOID, "PRIVATEOID"},
17057b5038d7SDag-Erling Smørgrav                 {0, NULL}};
17067b5038d7SDag-Erling Smørgrav         ldns_lookup_table* lt = ldns_signing_algorithms;
17077b5038d7SDag-Erling Smørgrav         while(lt->name) {
17087b5038d7SDag-Erling Smørgrav                 if(strcasecmp(lt->name, name) == 0)
17097b5038d7SDag-Erling Smørgrav                         return lt->id;
17107b5038d7SDag-Erling Smørgrav                 lt++;
17117b5038d7SDag-Erling Smørgrav         }
17127b5038d7SDag-Erling Smørgrav         lt = aliases;
17137b5038d7SDag-Erling Smørgrav         while(lt->name) {
17147b5038d7SDag-Erling Smørgrav                 if(strcasecmp(lt->name, name) == 0)
17157b5038d7SDag-Erling Smørgrav                         return lt->id;
17167b5038d7SDag-Erling Smørgrav                 lt++;
17177b5038d7SDag-Erling Smørgrav         }
17187b5038d7SDag-Erling Smørgrav         if(atoi(name) != 0)
17197b5038d7SDag-Erling Smørgrav                 return atoi(name);
17207b5038d7SDag-Erling Smørgrav         return 0;
17217b5038d7SDag-Erling Smørgrav }
1722