1266077Sdes/* 2266077Sdes * keyraw.c - raw key operations and conversions 3266077Sdes * 4266077Sdes * (c) NLnet Labs, 2004-2008 5266077Sdes * 6266077Sdes * See the file LICENSE for the license 7266077Sdes */ 8266077Sdes/** 9266077Sdes * \file 10266077Sdes * Implementation of raw DNSKEY functions (work on wire rdata). 11266077Sdes */ 12266077Sdes 13266077Sdes#include "config.h" 14287915Sdes#include "sldns/keyraw.h" 15287915Sdes#include "sldns/rrdef.h" 16266077Sdes 17266077Sdes#ifdef HAVE_SSL 18266077Sdes#include <openssl/ssl.h> 19266077Sdes#include <openssl/evp.h> 20266077Sdes#include <openssl/rand.h> 21266077Sdes#include <openssl/err.h> 22266077Sdes#include <openssl/md5.h> 23266077Sdes#ifdef HAVE_OPENSSL_ENGINE_H 24266077Sdes# include <openssl/engine.h> 25266077Sdes#endif 26307729Sdes#ifdef HAVE_OPENSSL_BN_H 27307729Sdes#include <openssl/bn.h> 28307729Sdes#endif 29307729Sdes#ifdef HAVE_OPENSSL_RSA_H 30307729Sdes#include <openssl/rsa.h> 31307729Sdes#endif 32307729Sdes#ifdef HAVE_OPENSSL_DSA_H 33307729Sdes#include <openssl/dsa.h> 34307729Sdes#endif 35266077Sdes#endif /* HAVE_SSL */ 36266077Sdes 37266077Sdessize_t 38266077Sdessldns_rr_dnskey_key_size_raw(const unsigned char* keydata, 39266077Sdes const size_t len, int alg) 40266077Sdes{ 41266077Sdes /* for DSA keys */ 42266077Sdes uint8_t t; 43266077Sdes 44266077Sdes /* for RSA keys */ 45266077Sdes uint16_t exp; 46266077Sdes uint16_t int16; 47266077Sdes 48266077Sdes switch ((sldns_algorithm)alg) { 49266077Sdes case LDNS_DSA: 50266077Sdes case LDNS_DSA_NSEC3: 51266077Sdes if (len > 0) { 52266077Sdes t = keydata[0]; 53266077Sdes return (64 + t*8)*8; 54266077Sdes } else { 55266077Sdes return 0; 56266077Sdes } 57266077Sdes break; 58266077Sdes case LDNS_RSAMD5: 59266077Sdes case LDNS_RSASHA1: 60266077Sdes case LDNS_RSASHA1_NSEC3: 61266077Sdes#ifdef USE_SHA2 62266077Sdes case LDNS_RSASHA256: 63266077Sdes case LDNS_RSASHA512: 64266077Sdes#endif 65266077Sdes if (len > 0) { 66266077Sdes if (keydata[0] == 0) { 67266077Sdes /* big exponent */ 68266077Sdes if (len > 3) { 69266077Sdes memmove(&int16, keydata + 1, 2); 70266077Sdes exp = ntohs(int16); 71266077Sdes return (len - exp - 3)*8; 72266077Sdes } else { 73266077Sdes return 0; 74266077Sdes } 75266077Sdes } else { 76266077Sdes exp = keydata[0]; 77266077Sdes return (len-exp-1)*8; 78266077Sdes } 79266077Sdes } else { 80266077Sdes return 0; 81266077Sdes } 82266077Sdes break; 83266077Sdes#ifdef USE_GOST 84266077Sdes case LDNS_ECC_GOST: 85266077Sdes return 512; 86266077Sdes#endif 87266077Sdes#ifdef USE_ECDSA 88266077Sdes case LDNS_ECDSAP256SHA256: 89266077Sdes return 256; 90266077Sdes case LDNS_ECDSAP384SHA384: 91266077Sdes return 384; 92266077Sdes#endif 93356345Scy#ifdef USE_ED25519 94356345Scy case LDNS_ED25519: 95356345Scy return 256; 96356345Scy#endif 97356345Scy#ifdef USE_ED448 98356345Scy case LDNS_ED448: 99356345Scy return 456; 100356345Scy#endif 101266077Sdes default: 102266077Sdes return 0; 103266077Sdes } 104266077Sdes} 105266077Sdes 106266077Sdesuint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize) 107266077Sdes{ 108266077Sdes if(keysize < 4) { 109266077Sdes return 0; 110266077Sdes } 111266077Sdes /* look at the algorithm field, copied from 2535bis */ 112266077Sdes if (key[3] == LDNS_RSAMD5) { 113266077Sdes uint16_t ac16 = 0; 114266077Sdes if (keysize > 4) { 115266077Sdes memmove(&ac16, key + keysize - 3, 2); 116266077Sdes } 117266077Sdes ac16 = ntohs(ac16); 118266077Sdes return (uint16_t) ac16; 119266077Sdes } else { 120266077Sdes size_t i; 121266077Sdes uint32_t ac32 = 0; 122266077Sdes for (i = 0; i < keysize; ++i) { 123266077Sdes ac32 += (i & 1) ? key[i] : key[i] << 8; 124266077Sdes } 125266077Sdes ac32 += (ac32 >> 16) & 0xFFFF; 126266077Sdes return (uint16_t) (ac32 & 0xFFFF); 127266077Sdes } 128266077Sdes} 129266077Sdes 130266077Sdes#ifdef HAVE_SSL 131266077Sdes#ifdef USE_GOST 132266077Sdes/** store GOST engine reference loaded into OpenSSL library */ 133266077SdesENGINE* sldns_gost_engine = NULL; 134266077Sdes 135266077Sdesint 136266077Sdessldns_key_EVP_load_gost_id(void) 137266077Sdes{ 138266077Sdes static int gost_id = 0; 139266077Sdes const EVP_PKEY_ASN1_METHOD* meth; 140266077Sdes ENGINE* e; 141266077Sdes 142266077Sdes if(gost_id) return gost_id; 143266077Sdes 144266077Sdes /* see if configuration loaded gost implementation from other engine*/ 145266077Sdes meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1); 146266077Sdes if(meth) { 147266077Sdes EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); 148266077Sdes return gost_id; 149266077Sdes } 150266077Sdes 151266077Sdes /* see if engine can be loaded already */ 152266077Sdes e = ENGINE_by_id("gost"); 153266077Sdes if(!e) { 154266077Sdes /* load it ourself, in case statically linked */ 155266077Sdes ENGINE_load_builtin_engines(); 156266077Sdes ENGINE_load_dynamic(); 157266077Sdes e = ENGINE_by_id("gost"); 158266077Sdes } 159266077Sdes if(!e) { 160266077Sdes /* no gost engine in openssl */ 161266077Sdes return 0; 162266077Sdes } 163266077Sdes if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { 164266077Sdes ENGINE_finish(e); 165266077Sdes ENGINE_free(e); 166266077Sdes return 0; 167266077Sdes } 168266077Sdes 169266077Sdes meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1); 170266077Sdes if(!meth) { 171266077Sdes /* algo not found */ 172266077Sdes ENGINE_finish(e); 173266077Sdes ENGINE_free(e); 174266077Sdes return 0; 175266077Sdes } 176266077Sdes /* Note: do not ENGINE_finish and ENGINE_free the acquired engine 177266077Sdes * on some platforms this frees up the meth and unloads gost stuff */ 178266077Sdes sldns_gost_engine = e; 179266077Sdes 180266077Sdes EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); 181266077Sdes return gost_id; 182266077Sdes} 183266077Sdes 184266077Sdesvoid sldns_key_EVP_unload_gost(void) 185266077Sdes{ 186266077Sdes if(sldns_gost_engine) { 187266077Sdes ENGINE_finish(sldns_gost_engine); 188266077Sdes ENGINE_free(sldns_gost_engine); 189266077Sdes sldns_gost_engine = NULL; 190266077Sdes } 191266077Sdes} 192266077Sdes#endif /* USE_GOST */ 193266077Sdes 194266077SdesDSA * 195266077Sdessldns_key_buf2dsa_raw(unsigned char* key, size_t len) 196266077Sdes{ 197266077Sdes uint8_t T; 198266077Sdes uint16_t length; 199266077Sdes uint16_t offset; 200266077Sdes DSA *dsa; 201266077Sdes BIGNUM *Q; BIGNUM *P; 202266077Sdes BIGNUM *G; BIGNUM *Y; 203266077Sdes 204266077Sdes if(len == 0) 205266077Sdes return NULL; 206266077Sdes T = (uint8_t)key[0]; 207266077Sdes length = (64 + T * 8); 208266077Sdes offset = 1; 209266077Sdes 210266077Sdes if (T > 8) { 211266077Sdes return NULL; 212266077Sdes } 213266077Sdes if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length) 214266077Sdes return NULL; 215266077Sdes 216266077Sdes Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL); 217266077Sdes offset += SHA_DIGEST_LENGTH; 218266077Sdes 219266077Sdes P = BN_bin2bn(key+offset, (int)length, NULL); 220266077Sdes offset += length; 221266077Sdes 222266077Sdes G = BN_bin2bn(key+offset, (int)length, NULL); 223266077Sdes offset += length; 224266077Sdes 225266077Sdes Y = BN_bin2bn(key+offset, (int)length, NULL); 226266077Sdes 227266077Sdes /* create the key and set its properties */ 228266077Sdes if(!Q || !P || !G || !Y || !(dsa = DSA_new())) { 229266077Sdes BN_free(Q); 230266077Sdes BN_free(P); 231266077Sdes BN_free(G); 232266077Sdes BN_free(Y); 233266077Sdes return NULL; 234266077Sdes } 235307729Sdes#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) 236266077Sdes#ifndef S_SPLINT_S 237266077Sdes dsa->p = P; 238266077Sdes dsa->q = Q; 239266077Sdes dsa->g = G; 240266077Sdes dsa->pub_key = Y; 241266077Sdes#endif /* splint */ 242266077Sdes 243307729Sdes#else /* OPENSSL_VERSION_NUMBER */ 244307729Sdes if (!DSA_set0_pqg(dsa, P, Q, G)) { 245307729Sdes /* QPG not yet attached, need to free */ 246307729Sdes BN_free(Q); 247307729Sdes BN_free(P); 248307729Sdes BN_free(G); 249307729Sdes 250307729Sdes DSA_free(dsa); 251307729Sdes BN_free(Y); 252307729Sdes return NULL; 253307729Sdes } 254307729Sdes if (!DSA_set0_key(dsa, Y, NULL)) { 255307729Sdes /* QPG attached, cleaned up by DSA_fre() */ 256307729Sdes DSA_free(dsa); 257307729Sdes BN_free(Y); 258307729Sdes return NULL; 259307729Sdes } 260307729Sdes#endif 261307729Sdes 262266077Sdes return dsa; 263266077Sdes} 264266077Sdes 265266077SdesRSA * 266266077Sdessldns_key_buf2rsa_raw(unsigned char* key, size_t len) 267266077Sdes{ 268266077Sdes uint16_t offset; 269266077Sdes uint16_t exp; 270266077Sdes uint16_t int16; 271266077Sdes RSA *rsa; 272266077Sdes BIGNUM *modulus; 273266077Sdes BIGNUM *exponent; 274266077Sdes 275266077Sdes if (len == 0) 276266077Sdes return NULL; 277266077Sdes if (key[0] == 0) { 278266077Sdes if(len < 3) 279266077Sdes return NULL; 280266077Sdes memmove(&int16, key+1, 2); 281266077Sdes exp = ntohs(int16); 282266077Sdes offset = 3; 283266077Sdes } else { 284266077Sdes exp = key[0]; 285266077Sdes offset = 1; 286266077Sdes } 287266077Sdes 288266077Sdes /* key length at least one */ 289266077Sdes if(len < (size_t)offset + exp + 1) 290266077Sdes return NULL; 291266077Sdes 292266077Sdes /* Exponent */ 293266077Sdes exponent = BN_new(); 294266077Sdes if(!exponent) return NULL; 295266077Sdes (void) BN_bin2bn(key+offset, (int)exp, exponent); 296266077Sdes offset += exp; 297266077Sdes 298266077Sdes /* Modulus */ 299266077Sdes modulus = BN_new(); 300266077Sdes if(!modulus) { 301266077Sdes BN_free(exponent); 302266077Sdes return NULL; 303266077Sdes } 304266077Sdes /* length of the buffer must match the key length! */ 305266077Sdes (void) BN_bin2bn(key+offset, (int)(len - offset), modulus); 306266077Sdes 307266077Sdes rsa = RSA_new(); 308266077Sdes if(!rsa) { 309266077Sdes BN_free(exponent); 310266077Sdes BN_free(modulus); 311266077Sdes return NULL; 312266077Sdes } 313307729Sdes#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) 314266077Sdes#ifndef S_SPLINT_S 315266077Sdes rsa->n = modulus; 316266077Sdes rsa->e = exponent; 317266077Sdes#endif /* splint */ 318266077Sdes 319307729Sdes#else /* OPENSSL_VERSION_NUMBER */ 320307729Sdes if (!RSA_set0_key(rsa, modulus, exponent, NULL)) { 321307729Sdes BN_free(exponent); 322307729Sdes BN_free(modulus); 323307729Sdes RSA_free(rsa); 324307729Sdes return NULL; 325307729Sdes } 326307729Sdes#endif 327307729Sdes 328266077Sdes return rsa; 329266077Sdes} 330266077Sdes 331266077Sdes#ifdef USE_GOST 332266077SdesEVP_PKEY* 333266077Sdessldns_gost2pkey_raw(unsigned char* key, size_t keylen) 334266077Sdes{ 335266077Sdes /* prefix header for X509 encoding */ 336266077Sdes uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, 337266077Sdes 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, 338266077Sdes 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 339266077Sdes 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40}; 340266077Sdes unsigned char encoded[37+64]; 341266077Sdes const unsigned char* pp; 342266077Sdes if(keylen != 64) { 343266077Sdes /* key wrong size */ 344266077Sdes return NULL; 345266077Sdes } 346266077Sdes 347266077Sdes /* create evp_key */ 348266077Sdes memmove(encoded, asn, 37); 349266077Sdes memmove(encoded+37, key, 64); 350266077Sdes pp = (unsigned char*)&encoded[0]; 351266077Sdes 352266077Sdes return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded)); 353266077Sdes} 354266077Sdes#endif /* USE_GOST */ 355266077Sdes 356266077Sdes#ifdef USE_ECDSA 357266077SdesEVP_PKEY* 358266077Sdessldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo) 359266077Sdes{ 360266077Sdes unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ 361266077Sdes const unsigned char* pp = buf; 362266077Sdes EVP_PKEY *evp_key; 363266077Sdes EC_KEY *ec; 364266077Sdes /* check length, which uncompressed must be 2 bignums */ 365266077Sdes if(algo == LDNS_ECDSAP256SHA256) { 366266077Sdes if(keylen != 2*256/8) return NULL; 367266077Sdes ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 368266077Sdes } else if(algo == LDNS_ECDSAP384SHA384) { 369266077Sdes if(keylen != 2*384/8) return NULL; 370266077Sdes ec = EC_KEY_new_by_curve_name(NID_secp384r1); 371266077Sdes } else ec = NULL; 372266077Sdes if(!ec) return NULL; 373276541Sdes if(keylen+1 > sizeof(buf)) { /* sanity check */ 374276541Sdes EC_KEY_free(ec); 375276541Sdes return NULL; 376276541Sdes } 377266077Sdes /* prepend the 0x02 (from docs) (or actually 0x04 from implementation 378266077Sdes * of openssl) for uncompressed data */ 379266077Sdes buf[0] = POINT_CONVERSION_UNCOMPRESSED; 380266077Sdes memmove(buf+1, key, keylen); 381266077Sdes if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) { 382266077Sdes EC_KEY_free(ec); 383266077Sdes return NULL; 384266077Sdes } 385266077Sdes evp_key = EVP_PKEY_new(); 386266077Sdes if(!evp_key) { 387266077Sdes EC_KEY_free(ec); 388266077Sdes return NULL; 389266077Sdes } 390266077Sdes if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) { 391266077Sdes EVP_PKEY_free(evp_key); 392266077Sdes EC_KEY_free(ec); 393266077Sdes return NULL; 394266077Sdes } 395266077Sdes return evp_key; 396266077Sdes} 397266077Sdes#endif /* USE_ECDSA */ 398266077Sdes 399356345Scy#ifdef USE_ED25519 400356345ScyEVP_PKEY* 401356345Scysldns_ed255192pkey_raw(const unsigned char* key, size_t keylen) 402356345Scy{ 403356345Scy /* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */ 404356345Scy uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 405356345Scy 0x70, 0x03, 0x21, 0x00}; 406356345Scy int pre_len = 12; 407356345Scy uint8_t buf[256]; 408356345Scy EVP_PKEY *evp_key; 409356345Scy /* pp gets modified by d2i() */ 410356345Scy const unsigned char* pp = (unsigned char*)buf; 411356345Scy if(keylen != 32 || keylen + pre_len > sizeof(buf)) 412356345Scy return NULL; /* wrong length */ 413356345Scy memmove(buf, pre, pre_len); 414356345Scy memmove(buf+pre_len, key, keylen); 415356345Scy evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen)); 416356345Scy return evp_key; 417356345Scy} 418356345Scy#endif /* USE_ED25519 */ 419356345Scy 420356345Scy#ifdef USE_ED448 421356345ScyEVP_PKEY* 422356345Scysldns_ed4482pkey_raw(const unsigned char* key, size_t keylen) 423356345Scy{ 424356345Scy /* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */ 425356345Scy uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 426356345Scy 0x71, 0x03, 0x3a, 0x00}; 427356345Scy int pre_len = 12; 428356345Scy uint8_t buf[256]; 429356345Scy EVP_PKEY *evp_key; 430356345Scy /* pp gets modified by d2i() */ 431356345Scy const unsigned char* pp = (unsigned char*)buf; 432356345Scy if(keylen != 57 || keylen + pre_len > sizeof(buf)) 433356345Scy return NULL; /* wrong length */ 434356345Scy memmove(buf, pre, pre_len); 435356345Scy memmove(buf+pre_len, key, keylen); 436356345Scy evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen)); 437356345Scy return evp_key; 438356345Scy} 439356345Scy#endif /* USE_ED448 */ 440356345Scy 441266077Sdesint 442266077Sdessldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest, 443266077Sdes const EVP_MD* md) 444266077Sdes{ 445266077Sdes EVP_MD_CTX* ctx; 446266077Sdes ctx = EVP_MD_CTX_create(); 447266077Sdes if(!ctx) 448266077Sdes return 0; 449266077Sdes if(!EVP_DigestInit_ex(ctx, md, NULL) || 450266077Sdes !EVP_DigestUpdate(ctx, data, len) || 451266077Sdes !EVP_DigestFinal_ex(ctx, dest, NULL)) { 452266077Sdes EVP_MD_CTX_destroy(ctx); 453266077Sdes return 0; 454266077Sdes } 455266077Sdes EVP_MD_CTX_destroy(ctx); 456266077Sdes return 1; 457266077Sdes} 458266077Sdes#endif /* HAVE_SSL */ 459