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 offset += length; 210 211 /* create the key and set its properties */ 212 if(!Q || !P || !G || !Y || !(dsa = DSA_new())) { 213 BN_free(Q); 214 BN_free(P); 215 BN_free(G); 216 BN_free(Y); 217 return NULL; 218 } 219 #ifndef S_SPLINT_S 220 dsa->p = P; 221 dsa->q = Q; 222 dsa->g = G; 223 dsa->pub_key = Y; 224 #endif /* splint */ 225 226 return dsa; 227 } 228 229 RSA * 230 sldns_key_buf2rsa_raw(unsigned char* key, size_t len) 231 { 232 uint16_t offset; 233 uint16_t exp; 234 uint16_t int16; 235 RSA *rsa; 236 BIGNUM *modulus; 237 BIGNUM *exponent; 238 239 if (len == 0) 240 return NULL; 241 if (key[0] == 0) { 242 if(len < 3) 243 return NULL; 244 memmove(&int16, key+1, 2); 245 exp = ntohs(int16); 246 offset = 3; 247 } else { 248 exp = key[0]; 249 offset = 1; 250 } 251 252 /* key length at least one */ 253 if(len < (size_t)offset + exp + 1) 254 return NULL; 255 256 /* Exponent */ 257 exponent = BN_new(); 258 if(!exponent) return NULL; 259 (void) BN_bin2bn(key+offset, (int)exp, exponent); 260 offset += exp; 261 262 /* Modulus */ 263 modulus = BN_new(); 264 if(!modulus) { 265 BN_free(exponent); 266 return NULL; 267 } 268 /* length of the buffer must match the key length! */ 269 (void) BN_bin2bn(key+offset, (int)(len - offset), modulus); 270 271 rsa = RSA_new(); 272 if(!rsa) { 273 BN_free(exponent); 274 BN_free(modulus); 275 return NULL; 276 } 277 #ifndef S_SPLINT_S 278 rsa->n = modulus; 279 rsa->e = exponent; 280 #endif /* splint */ 281 282 return rsa; 283 } 284 285 #ifdef USE_GOST 286 EVP_PKEY* 287 sldns_gost2pkey_raw(unsigned char* key, size_t keylen) 288 { 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; 296 if(keylen != 64) { 297 /* key wrong size */ 298 return NULL; 299 } 300 301 /* create evp_key */ 302 memmove(encoded, asn, 37); 303 memmove(encoded+37, key, 64); 304 pp = (unsigned char*)&encoded[0]; 305 306 return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded)); 307 } 308 #endif /* USE_GOST */ 309 310 #ifdef USE_ECDSA 311 EVP_PKEY* 312 sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo) 313 { 314 unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ 315 const unsigned char* pp = buf; 316 EVP_PKEY *evp_key; 317 EC_KEY *ec; 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); 325 } else ec = NULL; 326 if(!ec) return NULL; 327 if(keylen+1 > sizeof(buf)) { /* sanity check */ 328 EC_KEY_free(ec); 329 return NULL; 330 } 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)) { 336 EC_KEY_free(ec); 337 return NULL; 338 } 339 evp_key = EVP_PKEY_new(); 340 if(!evp_key) { 341 EC_KEY_free(ec); 342 return NULL; 343 } 344 if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) { 345 EVP_PKEY_free(evp_key); 346 EC_KEY_free(ec); 347 return NULL; 348 } 349 return evp_key; 350 } 351 #endif /* USE_ECDSA */ 352 353 int 354 sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest, 355 const EVP_MD* md) 356 { 357 EVP_MD_CTX* ctx; 358 ctx = EVP_MD_CTX_create(); 359 if(!ctx) 360 return 0; 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); 365 return 0; 366 } 367 EVP_MD_CTX_destroy(ctx); 368 return 1; 369 } 370 #endif /* HAVE_SSL */ 371