keyraw.c revision 276541
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" 14266077Sdes#include "ldns/keyraw.h" 15266077Sdes#include "ldns/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 26266077Sdes#endif /* HAVE_SSL */ 27266077Sdes 28266077Sdessize_t 29266077Sdessldns_rr_dnskey_key_size_raw(const unsigned char* keydata, 30266077Sdes const size_t len, int alg) 31266077Sdes{ 32266077Sdes /* for DSA keys */ 33266077Sdes uint8_t t; 34266077Sdes 35266077Sdes /* for RSA keys */ 36266077Sdes uint16_t exp; 37266077Sdes uint16_t int16; 38266077Sdes 39266077Sdes switch ((sldns_algorithm)alg) { 40266077Sdes case LDNS_DSA: 41266077Sdes case LDNS_DSA_NSEC3: 42266077Sdes if (len > 0) { 43266077Sdes t = keydata[0]; 44266077Sdes return (64 + t*8)*8; 45266077Sdes } else { 46266077Sdes return 0; 47266077Sdes } 48266077Sdes break; 49266077Sdes case LDNS_RSAMD5: 50266077Sdes case LDNS_RSASHA1: 51266077Sdes case LDNS_RSASHA1_NSEC3: 52266077Sdes#ifdef USE_SHA2 53266077Sdes case LDNS_RSASHA256: 54266077Sdes case LDNS_RSASHA512: 55266077Sdes#endif 56266077Sdes if (len > 0) { 57266077Sdes if (keydata[0] == 0) { 58266077Sdes /* big exponent */ 59266077Sdes if (len > 3) { 60266077Sdes memmove(&int16, keydata + 1, 2); 61266077Sdes exp = ntohs(int16); 62266077Sdes return (len - exp - 3)*8; 63266077Sdes } else { 64266077Sdes return 0; 65266077Sdes } 66266077Sdes } else { 67266077Sdes exp = keydata[0]; 68266077Sdes return (len-exp-1)*8; 69266077Sdes } 70266077Sdes } else { 71266077Sdes return 0; 72266077Sdes } 73266077Sdes break; 74266077Sdes#ifdef USE_GOST 75266077Sdes case LDNS_ECC_GOST: 76266077Sdes return 512; 77266077Sdes#endif 78266077Sdes#ifdef USE_ECDSA 79266077Sdes case LDNS_ECDSAP256SHA256: 80266077Sdes return 256; 81266077Sdes case LDNS_ECDSAP384SHA384: 82266077Sdes return 384; 83266077Sdes#endif 84266077Sdes default: 85266077Sdes return 0; 86266077Sdes } 87266077Sdes} 88266077Sdes 89266077Sdesuint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize) 90266077Sdes{ 91266077Sdes if(keysize < 4) { 92266077Sdes return 0; 93266077Sdes } 94266077Sdes /* look at the algorithm field, copied from 2535bis */ 95266077Sdes if (key[3] == LDNS_RSAMD5) { 96266077Sdes uint16_t ac16 = 0; 97266077Sdes if (keysize > 4) { 98266077Sdes memmove(&ac16, key + keysize - 3, 2); 99266077Sdes } 100266077Sdes ac16 = ntohs(ac16); 101266077Sdes return (uint16_t) ac16; 102266077Sdes } else { 103266077Sdes size_t i; 104266077Sdes uint32_t ac32 = 0; 105266077Sdes for (i = 0; i < keysize; ++i) { 106266077Sdes ac32 += (i & 1) ? key[i] : key[i] << 8; 107266077Sdes } 108266077Sdes ac32 += (ac32 >> 16) & 0xFFFF; 109266077Sdes return (uint16_t) (ac32 & 0xFFFF); 110266077Sdes } 111266077Sdes} 112266077Sdes 113266077Sdes#ifdef HAVE_SSL 114266077Sdes#ifdef USE_GOST 115266077Sdes/** store GOST engine reference loaded into OpenSSL library */ 116266077SdesENGINE* sldns_gost_engine = NULL; 117266077Sdes 118266077Sdesint 119266077Sdessldns_key_EVP_load_gost_id(void) 120266077Sdes{ 121266077Sdes static int gost_id = 0; 122266077Sdes const EVP_PKEY_ASN1_METHOD* meth; 123266077Sdes ENGINE* e; 124266077Sdes 125266077Sdes if(gost_id) return gost_id; 126266077Sdes 127266077Sdes /* see if configuration loaded gost implementation from other engine*/ 128266077Sdes meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1); 129266077Sdes if(meth) { 130266077Sdes EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); 131266077Sdes return gost_id; 132266077Sdes } 133266077Sdes 134266077Sdes /* see if engine can be loaded already */ 135266077Sdes e = ENGINE_by_id("gost"); 136266077Sdes if(!e) { 137266077Sdes /* load it ourself, in case statically linked */ 138266077Sdes ENGINE_load_builtin_engines(); 139266077Sdes ENGINE_load_dynamic(); 140266077Sdes e = ENGINE_by_id("gost"); 141266077Sdes } 142266077Sdes if(!e) { 143266077Sdes /* no gost engine in openssl */ 144266077Sdes return 0; 145266077Sdes } 146266077Sdes if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { 147266077Sdes ENGINE_finish(e); 148266077Sdes ENGINE_free(e); 149266077Sdes return 0; 150266077Sdes } 151266077Sdes 152266077Sdes meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1); 153266077Sdes if(!meth) { 154266077Sdes /* algo not found */ 155266077Sdes ENGINE_finish(e); 156266077Sdes ENGINE_free(e); 157266077Sdes return 0; 158266077Sdes } 159266077Sdes /* Note: do not ENGINE_finish and ENGINE_free the acquired engine 160266077Sdes * on some platforms this frees up the meth and unloads gost stuff */ 161266077Sdes sldns_gost_engine = e; 162266077Sdes 163266077Sdes EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); 164266077Sdes return gost_id; 165266077Sdes} 166266077Sdes 167266077Sdesvoid sldns_key_EVP_unload_gost(void) 168266077Sdes{ 169266077Sdes if(sldns_gost_engine) { 170266077Sdes ENGINE_finish(sldns_gost_engine); 171266077Sdes ENGINE_free(sldns_gost_engine); 172266077Sdes sldns_gost_engine = NULL; 173266077Sdes } 174266077Sdes} 175266077Sdes#endif /* USE_GOST */ 176266077Sdes 177266077SdesDSA * 178266077Sdessldns_key_buf2dsa_raw(unsigned char* key, size_t len) 179266077Sdes{ 180266077Sdes uint8_t T; 181266077Sdes uint16_t length; 182266077Sdes uint16_t offset; 183266077Sdes DSA *dsa; 184266077Sdes BIGNUM *Q; BIGNUM *P; 185266077Sdes BIGNUM *G; BIGNUM *Y; 186266077Sdes 187266077Sdes if(len == 0) 188266077Sdes return NULL; 189266077Sdes T = (uint8_t)key[0]; 190266077Sdes length = (64 + T * 8); 191266077Sdes offset = 1; 192266077Sdes 193266077Sdes if (T > 8) { 194266077Sdes return NULL; 195266077Sdes } 196266077Sdes if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length) 197266077Sdes return NULL; 198266077Sdes 199266077Sdes Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL); 200266077Sdes offset += SHA_DIGEST_LENGTH; 201266077Sdes 202266077Sdes P = BN_bin2bn(key+offset, (int)length, NULL); 203266077Sdes offset += length; 204266077Sdes 205266077Sdes G = BN_bin2bn(key+offset, (int)length, NULL); 206266077Sdes offset += length; 207266077Sdes 208266077Sdes Y = BN_bin2bn(key+offset, (int)length, NULL); 209266077Sdes offset += length; 210266077Sdes 211266077Sdes /* create the key and set its properties */ 212266077Sdes if(!Q || !P || !G || !Y || !(dsa = DSA_new())) { 213266077Sdes BN_free(Q); 214266077Sdes BN_free(P); 215266077Sdes BN_free(G); 216266077Sdes BN_free(Y); 217266077Sdes return NULL; 218266077Sdes } 219266077Sdes#ifndef S_SPLINT_S 220266077Sdes dsa->p = P; 221266077Sdes dsa->q = Q; 222266077Sdes dsa->g = G; 223266077Sdes dsa->pub_key = Y; 224266077Sdes#endif /* splint */ 225266077Sdes 226266077Sdes return dsa; 227266077Sdes} 228266077Sdes 229266077SdesRSA * 230266077Sdessldns_key_buf2rsa_raw(unsigned char* key, size_t len) 231266077Sdes{ 232266077Sdes uint16_t offset; 233266077Sdes uint16_t exp; 234266077Sdes uint16_t int16; 235266077Sdes RSA *rsa; 236266077Sdes BIGNUM *modulus; 237266077Sdes BIGNUM *exponent; 238266077Sdes 239266077Sdes if (len == 0) 240266077Sdes return NULL; 241266077Sdes if (key[0] == 0) { 242266077Sdes if(len < 3) 243266077Sdes return NULL; 244266077Sdes memmove(&int16, key+1, 2); 245266077Sdes exp = ntohs(int16); 246266077Sdes offset = 3; 247266077Sdes } else { 248266077Sdes exp = key[0]; 249266077Sdes offset = 1; 250266077Sdes } 251266077Sdes 252266077Sdes /* key length at least one */ 253266077Sdes if(len < (size_t)offset + exp + 1) 254266077Sdes return NULL; 255266077Sdes 256266077Sdes /* Exponent */ 257266077Sdes exponent = BN_new(); 258266077Sdes if(!exponent) return NULL; 259266077Sdes (void) BN_bin2bn(key+offset, (int)exp, exponent); 260266077Sdes offset += exp; 261266077Sdes 262266077Sdes /* Modulus */ 263266077Sdes modulus = BN_new(); 264266077Sdes if(!modulus) { 265266077Sdes BN_free(exponent); 266266077Sdes return NULL; 267266077Sdes } 268266077Sdes /* length of the buffer must match the key length! */ 269266077Sdes (void) BN_bin2bn(key+offset, (int)(len - offset), modulus); 270266077Sdes 271266077Sdes rsa = RSA_new(); 272266077Sdes if(!rsa) { 273266077Sdes BN_free(exponent); 274266077Sdes BN_free(modulus); 275266077Sdes return NULL; 276266077Sdes } 277266077Sdes#ifndef S_SPLINT_S 278266077Sdes rsa->n = modulus; 279266077Sdes rsa->e = exponent; 280266077Sdes#endif /* splint */ 281266077Sdes 282266077Sdes return rsa; 283266077Sdes} 284266077Sdes 285266077Sdes#ifdef USE_GOST 286266077SdesEVP_PKEY* 287266077Sdessldns_gost2pkey_raw(unsigned char* key, size_t keylen) 288266077Sdes{ 289266077Sdes /* prefix header for X509 encoding */ 290266077Sdes uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, 291266077Sdes 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, 292266077Sdes 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 293266077Sdes 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40}; 294266077Sdes unsigned char encoded[37+64]; 295266077Sdes const unsigned char* pp; 296266077Sdes if(keylen != 64) { 297266077Sdes /* key wrong size */ 298266077Sdes return NULL; 299266077Sdes } 300266077Sdes 301266077Sdes /* create evp_key */ 302266077Sdes memmove(encoded, asn, 37); 303266077Sdes memmove(encoded+37, key, 64); 304266077Sdes pp = (unsigned char*)&encoded[0]; 305266077Sdes 306266077Sdes return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded)); 307266077Sdes} 308266077Sdes#endif /* USE_GOST */ 309266077Sdes 310266077Sdes#ifdef USE_ECDSA 311266077SdesEVP_PKEY* 312266077Sdessldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo) 313266077Sdes{ 314266077Sdes unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ 315266077Sdes const unsigned char* pp = buf; 316266077Sdes EVP_PKEY *evp_key; 317266077Sdes EC_KEY *ec; 318266077Sdes /* check length, which uncompressed must be 2 bignums */ 319266077Sdes if(algo == LDNS_ECDSAP256SHA256) { 320266077Sdes if(keylen != 2*256/8) return NULL; 321266077Sdes ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 322266077Sdes } else if(algo == LDNS_ECDSAP384SHA384) { 323266077Sdes if(keylen != 2*384/8) return NULL; 324266077Sdes ec = EC_KEY_new_by_curve_name(NID_secp384r1); 325266077Sdes } else ec = NULL; 326266077Sdes if(!ec) return NULL; 327276541Sdes if(keylen+1 > sizeof(buf)) { /* sanity check */ 328276541Sdes EC_KEY_free(ec); 329276541Sdes return NULL; 330276541Sdes } 331266077Sdes /* prepend the 0x02 (from docs) (or actually 0x04 from implementation 332266077Sdes * of openssl) for uncompressed data */ 333266077Sdes buf[0] = POINT_CONVERSION_UNCOMPRESSED; 334266077Sdes memmove(buf+1, key, keylen); 335266077Sdes if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) { 336266077Sdes EC_KEY_free(ec); 337266077Sdes return NULL; 338266077Sdes } 339266077Sdes evp_key = EVP_PKEY_new(); 340266077Sdes if(!evp_key) { 341266077Sdes EC_KEY_free(ec); 342266077Sdes return NULL; 343266077Sdes } 344266077Sdes if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) { 345266077Sdes EVP_PKEY_free(evp_key); 346266077Sdes EC_KEY_free(ec); 347266077Sdes return NULL; 348266077Sdes } 349266077Sdes return evp_key; 350266077Sdes} 351266077Sdes#endif /* USE_ECDSA */ 352266077Sdes 353266077Sdesint 354266077Sdessldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest, 355266077Sdes const EVP_MD* md) 356266077Sdes{ 357266077Sdes EVP_MD_CTX* ctx; 358266077Sdes ctx = EVP_MD_CTX_create(); 359266077Sdes if(!ctx) 360266077Sdes return 0; 361266077Sdes if(!EVP_DigestInit_ex(ctx, md, NULL) || 362266077Sdes !EVP_DigestUpdate(ctx, data, len) || 363266077Sdes !EVP_DigestFinal_ex(ctx, dest, NULL)) { 364266077Sdes EVP_MD_CTX_destroy(ctx); 365266077Sdes return 0; 366266077Sdes } 367266077Sdes EVP_MD_CTX_destroy(ctx); 368266077Sdes return 1; 369266077Sdes} 370266077Sdes#endif /* HAVE_SSL */ 371