2 * keyraw.c - raw key operations and conversions
4 * (c) NLnet Labs, 2004-2008
6 * See the file LICENSE for the license
10 * Implementation of raw DNSKEY functions (work on wire rdata).
14 #include "sldns/keyraw.h"
15 #include "sldns/rrdef.h"
18 #include <openssl/ssl.h>
19 #include <openssl/evp.h>
20 #include <openssl/rand.h>
21 #include <openssl/err.h>
22 #include <openssl/md5.h>
23 #ifdef HAVE_OPENSSL_ENGINE_H
24 # include <openssl/engine.h>
26 #ifdef HAVE_OPENSSL_BN_H
27 #include <openssl/bn.h>
29 #ifdef HAVE_OPENSSL_RSA_H
30 #include <openssl/rsa.h>
32 #ifdef HAVE_OPENSSL_DSA_H
33 #include <openssl/dsa.h>
38 sldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
39 const size_t len, int alg)
48 switch ((sldns_algorithm)alg) {
60 case LDNS_RSASHA1_NSEC3:
66 if (keydata[0] == 0) {
69 memmove(&int16, keydata + 1, 2);
71 return (len - exp - 3)*8;
88 case LDNS_ECDSAP256SHA256:
90 case LDNS_ECDSAP384SHA384:
106 uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize)
111 /* look at the algorithm field, copied from 2535bis */
112 if (key[3] == LDNS_RSAMD5) {
115 memmove(&ac16, key + keysize - 3, 2);
118 return (uint16_t) ac16;
122 for (i = 0; i < keysize; ++i) {
123 ac32 += (i & 1) ? key[i] : key[i] << 8;
125 ac32 += (ac32 >> 16) & 0xFFFF;
126 return (uint16_t) (ac32 & 0xFFFF);
132 /** store GOST engine reference loaded into OpenSSL library */
133 ENGINE* sldns_gost_engine = NULL;
136 sldns_key_EVP_load_gost_id(void)
138 static int gost_id = 0;
139 const EVP_PKEY_ASN1_METHOD* meth;
142 if(gost_id) return gost_id;
144 /* see if configuration loaded gost implementation from other engine*/
145 meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
147 EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
151 /* see if engine can be loaded already */
152 e = ENGINE_by_id("gost");
154 /* load it ourself, in case statically linked */
155 ENGINE_load_builtin_engines();
156 ENGINE_load_dynamic();
157 e = ENGINE_by_id("gost");
160 /* no gost engine in openssl */
163 if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
169 meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
176 /* Note: do not ENGINE_finish and ENGINE_free the acquired engine
177 * on some platforms this frees up the meth and unloads gost stuff */
178 sldns_gost_engine = e;
180 EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
184 void sldns_key_EVP_unload_gost(void)
186 if(sldns_gost_engine) {
187 ENGINE_finish(sldns_gost_engine);
188 ENGINE_free(sldns_gost_engine);
189 sldns_gost_engine = NULL;
192 #endif /* USE_GOST */
195 sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
201 BIGNUM *Q; BIGNUM *P;
202 BIGNUM *G; BIGNUM *Y;
207 length = (64 + T * 8);
213 if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
216 Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
217 offset += SHA_DIGEST_LENGTH;
219 P = BN_bin2bn(key+offset, (int)length, NULL);
222 G = BN_bin2bn(key+offset, (int)length, NULL);
225 Y = BN_bin2bn(key+offset, (int)length, NULL);
227 /* create the key and set its properties */
228 if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
235 #if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
243 #else /* OPENSSL_VERSION_NUMBER */
244 if (!DSA_set0_pqg(dsa, P, Q, G)) {
245 /* QPG not yet attached, need to free */
254 if (!DSA_set0_key(dsa, Y, NULL)) {
255 /* QPG attached, cleaned up by DSA_fre() */
266 sldns_key_buf2rsa_raw(unsigned char* key, size_t len)
280 memmove(&int16, key+1, 2);
288 /* key length at least one */
289 if(len < (size_t)offset + exp + 1)
294 if(!exponent) return NULL;
295 (void) BN_bin2bn(key+offset, (int)exp, exponent);
304 /* length of the buffer must match the key length! */
305 (void) BN_bin2bn(key+offset, (int)(len - offset), modulus);
313 #if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
319 #else /* OPENSSL_VERSION_NUMBER */
320 if (!RSA_set0_key(rsa, modulus, exponent, NULL)) {
333 sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
335 /* prefix header for X509 encoding */
336 uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
337 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
338 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
339 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
340 unsigned char encoded[37+64];
341 const unsigned char* pp;
348 memmove(encoded, asn, 37);
349 memmove(encoded+37, key, 64);
350 pp = (unsigned char*)&encoded[0];
352 return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
354 #endif /* USE_GOST */
358 sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
360 unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
361 const unsigned char* pp = buf;
364 /* check length, which uncompressed must be 2 bignums */
365 if(algo == LDNS_ECDSAP256SHA256) {
366 if(keylen != 2*256/8) return NULL;
367 ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
368 } else if(algo == LDNS_ECDSAP384SHA384) {
369 if(keylen != 2*384/8) return NULL;
370 ec = EC_KEY_new_by_curve_name(NID_secp384r1);
373 if(keylen+1 > sizeof(buf)) { /* sanity check */
377 /* prepend the 0x02 (from docs) (or actually 0x04 from implementation
378 * of openssl) for uncompressed data */
379 buf[0] = POINT_CONVERSION_UNCOMPRESSED;
380 memmove(buf+1, key, keylen);
381 if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
385 evp_key = EVP_PKEY_new();
390 if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
391 EVP_PKEY_free(evp_key);
397 #endif /* USE_ECDSA */
401 sldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
403 /* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
404 uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
405 0x70, 0x03, 0x21, 0x00};
409 /* pp gets modified by d2i() */
410 const unsigned char* pp = (unsigned char*)buf;
411 if(keylen != 32 || keylen + pre_len > sizeof(buf))
412 return NULL; /* wrong length */
413 memmove(buf, pre, pre_len);
414 memmove(buf+pre_len, key, keylen);
415 evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
418 #endif /* USE_ED25519 */
422 sldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
424 /* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
425 uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
426 0x71, 0x03, 0x3a, 0x00};
430 /* pp gets modified by d2i() */
431 const unsigned char* pp = (unsigned char*)buf;
432 if(keylen != 57 || keylen + pre_len > sizeof(buf))
433 return NULL; /* wrong length */
434 memmove(buf, pre, pre_len);
435 memmove(buf+pre_len, key, keylen);
436 evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
439 #endif /* USE_ED448 */
442 sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
446 ctx = EVP_MD_CTX_create();
449 if(!EVP_DigestInit_ex(ctx, md, NULL) ||
450 !EVP_DigestUpdate(ctx, data, len) ||
451 !EVP_DigestFinal_ex(ctx, dest, NULL)) {
452 EVP_MD_CTX_destroy(ctx);
455 EVP_MD_CTX_destroy(ctx);
458 #endif /* HAVE_SSL */