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 "ldns/keyraw.h"
15 #include "ldns/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>
29 sldns_rr_dnskey_key_size_raw(const unsigned char* keydata
,
30 const size_t len
, int alg
)
39 switch ((sldns_algorithm
)alg
) {
51 case LDNS_RSASHA1_NSEC3
:
57 if (keydata
[0] == 0) {
60 memmove(&int16
, keydata
+ 1, 2);
62 return (len
- exp
- 3)*8;
79 case LDNS_ECDSAP256SHA256
:
81 case LDNS_ECDSAP384SHA384
:
89 uint16_t sldns_calc_keytag_raw(uint8_t* key
, size_t keysize
)
94 /* look at the algorithm field, copied from 2535bis */
95 if (key
[3] == LDNS_RSAMD5
) {
98 memmove(&ac16
, key
+ keysize
- 3, 2);
101 return (uint16_t) ac16
;
105 for (i
= 0; i
< keysize
; ++i
) {
106 ac32
+= (i
& 1) ? key
[i
] : key
[i
] << 8;
108 ac32
+= (ac32
>> 16) & 0xFFFF;
109 return (uint16_t) (ac32
& 0xFFFF);
115 /** store GOST engine reference loaded into OpenSSL library */
116 ENGINE
* sldns_gost_engine
= NULL
;
119 sldns_key_EVP_load_gost_id(void)
121 static int gost_id
= 0;
122 const EVP_PKEY_ASN1_METHOD
* meth
;
125 if(gost_id
) return gost_id
;
127 /* see if configuration loaded gost implementation from other engine*/
128 meth
= EVP_PKEY_asn1_find_str(NULL
, "gost2001", -1);
130 EVP_PKEY_asn1_get0_info(&gost_id
, NULL
, NULL
, NULL
, NULL
, meth
);
134 /* see if engine can be loaded already */
135 e
= ENGINE_by_id("gost");
137 /* load it ourself, in case statically linked */
138 ENGINE_load_builtin_engines();
139 ENGINE_load_dynamic();
140 e
= ENGINE_by_id("gost");
143 /* no gost engine in openssl */
146 if(!ENGINE_set_default(e
, ENGINE_METHOD_ALL
)) {
152 meth
= EVP_PKEY_asn1_find_str(&e
, "gost2001", -1);
159 /* Note: do not ENGINE_finish and ENGINE_free the acquired engine
160 * on some platforms this frees up the meth and unloads gost stuff */
161 sldns_gost_engine
= e
;
163 EVP_PKEY_asn1_get0_info(&gost_id
, NULL
, NULL
, NULL
, NULL
, meth
);
167 void sldns_key_EVP_unload_gost(void)
169 if(sldns_gost_engine
) {
170 ENGINE_finish(sldns_gost_engine
);
171 ENGINE_free(sldns_gost_engine
);
172 sldns_gost_engine
= NULL
;
175 #endif /* USE_GOST */
178 sldns_key_buf2dsa_raw(unsigned char* key
, size_t len
)
184 BIGNUM
*Q
; BIGNUM
*P
;
185 BIGNUM
*G
; BIGNUM
*Y
;
190 length
= (64 + T
* 8);
196 if(len
< (size_t)1 + SHA_DIGEST_LENGTH
+ 3*length
)
199 Q
= BN_bin2bn(key
+offset
, SHA_DIGEST_LENGTH
, NULL
);
200 offset
+= SHA_DIGEST_LENGTH
;
202 P
= BN_bin2bn(key
+offset
, (int)length
, NULL
);
205 G
= BN_bin2bn(key
+offset
, (int)length
, NULL
);
208 Y
= BN_bin2bn(key
+offset
, (int)length
, NULL
);
211 /* create the key and set its properties */
212 if(!Q
|| !P
|| !G
|| !Y
|| !(dsa
= DSA_new())) {
230 sldns_key_buf2rsa_raw(unsigned char* key
, size_t len
)
244 memmove(&int16
, key
+1, 2);
252 /* key length at least one */
253 if(len
< (size_t)offset
+ exp
+ 1)
258 if(!exponent
) return NULL
;
259 (void) BN_bin2bn(key
+offset
, (int)exp
, exponent
);
268 /* length of the buffer must match the key length! */
269 (void) BN_bin2bn(key
+offset
, (int)(len
- offset
), modulus
);
287 sldns_gost2pkey_raw(unsigned char* key
, size_t keylen
)
289 /* prefix header for X509 encoding */
290 uint8_t asn
[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
291 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
292 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
293 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
294 unsigned char encoded
[37+64];
295 const unsigned char* pp
;
302 memmove(encoded
, asn
, 37);
303 memmove(encoded
+37, key
, 64);
304 pp
= (unsigned char*)&encoded
[0];
306 return d2i_PUBKEY(NULL
, &pp
, (int)sizeof(encoded
));
308 #endif /* USE_GOST */
312 sldns_ecdsa2pkey_raw(unsigned char* key
, size_t keylen
, uint8_t algo
)
314 unsigned char buf
[256+2]; /* sufficient for 2*384/8+1 */
315 const unsigned char* pp
= buf
;
318 /* check length, which uncompressed must be 2 bignums */
319 if(algo
== LDNS_ECDSAP256SHA256
) {
320 if(keylen
!= 2*256/8) return NULL
;
321 ec
= EC_KEY_new_by_curve_name(NID_X9_62_prime256v1
);
322 } else if(algo
== LDNS_ECDSAP384SHA384
) {
323 if(keylen
!= 2*384/8) return NULL
;
324 ec
= EC_KEY_new_by_curve_name(NID_secp384r1
);
327 if(keylen
+1 > sizeof(buf
)) { /* sanity check */
331 /* prepend the 0x02 (from docs) (or actually 0x04 from implementation
332 * of openssl) for uncompressed data */
333 buf
[0] = POINT_CONVERSION_UNCOMPRESSED
;
334 memmove(buf
+1, key
, keylen
);
335 if(!o2i_ECPublicKey(&ec
, &pp
, (int)keylen
+1)) {
339 evp_key
= EVP_PKEY_new();
344 if (!EVP_PKEY_assign_EC_KEY(evp_key
, ec
)) {
345 EVP_PKEY_free(evp_key
);
351 #endif /* USE_ECDSA */
354 sldns_digest_evp(unsigned char* data
, unsigned int len
, unsigned char* dest
,
358 ctx
= EVP_MD_CTX_create();
361 if(!EVP_DigestInit_ex(ctx
, md
, NULL
) ||
362 !EVP_DigestUpdate(ctx
, data
, len
) ||
363 !EVP_DigestFinal_ex(ctx
, dest
, NULL
)) {
364 EVP_MD_CTX_destroy(ctx
);
367 EVP_MD_CTX_destroy(ctx
);
370 #endif /* HAVE_SSL */