1*8ed2b524SDag-Erling Smørgrav /* 2*8ed2b524SDag-Erling Smørgrav * validator/val_secalgo.c - validator security algorithm functions. 3*8ed2b524SDag-Erling Smørgrav * 4*8ed2b524SDag-Erling Smørgrav * Copyright (c) 2012, NLnet Labs. All rights reserved. 5*8ed2b524SDag-Erling Smørgrav * 6*8ed2b524SDag-Erling Smørgrav * This software is open source. 7*8ed2b524SDag-Erling Smørgrav * 8*8ed2b524SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 9*8ed2b524SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 10*8ed2b524SDag-Erling Smørgrav * are met: 11*8ed2b524SDag-Erling Smørgrav * 12*8ed2b524SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 13*8ed2b524SDag-Erling Smørgrav * this list of conditions and the following disclaimer. 14*8ed2b524SDag-Erling Smørgrav * 15*8ed2b524SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 16*8ed2b524SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 17*8ed2b524SDag-Erling Smørgrav * and/or other materials provided with the distribution. 18*8ed2b524SDag-Erling Smørgrav * 19*8ed2b524SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 20*8ed2b524SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 21*8ed2b524SDag-Erling Smørgrav * specific prior written permission. 22*8ed2b524SDag-Erling Smørgrav * 23*8ed2b524SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24*8ed2b524SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25*8ed2b524SDag-Erling Smørgrav * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26*8ed2b524SDag-Erling Smørgrav * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 27*8ed2b524SDag-Erling Smørgrav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28*8ed2b524SDag-Erling Smørgrav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29*8ed2b524SDag-Erling Smørgrav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30*8ed2b524SDag-Erling Smørgrav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31*8ed2b524SDag-Erling Smørgrav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32*8ed2b524SDag-Erling Smørgrav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33*8ed2b524SDag-Erling Smørgrav * POSSIBILITY OF SUCH DAMAGE. 34*8ed2b524SDag-Erling Smørgrav */ 35*8ed2b524SDag-Erling Smørgrav 36*8ed2b524SDag-Erling Smørgrav /** 37*8ed2b524SDag-Erling Smørgrav * \file 38*8ed2b524SDag-Erling Smørgrav * 39*8ed2b524SDag-Erling Smørgrav * This file contains helper functions for the validator module. 40*8ed2b524SDag-Erling Smørgrav * These functions take raw data buffers, formatted for crypto verification, 41*8ed2b524SDag-Erling Smørgrav * and do the library calls (for the crypto library in use). 42*8ed2b524SDag-Erling Smørgrav */ 43*8ed2b524SDag-Erling Smørgrav #include "config.h" 44*8ed2b524SDag-Erling Smørgrav #include <ldns/ldns.h> 45*8ed2b524SDag-Erling Smørgrav #include "validator/val_secalgo.h" 46*8ed2b524SDag-Erling Smørgrav #include "util/data/packed_rrset.h" 47*8ed2b524SDag-Erling Smørgrav #include "util/log.h" 48*8ed2b524SDag-Erling Smørgrav 49*8ed2b524SDag-Erling Smørgrav #if !defined(HAVE_SSL) && !defined(HAVE_NSS) 50*8ed2b524SDag-Erling Smørgrav #error "Need crypto library to do digital signature cryptography" 51*8ed2b524SDag-Erling Smørgrav #endif 52*8ed2b524SDag-Erling Smørgrav 53*8ed2b524SDag-Erling Smørgrav /* OpenSSL implementation */ 54*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 55*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ERR_H 56*8ed2b524SDag-Erling Smørgrav #include <openssl/err.h> 57*8ed2b524SDag-Erling Smørgrav #endif 58*8ed2b524SDag-Erling Smørgrav 59*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_RAND_H 60*8ed2b524SDag-Erling Smørgrav #include <openssl/rand.h> 61*8ed2b524SDag-Erling Smørgrav #endif 62*8ed2b524SDag-Erling Smørgrav 63*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_CONF_H 64*8ed2b524SDag-Erling Smørgrav #include <openssl/conf.h> 65*8ed2b524SDag-Erling Smørgrav #endif 66*8ed2b524SDag-Erling Smørgrav 67*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ENGINE_H 68*8ed2b524SDag-Erling Smørgrav #include <openssl/engine.h> 69*8ed2b524SDag-Erling Smørgrav #endif 70*8ed2b524SDag-Erling Smørgrav 71*8ed2b524SDag-Erling Smørgrav /** 72*8ed2b524SDag-Erling Smørgrav * Return size of DS digest according to its hash algorithm. 73*8ed2b524SDag-Erling Smørgrav * @param algo: DS digest algo. 74*8ed2b524SDag-Erling Smørgrav * @return size in bytes of digest, or 0 if not supported. 75*8ed2b524SDag-Erling Smørgrav */ 76*8ed2b524SDag-Erling Smørgrav size_t 77*8ed2b524SDag-Erling Smørgrav ds_digest_size_supported(int algo) 78*8ed2b524SDag-Erling Smørgrav { 79*8ed2b524SDag-Erling Smørgrav switch(algo) { 80*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_EVP_SHA1 81*8ed2b524SDag-Erling Smørgrav case LDNS_SHA1: 82*8ed2b524SDag-Erling Smørgrav return SHA_DIGEST_LENGTH; 83*8ed2b524SDag-Erling Smørgrav #endif 84*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_EVP_SHA256 85*8ed2b524SDag-Erling Smørgrav case LDNS_SHA256: 86*8ed2b524SDag-Erling Smørgrav return SHA256_DIGEST_LENGTH; 87*8ed2b524SDag-Erling Smørgrav #endif 88*8ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 89*8ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST: 90*8ed2b524SDag-Erling Smørgrav if(EVP_get_digestbyname("md_gost94")) 91*8ed2b524SDag-Erling Smørgrav return 32; 92*8ed2b524SDag-Erling Smørgrav else return 0; 93*8ed2b524SDag-Erling Smørgrav #endif 94*8ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 95*8ed2b524SDag-Erling Smørgrav case LDNS_SHA384: 96*8ed2b524SDag-Erling Smørgrav return SHA384_DIGEST_LENGTH; 97*8ed2b524SDag-Erling Smørgrav #endif 98*8ed2b524SDag-Erling Smørgrav default: break; 99*8ed2b524SDag-Erling Smørgrav } 100*8ed2b524SDag-Erling Smørgrav return 0; 101*8ed2b524SDag-Erling Smørgrav } 102*8ed2b524SDag-Erling Smørgrav 103*8ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 104*8ed2b524SDag-Erling Smørgrav /** Perform GOST hash */ 105*8ed2b524SDag-Erling Smørgrav static int 106*8ed2b524SDag-Erling Smørgrav do_gost94(unsigned char* data, size_t len, unsigned char* dest) 107*8ed2b524SDag-Erling Smørgrav { 108*8ed2b524SDag-Erling Smørgrav const EVP_MD* md = EVP_get_digestbyname("md_gost94"); 109*8ed2b524SDag-Erling Smørgrav if(!md) 110*8ed2b524SDag-Erling Smørgrav return 0; 111*8ed2b524SDag-Erling Smørgrav return ldns_digest_evp(data, (unsigned int)len, dest, md); 112*8ed2b524SDag-Erling Smørgrav } 113*8ed2b524SDag-Erling Smørgrav #endif 114*8ed2b524SDag-Erling Smørgrav 115*8ed2b524SDag-Erling Smørgrav int 116*8ed2b524SDag-Erling Smørgrav secalgo_ds_digest(int algo, unsigned char* buf, size_t len, 117*8ed2b524SDag-Erling Smørgrav unsigned char* res) 118*8ed2b524SDag-Erling Smørgrav { 119*8ed2b524SDag-Erling Smørgrav switch(algo) { 120*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_EVP_SHA1 121*8ed2b524SDag-Erling Smørgrav case LDNS_SHA1: 122*8ed2b524SDag-Erling Smørgrav (void)SHA1(buf, len, res); 123*8ed2b524SDag-Erling Smørgrav return 1; 124*8ed2b524SDag-Erling Smørgrav #endif 125*8ed2b524SDag-Erling Smørgrav #ifdef HAVE_EVP_SHA256 126*8ed2b524SDag-Erling Smørgrav case LDNS_SHA256: 127*8ed2b524SDag-Erling Smørgrav (void)SHA256(buf, len, res); 128*8ed2b524SDag-Erling Smørgrav return 1; 129*8ed2b524SDag-Erling Smørgrav #endif 130*8ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 131*8ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST: 132*8ed2b524SDag-Erling Smørgrav if(do_gost94(buf, len, res)) 133*8ed2b524SDag-Erling Smørgrav return 1; 134*8ed2b524SDag-Erling Smørgrav break; 135*8ed2b524SDag-Erling Smørgrav #endif 136*8ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 137*8ed2b524SDag-Erling Smørgrav case LDNS_SHA384: 138*8ed2b524SDag-Erling Smørgrav (void)SHA384(buf, len, res); 139*8ed2b524SDag-Erling Smørgrav return 1; 140*8ed2b524SDag-Erling Smørgrav #endif 141*8ed2b524SDag-Erling Smørgrav default: 142*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "unknown DS digest algorithm %d", 143*8ed2b524SDag-Erling Smørgrav algo); 144*8ed2b524SDag-Erling Smørgrav break; 145*8ed2b524SDag-Erling Smørgrav } 146*8ed2b524SDag-Erling Smørgrav return 0; 147*8ed2b524SDag-Erling Smørgrav } 148*8ed2b524SDag-Erling Smørgrav 149*8ed2b524SDag-Erling Smørgrav /** return true if DNSKEY algorithm id is supported */ 150*8ed2b524SDag-Erling Smørgrav int 151*8ed2b524SDag-Erling Smørgrav dnskey_algo_id_is_supported(int id) 152*8ed2b524SDag-Erling Smørgrav { 153*8ed2b524SDag-Erling Smørgrav switch(id) { 154*8ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5: 155*8ed2b524SDag-Erling Smørgrav /* RFC 6725 deprecates RSAMD5 */ 156*8ed2b524SDag-Erling Smørgrav return 0; 157*8ed2b524SDag-Erling Smørgrav case LDNS_DSA: 158*8ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 159*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1: 160*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 161*8ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) 162*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256: 163*8ed2b524SDag-Erling Smørgrav #endif 164*8ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) 165*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512: 166*8ed2b524SDag-Erling Smørgrav #endif 167*8ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 168*8ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 169*8ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 170*8ed2b524SDag-Erling Smørgrav #endif 171*8ed2b524SDag-Erling Smørgrav return 1; 172*8ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 173*8ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST: 174*8ed2b524SDag-Erling Smørgrav /* we support GOST if it can be loaded */ 175*8ed2b524SDag-Erling Smørgrav return ldns_key_EVP_load_gost_id(); 176*8ed2b524SDag-Erling Smørgrav #endif 177*8ed2b524SDag-Erling Smørgrav default: 178*8ed2b524SDag-Erling Smørgrav return 0; 179*8ed2b524SDag-Erling Smørgrav } 180*8ed2b524SDag-Erling Smørgrav } 181*8ed2b524SDag-Erling Smørgrav 182*8ed2b524SDag-Erling Smørgrav /** 183*8ed2b524SDag-Erling Smørgrav * Output a libcrypto openssl error to the logfile. 184*8ed2b524SDag-Erling Smørgrav * @param str: string to add to it. 185*8ed2b524SDag-Erling Smørgrav * @param e: the error to output, error number from ERR_get_error(). 186*8ed2b524SDag-Erling Smørgrav */ 187*8ed2b524SDag-Erling Smørgrav static void 188*8ed2b524SDag-Erling Smørgrav log_crypto_error(const char* str, unsigned long e) 189*8ed2b524SDag-Erling Smørgrav { 190*8ed2b524SDag-Erling Smørgrav char buf[128]; 191*8ed2b524SDag-Erling Smørgrav /* or use ERR_error_string if ERR_error_string_n is not avail TODO */ 192*8ed2b524SDag-Erling Smørgrav ERR_error_string_n(e, buf, sizeof(buf)); 193*8ed2b524SDag-Erling Smørgrav /* buf now contains */ 194*8ed2b524SDag-Erling Smørgrav /* error:[error code]:[library name]:[function name]:[reason string] */ 195*8ed2b524SDag-Erling Smørgrav log_err("%s crypto %s", str, buf); 196*8ed2b524SDag-Erling Smørgrav } 197*8ed2b524SDag-Erling Smørgrav 198*8ed2b524SDag-Erling Smørgrav /** 199*8ed2b524SDag-Erling Smørgrav * Setup DSA key digest in DER encoding ... 200*8ed2b524SDag-Erling Smørgrav * @param sig: input is signature output alloced ptr (unless failure). 201*8ed2b524SDag-Erling Smørgrav * caller must free alloced ptr if this routine returns true. 202*8ed2b524SDag-Erling Smørgrav * @param len: input is initial siglen, output is output len. 203*8ed2b524SDag-Erling Smørgrav * @return false on failure. 204*8ed2b524SDag-Erling Smørgrav */ 205*8ed2b524SDag-Erling Smørgrav static int 206*8ed2b524SDag-Erling Smørgrav setup_dsa_sig(unsigned char** sig, unsigned int* len) 207*8ed2b524SDag-Erling Smørgrav { 208*8ed2b524SDag-Erling Smørgrav unsigned char* orig = *sig; 209*8ed2b524SDag-Erling Smørgrav unsigned int origlen = *len; 210*8ed2b524SDag-Erling Smørgrav int newlen; 211*8ed2b524SDag-Erling Smørgrav BIGNUM *R, *S; 212*8ed2b524SDag-Erling Smørgrav DSA_SIG *dsasig; 213*8ed2b524SDag-Erling Smørgrav 214*8ed2b524SDag-Erling Smørgrav /* extract the R and S field from the sig buffer */ 215*8ed2b524SDag-Erling Smørgrav if(origlen < 1 + 2*SHA_DIGEST_LENGTH) 216*8ed2b524SDag-Erling Smørgrav return 0; 217*8ed2b524SDag-Erling Smørgrav R = BN_new(); 218*8ed2b524SDag-Erling Smørgrav if(!R) return 0; 219*8ed2b524SDag-Erling Smørgrav (void) BN_bin2bn(orig + 1, SHA_DIGEST_LENGTH, R); 220*8ed2b524SDag-Erling Smørgrav S = BN_new(); 221*8ed2b524SDag-Erling Smørgrav if(!S) return 0; 222*8ed2b524SDag-Erling Smørgrav (void) BN_bin2bn(orig + 21, SHA_DIGEST_LENGTH, S); 223*8ed2b524SDag-Erling Smørgrav dsasig = DSA_SIG_new(); 224*8ed2b524SDag-Erling Smørgrav if(!dsasig) return 0; 225*8ed2b524SDag-Erling Smørgrav 226*8ed2b524SDag-Erling Smørgrav dsasig->r = R; 227*8ed2b524SDag-Erling Smørgrav dsasig->s = S; 228*8ed2b524SDag-Erling Smørgrav *sig = NULL; 229*8ed2b524SDag-Erling Smørgrav newlen = i2d_DSA_SIG(dsasig, sig); 230*8ed2b524SDag-Erling Smørgrav if(newlen < 0) { 231*8ed2b524SDag-Erling Smørgrav DSA_SIG_free(dsasig); 232*8ed2b524SDag-Erling Smørgrav free(*sig); 233*8ed2b524SDag-Erling Smørgrav return 0; 234*8ed2b524SDag-Erling Smørgrav } 235*8ed2b524SDag-Erling Smørgrav *len = (unsigned int)newlen; 236*8ed2b524SDag-Erling Smørgrav DSA_SIG_free(dsasig); 237*8ed2b524SDag-Erling Smørgrav return 1; 238*8ed2b524SDag-Erling Smørgrav } 239*8ed2b524SDag-Erling Smørgrav 240*8ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 241*8ed2b524SDag-Erling Smørgrav /** 242*8ed2b524SDag-Erling Smørgrav * Setup the ECDSA signature in its encoding that the library wants. 243*8ed2b524SDag-Erling Smørgrav * Converts from plain numbers to ASN formatted. 244*8ed2b524SDag-Erling Smørgrav * @param sig: input is signature, output alloced ptr (unless failure). 245*8ed2b524SDag-Erling Smørgrav * caller must free alloced ptr if this routine returns true. 246*8ed2b524SDag-Erling Smørgrav * @param len: input is initial siglen, output is output len. 247*8ed2b524SDag-Erling Smørgrav * @return false on failure. 248*8ed2b524SDag-Erling Smørgrav */ 249*8ed2b524SDag-Erling Smørgrav static int 250*8ed2b524SDag-Erling Smørgrav setup_ecdsa_sig(unsigned char** sig, unsigned int* len) 251*8ed2b524SDag-Erling Smørgrav { 252*8ed2b524SDag-Erling Smørgrav ECDSA_SIG* ecdsa_sig; 253*8ed2b524SDag-Erling Smørgrav int newlen; 254*8ed2b524SDag-Erling Smørgrav int bnsize = (int)((*len)/2); 255*8ed2b524SDag-Erling Smørgrav /* if too short or not even length, fails */ 256*8ed2b524SDag-Erling Smørgrav if(*len < 16 || bnsize*2 != (int)*len) 257*8ed2b524SDag-Erling Smørgrav return 0; 258*8ed2b524SDag-Erling Smørgrav /* use the raw data to parse two evenly long BIGNUMs, "r | s". */ 259*8ed2b524SDag-Erling Smørgrav ecdsa_sig = ECDSA_SIG_new(); 260*8ed2b524SDag-Erling Smørgrav if(!ecdsa_sig) return 0; 261*8ed2b524SDag-Erling Smørgrav ecdsa_sig->r = BN_bin2bn(*sig, bnsize, ecdsa_sig->r); 262*8ed2b524SDag-Erling Smørgrav ecdsa_sig->s = BN_bin2bn(*sig+bnsize, bnsize, ecdsa_sig->s); 263*8ed2b524SDag-Erling Smørgrav if(!ecdsa_sig->r || !ecdsa_sig->s) { 264*8ed2b524SDag-Erling Smørgrav ECDSA_SIG_free(ecdsa_sig); 265*8ed2b524SDag-Erling Smørgrav return 0; 266*8ed2b524SDag-Erling Smørgrav } 267*8ed2b524SDag-Erling Smørgrav 268*8ed2b524SDag-Erling Smørgrav /* spool it into ASN format */ 269*8ed2b524SDag-Erling Smørgrav *sig = NULL; 270*8ed2b524SDag-Erling Smørgrav newlen = i2d_ECDSA_SIG(ecdsa_sig, sig); 271*8ed2b524SDag-Erling Smørgrav if(newlen <= 0) { 272*8ed2b524SDag-Erling Smørgrav ECDSA_SIG_free(ecdsa_sig); 273*8ed2b524SDag-Erling Smørgrav free(*sig); 274*8ed2b524SDag-Erling Smørgrav return 0; 275*8ed2b524SDag-Erling Smørgrav } 276*8ed2b524SDag-Erling Smørgrav *len = (unsigned int)newlen; 277*8ed2b524SDag-Erling Smørgrav ECDSA_SIG_free(ecdsa_sig); 278*8ed2b524SDag-Erling Smørgrav return 1; 279*8ed2b524SDag-Erling Smørgrav } 280*8ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */ 281*8ed2b524SDag-Erling Smørgrav 282*8ed2b524SDag-Erling Smørgrav /** 283*8ed2b524SDag-Erling Smørgrav * Setup key and digest for verification. Adjust sig if necessary. 284*8ed2b524SDag-Erling Smørgrav * 285*8ed2b524SDag-Erling Smørgrav * @param algo: key algorithm 286*8ed2b524SDag-Erling Smørgrav * @param evp_key: EVP PKEY public key to create. 287*8ed2b524SDag-Erling Smørgrav * @param digest_type: digest type to use 288*8ed2b524SDag-Erling Smørgrav * @param key: key to setup for. 289*8ed2b524SDag-Erling Smørgrav * @param keylen: length of key. 290*8ed2b524SDag-Erling Smørgrav * @return false on failure. 291*8ed2b524SDag-Erling Smørgrav */ 292*8ed2b524SDag-Erling Smørgrav static int 293*8ed2b524SDag-Erling Smørgrav setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, 294*8ed2b524SDag-Erling Smørgrav unsigned char* key, size_t keylen) 295*8ed2b524SDag-Erling Smørgrav { 296*8ed2b524SDag-Erling Smørgrav DSA* dsa; 297*8ed2b524SDag-Erling Smørgrav RSA* rsa; 298*8ed2b524SDag-Erling Smørgrav 299*8ed2b524SDag-Erling Smørgrav switch(algo) { 300*8ed2b524SDag-Erling Smørgrav case LDNS_DSA: 301*8ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 302*8ed2b524SDag-Erling Smørgrav *evp_key = EVP_PKEY_new(); 303*8ed2b524SDag-Erling Smørgrav if(!*evp_key) { 304*8ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 305*8ed2b524SDag-Erling Smørgrav return 0; 306*8ed2b524SDag-Erling Smørgrav } 307*8ed2b524SDag-Erling Smørgrav dsa = ldns_key_buf2dsa_raw(key, keylen); 308*8ed2b524SDag-Erling Smørgrav if(!dsa) { 309*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 310*8ed2b524SDag-Erling Smørgrav "ldns_key_buf2dsa_raw failed"); 311*8ed2b524SDag-Erling Smørgrav return 0; 312*8ed2b524SDag-Erling Smørgrav } 313*8ed2b524SDag-Erling Smørgrav if(EVP_PKEY_assign_DSA(*evp_key, dsa) == 0) { 314*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 315*8ed2b524SDag-Erling Smørgrav "EVP_PKEY_assign_DSA failed"); 316*8ed2b524SDag-Erling Smørgrav return 0; 317*8ed2b524SDag-Erling Smørgrav } 318*8ed2b524SDag-Erling Smørgrav *digest_type = EVP_dss1(); 319*8ed2b524SDag-Erling Smørgrav 320*8ed2b524SDag-Erling Smørgrav break; 321*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1: 322*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 323*8ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) 324*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256: 325*8ed2b524SDag-Erling Smørgrav #endif 326*8ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) 327*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512: 328*8ed2b524SDag-Erling Smørgrav #endif 329*8ed2b524SDag-Erling Smørgrav *evp_key = EVP_PKEY_new(); 330*8ed2b524SDag-Erling Smørgrav if(!*evp_key) { 331*8ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 332*8ed2b524SDag-Erling Smørgrav return 0; 333*8ed2b524SDag-Erling Smørgrav } 334*8ed2b524SDag-Erling Smørgrav rsa = ldns_key_buf2rsa_raw(key, keylen); 335*8ed2b524SDag-Erling Smørgrav if(!rsa) { 336*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 337*8ed2b524SDag-Erling Smørgrav "ldns_key_buf2rsa_raw SHA failed"); 338*8ed2b524SDag-Erling Smørgrav return 0; 339*8ed2b524SDag-Erling Smørgrav } 340*8ed2b524SDag-Erling Smørgrav if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) { 341*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 342*8ed2b524SDag-Erling Smørgrav "EVP_PKEY_assign_RSA SHA failed"); 343*8ed2b524SDag-Erling Smørgrav return 0; 344*8ed2b524SDag-Erling Smørgrav } 345*8ed2b524SDag-Erling Smørgrav 346*8ed2b524SDag-Erling Smørgrav /* select SHA version */ 347*8ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) 348*8ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA256) 349*8ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha256(); 350*8ed2b524SDag-Erling Smørgrav else 351*8ed2b524SDag-Erling Smørgrav #endif 352*8ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) 353*8ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA512) 354*8ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha512(); 355*8ed2b524SDag-Erling Smørgrav else 356*8ed2b524SDag-Erling Smørgrav #endif 357*8ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha1(); 358*8ed2b524SDag-Erling Smørgrav 359*8ed2b524SDag-Erling Smørgrav break; 360*8ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5: 361*8ed2b524SDag-Erling Smørgrav *evp_key = EVP_PKEY_new(); 362*8ed2b524SDag-Erling Smørgrav if(!*evp_key) { 363*8ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 364*8ed2b524SDag-Erling Smørgrav return 0; 365*8ed2b524SDag-Erling Smørgrav } 366*8ed2b524SDag-Erling Smørgrav rsa = ldns_key_buf2rsa_raw(key, keylen); 367*8ed2b524SDag-Erling Smørgrav if(!rsa) { 368*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 369*8ed2b524SDag-Erling Smørgrav "ldns_key_buf2rsa_raw MD5 failed"); 370*8ed2b524SDag-Erling Smørgrav return 0; 371*8ed2b524SDag-Erling Smørgrav } 372*8ed2b524SDag-Erling Smørgrav if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) { 373*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 374*8ed2b524SDag-Erling Smørgrav "EVP_PKEY_assign_RSA MD5 failed"); 375*8ed2b524SDag-Erling Smørgrav return 0; 376*8ed2b524SDag-Erling Smørgrav } 377*8ed2b524SDag-Erling Smørgrav *digest_type = EVP_md5(); 378*8ed2b524SDag-Erling Smørgrav 379*8ed2b524SDag-Erling Smørgrav break; 380*8ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 381*8ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST: 382*8ed2b524SDag-Erling Smørgrav *evp_key = ldns_gost2pkey_raw(key, keylen); 383*8ed2b524SDag-Erling Smørgrav if(!*evp_key) { 384*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 385*8ed2b524SDag-Erling Smørgrav "ldns_gost2pkey_raw failed"); 386*8ed2b524SDag-Erling Smørgrav return 0; 387*8ed2b524SDag-Erling Smørgrav } 388*8ed2b524SDag-Erling Smørgrav *digest_type = EVP_get_digestbyname("md_gost94"); 389*8ed2b524SDag-Erling Smørgrav if(!*digest_type) { 390*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 391*8ed2b524SDag-Erling Smørgrav "EVP_getdigest md_gost94 failed"); 392*8ed2b524SDag-Erling Smørgrav return 0; 393*8ed2b524SDag-Erling Smørgrav } 394*8ed2b524SDag-Erling Smørgrav break; 395*8ed2b524SDag-Erling Smørgrav #endif 396*8ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 397*8ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 398*8ed2b524SDag-Erling Smørgrav *evp_key = ldns_ecdsa2pkey_raw(key, keylen, 399*8ed2b524SDag-Erling Smørgrav LDNS_ECDSAP256SHA256); 400*8ed2b524SDag-Erling Smørgrav if(!*evp_key) { 401*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 402*8ed2b524SDag-Erling Smørgrav "ldns_ecdsa2pkey_raw failed"); 403*8ed2b524SDag-Erling Smørgrav return 0; 404*8ed2b524SDag-Erling Smørgrav } 405*8ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA_EVP_WORKAROUND 406*8ed2b524SDag-Erling Smørgrav /* openssl before 1.0.0 fixes RSA with the SHA256 407*8ed2b524SDag-Erling Smørgrav * hash in EVP. We create one for ecdsa_sha256 */ 408*8ed2b524SDag-Erling Smørgrav { 409*8ed2b524SDag-Erling Smørgrav static int md_ecdsa_256_done = 0; 410*8ed2b524SDag-Erling Smørgrav static EVP_MD md; 411*8ed2b524SDag-Erling Smørgrav if(!md_ecdsa_256_done) { 412*8ed2b524SDag-Erling Smørgrav EVP_MD m = *EVP_sha256(); 413*8ed2b524SDag-Erling Smørgrav md_ecdsa_256_done = 1; 414*8ed2b524SDag-Erling Smørgrav m.required_pkey_type[0] = (*evp_key)->type; 415*8ed2b524SDag-Erling Smørgrav m.verify = (void*)ECDSA_verify; 416*8ed2b524SDag-Erling Smørgrav md = m; 417*8ed2b524SDag-Erling Smørgrav } 418*8ed2b524SDag-Erling Smørgrav *digest_type = &md; 419*8ed2b524SDag-Erling Smørgrav } 420*8ed2b524SDag-Erling Smørgrav #else 421*8ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha256(); 422*8ed2b524SDag-Erling Smørgrav #endif 423*8ed2b524SDag-Erling Smørgrav break; 424*8ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 425*8ed2b524SDag-Erling Smørgrav *evp_key = ldns_ecdsa2pkey_raw(key, keylen, 426*8ed2b524SDag-Erling Smørgrav LDNS_ECDSAP384SHA384); 427*8ed2b524SDag-Erling Smørgrav if(!*evp_key) { 428*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 429*8ed2b524SDag-Erling Smørgrav "ldns_ecdsa2pkey_raw failed"); 430*8ed2b524SDag-Erling Smørgrav return 0; 431*8ed2b524SDag-Erling Smørgrav } 432*8ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA_EVP_WORKAROUND 433*8ed2b524SDag-Erling Smørgrav /* openssl before 1.0.0 fixes RSA with the SHA384 434*8ed2b524SDag-Erling Smørgrav * hash in EVP. We create one for ecdsa_sha384 */ 435*8ed2b524SDag-Erling Smørgrav { 436*8ed2b524SDag-Erling Smørgrav static int md_ecdsa_384_done = 0; 437*8ed2b524SDag-Erling Smørgrav static EVP_MD md; 438*8ed2b524SDag-Erling Smørgrav if(!md_ecdsa_384_done) { 439*8ed2b524SDag-Erling Smørgrav EVP_MD m = *EVP_sha384(); 440*8ed2b524SDag-Erling Smørgrav md_ecdsa_384_done = 1; 441*8ed2b524SDag-Erling Smørgrav m.required_pkey_type[0] = (*evp_key)->type; 442*8ed2b524SDag-Erling Smørgrav m.verify = (void*)ECDSA_verify; 443*8ed2b524SDag-Erling Smørgrav md = m; 444*8ed2b524SDag-Erling Smørgrav } 445*8ed2b524SDag-Erling Smørgrav *digest_type = &md; 446*8ed2b524SDag-Erling Smørgrav } 447*8ed2b524SDag-Erling Smørgrav #else 448*8ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha384(); 449*8ed2b524SDag-Erling Smørgrav #endif 450*8ed2b524SDag-Erling Smørgrav break; 451*8ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */ 452*8ed2b524SDag-Erling Smørgrav default: 453*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: unknown algorithm %d", 454*8ed2b524SDag-Erling Smørgrav algo); 455*8ed2b524SDag-Erling Smørgrav return 0; 456*8ed2b524SDag-Erling Smørgrav } 457*8ed2b524SDag-Erling Smørgrav return 1; 458*8ed2b524SDag-Erling Smørgrav } 459*8ed2b524SDag-Erling Smørgrav 460*8ed2b524SDag-Erling Smørgrav /** 461*8ed2b524SDag-Erling Smørgrav * Check a canonical sig+rrset and signature against a dnskey 462*8ed2b524SDag-Erling Smørgrav * @param buf: buffer with data to verify, the first rrsig part and the 463*8ed2b524SDag-Erling Smørgrav * canonicalized rrset. 464*8ed2b524SDag-Erling Smørgrav * @param algo: DNSKEY algorithm. 465*8ed2b524SDag-Erling Smørgrav * @param sigblock: signature rdata field from RRSIG 466*8ed2b524SDag-Erling Smørgrav * @param sigblock_len: length of sigblock data. 467*8ed2b524SDag-Erling Smørgrav * @param key: public key data from DNSKEY RR. 468*8ed2b524SDag-Erling Smørgrav * @param keylen: length of keydata. 469*8ed2b524SDag-Erling Smørgrav * @param reason: bogus reason in more detail. 470*8ed2b524SDag-Erling Smørgrav * @return secure if verification succeeded, bogus on crypto failure, 471*8ed2b524SDag-Erling Smørgrav * unchecked on format errors and alloc failures. 472*8ed2b524SDag-Erling Smørgrav */ 473*8ed2b524SDag-Erling Smørgrav enum sec_status 474*8ed2b524SDag-Erling Smørgrav verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock, 475*8ed2b524SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen, 476*8ed2b524SDag-Erling Smørgrav char** reason) 477*8ed2b524SDag-Erling Smørgrav { 478*8ed2b524SDag-Erling Smørgrav const EVP_MD *digest_type; 479*8ed2b524SDag-Erling Smørgrav EVP_MD_CTX ctx; 480*8ed2b524SDag-Erling Smørgrav int res, dofree = 0; 481*8ed2b524SDag-Erling Smørgrav EVP_PKEY *evp_key = NULL; 482*8ed2b524SDag-Erling Smørgrav 483*8ed2b524SDag-Erling Smørgrav if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) { 484*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup key"); 485*8ed2b524SDag-Erling Smørgrav *reason = "use of key for crypto failed"; 486*8ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 487*8ed2b524SDag-Erling Smørgrav return sec_status_bogus; 488*8ed2b524SDag-Erling Smørgrav } 489*8ed2b524SDag-Erling Smørgrav /* if it is a DSA signature in bind format, convert to DER format */ 490*8ed2b524SDag-Erling Smørgrav if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) && 491*8ed2b524SDag-Erling Smørgrav sigblock_len == 1+2*SHA_DIGEST_LENGTH) { 492*8ed2b524SDag-Erling Smørgrav if(!setup_dsa_sig(&sigblock, &sigblock_len)) { 493*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup DSA sig"); 494*8ed2b524SDag-Erling Smørgrav *reason = "use of key for DSA crypto failed"; 495*8ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 496*8ed2b524SDag-Erling Smørgrav return sec_status_bogus; 497*8ed2b524SDag-Erling Smørgrav } 498*8ed2b524SDag-Erling Smørgrav dofree = 1; 499*8ed2b524SDag-Erling Smørgrav } 500*8ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 501*8ed2b524SDag-Erling Smørgrav else if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) { 502*8ed2b524SDag-Erling Smørgrav /* EVP uses ASN prefix on sig, which is not in the wire data */ 503*8ed2b524SDag-Erling Smørgrav if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) { 504*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup ECDSA sig"); 505*8ed2b524SDag-Erling Smørgrav *reason = "use of signature for ECDSA crypto failed"; 506*8ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 507*8ed2b524SDag-Erling Smørgrav return sec_status_bogus; 508*8ed2b524SDag-Erling Smørgrav } 509*8ed2b524SDag-Erling Smørgrav dofree = 1; 510*8ed2b524SDag-Erling Smørgrav } 511*8ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */ 512*8ed2b524SDag-Erling Smørgrav 513*8ed2b524SDag-Erling Smørgrav /* do the signature cryptography work */ 514*8ed2b524SDag-Erling Smørgrav EVP_MD_CTX_init(&ctx); 515*8ed2b524SDag-Erling Smørgrav if(EVP_VerifyInit(&ctx, digest_type) == 0) { 516*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: EVP_VerifyInit failed"); 517*8ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 518*8ed2b524SDag-Erling Smørgrav if(dofree) free(sigblock); 519*8ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 520*8ed2b524SDag-Erling Smørgrav } 521*8ed2b524SDag-Erling Smørgrav if(EVP_VerifyUpdate(&ctx, (unsigned char*)ldns_buffer_begin(buf), 522*8ed2b524SDag-Erling Smørgrav (unsigned int)ldns_buffer_limit(buf)) == 0) { 523*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: EVP_VerifyUpdate failed"); 524*8ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 525*8ed2b524SDag-Erling Smørgrav if(dofree) free(sigblock); 526*8ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 527*8ed2b524SDag-Erling Smørgrav } 528*8ed2b524SDag-Erling Smørgrav 529*8ed2b524SDag-Erling Smørgrav res = EVP_VerifyFinal(&ctx, sigblock, sigblock_len, evp_key); 530*8ed2b524SDag-Erling Smørgrav if(EVP_MD_CTX_cleanup(&ctx) == 0) { 531*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: EVP_MD_CTX_cleanup failed"); 532*8ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 533*8ed2b524SDag-Erling Smørgrav if(dofree) free(sigblock); 534*8ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 535*8ed2b524SDag-Erling Smørgrav } 536*8ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 537*8ed2b524SDag-Erling Smørgrav 538*8ed2b524SDag-Erling Smørgrav if(dofree) 539*8ed2b524SDag-Erling Smørgrav free(sigblock); 540*8ed2b524SDag-Erling Smørgrav 541*8ed2b524SDag-Erling Smørgrav if(res == 1) { 542*8ed2b524SDag-Erling Smørgrav return sec_status_secure; 543*8ed2b524SDag-Erling Smørgrav } else if(res == 0) { 544*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: signature mismatch"); 545*8ed2b524SDag-Erling Smørgrav *reason = "signature crypto failed"; 546*8ed2b524SDag-Erling Smørgrav return sec_status_bogus; 547*8ed2b524SDag-Erling Smørgrav } 548*8ed2b524SDag-Erling Smørgrav 549*8ed2b524SDag-Erling Smørgrav log_crypto_error("verify:", ERR_get_error()); 550*8ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 551*8ed2b524SDag-Erling Smørgrav } 552*8ed2b524SDag-Erling Smørgrav 553*8ed2b524SDag-Erling Smørgrav /**************************************************/ 554*8ed2b524SDag-Erling Smørgrav #elif defined(HAVE_NSS) 555*8ed2b524SDag-Erling Smørgrav /* libnss implementation */ 556*8ed2b524SDag-Erling Smørgrav /* nss3 */ 557*8ed2b524SDag-Erling Smørgrav #include "sechash.h" 558*8ed2b524SDag-Erling Smørgrav #include "pk11pub.h" 559*8ed2b524SDag-Erling Smørgrav #include "keyhi.h" 560*8ed2b524SDag-Erling Smørgrav #include "secerr.h" 561*8ed2b524SDag-Erling Smørgrav #include "cryptohi.h" 562*8ed2b524SDag-Erling Smørgrav /* nspr4 */ 563*8ed2b524SDag-Erling Smørgrav #include "prerror.h" 564*8ed2b524SDag-Erling Smørgrav 565*8ed2b524SDag-Erling Smørgrav size_t 566*8ed2b524SDag-Erling Smørgrav ds_digest_size_supported(int algo) 567*8ed2b524SDag-Erling Smørgrav { 568*8ed2b524SDag-Erling Smørgrav /* uses libNSS */ 569*8ed2b524SDag-Erling Smørgrav switch(algo) { 570*8ed2b524SDag-Erling Smørgrav case LDNS_SHA1: 571*8ed2b524SDag-Erling Smørgrav return SHA1_LENGTH; 572*8ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 573*8ed2b524SDag-Erling Smørgrav case LDNS_SHA256: 574*8ed2b524SDag-Erling Smørgrav return SHA256_LENGTH; 575*8ed2b524SDag-Erling Smørgrav #endif 576*8ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 577*8ed2b524SDag-Erling Smørgrav case LDNS_SHA384: 578*8ed2b524SDag-Erling Smørgrav return SHA384_LENGTH; 579*8ed2b524SDag-Erling Smørgrav #endif 580*8ed2b524SDag-Erling Smørgrav /* GOST not supported in NSS */ 581*8ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST: 582*8ed2b524SDag-Erling Smørgrav default: break; 583*8ed2b524SDag-Erling Smørgrav } 584*8ed2b524SDag-Erling Smørgrav return 0; 585*8ed2b524SDag-Erling Smørgrav } 586*8ed2b524SDag-Erling Smørgrav 587*8ed2b524SDag-Erling Smørgrav int 588*8ed2b524SDag-Erling Smørgrav secalgo_ds_digest(int algo, unsigned char* buf, size_t len, 589*8ed2b524SDag-Erling Smørgrav unsigned char* res) 590*8ed2b524SDag-Erling Smørgrav { 591*8ed2b524SDag-Erling Smørgrav /* uses libNSS */ 592*8ed2b524SDag-Erling Smørgrav switch(algo) { 593*8ed2b524SDag-Erling Smørgrav case LDNS_SHA1: 594*8ed2b524SDag-Erling Smørgrav return HASH_HashBuf(HASH_AlgSHA1, res, buf, len) 595*8ed2b524SDag-Erling Smørgrav == SECSuccess; 596*8ed2b524SDag-Erling Smørgrav #if defined(USE_SHA2) 597*8ed2b524SDag-Erling Smørgrav case LDNS_SHA256: 598*8ed2b524SDag-Erling Smørgrav return HASH_HashBuf(HASH_AlgSHA256, res, buf, len) 599*8ed2b524SDag-Erling Smørgrav == SECSuccess; 600*8ed2b524SDag-Erling Smørgrav #endif 601*8ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 602*8ed2b524SDag-Erling Smørgrav case LDNS_SHA384: 603*8ed2b524SDag-Erling Smørgrav return HASH_HashBuf(HASH_AlgSHA384, res, buf, len) 604*8ed2b524SDag-Erling Smørgrav == SECSuccess; 605*8ed2b524SDag-Erling Smørgrav #endif 606*8ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST: 607*8ed2b524SDag-Erling Smørgrav default: 608*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "unknown DS digest algorithm %d", 609*8ed2b524SDag-Erling Smørgrav algo); 610*8ed2b524SDag-Erling Smørgrav break; 611*8ed2b524SDag-Erling Smørgrav } 612*8ed2b524SDag-Erling Smørgrav return 0; 613*8ed2b524SDag-Erling Smørgrav } 614*8ed2b524SDag-Erling Smørgrav 615*8ed2b524SDag-Erling Smørgrav int 616*8ed2b524SDag-Erling Smørgrav dnskey_algo_id_is_supported(int id) 617*8ed2b524SDag-Erling Smørgrav { 618*8ed2b524SDag-Erling Smørgrav /* uses libNSS */ 619*8ed2b524SDag-Erling Smørgrav switch(id) { 620*8ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5: 621*8ed2b524SDag-Erling Smørgrav /* RFC 6725 deprecates RSAMD5 */ 622*8ed2b524SDag-Erling Smørgrav return 0; 623*8ed2b524SDag-Erling Smørgrav case LDNS_DSA: 624*8ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 625*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1: 626*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 627*8ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 628*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256: 629*8ed2b524SDag-Erling Smørgrav #endif 630*8ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 631*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512: 632*8ed2b524SDag-Erling Smørgrav #endif 633*8ed2b524SDag-Erling Smørgrav return 1; 634*8ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 635*8ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 636*8ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 637*8ed2b524SDag-Erling Smørgrav return PK11_TokenExists(CKM_ECDSA); 638*8ed2b524SDag-Erling Smørgrav #endif 639*8ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST: 640*8ed2b524SDag-Erling Smørgrav default: 641*8ed2b524SDag-Erling Smørgrav return 0; 642*8ed2b524SDag-Erling Smørgrav } 643*8ed2b524SDag-Erling Smørgrav } 644*8ed2b524SDag-Erling Smørgrav 645*8ed2b524SDag-Erling Smørgrav /* return a new public key for NSS */ 646*8ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_key_create(KeyType ktype) 647*8ed2b524SDag-Erling Smørgrav { 648*8ed2b524SDag-Erling Smørgrav SECKEYPublicKey* key; 649*8ed2b524SDag-Erling Smørgrav PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 650*8ed2b524SDag-Erling Smørgrav if(!arena) { 651*8ed2b524SDag-Erling Smørgrav log_err("out of memory, PORT_NewArena failed"); 652*8ed2b524SDag-Erling Smørgrav return NULL; 653*8ed2b524SDag-Erling Smørgrav } 654*8ed2b524SDag-Erling Smørgrav key = PORT_ArenaZNew(arena, SECKEYPublicKey); 655*8ed2b524SDag-Erling Smørgrav if(!key) { 656*8ed2b524SDag-Erling Smørgrav log_err("out of memory, PORT_ArenaZNew failed"); 657*8ed2b524SDag-Erling Smørgrav PORT_FreeArena(arena, PR_FALSE); 658*8ed2b524SDag-Erling Smørgrav return NULL; 659*8ed2b524SDag-Erling Smørgrav } 660*8ed2b524SDag-Erling Smørgrav key->arena = arena; 661*8ed2b524SDag-Erling Smørgrav key->keyType = ktype; 662*8ed2b524SDag-Erling Smørgrav key->pkcs11Slot = NULL; 663*8ed2b524SDag-Erling Smørgrav key->pkcs11ID = CK_INVALID_HANDLE; 664*8ed2b524SDag-Erling Smørgrav return key; 665*8ed2b524SDag-Erling Smørgrav } 666*8ed2b524SDag-Erling Smørgrav 667*8ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_buf2ecdsa(unsigned char* key, size_t len, int algo) 668*8ed2b524SDag-Erling Smørgrav { 669*8ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pk; 670*8ed2b524SDag-Erling Smørgrav SECItem pub = {siBuffer, NULL, 0}; 671*8ed2b524SDag-Erling Smørgrav SECItem params = {siBuffer, NULL, 0}; 672*8ed2b524SDag-Erling Smørgrav unsigned char param256[] = { 673*8ed2b524SDag-Erling Smørgrav /* OBJECTIDENTIFIER 1.2.840.10045.3.1.7 (P-256) 674*8ed2b524SDag-Erling Smørgrav * {iso(1) member-body(2) us(840) ansi-x962(10045) curves(3) prime(1) prime256v1(7)} */ 675*8ed2b524SDag-Erling Smørgrav 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 676*8ed2b524SDag-Erling Smørgrav }; 677*8ed2b524SDag-Erling Smørgrav unsigned char param384[] = { 678*8ed2b524SDag-Erling Smørgrav /* OBJECTIDENTIFIER 1.3.132.0.34 (P-384) 679*8ed2b524SDag-Erling Smørgrav * {iso(1) identified-organization(3) certicom(132) curve(0) ansip384r1(34)} */ 680*8ed2b524SDag-Erling Smørgrav 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22 681*8ed2b524SDag-Erling Smørgrav }; 682*8ed2b524SDag-Erling Smørgrav unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ 683*8ed2b524SDag-Erling Smørgrav 684*8ed2b524SDag-Erling Smørgrav /* check length, which uncompressed must be 2 bignums */ 685*8ed2b524SDag-Erling Smørgrav if(algo == LDNS_ECDSAP256SHA256) { 686*8ed2b524SDag-Erling Smørgrav if(len != 2*256/8) return NULL; 687*8ed2b524SDag-Erling Smørgrav /* ECCurve_X9_62_PRIME_256V1 */ 688*8ed2b524SDag-Erling Smørgrav } else if(algo == LDNS_ECDSAP384SHA384) { 689*8ed2b524SDag-Erling Smørgrav if(len != 2*384/8) return NULL; 690*8ed2b524SDag-Erling Smørgrav /* ECCurve_X9_62_PRIME_384R1 */ 691*8ed2b524SDag-Erling Smørgrav } else return NULL; 692*8ed2b524SDag-Erling Smørgrav 693*8ed2b524SDag-Erling Smørgrav buf[0] = 0x04; /* POINT_FORM_UNCOMPRESSED */ 694*8ed2b524SDag-Erling Smørgrav memmove(buf+1, key, len); 695*8ed2b524SDag-Erling Smørgrav pub.data = buf; 696*8ed2b524SDag-Erling Smørgrav pub.len = len+1; 697*8ed2b524SDag-Erling Smørgrav if(algo == LDNS_ECDSAP256SHA256) { 698*8ed2b524SDag-Erling Smørgrav params.data = param256; 699*8ed2b524SDag-Erling Smørgrav params.len = sizeof(param256); 700*8ed2b524SDag-Erling Smørgrav } else { 701*8ed2b524SDag-Erling Smørgrav params.data = param384; 702*8ed2b524SDag-Erling Smørgrav params.len = sizeof(param384); 703*8ed2b524SDag-Erling Smørgrav } 704*8ed2b524SDag-Erling Smørgrav 705*8ed2b524SDag-Erling Smørgrav pk = nss_key_create(ecKey); 706*8ed2b524SDag-Erling Smørgrav if(!pk) 707*8ed2b524SDag-Erling Smørgrav return NULL; 708*8ed2b524SDag-Erling Smørgrav pk->u.ec.size = (len/2)*8; 709*8ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.ec.publicValue, &pub)) { 710*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 711*8ed2b524SDag-Erling Smørgrav return NULL; 712*8ed2b524SDag-Erling Smørgrav } 713*8ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.ec.DEREncodedParams, ¶ms)) { 714*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 715*8ed2b524SDag-Erling Smørgrav return NULL; 716*8ed2b524SDag-Erling Smørgrav } 717*8ed2b524SDag-Erling Smørgrav 718*8ed2b524SDag-Erling Smørgrav return pk; 719*8ed2b524SDag-Erling Smørgrav } 720*8ed2b524SDag-Erling Smørgrav 721*8ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_buf2dsa(unsigned char* key, size_t len) 722*8ed2b524SDag-Erling Smørgrav { 723*8ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pk; 724*8ed2b524SDag-Erling Smørgrav uint8_t T; 725*8ed2b524SDag-Erling Smørgrav uint16_t length; 726*8ed2b524SDag-Erling Smørgrav uint16_t offset; 727*8ed2b524SDag-Erling Smørgrav SECItem Q = {siBuffer, NULL, 0}; 728*8ed2b524SDag-Erling Smørgrav SECItem P = {siBuffer, NULL, 0}; 729*8ed2b524SDag-Erling Smørgrav SECItem G = {siBuffer, NULL, 0}; 730*8ed2b524SDag-Erling Smørgrav SECItem Y = {siBuffer, NULL, 0}; 731*8ed2b524SDag-Erling Smørgrav 732*8ed2b524SDag-Erling Smørgrav if(len == 0) 733*8ed2b524SDag-Erling Smørgrav return NULL; 734*8ed2b524SDag-Erling Smørgrav T = (uint8_t)key[0]; 735*8ed2b524SDag-Erling Smørgrav length = (64 + T * 8); 736*8ed2b524SDag-Erling Smørgrav offset = 1; 737*8ed2b524SDag-Erling Smørgrav 738*8ed2b524SDag-Erling Smørgrav if (T > 8) { 739*8ed2b524SDag-Erling Smørgrav return NULL; 740*8ed2b524SDag-Erling Smørgrav } 741*8ed2b524SDag-Erling Smørgrav if(len < (size_t)1 + SHA1_LENGTH + 3*length) 742*8ed2b524SDag-Erling Smørgrav return NULL; 743*8ed2b524SDag-Erling Smørgrav 744*8ed2b524SDag-Erling Smørgrav Q.data = key+offset; 745*8ed2b524SDag-Erling Smørgrav Q.len = SHA1_LENGTH; 746*8ed2b524SDag-Erling Smørgrav offset += SHA1_LENGTH; 747*8ed2b524SDag-Erling Smørgrav 748*8ed2b524SDag-Erling Smørgrav P.data = key+offset; 749*8ed2b524SDag-Erling Smørgrav P.len = length; 750*8ed2b524SDag-Erling Smørgrav offset += length; 751*8ed2b524SDag-Erling Smørgrav 752*8ed2b524SDag-Erling Smørgrav G.data = key+offset; 753*8ed2b524SDag-Erling Smørgrav G.len = length; 754*8ed2b524SDag-Erling Smørgrav offset += length; 755*8ed2b524SDag-Erling Smørgrav 756*8ed2b524SDag-Erling Smørgrav Y.data = key+offset; 757*8ed2b524SDag-Erling Smørgrav Y.len = length; 758*8ed2b524SDag-Erling Smørgrav offset += length; 759*8ed2b524SDag-Erling Smørgrav 760*8ed2b524SDag-Erling Smørgrav pk = nss_key_create(dsaKey); 761*8ed2b524SDag-Erling Smørgrav if(!pk) 762*8ed2b524SDag-Erling Smørgrav return NULL; 763*8ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.prime, &P)) { 764*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 765*8ed2b524SDag-Erling Smørgrav return NULL; 766*8ed2b524SDag-Erling Smørgrav } 767*8ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.subPrime, &Q)) { 768*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 769*8ed2b524SDag-Erling Smørgrav return NULL; 770*8ed2b524SDag-Erling Smørgrav } 771*8ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.base, &G)) { 772*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 773*8ed2b524SDag-Erling Smørgrav return NULL; 774*8ed2b524SDag-Erling Smørgrav } 775*8ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.publicValue, &Y)) { 776*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 777*8ed2b524SDag-Erling Smørgrav return NULL; 778*8ed2b524SDag-Erling Smørgrav } 779*8ed2b524SDag-Erling Smørgrav return pk; 780*8ed2b524SDag-Erling Smørgrav } 781*8ed2b524SDag-Erling Smørgrav 782*8ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_buf2rsa(unsigned char* key, size_t len) 783*8ed2b524SDag-Erling Smørgrav { 784*8ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pk; 785*8ed2b524SDag-Erling Smørgrav uint16_t exp; 786*8ed2b524SDag-Erling Smørgrav uint16_t offset; 787*8ed2b524SDag-Erling Smørgrav uint16_t int16; 788*8ed2b524SDag-Erling Smørgrav SECItem modulus = {siBuffer, NULL, 0}; 789*8ed2b524SDag-Erling Smørgrav SECItem exponent = {siBuffer, NULL, 0}; 790*8ed2b524SDag-Erling Smørgrav if(len == 0) 791*8ed2b524SDag-Erling Smørgrav return NULL; 792*8ed2b524SDag-Erling Smørgrav if(key[0] == 0) { 793*8ed2b524SDag-Erling Smørgrav if(len < 3) 794*8ed2b524SDag-Erling Smørgrav return NULL; 795*8ed2b524SDag-Erling Smørgrav /* the exponent is too large so it's places further */ 796*8ed2b524SDag-Erling Smørgrav memmove(&int16, key+1, 2); 797*8ed2b524SDag-Erling Smørgrav exp = ntohs(int16); 798*8ed2b524SDag-Erling Smørgrav offset = 3; 799*8ed2b524SDag-Erling Smørgrav } else { 800*8ed2b524SDag-Erling Smørgrav exp = key[0]; 801*8ed2b524SDag-Erling Smørgrav offset = 1; 802*8ed2b524SDag-Erling Smørgrav } 803*8ed2b524SDag-Erling Smørgrav 804*8ed2b524SDag-Erling Smørgrav /* key length at least one */ 805*8ed2b524SDag-Erling Smørgrav if(len < (size_t)offset + exp + 1) 806*8ed2b524SDag-Erling Smørgrav return NULL; 807*8ed2b524SDag-Erling Smørgrav 808*8ed2b524SDag-Erling Smørgrav exponent.data = key+offset; 809*8ed2b524SDag-Erling Smørgrav exponent.len = exp; 810*8ed2b524SDag-Erling Smørgrav offset += exp; 811*8ed2b524SDag-Erling Smørgrav modulus.data = key+offset; 812*8ed2b524SDag-Erling Smørgrav modulus.len = (len - offset); 813*8ed2b524SDag-Erling Smørgrav 814*8ed2b524SDag-Erling Smørgrav pk = nss_key_create(rsaKey); 815*8ed2b524SDag-Erling Smørgrav if(!pk) 816*8ed2b524SDag-Erling Smørgrav return NULL; 817*8ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.modulus, &modulus)) { 818*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 819*8ed2b524SDag-Erling Smørgrav return NULL; 820*8ed2b524SDag-Erling Smørgrav } 821*8ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.publicExponent, &exponent)) { 822*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 823*8ed2b524SDag-Erling Smørgrav return NULL; 824*8ed2b524SDag-Erling Smørgrav } 825*8ed2b524SDag-Erling Smørgrav return pk; 826*8ed2b524SDag-Erling Smørgrav } 827*8ed2b524SDag-Erling Smørgrav 828*8ed2b524SDag-Erling Smørgrav /** 829*8ed2b524SDag-Erling Smørgrav * Setup key and digest for verification. Adjust sig if necessary. 830*8ed2b524SDag-Erling Smørgrav * 831*8ed2b524SDag-Erling Smørgrav * @param algo: key algorithm 832*8ed2b524SDag-Erling Smørgrav * @param evp_key: EVP PKEY public key to create. 833*8ed2b524SDag-Erling Smørgrav * @param digest_type: digest type to use 834*8ed2b524SDag-Erling Smørgrav * @param key: key to setup for. 835*8ed2b524SDag-Erling Smørgrav * @param keylen: length of key. 836*8ed2b524SDag-Erling Smørgrav * @param prefix: if returned, the ASN prefix for the hashblob. 837*8ed2b524SDag-Erling Smørgrav * @param prefixlen: length of the prefix. 838*8ed2b524SDag-Erling Smørgrav * @return false on failure. 839*8ed2b524SDag-Erling Smørgrav */ 840*8ed2b524SDag-Erling Smørgrav static int 841*8ed2b524SDag-Erling Smørgrav nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype, 842*8ed2b524SDag-Erling Smørgrav unsigned char* key, size_t keylen, unsigned char** prefix, 843*8ed2b524SDag-Erling Smørgrav size_t* prefixlen) 844*8ed2b524SDag-Erling Smørgrav { 845*8ed2b524SDag-Erling Smørgrav /* uses libNSS */ 846*8ed2b524SDag-Erling Smørgrav 847*8ed2b524SDag-Erling Smørgrav /* hash prefix for md5, RFC2537 */ 848*8ed2b524SDag-Erling Smørgrav unsigned char p_md5[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 849*8ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}; 850*8ed2b524SDag-Erling Smørgrav /* hash prefix to prepend to hash output, from RFC3110 */ 851*8ed2b524SDag-Erling Smørgrav unsigned char p_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 852*8ed2b524SDag-Erling Smørgrav 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14}; 853*8ed2b524SDag-Erling Smørgrav /* from RFC5702 */ 854*8ed2b524SDag-Erling Smørgrav unsigned char p_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 855*8ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; 856*8ed2b524SDag-Erling Smørgrav unsigned char p_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 857*8ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}; 858*8ed2b524SDag-Erling Smørgrav /* from RFC6234 */ 859*8ed2b524SDag-Erling Smørgrav /* for future RSASHA384 .. 860*8ed2b524SDag-Erling Smørgrav unsigned char p_sha384[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 861*8ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}; 862*8ed2b524SDag-Erling Smørgrav */ 863*8ed2b524SDag-Erling Smørgrav 864*8ed2b524SDag-Erling Smørgrav switch(algo) { 865*8ed2b524SDag-Erling Smørgrav case LDNS_DSA: 866*8ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 867*8ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2dsa(key, keylen); 868*8ed2b524SDag-Erling Smørgrav if(!*pubkey) { 869*8ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 870*8ed2b524SDag-Erling Smørgrav return 0; 871*8ed2b524SDag-Erling Smørgrav } 872*8ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA1; 873*8ed2b524SDag-Erling Smørgrav /* no prefix for DSA verification */ 874*8ed2b524SDag-Erling Smørgrav break; 875*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1: 876*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 877*8ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 878*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256: 879*8ed2b524SDag-Erling Smørgrav #endif 880*8ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 881*8ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512: 882*8ed2b524SDag-Erling Smørgrav #endif 883*8ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2rsa(key, keylen); 884*8ed2b524SDag-Erling Smørgrav if(!*pubkey) { 885*8ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 886*8ed2b524SDag-Erling Smørgrav return 0; 887*8ed2b524SDag-Erling Smørgrav } 888*8ed2b524SDag-Erling Smørgrav /* select SHA version */ 889*8ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 890*8ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA256) { 891*8ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA256; 892*8ed2b524SDag-Erling Smørgrav *prefix = p_sha256; 893*8ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_sha256); 894*8ed2b524SDag-Erling Smørgrav } else 895*8ed2b524SDag-Erling Smørgrav #endif 896*8ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 897*8ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA512) { 898*8ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA512; 899*8ed2b524SDag-Erling Smørgrav *prefix = p_sha512; 900*8ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_sha512); 901*8ed2b524SDag-Erling Smørgrav } else 902*8ed2b524SDag-Erling Smørgrav #endif 903*8ed2b524SDag-Erling Smørgrav { 904*8ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA1; 905*8ed2b524SDag-Erling Smørgrav *prefix = p_sha1; 906*8ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_sha1); 907*8ed2b524SDag-Erling Smørgrav } 908*8ed2b524SDag-Erling Smørgrav 909*8ed2b524SDag-Erling Smørgrav break; 910*8ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5: 911*8ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2rsa(key, keylen); 912*8ed2b524SDag-Erling Smørgrav if(!*pubkey) { 913*8ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 914*8ed2b524SDag-Erling Smørgrav return 0; 915*8ed2b524SDag-Erling Smørgrav } 916*8ed2b524SDag-Erling Smørgrav *htype = HASH_AlgMD5; 917*8ed2b524SDag-Erling Smørgrav *prefix = p_md5; 918*8ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_md5); 919*8ed2b524SDag-Erling Smørgrav 920*8ed2b524SDag-Erling Smørgrav break; 921*8ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 922*8ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 923*8ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2ecdsa(key, keylen, 924*8ed2b524SDag-Erling Smørgrav LDNS_ECDSAP256SHA256); 925*8ed2b524SDag-Erling Smørgrav if(!*pubkey) { 926*8ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 927*8ed2b524SDag-Erling Smørgrav return 0; 928*8ed2b524SDag-Erling Smørgrav } 929*8ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA256; 930*8ed2b524SDag-Erling Smørgrav /* no prefix for DSA verification */ 931*8ed2b524SDag-Erling Smørgrav break; 932*8ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 933*8ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2ecdsa(key, keylen, 934*8ed2b524SDag-Erling Smørgrav LDNS_ECDSAP384SHA384); 935*8ed2b524SDag-Erling Smørgrav if(!*pubkey) { 936*8ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 937*8ed2b524SDag-Erling Smørgrav return 0; 938*8ed2b524SDag-Erling Smørgrav } 939*8ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA384; 940*8ed2b524SDag-Erling Smørgrav /* no prefix for DSA verification */ 941*8ed2b524SDag-Erling Smørgrav break; 942*8ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */ 943*8ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST: 944*8ed2b524SDag-Erling Smørgrav default: 945*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: unknown algorithm %d", 946*8ed2b524SDag-Erling Smørgrav algo); 947*8ed2b524SDag-Erling Smørgrav return 0; 948*8ed2b524SDag-Erling Smørgrav } 949*8ed2b524SDag-Erling Smørgrav return 1; 950*8ed2b524SDag-Erling Smørgrav } 951*8ed2b524SDag-Erling Smørgrav 952*8ed2b524SDag-Erling Smørgrav /** 953*8ed2b524SDag-Erling Smørgrav * Check a canonical sig+rrset and signature against a dnskey 954*8ed2b524SDag-Erling Smørgrav * @param buf: buffer with data to verify, the first rrsig part and the 955*8ed2b524SDag-Erling Smørgrav * canonicalized rrset. 956*8ed2b524SDag-Erling Smørgrav * @param algo: DNSKEY algorithm. 957*8ed2b524SDag-Erling Smørgrav * @param sigblock: signature rdata field from RRSIG 958*8ed2b524SDag-Erling Smørgrav * @param sigblock_len: length of sigblock data. 959*8ed2b524SDag-Erling Smørgrav * @param key: public key data from DNSKEY RR. 960*8ed2b524SDag-Erling Smørgrav * @param keylen: length of keydata. 961*8ed2b524SDag-Erling Smørgrav * @param reason: bogus reason in more detail. 962*8ed2b524SDag-Erling Smørgrav * @return secure if verification succeeded, bogus on crypto failure, 963*8ed2b524SDag-Erling Smørgrav * unchecked on format errors and alloc failures. 964*8ed2b524SDag-Erling Smørgrav */ 965*8ed2b524SDag-Erling Smørgrav enum sec_status 966*8ed2b524SDag-Erling Smørgrav verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock, 967*8ed2b524SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen, 968*8ed2b524SDag-Erling Smørgrav char** reason) 969*8ed2b524SDag-Erling Smørgrav { 970*8ed2b524SDag-Erling Smørgrav /* uses libNSS */ 971*8ed2b524SDag-Erling Smørgrav /* large enough for the different hashes */ 972*8ed2b524SDag-Erling Smørgrav unsigned char hash[HASH_LENGTH_MAX]; 973*8ed2b524SDag-Erling Smørgrav unsigned char hash2[HASH_LENGTH_MAX*2]; 974*8ed2b524SDag-Erling Smørgrav HASH_HashType htype = 0; 975*8ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pubkey = NULL; 976*8ed2b524SDag-Erling Smørgrav SECItem secsig = {siBuffer, sigblock, sigblock_len}; 977*8ed2b524SDag-Erling Smørgrav SECItem sechash = {siBuffer, hash, 0}; 978*8ed2b524SDag-Erling Smørgrav SECStatus res; 979*8ed2b524SDag-Erling Smørgrav unsigned char* prefix = NULL; /* prefix for hash, RFC3110, RFC5702 */ 980*8ed2b524SDag-Erling Smørgrav size_t prefixlen = 0; 981*8ed2b524SDag-Erling Smørgrav int err; 982*8ed2b524SDag-Erling Smørgrav 983*8ed2b524SDag-Erling Smørgrav if(!nss_setup_key_digest(algo, &pubkey, &htype, key, keylen, 984*8ed2b524SDag-Erling Smørgrav &prefix, &prefixlen)) { 985*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup key"); 986*8ed2b524SDag-Erling Smørgrav *reason = "use of key for crypto failed"; 987*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 988*8ed2b524SDag-Erling Smørgrav return sec_status_bogus; 989*8ed2b524SDag-Erling Smørgrav } 990*8ed2b524SDag-Erling Smørgrav 991*8ed2b524SDag-Erling Smørgrav /* need to convert DSA, ECDSA signatures? */ 992*8ed2b524SDag-Erling Smørgrav if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) { 993*8ed2b524SDag-Erling Smørgrav if(sigblock_len == 1+2*SHA1_LENGTH) { 994*8ed2b524SDag-Erling Smørgrav secsig.data ++; 995*8ed2b524SDag-Erling Smørgrav secsig.len --; 996*8ed2b524SDag-Erling Smørgrav } else { 997*8ed2b524SDag-Erling Smørgrav SECItem* p = DSAU_DecodeDerSig(&secsig); 998*8ed2b524SDag-Erling Smørgrav if(!p) { 999*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed DER decode"); 1000*8ed2b524SDag-Erling Smørgrav *reason = "signature DER decode failed"; 1001*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 1002*8ed2b524SDag-Erling Smørgrav return sec_status_bogus; 1003*8ed2b524SDag-Erling Smørgrav } 1004*8ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pubkey->arena, &secsig, p)) { 1005*8ed2b524SDag-Erling Smørgrav log_err("alloc failure in DER decode"); 1006*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 1007*8ed2b524SDag-Erling Smørgrav SECITEM_FreeItem(p, PR_TRUE); 1008*8ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 1009*8ed2b524SDag-Erling Smørgrav } 1010*8ed2b524SDag-Erling Smørgrav SECITEM_FreeItem(p, PR_TRUE); 1011*8ed2b524SDag-Erling Smørgrav } 1012*8ed2b524SDag-Erling Smørgrav } 1013*8ed2b524SDag-Erling Smørgrav 1014*8ed2b524SDag-Erling Smørgrav /* do the signature cryptography work */ 1015*8ed2b524SDag-Erling Smørgrav /* hash the data */ 1016*8ed2b524SDag-Erling Smørgrav sechash.len = HASH_ResultLen(htype); 1017*8ed2b524SDag-Erling Smørgrav if(sechash.len > sizeof(hash)) { 1018*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: hash too large for buffer"); 1019*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 1020*8ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 1021*8ed2b524SDag-Erling Smørgrav } 1022*8ed2b524SDag-Erling Smørgrav if(HASH_HashBuf(htype, hash, (unsigned char*)ldns_buffer_begin(buf), 1023*8ed2b524SDag-Erling Smørgrav (unsigned int)ldns_buffer_limit(buf)) != SECSuccess) { 1024*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: HASH_HashBuf failed"); 1025*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 1026*8ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 1027*8ed2b524SDag-Erling Smørgrav } 1028*8ed2b524SDag-Erling Smørgrav if(prefix) { 1029*8ed2b524SDag-Erling Smørgrav int hashlen = sechash.len; 1030*8ed2b524SDag-Erling Smørgrav if(prefixlen+hashlen > sizeof(hash2)) { 1031*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: hashprefix too large"); 1032*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 1033*8ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 1034*8ed2b524SDag-Erling Smørgrav } 1035*8ed2b524SDag-Erling Smørgrav sechash.data = hash2; 1036*8ed2b524SDag-Erling Smørgrav sechash.len = prefixlen+hashlen; 1037*8ed2b524SDag-Erling Smørgrav memcpy(sechash.data, prefix, prefixlen); 1038*8ed2b524SDag-Erling Smørgrav memmove(sechash.data+prefixlen, hash, hashlen); 1039*8ed2b524SDag-Erling Smørgrav } 1040*8ed2b524SDag-Erling Smørgrav 1041*8ed2b524SDag-Erling Smørgrav /* verify the signature */ 1042*8ed2b524SDag-Erling Smørgrav res = PK11_Verify(pubkey, &secsig, &sechash, NULL /*wincx*/); 1043*8ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 1044*8ed2b524SDag-Erling Smørgrav 1045*8ed2b524SDag-Erling Smørgrav if(res == SECSuccess) { 1046*8ed2b524SDag-Erling Smørgrav return sec_status_secure; 1047*8ed2b524SDag-Erling Smørgrav } 1048*8ed2b524SDag-Erling Smørgrav err = PORT_GetError(); 1049*8ed2b524SDag-Erling Smørgrav if(err != SEC_ERROR_BAD_SIGNATURE) { 1050*8ed2b524SDag-Erling Smørgrav /* failed to verify */ 1051*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: PK11_Verify failed: %s", 1052*8ed2b524SDag-Erling Smørgrav PORT_ErrorToString(err)); 1053*8ed2b524SDag-Erling Smørgrav /* if it is not supported, like ECC is removed, we get, 1054*8ed2b524SDag-Erling Smørgrav * SEC_ERROR_NO_MODULE */ 1055*8ed2b524SDag-Erling Smørgrav if(err == SEC_ERROR_NO_MODULE) 1056*8ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 1057*8ed2b524SDag-Erling Smørgrav /* but other errors are commonly returned 1058*8ed2b524SDag-Erling Smørgrav * for a bad signature from NSS. Thus we return bogus, 1059*8ed2b524SDag-Erling Smørgrav * not unchecked */ 1060*8ed2b524SDag-Erling Smørgrav *reason = "signature crypto failed"; 1061*8ed2b524SDag-Erling Smørgrav return sec_status_bogus; 1062*8ed2b524SDag-Erling Smørgrav } 1063*8ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: signature mismatch: %s", 1064*8ed2b524SDag-Erling Smørgrav PORT_ErrorToString(err)); 1065*8ed2b524SDag-Erling Smørgrav *reason = "signature crypto failed"; 1066*8ed2b524SDag-Erling Smørgrav return sec_status_bogus; 1067*8ed2b524SDag-Erling Smørgrav } 1068*8ed2b524SDag-Erling Smørgrav 1069*8ed2b524SDag-Erling Smørgrav 1070*8ed2b524SDag-Erling Smørgrav #endif /* HAVE_SSL or HAVE_NSS */ 1071