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" 4705ab2901SDag-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 5305ab2901SDag-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 75bc892140SDag-Erling Smørgrav /** fake DSA support for unit tests */ 76bc892140SDag-Erling Smørgrav int fake_dsa = 0; 7765b390aaSDag-Erling Smørgrav /** fake SHA1 support for unit tests */ 7865b390aaSDag-Erling Smørgrav int fake_sha1 = 0; 79bc892140SDag-Erling Smørgrav 8005ab2901SDag-Erling Smørgrav /* return size of digest if supported, or 0 otherwise */ 8105ab2901SDag-Erling Smørgrav size_t 8205ab2901SDag-Erling Smørgrav nsec3_hash_algo_size_supported(int id) 8305ab2901SDag-Erling Smørgrav { 8405ab2901SDag-Erling Smørgrav switch(id) { 8505ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1: 8605ab2901SDag-Erling Smørgrav return SHA_DIGEST_LENGTH; 8705ab2901SDag-Erling Smørgrav default: 8805ab2901SDag-Erling Smørgrav return 0; 8905ab2901SDag-Erling Smørgrav } 9005ab2901SDag-Erling Smørgrav } 9105ab2901SDag-Erling Smørgrav 9205ab2901SDag-Erling Smørgrav /* perform nsec3 hash. return false on failure */ 9305ab2901SDag-Erling Smørgrav int 9405ab2901SDag-Erling Smørgrav secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, 9505ab2901SDag-Erling Smørgrav unsigned char* res) 9605ab2901SDag-Erling Smørgrav { 9705ab2901SDag-Erling Smørgrav switch(algo) { 9805ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1: 9905ab2901SDag-Erling Smørgrav (void)SHA1(buf, len, res); 10005ab2901SDag-Erling Smørgrav return 1; 10105ab2901SDag-Erling Smørgrav default: 10205ab2901SDag-Erling Smørgrav return 0; 10305ab2901SDag-Erling Smørgrav } 10405ab2901SDag-Erling Smørgrav } 10505ab2901SDag-Erling Smørgrav 106e2d15004SDag-Erling Smørgrav void 107e2d15004SDag-Erling Smørgrav secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res) 108e2d15004SDag-Erling Smørgrav { 109e2d15004SDag-Erling Smørgrav (void)SHA256(buf, len, res); 110e2d15004SDag-Erling Smørgrav } 111e2d15004SDag-Erling Smørgrav 1128ed2b524SDag-Erling Smørgrav /** 1138ed2b524SDag-Erling Smørgrav * Return size of DS digest according to its hash algorithm. 1148ed2b524SDag-Erling Smørgrav * @param algo: DS digest algo. 1158ed2b524SDag-Erling Smørgrav * @return size in bytes of digest, or 0 if not supported. 1168ed2b524SDag-Erling Smørgrav */ 1178ed2b524SDag-Erling Smørgrav size_t 1188ed2b524SDag-Erling Smørgrav ds_digest_size_supported(int algo) 1198ed2b524SDag-Erling Smørgrav { 1208ed2b524SDag-Erling Smørgrav switch(algo) { 1218ed2b524SDag-Erling Smørgrav case LDNS_SHA1: 12265b390aaSDag-Erling Smørgrav #if defined(HAVE_EVP_SHA1) && defined(USE_SHA1) 1238ed2b524SDag-Erling Smørgrav return SHA_DIGEST_LENGTH; 12465b390aaSDag-Erling Smørgrav #else 12565b390aaSDag-Erling Smørgrav if(fake_sha1) return 20; 12665b390aaSDag-Erling Smørgrav return 0; 1278ed2b524SDag-Erling Smørgrav #endif 1288ed2b524SDag-Erling Smørgrav #ifdef HAVE_EVP_SHA256 1298ed2b524SDag-Erling Smørgrav case LDNS_SHA256: 1308ed2b524SDag-Erling Smørgrav return SHA256_DIGEST_LENGTH; 1318ed2b524SDag-Erling Smørgrav #endif 1328ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 1338ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST: 134f61ef7f6SDag-Erling Smørgrav /* we support GOST if it can be loaded */ 135f61ef7f6SDag-Erling Smørgrav (void)sldns_key_EVP_load_gost_id(); 1368ed2b524SDag-Erling Smørgrav if(EVP_get_digestbyname("md_gost94")) 1378ed2b524SDag-Erling Smørgrav return 32; 1388ed2b524SDag-Erling Smørgrav else return 0; 1398ed2b524SDag-Erling Smørgrav #endif 1408ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 1418ed2b524SDag-Erling Smørgrav case LDNS_SHA384: 1428ed2b524SDag-Erling Smørgrav return SHA384_DIGEST_LENGTH; 1438ed2b524SDag-Erling Smørgrav #endif 1448ed2b524SDag-Erling Smørgrav default: break; 1458ed2b524SDag-Erling Smørgrav } 1468ed2b524SDag-Erling Smørgrav return 0; 1478ed2b524SDag-Erling Smørgrav } 1488ed2b524SDag-Erling Smørgrav 1498ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 1508ed2b524SDag-Erling Smørgrav /** Perform GOST hash */ 1518ed2b524SDag-Erling Smørgrav static int 1528ed2b524SDag-Erling Smørgrav do_gost94(unsigned char* data, size_t len, unsigned char* dest) 1538ed2b524SDag-Erling Smørgrav { 1548ed2b524SDag-Erling Smørgrav const EVP_MD* md = EVP_get_digestbyname("md_gost94"); 1558ed2b524SDag-Erling Smørgrav if(!md) 1568ed2b524SDag-Erling Smørgrav return 0; 15717d15b25SDag-Erling Smørgrav return sldns_digest_evp(data, (unsigned int)len, dest, md); 1588ed2b524SDag-Erling Smørgrav } 1598ed2b524SDag-Erling Smørgrav #endif 1608ed2b524SDag-Erling Smørgrav 1618ed2b524SDag-Erling Smørgrav int 1628ed2b524SDag-Erling Smørgrav secalgo_ds_digest(int algo, unsigned char* buf, size_t len, 1638ed2b524SDag-Erling Smørgrav unsigned char* res) 1648ed2b524SDag-Erling Smørgrav { 1658ed2b524SDag-Erling Smørgrav switch(algo) { 16665b390aaSDag-Erling Smørgrav #if defined(HAVE_EVP_SHA1) && defined(USE_SHA1) 1678ed2b524SDag-Erling Smørgrav case LDNS_SHA1: 1688ed2b524SDag-Erling Smørgrav (void)SHA1(buf, len, res); 1698ed2b524SDag-Erling Smørgrav return 1; 1708ed2b524SDag-Erling Smørgrav #endif 1718ed2b524SDag-Erling Smørgrav #ifdef HAVE_EVP_SHA256 1728ed2b524SDag-Erling Smørgrav case LDNS_SHA256: 1738ed2b524SDag-Erling Smørgrav (void)SHA256(buf, len, res); 1748ed2b524SDag-Erling Smørgrav return 1; 1758ed2b524SDag-Erling Smørgrav #endif 1768ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 1778ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST: 1788ed2b524SDag-Erling Smørgrav if(do_gost94(buf, len, res)) 1798ed2b524SDag-Erling Smørgrav return 1; 1808ed2b524SDag-Erling Smørgrav break; 1818ed2b524SDag-Erling Smørgrav #endif 1828ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 1838ed2b524SDag-Erling Smørgrav case LDNS_SHA384: 1848ed2b524SDag-Erling Smørgrav (void)SHA384(buf, len, res); 1858ed2b524SDag-Erling Smørgrav return 1; 1868ed2b524SDag-Erling Smørgrav #endif 1878ed2b524SDag-Erling Smørgrav default: 1888ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "unknown DS digest algorithm %d", 1898ed2b524SDag-Erling Smørgrav algo); 1908ed2b524SDag-Erling Smørgrav break; 1918ed2b524SDag-Erling Smørgrav } 1928ed2b524SDag-Erling Smørgrav return 0; 1938ed2b524SDag-Erling Smørgrav } 1948ed2b524SDag-Erling Smørgrav 1958ed2b524SDag-Erling Smørgrav /** return true if DNSKEY algorithm id is supported */ 1968ed2b524SDag-Erling Smørgrav int 1978ed2b524SDag-Erling Smørgrav dnskey_algo_id_is_supported(int id) 1988ed2b524SDag-Erling Smørgrav { 1998ed2b524SDag-Erling Smørgrav switch(id) { 2008ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5: 2018ed2b524SDag-Erling Smørgrav /* RFC 6725 deprecates RSAMD5 */ 2028ed2b524SDag-Erling Smørgrav return 0; 2038ed2b524SDag-Erling Smørgrav case LDNS_DSA: 2048ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 20565b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1) 206bc892140SDag-Erling Smørgrav return 1; 207bc892140SDag-Erling Smørgrav #else 20865b390aaSDag-Erling Smørgrav if(fake_dsa || fake_sha1) return 1; 209bc892140SDag-Erling Smørgrav return 0; 210e2d15004SDag-Erling Smørgrav #endif 21165b390aaSDag-Erling Smørgrav 2128ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1: 2138ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 21465b390aaSDag-Erling Smørgrav #ifdef USE_SHA1 21565b390aaSDag-Erling Smørgrav return 1; 21665b390aaSDag-Erling Smørgrav #else 21765b390aaSDag-Erling Smørgrav if(fake_sha1) return 1; 21865b390aaSDag-Erling Smørgrav return 0; 21965b390aaSDag-Erling Smørgrav #endif 22065b390aaSDag-Erling Smørgrav 2218ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) 2228ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256: 2238ed2b524SDag-Erling Smørgrav #endif 2248ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) 2258ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512: 2268ed2b524SDag-Erling Smørgrav #endif 2278ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 2288ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 2298ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 2308ed2b524SDag-Erling Smørgrav #endif 231c7f4d7adSDag-Erling Smørgrav #ifdef USE_ED25519 232c7f4d7adSDag-Erling Smørgrav case LDNS_ED25519: 233c7f4d7adSDag-Erling Smørgrav #endif 234*0fb34990SDag-Erling Smørgrav #ifdef USE_ED448 235*0fb34990SDag-Erling Smørgrav case LDNS_ED448: 236*0fb34990SDag-Erling Smørgrav #endif 237*0fb34990SDag-Erling Smørgrav #if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA) || defined(USE_ED25519) || defined(USE_ED448) 2388ed2b524SDag-Erling Smørgrav return 1; 23965b390aaSDag-Erling Smørgrav #endif 24065b390aaSDag-Erling Smørgrav 2418ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 2428ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST: 2438ed2b524SDag-Erling Smørgrav /* we support GOST if it can be loaded */ 24417d15b25SDag-Erling Smørgrav return sldns_key_EVP_load_gost_id(); 2458ed2b524SDag-Erling Smørgrav #endif 2468ed2b524SDag-Erling Smørgrav default: 2478ed2b524SDag-Erling Smørgrav return 0; 2488ed2b524SDag-Erling Smørgrav } 2498ed2b524SDag-Erling Smørgrav } 2508ed2b524SDag-Erling Smørgrav 2518ed2b524SDag-Erling Smørgrav /** 2528ed2b524SDag-Erling Smørgrav * Output a libcrypto openssl error to the logfile. 2538ed2b524SDag-Erling Smørgrav * @param str: string to add to it. 2548ed2b524SDag-Erling Smørgrav * @param e: the error to output, error number from ERR_get_error(). 2558ed2b524SDag-Erling Smørgrav */ 2568ed2b524SDag-Erling Smørgrav static void 2578ed2b524SDag-Erling Smørgrav log_crypto_error(const char* str, unsigned long e) 2588ed2b524SDag-Erling Smørgrav { 2598ed2b524SDag-Erling Smørgrav char buf[128]; 2608ed2b524SDag-Erling Smørgrav /* or use ERR_error_string if ERR_error_string_n is not avail TODO */ 2618ed2b524SDag-Erling Smørgrav ERR_error_string_n(e, buf, sizeof(buf)); 2628ed2b524SDag-Erling Smørgrav /* buf now contains */ 2638ed2b524SDag-Erling Smørgrav /* error:[error code]:[library name]:[function name]:[reason string] */ 2648ed2b524SDag-Erling Smørgrav log_err("%s crypto %s", str, buf); 2658ed2b524SDag-Erling Smørgrav } 2668ed2b524SDag-Erling Smørgrav 267e2d15004SDag-Erling Smørgrav #ifdef USE_DSA 2688ed2b524SDag-Erling Smørgrav /** 2698ed2b524SDag-Erling Smørgrav * Setup DSA key digest in DER encoding ... 2708ed2b524SDag-Erling Smørgrav * @param sig: input is signature output alloced ptr (unless failure). 2718ed2b524SDag-Erling Smørgrav * caller must free alloced ptr if this routine returns true. 2728ed2b524SDag-Erling Smørgrav * @param len: input is initial siglen, output is output len. 2738ed2b524SDag-Erling Smørgrav * @return false on failure. 2748ed2b524SDag-Erling Smørgrav */ 2758ed2b524SDag-Erling Smørgrav static int 2768ed2b524SDag-Erling Smørgrav setup_dsa_sig(unsigned char** sig, unsigned int* len) 2778ed2b524SDag-Erling Smørgrav { 2788ed2b524SDag-Erling Smørgrav unsigned char* orig = *sig; 2798ed2b524SDag-Erling Smørgrav unsigned int origlen = *len; 2808ed2b524SDag-Erling Smørgrav int newlen; 2818ed2b524SDag-Erling Smørgrav BIGNUM *R, *S; 2828ed2b524SDag-Erling Smørgrav DSA_SIG *dsasig; 2838ed2b524SDag-Erling Smørgrav 2848ed2b524SDag-Erling Smørgrav /* extract the R and S field from the sig buffer */ 2858ed2b524SDag-Erling Smørgrav if(origlen < 1 + 2*SHA_DIGEST_LENGTH) 2868ed2b524SDag-Erling Smørgrav return 0; 2878ed2b524SDag-Erling Smørgrav R = BN_new(); 2888ed2b524SDag-Erling Smørgrav if(!R) return 0; 2898ed2b524SDag-Erling Smørgrav (void) BN_bin2bn(orig + 1, SHA_DIGEST_LENGTH, R); 2908ed2b524SDag-Erling Smørgrav S = BN_new(); 2918ed2b524SDag-Erling Smørgrav if(!S) return 0; 2928ed2b524SDag-Erling Smørgrav (void) BN_bin2bn(orig + 21, SHA_DIGEST_LENGTH, S); 2938ed2b524SDag-Erling Smørgrav dsasig = DSA_SIG_new(); 2948ed2b524SDag-Erling Smørgrav if(!dsasig) return 0; 2958ed2b524SDag-Erling Smørgrav 296bc892140SDag-Erling Smørgrav #ifdef HAVE_DSA_SIG_SET0 297bc892140SDag-Erling Smørgrav if(!DSA_SIG_set0(dsasig, R, S)) return 0; 298bc892140SDag-Erling Smørgrav #else 2998ed2b524SDag-Erling Smørgrav dsasig->r = R; 3008ed2b524SDag-Erling Smørgrav dsasig->s = S; 301bc892140SDag-Erling Smørgrav #endif 3028ed2b524SDag-Erling Smørgrav *sig = NULL; 3038ed2b524SDag-Erling Smørgrav newlen = i2d_DSA_SIG(dsasig, sig); 3048ed2b524SDag-Erling Smørgrav if(newlen < 0) { 3058ed2b524SDag-Erling Smørgrav DSA_SIG_free(dsasig); 3068ed2b524SDag-Erling Smørgrav free(*sig); 3078ed2b524SDag-Erling Smørgrav return 0; 3088ed2b524SDag-Erling Smørgrav } 3098ed2b524SDag-Erling Smørgrav *len = (unsigned int)newlen; 3108ed2b524SDag-Erling Smørgrav DSA_SIG_free(dsasig); 3118ed2b524SDag-Erling Smørgrav return 1; 3128ed2b524SDag-Erling Smørgrav } 313e2d15004SDag-Erling Smørgrav #endif /* USE_DSA */ 3148ed2b524SDag-Erling Smørgrav 3158ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 3168ed2b524SDag-Erling Smørgrav /** 3178ed2b524SDag-Erling Smørgrav * Setup the ECDSA signature in its encoding that the library wants. 3188ed2b524SDag-Erling Smørgrav * Converts from plain numbers to ASN formatted. 3198ed2b524SDag-Erling Smørgrav * @param sig: input is signature, output alloced ptr (unless failure). 3208ed2b524SDag-Erling Smørgrav * caller must free alloced ptr if this routine returns true. 3218ed2b524SDag-Erling Smørgrav * @param len: input is initial siglen, output is output len. 3228ed2b524SDag-Erling Smørgrav * @return false on failure. 3238ed2b524SDag-Erling Smørgrav */ 3248ed2b524SDag-Erling Smørgrav static int 3258ed2b524SDag-Erling Smørgrav setup_ecdsa_sig(unsigned char** sig, unsigned int* len) 3268ed2b524SDag-Erling Smørgrav { 327e2d15004SDag-Erling Smørgrav /* convert from two BIGNUMs in the rdata buffer, to ASN notation. 3288a384985SDag-Erling Smørgrav * ASN preamble: 30440220 <R 32bytefor256> 0220 <S 32bytefor256> 329e2d15004SDag-Erling Smørgrav * the '20' is the length of that field (=bnsize). 330e2d15004SDag-Erling Smørgrav i * the '44' is the total remaining length. 331e2d15004SDag-Erling Smørgrav * if negative, start with leading zero. 332e2d15004SDag-Erling Smørgrav * if starts with 00s, remove them from the number. 333e2d15004SDag-Erling Smørgrav */ 334e2d15004SDag-Erling Smørgrav uint8_t pre[] = {0x30, 0x44, 0x02, 0x20}; 335e2d15004SDag-Erling Smørgrav int pre_len = 4; 336e2d15004SDag-Erling Smørgrav uint8_t mid[] = {0x02, 0x20}; 337e2d15004SDag-Erling Smørgrav int mid_len = 2; 338e2d15004SDag-Erling Smørgrav int raw_sig_len, r_high, s_high, r_rem=0, s_rem=0; 3398ed2b524SDag-Erling Smørgrav int bnsize = (int)((*len)/2); 340e2d15004SDag-Erling Smørgrav unsigned char* d = *sig; 341e2d15004SDag-Erling Smørgrav uint8_t* p; 3428ed2b524SDag-Erling Smørgrav /* if too short or not even length, fails */ 3438ed2b524SDag-Erling Smørgrav if(*len < 16 || bnsize*2 != (int)*len) 3448ed2b524SDag-Erling Smørgrav return 0; 3458ed2b524SDag-Erling Smørgrav 346e2d15004SDag-Erling Smørgrav /* strip leading zeroes from r (but not last one) */ 347e2d15004SDag-Erling Smørgrav while(r_rem < bnsize-1 && d[r_rem] == 0) 348e2d15004SDag-Erling Smørgrav r_rem++; 349e2d15004SDag-Erling Smørgrav /* strip leading zeroes from s (but not last one) */ 350e2d15004SDag-Erling Smørgrav while(s_rem < bnsize-1 && d[bnsize+s_rem] == 0) 351e2d15004SDag-Erling Smørgrav s_rem++; 352e2d15004SDag-Erling Smørgrav 353e2d15004SDag-Erling Smørgrav r_high = ((d[0+r_rem]&0x80)?1:0); 354e2d15004SDag-Erling Smørgrav s_high = ((d[bnsize+s_rem]&0x80)?1:0); 355e2d15004SDag-Erling Smørgrav raw_sig_len = pre_len + r_high + bnsize - r_rem + mid_len + 356e2d15004SDag-Erling Smørgrav s_high + bnsize - s_rem; 357e2d15004SDag-Erling Smørgrav *sig = (unsigned char*)malloc((size_t)raw_sig_len); 358e2d15004SDag-Erling Smørgrav if(!*sig) 3598ed2b524SDag-Erling Smørgrav return 0; 360e2d15004SDag-Erling Smørgrav p = (uint8_t*)*sig; 361e2d15004SDag-Erling Smørgrav p[0] = pre[0]; 362e2d15004SDag-Erling Smørgrav p[1] = (uint8_t)(raw_sig_len-2); 363e2d15004SDag-Erling Smørgrav p[2] = pre[2]; 364e2d15004SDag-Erling Smørgrav p[3] = (uint8_t)(bnsize + r_high - r_rem); 365e2d15004SDag-Erling Smørgrav p += 4; 366e2d15004SDag-Erling Smørgrav if(r_high) { 367e2d15004SDag-Erling Smørgrav *p = 0; 368e2d15004SDag-Erling Smørgrav p += 1; 3698ed2b524SDag-Erling Smørgrav } 370e2d15004SDag-Erling Smørgrav memmove(p, d+r_rem, (size_t)bnsize-r_rem); 371e2d15004SDag-Erling Smørgrav p += bnsize-r_rem; 372e2d15004SDag-Erling Smørgrav memmove(p, mid, (size_t)mid_len-1); 373e2d15004SDag-Erling Smørgrav p += mid_len-1; 374e2d15004SDag-Erling Smørgrav *p = (uint8_t)(bnsize + s_high - s_rem); 375e2d15004SDag-Erling Smørgrav p += 1; 376e2d15004SDag-Erling Smørgrav if(s_high) { 377e2d15004SDag-Erling Smørgrav *p = 0; 378e2d15004SDag-Erling Smørgrav p += 1; 379e2d15004SDag-Erling Smørgrav } 380e2d15004SDag-Erling Smørgrav memmove(p, d+bnsize+s_rem, (size_t)bnsize-s_rem); 381e2d15004SDag-Erling Smørgrav *len = (unsigned int)raw_sig_len; 3828ed2b524SDag-Erling Smørgrav return 1; 3838ed2b524SDag-Erling Smørgrav } 3848ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */ 3858ed2b524SDag-Erling Smørgrav 386b5663de9SDag-Erling Smørgrav #ifdef USE_ECDSA_EVP_WORKAROUND 387b5663de9SDag-Erling Smørgrav static EVP_MD ecdsa_evp_256_md; 388b5663de9SDag-Erling Smørgrav static EVP_MD ecdsa_evp_384_md; 389b5663de9SDag-Erling Smørgrav void ecdsa_evp_workaround_init(void) 390b5663de9SDag-Erling Smørgrav { 391b5663de9SDag-Erling Smørgrav /* openssl before 1.0.0 fixes RSA with the SHA256 392b5663de9SDag-Erling Smørgrav * hash in EVP. We create one for ecdsa_sha256 */ 393b5663de9SDag-Erling Smørgrav ecdsa_evp_256_md = *EVP_sha256(); 394b5663de9SDag-Erling Smørgrav ecdsa_evp_256_md.required_pkey_type[0] = EVP_PKEY_EC; 395b5663de9SDag-Erling Smørgrav ecdsa_evp_256_md.verify = (void*)ECDSA_verify; 396b5663de9SDag-Erling Smørgrav 397b5663de9SDag-Erling Smørgrav ecdsa_evp_384_md = *EVP_sha384(); 398b5663de9SDag-Erling Smørgrav ecdsa_evp_384_md.required_pkey_type[0] = EVP_PKEY_EC; 399b5663de9SDag-Erling Smørgrav ecdsa_evp_384_md.verify = (void*)ECDSA_verify; 400b5663de9SDag-Erling Smørgrav } 401b5663de9SDag-Erling Smørgrav #endif /* USE_ECDSA_EVP_WORKAROUND */ 402b5663de9SDag-Erling Smørgrav 4038ed2b524SDag-Erling Smørgrav /** 4048ed2b524SDag-Erling Smørgrav * Setup key and digest for verification. Adjust sig if necessary. 4058ed2b524SDag-Erling Smørgrav * 4068ed2b524SDag-Erling Smørgrav * @param algo: key algorithm 4078ed2b524SDag-Erling Smørgrav * @param evp_key: EVP PKEY public key to create. 4088ed2b524SDag-Erling Smørgrav * @param digest_type: digest type to use 4098ed2b524SDag-Erling Smørgrav * @param key: key to setup for. 4108ed2b524SDag-Erling Smørgrav * @param keylen: length of key. 4118ed2b524SDag-Erling Smørgrav * @return false on failure. 4128ed2b524SDag-Erling Smørgrav */ 4138ed2b524SDag-Erling Smørgrav static int 4148ed2b524SDag-Erling Smørgrav setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, 4158ed2b524SDag-Erling Smørgrav unsigned char* key, size_t keylen) 4168ed2b524SDag-Erling Smørgrav { 41765b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1) 4188ed2b524SDag-Erling Smørgrav DSA* dsa; 419e2d15004SDag-Erling Smørgrav #endif 4208ed2b524SDag-Erling Smørgrav RSA* rsa; 4218ed2b524SDag-Erling Smørgrav 4228ed2b524SDag-Erling Smørgrav switch(algo) { 42365b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1) 4248ed2b524SDag-Erling Smørgrav case LDNS_DSA: 4258ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 4268ed2b524SDag-Erling Smørgrav *evp_key = EVP_PKEY_new(); 4278ed2b524SDag-Erling Smørgrav if(!*evp_key) { 4288ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 4298ed2b524SDag-Erling Smørgrav return 0; 4308ed2b524SDag-Erling Smørgrav } 43117d15b25SDag-Erling Smørgrav dsa = sldns_key_buf2dsa_raw(key, keylen); 4328ed2b524SDag-Erling Smørgrav if(!dsa) { 4338ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 43417d15b25SDag-Erling Smørgrav "sldns_key_buf2dsa_raw failed"); 4358ed2b524SDag-Erling Smørgrav return 0; 4368ed2b524SDag-Erling Smørgrav } 4378ed2b524SDag-Erling Smørgrav if(EVP_PKEY_assign_DSA(*evp_key, dsa) == 0) { 4388ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 4398ed2b524SDag-Erling Smørgrav "EVP_PKEY_assign_DSA failed"); 4408ed2b524SDag-Erling Smørgrav return 0; 4418ed2b524SDag-Erling Smørgrav } 442bc892140SDag-Erling Smørgrav #ifdef HAVE_EVP_DSS1 4438ed2b524SDag-Erling Smørgrav *digest_type = EVP_dss1(); 444bc892140SDag-Erling Smørgrav #else 445bc892140SDag-Erling Smørgrav *digest_type = EVP_sha1(); 446bc892140SDag-Erling Smørgrav #endif 4478ed2b524SDag-Erling Smørgrav 4488ed2b524SDag-Erling Smørgrav break; 44965b390aaSDag-Erling Smørgrav #endif /* USE_DSA && USE_SHA1 */ 45065b390aaSDag-Erling Smørgrav 45165b390aaSDag-Erling Smørgrav #if defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) 45265b390aaSDag-Erling Smørgrav #ifdef USE_SHA1 4538ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1: 4548ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 45565b390aaSDag-Erling Smørgrav #endif 4568ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) 4578ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256: 4588ed2b524SDag-Erling Smørgrav #endif 4598ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) 4608ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512: 4618ed2b524SDag-Erling Smørgrav #endif 4628ed2b524SDag-Erling Smørgrav *evp_key = EVP_PKEY_new(); 4638ed2b524SDag-Erling Smørgrav if(!*evp_key) { 4648ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 4658ed2b524SDag-Erling Smørgrav return 0; 4668ed2b524SDag-Erling Smørgrav } 46717d15b25SDag-Erling Smørgrav rsa = sldns_key_buf2rsa_raw(key, keylen); 4688ed2b524SDag-Erling Smørgrav if(!rsa) { 4698ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 47017d15b25SDag-Erling Smørgrav "sldns_key_buf2rsa_raw SHA failed"); 4718ed2b524SDag-Erling Smørgrav return 0; 4728ed2b524SDag-Erling Smørgrav } 4738ed2b524SDag-Erling Smørgrav if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) { 4748ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 4758ed2b524SDag-Erling Smørgrav "EVP_PKEY_assign_RSA SHA failed"); 4768ed2b524SDag-Erling Smørgrav return 0; 4778ed2b524SDag-Erling Smørgrav } 4788ed2b524SDag-Erling Smørgrav 4798ed2b524SDag-Erling Smørgrav /* select SHA version */ 4808ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) 4818ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA256) 4828ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha256(); 4838ed2b524SDag-Erling Smørgrav else 4848ed2b524SDag-Erling Smørgrav #endif 4858ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2) 4868ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA512) 4878ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha512(); 4888ed2b524SDag-Erling Smørgrav else 4898ed2b524SDag-Erling Smørgrav #endif 49065b390aaSDag-Erling Smørgrav #ifdef USE_SHA1 4918ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha1(); 49265b390aaSDag-Erling Smørgrav #else 49365b390aaSDag-Erling Smørgrav { verbose(VERB_QUERY, "no digest available"); return 0; } 49465b390aaSDag-Erling Smørgrav #endif 4958ed2b524SDag-Erling Smørgrav break; 49665b390aaSDag-Erling Smørgrav #endif /* defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) */ 49765b390aaSDag-Erling Smørgrav 4988ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5: 4998ed2b524SDag-Erling Smørgrav *evp_key = EVP_PKEY_new(); 5008ed2b524SDag-Erling Smørgrav if(!*evp_key) { 5018ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 5028ed2b524SDag-Erling Smørgrav return 0; 5038ed2b524SDag-Erling Smørgrav } 50417d15b25SDag-Erling Smørgrav rsa = sldns_key_buf2rsa_raw(key, keylen); 5058ed2b524SDag-Erling Smørgrav if(!rsa) { 5068ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 50717d15b25SDag-Erling Smørgrav "sldns_key_buf2rsa_raw MD5 failed"); 5088ed2b524SDag-Erling Smørgrav return 0; 5098ed2b524SDag-Erling Smørgrav } 5108ed2b524SDag-Erling Smørgrav if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) { 5118ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 5128ed2b524SDag-Erling Smørgrav "EVP_PKEY_assign_RSA MD5 failed"); 5138ed2b524SDag-Erling Smørgrav return 0; 5148ed2b524SDag-Erling Smørgrav } 5158ed2b524SDag-Erling Smørgrav *digest_type = EVP_md5(); 5168ed2b524SDag-Erling Smørgrav 5178ed2b524SDag-Erling Smørgrav break; 5188ed2b524SDag-Erling Smørgrav #ifdef USE_GOST 5198ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST: 52017d15b25SDag-Erling Smørgrav *evp_key = sldns_gost2pkey_raw(key, keylen); 5218ed2b524SDag-Erling Smørgrav if(!*evp_key) { 5228ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 52317d15b25SDag-Erling Smørgrav "sldns_gost2pkey_raw failed"); 5248ed2b524SDag-Erling Smørgrav return 0; 5258ed2b524SDag-Erling Smørgrav } 5268ed2b524SDag-Erling Smørgrav *digest_type = EVP_get_digestbyname("md_gost94"); 5278ed2b524SDag-Erling Smørgrav if(!*digest_type) { 5288ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 5298ed2b524SDag-Erling Smørgrav "EVP_getdigest md_gost94 failed"); 5308ed2b524SDag-Erling Smørgrav return 0; 5318ed2b524SDag-Erling Smørgrav } 5328ed2b524SDag-Erling Smørgrav break; 5338ed2b524SDag-Erling Smørgrav #endif 5348ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 5358ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 53617d15b25SDag-Erling Smørgrav *evp_key = sldns_ecdsa2pkey_raw(key, keylen, 5378ed2b524SDag-Erling Smørgrav LDNS_ECDSAP256SHA256); 5388ed2b524SDag-Erling Smørgrav if(!*evp_key) { 5398ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 54017d15b25SDag-Erling Smørgrav "sldns_ecdsa2pkey_raw failed"); 5418ed2b524SDag-Erling Smørgrav return 0; 5428ed2b524SDag-Erling Smørgrav } 5438ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA_EVP_WORKAROUND 544b5663de9SDag-Erling Smørgrav *digest_type = &ecdsa_evp_256_md; 5458ed2b524SDag-Erling Smørgrav #else 5468ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha256(); 5478ed2b524SDag-Erling Smørgrav #endif 5488ed2b524SDag-Erling Smørgrav break; 5498ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 55017d15b25SDag-Erling Smørgrav *evp_key = sldns_ecdsa2pkey_raw(key, keylen, 5518ed2b524SDag-Erling Smørgrav LDNS_ECDSAP384SHA384); 5528ed2b524SDag-Erling Smørgrav if(!*evp_key) { 5538ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 55417d15b25SDag-Erling Smørgrav "sldns_ecdsa2pkey_raw failed"); 5558ed2b524SDag-Erling Smørgrav return 0; 5568ed2b524SDag-Erling Smørgrav } 5578ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA_EVP_WORKAROUND 558b5663de9SDag-Erling Smørgrav *digest_type = &ecdsa_evp_384_md; 5598ed2b524SDag-Erling Smørgrav #else 5608ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha384(); 5618ed2b524SDag-Erling Smørgrav #endif 5628ed2b524SDag-Erling Smørgrav break; 5638ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */ 564c7f4d7adSDag-Erling Smørgrav #ifdef USE_ED25519 565c7f4d7adSDag-Erling Smørgrav case LDNS_ED25519: 566c7f4d7adSDag-Erling Smørgrav *evp_key = sldns_ed255192pkey_raw(key, keylen); 567c7f4d7adSDag-Erling Smørgrav if(!*evp_key) { 568c7f4d7adSDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 569c7f4d7adSDag-Erling Smørgrav "sldns_ed255192pkey_raw failed"); 570c7f4d7adSDag-Erling Smørgrav return 0; 571c7f4d7adSDag-Erling Smørgrav } 572c7f4d7adSDag-Erling Smørgrav *digest_type = NULL; 573c7f4d7adSDag-Erling Smørgrav break; 574c7f4d7adSDag-Erling Smørgrav #endif /* USE_ED25519 */ 575*0fb34990SDag-Erling Smørgrav #ifdef USE_ED448 576*0fb34990SDag-Erling Smørgrav case LDNS_ED448: 577*0fb34990SDag-Erling Smørgrav *evp_key = sldns_ed4482pkey_raw(key, keylen); 578*0fb34990SDag-Erling Smørgrav if(!*evp_key) { 579*0fb34990SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: " 580*0fb34990SDag-Erling Smørgrav "sldns_ed4482pkey_raw failed"); 581*0fb34990SDag-Erling Smørgrav return 0; 582*0fb34990SDag-Erling Smørgrav } 583*0fb34990SDag-Erling Smørgrav *digest_type = NULL; 584*0fb34990SDag-Erling Smørgrav break; 585*0fb34990SDag-Erling Smørgrav #endif /* USE_ED448 */ 5868ed2b524SDag-Erling Smørgrav default: 5878ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: unknown algorithm %d", 5888ed2b524SDag-Erling Smørgrav algo); 5898ed2b524SDag-Erling Smørgrav return 0; 5908ed2b524SDag-Erling Smørgrav } 5918ed2b524SDag-Erling Smørgrav return 1; 5928ed2b524SDag-Erling Smørgrav } 5938ed2b524SDag-Erling Smørgrav 5948ed2b524SDag-Erling Smørgrav /** 5958ed2b524SDag-Erling Smørgrav * Check a canonical sig+rrset and signature against a dnskey 5968ed2b524SDag-Erling Smørgrav * @param buf: buffer with data to verify, the first rrsig part and the 5978ed2b524SDag-Erling Smørgrav * canonicalized rrset. 5988ed2b524SDag-Erling Smørgrav * @param algo: DNSKEY algorithm. 5998ed2b524SDag-Erling Smørgrav * @param sigblock: signature rdata field from RRSIG 6008ed2b524SDag-Erling Smørgrav * @param sigblock_len: length of sigblock data. 6018ed2b524SDag-Erling Smørgrav * @param key: public key data from DNSKEY RR. 6028ed2b524SDag-Erling Smørgrav * @param keylen: length of keydata. 6038ed2b524SDag-Erling Smørgrav * @param reason: bogus reason in more detail. 6048ed2b524SDag-Erling Smørgrav * @return secure if verification succeeded, bogus on crypto failure, 6058ed2b524SDag-Erling Smørgrav * unchecked on format errors and alloc failures. 6068ed2b524SDag-Erling Smørgrav */ 6078ed2b524SDag-Erling Smørgrav enum sec_status 60817d15b25SDag-Erling Smørgrav verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, 6098ed2b524SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen, 6108ed2b524SDag-Erling Smørgrav char** reason) 6118ed2b524SDag-Erling Smørgrav { 6128ed2b524SDag-Erling Smørgrav const EVP_MD *digest_type; 613e2d15004SDag-Erling Smørgrav EVP_MD_CTX* ctx; 614e2d15004SDag-Erling Smørgrav int res, dofree = 0, docrypto_free = 0; 6158ed2b524SDag-Erling Smørgrav EVP_PKEY *evp_key = NULL; 6168ed2b524SDag-Erling Smørgrav 617bc892140SDag-Erling Smørgrav #ifndef USE_DSA 61865b390aaSDag-Erling Smørgrav if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1)) 61965b390aaSDag-Erling Smørgrav return sec_status_secure; 62065b390aaSDag-Erling Smørgrav #endif 62165b390aaSDag-Erling Smørgrav #ifndef USE_SHA1 62265b390aaSDag-Erling Smørgrav if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3)) 623bc892140SDag-Erling Smørgrav return sec_status_secure; 624bc892140SDag-Erling Smørgrav #endif 625bc892140SDag-Erling Smørgrav 6268ed2b524SDag-Erling Smørgrav if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) { 6278ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup key"); 6288ed2b524SDag-Erling Smørgrav *reason = "use of key for crypto failed"; 6298ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 6308ed2b524SDag-Erling Smørgrav return sec_status_bogus; 6318ed2b524SDag-Erling Smørgrav } 632e2d15004SDag-Erling Smørgrav #ifdef USE_DSA 6338ed2b524SDag-Erling Smørgrav /* if it is a DSA signature in bind format, convert to DER format */ 6348ed2b524SDag-Erling Smørgrav if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) && 6358ed2b524SDag-Erling Smørgrav sigblock_len == 1+2*SHA_DIGEST_LENGTH) { 6368ed2b524SDag-Erling Smørgrav if(!setup_dsa_sig(&sigblock, &sigblock_len)) { 6378ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup DSA sig"); 6388ed2b524SDag-Erling Smørgrav *reason = "use of key for DSA crypto failed"; 6398ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 6408ed2b524SDag-Erling Smørgrav return sec_status_bogus; 6418ed2b524SDag-Erling Smørgrav } 642e2d15004SDag-Erling Smørgrav docrypto_free = 1; 6438ed2b524SDag-Erling Smørgrav } 644e2d15004SDag-Erling Smørgrav #endif 645e2d15004SDag-Erling Smørgrav #if defined(USE_ECDSA) && defined(USE_DSA) 646e2d15004SDag-Erling Smørgrav else 647e2d15004SDag-Erling Smørgrav #endif 6488ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 649e2d15004SDag-Erling Smørgrav if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) { 6508ed2b524SDag-Erling Smørgrav /* EVP uses ASN prefix on sig, which is not in the wire data */ 6518ed2b524SDag-Erling Smørgrav if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) { 6528ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup ECDSA sig"); 6538ed2b524SDag-Erling Smørgrav *reason = "use of signature for ECDSA crypto failed"; 6548ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 6558ed2b524SDag-Erling Smørgrav return sec_status_bogus; 6568ed2b524SDag-Erling Smørgrav } 6578ed2b524SDag-Erling Smørgrav dofree = 1; 6588ed2b524SDag-Erling Smørgrav } 6598ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */ 6608ed2b524SDag-Erling Smørgrav 6618ed2b524SDag-Erling Smørgrav /* do the signature cryptography work */ 662e2d15004SDag-Erling Smørgrav #ifdef HAVE_EVP_MD_CTX_NEW 663e2d15004SDag-Erling Smørgrav ctx = EVP_MD_CTX_new(); 664e2d15004SDag-Erling Smørgrav #else 665e2d15004SDag-Erling Smørgrav ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx)); 666e2d15004SDag-Erling Smørgrav if(ctx) EVP_MD_CTX_init(ctx); 667e2d15004SDag-Erling Smørgrav #endif 668e2d15004SDag-Erling Smørgrav if(!ctx) { 669e2d15004SDag-Erling Smørgrav log_err("EVP_MD_CTX_new: malloc failure"); 6708ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 6718ed2b524SDag-Erling Smørgrav if(dofree) free(sigblock); 672b5663de9SDag-Erling Smørgrav else if(docrypto_free) OPENSSL_free(sigblock); 6738ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 6748ed2b524SDag-Erling Smørgrav } 675c7f4d7adSDag-Erling Smørgrav #ifndef HAVE_EVP_DIGESTVERIFY 676c7f4d7adSDag-Erling Smørgrav if(EVP_DigestInit(ctx, digest_type) == 0) { 677c7f4d7adSDag-Erling Smørgrav verbose(VERB_QUERY, "verify: EVP_DigestInit failed"); 678c7f4d7adSDag-Erling Smørgrav #ifdef HAVE_EVP_MD_CTX_NEW 679e2d15004SDag-Erling Smørgrav EVP_MD_CTX_destroy(ctx); 680c7f4d7adSDag-Erling Smørgrav #else 681c7f4d7adSDag-Erling Smørgrav EVP_MD_CTX_cleanup(ctx); 682c7f4d7adSDag-Erling Smørgrav free(ctx); 683c7f4d7adSDag-Erling Smørgrav #endif 684e2d15004SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 685e2d15004SDag-Erling Smørgrav if(dofree) free(sigblock); 686b5663de9SDag-Erling Smørgrav else if(docrypto_free) OPENSSL_free(sigblock); 687e2d15004SDag-Erling Smørgrav return sec_status_unchecked; 688e2d15004SDag-Erling Smørgrav } 689c7f4d7adSDag-Erling Smørgrav if(EVP_DigestUpdate(ctx, (unsigned char*)sldns_buffer_begin(buf), 69017d15b25SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf)) == 0) { 691c7f4d7adSDag-Erling Smørgrav verbose(VERB_QUERY, "verify: EVP_DigestUpdate failed"); 692c7f4d7adSDag-Erling Smørgrav #ifdef HAVE_EVP_MD_CTX_NEW 693e2d15004SDag-Erling Smørgrav EVP_MD_CTX_destroy(ctx); 694c7f4d7adSDag-Erling Smørgrav #else 695c7f4d7adSDag-Erling Smørgrav EVP_MD_CTX_cleanup(ctx); 696c7f4d7adSDag-Erling Smørgrav free(ctx); 697c7f4d7adSDag-Erling Smørgrav #endif 6988ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 6998ed2b524SDag-Erling Smørgrav if(dofree) free(sigblock); 700b5663de9SDag-Erling Smørgrav else if(docrypto_free) OPENSSL_free(sigblock); 7018ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 7028ed2b524SDag-Erling Smørgrav } 7038ed2b524SDag-Erling Smørgrav 704e2d15004SDag-Erling Smørgrav res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key); 705c7f4d7adSDag-Erling Smørgrav #else /* HAVE_EVP_DIGESTVERIFY */ 706c7f4d7adSDag-Erling Smørgrav if(EVP_DigestVerifyInit(ctx, NULL, digest_type, NULL, evp_key) == 0) { 707c7f4d7adSDag-Erling Smørgrav verbose(VERB_QUERY, "verify: EVP_DigestVerifyInit failed"); 708c7f4d7adSDag-Erling Smørgrav #ifdef HAVE_EVP_MD_CTX_NEW 709c7f4d7adSDag-Erling Smørgrav EVP_MD_CTX_destroy(ctx); 710c7f4d7adSDag-Erling Smørgrav #else 711c7f4d7adSDag-Erling Smørgrav EVP_MD_CTX_cleanup(ctx); 712c7f4d7adSDag-Erling Smørgrav free(ctx); 713c7f4d7adSDag-Erling Smørgrav #endif 714c7f4d7adSDag-Erling Smørgrav EVP_PKEY_free(evp_key); 715c7f4d7adSDag-Erling Smørgrav if(dofree) free(sigblock); 716c7f4d7adSDag-Erling Smørgrav else if(docrypto_free) OPENSSL_free(sigblock); 717c7f4d7adSDag-Erling Smørgrav return sec_status_unchecked; 718c7f4d7adSDag-Erling Smørgrav } 719c7f4d7adSDag-Erling Smørgrav res = EVP_DigestVerify(ctx, sigblock, sigblock_len, 720c7f4d7adSDag-Erling Smørgrav (unsigned char*)sldns_buffer_begin(buf), 721c7f4d7adSDag-Erling Smørgrav sldns_buffer_limit(buf)); 722c7f4d7adSDag-Erling Smørgrav #endif 723e2d15004SDag-Erling Smørgrav #ifdef HAVE_EVP_MD_CTX_NEW 724e2d15004SDag-Erling Smørgrav EVP_MD_CTX_destroy(ctx); 725e2d15004SDag-Erling Smørgrav #else 726e2d15004SDag-Erling Smørgrav EVP_MD_CTX_cleanup(ctx); 727e2d15004SDag-Erling Smørgrav free(ctx); 728e2d15004SDag-Erling Smørgrav #endif 7298ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key); 7308ed2b524SDag-Erling Smørgrav 731e2d15004SDag-Erling Smørgrav if(dofree) free(sigblock); 732b5663de9SDag-Erling Smørgrav else if(docrypto_free) OPENSSL_free(sigblock); 7338ed2b524SDag-Erling Smørgrav 7348ed2b524SDag-Erling Smørgrav if(res == 1) { 7358ed2b524SDag-Erling Smørgrav return sec_status_secure; 7368ed2b524SDag-Erling Smørgrav } else if(res == 0) { 7378ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: signature mismatch"); 7388ed2b524SDag-Erling Smørgrav *reason = "signature crypto failed"; 7398ed2b524SDag-Erling Smørgrav return sec_status_bogus; 7408ed2b524SDag-Erling Smørgrav } 7418ed2b524SDag-Erling Smørgrav 7428ed2b524SDag-Erling Smørgrav log_crypto_error("verify:", ERR_get_error()); 7438ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 7448ed2b524SDag-Erling Smørgrav } 7458ed2b524SDag-Erling Smørgrav 7468ed2b524SDag-Erling Smørgrav /**************************************************/ 7478ed2b524SDag-Erling Smørgrav #elif defined(HAVE_NSS) 7488ed2b524SDag-Erling Smørgrav /* libnss implementation */ 7498ed2b524SDag-Erling Smørgrav /* nss3 */ 7508ed2b524SDag-Erling Smørgrav #include "sechash.h" 7518ed2b524SDag-Erling Smørgrav #include "pk11pub.h" 7528ed2b524SDag-Erling Smørgrav #include "keyhi.h" 7538ed2b524SDag-Erling Smørgrav #include "secerr.h" 7548ed2b524SDag-Erling Smørgrav #include "cryptohi.h" 7558ed2b524SDag-Erling Smørgrav /* nspr4 */ 7568ed2b524SDag-Erling Smørgrav #include "prerror.h" 7578ed2b524SDag-Erling Smørgrav 75805ab2901SDag-Erling Smørgrav /* return size of digest if supported, or 0 otherwise */ 75905ab2901SDag-Erling Smørgrav size_t 76005ab2901SDag-Erling Smørgrav nsec3_hash_algo_size_supported(int id) 76105ab2901SDag-Erling Smørgrav { 76205ab2901SDag-Erling Smørgrav switch(id) { 76305ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1: 76405ab2901SDag-Erling Smørgrav return SHA1_LENGTH; 76505ab2901SDag-Erling Smørgrav default: 76605ab2901SDag-Erling Smørgrav return 0; 76705ab2901SDag-Erling Smørgrav } 76805ab2901SDag-Erling Smørgrav } 76905ab2901SDag-Erling Smørgrav 77005ab2901SDag-Erling Smørgrav /* perform nsec3 hash. return false on failure */ 77105ab2901SDag-Erling Smørgrav int 77205ab2901SDag-Erling Smørgrav secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, 77305ab2901SDag-Erling Smørgrav unsigned char* res) 77405ab2901SDag-Erling Smørgrav { 77505ab2901SDag-Erling Smørgrav switch(algo) { 77605ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1: 77705ab2901SDag-Erling Smørgrav (void)HASH_HashBuf(HASH_AlgSHA1, res, buf, (unsigned long)len); 77805ab2901SDag-Erling Smørgrav return 1; 77905ab2901SDag-Erling Smørgrav default: 78005ab2901SDag-Erling Smørgrav return 0; 78105ab2901SDag-Erling Smørgrav } 78205ab2901SDag-Erling Smørgrav } 78305ab2901SDag-Erling Smørgrav 784e2d15004SDag-Erling Smørgrav void 785e2d15004SDag-Erling Smørgrav secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res) 786e2d15004SDag-Erling Smørgrav { 787e2d15004SDag-Erling Smørgrav (void)HASH_HashBuf(HASH_AlgSHA256, res, buf, (unsigned long)len); 788e2d15004SDag-Erling Smørgrav } 789e2d15004SDag-Erling Smørgrav 7908ed2b524SDag-Erling Smørgrav size_t 7918ed2b524SDag-Erling Smørgrav ds_digest_size_supported(int algo) 7928ed2b524SDag-Erling Smørgrav { 7938ed2b524SDag-Erling Smørgrav /* uses libNSS */ 7948ed2b524SDag-Erling Smørgrav switch(algo) { 79565b390aaSDag-Erling Smørgrav #ifdef USE_SHA1 7968ed2b524SDag-Erling Smørgrav case LDNS_SHA1: 7978ed2b524SDag-Erling Smørgrav return SHA1_LENGTH; 79865b390aaSDag-Erling Smørgrav #endif 7998ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 8008ed2b524SDag-Erling Smørgrav case LDNS_SHA256: 8018ed2b524SDag-Erling Smørgrav return SHA256_LENGTH; 8028ed2b524SDag-Erling Smørgrav #endif 8038ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 8048ed2b524SDag-Erling Smørgrav case LDNS_SHA384: 8058ed2b524SDag-Erling Smørgrav return SHA384_LENGTH; 8068ed2b524SDag-Erling Smørgrav #endif 8078ed2b524SDag-Erling Smørgrav /* GOST not supported in NSS */ 8088ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST: 8098ed2b524SDag-Erling Smørgrav default: break; 8108ed2b524SDag-Erling Smørgrav } 8118ed2b524SDag-Erling Smørgrav return 0; 8128ed2b524SDag-Erling Smørgrav } 8138ed2b524SDag-Erling Smørgrav 8148ed2b524SDag-Erling Smørgrav int 8158ed2b524SDag-Erling Smørgrav secalgo_ds_digest(int algo, unsigned char* buf, size_t len, 8168ed2b524SDag-Erling Smørgrav unsigned char* res) 8178ed2b524SDag-Erling Smørgrav { 8188ed2b524SDag-Erling Smørgrav /* uses libNSS */ 8198ed2b524SDag-Erling Smørgrav switch(algo) { 82065b390aaSDag-Erling Smørgrav #ifdef USE_SHA1 8218ed2b524SDag-Erling Smørgrav case LDNS_SHA1: 8228ed2b524SDag-Erling Smørgrav return HASH_HashBuf(HASH_AlgSHA1, res, buf, len) 8238ed2b524SDag-Erling Smørgrav == SECSuccess; 82465b390aaSDag-Erling Smørgrav #endif 8258ed2b524SDag-Erling Smørgrav #if defined(USE_SHA2) 8268ed2b524SDag-Erling Smørgrav case LDNS_SHA256: 8278ed2b524SDag-Erling Smørgrav return HASH_HashBuf(HASH_AlgSHA256, res, buf, len) 8288ed2b524SDag-Erling Smørgrav == SECSuccess; 8298ed2b524SDag-Erling Smørgrav #endif 8308ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 8318ed2b524SDag-Erling Smørgrav case LDNS_SHA384: 8328ed2b524SDag-Erling Smørgrav return HASH_HashBuf(HASH_AlgSHA384, res, buf, len) 8338ed2b524SDag-Erling Smørgrav == SECSuccess; 8348ed2b524SDag-Erling Smørgrav #endif 8358ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST: 8368ed2b524SDag-Erling Smørgrav default: 8378ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "unknown DS digest algorithm %d", 8388ed2b524SDag-Erling Smørgrav algo); 8398ed2b524SDag-Erling Smørgrav break; 8408ed2b524SDag-Erling Smørgrav } 8418ed2b524SDag-Erling Smørgrav return 0; 8428ed2b524SDag-Erling Smørgrav } 8438ed2b524SDag-Erling Smørgrav 8448ed2b524SDag-Erling Smørgrav int 8458ed2b524SDag-Erling Smørgrav dnskey_algo_id_is_supported(int id) 8468ed2b524SDag-Erling Smørgrav { 8478ed2b524SDag-Erling Smørgrav /* uses libNSS */ 8488ed2b524SDag-Erling Smørgrav switch(id) { 8498ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5: 8508ed2b524SDag-Erling Smørgrav /* RFC 6725 deprecates RSAMD5 */ 8518ed2b524SDag-Erling Smørgrav return 0; 85265b390aaSDag-Erling Smørgrav #if defined(USE_SHA1) || defined(USE_SHA2) 85365b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1) 8548ed2b524SDag-Erling Smørgrav case LDNS_DSA: 8558ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 856e2d15004SDag-Erling Smørgrav #endif 85765b390aaSDag-Erling Smørgrav #ifdef USE_SHA1 8588ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1: 8598ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 86065b390aaSDag-Erling Smørgrav #endif 8618ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 8628ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256: 8638ed2b524SDag-Erling Smørgrav #endif 8648ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 8658ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512: 8668ed2b524SDag-Erling Smørgrav #endif 8678ed2b524SDag-Erling Smørgrav return 1; 86865b390aaSDag-Erling Smørgrav #endif /* SHA1 or SHA2 */ 86965b390aaSDag-Erling Smørgrav 8708ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 8718ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 8728ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 8738ed2b524SDag-Erling Smørgrav return PK11_TokenExists(CKM_ECDSA); 8748ed2b524SDag-Erling Smørgrav #endif 8758ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST: 8768ed2b524SDag-Erling Smørgrav default: 8778ed2b524SDag-Erling Smørgrav return 0; 8788ed2b524SDag-Erling Smørgrav } 8798ed2b524SDag-Erling Smørgrav } 8808ed2b524SDag-Erling Smørgrav 8818ed2b524SDag-Erling Smørgrav /* return a new public key for NSS */ 8828ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_key_create(KeyType ktype) 8838ed2b524SDag-Erling Smørgrav { 8848ed2b524SDag-Erling Smørgrav SECKEYPublicKey* key; 8858ed2b524SDag-Erling Smørgrav PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 8868ed2b524SDag-Erling Smørgrav if(!arena) { 8878ed2b524SDag-Erling Smørgrav log_err("out of memory, PORT_NewArena failed"); 8888ed2b524SDag-Erling Smørgrav return NULL; 8898ed2b524SDag-Erling Smørgrav } 8908ed2b524SDag-Erling Smørgrav key = PORT_ArenaZNew(arena, SECKEYPublicKey); 8918ed2b524SDag-Erling Smørgrav if(!key) { 8928ed2b524SDag-Erling Smørgrav log_err("out of memory, PORT_ArenaZNew failed"); 8938ed2b524SDag-Erling Smørgrav PORT_FreeArena(arena, PR_FALSE); 8948ed2b524SDag-Erling Smørgrav return NULL; 8958ed2b524SDag-Erling Smørgrav } 8968ed2b524SDag-Erling Smørgrav key->arena = arena; 8978ed2b524SDag-Erling Smørgrav key->keyType = ktype; 8988ed2b524SDag-Erling Smørgrav key->pkcs11Slot = NULL; 8998ed2b524SDag-Erling Smørgrav key->pkcs11ID = CK_INVALID_HANDLE; 9008ed2b524SDag-Erling Smørgrav return key; 9018ed2b524SDag-Erling Smørgrav } 9028ed2b524SDag-Erling Smørgrav 9038ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_buf2ecdsa(unsigned char* key, size_t len, int algo) 9048ed2b524SDag-Erling Smørgrav { 9058ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pk; 9068ed2b524SDag-Erling Smørgrav SECItem pub = {siBuffer, NULL, 0}; 9078ed2b524SDag-Erling Smørgrav SECItem params = {siBuffer, NULL, 0}; 90817d15b25SDag-Erling Smørgrav static unsigned char param256[] = { 9098ed2b524SDag-Erling Smørgrav /* OBJECTIDENTIFIER 1.2.840.10045.3.1.7 (P-256) 9108ed2b524SDag-Erling Smørgrav * {iso(1) member-body(2) us(840) ansi-x962(10045) curves(3) prime(1) prime256v1(7)} */ 9118ed2b524SDag-Erling Smørgrav 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 9128ed2b524SDag-Erling Smørgrav }; 91317d15b25SDag-Erling Smørgrav static unsigned char param384[] = { 9148ed2b524SDag-Erling Smørgrav /* OBJECTIDENTIFIER 1.3.132.0.34 (P-384) 9158ed2b524SDag-Erling Smørgrav * {iso(1) identified-organization(3) certicom(132) curve(0) ansip384r1(34)} */ 9168ed2b524SDag-Erling Smørgrav 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22 9178ed2b524SDag-Erling Smørgrav }; 9188ed2b524SDag-Erling Smørgrav unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ 9198ed2b524SDag-Erling Smørgrav 9208ed2b524SDag-Erling Smørgrav /* check length, which uncompressed must be 2 bignums */ 9218ed2b524SDag-Erling Smørgrav if(algo == LDNS_ECDSAP256SHA256) { 9228ed2b524SDag-Erling Smørgrav if(len != 2*256/8) return NULL; 9238ed2b524SDag-Erling Smørgrav /* ECCurve_X9_62_PRIME_256V1 */ 9248ed2b524SDag-Erling Smørgrav } else if(algo == LDNS_ECDSAP384SHA384) { 9258ed2b524SDag-Erling Smørgrav if(len != 2*384/8) return NULL; 9268ed2b524SDag-Erling Smørgrav /* ECCurve_X9_62_PRIME_384R1 */ 9278ed2b524SDag-Erling Smørgrav } else return NULL; 9288ed2b524SDag-Erling Smørgrav 9298ed2b524SDag-Erling Smørgrav buf[0] = 0x04; /* POINT_FORM_UNCOMPRESSED */ 9308ed2b524SDag-Erling Smørgrav memmove(buf+1, key, len); 9318ed2b524SDag-Erling Smørgrav pub.data = buf; 9328ed2b524SDag-Erling Smørgrav pub.len = len+1; 9338ed2b524SDag-Erling Smørgrav if(algo == LDNS_ECDSAP256SHA256) { 9348ed2b524SDag-Erling Smørgrav params.data = param256; 9358ed2b524SDag-Erling Smørgrav params.len = sizeof(param256); 9368ed2b524SDag-Erling Smørgrav } else { 9378ed2b524SDag-Erling Smørgrav params.data = param384; 9388ed2b524SDag-Erling Smørgrav params.len = sizeof(param384); 9398ed2b524SDag-Erling Smørgrav } 9408ed2b524SDag-Erling Smørgrav 9418ed2b524SDag-Erling Smørgrav pk = nss_key_create(ecKey); 9428ed2b524SDag-Erling Smørgrav if(!pk) 9438ed2b524SDag-Erling Smørgrav return NULL; 9448ed2b524SDag-Erling Smørgrav pk->u.ec.size = (len/2)*8; 9458ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.ec.publicValue, &pub)) { 9468ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 9478ed2b524SDag-Erling Smørgrav return NULL; 9488ed2b524SDag-Erling Smørgrav } 9498ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.ec.DEREncodedParams, ¶ms)) { 9508ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 9518ed2b524SDag-Erling Smørgrav return NULL; 9528ed2b524SDag-Erling Smørgrav } 9538ed2b524SDag-Erling Smørgrav 9548ed2b524SDag-Erling Smørgrav return pk; 9558ed2b524SDag-Erling Smørgrav } 9568ed2b524SDag-Erling Smørgrav 9578ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_buf2dsa(unsigned char* key, size_t len) 9588ed2b524SDag-Erling Smørgrav { 9598ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pk; 9608ed2b524SDag-Erling Smørgrav uint8_t T; 9618ed2b524SDag-Erling Smørgrav uint16_t length; 9628ed2b524SDag-Erling Smørgrav uint16_t offset; 9638ed2b524SDag-Erling Smørgrav SECItem Q = {siBuffer, NULL, 0}; 9648ed2b524SDag-Erling Smørgrav SECItem P = {siBuffer, NULL, 0}; 9658ed2b524SDag-Erling Smørgrav SECItem G = {siBuffer, NULL, 0}; 9668ed2b524SDag-Erling Smørgrav SECItem Y = {siBuffer, NULL, 0}; 9678ed2b524SDag-Erling Smørgrav 9688ed2b524SDag-Erling Smørgrav if(len == 0) 9698ed2b524SDag-Erling Smørgrav return NULL; 9708ed2b524SDag-Erling Smørgrav T = (uint8_t)key[0]; 9718ed2b524SDag-Erling Smørgrav length = (64 + T * 8); 9728ed2b524SDag-Erling Smørgrav offset = 1; 9738ed2b524SDag-Erling Smørgrav 9748ed2b524SDag-Erling Smørgrav if (T > 8) { 9758ed2b524SDag-Erling Smørgrav return NULL; 9768ed2b524SDag-Erling Smørgrav } 9778ed2b524SDag-Erling Smørgrav if(len < (size_t)1 + SHA1_LENGTH + 3*length) 9788ed2b524SDag-Erling Smørgrav return NULL; 9798ed2b524SDag-Erling Smørgrav 9808ed2b524SDag-Erling Smørgrav Q.data = key+offset; 9818ed2b524SDag-Erling Smørgrav Q.len = SHA1_LENGTH; 9828ed2b524SDag-Erling Smørgrav offset += SHA1_LENGTH; 9838ed2b524SDag-Erling Smørgrav 9848ed2b524SDag-Erling Smørgrav P.data = key+offset; 9858ed2b524SDag-Erling Smørgrav P.len = length; 9868ed2b524SDag-Erling Smørgrav offset += length; 9878ed2b524SDag-Erling Smørgrav 9888ed2b524SDag-Erling Smørgrav G.data = key+offset; 9898ed2b524SDag-Erling Smørgrav G.len = length; 9908ed2b524SDag-Erling Smørgrav offset += length; 9918ed2b524SDag-Erling Smørgrav 9928ed2b524SDag-Erling Smørgrav Y.data = key+offset; 9938ed2b524SDag-Erling Smørgrav Y.len = length; 9948ed2b524SDag-Erling Smørgrav offset += length; 9958ed2b524SDag-Erling Smørgrav 9968ed2b524SDag-Erling Smørgrav pk = nss_key_create(dsaKey); 9978ed2b524SDag-Erling Smørgrav if(!pk) 9988ed2b524SDag-Erling Smørgrav return NULL; 9998ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.prime, &P)) { 10008ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 10018ed2b524SDag-Erling Smørgrav return NULL; 10028ed2b524SDag-Erling Smørgrav } 10038ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.subPrime, &Q)) { 10048ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 10058ed2b524SDag-Erling Smørgrav return NULL; 10068ed2b524SDag-Erling Smørgrav } 10078ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.base, &G)) { 10088ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 10098ed2b524SDag-Erling Smørgrav return NULL; 10108ed2b524SDag-Erling Smørgrav } 10118ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.publicValue, &Y)) { 10128ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 10138ed2b524SDag-Erling Smørgrav return NULL; 10148ed2b524SDag-Erling Smørgrav } 10158ed2b524SDag-Erling Smørgrav return pk; 10168ed2b524SDag-Erling Smørgrav } 10178ed2b524SDag-Erling Smørgrav 10188ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_buf2rsa(unsigned char* key, size_t len) 10198ed2b524SDag-Erling Smørgrav { 10208ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pk; 10218ed2b524SDag-Erling Smørgrav uint16_t exp; 10228ed2b524SDag-Erling Smørgrav uint16_t offset; 10238ed2b524SDag-Erling Smørgrav uint16_t int16; 10248ed2b524SDag-Erling Smørgrav SECItem modulus = {siBuffer, NULL, 0}; 10258ed2b524SDag-Erling Smørgrav SECItem exponent = {siBuffer, NULL, 0}; 10268ed2b524SDag-Erling Smørgrav if(len == 0) 10278ed2b524SDag-Erling Smørgrav return NULL; 10288ed2b524SDag-Erling Smørgrav if(key[0] == 0) { 10298ed2b524SDag-Erling Smørgrav if(len < 3) 10308ed2b524SDag-Erling Smørgrav return NULL; 10318ed2b524SDag-Erling Smørgrav /* the exponent is too large so it's places further */ 10328ed2b524SDag-Erling Smørgrav memmove(&int16, key+1, 2); 10338ed2b524SDag-Erling Smørgrav exp = ntohs(int16); 10348ed2b524SDag-Erling Smørgrav offset = 3; 10358ed2b524SDag-Erling Smørgrav } else { 10368ed2b524SDag-Erling Smørgrav exp = key[0]; 10378ed2b524SDag-Erling Smørgrav offset = 1; 10388ed2b524SDag-Erling Smørgrav } 10398ed2b524SDag-Erling Smørgrav 10408ed2b524SDag-Erling Smørgrav /* key length at least one */ 10418ed2b524SDag-Erling Smørgrav if(len < (size_t)offset + exp + 1) 10428ed2b524SDag-Erling Smørgrav return NULL; 10438ed2b524SDag-Erling Smørgrav 10448ed2b524SDag-Erling Smørgrav exponent.data = key+offset; 10458ed2b524SDag-Erling Smørgrav exponent.len = exp; 10468ed2b524SDag-Erling Smørgrav offset += exp; 10478ed2b524SDag-Erling Smørgrav modulus.data = key+offset; 10488ed2b524SDag-Erling Smørgrav modulus.len = (len - offset); 10498ed2b524SDag-Erling Smørgrav 10508ed2b524SDag-Erling Smørgrav pk = nss_key_create(rsaKey); 10518ed2b524SDag-Erling Smørgrav if(!pk) 10528ed2b524SDag-Erling Smørgrav return NULL; 10538ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.modulus, &modulus)) { 10548ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 10558ed2b524SDag-Erling Smørgrav return NULL; 10568ed2b524SDag-Erling Smørgrav } 10578ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.publicExponent, &exponent)) { 10588ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk); 10598ed2b524SDag-Erling Smørgrav return NULL; 10608ed2b524SDag-Erling Smørgrav } 10618ed2b524SDag-Erling Smørgrav return pk; 10628ed2b524SDag-Erling Smørgrav } 10638ed2b524SDag-Erling Smørgrav 10648ed2b524SDag-Erling Smørgrav /** 10658ed2b524SDag-Erling Smørgrav * Setup key and digest for verification. Adjust sig if necessary. 10668ed2b524SDag-Erling Smørgrav * 10678ed2b524SDag-Erling Smørgrav * @param algo: key algorithm 10688ed2b524SDag-Erling Smørgrav * @param evp_key: EVP PKEY public key to create. 10698ed2b524SDag-Erling Smørgrav * @param digest_type: digest type to use 10708ed2b524SDag-Erling Smørgrav * @param key: key to setup for. 10718ed2b524SDag-Erling Smørgrav * @param keylen: length of key. 10728ed2b524SDag-Erling Smørgrav * @param prefix: if returned, the ASN prefix for the hashblob. 10738ed2b524SDag-Erling Smørgrav * @param prefixlen: length of the prefix. 10748ed2b524SDag-Erling Smørgrav * @return false on failure. 10758ed2b524SDag-Erling Smørgrav */ 10768ed2b524SDag-Erling Smørgrav static int 10778ed2b524SDag-Erling Smørgrav nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype, 10788ed2b524SDag-Erling Smørgrav unsigned char* key, size_t keylen, unsigned char** prefix, 10798ed2b524SDag-Erling Smørgrav size_t* prefixlen) 10808ed2b524SDag-Erling Smørgrav { 10818ed2b524SDag-Erling Smørgrav /* uses libNSS */ 10828ed2b524SDag-Erling Smørgrav 10838ed2b524SDag-Erling Smørgrav /* hash prefix for md5, RFC2537 */ 108417d15b25SDag-Erling Smørgrav static unsigned char p_md5[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 10858ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}; 10868ed2b524SDag-Erling Smørgrav /* hash prefix to prepend to hash output, from RFC3110 */ 108717d15b25SDag-Erling Smørgrav static unsigned char p_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 10888ed2b524SDag-Erling Smørgrav 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14}; 10898ed2b524SDag-Erling Smørgrav /* from RFC5702 */ 109017d15b25SDag-Erling Smørgrav static unsigned char p_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 10918ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; 109217d15b25SDag-Erling Smørgrav static unsigned char p_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 10938ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}; 10948ed2b524SDag-Erling Smørgrav /* from RFC6234 */ 10958ed2b524SDag-Erling Smørgrav /* for future RSASHA384 .. 109617d15b25SDag-Erling Smørgrav static unsigned char p_sha384[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 10978ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}; 10988ed2b524SDag-Erling Smørgrav */ 10998ed2b524SDag-Erling Smørgrav 11008ed2b524SDag-Erling Smørgrav switch(algo) { 110165b390aaSDag-Erling Smørgrav 110265b390aaSDag-Erling Smørgrav #if defined(USE_SHA1) || defined(USE_SHA2) 110365b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1) 11048ed2b524SDag-Erling Smørgrav case LDNS_DSA: 11058ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 11068ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2dsa(key, keylen); 11078ed2b524SDag-Erling Smørgrav if(!*pubkey) { 11088ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 11098ed2b524SDag-Erling Smørgrav return 0; 11108ed2b524SDag-Erling Smørgrav } 11118ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA1; 11128ed2b524SDag-Erling Smørgrav /* no prefix for DSA verification */ 11138ed2b524SDag-Erling Smørgrav break; 1114e2d15004SDag-Erling Smørgrav #endif 111565b390aaSDag-Erling Smørgrav #ifdef USE_SHA1 11168ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1: 11178ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 111865b390aaSDag-Erling Smørgrav #endif 11198ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 11208ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256: 11218ed2b524SDag-Erling Smørgrav #endif 11228ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 11238ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512: 11248ed2b524SDag-Erling Smørgrav #endif 11258ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2rsa(key, keylen); 11268ed2b524SDag-Erling Smørgrav if(!*pubkey) { 11278ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 11288ed2b524SDag-Erling Smørgrav return 0; 11298ed2b524SDag-Erling Smørgrav } 11308ed2b524SDag-Erling Smørgrav /* select SHA version */ 11318ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 11328ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA256) { 11338ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA256; 11348ed2b524SDag-Erling Smørgrav *prefix = p_sha256; 11358ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_sha256); 11368ed2b524SDag-Erling Smørgrav } else 11378ed2b524SDag-Erling Smørgrav #endif 11388ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2 11398ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA512) { 11408ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA512; 11418ed2b524SDag-Erling Smørgrav *prefix = p_sha512; 11428ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_sha512); 11438ed2b524SDag-Erling Smørgrav } else 11448ed2b524SDag-Erling Smørgrav #endif 114565b390aaSDag-Erling Smørgrav #ifdef USE_SHA1 11468ed2b524SDag-Erling Smørgrav { 11478ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA1; 11488ed2b524SDag-Erling Smørgrav *prefix = p_sha1; 11498ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_sha1); 11508ed2b524SDag-Erling Smørgrav } 115165b390aaSDag-Erling Smørgrav #else 115265b390aaSDag-Erling Smørgrav { 115365b390aaSDag-Erling Smørgrav verbose(VERB_QUERY, "verify: no digest algo"); 115465b390aaSDag-Erling Smørgrav return 0; 115565b390aaSDag-Erling Smørgrav } 115665b390aaSDag-Erling Smørgrav #endif 11578ed2b524SDag-Erling Smørgrav 11588ed2b524SDag-Erling Smørgrav break; 115965b390aaSDag-Erling Smørgrav #endif /* SHA1 or SHA2 */ 116065b390aaSDag-Erling Smørgrav 11618ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5: 11628ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2rsa(key, keylen); 11638ed2b524SDag-Erling Smørgrav if(!*pubkey) { 11648ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 11658ed2b524SDag-Erling Smørgrav return 0; 11668ed2b524SDag-Erling Smørgrav } 11678ed2b524SDag-Erling Smørgrav *htype = HASH_AlgMD5; 11688ed2b524SDag-Erling Smørgrav *prefix = p_md5; 11698ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_md5); 11708ed2b524SDag-Erling Smørgrav 11718ed2b524SDag-Erling Smørgrav break; 11728ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA 11738ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 11748ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2ecdsa(key, keylen, 11758ed2b524SDag-Erling Smørgrav LDNS_ECDSAP256SHA256); 11768ed2b524SDag-Erling Smørgrav if(!*pubkey) { 11778ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 11788ed2b524SDag-Erling Smørgrav return 0; 11798ed2b524SDag-Erling Smørgrav } 11808ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA256; 11818ed2b524SDag-Erling Smørgrav /* no prefix for DSA verification */ 11828ed2b524SDag-Erling Smørgrav break; 11838ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 11848ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2ecdsa(key, keylen, 11858ed2b524SDag-Erling Smørgrav LDNS_ECDSAP384SHA384); 11868ed2b524SDag-Erling Smørgrav if(!*pubkey) { 11878ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto"); 11888ed2b524SDag-Erling Smørgrav return 0; 11898ed2b524SDag-Erling Smørgrav } 11908ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA384; 11918ed2b524SDag-Erling Smørgrav /* no prefix for DSA verification */ 11928ed2b524SDag-Erling Smørgrav break; 11938ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */ 11948ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST: 11958ed2b524SDag-Erling Smørgrav default: 11968ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: unknown algorithm %d", 11978ed2b524SDag-Erling Smørgrav algo); 11988ed2b524SDag-Erling Smørgrav return 0; 11998ed2b524SDag-Erling Smørgrav } 12008ed2b524SDag-Erling Smørgrav return 1; 12018ed2b524SDag-Erling Smørgrav } 12028ed2b524SDag-Erling Smørgrav 12038ed2b524SDag-Erling Smørgrav /** 12048ed2b524SDag-Erling Smørgrav * Check a canonical sig+rrset and signature against a dnskey 12058ed2b524SDag-Erling Smørgrav * @param buf: buffer with data to verify, the first rrsig part and the 12068ed2b524SDag-Erling Smørgrav * canonicalized rrset. 12078ed2b524SDag-Erling Smørgrav * @param algo: DNSKEY algorithm. 12088ed2b524SDag-Erling Smørgrav * @param sigblock: signature rdata field from RRSIG 12098ed2b524SDag-Erling Smørgrav * @param sigblock_len: length of sigblock data. 12108ed2b524SDag-Erling Smørgrav * @param key: public key data from DNSKEY RR. 12118ed2b524SDag-Erling Smørgrav * @param keylen: length of keydata. 12128ed2b524SDag-Erling Smørgrav * @param reason: bogus reason in more detail. 12138ed2b524SDag-Erling Smørgrav * @return secure if verification succeeded, bogus on crypto failure, 12148ed2b524SDag-Erling Smørgrav * unchecked on format errors and alloc failures. 12158ed2b524SDag-Erling Smørgrav */ 12168ed2b524SDag-Erling Smørgrav enum sec_status 121717d15b25SDag-Erling Smørgrav verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, 12188ed2b524SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen, 12198ed2b524SDag-Erling Smørgrav char** reason) 12208ed2b524SDag-Erling Smørgrav { 12218ed2b524SDag-Erling Smørgrav /* uses libNSS */ 12228ed2b524SDag-Erling Smørgrav /* large enough for the different hashes */ 12238ed2b524SDag-Erling Smørgrav unsigned char hash[HASH_LENGTH_MAX]; 12248ed2b524SDag-Erling Smørgrav unsigned char hash2[HASH_LENGTH_MAX*2]; 12258ed2b524SDag-Erling Smørgrav HASH_HashType htype = 0; 12268ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pubkey = NULL; 12278ed2b524SDag-Erling Smørgrav SECItem secsig = {siBuffer, sigblock, sigblock_len}; 12288ed2b524SDag-Erling Smørgrav SECItem sechash = {siBuffer, hash, 0}; 12298ed2b524SDag-Erling Smørgrav SECStatus res; 12308ed2b524SDag-Erling Smørgrav unsigned char* prefix = NULL; /* prefix for hash, RFC3110, RFC5702 */ 12318ed2b524SDag-Erling Smørgrav size_t prefixlen = 0; 12328ed2b524SDag-Erling Smørgrav int err; 12338ed2b524SDag-Erling Smørgrav 12348ed2b524SDag-Erling Smørgrav if(!nss_setup_key_digest(algo, &pubkey, &htype, key, keylen, 12358ed2b524SDag-Erling Smørgrav &prefix, &prefixlen)) { 12368ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup key"); 12378ed2b524SDag-Erling Smørgrav *reason = "use of key for crypto failed"; 12388ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 12398ed2b524SDag-Erling Smørgrav return sec_status_bogus; 12408ed2b524SDag-Erling Smørgrav } 12418ed2b524SDag-Erling Smørgrav 124265b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1) 12438ed2b524SDag-Erling Smørgrav /* need to convert DSA, ECDSA signatures? */ 12448ed2b524SDag-Erling Smørgrav if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) { 12458ed2b524SDag-Erling Smørgrav if(sigblock_len == 1+2*SHA1_LENGTH) { 12468ed2b524SDag-Erling Smørgrav secsig.data ++; 12478ed2b524SDag-Erling Smørgrav secsig.len --; 12488ed2b524SDag-Erling Smørgrav } else { 12498ed2b524SDag-Erling Smørgrav SECItem* p = DSAU_DecodeDerSig(&secsig); 12508ed2b524SDag-Erling Smørgrav if(!p) { 12518ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed DER decode"); 12528ed2b524SDag-Erling Smørgrav *reason = "signature DER decode failed"; 12538ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 12548ed2b524SDag-Erling Smørgrav return sec_status_bogus; 12558ed2b524SDag-Erling Smørgrav } 12568ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pubkey->arena, &secsig, p)) { 12578ed2b524SDag-Erling Smørgrav log_err("alloc failure in DER decode"); 12588ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 12598ed2b524SDag-Erling Smørgrav SECITEM_FreeItem(p, PR_TRUE); 12608ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 12618ed2b524SDag-Erling Smørgrav } 12628ed2b524SDag-Erling Smørgrav SECITEM_FreeItem(p, PR_TRUE); 12638ed2b524SDag-Erling Smørgrav } 12648ed2b524SDag-Erling Smørgrav } 1265e2d15004SDag-Erling Smørgrav #endif /* USE_DSA */ 12668ed2b524SDag-Erling Smørgrav 12678ed2b524SDag-Erling Smørgrav /* do the signature cryptography work */ 12688ed2b524SDag-Erling Smørgrav /* hash the data */ 12698ed2b524SDag-Erling Smørgrav sechash.len = HASH_ResultLen(htype); 12708ed2b524SDag-Erling Smørgrav if(sechash.len > sizeof(hash)) { 12718ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: hash too large for buffer"); 12728ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 12738ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 12748ed2b524SDag-Erling Smørgrav } 127517d15b25SDag-Erling Smørgrav if(HASH_HashBuf(htype, hash, (unsigned char*)sldns_buffer_begin(buf), 127617d15b25SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf)) != SECSuccess) { 12778ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: HASH_HashBuf failed"); 12788ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 12798ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 12808ed2b524SDag-Erling Smørgrav } 12818ed2b524SDag-Erling Smørgrav if(prefix) { 12828ed2b524SDag-Erling Smørgrav int hashlen = sechash.len; 12838ed2b524SDag-Erling Smørgrav if(prefixlen+hashlen > sizeof(hash2)) { 12848ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: hashprefix too large"); 12858ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 12868ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 12878ed2b524SDag-Erling Smørgrav } 12888ed2b524SDag-Erling Smørgrav sechash.data = hash2; 12898ed2b524SDag-Erling Smørgrav sechash.len = prefixlen+hashlen; 12908ed2b524SDag-Erling Smørgrav memcpy(sechash.data, prefix, prefixlen); 12918ed2b524SDag-Erling Smørgrav memmove(sechash.data+prefixlen, hash, hashlen); 12928ed2b524SDag-Erling Smørgrav } 12938ed2b524SDag-Erling Smørgrav 12948ed2b524SDag-Erling Smørgrav /* verify the signature */ 12958ed2b524SDag-Erling Smørgrav res = PK11_Verify(pubkey, &secsig, &sechash, NULL /*wincx*/); 12968ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey); 12978ed2b524SDag-Erling Smørgrav 12988ed2b524SDag-Erling Smørgrav if(res == SECSuccess) { 12998ed2b524SDag-Erling Smørgrav return sec_status_secure; 13008ed2b524SDag-Erling Smørgrav } 13018ed2b524SDag-Erling Smørgrav err = PORT_GetError(); 13028ed2b524SDag-Erling Smørgrav if(err != SEC_ERROR_BAD_SIGNATURE) { 13038ed2b524SDag-Erling Smørgrav /* failed to verify */ 13048ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: PK11_Verify failed: %s", 13058ed2b524SDag-Erling Smørgrav PORT_ErrorToString(err)); 13068ed2b524SDag-Erling Smørgrav /* if it is not supported, like ECC is removed, we get, 13078ed2b524SDag-Erling Smørgrav * SEC_ERROR_NO_MODULE */ 13088ed2b524SDag-Erling Smørgrav if(err == SEC_ERROR_NO_MODULE) 13098ed2b524SDag-Erling Smørgrav return sec_status_unchecked; 13108ed2b524SDag-Erling Smørgrav /* but other errors are commonly returned 13118ed2b524SDag-Erling Smørgrav * for a bad signature from NSS. Thus we return bogus, 13128ed2b524SDag-Erling Smørgrav * not unchecked */ 13138ed2b524SDag-Erling Smørgrav *reason = "signature crypto failed"; 13148ed2b524SDag-Erling Smørgrav return sec_status_bogus; 13158ed2b524SDag-Erling Smørgrav } 13168ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: signature mismatch: %s", 13178ed2b524SDag-Erling Smørgrav PORT_ErrorToString(err)); 13188ed2b524SDag-Erling Smørgrav *reason = "signature crypto failed"; 13198ed2b524SDag-Erling Smørgrav return sec_status_bogus; 13208ed2b524SDag-Erling Smørgrav } 13218ed2b524SDag-Erling Smørgrav 132205ab2901SDag-Erling Smørgrav #elif defined(HAVE_NETTLE) 13238ed2b524SDag-Erling Smørgrav 132405ab2901SDag-Erling Smørgrav #include "sha.h" 132505ab2901SDag-Erling Smørgrav #include "bignum.h" 132605ab2901SDag-Erling Smørgrav #include "macros.h" 132705ab2901SDag-Erling Smørgrav #include "rsa.h" 132805ab2901SDag-Erling Smørgrav #include "dsa.h" 1329b5663de9SDag-Erling Smørgrav #ifdef HAVE_NETTLE_DSA_COMPAT_H 1330b5663de9SDag-Erling Smørgrav #include "dsa-compat.h" 1331b5663de9SDag-Erling Smørgrav #endif 133205ab2901SDag-Erling Smørgrav #include "asn1.h" 133305ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA 133405ab2901SDag-Erling Smørgrav #include "ecdsa.h" 133505ab2901SDag-Erling Smørgrav #include "ecc-curve.h" 133605ab2901SDag-Erling Smørgrav #endif 1337971980c3SDag-Erling Smørgrav #ifdef HAVE_NETTLE_EDDSA_H 1338971980c3SDag-Erling Smørgrav #include "eddsa.h" 1339971980c3SDag-Erling Smørgrav #endif 134005ab2901SDag-Erling Smørgrav 134105ab2901SDag-Erling Smørgrav static int 134205ab2901SDag-Erling Smørgrav _digest_nettle(int algo, uint8_t* buf, size_t len, 134305ab2901SDag-Erling Smørgrav unsigned char* res) 134405ab2901SDag-Erling Smørgrav { 134505ab2901SDag-Erling Smørgrav switch(algo) { 134605ab2901SDag-Erling Smørgrav case SHA1_DIGEST_SIZE: 134705ab2901SDag-Erling Smørgrav { 134805ab2901SDag-Erling Smørgrav struct sha1_ctx ctx; 134905ab2901SDag-Erling Smørgrav sha1_init(&ctx); 135005ab2901SDag-Erling Smørgrav sha1_update(&ctx, len, buf); 135105ab2901SDag-Erling Smørgrav sha1_digest(&ctx, SHA1_DIGEST_SIZE, res); 135205ab2901SDag-Erling Smørgrav return 1; 135305ab2901SDag-Erling Smørgrav } 135405ab2901SDag-Erling Smørgrav case SHA256_DIGEST_SIZE: 135505ab2901SDag-Erling Smørgrav { 135605ab2901SDag-Erling Smørgrav struct sha256_ctx ctx; 135705ab2901SDag-Erling Smørgrav sha256_init(&ctx); 135805ab2901SDag-Erling Smørgrav sha256_update(&ctx, len, buf); 135905ab2901SDag-Erling Smørgrav sha256_digest(&ctx, SHA256_DIGEST_SIZE, res); 136005ab2901SDag-Erling Smørgrav return 1; 136105ab2901SDag-Erling Smørgrav } 136205ab2901SDag-Erling Smørgrav case SHA384_DIGEST_SIZE: 136305ab2901SDag-Erling Smørgrav { 136405ab2901SDag-Erling Smørgrav struct sha384_ctx ctx; 136505ab2901SDag-Erling Smørgrav sha384_init(&ctx); 136605ab2901SDag-Erling Smørgrav sha384_update(&ctx, len, buf); 136705ab2901SDag-Erling Smørgrav sha384_digest(&ctx, SHA384_DIGEST_SIZE, res); 136805ab2901SDag-Erling Smørgrav return 1; 136905ab2901SDag-Erling Smørgrav } 137005ab2901SDag-Erling Smørgrav case SHA512_DIGEST_SIZE: 137105ab2901SDag-Erling Smørgrav { 137205ab2901SDag-Erling Smørgrav struct sha512_ctx ctx; 137305ab2901SDag-Erling Smørgrav sha512_init(&ctx); 137405ab2901SDag-Erling Smørgrav sha512_update(&ctx, len, buf); 137505ab2901SDag-Erling Smørgrav sha512_digest(&ctx, SHA512_DIGEST_SIZE, res); 137605ab2901SDag-Erling Smørgrav return 1; 137705ab2901SDag-Erling Smørgrav } 137805ab2901SDag-Erling Smørgrav default: 137905ab2901SDag-Erling Smørgrav break; 138005ab2901SDag-Erling Smørgrav } 138105ab2901SDag-Erling Smørgrav return 0; 138205ab2901SDag-Erling Smørgrav } 138305ab2901SDag-Erling Smørgrav 138405ab2901SDag-Erling Smørgrav /* return size of digest if supported, or 0 otherwise */ 138505ab2901SDag-Erling Smørgrav size_t 138605ab2901SDag-Erling Smørgrav nsec3_hash_algo_size_supported(int id) 138705ab2901SDag-Erling Smørgrav { 138805ab2901SDag-Erling Smørgrav switch(id) { 138905ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1: 139005ab2901SDag-Erling Smørgrav return SHA1_DIGEST_SIZE; 139105ab2901SDag-Erling Smørgrav default: 139205ab2901SDag-Erling Smørgrav return 0; 139305ab2901SDag-Erling Smørgrav } 139405ab2901SDag-Erling Smørgrav } 139505ab2901SDag-Erling Smørgrav 139605ab2901SDag-Erling Smørgrav /* perform nsec3 hash. return false on failure */ 139705ab2901SDag-Erling Smørgrav int 139805ab2901SDag-Erling Smørgrav secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len, 139905ab2901SDag-Erling Smørgrav unsigned char* res) 140005ab2901SDag-Erling Smørgrav { 140105ab2901SDag-Erling Smørgrav switch(algo) { 140205ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1: 140305ab2901SDag-Erling Smørgrav return _digest_nettle(SHA1_DIGEST_SIZE, (uint8_t*)buf, len, 140405ab2901SDag-Erling Smørgrav res); 140505ab2901SDag-Erling Smørgrav default: 140605ab2901SDag-Erling Smørgrav return 0; 140705ab2901SDag-Erling Smørgrav } 140805ab2901SDag-Erling Smørgrav } 140905ab2901SDag-Erling Smørgrav 1410e2d15004SDag-Erling Smørgrav void 1411e2d15004SDag-Erling Smørgrav secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res) 1412e2d15004SDag-Erling Smørgrav { 1413e2d15004SDag-Erling Smørgrav _digest_nettle(SHA256_DIGEST_SIZE, (uint8_t*)buf, len, res); 1414e2d15004SDag-Erling Smørgrav } 1415e2d15004SDag-Erling Smørgrav 141605ab2901SDag-Erling Smørgrav /** 141705ab2901SDag-Erling Smørgrav * Return size of DS digest according to its hash algorithm. 141805ab2901SDag-Erling Smørgrav * @param algo: DS digest algo. 141905ab2901SDag-Erling Smørgrav * @return size in bytes of digest, or 0 if not supported. 142005ab2901SDag-Erling Smørgrav */ 142105ab2901SDag-Erling Smørgrav size_t 142205ab2901SDag-Erling Smørgrav ds_digest_size_supported(int algo) 142305ab2901SDag-Erling Smørgrav { 142405ab2901SDag-Erling Smørgrav switch(algo) { 142505ab2901SDag-Erling Smørgrav case LDNS_SHA1: 142665b390aaSDag-Erling Smørgrav #ifdef USE_SHA1 142705ab2901SDag-Erling Smørgrav return SHA1_DIGEST_SIZE; 142865b390aaSDag-Erling Smørgrav #else 142965b390aaSDag-Erling Smørgrav if(fake_sha1) return 20; 143065b390aaSDag-Erling Smørgrav return 0; 143165b390aaSDag-Erling Smørgrav #endif 143205ab2901SDag-Erling Smørgrav #ifdef USE_SHA2 143305ab2901SDag-Erling Smørgrav case LDNS_SHA256: 143405ab2901SDag-Erling Smørgrav return SHA256_DIGEST_SIZE; 143505ab2901SDag-Erling Smørgrav #endif 143605ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA 143705ab2901SDag-Erling Smørgrav case LDNS_SHA384: 143805ab2901SDag-Erling Smørgrav return SHA384_DIGEST_SIZE; 143905ab2901SDag-Erling Smørgrav #endif 144005ab2901SDag-Erling Smørgrav /* GOST not supported */ 144105ab2901SDag-Erling Smørgrav case LDNS_HASH_GOST: 144205ab2901SDag-Erling Smørgrav default: 144305ab2901SDag-Erling Smørgrav break; 144405ab2901SDag-Erling Smørgrav } 144505ab2901SDag-Erling Smørgrav return 0; 144605ab2901SDag-Erling Smørgrav } 144705ab2901SDag-Erling Smørgrav 144805ab2901SDag-Erling Smørgrav int 144905ab2901SDag-Erling Smørgrav secalgo_ds_digest(int algo, unsigned char* buf, size_t len, 145005ab2901SDag-Erling Smørgrav unsigned char* res) 145105ab2901SDag-Erling Smørgrav { 145205ab2901SDag-Erling Smørgrav switch(algo) { 145365b390aaSDag-Erling Smørgrav #ifdef USE_SHA1 145405ab2901SDag-Erling Smørgrav case LDNS_SHA1: 145505ab2901SDag-Erling Smørgrav return _digest_nettle(SHA1_DIGEST_SIZE, buf, len, res); 145665b390aaSDag-Erling Smørgrav #endif 145705ab2901SDag-Erling Smørgrav #if defined(USE_SHA2) 145805ab2901SDag-Erling Smørgrav case LDNS_SHA256: 145905ab2901SDag-Erling Smørgrav return _digest_nettle(SHA256_DIGEST_SIZE, buf, len, res); 146005ab2901SDag-Erling Smørgrav #endif 146105ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA 146205ab2901SDag-Erling Smørgrav case LDNS_SHA384: 146305ab2901SDag-Erling Smørgrav return _digest_nettle(SHA384_DIGEST_SIZE, buf, len, res); 146405ab2901SDag-Erling Smørgrav 146505ab2901SDag-Erling Smørgrav #endif 146605ab2901SDag-Erling Smørgrav case LDNS_HASH_GOST: 146705ab2901SDag-Erling Smørgrav default: 146805ab2901SDag-Erling Smørgrav verbose(VERB_QUERY, "unknown DS digest algorithm %d", 146905ab2901SDag-Erling Smørgrav algo); 147005ab2901SDag-Erling Smørgrav break; 147105ab2901SDag-Erling Smørgrav } 147205ab2901SDag-Erling Smørgrav return 0; 147305ab2901SDag-Erling Smørgrav } 147405ab2901SDag-Erling Smørgrav 147505ab2901SDag-Erling Smørgrav int 147605ab2901SDag-Erling Smørgrav dnskey_algo_id_is_supported(int id) 147705ab2901SDag-Erling Smørgrav { 147805ab2901SDag-Erling Smørgrav /* uses libnettle */ 147905ab2901SDag-Erling Smørgrav switch(id) { 148065b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1) 148105ab2901SDag-Erling Smørgrav case LDNS_DSA: 148205ab2901SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 1483e2d15004SDag-Erling Smørgrav #endif 148465b390aaSDag-Erling Smørgrav #ifdef USE_SHA1 148505ab2901SDag-Erling Smørgrav case LDNS_RSASHA1: 148605ab2901SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 148765b390aaSDag-Erling Smørgrav #endif 148805ab2901SDag-Erling Smørgrav #ifdef USE_SHA2 148905ab2901SDag-Erling Smørgrav case LDNS_RSASHA256: 149005ab2901SDag-Erling Smørgrav case LDNS_RSASHA512: 149105ab2901SDag-Erling Smørgrav #endif 149205ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA 149305ab2901SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 149405ab2901SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 149505ab2901SDag-Erling Smørgrav #endif 149605ab2901SDag-Erling Smørgrav return 1; 1497971980c3SDag-Erling Smørgrav #ifdef USE_ED25519 1498971980c3SDag-Erling Smørgrav case LDNS_ED25519: 1499971980c3SDag-Erling Smørgrav return 1; 1500971980c3SDag-Erling Smørgrav #endif 150105ab2901SDag-Erling Smørgrav case LDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */ 150205ab2901SDag-Erling Smørgrav case LDNS_ECC_GOST: 150305ab2901SDag-Erling Smørgrav default: 150405ab2901SDag-Erling Smørgrav return 0; 150505ab2901SDag-Erling Smørgrav } 150605ab2901SDag-Erling Smørgrav } 150705ab2901SDag-Erling Smørgrav 150865b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1) 150905ab2901SDag-Erling Smørgrav static char * 151005ab2901SDag-Erling Smørgrav _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock, 151105ab2901SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen) 151205ab2901SDag-Erling Smørgrav { 151305ab2901SDag-Erling Smørgrav uint8_t digest[SHA1_DIGEST_SIZE]; 15143005e0a3SDag-Erling Smørgrav uint8_t key_t_value; 151505ab2901SDag-Erling Smørgrav int res = 0; 151605ab2901SDag-Erling Smørgrav size_t offset; 151705ab2901SDag-Erling Smørgrav struct dsa_public_key pubkey; 151805ab2901SDag-Erling Smørgrav struct dsa_signature signature; 151905ab2901SDag-Erling Smørgrav unsigned int expected_len; 152005ab2901SDag-Erling Smørgrav 152105ab2901SDag-Erling Smørgrav /* Extract DSA signature from the record */ 152205ab2901SDag-Erling Smørgrav nettle_dsa_signature_init(&signature); 152305ab2901SDag-Erling Smørgrav /* Signature length: 41 bytes - RFC 2536 sec. 3 */ 152405ab2901SDag-Erling Smørgrav if(sigblock_len == 41) { 152505ab2901SDag-Erling Smørgrav if(key[0] != sigblock[0]) 152605ab2901SDag-Erling Smørgrav return "invalid T value in DSA signature or pubkey"; 152705ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.r, 20, sigblock+1); 152805ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.s, 20, sigblock+1+20); 152905ab2901SDag-Erling Smørgrav } else { 153005ab2901SDag-Erling Smørgrav /* DER encoded, decode the ASN1 notated R and S bignums */ 153105ab2901SDag-Erling Smørgrav /* SEQUENCE { r INTEGER, s INTEGER } */ 153205ab2901SDag-Erling Smørgrav struct asn1_der_iterator i, seq; 153305ab2901SDag-Erling Smørgrav if(asn1_der_iterator_first(&i, sigblock_len, 153405ab2901SDag-Erling Smørgrav (uint8_t*)sigblock) != ASN1_ITERATOR_CONSTRUCTED 153505ab2901SDag-Erling Smørgrav || i.type != ASN1_SEQUENCE) 153605ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature"; 153705ab2901SDag-Erling Smørgrav /* decode this element of i using the seq iterator */ 153805ab2901SDag-Erling Smørgrav if(asn1_der_decode_constructed(&i, &seq) != 153905ab2901SDag-Erling Smørgrav ASN1_ITERATOR_PRIMITIVE || seq.type != ASN1_INTEGER) 154005ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature"; 154105ab2901SDag-Erling Smørgrav if(!asn1_der_get_bignum(&seq, signature.r, 20*8)) 154205ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature"; 154305ab2901SDag-Erling Smørgrav if(asn1_der_iterator_next(&seq) != ASN1_ITERATOR_PRIMITIVE 154405ab2901SDag-Erling Smørgrav || seq.type != ASN1_INTEGER) 154505ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature"; 154605ab2901SDag-Erling Smørgrav if(!asn1_der_get_bignum(&seq, signature.s, 20*8)) 154705ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature"; 154805ab2901SDag-Erling Smørgrav if(asn1_der_iterator_next(&i) != ASN1_ITERATOR_END) 154905ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature"; 155005ab2901SDag-Erling Smørgrav } 155105ab2901SDag-Erling Smørgrav 155205ab2901SDag-Erling Smørgrav /* Validate T values constraints - RFC 2536 sec. 2 & sec. 3 */ 15533005e0a3SDag-Erling Smørgrav key_t_value = key[0]; 15543005e0a3SDag-Erling Smørgrav if (key_t_value > 8) { 155505ab2901SDag-Erling Smørgrav return "invalid T value in DSA pubkey"; 155605ab2901SDag-Erling Smørgrav } 155705ab2901SDag-Erling Smørgrav 155805ab2901SDag-Erling Smørgrav /* Pubkey minimum length: 21 bytes - RFC 2536 sec. 2 */ 155905ab2901SDag-Erling Smørgrav if (keylen < 21) { 156005ab2901SDag-Erling Smørgrav return "DSA pubkey too short"; 156105ab2901SDag-Erling Smørgrav } 156205ab2901SDag-Erling Smørgrav 156305ab2901SDag-Erling Smørgrav expected_len = 1 + /* T */ 156405ab2901SDag-Erling Smørgrav 20 + /* Q */ 15653005e0a3SDag-Erling Smørgrav (64 + key_t_value*8) + /* P */ 15663005e0a3SDag-Erling Smørgrav (64 + key_t_value*8) + /* G */ 15673005e0a3SDag-Erling Smørgrav (64 + key_t_value*8); /* Y */ 156805ab2901SDag-Erling Smørgrav if (keylen != expected_len ) { 156905ab2901SDag-Erling Smørgrav return "invalid DSA pubkey length"; 157005ab2901SDag-Erling Smørgrav } 157105ab2901SDag-Erling Smørgrav 157205ab2901SDag-Erling Smørgrav /* Extract DSA pubkey from the record */ 157305ab2901SDag-Erling Smørgrav nettle_dsa_public_key_init(&pubkey); 157405ab2901SDag-Erling Smørgrav offset = 1; 157505ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.q, 20, key+offset); 157605ab2901SDag-Erling Smørgrav offset += 20; 15773005e0a3SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.p, (64 + key_t_value*8), key+offset); 15783005e0a3SDag-Erling Smørgrav offset += (64 + key_t_value*8); 15793005e0a3SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.g, (64 + key_t_value*8), key+offset); 15803005e0a3SDag-Erling Smørgrav offset += (64 + key_t_value*8); 15813005e0a3SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.y, (64 + key_t_value*8), key+offset); 158205ab2901SDag-Erling Smørgrav 158305ab2901SDag-Erling Smørgrav /* Digest content of "buf" and verify its DSA signature in "sigblock"*/ 158405ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), 158505ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); 158605ab2901SDag-Erling Smørgrav res &= dsa_sha1_verify_digest(&pubkey, digest, &signature); 158705ab2901SDag-Erling Smørgrav 158805ab2901SDag-Erling Smørgrav /* Clear and return */ 158905ab2901SDag-Erling Smørgrav nettle_dsa_signature_clear(&signature); 159005ab2901SDag-Erling Smørgrav nettle_dsa_public_key_clear(&pubkey); 159105ab2901SDag-Erling Smørgrav if (!res) 159205ab2901SDag-Erling Smørgrav return "DSA signature verification failed"; 159305ab2901SDag-Erling Smørgrav else 159405ab2901SDag-Erling Smørgrav return NULL; 159505ab2901SDag-Erling Smørgrav } 1596b5663de9SDag-Erling Smørgrav #endif /* USE_DSA */ 159705ab2901SDag-Erling Smørgrav 159805ab2901SDag-Erling Smørgrav static char * 159905ab2901SDag-Erling Smørgrav _verify_nettle_rsa(sldns_buffer* buf, unsigned int digest_size, char* sigblock, 160005ab2901SDag-Erling Smørgrav unsigned int sigblock_len, uint8_t* key, unsigned int keylen) 160105ab2901SDag-Erling Smørgrav { 160205ab2901SDag-Erling Smørgrav uint16_t exp_len = 0; 160305ab2901SDag-Erling Smørgrav size_t exp_offset = 0, mod_offset = 0; 160405ab2901SDag-Erling Smørgrav struct rsa_public_key pubkey; 160505ab2901SDag-Erling Smørgrav mpz_t signature; 160605ab2901SDag-Erling Smørgrav int res = 0; 160705ab2901SDag-Erling Smørgrav 160805ab2901SDag-Erling Smørgrav /* RSA pubkey parsing as per RFC 3110 sec. 2 */ 160905ab2901SDag-Erling Smørgrav if( keylen <= 1) { 161005ab2901SDag-Erling Smørgrav return "null RSA key"; 161105ab2901SDag-Erling Smørgrav } 161205ab2901SDag-Erling Smørgrav if (key[0] != 0) { 161305ab2901SDag-Erling Smørgrav /* 1-byte length */ 161405ab2901SDag-Erling Smørgrav exp_len = key[0]; 161505ab2901SDag-Erling Smørgrav exp_offset = 1; 161605ab2901SDag-Erling Smørgrav } else { 161705ab2901SDag-Erling Smørgrav /* 1-byte NUL + 2-bytes exponent length */ 161805ab2901SDag-Erling Smørgrav if (keylen < 3) { 161905ab2901SDag-Erling Smørgrav return "incorrect RSA key length"; 162005ab2901SDag-Erling Smørgrav } 162105ab2901SDag-Erling Smørgrav exp_len = READ_UINT16(key+1); 162205ab2901SDag-Erling Smørgrav if (exp_len == 0) 162305ab2901SDag-Erling Smørgrav return "null RSA exponent length"; 162405ab2901SDag-Erling Smørgrav exp_offset = 3; 162505ab2901SDag-Erling Smørgrav } 162605ab2901SDag-Erling Smørgrav /* Check that we are not over-running input length */ 162705ab2901SDag-Erling Smørgrav if (keylen < exp_offset + exp_len + 1) { 162805ab2901SDag-Erling Smørgrav return "RSA key content shorter than expected"; 162905ab2901SDag-Erling Smørgrav } 163005ab2901SDag-Erling Smørgrav mod_offset = exp_offset + exp_len; 163105ab2901SDag-Erling Smørgrav nettle_rsa_public_key_init(&pubkey); 163205ab2901SDag-Erling Smørgrav pubkey.size = keylen - mod_offset; 163305ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.e, exp_len, &key[exp_offset]); 163405ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.n, pubkey.size, &key[mod_offset]); 163505ab2901SDag-Erling Smørgrav 163605ab2901SDag-Erling Smørgrav /* Digest content of "buf" and verify its RSA signature in "sigblock"*/ 163705ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(signature, sigblock_len, (uint8_t*)sigblock); 163805ab2901SDag-Erling Smørgrav switch (digest_size) { 163905ab2901SDag-Erling Smørgrav case SHA1_DIGEST_SIZE: 164005ab2901SDag-Erling Smørgrav { 164105ab2901SDag-Erling Smørgrav uint8_t digest[SHA1_DIGEST_SIZE]; 164205ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), 164305ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); 164405ab2901SDag-Erling Smørgrav res &= rsa_sha1_verify_digest(&pubkey, digest, signature); 164505ab2901SDag-Erling Smørgrav break; 164605ab2901SDag-Erling Smørgrav } 164705ab2901SDag-Erling Smørgrav case SHA256_DIGEST_SIZE: 164805ab2901SDag-Erling Smørgrav { 164905ab2901SDag-Erling Smørgrav uint8_t digest[SHA256_DIGEST_SIZE]; 165005ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), 165105ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); 165205ab2901SDag-Erling Smørgrav res &= rsa_sha256_verify_digest(&pubkey, digest, signature); 165305ab2901SDag-Erling Smørgrav break; 165405ab2901SDag-Erling Smørgrav } 165505ab2901SDag-Erling Smørgrav case SHA512_DIGEST_SIZE: 165605ab2901SDag-Erling Smørgrav { 165705ab2901SDag-Erling Smørgrav uint8_t digest[SHA512_DIGEST_SIZE]; 165805ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA512_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), 165905ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); 166005ab2901SDag-Erling Smørgrav res &= rsa_sha512_verify_digest(&pubkey, digest, signature); 166105ab2901SDag-Erling Smørgrav break; 166205ab2901SDag-Erling Smørgrav } 166305ab2901SDag-Erling Smørgrav default: 166405ab2901SDag-Erling Smørgrav break; 166505ab2901SDag-Erling Smørgrav } 166605ab2901SDag-Erling Smørgrav 166705ab2901SDag-Erling Smørgrav /* Clear and return */ 166805ab2901SDag-Erling Smørgrav nettle_rsa_public_key_clear(&pubkey); 166905ab2901SDag-Erling Smørgrav mpz_clear(signature); 167005ab2901SDag-Erling Smørgrav if (!res) { 167105ab2901SDag-Erling Smørgrav return "RSA signature verification failed"; 167205ab2901SDag-Erling Smørgrav } else { 167305ab2901SDag-Erling Smørgrav return NULL; 167405ab2901SDag-Erling Smørgrav } 167505ab2901SDag-Erling Smørgrav } 167605ab2901SDag-Erling Smørgrav 167705ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA 167805ab2901SDag-Erling Smørgrav static char * 167905ab2901SDag-Erling Smørgrav _verify_nettle_ecdsa(sldns_buffer* buf, unsigned int digest_size, unsigned char* sigblock, 168005ab2901SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen) 168105ab2901SDag-Erling Smørgrav { 168205ab2901SDag-Erling Smørgrav int res = 0; 168305ab2901SDag-Erling Smørgrav struct ecc_point pubkey; 168405ab2901SDag-Erling Smørgrav struct dsa_signature signature; 168505ab2901SDag-Erling Smørgrav 168605ab2901SDag-Erling Smørgrav /* Always matched strength, as per RFC 6605 sec. 1 */ 168705ab2901SDag-Erling Smørgrav if (sigblock_len != 2*digest_size || keylen != 2*digest_size) { 168805ab2901SDag-Erling Smørgrav return "wrong ECDSA signature length"; 168905ab2901SDag-Erling Smørgrav } 169005ab2901SDag-Erling Smørgrav 169105ab2901SDag-Erling Smørgrav /* Parse ECDSA signature as per RFC 6605 sec. 4 */ 169205ab2901SDag-Erling Smørgrav nettle_dsa_signature_init(&signature); 169305ab2901SDag-Erling Smørgrav switch (digest_size) { 169405ab2901SDag-Erling Smørgrav case SHA256_DIGEST_SIZE: 169505ab2901SDag-Erling Smørgrav { 169605ab2901SDag-Erling Smørgrav uint8_t digest[SHA256_DIGEST_SIZE]; 169705ab2901SDag-Erling Smørgrav mpz_t x, y; 169805ab2901SDag-Erling Smørgrav nettle_ecc_point_init(&pubkey, &nettle_secp_256r1); 169905ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(x, SHA256_DIGEST_SIZE, key); 170005ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(y, SHA256_DIGEST_SIZE, key+SHA256_DIGEST_SIZE); 170105ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.r, SHA256_DIGEST_SIZE, sigblock); 170205ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.s, SHA256_DIGEST_SIZE, sigblock+SHA256_DIGEST_SIZE); 170305ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), 170405ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); 170505ab2901SDag-Erling Smørgrav res &= nettle_ecc_point_set(&pubkey, x, y); 170605ab2901SDag-Erling Smørgrav res &= nettle_ecdsa_verify (&pubkey, SHA256_DIGEST_SIZE, digest, &signature); 170705ab2901SDag-Erling Smørgrav mpz_clear(x); 170805ab2901SDag-Erling Smørgrav mpz_clear(y); 170905ab2901SDag-Erling Smørgrav break; 171005ab2901SDag-Erling Smørgrav } 171105ab2901SDag-Erling Smørgrav case SHA384_DIGEST_SIZE: 171205ab2901SDag-Erling Smørgrav { 171305ab2901SDag-Erling Smørgrav uint8_t digest[SHA384_DIGEST_SIZE]; 171405ab2901SDag-Erling Smørgrav mpz_t x, y; 171505ab2901SDag-Erling Smørgrav nettle_ecc_point_init(&pubkey, &nettle_secp_384r1); 171605ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(x, SHA384_DIGEST_SIZE, key); 171705ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(y, SHA384_DIGEST_SIZE, key+SHA384_DIGEST_SIZE); 171805ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.r, SHA384_DIGEST_SIZE, sigblock); 171905ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.s, SHA384_DIGEST_SIZE, sigblock+SHA384_DIGEST_SIZE); 172005ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA384_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf), 172105ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest); 172205ab2901SDag-Erling Smørgrav res &= nettle_ecc_point_set(&pubkey, x, y); 172305ab2901SDag-Erling Smørgrav res &= nettle_ecdsa_verify (&pubkey, SHA384_DIGEST_SIZE, digest, &signature); 172405ab2901SDag-Erling Smørgrav mpz_clear(x); 172505ab2901SDag-Erling Smørgrav mpz_clear(y); 172605ab2901SDag-Erling Smørgrav nettle_ecc_point_clear(&pubkey); 172705ab2901SDag-Erling Smørgrav break; 172805ab2901SDag-Erling Smørgrav } 172905ab2901SDag-Erling Smørgrav default: 173005ab2901SDag-Erling Smørgrav return "unknown ECDSA algorithm"; 173105ab2901SDag-Erling Smørgrav } 173205ab2901SDag-Erling Smørgrav 173305ab2901SDag-Erling Smørgrav /* Clear and return */ 173405ab2901SDag-Erling Smørgrav nettle_dsa_signature_clear(&signature); 173505ab2901SDag-Erling Smørgrav if (!res) 173605ab2901SDag-Erling Smørgrav return "ECDSA signature verification failed"; 173705ab2901SDag-Erling Smørgrav else 173805ab2901SDag-Erling Smørgrav return NULL; 173905ab2901SDag-Erling Smørgrav } 174005ab2901SDag-Erling Smørgrav #endif 174105ab2901SDag-Erling Smørgrav 1742971980c3SDag-Erling Smørgrav #ifdef USE_ED25519 1743971980c3SDag-Erling Smørgrav static char * 1744971980c3SDag-Erling Smørgrav _verify_nettle_ed25519(sldns_buffer* buf, unsigned char* sigblock, 1745971980c3SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen) 1746971980c3SDag-Erling Smørgrav { 1747971980c3SDag-Erling Smørgrav int res = 0; 1748971980c3SDag-Erling Smørgrav 1749971980c3SDag-Erling Smørgrav if(sigblock_len != ED25519_SIGNATURE_SIZE) { 1750971980c3SDag-Erling Smørgrav return "wrong ED25519 signature length"; 1751971980c3SDag-Erling Smørgrav } 1752971980c3SDag-Erling Smørgrav if(keylen != ED25519_KEY_SIZE) { 1753971980c3SDag-Erling Smørgrav return "wrong ED25519 key length"; 1754971980c3SDag-Erling Smørgrav } 1755971980c3SDag-Erling Smørgrav 1756971980c3SDag-Erling Smørgrav res = ed25519_sha512_verify((uint8_t*)key, sldns_buffer_limit(buf), 1757971980c3SDag-Erling Smørgrav sldns_buffer_begin(buf), (uint8_t*)sigblock); 1758971980c3SDag-Erling Smørgrav 1759971980c3SDag-Erling Smørgrav if (!res) 1760971980c3SDag-Erling Smørgrav return "ED25519 signature verification failed"; 1761971980c3SDag-Erling Smørgrav else 1762971980c3SDag-Erling Smørgrav return NULL; 1763971980c3SDag-Erling Smørgrav } 1764971980c3SDag-Erling Smørgrav #endif 1765971980c3SDag-Erling Smørgrav 176605ab2901SDag-Erling Smørgrav /** 176705ab2901SDag-Erling Smørgrav * Check a canonical sig+rrset and signature against a dnskey 176805ab2901SDag-Erling Smørgrav * @param buf: buffer with data to verify, the first rrsig part and the 176905ab2901SDag-Erling Smørgrav * canonicalized rrset. 177005ab2901SDag-Erling Smørgrav * @param algo: DNSKEY algorithm. 177105ab2901SDag-Erling Smørgrav * @param sigblock: signature rdata field from RRSIG 177205ab2901SDag-Erling Smørgrav * @param sigblock_len: length of sigblock data. 177305ab2901SDag-Erling Smørgrav * @param key: public key data from DNSKEY RR. 177405ab2901SDag-Erling Smørgrav * @param keylen: length of keydata. 177505ab2901SDag-Erling Smørgrav * @param reason: bogus reason in more detail. 177605ab2901SDag-Erling Smørgrav * @return secure if verification succeeded, bogus on crypto failure, 177705ab2901SDag-Erling Smørgrav * unchecked on format errors and alloc failures. 177805ab2901SDag-Erling Smørgrav */ 177905ab2901SDag-Erling Smørgrav enum sec_status 178005ab2901SDag-Erling Smørgrav verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock, 178105ab2901SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen, 178205ab2901SDag-Erling Smørgrav char** reason) 178305ab2901SDag-Erling Smørgrav { 178405ab2901SDag-Erling Smørgrav unsigned int digest_size = 0; 178505ab2901SDag-Erling Smørgrav 178605ab2901SDag-Erling Smørgrav if (sigblock_len == 0 || keylen == 0) { 178705ab2901SDag-Erling Smørgrav *reason = "null signature"; 178805ab2901SDag-Erling Smørgrav return sec_status_bogus; 178905ab2901SDag-Erling Smørgrav } 179005ab2901SDag-Erling Smørgrav 179105ab2901SDag-Erling Smørgrav switch(algo) { 179265b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1) 179305ab2901SDag-Erling Smørgrav case LDNS_DSA: 179405ab2901SDag-Erling Smørgrav case LDNS_DSA_NSEC3: 179505ab2901SDag-Erling Smørgrav *reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen); 179605ab2901SDag-Erling Smørgrav if (*reason != NULL) 179705ab2901SDag-Erling Smørgrav return sec_status_bogus; 179805ab2901SDag-Erling Smørgrav else 179905ab2901SDag-Erling Smørgrav return sec_status_secure; 1800e2d15004SDag-Erling Smørgrav #endif /* USE_DSA */ 180105ab2901SDag-Erling Smørgrav 180265b390aaSDag-Erling Smørgrav #ifdef USE_SHA1 180305ab2901SDag-Erling Smørgrav case LDNS_RSASHA1: 180405ab2901SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3: 180505ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE); 180665b390aaSDag-Erling Smørgrav #endif 1807971980c3SDag-Erling Smørgrav /* double fallthrough annotation to please gcc parser */ 1808971980c3SDag-Erling Smørgrav /* fallthrough */ 180905ab2901SDag-Erling Smørgrav #ifdef USE_SHA2 1810971980c3SDag-Erling Smørgrav /* fallthrough */ 181105ab2901SDag-Erling Smørgrav case LDNS_RSASHA256: 181205ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE); 1813971980c3SDag-Erling Smørgrav /* fallthrough */ 181405ab2901SDag-Erling Smørgrav case LDNS_RSASHA512: 181505ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA512_DIGEST_SIZE); 181605ab2901SDag-Erling Smørgrav 181705ab2901SDag-Erling Smørgrav #endif 181805ab2901SDag-Erling Smørgrav *reason = _verify_nettle_rsa(buf, digest_size, (char*)sigblock, 181905ab2901SDag-Erling Smørgrav sigblock_len, key, keylen); 182005ab2901SDag-Erling Smørgrav if (*reason != NULL) 182105ab2901SDag-Erling Smørgrav return sec_status_bogus; 182205ab2901SDag-Erling Smørgrav else 182305ab2901SDag-Erling Smørgrav return sec_status_secure; 182405ab2901SDag-Erling Smørgrav 182505ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA 182605ab2901SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256: 182705ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE); 1828971980c3SDag-Erling Smørgrav /* fallthrough */ 182905ab2901SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384: 183005ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA384_DIGEST_SIZE); 183105ab2901SDag-Erling Smørgrav *reason = _verify_nettle_ecdsa(buf, digest_size, sigblock, 183205ab2901SDag-Erling Smørgrav sigblock_len, key, keylen); 183305ab2901SDag-Erling Smørgrav if (*reason != NULL) 183405ab2901SDag-Erling Smørgrav return sec_status_bogus; 183505ab2901SDag-Erling Smørgrav else 183605ab2901SDag-Erling Smørgrav return sec_status_secure; 183705ab2901SDag-Erling Smørgrav #endif 1838971980c3SDag-Erling Smørgrav #ifdef USE_ED25519 1839971980c3SDag-Erling Smørgrav case LDNS_ED25519: 1840971980c3SDag-Erling Smørgrav *reason = _verify_nettle_ed25519(buf, sigblock, sigblock_len, 1841971980c3SDag-Erling Smørgrav key, keylen); 1842971980c3SDag-Erling Smørgrav if (*reason != NULL) 1843971980c3SDag-Erling Smørgrav return sec_status_bogus; 1844971980c3SDag-Erling Smørgrav else 1845971980c3SDag-Erling Smørgrav return sec_status_secure; 1846971980c3SDag-Erling Smørgrav #endif 184705ab2901SDag-Erling Smørgrav case LDNS_RSAMD5: 184805ab2901SDag-Erling Smørgrav case LDNS_ECC_GOST: 184905ab2901SDag-Erling Smørgrav default: 185005ab2901SDag-Erling Smørgrav *reason = "unable to verify signature, unknown algorithm"; 185105ab2901SDag-Erling Smørgrav return sec_status_bogus; 185205ab2901SDag-Erling Smørgrav } 185305ab2901SDag-Erling Smørgrav } 185405ab2901SDag-Erling Smørgrav 185505ab2901SDag-Erling Smørgrav #endif /* HAVE_SSL or HAVE_NSS or HAVE_NETTLE */ 1856