1 /* 2 * keyraw.c - raw key operations and conversions 3 * 4 * (c) NLnet Labs, 2004-2008 5 * 6 * See the file LICENSE for the license 7 */ 8 /** 9 * \file 10 * Implementation of raw DNSKEY functions (work on wire rdata). 11 */ 12 13 #include "config.h" 14 #include "sldns/keyraw.h" 15 #include "sldns/rrdef.h" 16 17 #ifdef HAVE_SSL 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> 25 #endif 26 #endif /* HAVE_SSL */ 27 28 size_t 29 sldns_rr_dnskey_key_size_raw(const unsigned char* keydata, 30 const size_t len, int alg) 31 { 32 /* for DSA keys */ 33 uint8_t t; 34 35 /* for RSA keys */ 36 uint16_t exp; 37 uint16_t int16; 38 39 switch ((sldns_algorithm)alg) { 40 case LDNS_DSA: 41 case LDNS_DSA_NSEC3: 42 if (len > 0) { 43 t = keydata[0]; 44 return (64 + t*8)*8; 45 } else { 46 return 0; 47 } 48 break; 49 case LDNS_RSAMD5: 50 case LDNS_RSASHA1: 51 case LDNS_RSASHA1_NSEC3: 52 #ifdef USE_SHA2 53 case LDNS_RSASHA256: 54 case LDNS_RSASHA512: 55 #endif 56 if (len > 0) { 57 if (keydata[0] == 0) { 58 /* big exponent */ 59 if (len > 3) { 60 memmove(&int16, keydata + 1, 2); 61 exp = ntohs(int16); 62 return (len - exp - 3)*8; 63 } else { 64 return 0; 65 } 66 } else { 67 exp = keydata[0]; 68 return (len-exp-1)*8; 69 } 70 } else { 71 return 0; 72 } 73 break; 74 #ifdef USE_GOST 75 case LDNS_ECC_GOST: 76 return 512; 77 #endif 78 #ifdef USE_ECDSA 79 case LDNS_ECDSAP256SHA256: 80 return 256; 81 case LDNS_ECDSAP384SHA384: 82 return 384; 83 #endif 84 default: 85 return 0; 86 } 87 } 88 89 uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize) 90 { 91 if(keysize < 4) { 92 return 0; 93 } 94 /* look at the algorithm field, copied from 2535bis */ 95 if (key[3] == LDNS_RSAMD5) { 96 uint16_t ac16 = 0; 97 if (keysize > 4) { 98 memmove(&ac16, key + keysize - 3, 2); 99 } 100 ac16 = ntohs(ac16); 101 return (uint16_t) ac16; 102 } else { 103 size_t i; 104 uint32_t ac32 = 0; 105 for (i = 0; i < keysize; ++i) { 106 ac32 += (i & 1) ? key[i] : key[i] << 8; 107 } 108 ac32 += (ac32 >> 16) & 0xFFFF; 109 return (uint16_t) (ac32 & 0xFFFF); 110 } 111 } 112 113 #ifdef HAVE_SSL 114 #ifdef USE_GOST 115 /** store GOST engine reference loaded into OpenSSL library */ 116 ENGINE* sldns_gost_engine = NULL; 117 118 int 119 sldns_key_EVP_load_gost_id(void) 120 { 121 static int gost_id = 0; 122 const EVP_PKEY_ASN1_METHOD* meth; 123 ENGINE* e; 124 125 if(gost_id) return gost_id; 126 127 /* see if configuration loaded gost implementation from other engine*/ 128 meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1); 129 if(meth) { 130 EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); 131 return gost_id; 132 } 133 134 /* see if engine can be loaded already */ 135 e = ENGINE_by_id("gost"); 136 if(!e) { 137 /* load it ourself, in case statically linked */ 138 ENGINE_load_builtin_engines(); 139 ENGINE_load_dynamic(); 140 e = ENGINE_by_id("gost"); 141 } 142 if(!e) { 143 /* no gost engine in openssl */ 144 return 0; 145 } 146 if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { 147 ENGINE_finish(e); 148 ENGINE_free(e); 149 return 0; 150 } 151 152 meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1); 153 if(!meth) { 154 /* algo not found */ 155 ENGINE_finish(e); 156 ENGINE_free(e); 157 return 0; 158 } 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; 162 163 EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); 164 return gost_id; 165 } 166 167 void sldns_key_EVP_unload_gost(void) 168 { 169 if(sldns_gost_engine) { 170 ENGINE_finish(sldns_gost_engine); 171 ENGINE_free(sldns_gost_engine); 172 sldns_gost_engine = NULL; 173 } 174 } 175 #endif /* USE_GOST */ 176 177 DSA * 178 sldns_key_buf2dsa_raw(unsigned char* key, size_t len) 179 { 180 uint8_t T; 181 uint16_t length; 182 uint16_t offset; 183 DSA *dsa; 184 BIGNUM *Q; BIGNUM *P; 185 BIGNUM *G; BIGNUM *Y; 186 187 if(len == 0) 188 return NULL; 189 T = (uint8_t)key[0]; 190 length = (64 + T * 8); 191 offset = 1; 192 193 if (T > 8) { 194 return NULL; 195 } 196 if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length) 197 return NULL; 198 199 Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL); 200 offset += SHA_DIGEST_LENGTH; 201 202 P = BN_bin2bn(key+offset, (int)length, NULL); 203 offset += length; 204 205 G = BN_bin2bn(key+offset, (int)length, NULL); 206 offset += length; 207 208 Y = BN_bin2bn(key+offset, (int)length, NULL); 209 210 /* create the key and set its properties */ 211 if(!Q || !P || !G || !Y || !(dsa = DSA_new())) { 212 BN_free(Q); 213 BN_free(P); 214 BN_free(G); 215 BN_free(Y); 216 return NULL; 217 } 218 #ifndef S_SPLINT_S 219 dsa->p = P; 220 dsa->q = Q; 221 dsa->g = G; 222 dsa->pub_key = Y; 223 #endif /* splint */ 224 225 return dsa; 226 } 227 228 RSA * 229 sldns_key_buf2rsa_raw(unsigned char* key, size_t len) 230 { 231 uint16_t offset; 232 uint16_t exp; 233 uint16_t int16; 234 RSA *rsa; 235 BIGNUM *modulus; 236 BIGNUM *exponent; 237 238 if (len == 0) 239 return NULL; 240 if (key[0] == 0) { 241 if(len < 3) 242 return NULL; 243 memmove(&int16, key+1, 2); 244 exp = ntohs(int16); 245 offset = 3; 246 } else { 247 exp = key[0]; 248 offset = 1; 249 } 250 251 /* key length at least one */ 252 if(len < (size_t)offset + exp + 1) 253 return NULL; 254 255 /* Exponent */ 256 exponent = BN_new(); 257 if(!exponent) return NULL; 258 (void) BN_bin2bn(key+offset, (int)exp, exponent); 259 offset += exp; 260 261 /* Modulus */ 262 modulus = BN_new(); 263 if(!modulus) { 264 BN_free(exponent); 265 return NULL; 266 } 267 /* length of the buffer must match the key length! */ 268 (void) BN_bin2bn(key+offset, (int)(len - offset), modulus); 269 270 rsa = RSA_new(); 271 if(!rsa) { 272 BN_free(exponent); 273 BN_free(modulus); 274 return NULL; 275 } 276 #ifndef S_SPLINT_S 277 rsa->n = modulus; 278 rsa->e = exponent; 279 #endif /* splint */ 280 281 return rsa; 282 } 283 284 #ifdef USE_GOST 285 EVP_PKEY* 286 sldns_gost2pkey_raw(unsigned char* key, size_t keylen) 287 { 288 /* prefix header for X509 encoding */ 289 uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, 290 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, 291 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 292 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40}; 293 unsigned char encoded[37+64]; 294 const unsigned char* pp; 295 if(keylen != 64) { 296 /* key wrong size */ 297 return NULL; 298 } 299 300 /* create evp_key */ 301 memmove(encoded, asn, 37); 302 memmove(encoded+37, key, 64); 303 pp = (unsigned char*)&encoded[0]; 304 305 return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded)); 306 } 307 #endif /* USE_GOST */ 308 309 #ifdef USE_ECDSA 310 EVP_PKEY* 311 sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo) 312 { 313 unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ 314 const unsigned char* pp = buf; 315 EVP_PKEY *evp_key; 316 EC_KEY *ec; 317 /* check length, which uncompressed must be 2 bignums */ 318 if(algo == LDNS_ECDSAP256SHA256) { 319 if(keylen != 2*256/8) return NULL; 320 ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 321 } else if(algo == LDNS_ECDSAP384SHA384) { 322 if(keylen != 2*384/8) return NULL; 323 ec = EC_KEY_new_by_curve_name(NID_secp384r1); 324 } else ec = NULL; 325 if(!ec) return NULL; 326 if(keylen+1 > sizeof(buf)) { /* sanity check */ 327 EC_KEY_free(ec); 328 return NULL; 329 } 330 /* prepend the 0x02 (from docs) (or actually 0x04 from implementation 331 * of openssl) for uncompressed data */ 332 buf[0] = POINT_CONVERSION_UNCOMPRESSED; 333 memmove(buf+1, key, keylen); 334 if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) { 335 EC_KEY_free(ec); 336 return NULL; 337 } 338 evp_key = EVP_PKEY_new(); 339 if(!evp_key) { 340 EC_KEY_free(ec); 341 return NULL; 342 } 343 if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) { 344 EVP_PKEY_free(evp_key); 345 EC_KEY_free(ec); 346 return NULL; 347 } 348 return evp_key; 349 } 350 #endif /* USE_ECDSA */ 351 352 int 353 sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest, 354 const EVP_MD* md) 355 { 356 EVP_MD_CTX* ctx; 357 ctx = EVP_MD_CTX_create(); 358 if(!ctx) 359 return 0; 360 if(!EVP_DigestInit_ex(ctx, md, NULL) || 361 !EVP_DigestUpdate(ctx, data, len) || 362 !EVP_DigestFinal_ex(ctx, dest, NULL)) { 363 EVP_MD_CTX_destroy(ctx); 364 return 0; 365 } 366 EVP_MD_CTX_destroy(ctx); 367 return 1; 368 } 369 #endif /* HAVE_SSL */ 370