18ed2b524SDag-Erling Smørgrav /* 28ed2b524SDag-Erling Smørgrav * validator/val_secalgo.c - validator security algorithm functions. 38ed2b524SDag-Erling Smørgrav * 48ed2b524SDag-Erling Smørgrav * Copyright (c) 2012, NLnet Labs. All rights reserved. 58ed2b524SDag-Erling Smørgrav * 68ed2b524SDag-Erling Smørgrav * This software is open source. 78ed2b524SDag-Erling Smørgrav * 88ed2b524SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 98ed2b524SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 108ed2b524SDag-Erling Smørgrav * are met: 118ed2b524SDag-Erling Smørgrav * 128ed2b524SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 138ed2b524SDag-Erling Smørgrav * this list of conditions and the following disclaimer. 148ed2b524SDag-Erling Smørgrav * 158ed2b524SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 168ed2b524SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 178ed2b524SDag-Erling Smørgrav * and/or other materials provided with the distribution. 188ed2b524SDag-Erling Smørgrav * 198ed2b524SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 208ed2b524SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 218ed2b524SDag-Erling Smørgrav * specific prior written permission. 228ed2b524SDag-Erling Smørgrav * 238ed2b524SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2417d15b25SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2517d15b25SDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2617d15b25SDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2717d15b25SDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2817d15b25SDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2917d15b25SDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3017d15b25SDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3117d15b25SDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3217d15b25SDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3317d15b25SDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 348ed2b524SDag-Erling Smørgrav */ 358ed2b524SDag-Erling Smørgrav 368ed2b524SDag-Erling Smørgrav /** 378ed2b524SDag-Erling Smørgrav * \file 388ed2b524SDag-Erling Smørgrav * 398ed2b524SDag-Erling Smørgrav * This file contains helper functions for the validator module. 408ed2b524SDag-Erling Smørgrav * These functions take raw data buffers, formatted for crypto verification, 418ed2b524SDag-Erling Smørgrav * and do the library calls (for the crypto library in use). 428ed2b524SDag-Erling Smørgrav */ 438ed2b524SDag-Erling Smørgrav #include "config.h" 446480faa8SDag-Erling Smørgrav /* packed_rrset on top to define enum types (forced by c99 standard) */ 458ed2b524SDag-Erling Smørgrav #include "util/data/packed_rrset.h" 466480faa8SDag-Erling Smørgrav #include "validator/val_secalgo.h" 47*05ab2901SDag-Erling Smørgrav #include "validator/val_nsec3.h" 488ed2b524SDag-Erling Smørgrav #include "util/log.h" 4909a3aaf3SDag-Erling Smørgrav #include "sldns/rrdef.h" 5009a3aaf3SDag-Erling Smørgrav #include "sldns/keyraw.h" 5109a3aaf3SDag-Erling Smørgrav #include "sldns/sbuffer.h" 528ed2b524SDag-Erling Smørgrav 53*05ab2901SDag-Erling Smørgrav #if !defined(HAVE_SSL) && !defined(HAVE_NSS) && !defined(HAVE_NETTLE) 548ed2b524SDag-Erling Smørgrav #error "Need crypto library to do digital signature cryptography" 558ed2b524SDag-Erling Smørgrav #endif 568ed2b524SDag-Erling Smørgrav 578ed2b524SDag-Erling Smørgrav /* OpenSSL implementation */ 588ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 598ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ERR_H 608ed2b524SDag-Erling Smørgrav #include <openssl/err.h> 618ed2b524SDag-Erling Smørgrav #endif 628ed2b524SDag-Erling Smørgrav 638ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_RAND_H 648ed2b524SDag-Erling Smørgrav #include <openssl/rand.h> 658ed2b524SDag-Erling Smørgrav #endif 668ed2b524SDag-Erling Smørgrav 678ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_CONF_H 688ed2b524SDag-Erling Smørgrav #include <openssl/conf.h> 698ed2b524SDag-Erling Smørgrav #endif 708ed2b524SDag-Erling Smørgrav 718ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ENGINE_H 728ed2b524SDag-Erling Smørgrav #include <openssl/engine.h> 738ed2b524SDag-Erling Smørgrav #endif 748ed2b524SDag-Erling Smørgrav 75*05ab2901SDag-Erling Smørgrav /* return size of digest if supported, or 0 otherwise */ 76*05ab2901SDag-Erling Smørgrav size_t 77*05ab2901SDag-Erling Smørgrav nsec3_hash_algo_size_supported(int id) 78*05ab2901SDag-Erling Smørgrav { 79*05ab2901SDag-Erling Smørgrav switch(id) { 80*05ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1: 81*05ab2901SDag-Erling Smørgrav return SHA_DIGEST_LENGTH; 82*05ab2901SDag-Erling Smørgrav default: 83*05ab2901SDag-Erling Smørgrav return 0; 84*05ab2901SDag-Erling Smørgrav } 85*05ab2901SDag-Erling Smørgrav } 86*05ab2901SDag-Erling Smørgrav 87*05ab2901SDag-Erling Smørgrav /* perform nsec3 hash. return false on failure */ 88*05ab2901SDag-Erling Smørgrav int 89*05ab2901SDag-Erling Smørgrav secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, 90*05ab2901SDag-Erling Smørgrav unsigned char* res) 91*05ab2901SDag-Erling Smørgrav { 92*05ab2901SDag-Erling Smørgrav switch(algo) { 93*05ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1: 94*05ab2901SDag-Erling Smørgrav (void)SHA1(buf, len, res); 95*05ab2901SDag-Erling Smørgrav return 1; 96*05ab2901SDag-Erling Smørgrav default: 97*05ab2901SDag-Erling Smørgrav return 0; 98*05ab2901SDag-Erling Smørgrav } 99*05ab2901SDag-Erling Smørgrav } 100*05ab2901SDag-Erling Smørgrav 1018ed2b524SDag-Erling Smørgrav /** 1028ed2b524SDag-Erling Smørgrav * Return size of DS digest according to its hash algorithm. 1038ed2b524SDag-Erling Smørgrav * @param algo: DS digest algo. 1048ed2b524SDag-Erling Smørgrav * @return size in bytes of digest, or 0 if not supported. 1058ed2b524SDag-Erling Smørgrav */ 1068ed2b524SDag-Erling Smørgrav size_t 1078ed2b524SDag-Erling Smørgrav ds_digest_size_supported(int algo) 1088ed2b524SDag-Erling Smørgrav { 1098ed2b524SDag-Erling Smørgrav switch(algo) { 1108ed2b524SDag-Erling Smørgrav #ifdef HAVE_EVP_SHA1 1118ed2b524SDag-Erling Smørgrav case LDNS_SHA1: 1128ed2b524SDag-Erling Smørgrav return SHA_DIGEST_LENGTH; 1138ed2b524SDag-Erling Smørgrav #endif 1148ed2b524SDag-Erling Smørgrav #ifdef HAVE_EVP_SHA256 1158ed2b524SDag-Erling Smørgrav case LDNS_SHA256: 1168ed2b524SDag-Erling Smørgrav return SHA256_DIGEST_LENGTH; 1178ed2b524SDag-Erling Smørgrav #endif 1188ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 1198ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST: 1208ed2b524SDag-Erling Smørgrav if(EVP_get_digestbyname("md_gost94")) 1218ed2b524SDag-Erling Smørgrav return 32; 1228ed2b524SDag-Erling Smørgrav else return 0; 1238ed2b524SDag-Erling Smørgrav #endif 1248ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 1258ed2b524SDag-Erling Smørgrav case LDNS_SHA384: 1268ed2b524SDag-Erling Smørgrav return SHA384_DIGEST_LENGTH; 1278ed2b524SDag-Erling Smørgrav #endif 1288ed2b524SDag-Erling Smørgrav default: break; 1298ed2b524SDag-Erling Smørgrav } 1308ed2b524SDag-Erling Smørgrav return 0; 1318ed2b524SDag-Erling Smørgrav } 1328ed2b524SDag-Erling Smørgrav 1338ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 1348ed2b524SDag-Erling Smørgrav /** Perform GOST hash */ 1358ed2b524SDag-Erling Smørgrav static int 1368ed2b524SDag-Erling Smørgrav do_gost94(unsigned char* data, size_t len, unsigned char* dest) 1378ed2b524SDag-Erling Smørgrav { 1388ed2b524SDag-Erling Smørgrav const EVP_MD* md = EVP_get_digestbyname("md_gost94"); 1398ed2b524SDag-Erling Smørgrav if(!md) 1408ed2b524SDag-Erling Smørgrav return 0; 14117d15b25SDag-Erling Smørgrav return sldns_digest_evp(data, (unsigned int)len, dest, md); 1428ed2b524SDag-Erling Smørgrav } 1438ed2b524SDag-Erling Smørgrav #endif 1448ed2b524SDag-Erling Smørgrav 1458ed2b524SDag-Erling Smørgrav int 1468ed2b524SDag-Erling Smørgrav secalgo_ds_digest(int algo, unsigned char* buf, size_t len, 1478ed2b524SDag-Erling Smørgrav unsigned char* res) 1488ed2b524SDag-Erling Smørgrav { 1498ed2b524SDag-Erling Smørgrav switch(algo) { 1508ed2b524SDag-Erling Smørgrav #ifdef HAVE_EVP_SHA1 1518ed2b524SDag-Erling Smørgrav case LDNS_SHA1: 1528ed2b524SDag-Erling Smørgrav (void)SHA1(buf, len, res); 1538ed2b524SDag-Erling Smørgrav return 1; 1548ed2b524SDag-Erling Smørgrav #endif 1558ed2b524SDag-Erling Smørgrav #ifdef HAVE_EVP_SHA256 1568ed2b524SDag-Erling Smørgrav case LDNS_SHA256: 1578ed2b524SDag-Erling Smørgrav (void)SHA256(buf, len, res); 1588ed2b524SDag-Erling Smørgrav return 1; 1598ed2b524SDag-Erling Smørgrav #endif 1608ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 1618ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST: 1628ed2b524SDag-Erling Smørgrav if(do_gost94(buf, len, res)) 1638ed2b524SDag-Erling Smørgrav return 1; 1648ed2b524SDag-Erling Smørgrav break; 1658ed2b524SDag-Erling Smørgrav #endif 1668ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 1678ed2b524SDag-Erling Smørgrav case LDNS_SHA384: 1688ed2b524SDag-Erling Smørgrav (void)SHA384(buf, len, res); 1698ed2b524SDag-Erling Smørgrav return 1; 1708ed2b524SDag-Erling Smørgrav #endif 1718ed2b524SDag-Erling Smørgrav default: 1728ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "unknown DS digest algorithm %d", 1738ed2b524SDag-Erling Smørgrav algo); 1748ed2b524SDag-Erling Smørgrav break; 1758ed2b524SDag-Erling Smørgrav } 1768ed2b524SDag-Erling Smørgrav return 0; 1778ed2b524SDag-Erling Smørgrav } 1788ed2b524SDag-Erling Smørgrav 1798ed2b524SDag-Erling Smørgrav /** return true if DNSKEY algorithm id is supported */ 1808ed2b524SDag-Erling Smørgrav int 1818ed2b524SDag-Erling Smørgrav dnskey_algo_id_is_supported(int id) 1828ed2b524SDag-Erling Smørgrav { 1838ed2b524SDag-Erling Smørgrav switch(id) { 1848ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5: 1858ed2b524SDag-Erling Smørgrav /* RFC 6725 deprecates RSAMD5 */ 1868ed2b524SDag-Erling Smørgrav return 0; 1878ed2b524SDag-Erling Smørgrav case LDNS_DSA: 1888ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 1898ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1: 1908ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 1918ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) 1928ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256: 1938ed2b524SDag-Erling Smørgrav #endif 1948ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) 1958ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512: 1968ed2b524SDag-Erling Smørgrav #endif 1978ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 1988ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 1998ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 2008ed2b524SDag-Erling Smørgrav #endif 2018ed2b524SDag-Erling Smørgrav return 1; 2028ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 2038ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST: 2048ed2b524SDag-Erling Smørgrav /* we support GOST if it can be loaded */ 20517d15b25SDag-Erling Smørgrav return sldns_key_EVP_load_gost_id(); 2068ed2b524SDag-Erling Smørgrav #endif 2078ed2b524SDag-Erling Smørgrav default: 2088ed2b524SDag-Erling Smørgrav return 0; 2098ed2b524SDag-Erling Smørgrav } 2108ed2b524SDag-Erling Smørgrav } 2118ed2b524SDag-Erling Smørgrav 2128ed2b524SDag-Erling Smørgrav /** 2138ed2b524SDag-Erling Smørgrav * Output a libcrypto openssl error to the logfile. 2148ed2b524SDag-Erling Smørgrav * @param str: string to add to it. 2158ed2b524SDag-Erling Smørgrav * @param e: the error to output, error number from ERR_get_error(). 2168ed2b524SDag-Erling Smørgrav */ 2178ed2b524SDag-Erling Smørgrav static void 2188ed2b524SDag-Erling Smørgrav log_crypto_error(const char* str, unsigned long e) 2198ed2b524SDag-Erling Smørgrav { 2208ed2b524SDag-Erling Smørgrav char buf[128]; 2218ed2b524SDag-Erling Smørgrav /* or use ERR_error_string if ERR_error_string_n is not avail TODO */ 2228ed2b524SDag-Erling Smørgrav ERR_error_string_n(e, buf, sizeof(buf)); 2238ed2b524SDag-Erling Smørgrav /* buf now contains */ 2248ed2b524SDag-Erling Smørgrav /* error:[error code]:[library name]:[function name]:[reason string] */ 2258ed2b524SDag-Erling Smørgrav log_err("%s crypto %s", str, buf); 2268ed2b524SDag-Erling Smørgrav } 2278ed2b524SDag-Erling Smørgrav 2288ed2b524SDag-Erling Smørgrav /** 2298ed2b524SDag-Erling Smørgrav * Setup DSA key digest in DER encoding ... 2308ed2b524SDag-Erling Smørgrav * @param sig: input is signature output alloced ptr (unless failure). 2318ed2b524SDag-Erling Smørgrav * caller must free alloced ptr if this routine returns true. 2328ed2b524SDag-Erling Smørgrav * @param len: input is initial siglen, output is output len. 2338ed2b524SDag-Erling Smørgrav * @return false on failure. 2348ed2b524SDag-Erling Smørgrav */ 2358ed2b524SDag-Erling Smørgrav static int 2368ed2b524SDag-Erling Smørgrav setup_dsa_sig(unsigned char** sig, unsigned int* len) 2378ed2b524SDag-Erling Smørgrav { 2388ed2b524SDag-Erling Smørgrav unsigned char* orig = *sig; 2398ed2b524SDag-Erling Smørgrav unsigned int origlen = *len; 2408ed2b524SDag-Erling Smørgrav int newlen; 2418ed2b524SDag-Erling Smørgrav BIGNUM *R, *S; 2428ed2b524SDag-Erling Smørgrav DSA_SIG *dsasig; 2438ed2b524SDag-Erling Smørgrav 2448ed2b524SDag-Erling Smørgrav /* extract the R and S field from the sig buffer */ 2458ed2b524SDag-Erling Smørgrav if(origlen < 1 + 2*SHA_DIGEST_LENGTH) 2468ed2b524SDag-Erling Smørgrav return 0; 2478ed2b524SDag-Erling Smørgrav R = BN_new(); 2488ed2b524SDag-Erling Smørgrav if(!R) return 0; 2498ed2b524SDag-Erling Smørgrav (void) BN_bin2bn(orig + 1, SHA_DIGEST_LENGTH, R); 2508ed2b524SDag-Erling Smørgrav S = BN_new(); 2518ed2b524SDag-Erling Smørgrav if(!S) return 0; 2528ed2b524SDag-Erling Smørgrav (void) BN_bin2bn(orig + 21, SHA_DIGEST_LENGTH, S); 2538ed2b524SDag-Erling Smørgrav dsasig = DSA_SIG_new(); 2548ed2b524SDag-Erling Smørgrav if(!dsasig) return 0; 2558ed2b524SDag-Erling Smørgrav 2568ed2b524SDag-Erling Smørgrav dsasig->r = R; 2578ed2b524SDag-Erling Smørgrav dsasig->s = S; 2588ed2b524SDag-Erling Smørgrav *sig = NULL; 2598ed2b524SDag-Erling Smørgrav newlen = i2d_DSA_SIG(dsasig, sig); 2608ed2b524SDag-Erling Smørgrav if(newlen < 0) { 2618ed2b524SDag-Erling Smørgrav DSA_SIG_free(dsasig); 2628ed2b524SDag-Erling Smørgrav free(*sig); 2638ed2b524SDag-Erling Smørgrav return 0; 2648ed2b524SDag-Erling Smørgrav } 2658ed2b524SDag-Erling Smørgrav *len = (unsigned int)newlen; 2668ed2b524SDag-Erling Smørgrav DSA_SIG_free(dsasig); 2678ed2b524SDag-Erling Smørgrav return 1; 2688ed2b524SDag-Erling Smørgrav } 2698ed2b524SDag-Erling Smørgrav 2708ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 2718ed2b524SDag-Erling Smørgrav /** 2728ed2b524SDag-Erling Smørgrav * Setup the ECDSA signature in its encoding that the library wants. 2738ed2b524SDag-Erling Smørgrav * Converts from plain numbers to ASN formatted. 2748ed2b524SDag-Erling Smørgrav * @param sig: input is signature, output alloced ptr (unless failure). 2758ed2b524SDag-Erling Smørgrav * caller must free alloced ptr if this routine returns true. 2768ed2b524SDag-Erling Smørgrav * @param len: input is initial siglen, output is output len. 2778ed2b524SDag-Erling Smørgrav * @return false on failure. 2788ed2b524SDag-Erling Smørgrav */ 2798ed2b524SDag-Erling Smørgrav static int 2808ed2b524SDag-Erling Smørgrav setup_ecdsa_sig(unsigned char** sig, unsigned int* len) 2818ed2b524SDag-Erling Smørgrav { 2828ed2b524SDag-Erling Smørgrav ECDSA_SIG* ecdsa_sig; 2838ed2b524SDag-Erling Smørgrav int newlen; 2848ed2b524SDag-Erling Smørgrav int bnsize = (int)((*len)/2); 2858ed2b524SDag-Erling Smørgrav /* if too short or not even length, fails */ 2868ed2b524SDag-Erling Smørgrav if(*len < 16 || bnsize*2 != (int)*len) 2878ed2b524SDag-Erling Smørgrav return 0; 2888ed2b524SDag-Erling Smørgrav /* use the raw data to parse two evenly long BIGNUMs, "r | s". */ 2898ed2b524SDag-Erling Smørgrav ecdsa_sig = ECDSA_SIG_new(); 2908ed2b524SDag-Erling Smørgrav if(!ecdsa_sig) return 0; 2918ed2b524SDag-Erling Smørgrav ecdsa_sig->r = BN_bin2bn(*sig, bnsize, ecdsa_sig->r); 2928ed2b524SDag-Erling Smørgrav ecdsa_sig->s = BN_bin2bn(*sig+bnsize, bnsize, ecdsa_sig->s); 2938ed2b524SDag-Erling Smørgrav if(!ecdsa_sig->r || !ecdsa_sig->s) { 2948ed2b524SDag-Erling Smørgrav ECDSA_SIG_free(ecdsa_sig); 2958ed2b524SDag-Erling Smørgrav return 0; 2968ed2b524SDag-Erling Smørgrav } 2978ed2b524SDag-Erling Smørgrav 2988ed2b524SDag-Erling Smørgrav /* spool it into ASN format */ 2998ed2b524SDag-Erling Smørgrav *sig = NULL; 3008ed2b524SDag-Erling Smørgrav newlen = i2d_ECDSA_SIG(ecdsa_sig, sig); 3018ed2b524SDag-Erling Smørgrav if(newlen <= 0) { 3028ed2b524SDag-Erling Smørgrav ECDSA_SIG_free(ecdsa_sig); 3038ed2b524SDag-Erling Smørgrav free(*sig); 3048ed2b524SDag-Erling Smørgrav return 0; 3058ed2b524SDag-Erling Smørgrav } 3068ed2b524SDag-Erling Smørgrav *len = (unsigned int)newlen; 3078ed2b524SDag-Erling Smørgrav ECDSA_SIG_free(ecdsa_sig); 3088ed2b524SDag-Erling Smørgrav return 1; 3098ed2b524SDag-Erling Smørgrav } 3108ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */ 3118ed2b524SDag-Erling Smørgrav 3128ed2b524SDag-Erling Smørgrav /** 3138ed2b524SDag-Erling Smørgrav * Setup key and digest for verification. Adjust sig if necessary. 3148ed2b524SDag-Erling Smørgrav * 3158ed2b524SDag-Erling Smørgrav * @param algo: key algorithm 3168ed2b524SDag-Erling Smørgrav * @param evp_key: EVP PKEY public key to create. 3178ed2b524SDag-Erling Smørgrav * @param digest_type: digest type to use 3188ed2b524SDag-Erling Smørgrav * @param key: key to setup for. 3198ed2b524SDag-Erling Smørgrav * @param keylen: length of key. 3208ed2b524SDag-Erling Smørgrav * @return false on failure. 3218ed2b524SDag-Erling Smørgrav */ 3228ed2b524SDag-Erling Smørgrav static int 3238ed2b524SDag-Erling Smørgrav setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, 3248ed2b524SDag-Erling Smørgrav unsigned char* key, size_t keylen) 3258ed2b524SDag-Erling Smørgrav { 3268ed2b524SDag-Erling Smørgrav DSA* dsa; 3278ed2b524SDag-Erling Smørgrav RSA* rsa; 3288ed2b524SDag-Erling Smørgrav 3298ed2b524SDag-Erling Smørgrav switch(algo) { 3308ed2b524SDag-Erling Smørgrav case LDNS_DSA: 3318ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 3328ed2b524SDag-Erling Smørgrav *evp_key = EVP_PKEY_new(); 3338ed2b524SDag-Erling Smørgrav if(!*evp_key) { 3348ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 3358ed2b524SDag-Erling Smørgrav return 0; 3368ed2b524SDag-Erling Smørgrav } 33717d15b25SDag-Erling Smørgrav dsa = sldns_key_buf2dsa_raw(key, keylen); 3388ed2b524SDag-Erling Smørgrav if(!dsa) { 3398ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 34017d15b25SDag-Erling Smørgrav "sldns_key_buf2dsa_raw failed"); 3418ed2b524SDag-Erling Smørgrav return 0; 3428ed2b524SDag-Erling Smørgrav } 3438ed2b524SDag-Erling Smørgrav if(EVP_PKEY_assign_DSA(*evp_key, dsa) == 0) { 3448ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 3458ed2b524SDag-Erling Smørgrav "EVP_PKEY_assign_DSA failed"); 3468ed2b524SDag-Erling Smørgrav return 0; 3478ed2b524SDag-Erling Smørgrav } 3488ed2b524SDag-Erling Smørgrav *digest_type = EVP_dss1(); 3498ed2b524SDag-Erling Smørgrav 3508ed2b524SDag-Erling Smørgrav break; 3518ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1: 3528ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 3538ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) 3548ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256: 3558ed2b524SDag-Erling Smørgrav #endif 3568ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) 3578ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512: 3588ed2b524SDag-Erling Smørgrav #endif 3598ed2b524SDag-Erling Smørgrav *evp_key = EVP_PKEY_new(); 3608ed2b524SDag-Erling Smørgrav if(!*evp_key) { 3618ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 3628ed2b524SDag-Erling Smørgrav return 0; 3638ed2b524SDag-Erling Smørgrav } 36417d15b25SDag-Erling Smørgrav rsa = sldns_key_buf2rsa_raw(key, keylen); 3658ed2b524SDag-Erling Smørgrav if(!rsa) { 3668ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 36717d15b25SDag-Erling Smørgrav "sldns_key_buf2rsa_raw SHA failed"); 3688ed2b524SDag-Erling Smørgrav return 0; 3698ed2b524SDag-Erling Smørgrav } 3708ed2b524SDag-Erling Smørgrav if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) { 3718ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 3728ed2b524SDag-Erling Smørgrav "EVP_PKEY_assign_RSA SHA failed"); 3738ed2b524SDag-Erling Smørgrav return 0; 3748ed2b524SDag-Erling Smørgrav } 3758ed2b524SDag-Erling Smørgrav 3768ed2b524SDag-Erling Smørgrav /* select SHA version */ 3778ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) 3788ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA256) 3798ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha256(); 3808ed2b524SDag-Erling Smørgrav else 3818ed2b524SDag-Erling Smørgrav #endif 3828ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) 3838ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA512) 3848ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha512(); 3858ed2b524SDag-Erling Smørgrav else 3868ed2b524SDag-Erling Smørgrav #endif 3878ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha1(); 3888ed2b524SDag-Erling Smørgrav 3898ed2b524SDag-Erling Smørgrav break; 3908ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5: 3918ed2b524SDag-Erling Smørgrav *evp_key = EVP_PKEY_new(); 3928ed2b524SDag-Erling Smørgrav if(!*evp_key) { 3938ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 3948ed2b524SDag-Erling Smørgrav return 0; 3958ed2b524SDag-Erling Smørgrav } 39617d15b25SDag-Erling Smørgrav rsa = sldns_key_buf2rsa_raw(key, keylen); 3978ed2b524SDag-Erling Smørgrav if(!rsa) { 3988ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 39917d15b25SDag-Erling Smørgrav "sldns_key_buf2rsa_raw MD5 failed"); 4008ed2b524SDag-Erling Smørgrav return 0; 4018ed2b524SDag-Erling Smørgrav } 4028ed2b524SDag-Erling Smørgrav if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) { 4038ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 4048ed2b524SDag-Erling Smørgrav "EVP_PKEY_assign_RSA MD5 failed"); 4058ed2b524SDag-Erling Smørgrav return 0; 4068ed2b524SDag-Erling Smørgrav } 4078ed2b524SDag-Erling Smørgrav *digest_type = EVP_md5(); 4088ed2b524SDag-Erling Smørgrav 4098ed2b524SDag-Erling Smørgrav break; 4108ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 4118ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST: 41217d15b25SDag-Erling Smørgrav *evp_key = sldns_gost2pkey_raw(key, keylen); 4138ed2b524SDag-Erling Smørgrav if(!*evp_key) { 4148ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 41517d15b25SDag-Erling Smørgrav "sldns_gost2pkey_raw failed"); 4168ed2b524SDag-Erling Smørgrav return 0; 4178ed2b524SDag-Erling Smørgrav } 4188ed2b524SDag-Erling Smørgrav *digest_type = EVP_get_digestbyname("md_gost94"); 4198ed2b524SDag-Erling Smørgrav if(!*digest_type) { 4208ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 4218ed2b524SDag-Erling Smørgrav "EVP_getdigest md_gost94 failed"); 4228ed2b524SDag-Erling Smørgrav return 0; 4238ed2b524SDag-Erling Smørgrav } 4248ed2b524SDag-Erling Smørgrav break; 4258ed2b524SDag-Erling Smørgrav #endif 4268ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 4278ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 42817d15b25SDag-Erling Smørgrav *evp_key = sldns_ecdsa2pkey_raw(key, keylen, 4298ed2b524SDag-Erling Smørgrav LDNS_ECDSAP256SHA256); 4308ed2b524SDag-Erling Smørgrav if(!*evp_key) { 4318ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 43217d15b25SDag-Erling Smørgrav "sldns_ecdsa2pkey_raw failed"); 4338ed2b524SDag-Erling Smørgrav return 0; 4348ed2b524SDag-Erling Smørgrav } 4358ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA_EVP_WORKAROUND 4368ed2b524SDag-Erling Smørgrav /* openssl before 1.0.0 fixes RSA with the SHA256 4378ed2b524SDag-Erling Smørgrav * hash in EVP. We create one for ecdsa_sha256 */ 4388ed2b524SDag-Erling Smørgrav { 4398ed2b524SDag-Erling Smørgrav static int md_ecdsa_256_done = 0; 4408ed2b524SDag-Erling Smørgrav static EVP_MD md; 4418ed2b524SDag-Erling Smørgrav if(!md_ecdsa_256_done) { 4428ed2b524SDag-Erling Smørgrav EVP_MD m = *EVP_sha256(); 4438ed2b524SDag-Erling Smørgrav md_ecdsa_256_done = 1; 4448ed2b524SDag-Erling Smørgrav m.required_pkey_type[0] = (*evp_key)->type; 4458ed2b524SDag-Erling Smørgrav m.verify = (void*)ECDSA_verify; 4468ed2b524SDag-Erling Smørgrav md = m; 4478ed2b524SDag-Erling Smørgrav } 4488ed2b524SDag-Erling Smørgrav *digest_type = &md; 4498ed2b524SDag-Erling Smørgrav } 4508ed2b524SDag-Erling Smørgrav #else 4518ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha256(); 4528ed2b524SDag-Erling Smørgrav #endif 4538ed2b524SDag-Erling Smørgrav break; 4548ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 45517d15b25SDag-Erling Smørgrav *evp_key = sldns_ecdsa2pkey_raw(key, keylen, 4568ed2b524SDag-Erling Smørgrav LDNS_ECDSAP384SHA384); 4578ed2b524SDag-Erling Smørgrav if(!*evp_key) { 4588ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 45917d15b25SDag-Erling Smørgrav "sldns_ecdsa2pkey_raw failed"); 4608ed2b524SDag-Erling Smørgrav return 0; 4618ed2b524SDag-Erling Smørgrav } 4628ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA_EVP_WORKAROUND 4638ed2b524SDag-Erling Smørgrav /* openssl before 1.0.0 fixes RSA with the SHA384 4648ed2b524SDag-Erling Smørgrav * hash in EVP. We create one for ecdsa_sha384 */ 4658ed2b524SDag-Erling Smørgrav { 4668ed2b524SDag-Erling Smørgrav static int md_ecdsa_384_done = 0; 4678ed2b524SDag-Erling Smørgrav static EVP_MD md; 4688ed2b524SDag-Erling Smørgrav if(!md_ecdsa_384_done) { 4698ed2b524SDag-Erling Smørgrav EVP_MD m = *EVP_sha384(); 4708ed2b524SDag-Erling Smørgrav md_ecdsa_384_done = 1; 4718ed2b524SDag-Erling Smørgrav m.required_pkey_type[0] = (*evp_key)->type; 4728ed2b524SDag-Erling Smørgrav m.verify = (void*)ECDSA_verify; 4738ed2b524SDag-Erling Smørgrav md = m; 4748ed2b524SDag-Erling Smørgrav } 4758ed2b524SDag-Erling Smørgrav *digest_type = &md; 4768ed2b524SDag-Erling Smørgrav } 4778ed2b524SDag-Erling Smørgrav #else 4788ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha384(); 4798ed2b524SDag-Erling Smørgrav #endif 4808ed2b524SDag-Erling Smørgrav break; 4818ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */ 4828ed2b524SDag-Erling Smørgrav default: 4838ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: unknown algorithm %d", 4848ed2b524SDag-Erling Smørgrav algo); 4858ed2b524SDag-Erling Smørgrav return 0; 4868ed2b524SDag-Erling Smørgrav } 4878ed2b524SDag-Erling Smørgrav return 1; 4888ed2b524SDag-Erling Smørgrav } 4898ed2b524SDag-Erling Smørgrav 4908ed2b524SDag-Erling Smørgrav /** 4918ed2b524SDag-Erling Smørgrav * Check a canonical sig+rrset and signature against a dnskey 4928ed2b524SDag-Erling Smørgrav * @param buf: buffer with data to verify, the first rrsig part and the 4938ed2b524SDag-Erling Smørgrav * canonicalized rrset. 4948ed2b524SDag-Erling Smørgrav * @param algo: DNSKEY algorithm. 4958ed2b524SDag-Erling Smørgrav * @param sigblock: signature rdata field from RRSIG 4968ed2b524SDag-Erling Smørgrav * @param sigblock_len: length of sigblock data. 4978ed2b524SDag-Erling Smørgrav * @param key: public key data from DNSKEY RR. 4988ed2b524SDag-Erling Smørgrav * @param keylen: length of keydata. 4998ed2b524SDag-Erling Smørgrav * @param reason: bogus reason in more detail. 5008ed2b524SDag-Erling Smørgrav * @return secure if verification succeeded, bogus on crypto failure, 5018ed2b524SDag-Erling Smørgrav * unchecked on format errors and alloc failures. 5028ed2b524SDag-Erling Smørgrav */ 5038ed2b524SDag-Erling Smørgrav enum sec_status 50417d15b25SDag-Erling Smørgrav verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, 5058ed2b524SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen, 5068ed2b524SDag-Erling Smørgrav char** reason) 5078ed2b524SDag-Erling Smørgrav { 5088ed2b524SDag-Erling Smørgrav const EVP_MD *digest_type; 5098ed2b524SDag-Erling Smørgrav EVP_MD_CTX ctx; 5108ed2b524SDag-Erling Smørgrav int res, dofree = 0; 5118ed2b524SDag-Erling Smørgrav EVP_PKEY *evp_key = NULL; 5128ed2b524SDag-Erling Smørgrav 5138ed2b524SDag-Erling Smørgrav if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) { 5148ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup key"); 5158ed2b524SDag-Erling Smørgrav *reason = "use of key for crypto failed"; 5168ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 5178ed2b524SDag-Erling Smørgrav return sec_status_bogus; 5188ed2b524SDag-Erling Smørgrav } 5198ed2b524SDag-Erling Smørgrav /* if it is a DSA signature in bind format, convert to DER format */ 5208ed2b524SDag-Erling Smørgrav if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) && 5218ed2b524SDag-Erling Smørgrav sigblock_len == 1+2*SHA_DIGEST_LENGTH) { 5228ed2b524SDag-Erling Smørgrav if(!setup_dsa_sig(&sigblock, &sigblock_len)) { 5238ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup DSA sig"); 5248ed2b524SDag-Erling Smørgrav *reason = "use of key for DSA crypto failed"; 5258ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 5268ed2b524SDag-Erling Smørgrav return sec_status_bogus; 5278ed2b524SDag-Erling Smørgrav } 5288ed2b524SDag-Erling Smørgrav dofree = 1; 5298ed2b524SDag-Erling Smørgrav } 5308ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 5318ed2b524SDag-Erling Smørgrav else if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) { 5328ed2b524SDag-Erling Smørgrav /* EVP uses ASN prefix on sig, which is not in the wire data */ 5338ed2b524SDag-Erling Smørgrav if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) { 5348ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup ECDSA sig"); 5358ed2b524SDag-Erling Smørgrav *reason = "use of signature for ECDSA crypto failed"; 5368ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 5378ed2b524SDag-Erling Smørgrav return sec_status_bogus; 5388ed2b524SDag-Erling Smørgrav } 5398ed2b524SDag-Erling Smørgrav dofree = 1; 5408ed2b524SDag-Erling Smørgrav } 5418ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */ 5428ed2b524SDag-Erling Smørgrav 5438ed2b524SDag-Erling Smørgrav /* do the signature cryptography work */ 5448ed2b524SDag-Erling Smørgrav EVP_MD_CTX_init(&ctx); 5458ed2b524SDag-Erling Smørgrav if(EVP_VerifyInit(&ctx, digest_type) == 0) { 5468ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: EVP_VerifyInit failed"); 5478ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 5488ed2b524SDag-Erling Smørgrav if(dofree) free(sigblock); 5498ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 5508ed2b524SDag-Erling Smørgrav } 55117d15b25SDag-Erling Smørgrav if(EVP_VerifyUpdate(&ctx, (unsigned char*)sldns_buffer_begin(buf), 55217d15b25SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf)) == 0) { 5538ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: EVP_VerifyUpdate failed"); 5548ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 5558ed2b524SDag-Erling Smørgrav if(dofree) free(sigblock); 5568ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 5578ed2b524SDag-Erling Smørgrav } 5588ed2b524SDag-Erling Smørgrav 5598ed2b524SDag-Erling Smørgrav res = EVP_VerifyFinal(&ctx, sigblock, sigblock_len, evp_key); 5608ed2b524SDag-Erling Smørgrav if(EVP_MD_CTX_cleanup(&ctx) == 0) { 5618ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: EVP_MD_CTX_cleanup failed"); 5628ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 5638ed2b524SDag-Erling Smørgrav if(dofree) free(sigblock); 5648ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 5658ed2b524SDag-Erling Smørgrav } 5668ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 5678ed2b524SDag-Erling Smørgrav 5688ed2b524SDag-Erling Smørgrav if(dofree) 5698ed2b524SDag-Erling Smørgrav free(sigblock); 5708ed2b524SDag-Erling Smørgrav 5718ed2b524SDag-Erling Smørgrav if(res == 1) { 5728ed2b524SDag-Erling Smørgrav return sec_status_secure; 5738ed2b524SDag-Erling Smørgrav } else if(res == 0) { 5748ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: signature mismatch"); 5758ed2b524SDag-Erling Smørgrav *reason = "signature crypto failed"; 5768ed2b524SDag-Erling Smørgrav return sec_status_bogus; 5778ed2b524SDag-Erling Smørgrav } 5788ed2b524SDag-Erling Smørgrav 5798ed2b524SDag-Erling Smørgrav log_crypto_error("verify:", ERR_get_error()); 5808ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 5818ed2b524SDag-Erling Smørgrav } 5828ed2b524SDag-Erling Smørgrav 5838ed2b524SDag-Erling Smørgrav /**************************************************/ 5848ed2b524SDag-Erling Smørgrav #elif defined(HAVE_NSS) 5858ed2b524SDag-Erling Smørgrav /* libnss implementation */ 5868ed2b524SDag-Erling Smørgrav /* nss3 */ 5878ed2b524SDag-Erling Smørgrav #include "sechash.h" 5888ed2b524SDag-Erling Smørgrav #include "pk11pub.h" 5898ed2b524SDag-Erling Smørgrav #include "keyhi.h" 5908ed2b524SDag-Erling Smørgrav #include "secerr.h" 5918ed2b524SDag-Erling Smørgrav #include "cryptohi.h" 5928ed2b524SDag-Erling Smørgrav /* nspr4 */ 5938ed2b524SDag-Erling Smørgrav #include "prerror.h" 5948ed2b524SDag-Erling Smørgrav 595*05ab2901SDag-Erling Smørgrav /* return size of digest if supported, or 0 otherwise */ 596*05ab2901SDag-Erling Smørgrav size_t 597*05ab2901SDag-Erling Smørgrav nsec3_hash_algo_size_supported(int id) 598*05ab2901SDag-Erling Smørgrav { 599*05ab2901SDag-Erling Smørgrav switch(id) { 600*05ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1: 601*05ab2901SDag-Erling Smørgrav return SHA1_LENGTH; 602*05ab2901SDag-Erling Smørgrav default: 603*05ab2901SDag-Erling Smørgrav return 0; 604*05ab2901SDag-Erling Smørgrav } 605*05ab2901SDag-Erling Smørgrav } 606*05ab2901SDag-Erling Smørgrav 607*05ab2901SDag-Erling Smørgrav /* perform nsec3 hash. return false on failure */ 608*05ab2901SDag-Erling Smørgrav int 609*05ab2901SDag-Erling Smørgrav secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, 610*05ab2901SDag-Erling Smørgrav unsigned char* res) 611*05ab2901SDag-Erling Smørgrav { 612*05ab2901SDag-Erling Smørgrav switch(algo) { 613*05ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1: 614*05ab2901SDag-Erling Smørgrav (void)HASH_HashBuf(HASH_AlgSHA1, res, buf, (unsigned long)len); 615*05ab2901SDag-Erling Smørgrav return 1; 616*05ab2901SDag-Erling Smørgrav default: 617*05ab2901SDag-Erling Smørgrav return 0; 618*05ab2901SDag-Erling Smørgrav } 619*05ab2901SDag-Erling Smørgrav } 620*05ab2901SDag-Erling Smørgrav 6218ed2b524SDag-Erling Smørgrav size_t 6228ed2b524SDag-Erling Smørgrav ds_digest_size_supported(int algo) 6238ed2b524SDag-Erling Smørgrav { 6248ed2b524SDag-Erling Smørgrav /* uses libNSS */ 6258ed2b524SDag-Erling Smørgrav switch(algo) { 6268ed2b524SDag-Erling Smørgrav case LDNS_SHA1: 6278ed2b524SDag-Erling Smørgrav return SHA1_LENGTH; 6288ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 6298ed2b524SDag-Erling Smørgrav case LDNS_SHA256: 6308ed2b524SDag-Erling Smørgrav return SHA256_LENGTH; 6318ed2b524SDag-Erling Smørgrav #endif 6328ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 6338ed2b524SDag-Erling Smørgrav case LDNS_SHA384: 6348ed2b524SDag-Erling Smørgrav return SHA384_LENGTH; 6358ed2b524SDag-Erling Smørgrav #endif 6368ed2b524SDag-Erling Smørgrav /* GOST not supported in NSS */ 6378ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST: 6388ed2b524SDag-Erling Smørgrav default: break; 6398ed2b524SDag-Erling Smørgrav } 6408ed2b524SDag-Erling Smørgrav return 0; 6418ed2b524SDag-Erling Smørgrav } 6428ed2b524SDag-Erling Smørgrav 6438ed2b524SDag-Erling Smørgrav int 6448ed2b524SDag-Erling Smørgrav secalgo_ds_digest(int algo, unsigned char* buf, size_t len, 6458ed2b524SDag-Erling Smørgrav unsigned char* res) 6468ed2b524SDag-Erling Smørgrav { 6478ed2b524SDag-Erling Smørgrav /* uses libNSS */ 6488ed2b524SDag-Erling Smørgrav switch(algo) { 6498ed2b524SDag-Erling Smørgrav case LDNS_SHA1: 6508ed2b524SDag-Erling Smørgrav return HASH_HashBuf(HASH_AlgSHA1, res, buf, len) 6518ed2b524SDag-Erling Smørgrav == SECSuccess; 6528ed2b524SDag-Erling Smørgrav #if defined(USE_SHA2) 6538ed2b524SDag-Erling Smørgrav case LDNS_SHA256: 6548ed2b524SDag-Erling Smørgrav return HASH_HashBuf(HASH_AlgSHA256, res, buf, len) 6558ed2b524SDag-Erling Smørgrav == SECSuccess; 6568ed2b524SDag-Erling Smørgrav #endif 6578ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 6588ed2b524SDag-Erling Smørgrav case LDNS_SHA384: 6598ed2b524SDag-Erling Smørgrav return HASH_HashBuf(HASH_AlgSHA384, res, buf, len) 6608ed2b524SDag-Erling Smørgrav == SECSuccess; 6618ed2b524SDag-Erling Smørgrav #endif 6628ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST: 6638ed2b524SDag-Erling Smørgrav default: 6648ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "unknown DS digest algorithm %d", 6658ed2b524SDag-Erling Smørgrav algo); 6668ed2b524SDag-Erling Smørgrav break; 6678ed2b524SDag-Erling Smørgrav } 6688ed2b524SDag-Erling Smørgrav return 0; 6698ed2b524SDag-Erling Smørgrav } 6708ed2b524SDag-Erling Smørgrav 6718ed2b524SDag-Erling Smørgrav int 6728ed2b524SDag-Erling Smørgrav dnskey_algo_id_is_supported(int id) 6738ed2b524SDag-Erling Smørgrav { 6748ed2b524SDag-Erling Smørgrav /* uses libNSS */ 6758ed2b524SDag-Erling Smørgrav switch(id) { 6768ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5: 6778ed2b524SDag-Erling Smørgrav /* RFC 6725 deprecates RSAMD5 */ 6788ed2b524SDag-Erling Smørgrav return 0; 6798ed2b524SDag-Erling Smørgrav case LDNS_DSA: 6808ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 6818ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1: 6828ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 6838ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 6848ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256: 6858ed2b524SDag-Erling Smørgrav #endif 6868ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 6878ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512: 6888ed2b524SDag-Erling Smørgrav #endif 6898ed2b524SDag-Erling Smørgrav return 1; 6908ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 6918ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 6928ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 6938ed2b524SDag-Erling Smørgrav return PK11_TokenExists(CKM_ECDSA); 6948ed2b524SDag-Erling Smørgrav #endif 6958ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST: 6968ed2b524SDag-Erling Smørgrav default: 6978ed2b524SDag-Erling Smørgrav return 0; 6988ed2b524SDag-Erling Smørgrav } 6998ed2b524SDag-Erling Smørgrav } 7008ed2b524SDag-Erling Smørgrav 7018ed2b524SDag-Erling Smørgrav /* return a new public key for NSS */ 7028ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_key_create(KeyType ktype) 7038ed2b524SDag-Erling Smørgrav { 7048ed2b524SDag-Erling Smørgrav SECKEYPublicKey* key; 7058ed2b524SDag-Erling Smørgrav PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 7068ed2b524SDag-Erling Smørgrav if(!arena) { 7078ed2b524SDag-Erling Smørgrav log_err("out of memory, PORT_NewArena failed"); 7088ed2b524SDag-Erling Smørgrav return NULL; 7098ed2b524SDag-Erling Smørgrav } 7108ed2b524SDag-Erling Smørgrav key = PORT_ArenaZNew(arena, SECKEYPublicKey); 7118ed2b524SDag-Erling Smørgrav if(!key) { 7128ed2b524SDag-Erling Smørgrav log_err("out of memory, PORT_ArenaZNew failed"); 7138ed2b524SDag-Erling Smørgrav PORT_FreeArena(arena, PR_FALSE); 7148ed2b524SDag-Erling Smørgrav return NULL; 7158ed2b524SDag-Erling Smørgrav } 7168ed2b524SDag-Erling Smørgrav key->arena = arena; 7178ed2b524SDag-Erling Smørgrav key->keyType = ktype; 7188ed2b524SDag-Erling Smørgrav key->pkcs11Slot = NULL; 7198ed2b524SDag-Erling Smørgrav key->pkcs11ID = CK_INVALID_HANDLE; 7208ed2b524SDag-Erling Smørgrav return key; 7218ed2b524SDag-Erling Smørgrav } 7228ed2b524SDag-Erling Smørgrav 7238ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_buf2ecdsa(unsigned char* key, size_t len, int algo) 7248ed2b524SDag-Erling Smørgrav { 7258ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pk; 7268ed2b524SDag-Erling Smørgrav SECItem pub = {siBuffer, NULL, 0}; 7278ed2b524SDag-Erling Smørgrav SECItem params = {siBuffer, NULL, 0}; 72817d15b25SDag-Erling Smørgrav static unsigned char param256[] = { 7298ed2b524SDag-Erling Smørgrav /* OBJECTIDENTIFIER 1.2.840.10045.3.1.7 (P-256) 7308ed2b524SDag-Erling Smørgrav * {iso(1) member-body(2) us(840) ansi-x962(10045) curves(3) prime(1) prime256v1(7)} */ 7318ed2b524SDag-Erling Smørgrav 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 7328ed2b524SDag-Erling Smørgrav }; 73317d15b25SDag-Erling Smørgrav static unsigned char param384[] = { 7348ed2b524SDag-Erling Smørgrav /* OBJECTIDENTIFIER 1.3.132.0.34 (P-384) 7358ed2b524SDag-Erling Smørgrav * {iso(1) identified-organization(3) certicom(132) curve(0) ansip384r1(34)} */ 7368ed2b524SDag-Erling Smørgrav 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22 7378ed2b524SDag-Erling Smørgrav }; 7388ed2b524SDag-Erling Smørgrav unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ 7398ed2b524SDag-Erling Smørgrav 7408ed2b524SDag-Erling Smørgrav /* check length, which uncompressed must be 2 bignums */ 7418ed2b524SDag-Erling Smørgrav if(algo == LDNS_ECDSAP256SHA256) { 7428ed2b524SDag-Erling Smørgrav if(len != 2*256/8) return NULL; 7438ed2b524SDag-Erling Smørgrav /* ECCurve_X9_62_PRIME_256V1 */ 7448ed2b524SDag-Erling Smørgrav } else if(algo == LDNS_ECDSAP384SHA384) { 7458ed2b524SDag-Erling Smørgrav if(len != 2*384/8) return NULL; 7468ed2b524SDag-Erling Smørgrav /* ECCurve_X9_62_PRIME_384R1 */ 7478ed2b524SDag-Erling Smørgrav } else return NULL; 7488ed2b524SDag-Erling Smørgrav 7498ed2b524SDag-Erling Smørgrav buf[0] = 0x04; /* POINT_FORM_UNCOMPRESSED */ 7508ed2b524SDag-Erling Smørgrav memmove(buf+1, key, len); 7518ed2b524SDag-Erling Smørgrav pub.data = buf; 7528ed2b524SDag-Erling Smørgrav pub.len = len+1; 7538ed2b524SDag-Erling Smørgrav if(algo == LDNS_ECDSAP256SHA256) { 7548ed2b524SDag-Erling Smørgrav params.data = param256; 7558ed2b524SDag-Erling Smørgrav params.len = sizeof(param256); 7568ed2b524SDag-Erling Smørgrav } else { 7578ed2b524SDag-Erling Smørgrav params.data = param384; 7588ed2b524SDag-Erling Smørgrav params.len = sizeof(param384); 7598ed2b524SDag-Erling Smørgrav } 7608ed2b524SDag-Erling Smørgrav 7618ed2b524SDag-Erling Smørgrav pk = nss_key_create(ecKey); 7628ed2b524SDag-Erling Smørgrav if(!pk) 7638ed2b524SDag-Erling Smørgrav return NULL; 7648ed2b524SDag-Erling Smørgrav pk->u.ec.size = (len/2)*8; 7658ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.ec.publicValue, &pub)) { 7668ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 7678ed2b524SDag-Erling Smørgrav return NULL; 7688ed2b524SDag-Erling Smørgrav } 7698ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.ec.DEREncodedParams, ¶ms)) { 7708ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 7718ed2b524SDag-Erling Smørgrav return NULL; 7728ed2b524SDag-Erling Smørgrav } 7738ed2b524SDag-Erling Smørgrav 7748ed2b524SDag-Erling Smørgrav return pk; 7758ed2b524SDag-Erling Smørgrav } 7768ed2b524SDag-Erling Smørgrav 7778ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_buf2dsa(unsigned char* key, size_t len) 7788ed2b524SDag-Erling Smørgrav { 7798ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pk; 7808ed2b524SDag-Erling Smørgrav uint8_t T; 7818ed2b524SDag-Erling Smørgrav uint16_t length; 7828ed2b524SDag-Erling Smørgrav uint16_t offset; 7838ed2b524SDag-Erling Smørgrav SECItem Q = {siBuffer, NULL, 0}; 7848ed2b524SDag-Erling Smørgrav SECItem P = {siBuffer, NULL, 0}; 7858ed2b524SDag-Erling Smørgrav SECItem G = {siBuffer, NULL, 0}; 7868ed2b524SDag-Erling Smørgrav SECItem Y = {siBuffer, NULL, 0}; 7878ed2b524SDag-Erling Smørgrav 7888ed2b524SDag-Erling Smørgrav if(len == 0) 7898ed2b524SDag-Erling Smørgrav return NULL; 7908ed2b524SDag-Erling Smørgrav T = (uint8_t)key[0]; 7918ed2b524SDag-Erling Smørgrav length = (64 + T * 8); 7928ed2b524SDag-Erling Smørgrav offset = 1; 7938ed2b524SDag-Erling Smørgrav 7948ed2b524SDag-Erling Smørgrav if (T > 8) { 7958ed2b524SDag-Erling Smørgrav return NULL; 7968ed2b524SDag-Erling Smørgrav } 7978ed2b524SDag-Erling Smørgrav if(len < (size_t)1 + SHA1_LENGTH + 3*length) 7988ed2b524SDag-Erling Smørgrav return NULL; 7998ed2b524SDag-Erling Smørgrav 8008ed2b524SDag-Erling Smørgrav Q.data = key+offset; 8018ed2b524SDag-Erling Smørgrav Q.len = SHA1_LENGTH; 8028ed2b524SDag-Erling Smørgrav offset += SHA1_LENGTH; 8038ed2b524SDag-Erling Smørgrav 8048ed2b524SDag-Erling Smørgrav P.data = key+offset; 8058ed2b524SDag-Erling Smørgrav P.len = length; 8068ed2b524SDag-Erling Smørgrav offset += length; 8078ed2b524SDag-Erling Smørgrav 8088ed2b524SDag-Erling Smørgrav G.data = key+offset; 8098ed2b524SDag-Erling Smørgrav G.len = length; 8108ed2b524SDag-Erling Smørgrav offset += length; 8118ed2b524SDag-Erling Smørgrav 8128ed2b524SDag-Erling Smørgrav Y.data = key+offset; 8138ed2b524SDag-Erling Smørgrav Y.len = length; 8148ed2b524SDag-Erling Smørgrav offset += length; 8158ed2b524SDag-Erling Smørgrav 8168ed2b524SDag-Erling Smørgrav pk = nss_key_create(dsaKey); 8178ed2b524SDag-Erling Smørgrav if(!pk) 8188ed2b524SDag-Erling Smørgrav return NULL; 8198ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.prime, &P)) { 8208ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 8218ed2b524SDag-Erling Smørgrav return NULL; 8228ed2b524SDag-Erling Smørgrav } 8238ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.subPrime, &Q)) { 8248ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 8258ed2b524SDag-Erling Smørgrav return NULL; 8268ed2b524SDag-Erling Smørgrav } 8278ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.base, &G)) { 8288ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 8298ed2b524SDag-Erling Smørgrav return NULL; 8308ed2b524SDag-Erling Smørgrav } 8318ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.publicValue, &Y)) { 8328ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 8338ed2b524SDag-Erling Smørgrav return NULL; 8348ed2b524SDag-Erling Smørgrav } 8358ed2b524SDag-Erling Smørgrav return pk; 8368ed2b524SDag-Erling Smørgrav } 8378ed2b524SDag-Erling Smørgrav 8388ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_buf2rsa(unsigned char* key, size_t len) 8398ed2b524SDag-Erling Smørgrav { 8408ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pk; 8418ed2b524SDag-Erling Smørgrav uint16_t exp; 8428ed2b524SDag-Erling Smørgrav uint16_t offset; 8438ed2b524SDag-Erling Smørgrav uint16_t int16; 8448ed2b524SDag-Erling Smørgrav SECItem modulus = {siBuffer, NULL, 0}; 8458ed2b524SDag-Erling Smørgrav SECItem exponent = {siBuffer, NULL, 0}; 8468ed2b524SDag-Erling Smørgrav if(len == 0) 8478ed2b524SDag-Erling Smørgrav return NULL; 8488ed2b524SDag-Erling Smørgrav if(key[0] == 0) { 8498ed2b524SDag-Erling Smørgrav if(len < 3) 8508ed2b524SDag-Erling Smørgrav return NULL; 8518ed2b524SDag-Erling Smørgrav /* the exponent is too large so it's places further */ 8528ed2b524SDag-Erling Smørgrav memmove(&int16, key+1, 2); 8538ed2b524SDag-Erling Smørgrav exp = ntohs(int16); 8548ed2b524SDag-Erling Smørgrav offset = 3; 8558ed2b524SDag-Erling Smørgrav } else { 8568ed2b524SDag-Erling Smørgrav exp = key[0]; 8578ed2b524SDag-Erling Smørgrav offset = 1; 8588ed2b524SDag-Erling Smørgrav } 8598ed2b524SDag-Erling Smørgrav 8608ed2b524SDag-Erling Smørgrav /* key length at least one */ 8618ed2b524SDag-Erling Smørgrav if(len < (size_t)offset + exp + 1) 8628ed2b524SDag-Erling Smørgrav return NULL; 8638ed2b524SDag-Erling Smørgrav 8648ed2b524SDag-Erling Smørgrav exponent.data = key+offset; 8658ed2b524SDag-Erling Smørgrav exponent.len = exp; 8668ed2b524SDag-Erling Smørgrav offset += exp; 8678ed2b524SDag-Erling Smørgrav modulus.data = key+offset; 8688ed2b524SDag-Erling Smørgrav modulus.len = (len - offset); 8698ed2b524SDag-Erling Smørgrav 8708ed2b524SDag-Erling Smørgrav pk = nss_key_create(rsaKey); 8718ed2b524SDag-Erling Smørgrav if(!pk) 8728ed2b524SDag-Erling Smørgrav return NULL; 8738ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.modulus, &modulus)) { 8748ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 8758ed2b524SDag-Erling Smørgrav return NULL; 8768ed2b524SDag-Erling Smørgrav } 8778ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.publicExponent, &exponent)) { 8788ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 8798ed2b524SDag-Erling Smørgrav return NULL; 8808ed2b524SDag-Erling Smørgrav } 8818ed2b524SDag-Erling Smørgrav return pk; 8828ed2b524SDag-Erling Smørgrav } 8838ed2b524SDag-Erling Smørgrav 8848ed2b524SDag-Erling Smørgrav /** 8858ed2b524SDag-Erling Smørgrav * Setup key and digest for verification. Adjust sig if necessary. 8868ed2b524SDag-Erling Smørgrav * 8878ed2b524SDag-Erling Smørgrav * @param algo: key algorithm 8888ed2b524SDag-Erling Smørgrav * @param evp_key: EVP PKEY public key to create. 8898ed2b524SDag-Erling Smørgrav * @param digest_type: digest type to use 8908ed2b524SDag-Erling Smørgrav * @param key: key to setup for. 8918ed2b524SDag-Erling Smørgrav * @param keylen: length of key. 8928ed2b524SDag-Erling Smørgrav * @param prefix: if returned, the ASN prefix for the hashblob. 8938ed2b524SDag-Erling Smørgrav * @param prefixlen: length of the prefix. 8948ed2b524SDag-Erling Smørgrav * @return false on failure. 8958ed2b524SDag-Erling Smørgrav */ 8968ed2b524SDag-Erling Smørgrav static int 8978ed2b524SDag-Erling Smørgrav nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype, 8988ed2b524SDag-Erling Smørgrav unsigned char* key, size_t keylen, unsigned char** prefix, 8998ed2b524SDag-Erling Smørgrav size_t* prefixlen) 9008ed2b524SDag-Erling Smørgrav { 9018ed2b524SDag-Erling Smørgrav /* uses libNSS */ 9028ed2b524SDag-Erling Smørgrav 9038ed2b524SDag-Erling Smørgrav /* hash prefix for md5, RFC2537 */ 90417d15b25SDag-Erling Smørgrav static unsigned char p_md5[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 9058ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}; 9068ed2b524SDag-Erling Smørgrav /* hash prefix to prepend to hash output, from RFC3110 */ 90717d15b25SDag-Erling Smørgrav static unsigned char p_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 9088ed2b524SDag-Erling Smørgrav 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14}; 9098ed2b524SDag-Erling Smørgrav /* from RFC5702 */ 91017d15b25SDag-Erling Smørgrav static unsigned char p_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 9118ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; 91217d15b25SDag-Erling Smørgrav static unsigned char p_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 9138ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}; 9148ed2b524SDag-Erling Smørgrav /* from RFC6234 */ 9158ed2b524SDag-Erling Smørgrav /* for future RSASHA384 .. 91617d15b25SDag-Erling Smørgrav static unsigned char p_sha384[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 9178ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}; 9188ed2b524SDag-Erling Smørgrav */ 9198ed2b524SDag-Erling Smørgrav 9208ed2b524SDag-Erling Smørgrav switch(algo) { 9218ed2b524SDag-Erling Smørgrav case LDNS_DSA: 9228ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 9238ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2dsa(key, keylen); 9248ed2b524SDag-Erling Smørgrav if(!*pubkey) { 9258ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 9268ed2b524SDag-Erling Smørgrav return 0; 9278ed2b524SDag-Erling Smørgrav } 9288ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA1; 9298ed2b524SDag-Erling Smørgrav /* no prefix for DSA verification */ 9308ed2b524SDag-Erling Smørgrav break; 9318ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1: 9328ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 9338ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 9348ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256: 9358ed2b524SDag-Erling Smørgrav #endif 9368ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 9378ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512: 9388ed2b524SDag-Erling Smørgrav #endif 9398ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2rsa(key, keylen); 9408ed2b524SDag-Erling Smørgrav if(!*pubkey) { 9418ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 9428ed2b524SDag-Erling Smørgrav return 0; 9438ed2b524SDag-Erling Smørgrav } 9448ed2b524SDag-Erling Smørgrav /* select SHA version */ 9458ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 9468ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA256) { 9478ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA256; 9488ed2b524SDag-Erling Smørgrav *prefix = p_sha256; 9498ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_sha256); 9508ed2b524SDag-Erling Smørgrav } else 9518ed2b524SDag-Erling Smørgrav #endif 9528ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 9538ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA512) { 9548ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA512; 9558ed2b524SDag-Erling Smørgrav *prefix = p_sha512; 9568ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_sha512); 9578ed2b524SDag-Erling Smørgrav } else 9588ed2b524SDag-Erling Smørgrav #endif 9598ed2b524SDag-Erling Smørgrav { 9608ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA1; 9618ed2b524SDag-Erling Smørgrav *prefix = p_sha1; 9628ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_sha1); 9638ed2b524SDag-Erling Smørgrav } 9648ed2b524SDag-Erling Smørgrav 9658ed2b524SDag-Erling Smørgrav break; 9668ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5: 9678ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2rsa(key, keylen); 9688ed2b524SDag-Erling Smørgrav if(!*pubkey) { 9698ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 9708ed2b524SDag-Erling Smørgrav return 0; 9718ed2b524SDag-Erling Smørgrav } 9728ed2b524SDag-Erling Smørgrav *htype = HASH_AlgMD5; 9738ed2b524SDag-Erling Smørgrav *prefix = p_md5; 9748ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_md5); 9758ed2b524SDag-Erling Smørgrav 9768ed2b524SDag-Erling Smørgrav break; 9778ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 9788ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 9798ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2ecdsa(key, keylen, 9808ed2b524SDag-Erling Smørgrav LDNS_ECDSAP256SHA256); 9818ed2b524SDag-Erling Smørgrav if(!*pubkey) { 9828ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 9838ed2b524SDag-Erling Smørgrav return 0; 9848ed2b524SDag-Erling Smørgrav } 9858ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA256; 9868ed2b524SDag-Erling Smørgrav /* no prefix for DSA verification */ 9878ed2b524SDag-Erling Smørgrav break; 9888ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 9898ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2ecdsa(key, keylen, 9908ed2b524SDag-Erling Smørgrav LDNS_ECDSAP384SHA384); 9918ed2b524SDag-Erling Smørgrav if(!*pubkey) { 9928ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 9938ed2b524SDag-Erling Smørgrav return 0; 9948ed2b524SDag-Erling Smørgrav } 9958ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA384; 9968ed2b524SDag-Erling Smørgrav /* no prefix for DSA verification */ 9978ed2b524SDag-Erling Smørgrav break; 9988ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */ 9998ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST: 10008ed2b524SDag-Erling Smørgrav default: 10018ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: unknown algorithm %d", 10028ed2b524SDag-Erling Smørgrav algo); 10038ed2b524SDag-Erling Smørgrav return 0; 10048ed2b524SDag-Erling Smørgrav } 10058ed2b524SDag-Erling Smørgrav return 1; 10068ed2b524SDag-Erling Smørgrav } 10078ed2b524SDag-Erling Smørgrav 10088ed2b524SDag-Erling Smørgrav /** 10098ed2b524SDag-Erling Smørgrav * Check a canonical sig+rrset and signature against a dnskey 10108ed2b524SDag-Erling Smørgrav * @param buf: buffer with data to verify, the first rrsig part and the 10118ed2b524SDag-Erling Smørgrav * canonicalized rrset. 10128ed2b524SDag-Erling Smørgrav * @param algo: DNSKEY algorithm. 10138ed2b524SDag-Erling Smørgrav * @param sigblock: signature rdata field from RRSIG 10148ed2b524SDag-Erling Smørgrav * @param sigblock_len: length of sigblock data. 10158ed2b524SDag-Erling Smørgrav * @param key: public key data from DNSKEY RR. 10168ed2b524SDag-Erling Smørgrav * @param keylen: length of keydata. 10178ed2b524SDag-Erling Smørgrav * @param reason: bogus reason in more detail. 10188ed2b524SDag-Erling Smørgrav * @return secure if verification succeeded, bogus on crypto failure, 10198ed2b524SDag-Erling Smørgrav * unchecked on format errors and alloc failures. 10208ed2b524SDag-Erling Smørgrav */ 10218ed2b524SDag-Erling Smørgrav enum sec_status 102217d15b25SDag-Erling Smørgrav verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, 10238ed2b524SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen, 10248ed2b524SDag-Erling Smørgrav char** reason) 10258ed2b524SDag-Erling Smørgrav { 10268ed2b524SDag-Erling Smørgrav /* uses libNSS */ 10278ed2b524SDag-Erling Smørgrav /* large enough for the different hashes */ 10288ed2b524SDag-Erling Smørgrav unsigned char hash[HASH_LENGTH_MAX]; 10298ed2b524SDag-Erling Smørgrav unsigned char hash2[HASH_LENGTH_MAX*2]; 10308ed2b524SDag-Erling Smørgrav HASH_HashType htype = 0; 10318ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pubkey = NULL; 10328ed2b524SDag-Erling Smørgrav SECItem secsig = {siBuffer, sigblock, sigblock_len}; 10338ed2b524SDag-Erling Smørgrav SECItem sechash = {siBuffer, hash, 0}; 10348ed2b524SDag-Erling Smørgrav SECStatus res; 10358ed2b524SDag-Erling Smørgrav unsigned char* prefix = NULL; /* prefix for hash, RFC3110, RFC5702 */ 10368ed2b524SDag-Erling Smørgrav size_t prefixlen = 0; 10378ed2b524SDag-Erling Smørgrav int err; 10388ed2b524SDag-Erling Smørgrav 10398ed2b524SDag-Erling Smørgrav if(!nss_setup_key_digest(algo, &pubkey, &htype, key, keylen, 10408ed2b524SDag-Erling Smørgrav &prefix, &prefixlen)) { 10418ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup key"); 10428ed2b524SDag-Erling Smørgrav *reason = "use of key for crypto failed"; 10438ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 10448ed2b524SDag-Erling Smørgrav return sec_status_bogus; 10458ed2b524SDag-Erling Smørgrav } 10468ed2b524SDag-Erling Smørgrav 10478ed2b524SDag-Erling Smørgrav /* need to convert DSA, ECDSA signatures? */ 10488ed2b524SDag-Erling Smørgrav if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) { 10498ed2b524SDag-Erling Smørgrav if(sigblock_len == 1+2*SHA1_LENGTH) { 10508ed2b524SDag-Erling Smørgrav secsig.data ++; 10518ed2b524SDag-Erling Smørgrav secsig.len --; 10528ed2b524SDag-Erling Smørgrav } else { 10538ed2b524SDag-Erling Smørgrav SECItem* p = DSAU_DecodeDerSig(&secsig); 10548ed2b524SDag-Erling Smørgrav if(!p) { 10558ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed DER decode"); 10568ed2b524SDag-Erling Smørgrav *reason = "signature DER decode failed"; 10578ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 10588ed2b524SDag-Erling Smørgrav return sec_status_bogus; 10598ed2b524SDag-Erling Smørgrav } 10608ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pubkey->arena, &secsig, p)) { 10618ed2b524SDag-Erling Smørgrav log_err("alloc failure in DER decode"); 10628ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 10638ed2b524SDag-Erling Smørgrav SECITEM_FreeItem(p, PR_TRUE); 10648ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 10658ed2b524SDag-Erling Smørgrav } 10668ed2b524SDag-Erling Smørgrav SECITEM_FreeItem(p, PR_TRUE); 10678ed2b524SDag-Erling Smørgrav } 10688ed2b524SDag-Erling Smørgrav } 10698ed2b524SDag-Erling Smørgrav 10708ed2b524SDag-Erling Smørgrav /* do the signature cryptography work */ 10718ed2b524SDag-Erling Smørgrav /* hash the data */ 10728ed2b524SDag-Erling Smørgrav sechash.len = HASH_ResultLen(htype); 10738ed2b524SDag-Erling Smørgrav if(sechash.len > sizeof(hash)) { 10748ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: hash too large for buffer"); 10758ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 10768ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 10778ed2b524SDag-Erling Smørgrav } 107817d15b25SDag-Erling Smørgrav if(HASH_HashBuf(htype, hash, (unsigned char*)sldns_buffer_begin(buf), 107917d15b25SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf)) != SECSuccess) { 10808ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: HASH_HashBuf failed"); 10818ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 10828ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 10838ed2b524SDag-Erling Smørgrav } 10848ed2b524SDag-Erling Smørgrav if(prefix) { 10858ed2b524SDag-Erling Smørgrav int hashlen = sechash.len; 10868ed2b524SDag-Erling Smørgrav if(prefixlen+hashlen > sizeof(hash2)) { 10878ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: hashprefix too large"); 10888ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 10898ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 10908ed2b524SDag-Erling Smørgrav } 10918ed2b524SDag-Erling Smørgrav sechash.data = hash2; 10928ed2b524SDag-Erling Smørgrav sechash.len = prefixlen+hashlen; 10938ed2b524SDag-Erling Smørgrav memcpy(sechash.data, prefix, prefixlen); 10948ed2b524SDag-Erling Smørgrav memmove(sechash.data+prefixlen, hash, hashlen); 10958ed2b524SDag-Erling Smørgrav } 10968ed2b524SDag-Erling Smørgrav 10978ed2b524SDag-Erling Smørgrav /* verify the signature */ 10988ed2b524SDag-Erling Smørgrav res = PK11_Verify(pubkey, &secsig, &sechash, NULL /*wincx*/); 10998ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 11008ed2b524SDag-Erling Smørgrav 11018ed2b524SDag-Erling Smørgrav if(res == SECSuccess) { 11028ed2b524SDag-Erling Smørgrav return sec_status_secure; 11038ed2b524SDag-Erling Smørgrav } 11048ed2b524SDag-Erling Smørgrav err = PORT_GetError(); 11058ed2b524SDag-Erling Smørgrav if(err != SEC_ERROR_BAD_SIGNATURE) { 11068ed2b524SDag-Erling Smørgrav /* failed to verify */ 11078ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: PK11_Verify failed: %s", 11088ed2b524SDag-Erling Smørgrav PORT_ErrorToString(err)); 11098ed2b524SDag-Erling Smørgrav /* if it is not supported, like ECC is removed, we get, 11108ed2b524SDag-Erling Smørgrav * SEC_ERROR_NO_MODULE */ 11118ed2b524SDag-Erling Smørgrav if(err == SEC_ERROR_NO_MODULE) 11128ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 11138ed2b524SDag-Erling Smørgrav /* but other errors are commonly returned 11148ed2b524SDag-Erling Smørgrav * for a bad signature from NSS. Thus we return bogus, 11158ed2b524SDag-Erling Smørgrav * not unchecked */ 11168ed2b524SDag-Erling Smørgrav *reason = "signature crypto failed"; 11178ed2b524SDag-Erling Smørgrav return sec_status_bogus; 11188ed2b524SDag-Erling Smørgrav } 11198ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: signature mismatch: %s", 11208ed2b524SDag-Erling Smørgrav PORT_ErrorToString(err)); 11218ed2b524SDag-Erling Smørgrav *reason = "signature crypto failed"; 11228ed2b524SDag-Erling Smørgrav return sec_status_bogus; 11238ed2b524SDag-Erling Smørgrav } 11248ed2b524SDag-Erling Smørgrav 1125*05ab2901SDag-Erling Smørgrav #elif defined(HAVE_NETTLE) 11268ed2b524SDag-Erling Smørgrav 1127*05ab2901SDag-Erling Smørgrav #include "sha.h" 1128*05ab2901SDag-Erling Smørgrav #include "bignum.h" 1129*05ab2901SDag-Erling Smørgrav #include "macros.h" 1130*05ab2901SDag-Erling Smørgrav #include "rsa.h" 1131*05ab2901SDag-Erling Smørgrav #include "dsa.h" 1132*05ab2901SDag-Erling Smørgrav #include "asn1.h" 1133*05ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA 1134*05ab2901SDag-Erling Smørgrav #include "ecdsa.h" 1135*05ab2901SDag-Erling Smørgrav #include "ecc-curve.h" 1136*05ab2901SDag-Erling Smørgrav #endif 1137*05ab2901SDag-Erling Smørgrav 1138*05ab2901SDag-Erling Smørgrav static int 1139*05ab2901SDag-Erling Smørgrav _digest_nettle(int algo, uint8_t* buf, size_t len, 1140*05ab2901SDag-Erling Smørgrav unsigned char* res) 1141*05ab2901SDag-Erling Smørgrav { 1142*05ab2901SDag-Erling Smørgrav switch(algo) { 1143*05ab2901SDag-Erling Smørgrav case SHA1_DIGEST_SIZE: 1144*05ab2901SDag-Erling Smørgrav { 1145*05ab2901SDag-Erling Smørgrav struct sha1_ctx ctx; 1146*05ab2901SDag-Erling Smørgrav sha1_init(&ctx); 1147*05ab2901SDag-Erling Smørgrav sha1_update(&ctx, len, buf); 1148*05ab2901SDag-Erling Smørgrav sha1_digest(&ctx, SHA1_DIGEST_SIZE, res); 1149*05ab2901SDag-Erling Smørgrav return 1; 1150*05ab2901SDag-Erling Smørgrav } 1151*05ab2901SDag-Erling Smørgrav case SHA256_DIGEST_SIZE: 1152*05ab2901SDag-Erling Smørgrav { 1153*05ab2901SDag-Erling Smørgrav struct sha256_ctx ctx; 1154*05ab2901SDag-Erling Smørgrav sha256_init(&ctx); 1155*05ab2901SDag-Erling Smørgrav sha256_update(&ctx, len, buf); 1156*05ab2901SDag-Erling Smørgrav sha256_digest(&ctx, SHA256_DIGEST_SIZE, res); 1157*05ab2901SDag-Erling Smørgrav return 1; 1158*05ab2901SDag-Erling Smørgrav } 1159*05ab2901SDag-Erling Smørgrav case SHA384_DIGEST_SIZE: 1160*05ab2901SDag-Erling Smørgrav { 1161*05ab2901SDag-Erling Smørgrav struct sha384_ctx ctx; 1162*05ab2901SDag-Erling Smørgrav sha384_init(&ctx); 1163*05ab2901SDag-Erling Smørgrav sha384_update(&ctx, len, buf); 1164*05ab2901SDag-Erling Smørgrav sha384_digest(&ctx, SHA384_DIGEST_SIZE, res); 1165*05ab2901SDag-Erling Smørgrav return 1; 1166*05ab2901SDag-Erling Smørgrav } 1167*05ab2901SDag-Erling Smørgrav case SHA512_DIGEST_SIZE: 1168*05ab2901SDag-Erling Smørgrav { 1169*05ab2901SDag-Erling Smørgrav struct sha512_ctx ctx; 1170*05ab2901SDag-Erling Smørgrav sha512_init(&ctx); 1171*05ab2901SDag-Erling Smørgrav sha512_update(&ctx, len, buf); 1172*05ab2901SDag-Erling Smørgrav sha512_digest(&ctx, SHA512_DIGEST_SIZE, res); 1173*05ab2901SDag-Erling Smørgrav return 1; 1174*05ab2901SDag-Erling Smørgrav } 1175*05ab2901SDag-Erling Smørgrav default: 1176*05ab2901SDag-Erling Smørgrav break; 1177*05ab2901SDag-Erling Smørgrav } 1178*05ab2901SDag-Erling Smørgrav return 0; 1179*05ab2901SDag-Erling Smørgrav } 1180*05ab2901SDag-Erling Smørgrav 1181*05ab2901SDag-Erling Smørgrav /* return size of digest if supported, or 0 otherwise */ 1182*05ab2901SDag-Erling Smørgrav size_t 1183*05ab2901SDag-Erling Smørgrav nsec3_hash_algo_size_supported(int id) 1184*05ab2901SDag-Erling Smørgrav { 1185*05ab2901SDag-Erling Smørgrav switch(id) { 1186*05ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1: 1187*05ab2901SDag-Erling Smørgrav return SHA1_DIGEST_SIZE; 1188*05ab2901SDag-Erling Smørgrav default: 1189*05ab2901SDag-Erling Smørgrav return 0; 1190*05ab2901SDag-Erling Smørgrav } 1191*05ab2901SDag-Erling Smørgrav } 1192*05ab2901SDag-Erling Smørgrav 1193*05ab2901SDag-Erling Smørgrav /* perform nsec3 hash. return false on failure */ 1194*05ab2901SDag-Erling Smørgrav int 1195*05ab2901SDag-Erling Smørgrav secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, 1196*05ab2901SDag-Erling Smørgrav unsigned char* res) 1197*05ab2901SDag-Erling Smørgrav { 1198*05ab2901SDag-Erling Smørgrav switch(algo) { 1199*05ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1: 1200*05ab2901SDag-Erling Smørgrav return _digest_nettle(SHA1_DIGEST_SIZE, (uint8_t*)buf, len, 1201*05ab2901SDag-Erling Smørgrav res); 1202*05ab2901SDag-Erling Smørgrav default: 1203*05ab2901SDag-Erling Smørgrav return 0; 1204*05ab2901SDag-Erling Smørgrav } 1205*05ab2901SDag-Erling Smørgrav } 1206*05ab2901SDag-Erling Smørgrav 1207*05ab2901SDag-Erling Smørgrav /** 1208*05ab2901SDag-Erling Smørgrav * Return size of DS digest according to its hash algorithm. 1209*05ab2901SDag-Erling Smørgrav * @param algo: DS digest algo. 1210*05ab2901SDag-Erling Smørgrav * @return size in bytes of digest, or 0 if not supported. 1211*05ab2901SDag-Erling Smørgrav */ 1212*05ab2901SDag-Erling Smørgrav size_t 1213*05ab2901SDag-Erling Smørgrav ds_digest_size_supported(int algo) 1214*05ab2901SDag-Erling Smørgrav { 1215*05ab2901SDag-Erling Smørgrav switch(algo) { 1216*05ab2901SDag-Erling Smørgrav case LDNS_SHA1: 1217*05ab2901SDag-Erling Smørgrav return SHA1_DIGEST_SIZE; 1218*05ab2901SDag-Erling Smørgrav #ifdef USE_SHA2 1219*05ab2901SDag-Erling Smørgrav case LDNS_SHA256: 1220*05ab2901SDag-Erling Smørgrav return SHA256_DIGEST_SIZE; 1221*05ab2901SDag-Erling Smørgrav #endif 1222*05ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA 1223*05ab2901SDag-Erling Smørgrav case LDNS_SHA384: 1224*05ab2901SDag-Erling Smørgrav return SHA384_DIGEST_SIZE; 1225*05ab2901SDag-Erling Smørgrav #endif 1226*05ab2901SDag-Erling Smørgrav /* GOST not supported */ 1227*05ab2901SDag-Erling Smørgrav case LDNS_HASH_GOST: 1228*05ab2901SDag-Erling Smørgrav default: 1229*05ab2901SDag-Erling Smørgrav break; 1230*05ab2901SDag-Erling Smørgrav } 1231*05ab2901SDag-Erling Smørgrav return 0; 1232*05ab2901SDag-Erling Smørgrav } 1233*05ab2901SDag-Erling Smørgrav 1234*05ab2901SDag-Erling Smørgrav int 1235*05ab2901SDag-Erling Smørgrav secalgo_ds_digest(int algo, unsigned char* buf, size_t len, 1236*05ab2901SDag-Erling Smørgrav unsigned char* res) 1237*05ab2901SDag-Erling Smørgrav { 1238*05ab2901SDag-Erling Smørgrav switch(algo) { 1239*05ab2901SDag-Erling Smørgrav case LDNS_SHA1: 1240*05ab2901SDag-Erling Smørgrav return _digest_nettle(SHA1_DIGEST_SIZE, buf, len, res); 1241*05ab2901SDag-Erling Smørgrav #if defined(USE_SHA2) 1242*05ab2901SDag-Erling Smørgrav case LDNS_SHA256: 1243*05ab2901SDag-Erling Smørgrav return _digest_nettle(SHA256_DIGEST_SIZE, buf, len, res); 1244*05ab2901SDag-Erling Smørgrav #endif 1245*05ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA 1246*05ab2901SDag-Erling Smørgrav case LDNS_SHA384: 1247*05ab2901SDag-Erling Smørgrav return _digest_nettle(SHA384_DIGEST_SIZE, buf, len, res); 1248*05ab2901SDag-Erling Smørgrav 1249*05ab2901SDag-Erling Smørgrav #endif 1250*05ab2901SDag-Erling Smørgrav case LDNS_HASH_GOST: 1251*05ab2901SDag-Erling Smørgrav default: 1252*05ab2901SDag-Erling Smørgrav verbose(VERB_QUERY, "unknown DS digest algorithm %d", 1253*05ab2901SDag-Erling Smørgrav algo); 1254*05ab2901SDag-Erling Smørgrav break; 1255*05ab2901SDag-Erling Smørgrav } 1256*05ab2901SDag-Erling Smørgrav return 0; 1257*05ab2901SDag-Erling Smørgrav } 1258*05ab2901SDag-Erling Smørgrav 1259*05ab2901SDag-Erling Smørgrav int 1260*05ab2901SDag-Erling Smørgrav dnskey_algo_id_is_supported(int id) 1261*05ab2901SDag-Erling Smørgrav { 1262*05ab2901SDag-Erling Smørgrav /* uses libnettle */ 1263*05ab2901SDag-Erling Smørgrav switch(id) { 1264*05ab2901SDag-Erling Smørgrav case LDNS_DSA: 1265*05ab2901SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 1266*05ab2901SDag-Erling Smørgrav case LDNS_RSASHA1: 1267*05ab2901SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 1268*05ab2901SDag-Erling Smørgrav #ifdef USE_SHA2 1269*05ab2901SDag-Erling Smørgrav case LDNS_RSASHA256: 1270*05ab2901SDag-Erling Smørgrav case LDNS_RSASHA512: 1271*05ab2901SDag-Erling Smørgrav #endif 1272*05ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA 1273*05ab2901SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 1274*05ab2901SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 1275*05ab2901SDag-Erling Smørgrav #endif 1276*05ab2901SDag-Erling Smørgrav return 1; 1277*05ab2901SDag-Erling Smørgrav case LDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */ 1278*05ab2901SDag-Erling Smørgrav case LDNS_ECC_GOST: 1279*05ab2901SDag-Erling Smørgrav default: 1280*05ab2901SDag-Erling Smørgrav return 0; 1281*05ab2901SDag-Erling Smørgrav } 1282*05ab2901SDag-Erling Smørgrav } 1283*05ab2901SDag-Erling Smørgrav 1284*05ab2901SDag-Erling Smørgrav static char * 1285*05ab2901SDag-Erling Smørgrav _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock, 1286*05ab2901SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen) 1287*05ab2901SDag-Erling Smørgrav { 1288*05ab2901SDag-Erling Smørgrav uint8_t digest[SHA1_DIGEST_SIZE]; 1289*05ab2901SDag-Erling Smørgrav uint8_t key_t; 1290*05ab2901SDag-Erling Smørgrav int res = 0; 1291*05ab2901SDag-Erling Smørgrav size_t offset; 1292*05ab2901SDag-Erling Smørgrav struct dsa_public_key pubkey; 1293*05ab2901SDag-Erling Smørgrav struct dsa_signature signature; 1294*05ab2901SDag-Erling Smørgrav unsigned int expected_len; 1295*05ab2901SDag-Erling Smørgrav 1296*05ab2901SDag-Erling Smørgrav /* Extract DSA signature from the record */ 1297*05ab2901SDag-Erling Smørgrav nettle_dsa_signature_init(&signature); 1298*05ab2901SDag-Erling Smørgrav /* Signature length: 41 bytes - RFC 2536 sec. 3 */ 1299*05ab2901SDag-Erling Smørgrav if(sigblock_len == 41) { 1300*05ab2901SDag-Erling Smørgrav if(key[0] != sigblock[0]) 1301*05ab2901SDag-Erling Smørgrav return "invalid T value in DSA signature or pubkey"; 1302*05ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.r, 20, sigblock+1); 1303*05ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.s, 20, sigblock+1+20); 1304*05ab2901SDag-Erling Smørgrav } else { 1305*05ab2901SDag-Erling Smørgrav /* DER encoded, decode the ASN1 notated R and S bignums */ 1306*05ab2901SDag-Erling Smørgrav /* SEQUENCE { r INTEGER, s INTEGER } */ 1307*05ab2901SDag-Erling Smørgrav struct asn1_der_iterator i, seq; 1308*05ab2901SDag-Erling Smørgrav if(asn1_der_iterator_first(&i, sigblock_len, 1309*05ab2901SDag-Erling Smørgrav (uint8_t*)sigblock) != ASN1_ITERATOR_CONSTRUCTED 1310*05ab2901SDag-Erling Smørgrav || i.type != ASN1_SEQUENCE) 1311*05ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature"; 1312*05ab2901SDag-Erling Smørgrav /* decode this element of i using the seq iterator */ 1313*05ab2901SDag-Erling Smørgrav if(asn1_der_decode_constructed(&i, &seq) != 1314*05ab2901SDag-Erling Smørgrav ASN1_ITERATOR_PRIMITIVE || seq.type != ASN1_INTEGER) 1315*05ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature"; 1316*05ab2901SDag-Erling Smørgrav if(!asn1_der_get_bignum(&seq, signature.r, 20*8)) 1317*05ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature"; 1318*05ab2901SDag-Erling Smørgrav if(asn1_der_iterator_next(&seq) != ASN1_ITERATOR_PRIMITIVE 1319*05ab2901SDag-Erling Smørgrav || seq.type != ASN1_INTEGER) 1320*05ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature"; 1321*05ab2901SDag-Erling Smørgrav if(!asn1_der_get_bignum(&seq, signature.s, 20*8)) 1322*05ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature"; 1323*05ab2901SDag-Erling Smørgrav if(asn1_der_iterator_next(&i) != ASN1_ITERATOR_END) 1324*05ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature"; 1325*05ab2901SDag-Erling Smørgrav } 1326*05ab2901SDag-Erling Smørgrav 1327*05ab2901SDag-Erling Smørgrav /* Validate T values constraints - RFC 2536 sec. 2 & sec. 3 */ 1328*05ab2901SDag-Erling Smørgrav key_t = key[0]; 1329*05ab2901SDag-Erling Smørgrav if (key_t > 8) { 1330*05ab2901SDag-Erling Smørgrav return "invalid T value in DSA pubkey"; 1331*05ab2901SDag-Erling Smørgrav } 1332*05ab2901SDag-Erling Smørgrav 1333*05ab2901SDag-Erling Smørgrav /* Pubkey minimum length: 21 bytes - RFC 2536 sec. 2 */ 1334*05ab2901SDag-Erling Smørgrav if (keylen < 21) { 1335*05ab2901SDag-Erling Smørgrav return "DSA pubkey too short"; 1336*05ab2901SDag-Erling Smørgrav } 1337*05ab2901SDag-Erling Smørgrav 1338*05ab2901SDag-Erling Smørgrav expected_len = 1 + /* T */ 1339*05ab2901SDag-Erling Smørgrav 20 + /* Q */ 1340*05ab2901SDag-Erling Smørgrav (64 + key_t*8) + /* P */ 1341*05ab2901SDag-Erling Smørgrav (64 + key_t*8) + /* G */ 1342*05ab2901SDag-Erling Smørgrav (64 + key_t*8); /* Y */ 1343*05ab2901SDag-Erling Smørgrav if (keylen != expected_len ) { 1344*05ab2901SDag-Erling Smørgrav return "invalid DSA pubkey length"; 1345*05ab2901SDag-Erling Smørgrav } 1346*05ab2901SDag-Erling Smørgrav 1347*05ab2901SDag-Erling Smørgrav /* Extract DSA pubkey from the record */ 1348*05ab2901SDag-Erling Smørgrav nettle_dsa_public_key_init(&pubkey); 1349*05ab2901SDag-Erling Smørgrav offset = 1; 1350*05ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.q, 20, key+offset); 1351*05ab2901SDag-Erling Smørgrav offset += 20; 1352*05ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.p, (64 + key_t*8), key+offset); 1353*05ab2901SDag-Erling Smørgrav offset += (64 + key_t*8); 1354*05ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.g, (64 + key_t*8), key+offset); 1355*05ab2901SDag-Erling Smørgrav offset += (64 + key_t*8); 1356*05ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.y, (64 + key_t*8), key+offset); 1357*05ab2901SDag-Erling Smørgrav 1358*05ab2901SDag-Erling Smørgrav /* Digest content of "buf" and verify its DSA signature in "sigblock"*/ 1359*05ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), 1360*05ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); 1361*05ab2901SDag-Erling Smørgrav res &= dsa_sha1_verify_digest(&pubkey, digest, &signature); 1362*05ab2901SDag-Erling Smørgrav 1363*05ab2901SDag-Erling Smørgrav /* Clear and return */ 1364*05ab2901SDag-Erling Smørgrav nettle_dsa_signature_clear(&signature); 1365*05ab2901SDag-Erling Smørgrav nettle_dsa_public_key_clear(&pubkey); 1366*05ab2901SDag-Erling Smørgrav if (!res) 1367*05ab2901SDag-Erling Smørgrav return "DSA signature verification failed"; 1368*05ab2901SDag-Erling Smørgrav else 1369*05ab2901SDag-Erling Smørgrav return NULL; 1370*05ab2901SDag-Erling Smørgrav } 1371*05ab2901SDag-Erling Smørgrav 1372*05ab2901SDag-Erling Smørgrav static char * 1373*05ab2901SDag-Erling Smørgrav _verify_nettle_rsa(sldns_buffer* buf, unsigned int digest_size, char* sigblock, 1374*05ab2901SDag-Erling Smørgrav unsigned int sigblock_len, uint8_t* key, unsigned int keylen) 1375*05ab2901SDag-Erling Smørgrav { 1376*05ab2901SDag-Erling Smørgrav uint16_t exp_len = 0; 1377*05ab2901SDag-Erling Smørgrav size_t exp_offset = 0, mod_offset = 0; 1378*05ab2901SDag-Erling Smørgrav struct rsa_public_key pubkey; 1379*05ab2901SDag-Erling Smørgrav mpz_t signature; 1380*05ab2901SDag-Erling Smørgrav int res = 0; 1381*05ab2901SDag-Erling Smørgrav 1382*05ab2901SDag-Erling Smørgrav /* RSA pubkey parsing as per RFC 3110 sec. 2 */ 1383*05ab2901SDag-Erling Smørgrav if( keylen <= 1) { 1384*05ab2901SDag-Erling Smørgrav return "null RSA key"; 1385*05ab2901SDag-Erling Smørgrav } 1386*05ab2901SDag-Erling Smørgrav if (key[0] != 0) { 1387*05ab2901SDag-Erling Smørgrav /* 1-byte length */ 1388*05ab2901SDag-Erling Smørgrav exp_len = key[0]; 1389*05ab2901SDag-Erling Smørgrav exp_offset = 1; 1390*05ab2901SDag-Erling Smørgrav } else { 1391*05ab2901SDag-Erling Smørgrav /* 1-byte NUL + 2-bytes exponent length */ 1392*05ab2901SDag-Erling Smørgrav if (keylen < 3) { 1393*05ab2901SDag-Erling Smørgrav return "incorrect RSA key length"; 1394*05ab2901SDag-Erling Smørgrav } 1395*05ab2901SDag-Erling Smørgrav exp_len = READ_UINT16(key+1); 1396*05ab2901SDag-Erling Smørgrav if (exp_len == 0) 1397*05ab2901SDag-Erling Smørgrav return "null RSA exponent length"; 1398*05ab2901SDag-Erling Smørgrav exp_offset = 3; 1399*05ab2901SDag-Erling Smørgrav } 1400*05ab2901SDag-Erling Smørgrav /* Check that we are not over-running input length */ 1401*05ab2901SDag-Erling Smørgrav if (keylen < exp_offset + exp_len + 1) { 1402*05ab2901SDag-Erling Smørgrav return "RSA key content shorter than expected"; 1403*05ab2901SDag-Erling Smørgrav } 1404*05ab2901SDag-Erling Smørgrav mod_offset = exp_offset + exp_len; 1405*05ab2901SDag-Erling Smørgrav nettle_rsa_public_key_init(&pubkey); 1406*05ab2901SDag-Erling Smørgrav pubkey.size = keylen - mod_offset; 1407*05ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.e, exp_len, &key[exp_offset]); 1408*05ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.n, pubkey.size, &key[mod_offset]); 1409*05ab2901SDag-Erling Smørgrav 1410*05ab2901SDag-Erling Smørgrav /* Digest content of "buf" and verify its RSA signature in "sigblock"*/ 1411*05ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(signature, sigblock_len, (uint8_t*)sigblock); 1412*05ab2901SDag-Erling Smørgrav switch (digest_size) { 1413*05ab2901SDag-Erling Smørgrav case SHA1_DIGEST_SIZE: 1414*05ab2901SDag-Erling Smørgrav { 1415*05ab2901SDag-Erling Smørgrav uint8_t digest[SHA1_DIGEST_SIZE]; 1416*05ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), 1417*05ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); 1418*05ab2901SDag-Erling Smørgrav res &= rsa_sha1_verify_digest(&pubkey, digest, signature); 1419*05ab2901SDag-Erling Smørgrav break; 1420*05ab2901SDag-Erling Smørgrav } 1421*05ab2901SDag-Erling Smørgrav case SHA256_DIGEST_SIZE: 1422*05ab2901SDag-Erling Smørgrav { 1423*05ab2901SDag-Erling Smørgrav uint8_t digest[SHA256_DIGEST_SIZE]; 1424*05ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), 1425*05ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); 1426*05ab2901SDag-Erling Smørgrav res &= rsa_sha256_verify_digest(&pubkey, digest, signature); 1427*05ab2901SDag-Erling Smørgrav break; 1428*05ab2901SDag-Erling Smørgrav } 1429*05ab2901SDag-Erling Smørgrav case SHA512_DIGEST_SIZE: 1430*05ab2901SDag-Erling Smørgrav { 1431*05ab2901SDag-Erling Smørgrav uint8_t digest[SHA512_DIGEST_SIZE]; 1432*05ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA512_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), 1433*05ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); 1434*05ab2901SDag-Erling Smørgrav res &= rsa_sha512_verify_digest(&pubkey, digest, signature); 1435*05ab2901SDag-Erling Smørgrav break; 1436*05ab2901SDag-Erling Smørgrav } 1437*05ab2901SDag-Erling Smørgrav default: 1438*05ab2901SDag-Erling Smørgrav break; 1439*05ab2901SDag-Erling Smørgrav } 1440*05ab2901SDag-Erling Smørgrav 1441*05ab2901SDag-Erling Smørgrav /* Clear and return */ 1442*05ab2901SDag-Erling Smørgrav nettle_rsa_public_key_clear(&pubkey); 1443*05ab2901SDag-Erling Smørgrav mpz_clear(signature); 1444*05ab2901SDag-Erling Smørgrav if (!res) { 1445*05ab2901SDag-Erling Smørgrav return "RSA signature verification failed"; 1446*05ab2901SDag-Erling Smørgrav } else { 1447*05ab2901SDag-Erling Smørgrav return NULL; 1448*05ab2901SDag-Erling Smørgrav } 1449*05ab2901SDag-Erling Smørgrav } 1450*05ab2901SDag-Erling Smørgrav 1451*05ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA 1452*05ab2901SDag-Erling Smørgrav static char * 1453*05ab2901SDag-Erling Smørgrav _verify_nettle_ecdsa(sldns_buffer* buf, unsigned int digest_size, unsigned char* sigblock, 1454*05ab2901SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen) 1455*05ab2901SDag-Erling Smørgrav { 1456*05ab2901SDag-Erling Smørgrav int res = 0; 1457*05ab2901SDag-Erling Smørgrav struct ecc_point pubkey; 1458*05ab2901SDag-Erling Smørgrav struct dsa_signature signature; 1459*05ab2901SDag-Erling Smørgrav 1460*05ab2901SDag-Erling Smørgrav /* Always matched strength, as per RFC 6605 sec. 1 */ 1461*05ab2901SDag-Erling Smørgrav if (sigblock_len != 2*digest_size || keylen != 2*digest_size) { 1462*05ab2901SDag-Erling Smørgrav return "wrong ECDSA signature length"; 1463*05ab2901SDag-Erling Smørgrav } 1464*05ab2901SDag-Erling Smørgrav 1465*05ab2901SDag-Erling Smørgrav /* Parse ECDSA signature as per RFC 6605 sec. 4 */ 1466*05ab2901SDag-Erling Smørgrav nettle_dsa_signature_init(&signature); 1467*05ab2901SDag-Erling Smørgrav switch (digest_size) { 1468*05ab2901SDag-Erling Smørgrav case SHA256_DIGEST_SIZE: 1469*05ab2901SDag-Erling Smørgrav { 1470*05ab2901SDag-Erling Smørgrav uint8_t digest[SHA256_DIGEST_SIZE]; 1471*05ab2901SDag-Erling Smørgrav mpz_t x, y; 1472*05ab2901SDag-Erling Smørgrav nettle_ecc_point_init(&pubkey, &nettle_secp_256r1); 1473*05ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(x, SHA256_DIGEST_SIZE, key); 1474*05ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(y, SHA256_DIGEST_SIZE, key+SHA256_DIGEST_SIZE); 1475*05ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.r, SHA256_DIGEST_SIZE, sigblock); 1476*05ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.s, SHA256_DIGEST_SIZE, sigblock+SHA256_DIGEST_SIZE); 1477*05ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), 1478*05ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); 1479*05ab2901SDag-Erling Smørgrav res &= nettle_ecc_point_set(&pubkey, x, y); 1480*05ab2901SDag-Erling Smørgrav res &= nettle_ecdsa_verify (&pubkey, SHA256_DIGEST_SIZE, digest, &signature); 1481*05ab2901SDag-Erling Smørgrav mpz_clear(x); 1482*05ab2901SDag-Erling Smørgrav mpz_clear(y); 1483*05ab2901SDag-Erling Smørgrav break; 1484*05ab2901SDag-Erling Smørgrav } 1485*05ab2901SDag-Erling Smørgrav case SHA384_DIGEST_SIZE: 1486*05ab2901SDag-Erling Smørgrav { 1487*05ab2901SDag-Erling Smørgrav uint8_t digest[SHA384_DIGEST_SIZE]; 1488*05ab2901SDag-Erling Smørgrav mpz_t x, y; 1489*05ab2901SDag-Erling Smørgrav nettle_ecc_point_init(&pubkey, &nettle_secp_384r1); 1490*05ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(x, SHA384_DIGEST_SIZE, key); 1491*05ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(y, SHA384_DIGEST_SIZE, key+SHA384_DIGEST_SIZE); 1492*05ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.r, SHA384_DIGEST_SIZE, sigblock); 1493*05ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.s, SHA384_DIGEST_SIZE, sigblock+SHA384_DIGEST_SIZE); 1494*05ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA384_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), 1495*05ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); 1496*05ab2901SDag-Erling Smørgrav res &= nettle_ecc_point_set(&pubkey, x, y); 1497*05ab2901SDag-Erling Smørgrav res &= nettle_ecdsa_verify (&pubkey, SHA384_DIGEST_SIZE, digest, &signature); 1498*05ab2901SDag-Erling Smørgrav mpz_clear(x); 1499*05ab2901SDag-Erling Smørgrav mpz_clear(y); 1500*05ab2901SDag-Erling Smørgrav nettle_ecc_point_clear(&pubkey); 1501*05ab2901SDag-Erling Smørgrav break; 1502*05ab2901SDag-Erling Smørgrav } 1503*05ab2901SDag-Erling Smørgrav default: 1504*05ab2901SDag-Erling Smørgrav return "unknown ECDSA algorithm"; 1505*05ab2901SDag-Erling Smørgrav } 1506*05ab2901SDag-Erling Smørgrav 1507*05ab2901SDag-Erling Smørgrav /* Clear and return */ 1508*05ab2901SDag-Erling Smørgrav nettle_dsa_signature_clear(&signature); 1509*05ab2901SDag-Erling Smørgrav if (!res) 1510*05ab2901SDag-Erling Smørgrav return "ECDSA signature verification failed"; 1511*05ab2901SDag-Erling Smørgrav else 1512*05ab2901SDag-Erling Smørgrav return NULL; 1513*05ab2901SDag-Erling Smørgrav } 1514*05ab2901SDag-Erling Smørgrav #endif 1515*05ab2901SDag-Erling Smørgrav 1516*05ab2901SDag-Erling Smørgrav /** 1517*05ab2901SDag-Erling Smørgrav * Check a canonical sig+rrset and signature against a dnskey 1518*05ab2901SDag-Erling Smørgrav * @param buf: buffer with data to verify, the first rrsig part and the 1519*05ab2901SDag-Erling Smørgrav * canonicalized rrset. 1520*05ab2901SDag-Erling Smørgrav * @param algo: DNSKEY algorithm. 1521*05ab2901SDag-Erling Smørgrav * @param sigblock: signature rdata field from RRSIG 1522*05ab2901SDag-Erling Smørgrav * @param sigblock_len: length of sigblock data. 1523*05ab2901SDag-Erling Smørgrav * @param key: public key data from DNSKEY RR. 1524*05ab2901SDag-Erling Smørgrav * @param keylen: length of keydata. 1525*05ab2901SDag-Erling Smørgrav * @param reason: bogus reason in more detail. 1526*05ab2901SDag-Erling Smørgrav * @return secure if verification succeeded, bogus on crypto failure, 1527*05ab2901SDag-Erling Smørgrav * unchecked on format errors and alloc failures. 1528*05ab2901SDag-Erling Smørgrav */ 1529*05ab2901SDag-Erling Smørgrav enum sec_status 1530*05ab2901SDag-Erling Smørgrav verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, 1531*05ab2901SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen, 1532*05ab2901SDag-Erling Smørgrav char** reason) 1533*05ab2901SDag-Erling Smørgrav { 1534*05ab2901SDag-Erling Smørgrav unsigned int digest_size = 0; 1535*05ab2901SDag-Erling Smørgrav 1536*05ab2901SDag-Erling Smørgrav if (sigblock_len == 0 || keylen == 0) { 1537*05ab2901SDag-Erling Smørgrav *reason = "null signature"; 1538*05ab2901SDag-Erling Smørgrav return sec_status_bogus; 1539*05ab2901SDag-Erling Smørgrav } 1540*05ab2901SDag-Erling Smørgrav 1541*05ab2901SDag-Erling Smørgrav switch(algo) { 1542*05ab2901SDag-Erling Smørgrav case LDNS_DSA: 1543*05ab2901SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 1544*05ab2901SDag-Erling Smørgrav *reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen); 1545*05ab2901SDag-Erling Smørgrav if (*reason != NULL) 1546*05ab2901SDag-Erling Smørgrav return sec_status_bogus; 1547*05ab2901SDag-Erling Smørgrav else 1548*05ab2901SDag-Erling Smørgrav return sec_status_secure; 1549*05ab2901SDag-Erling Smørgrav 1550*05ab2901SDag-Erling Smørgrav case LDNS_RSASHA1: 1551*05ab2901SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 1552*05ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE); 1553*05ab2901SDag-Erling Smørgrav #ifdef USE_SHA2 1554*05ab2901SDag-Erling Smørgrav case LDNS_RSASHA256: 1555*05ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE); 1556*05ab2901SDag-Erling Smørgrav case LDNS_RSASHA512: 1557*05ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA512_DIGEST_SIZE); 1558*05ab2901SDag-Erling Smørgrav 1559*05ab2901SDag-Erling Smørgrav #endif 1560*05ab2901SDag-Erling Smørgrav *reason = _verify_nettle_rsa(buf, digest_size, (char*)sigblock, 1561*05ab2901SDag-Erling Smørgrav sigblock_len, key, keylen); 1562*05ab2901SDag-Erling Smørgrav if (*reason != NULL) 1563*05ab2901SDag-Erling Smørgrav return sec_status_bogus; 1564*05ab2901SDag-Erling Smørgrav else 1565*05ab2901SDag-Erling Smørgrav return sec_status_secure; 1566*05ab2901SDag-Erling Smørgrav 1567*05ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA 1568*05ab2901SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 1569*05ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE); 1570*05ab2901SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 1571*05ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA384_DIGEST_SIZE); 1572*05ab2901SDag-Erling Smørgrav *reason = _verify_nettle_ecdsa(buf, digest_size, sigblock, 1573*05ab2901SDag-Erling Smørgrav sigblock_len, key, keylen); 1574*05ab2901SDag-Erling Smørgrav if (*reason != NULL) 1575*05ab2901SDag-Erling Smørgrav return sec_status_bogus; 1576*05ab2901SDag-Erling Smørgrav else 1577*05ab2901SDag-Erling Smørgrav return sec_status_secure; 1578*05ab2901SDag-Erling Smørgrav #endif 1579*05ab2901SDag-Erling Smørgrav case LDNS_RSAMD5: 1580*05ab2901SDag-Erling Smørgrav case LDNS_ECC_GOST: 1581*05ab2901SDag-Erling Smørgrav default: 1582*05ab2901SDag-Erling Smørgrav *reason = "unable to verify signature, unknown algorithm"; 1583*05ab2901SDag-Erling Smørgrav return sec_status_bogus; 1584*05ab2901SDag-Erling Smørgrav } 1585*05ab2901SDag-Erling Smørgrav } 1586*05ab2901SDag-Erling Smørgrav 1587*05ab2901SDag-Erling Smørgrav #endif /* HAVE_SSL or HAVE_NSS or HAVE_NETTLE */ 1588