13b6c3722Schristos /*
23b6c3722Schristos * validator/val_secalgo.c - validator security algorithm functions.
33b6c3722Schristos *
43b6c3722Schristos * Copyright (c) 2012, NLnet Labs. All rights reserved.
53b6c3722Schristos *
63b6c3722Schristos * This software is open source.
73b6c3722Schristos *
83b6c3722Schristos * Redistribution and use in source and binary forms, with or without
93b6c3722Schristos * modification, are permitted provided that the following conditions
103b6c3722Schristos * are met:
113b6c3722Schristos *
123b6c3722Schristos * Redistributions of source code must retain the above copyright notice,
133b6c3722Schristos * this list of conditions and the following disclaimer.
143b6c3722Schristos *
153b6c3722Schristos * Redistributions in binary form must reproduce the above copyright notice,
163b6c3722Schristos * this list of conditions and the following disclaimer in the documentation
173b6c3722Schristos * and/or other materials provided with the distribution.
183b6c3722Schristos *
193b6c3722Schristos * Neither the name of the NLNET LABS nor the names of its contributors may
203b6c3722Schristos * be used to endorse or promote products derived from this software without
213b6c3722Schristos * specific prior written permission.
223b6c3722Schristos *
233b6c3722Schristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
243b6c3722Schristos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
253b6c3722Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
263b6c3722Schristos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
273b6c3722Schristos * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
283b6c3722Schristos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
293b6c3722Schristos * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
303b6c3722Schristos * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
313b6c3722Schristos * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
323b6c3722Schristos * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
333b6c3722Schristos * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
343b6c3722Schristos */
353b6c3722Schristos
363b6c3722Schristos /**
373b6c3722Schristos * \file
383b6c3722Schristos *
393b6c3722Schristos * This file contains helper functions for the validator module.
403b6c3722Schristos * These functions take raw data buffers, formatted for crypto verification,
413b6c3722Schristos * and do the library calls (for the crypto library in use).
423b6c3722Schristos */
433b6c3722Schristos #include "config.h"
443b6c3722Schristos /* packed_rrset on top to define enum types (forced by c99 standard) */
453b6c3722Schristos #include "util/data/packed_rrset.h"
463b6c3722Schristos #include "validator/val_secalgo.h"
473b6c3722Schristos #include "validator/val_nsec3.h"
483b6c3722Schristos #include "util/log.h"
493b6c3722Schristos #include "sldns/rrdef.h"
503b6c3722Schristos #include "sldns/keyraw.h"
513b6c3722Schristos #include "sldns/sbuffer.h"
523b6c3722Schristos
533b6c3722Schristos #if !defined(HAVE_SSL) && !defined(HAVE_NSS) && !defined(HAVE_NETTLE)
543b6c3722Schristos #error "Need crypto library to do digital signature cryptography"
553b6c3722Schristos #endif
563b6c3722Schristos
57d0eba39bSchristos /** fake DSA support for unit tests */
58d0eba39bSchristos int fake_dsa = 0;
59d0eba39bSchristos /** fake SHA1 support for unit tests */
60d0eba39bSchristos int fake_sha1 = 0;
61d0eba39bSchristos
623b6c3722Schristos /* OpenSSL implementation */
633b6c3722Schristos #ifdef HAVE_SSL
643b6c3722Schristos #ifdef HAVE_OPENSSL_ERR_H
653b6c3722Schristos #include <openssl/err.h>
663b6c3722Schristos #endif
673b6c3722Schristos
683b6c3722Schristos #ifdef HAVE_OPENSSL_RAND_H
693b6c3722Schristos #include <openssl/rand.h>
703b6c3722Schristos #endif
713b6c3722Schristos
723b6c3722Schristos #ifdef HAVE_OPENSSL_CONF_H
733b6c3722Schristos #include <openssl/conf.h>
743b6c3722Schristos #endif
753b6c3722Schristos
763b6c3722Schristos #ifdef HAVE_OPENSSL_ENGINE_H
773b6c3722Schristos #include <openssl/engine.h>
783b6c3722Schristos #endif
793b6c3722Schristos
80d0eba39bSchristos #if defined(HAVE_OPENSSL_DSA_H) && defined(USE_DSA)
81d0eba39bSchristos #include <openssl/dsa.h>
82d0eba39bSchristos #endif
830cd9f4ecSchristos
84f42d8de7Schristos /**
85f42d8de7Schristos * Output a libcrypto openssl error to the logfile.
86f42d8de7Schristos * @param str: string to add to it.
87f42d8de7Schristos * @param e: the error to output, error number from ERR_get_error().
88f42d8de7Schristos */
89f42d8de7Schristos static void
log_crypto_error(const char * str,unsigned long e)90f42d8de7Schristos log_crypto_error(const char* str, unsigned long e)
91f42d8de7Schristos {
92f42d8de7Schristos char buf[128];
93f42d8de7Schristos /* or use ERR_error_string if ERR_error_string_n is not avail TODO */
94f42d8de7Schristos ERR_error_string_n(e, buf, sizeof(buf));
95f42d8de7Schristos /* buf now contains */
96f42d8de7Schristos /* error:[error code]:[library name]:[function name]:[reason string] */
97f42d8de7Schristos log_err("%s crypto %s", str, buf);
98f42d8de7Schristos }
99f42d8de7Schristos
100*7a540f2bSchristos /**
101*7a540f2bSchristos * Output a libcrypto openssl error to the logfile as a debug message.
102*7a540f2bSchristos * @param level: debug level to use in verbose() call
103*7a540f2bSchristos * @param str: string to add to it.
104*7a540f2bSchristos * @param e: the error to output, error number from ERR_get_error().
105*7a540f2bSchristos */
106*7a540f2bSchristos static void
log_crypto_verbose(enum verbosity_value level,const char * str,unsigned long e)107*7a540f2bSchristos log_crypto_verbose(enum verbosity_value level, const char* str, unsigned long e)
108*7a540f2bSchristos {
109*7a540f2bSchristos char buf[128];
110*7a540f2bSchristos /* or use ERR_error_string if ERR_error_string_n is not avail TODO */
111*7a540f2bSchristos ERR_error_string_n(e, buf, sizeof(buf));
112*7a540f2bSchristos /* buf now contains */
113*7a540f2bSchristos /* error:[error code]:[library name]:[function name]:[reason string] */
114*7a540f2bSchristos verbose(level, "%s crypto %s", str, buf);
115*7a540f2bSchristos }
116*7a540f2bSchristos
1173b6c3722Schristos /* return size of digest if supported, or 0 otherwise */
1183b6c3722Schristos size_t
nsec3_hash_algo_size_supported(int id)1193b6c3722Schristos nsec3_hash_algo_size_supported(int id)
1203b6c3722Schristos {
1213b6c3722Schristos switch(id) {
1223b6c3722Schristos case NSEC3_HASH_SHA1:
1233b6c3722Schristos return SHA_DIGEST_LENGTH;
1243b6c3722Schristos default:
1253b6c3722Schristos return 0;
1263b6c3722Schristos }
1273b6c3722Schristos }
1283b6c3722Schristos
1293b6c3722Schristos /* perform nsec3 hash. return false on failure */
1303b6c3722Schristos int
secalgo_nsec3_hash(int algo,unsigned char * buf,size_t len,unsigned char * res)1313b6c3722Schristos secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
1323b6c3722Schristos unsigned char* res)
1333b6c3722Schristos {
1343b6c3722Schristos switch(algo) {
1353b6c3722Schristos case NSEC3_HASH_SHA1:
136f42d8de7Schristos #ifdef OPENSSL_FIPS
137f42d8de7Schristos if(!sldns_digest_evp(buf, len, res, EVP_sha1()))
138f42d8de7Schristos log_crypto_error("could not digest with EVP_sha1",
139f42d8de7Schristos ERR_get_error());
140f42d8de7Schristos #else
1413b6c3722Schristos (void)SHA1(buf, len, res);
142f42d8de7Schristos #endif
1433b6c3722Schristos return 1;
1443b6c3722Schristos default:
1453b6c3722Schristos return 0;
1463b6c3722Schristos }
1473b6c3722Schristos }
1483b6c3722Schristos
1493b6c3722Schristos void
secalgo_hash_sha256(unsigned char * buf,size_t len,unsigned char * res)1503b6c3722Schristos secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
1513b6c3722Schristos {
152f42d8de7Schristos #ifdef OPENSSL_FIPS
153f42d8de7Schristos if(!sldns_digest_evp(buf, len, res, EVP_sha256()))
154f42d8de7Schristos log_crypto_error("could not digest with EVP_sha256",
155f42d8de7Schristos ERR_get_error());
156f42d8de7Schristos #else
1573b6c3722Schristos (void)SHA256(buf, len, res);
158f42d8de7Schristos #endif
1593b6c3722Schristos }
1603b6c3722Schristos
161*7a540f2bSchristos /** hash structure for keeping track of running hashes */
162*7a540f2bSchristos struct secalgo_hash {
163*7a540f2bSchristos /** the openssl message digest context */
164*7a540f2bSchristos EVP_MD_CTX* ctx;
165*7a540f2bSchristos };
166*7a540f2bSchristos
167*7a540f2bSchristos /** create secalgo hash with hash type */
secalgo_hash_create_md(const EVP_MD * md)168*7a540f2bSchristos static struct secalgo_hash* secalgo_hash_create_md(const EVP_MD* md)
169*7a540f2bSchristos {
170*7a540f2bSchristos struct secalgo_hash* h;
171*7a540f2bSchristos if(!md)
172*7a540f2bSchristos return NULL;
173*7a540f2bSchristos h = calloc(1, sizeof(*h));
174*7a540f2bSchristos if(!h)
175*7a540f2bSchristos return NULL;
176*7a540f2bSchristos h->ctx = EVP_MD_CTX_create();
177*7a540f2bSchristos if(!h->ctx) {
178*7a540f2bSchristos free(h);
179*7a540f2bSchristos return NULL;
180*7a540f2bSchristos }
181*7a540f2bSchristos if(!EVP_DigestInit_ex(h->ctx, md, NULL)) {
182*7a540f2bSchristos EVP_MD_CTX_destroy(h->ctx);
183*7a540f2bSchristos free(h);
184*7a540f2bSchristos return NULL;
185*7a540f2bSchristos }
186*7a540f2bSchristos return h;
187*7a540f2bSchristos }
188*7a540f2bSchristos
secalgo_hash_create_sha384(void)189*7a540f2bSchristos struct secalgo_hash* secalgo_hash_create_sha384(void)
190*7a540f2bSchristos {
191*7a540f2bSchristos return secalgo_hash_create_md(EVP_sha384());
192*7a540f2bSchristos }
193*7a540f2bSchristos
secalgo_hash_create_sha512(void)194*7a540f2bSchristos struct secalgo_hash* secalgo_hash_create_sha512(void)
195*7a540f2bSchristos {
196*7a540f2bSchristos return secalgo_hash_create_md(EVP_sha512());
197*7a540f2bSchristos }
198*7a540f2bSchristos
secalgo_hash_update(struct secalgo_hash * hash,uint8_t * data,size_t len)199*7a540f2bSchristos int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len)
200*7a540f2bSchristos {
201*7a540f2bSchristos return EVP_DigestUpdate(hash->ctx, (unsigned char*)data,
202*7a540f2bSchristos (unsigned int)len);
203*7a540f2bSchristos }
204*7a540f2bSchristos
secalgo_hash_final(struct secalgo_hash * hash,uint8_t * result,size_t maxlen,size_t * resultlen)205*7a540f2bSchristos int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result,
206*7a540f2bSchristos size_t maxlen, size_t* resultlen)
207*7a540f2bSchristos {
208*7a540f2bSchristos if(EVP_MD_CTX_size(hash->ctx) > (int)maxlen) {
209*7a540f2bSchristos *resultlen = 0;
210*7a540f2bSchristos log_err("secalgo_hash_final: hash buffer too small");
211*7a540f2bSchristos return 0;
212*7a540f2bSchristos }
213*7a540f2bSchristos *resultlen = EVP_MD_CTX_size(hash->ctx);
214*7a540f2bSchristos return EVP_DigestFinal_ex(hash->ctx, result, NULL);
215*7a540f2bSchristos }
216*7a540f2bSchristos
secalgo_hash_delete(struct secalgo_hash * hash)217*7a540f2bSchristos void secalgo_hash_delete(struct secalgo_hash* hash)
218*7a540f2bSchristos {
219*7a540f2bSchristos if(!hash) return;
220*7a540f2bSchristos EVP_MD_CTX_destroy(hash->ctx);
221*7a540f2bSchristos free(hash);
222*7a540f2bSchristos }
223*7a540f2bSchristos
2243b6c3722Schristos /**
2253b6c3722Schristos * Return size of DS digest according to its hash algorithm.
2263b6c3722Schristos * @param algo: DS digest algo.
2273b6c3722Schristos * @return size in bytes of digest, or 0 if not supported.
2283b6c3722Schristos */
2293b6c3722Schristos size_t
ds_digest_size_supported(int algo)2303b6c3722Schristos ds_digest_size_supported(int algo)
2313b6c3722Schristos {
2323b6c3722Schristos switch(algo) {
2333b6c3722Schristos case LDNS_SHA1:
2340cd9f4ecSchristos #if defined(HAVE_EVP_SHA1) && defined(USE_SHA1)
235*7a540f2bSchristos #ifdef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED
236*7a540f2bSchristos if (EVP_default_properties_is_fips_enabled(NULL))
237*7a540f2bSchristos return 0;
238*7a540f2bSchristos #endif
2393b6c3722Schristos return SHA_DIGEST_LENGTH;
2400cd9f4ecSchristos #else
2410cd9f4ecSchristos if(fake_sha1) return 20;
2420cd9f4ecSchristos return 0;
2433b6c3722Schristos #endif
2443b6c3722Schristos #ifdef HAVE_EVP_SHA256
2453b6c3722Schristos case LDNS_SHA256:
2463b6c3722Schristos return SHA256_DIGEST_LENGTH;
2473b6c3722Schristos #endif
2483b6c3722Schristos #ifdef USE_GOST
2493b6c3722Schristos case LDNS_HASH_GOST:
2503b6c3722Schristos /* we support GOST if it can be loaded */
2513b6c3722Schristos (void)sldns_key_EVP_load_gost_id();
2523b6c3722Schristos if(EVP_get_digestbyname("md_gost94"))
2533b6c3722Schristos return 32;
2543b6c3722Schristos else return 0;
2553b6c3722Schristos #endif
2563b6c3722Schristos #ifdef USE_ECDSA
2573b6c3722Schristos case LDNS_SHA384:
2583b6c3722Schristos return SHA384_DIGEST_LENGTH;
2593b6c3722Schristos #endif
2603b6c3722Schristos default: break;
2613b6c3722Schristos }
2623b6c3722Schristos return 0;
2633b6c3722Schristos }
2643b6c3722Schristos
2653b6c3722Schristos #ifdef USE_GOST
2663b6c3722Schristos /** Perform GOST hash */
2673b6c3722Schristos static int
do_gost94(unsigned char * data,size_t len,unsigned char * dest)2683b6c3722Schristos do_gost94(unsigned char* data, size_t len, unsigned char* dest)
2693b6c3722Schristos {
2703b6c3722Schristos const EVP_MD* md = EVP_get_digestbyname("md_gost94");
2713b6c3722Schristos if(!md)
2723b6c3722Schristos return 0;
2733b6c3722Schristos return sldns_digest_evp(data, (unsigned int)len, dest, md);
2743b6c3722Schristos }
2753b6c3722Schristos #endif
2763b6c3722Schristos
2773b6c3722Schristos int
secalgo_ds_digest(int algo,unsigned char * buf,size_t len,unsigned char * res)2783b6c3722Schristos secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
2793b6c3722Schristos unsigned char* res)
2803b6c3722Schristos {
2813b6c3722Schristos switch(algo) {
2820cd9f4ecSchristos #if defined(HAVE_EVP_SHA1) && defined(USE_SHA1)
2833b6c3722Schristos case LDNS_SHA1:
284f42d8de7Schristos #ifdef OPENSSL_FIPS
285f42d8de7Schristos if(!sldns_digest_evp(buf, len, res, EVP_sha1()))
286f42d8de7Schristos log_crypto_error("could not digest with EVP_sha1",
287f42d8de7Schristos ERR_get_error());
288f42d8de7Schristos #else
2893b6c3722Schristos (void)SHA1(buf, len, res);
290f42d8de7Schristos #endif
2913b6c3722Schristos return 1;
2923b6c3722Schristos #endif
2933b6c3722Schristos #ifdef HAVE_EVP_SHA256
2943b6c3722Schristos case LDNS_SHA256:
295f42d8de7Schristos #ifdef OPENSSL_FIPS
296f42d8de7Schristos if(!sldns_digest_evp(buf, len, res, EVP_sha256()))
297f42d8de7Schristos log_crypto_error("could not digest with EVP_sha256",
298f42d8de7Schristos ERR_get_error());
299f42d8de7Schristos #else
3003b6c3722Schristos (void)SHA256(buf, len, res);
301f42d8de7Schristos #endif
3023b6c3722Schristos return 1;
3033b6c3722Schristos #endif
3043b6c3722Schristos #ifdef USE_GOST
3053b6c3722Schristos case LDNS_HASH_GOST:
3063b6c3722Schristos if(do_gost94(buf, len, res))
3073b6c3722Schristos return 1;
3083b6c3722Schristos break;
3093b6c3722Schristos #endif
3103b6c3722Schristos #ifdef USE_ECDSA
3113b6c3722Schristos case LDNS_SHA384:
312f42d8de7Schristos #ifdef OPENSSL_FIPS
313f42d8de7Schristos if(!sldns_digest_evp(buf, len, res, EVP_sha384()))
314f42d8de7Schristos log_crypto_error("could not digest with EVP_sha384",
315f42d8de7Schristos ERR_get_error());
316f42d8de7Schristos #else
3173b6c3722Schristos (void)SHA384(buf, len, res);
318f42d8de7Schristos #endif
3193b6c3722Schristos return 1;
3203b6c3722Schristos #endif
3213b6c3722Schristos default:
3223b6c3722Schristos verbose(VERB_QUERY, "unknown DS digest algorithm %d",
3233b6c3722Schristos algo);
3243b6c3722Schristos break;
3253b6c3722Schristos }
3263b6c3722Schristos return 0;
3273b6c3722Schristos }
3283b6c3722Schristos
3293b6c3722Schristos /** return true if DNSKEY algorithm id is supported */
3303b6c3722Schristos int
dnskey_algo_id_is_supported(int id)3313b6c3722Schristos dnskey_algo_id_is_supported(int id)
3323b6c3722Schristos {
3333b6c3722Schristos switch(id) {
3343b6c3722Schristos case LDNS_RSAMD5:
3353b6c3722Schristos /* RFC 6725 deprecates RSAMD5 */
3363b6c3722Schristos return 0;
3373b6c3722Schristos case LDNS_DSA:
3383b6c3722Schristos case LDNS_DSA_NSEC3:
3390cd9f4ecSchristos #if defined(USE_DSA) && defined(USE_SHA1)
3400cd9f4ecSchristos return 1;
3410cd9f4ecSchristos #else
3420cd9f4ecSchristos if(fake_dsa || fake_sha1) return 1;
3430cd9f4ecSchristos return 0;
3443b6c3722Schristos #endif
3450cd9f4ecSchristos
3463b6c3722Schristos case LDNS_RSASHA1:
3473b6c3722Schristos case LDNS_RSASHA1_NSEC3:
3480cd9f4ecSchristos #ifdef USE_SHA1
349*7a540f2bSchristos #ifdef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED
350*7a540f2bSchristos return !EVP_default_properties_is_fips_enabled(NULL);
351*7a540f2bSchristos #else
3520cd9f4ecSchristos return 1;
353*7a540f2bSchristos #endif
3540cd9f4ecSchristos #else
3550cd9f4ecSchristos if(fake_sha1) return 1;
3560cd9f4ecSchristos return 0;
3570cd9f4ecSchristos #endif
3580cd9f4ecSchristos
3593b6c3722Schristos #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
3603b6c3722Schristos case LDNS_RSASHA256:
3613b6c3722Schristos #endif
3623b6c3722Schristos #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
3633b6c3722Schristos case LDNS_RSASHA512:
3643b6c3722Schristos #endif
3653b6c3722Schristos #ifdef USE_ECDSA
3663b6c3722Schristos case LDNS_ECDSAP256SHA256:
3673b6c3722Schristos case LDNS_ECDSAP384SHA384:
3683b6c3722Schristos #endif
369*7a540f2bSchristos #if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA)
370*7a540f2bSchristos return 1;
371*7a540f2bSchristos #endif
3720cd9f4ecSchristos #ifdef USE_ED25519
3730cd9f4ecSchristos case LDNS_ED25519:
3740cd9f4ecSchristos #endif
3757cd94d69Schristos #ifdef USE_ED448
3767cd94d69Schristos case LDNS_ED448:
3777cd94d69Schristos #endif
378*7a540f2bSchristos #if defined(USE_ED25519) || defined(USE_ED448)
379*7a540f2bSchristos #ifdef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED
380*7a540f2bSchristos return !EVP_default_properties_is_fips_enabled(NULL);
381*7a540f2bSchristos #else
3823b6c3722Schristos return 1;
3830cd9f4ecSchristos #endif
384*7a540f2bSchristos #endif
3850cd9f4ecSchristos
3863b6c3722Schristos #ifdef USE_GOST
3873b6c3722Schristos case LDNS_ECC_GOST:
3883b6c3722Schristos /* we support GOST if it can be loaded */
3893b6c3722Schristos return sldns_key_EVP_load_gost_id();
3903b6c3722Schristos #endif
3913b6c3722Schristos default:
3923b6c3722Schristos return 0;
3933b6c3722Schristos }
3943b6c3722Schristos }
3953b6c3722Schristos
3963b6c3722Schristos #ifdef USE_DSA
3973b6c3722Schristos /**
3983b6c3722Schristos * Setup DSA key digest in DER encoding ...
3993b6c3722Schristos * @param sig: input is signature output alloced ptr (unless failure).
4003b6c3722Schristos * caller must free alloced ptr if this routine returns true.
4013b6c3722Schristos * @param len: input is initial siglen, output is output len.
4023b6c3722Schristos * @return false on failure.
4033b6c3722Schristos */
4043b6c3722Schristos static int
setup_dsa_sig(unsigned char ** sig,unsigned int * len)4053b6c3722Schristos setup_dsa_sig(unsigned char** sig, unsigned int* len)
4063b6c3722Schristos {
4073b6c3722Schristos unsigned char* orig = *sig;
4083b6c3722Schristos unsigned int origlen = *len;
4093b6c3722Schristos int newlen;
4103b6c3722Schristos BIGNUM *R, *S;
4113b6c3722Schristos DSA_SIG *dsasig;
4123b6c3722Schristos
4133b6c3722Schristos /* extract the R and S field from the sig buffer */
4143b6c3722Schristos if(origlen < 1 + 2*SHA_DIGEST_LENGTH)
4153b6c3722Schristos return 0;
4163b6c3722Schristos R = BN_new();
4173b6c3722Schristos if(!R) return 0;
4183b6c3722Schristos (void) BN_bin2bn(orig + 1, SHA_DIGEST_LENGTH, R);
4193b6c3722Schristos S = BN_new();
4203b6c3722Schristos if(!S) return 0;
4213b6c3722Schristos (void) BN_bin2bn(orig + 21, SHA_DIGEST_LENGTH, S);
4223b6c3722Schristos dsasig = DSA_SIG_new();
4233b6c3722Schristos if(!dsasig) return 0;
4243b6c3722Schristos
4250cd9f4ecSchristos #ifdef HAVE_DSA_SIG_SET0
4260cd9f4ecSchristos if(!DSA_SIG_set0(dsasig, R, S)) return 0;
4270cd9f4ecSchristos #else
42801049ae6Schristos # ifndef S_SPLINT_S
4293b6c3722Schristos dsasig->r = R;
4303b6c3722Schristos dsasig->s = S;
43101049ae6Schristos # endif /* S_SPLINT_S */
4320cd9f4ecSchristos #endif
4333b6c3722Schristos *sig = NULL;
4343b6c3722Schristos newlen = i2d_DSA_SIG(dsasig, sig);
4353b6c3722Schristos if(newlen < 0) {
4363b6c3722Schristos DSA_SIG_free(dsasig);
4373b6c3722Schristos free(*sig);
4383b6c3722Schristos return 0;
4393b6c3722Schristos }
4403b6c3722Schristos *len = (unsigned int)newlen;
4413b6c3722Schristos DSA_SIG_free(dsasig);
4423b6c3722Schristos return 1;
4433b6c3722Schristos }
4443b6c3722Schristos #endif /* USE_DSA */
4453b6c3722Schristos
4463b6c3722Schristos #ifdef USE_ECDSA
4473b6c3722Schristos /**
4483b6c3722Schristos * Setup the ECDSA signature in its encoding that the library wants.
4493b6c3722Schristos * Converts from plain numbers to ASN formatted.
4503b6c3722Schristos * @param sig: input is signature, output alloced ptr (unless failure).
4513b6c3722Schristos * caller must free alloced ptr if this routine returns true.
4523b6c3722Schristos * @param len: input is initial siglen, output is output len.
4533b6c3722Schristos * @return false on failure.
4543b6c3722Schristos */
4553b6c3722Schristos static int
setup_ecdsa_sig(unsigned char ** sig,unsigned int * len)4563b6c3722Schristos setup_ecdsa_sig(unsigned char** sig, unsigned int* len)
4573b6c3722Schristos {
4583b6c3722Schristos /* convert from two BIGNUMs in the rdata buffer, to ASN notation.
4590cd9f4ecSchristos * ASN preamble: 30440220 <R 32bytefor256> 0220 <S 32bytefor256>
4603b6c3722Schristos * the '20' is the length of that field (=bnsize).
4613b6c3722Schristos i * the '44' is the total remaining length.
4623b6c3722Schristos * if negative, start with leading zero.
4633b6c3722Schristos * if starts with 00s, remove them from the number.
4643b6c3722Schristos */
4653b6c3722Schristos uint8_t pre[] = {0x30, 0x44, 0x02, 0x20};
4663b6c3722Schristos int pre_len = 4;
4673b6c3722Schristos uint8_t mid[] = {0x02, 0x20};
4683b6c3722Schristos int mid_len = 2;
4693b6c3722Schristos int raw_sig_len, r_high, s_high, r_rem=0, s_rem=0;
4703b6c3722Schristos int bnsize = (int)((*len)/2);
4713b6c3722Schristos unsigned char* d = *sig;
4723b6c3722Schristos uint8_t* p;
4733b6c3722Schristos /* if too short or not even length, fails */
4743b6c3722Schristos if(*len < 16 || bnsize*2 != (int)*len)
4753b6c3722Schristos return 0;
4763b6c3722Schristos
4773b6c3722Schristos /* strip leading zeroes from r (but not last one) */
4783b6c3722Schristos while(r_rem < bnsize-1 && d[r_rem] == 0)
4793b6c3722Schristos r_rem++;
4803b6c3722Schristos /* strip leading zeroes from s (but not last one) */
4813b6c3722Schristos while(s_rem < bnsize-1 && d[bnsize+s_rem] == 0)
4823b6c3722Schristos s_rem++;
4833b6c3722Schristos
4843b6c3722Schristos r_high = ((d[0+r_rem]&0x80)?1:0);
4853b6c3722Schristos s_high = ((d[bnsize+s_rem]&0x80)?1:0);
4863b6c3722Schristos raw_sig_len = pre_len + r_high + bnsize - r_rem + mid_len +
4873b6c3722Schristos s_high + bnsize - s_rem;
4883b6c3722Schristos *sig = (unsigned char*)malloc((size_t)raw_sig_len);
4893b6c3722Schristos if(!*sig)
4903b6c3722Schristos return 0;
4913b6c3722Schristos p = (uint8_t*)*sig;
4923b6c3722Schristos p[0] = pre[0];
4933b6c3722Schristos p[1] = (uint8_t)(raw_sig_len-2);
4943b6c3722Schristos p[2] = pre[2];
4953b6c3722Schristos p[3] = (uint8_t)(bnsize + r_high - r_rem);
4963b6c3722Schristos p += 4;
4973b6c3722Schristos if(r_high) {
4983b6c3722Schristos *p = 0;
4993b6c3722Schristos p += 1;
5003b6c3722Schristos }
5013b6c3722Schristos memmove(p, d+r_rem, (size_t)bnsize-r_rem);
5023b6c3722Schristos p += bnsize-r_rem;
5033b6c3722Schristos memmove(p, mid, (size_t)mid_len-1);
5043b6c3722Schristos p += mid_len-1;
5053b6c3722Schristos *p = (uint8_t)(bnsize + s_high - s_rem);
5063b6c3722Schristos p += 1;
5073b6c3722Schristos if(s_high) {
5083b6c3722Schristos *p = 0;
5093b6c3722Schristos p += 1;
5103b6c3722Schristos }
5113b6c3722Schristos memmove(p, d+bnsize+s_rem, (size_t)bnsize-s_rem);
5123b6c3722Schristos *len = (unsigned int)raw_sig_len;
5133b6c3722Schristos return 1;
5143b6c3722Schristos }
5153b6c3722Schristos #endif /* USE_ECDSA */
5163b6c3722Schristos
5170cd9f4ecSchristos #ifdef USE_ECDSA_EVP_WORKAROUND
5180cd9f4ecSchristos static EVP_MD ecdsa_evp_256_md;
5190cd9f4ecSchristos static EVP_MD ecdsa_evp_384_md;
ecdsa_evp_workaround_init(void)5200cd9f4ecSchristos void ecdsa_evp_workaround_init(void)
5210cd9f4ecSchristos {
5220cd9f4ecSchristos /* openssl before 1.0.0 fixes RSA with the SHA256
5230cd9f4ecSchristos * hash in EVP. We create one for ecdsa_sha256 */
5240cd9f4ecSchristos ecdsa_evp_256_md = *EVP_sha256();
5250cd9f4ecSchristos ecdsa_evp_256_md.required_pkey_type[0] = EVP_PKEY_EC;
5260cd9f4ecSchristos ecdsa_evp_256_md.verify = (void*)ECDSA_verify;
5270cd9f4ecSchristos
5280cd9f4ecSchristos ecdsa_evp_384_md = *EVP_sha384();
5290cd9f4ecSchristos ecdsa_evp_384_md.required_pkey_type[0] = EVP_PKEY_EC;
5300cd9f4ecSchristos ecdsa_evp_384_md.verify = (void*)ECDSA_verify;
5310cd9f4ecSchristos }
5320cd9f4ecSchristos #endif /* USE_ECDSA_EVP_WORKAROUND */
5330cd9f4ecSchristos
5343b6c3722Schristos /**
5353b6c3722Schristos * Setup key and digest for verification. Adjust sig if necessary.
5363b6c3722Schristos *
5373b6c3722Schristos * @param algo: key algorithm
5383b6c3722Schristos * @param evp_key: EVP PKEY public key to create.
5393b6c3722Schristos * @param digest_type: digest type to use
5403b6c3722Schristos * @param key: key to setup for.
5413b6c3722Schristos * @param keylen: length of key.
5423b6c3722Schristos * @return false on failure.
5433b6c3722Schristos */
5443b6c3722Schristos static int
setup_key_digest(int algo,EVP_PKEY ** evp_key,const EVP_MD ** digest_type,unsigned char * key,size_t keylen)5453b6c3722Schristos setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
5463b6c3722Schristos unsigned char* key, size_t keylen)
5473b6c3722Schristos {
5483b6c3722Schristos switch(algo) {
5490cd9f4ecSchristos #if defined(USE_DSA) && defined(USE_SHA1)
5503b6c3722Schristos case LDNS_DSA:
5513b6c3722Schristos case LDNS_DSA_NSEC3:
552*7a540f2bSchristos *evp_key = sldns_key_dsa2pkey_raw(key, keylen);
5533b6c3722Schristos if(!*evp_key) {
554*7a540f2bSchristos verbose(VERB_QUERY, "verify: sldns_key_dsa2pkey failed");
5553b6c3722Schristos return 0;
5563b6c3722Schristos }
5570cd9f4ecSchristos #ifdef HAVE_EVP_DSS1
5583b6c3722Schristos *digest_type = EVP_dss1();
5590cd9f4ecSchristos #else
5600cd9f4ecSchristos *digest_type = EVP_sha1();
5610cd9f4ecSchristos #endif
5623b6c3722Schristos
5633b6c3722Schristos break;
5640cd9f4ecSchristos #endif /* USE_DSA && USE_SHA1 */
5650cd9f4ecSchristos
5660cd9f4ecSchristos #if defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2))
5670cd9f4ecSchristos #ifdef USE_SHA1
5683b6c3722Schristos case LDNS_RSASHA1:
5693b6c3722Schristos case LDNS_RSASHA1_NSEC3:
5700cd9f4ecSchristos #endif
5713b6c3722Schristos #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
5723b6c3722Schristos case LDNS_RSASHA256:
5733b6c3722Schristos #endif
5743b6c3722Schristos #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
5753b6c3722Schristos case LDNS_RSASHA512:
5763b6c3722Schristos #endif
577*7a540f2bSchristos *evp_key = sldns_key_rsa2pkey_raw(key, keylen);
5783b6c3722Schristos if(!*evp_key) {
579*7a540f2bSchristos verbose(VERB_QUERY, "verify: sldns_key_rsa2pkey SHA failed");
5803b6c3722Schristos return 0;
5813b6c3722Schristos }
5823b6c3722Schristos
5833b6c3722Schristos /* select SHA version */
5843b6c3722Schristos #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
5853b6c3722Schristos if(algo == LDNS_RSASHA256)
5863b6c3722Schristos *digest_type = EVP_sha256();
5873b6c3722Schristos else
5883b6c3722Schristos #endif
5893b6c3722Schristos #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
5903b6c3722Schristos if(algo == LDNS_RSASHA512)
5913b6c3722Schristos *digest_type = EVP_sha512();
5923b6c3722Schristos else
5933b6c3722Schristos #endif
5940cd9f4ecSchristos #ifdef USE_SHA1
5953b6c3722Schristos *digest_type = EVP_sha1();
5960cd9f4ecSchristos #else
5970cd9f4ecSchristos { verbose(VERB_QUERY, "no digest available"); return 0; }
5980cd9f4ecSchristos #endif
5993b6c3722Schristos break;
6000cd9f4ecSchristos #endif /* defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) */
6010cd9f4ecSchristos
6023b6c3722Schristos case LDNS_RSAMD5:
603*7a540f2bSchristos *evp_key = sldns_key_rsa2pkey_raw(key, keylen);
6043b6c3722Schristos if(!*evp_key) {
605*7a540f2bSchristos verbose(VERB_QUERY, "verify: sldns_key_rsa2pkey MD5 failed");
6063b6c3722Schristos return 0;
6073b6c3722Schristos }
6083b6c3722Schristos *digest_type = EVP_md5();
6093b6c3722Schristos
6103b6c3722Schristos break;
6113b6c3722Schristos #ifdef USE_GOST
6123b6c3722Schristos case LDNS_ECC_GOST:
6133b6c3722Schristos *evp_key = sldns_gost2pkey_raw(key, keylen);
6143b6c3722Schristos if(!*evp_key) {
6153b6c3722Schristos verbose(VERB_QUERY, "verify: "
6163b6c3722Schristos "sldns_gost2pkey_raw failed");
6173b6c3722Schristos return 0;
6183b6c3722Schristos }
6193b6c3722Schristos *digest_type = EVP_get_digestbyname("md_gost94");
6203b6c3722Schristos if(!*digest_type) {
6213b6c3722Schristos verbose(VERB_QUERY, "verify: "
6223b6c3722Schristos "EVP_getdigest md_gost94 failed");
6233b6c3722Schristos return 0;
6243b6c3722Schristos }
6253b6c3722Schristos break;
6263b6c3722Schristos #endif
6273b6c3722Schristos #ifdef USE_ECDSA
6283b6c3722Schristos case LDNS_ECDSAP256SHA256:
6293b6c3722Schristos *evp_key = sldns_ecdsa2pkey_raw(key, keylen,
6303b6c3722Schristos LDNS_ECDSAP256SHA256);
6313b6c3722Schristos if(!*evp_key) {
6323b6c3722Schristos verbose(VERB_QUERY, "verify: "
6333b6c3722Schristos "sldns_ecdsa2pkey_raw failed");
6343b6c3722Schristos return 0;
6353b6c3722Schristos }
6363b6c3722Schristos #ifdef USE_ECDSA_EVP_WORKAROUND
6370cd9f4ecSchristos *digest_type = &ecdsa_evp_256_md;
6383b6c3722Schristos #else
6393b6c3722Schristos *digest_type = EVP_sha256();
6403b6c3722Schristos #endif
6413b6c3722Schristos break;
6423b6c3722Schristos case LDNS_ECDSAP384SHA384:
6433b6c3722Schristos *evp_key = sldns_ecdsa2pkey_raw(key, keylen,
6443b6c3722Schristos LDNS_ECDSAP384SHA384);
6453b6c3722Schristos if(!*evp_key) {
6463b6c3722Schristos verbose(VERB_QUERY, "verify: "
6473b6c3722Schristos "sldns_ecdsa2pkey_raw failed");
6483b6c3722Schristos return 0;
6493b6c3722Schristos }
6503b6c3722Schristos #ifdef USE_ECDSA_EVP_WORKAROUND
6510cd9f4ecSchristos *digest_type = &ecdsa_evp_384_md;
6523b6c3722Schristos #else
6533b6c3722Schristos *digest_type = EVP_sha384();
6543b6c3722Schristos #endif
6553b6c3722Schristos break;
6563b6c3722Schristos #endif /* USE_ECDSA */
6570cd9f4ecSchristos #ifdef USE_ED25519
6580cd9f4ecSchristos case LDNS_ED25519:
6590cd9f4ecSchristos *evp_key = sldns_ed255192pkey_raw(key, keylen);
6600cd9f4ecSchristos if(!*evp_key) {
6610cd9f4ecSchristos verbose(VERB_QUERY, "verify: "
6620cd9f4ecSchristos "sldns_ed255192pkey_raw failed");
6630cd9f4ecSchristos return 0;
6640cd9f4ecSchristos }
6650cd9f4ecSchristos *digest_type = NULL;
6660cd9f4ecSchristos break;
6670cd9f4ecSchristos #endif /* USE_ED25519 */
6687cd94d69Schristos #ifdef USE_ED448
6697cd94d69Schristos case LDNS_ED448:
6707cd94d69Schristos *evp_key = sldns_ed4482pkey_raw(key, keylen);
6717cd94d69Schristos if(!*evp_key) {
6727cd94d69Schristos verbose(VERB_QUERY, "verify: "
6737cd94d69Schristos "sldns_ed4482pkey_raw failed");
6747cd94d69Schristos return 0;
6757cd94d69Schristos }
6767cd94d69Schristos *digest_type = NULL;
6777cd94d69Schristos break;
6787cd94d69Schristos #endif /* USE_ED448 */
6793b6c3722Schristos default:
6803b6c3722Schristos verbose(VERB_QUERY, "verify: unknown algorithm %d",
6813b6c3722Schristos algo);
6823b6c3722Schristos return 0;
6833b6c3722Schristos }
6843b6c3722Schristos return 1;
6853b6c3722Schristos }
6863b6c3722Schristos
687*7a540f2bSchristos static void
digest_ctx_free(EVP_MD_CTX * ctx,EVP_PKEY * evp_key,unsigned char * sigblock,int dofree,int docrypto_free)688*7a540f2bSchristos digest_ctx_free(EVP_MD_CTX* ctx, EVP_PKEY *evp_key,
689*7a540f2bSchristos unsigned char* sigblock, int dofree, int docrypto_free)
690*7a540f2bSchristos {
691*7a540f2bSchristos #ifdef HAVE_EVP_MD_CTX_NEW
692*7a540f2bSchristos EVP_MD_CTX_destroy(ctx);
693*7a540f2bSchristos #else
694*7a540f2bSchristos EVP_MD_CTX_cleanup(ctx);
695*7a540f2bSchristos free(ctx);
696*7a540f2bSchristos #endif
697*7a540f2bSchristos EVP_PKEY_free(evp_key);
698*7a540f2bSchristos if(dofree) free(sigblock);
699*7a540f2bSchristos else if(docrypto_free) OPENSSL_free(sigblock);
700*7a540f2bSchristos }
701*7a540f2bSchristos
702*7a540f2bSchristos static enum sec_status
digest_error_status(const char * str)703*7a540f2bSchristos digest_error_status(const char *str)
704*7a540f2bSchristos {
705*7a540f2bSchristos unsigned long e = ERR_get_error();
706*7a540f2bSchristos #ifdef EVP_R_INVALID_DIGEST
707*7a540f2bSchristos if (ERR_GET_LIB(e) == ERR_LIB_EVP &&
708*7a540f2bSchristos ERR_GET_REASON(e) == EVP_R_INVALID_DIGEST) {
709*7a540f2bSchristos log_crypto_verbose(VERB_ALGO, str, e);
710*7a540f2bSchristos return sec_status_indeterminate;
711*7a540f2bSchristos }
712*7a540f2bSchristos #endif
713*7a540f2bSchristos log_crypto_verbose(VERB_QUERY, str, e);
714*7a540f2bSchristos return sec_status_unchecked;
715*7a540f2bSchristos }
716*7a540f2bSchristos
7173b6c3722Schristos /**
7183b6c3722Schristos * Check a canonical sig+rrset and signature against a dnskey
7193b6c3722Schristos * @param buf: buffer with data to verify, the first rrsig part and the
7203b6c3722Schristos * canonicalized rrset.
7213b6c3722Schristos * @param algo: DNSKEY algorithm.
7223b6c3722Schristos * @param sigblock: signature rdata field from RRSIG
7233b6c3722Schristos * @param sigblock_len: length of sigblock data.
7243b6c3722Schristos * @param key: public key data from DNSKEY RR.
7253b6c3722Schristos * @param keylen: length of keydata.
7263b6c3722Schristos * @param reason: bogus reason in more detail.
7273b6c3722Schristos * @return secure if verification succeeded, bogus on crypto failure,
728*7a540f2bSchristos * unchecked on format errors and alloc failures, indeterminate
729*7a540f2bSchristos * if digest is not supported by the crypto library (openssl3+ only).
7303b6c3722Schristos */
7313b6c3722Schristos enum sec_status
verify_canonrrset(sldns_buffer * buf,int algo,unsigned char * sigblock,unsigned int sigblock_len,unsigned char * key,unsigned int keylen,char ** reason)7323b6c3722Schristos verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
7333b6c3722Schristos unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
7343b6c3722Schristos char** reason)
7353b6c3722Schristos {
7363b6c3722Schristos const EVP_MD *digest_type;
7373b6c3722Schristos EVP_MD_CTX* ctx;
7383b6c3722Schristos int res, dofree = 0, docrypto_free = 0;
7393b6c3722Schristos EVP_PKEY *evp_key = NULL;
7403b6c3722Schristos
7410cd9f4ecSchristos #ifndef USE_DSA
7420cd9f4ecSchristos if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1))
7430cd9f4ecSchristos return sec_status_secure;
7440cd9f4ecSchristos #endif
7450cd9f4ecSchristos #ifndef USE_SHA1
7460cd9f4ecSchristos if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3))
7470cd9f4ecSchristos return sec_status_secure;
7480cd9f4ecSchristos #endif
7490cd9f4ecSchristos
7503b6c3722Schristos if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) {
7513b6c3722Schristos verbose(VERB_QUERY, "verify: failed to setup key");
7523b6c3722Schristos *reason = "use of key for crypto failed";
7533b6c3722Schristos EVP_PKEY_free(evp_key);
7543b6c3722Schristos return sec_status_bogus;
7553b6c3722Schristos }
7563b6c3722Schristos #ifdef USE_DSA
7573b6c3722Schristos /* if it is a DSA signature in bind format, convert to DER format */
7583b6c3722Schristos if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&
7593b6c3722Schristos sigblock_len == 1+2*SHA_DIGEST_LENGTH) {
7603b6c3722Schristos if(!setup_dsa_sig(&sigblock, &sigblock_len)) {
7613b6c3722Schristos verbose(VERB_QUERY, "verify: failed to setup DSA sig");
7623b6c3722Schristos *reason = "use of key for DSA crypto failed";
7633b6c3722Schristos EVP_PKEY_free(evp_key);
7643b6c3722Schristos return sec_status_bogus;
7653b6c3722Schristos }
7663b6c3722Schristos docrypto_free = 1;
7673b6c3722Schristos }
7683b6c3722Schristos #endif
7693b6c3722Schristos #if defined(USE_ECDSA) && defined(USE_DSA)
7703b6c3722Schristos else
7713b6c3722Schristos #endif
7723b6c3722Schristos #ifdef USE_ECDSA
7733b6c3722Schristos if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) {
7743b6c3722Schristos /* EVP uses ASN prefix on sig, which is not in the wire data */
7753b6c3722Schristos if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) {
7763b6c3722Schristos verbose(VERB_QUERY, "verify: failed to setup ECDSA sig");
7773b6c3722Schristos *reason = "use of signature for ECDSA crypto failed";
7783b6c3722Schristos EVP_PKEY_free(evp_key);
7793b6c3722Schristos return sec_status_bogus;
7803b6c3722Schristos }
7813b6c3722Schristos dofree = 1;
7823b6c3722Schristos }
7833b6c3722Schristos #endif /* USE_ECDSA */
7843b6c3722Schristos
7853b6c3722Schristos /* do the signature cryptography work */
7863b6c3722Schristos #ifdef HAVE_EVP_MD_CTX_NEW
7873b6c3722Schristos ctx = EVP_MD_CTX_new();
7883b6c3722Schristos #else
7893b6c3722Schristos ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx));
7903b6c3722Schristos if(ctx) EVP_MD_CTX_init(ctx);
7913b6c3722Schristos #endif
7923b6c3722Schristos if(!ctx) {
7933b6c3722Schristos log_err("EVP_MD_CTX_new: malloc failure");
7943b6c3722Schristos EVP_PKEY_free(evp_key);
7953b6c3722Schristos if(dofree) free(sigblock);
7960cd9f4ecSchristos else if(docrypto_free) OPENSSL_free(sigblock);
7973b6c3722Schristos return sec_status_unchecked;
7983b6c3722Schristos }
7990cd9f4ecSchristos #ifndef HAVE_EVP_DIGESTVERIFY
8000cd9f4ecSchristos if(EVP_DigestInit(ctx, digest_type) == 0) {
801*7a540f2bSchristos enum sec_status sec;
802*7a540f2bSchristos sec = digest_error_status("verify: EVP_DigestInit failed");
803*7a540f2bSchristos digest_ctx_free(ctx, evp_key, sigblock,
804*7a540f2bSchristos dofree, docrypto_free);
805*7a540f2bSchristos return sec;
8063b6c3722Schristos }
8070cd9f4ecSchristos if(EVP_DigestUpdate(ctx, (unsigned char*)sldns_buffer_begin(buf),
8083b6c3722Schristos (unsigned int)sldns_buffer_limit(buf)) == 0) {
809*7a540f2bSchristos log_crypto_verbose(VERB_QUERY, "verify: EVP_DigestUpdate failed",
810*7a540f2bSchristos ERR_get_error());
811*7a540f2bSchristos digest_ctx_free(ctx, evp_key, sigblock,
812*7a540f2bSchristos dofree, docrypto_free);
8133b6c3722Schristos return sec_status_unchecked;
8143b6c3722Schristos }
8153b6c3722Schristos
8163b6c3722Schristos res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key);
8170cd9f4ecSchristos #else /* HAVE_EVP_DIGESTVERIFY */
8180cd9f4ecSchristos if(EVP_DigestVerifyInit(ctx, NULL, digest_type, NULL, evp_key) == 0) {
819*7a540f2bSchristos enum sec_status sec;
820*7a540f2bSchristos sec = digest_error_status("verify: EVP_DigestVerifyInit failed");
821*7a540f2bSchristos digest_ctx_free(ctx, evp_key, sigblock,
822*7a540f2bSchristos dofree, docrypto_free);
823*7a540f2bSchristos return sec;
8240cd9f4ecSchristos }
8250cd9f4ecSchristos res = EVP_DigestVerify(ctx, sigblock, sigblock_len,
8260cd9f4ecSchristos (unsigned char*)sldns_buffer_begin(buf),
8270cd9f4ecSchristos sldns_buffer_limit(buf));
8280cd9f4ecSchristos #endif
829*7a540f2bSchristos digest_ctx_free(ctx, evp_key, sigblock,
830*7a540f2bSchristos dofree, docrypto_free);
8313b6c3722Schristos
8323b6c3722Schristos if(res == 1) {
8333b6c3722Schristos return sec_status_secure;
8343b6c3722Schristos } else if(res == 0) {
8353b6c3722Schristos verbose(VERB_QUERY, "verify: signature mismatch");
8363b6c3722Schristos *reason = "signature crypto failed";
8373b6c3722Schristos return sec_status_bogus;
8383b6c3722Schristos }
8393b6c3722Schristos
8403b6c3722Schristos log_crypto_error("verify:", ERR_get_error());
8413b6c3722Schristos return sec_status_unchecked;
8423b6c3722Schristos }
8433b6c3722Schristos
8443b6c3722Schristos /**************************************************/
8453b6c3722Schristos #elif defined(HAVE_NSS)
8463b6c3722Schristos /* libnss implementation */
8473b6c3722Schristos /* nss3 */
8483b6c3722Schristos #include "sechash.h"
8493b6c3722Schristos #include "pk11pub.h"
8503b6c3722Schristos #include "keyhi.h"
8513b6c3722Schristos #include "secerr.h"
8523b6c3722Schristos #include "cryptohi.h"
8533b6c3722Schristos /* nspr4 */
8543b6c3722Schristos #include "prerror.h"
8553b6c3722Schristos
8563b6c3722Schristos /* return size of digest if supported, or 0 otherwise */
8573b6c3722Schristos size_t
nsec3_hash_algo_size_supported(int id)8583b6c3722Schristos nsec3_hash_algo_size_supported(int id)
8593b6c3722Schristos {
8603b6c3722Schristos switch(id) {
8613b6c3722Schristos case NSEC3_HASH_SHA1:
8623b6c3722Schristos return SHA1_LENGTH;
8633b6c3722Schristos default:
8643b6c3722Schristos return 0;
8653b6c3722Schristos }
8663b6c3722Schristos }
8673b6c3722Schristos
8683b6c3722Schristos /* perform nsec3 hash. return false on failure */
8693b6c3722Schristos int
secalgo_nsec3_hash(int algo,unsigned char * buf,size_t len,unsigned char * res)8703b6c3722Schristos secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
8713b6c3722Schristos unsigned char* res)
8723b6c3722Schristos {
8733b6c3722Schristos switch(algo) {
8743b6c3722Schristos case NSEC3_HASH_SHA1:
8753b6c3722Schristos (void)HASH_HashBuf(HASH_AlgSHA1, res, buf, (unsigned long)len);
8763b6c3722Schristos return 1;
8773b6c3722Schristos default:
8783b6c3722Schristos return 0;
8793b6c3722Schristos }
8803b6c3722Schristos }
8813b6c3722Schristos
8823b6c3722Schristos void
secalgo_hash_sha256(unsigned char * buf,size_t len,unsigned char * res)8833b6c3722Schristos secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
8843b6c3722Schristos {
8853b6c3722Schristos (void)HASH_HashBuf(HASH_AlgSHA256, res, buf, (unsigned long)len);
8863b6c3722Schristos }
8873b6c3722Schristos
888*7a540f2bSchristos /** the secalgo hash structure */
889*7a540f2bSchristos struct secalgo_hash {
890*7a540f2bSchristos /** hash context */
891*7a540f2bSchristos HASHContext* ctx;
892*7a540f2bSchristos };
893*7a540f2bSchristos
894*7a540f2bSchristos /** create hash struct of type */
secalgo_hash_create_type(HASH_HashType tp)895*7a540f2bSchristos static struct secalgo_hash* secalgo_hash_create_type(HASH_HashType tp)
896*7a540f2bSchristos {
897*7a540f2bSchristos struct secalgo_hash* h = calloc(1, sizeof(*h));
898*7a540f2bSchristos if(!h)
899*7a540f2bSchristos return NULL;
900*7a540f2bSchristos h->ctx = HASH_Create(tp);
901*7a540f2bSchristos if(!h->ctx) {
902*7a540f2bSchristos free(h);
903*7a540f2bSchristos return NULL;
904*7a540f2bSchristos }
905*7a540f2bSchristos return h;
906*7a540f2bSchristos }
907*7a540f2bSchristos
secalgo_hash_create_sha384(void)908*7a540f2bSchristos struct secalgo_hash* secalgo_hash_create_sha384(void)
909*7a540f2bSchristos {
910*7a540f2bSchristos return secalgo_hash_create_type(HASH_AlgSHA384);
911*7a540f2bSchristos }
912*7a540f2bSchristos
secalgo_hash_create_sha512(void)913*7a540f2bSchristos struct secalgo_hash* secalgo_hash_create_sha512(void)
914*7a540f2bSchristos {
915*7a540f2bSchristos return secalgo_hash_create_type(HASH_AlgSHA512);
916*7a540f2bSchristos }
917*7a540f2bSchristos
secalgo_hash_update(struct secalgo_hash * hash,uint8_t * data,size_t len)918*7a540f2bSchristos int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len)
919*7a540f2bSchristos {
920*7a540f2bSchristos HASH_Update(hash->ctx, (unsigned char*)data, (unsigned int)len);
921*7a540f2bSchristos return 1;
922*7a540f2bSchristos }
923*7a540f2bSchristos
secalgo_hash_final(struct secalgo_hash * hash,uint8_t * result,size_t maxlen,size_t * resultlen)924*7a540f2bSchristos int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result,
925*7a540f2bSchristos size_t maxlen, size_t* resultlen)
926*7a540f2bSchristos {
927*7a540f2bSchristos unsigned int reslen = 0;
928*7a540f2bSchristos if(HASH_ResultLenContext(hash->ctx) > (unsigned int)maxlen) {
929*7a540f2bSchristos *resultlen = 0;
930*7a540f2bSchristos log_err("secalgo_hash_final: hash buffer too small");
931*7a540f2bSchristos return 0;
932*7a540f2bSchristos }
933*7a540f2bSchristos HASH_End(hash->ctx, (unsigned char*)result, &reslen,
934*7a540f2bSchristos (unsigned int)maxlen);
935*7a540f2bSchristos *resultlen = (size_t)reslen;
936*7a540f2bSchristos return 1;
937*7a540f2bSchristos }
938*7a540f2bSchristos
secalgo_hash_delete(struct secalgo_hash * hash)939*7a540f2bSchristos void secalgo_hash_delete(struct secalgo_hash* hash)
940*7a540f2bSchristos {
941*7a540f2bSchristos if(!hash) return;
942*7a540f2bSchristos HASH_Destroy(hash->ctx);
943*7a540f2bSchristos free(hash);
944*7a540f2bSchristos }
945*7a540f2bSchristos
9463b6c3722Schristos size_t
ds_digest_size_supported(int algo)9473b6c3722Schristos ds_digest_size_supported(int algo)
9483b6c3722Schristos {
9493b6c3722Schristos /* uses libNSS */
9503b6c3722Schristos switch(algo) {
9510cd9f4ecSchristos #ifdef USE_SHA1
9523b6c3722Schristos case LDNS_SHA1:
9533b6c3722Schristos return SHA1_LENGTH;
9540cd9f4ecSchristos #endif
9553b6c3722Schristos #ifdef USE_SHA2
9563b6c3722Schristos case LDNS_SHA256:
9573b6c3722Schristos return SHA256_LENGTH;
9583b6c3722Schristos #endif
9593b6c3722Schristos #ifdef USE_ECDSA
9603b6c3722Schristos case LDNS_SHA384:
9613b6c3722Schristos return SHA384_LENGTH;
9623b6c3722Schristos #endif
9633b6c3722Schristos /* GOST not supported in NSS */
9643b6c3722Schristos case LDNS_HASH_GOST:
9653b6c3722Schristos default: break;
9663b6c3722Schristos }
9673b6c3722Schristos return 0;
9683b6c3722Schristos }
9693b6c3722Schristos
9703b6c3722Schristos int
secalgo_ds_digest(int algo,unsigned char * buf,size_t len,unsigned char * res)9713b6c3722Schristos secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
9723b6c3722Schristos unsigned char* res)
9733b6c3722Schristos {
9743b6c3722Schristos /* uses libNSS */
9753b6c3722Schristos switch(algo) {
9760cd9f4ecSchristos #ifdef USE_SHA1
9773b6c3722Schristos case LDNS_SHA1:
9783b6c3722Schristos return HASH_HashBuf(HASH_AlgSHA1, res, buf, len)
9793b6c3722Schristos == SECSuccess;
9800cd9f4ecSchristos #endif
9813b6c3722Schristos #if defined(USE_SHA2)
9823b6c3722Schristos case LDNS_SHA256:
9833b6c3722Schristos return HASH_HashBuf(HASH_AlgSHA256, res, buf, len)
9843b6c3722Schristos == SECSuccess;
9853b6c3722Schristos #endif
9863b6c3722Schristos #ifdef USE_ECDSA
9873b6c3722Schristos case LDNS_SHA384:
9883b6c3722Schristos return HASH_HashBuf(HASH_AlgSHA384, res, buf, len)
9893b6c3722Schristos == SECSuccess;
9903b6c3722Schristos #endif
9913b6c3722Schristos case LDNS_HASH_GOST:
9923b6c3722Schristos default:
9933b6c3722Schristos verbose(VERB_QUERY, "unknown DS digest algorithm %d",
9943b6c3722Schristos algo);
9953b6c3722Schristos break;
9963b6c3722Schristos }
9973b6c3722Schristos return 0;
9983b6c3722Schristos }
9993b6c3722Schristos
10003b6c3722Schristos int
dnskey_algo_id_is_supported(int id)10013b6c3722Schristos dnskey_algo_id_is_supported(int id)
10023b6c3722Schristos {
10033b6c3722Schristos /* uses libNSS */
10043b6c3722Schristos switch(id) {
10053b6c3722Schristos case LDNS_RSAMD5:
10063b6c3722Schristos /* RFC 6725 deprecates RSAMD5 */
10073b6c3722Schristos return 0;
10080cd9f4ecSchristos #if defined(USE_SHA1) || defined(USE_SHA2)
10090cd9f4ecSchristos #if defined(USE_DSA) && defined(USE_SHA1)
10103b6c3722Schristos case LDNS_DSA:
10113b6c3722Schristos case LDNS_DSA_NSEC3:
10123b6c3722Schristos #endif
10130cd9f4ecSchristos #ifdef USE_SHA1
10143b6c3722Schristos case LDNS_RSASHA1:
10153b6c3722Schristos case LDNS_RSASHA1_NSEC3:
10160cd9f4ecSchristos #endif
10173b6c3722Schristos #ifdef USE_SHA2
10183b6c3722Schristos case LDNS_RSASHA256:
10193b6c3722Schristos #endif
10203b6c3722Schristos #ifdef USE_SHA2
10213b6c3722Schristos case LDNS_RSASHA512:
10223b6c3722Schristos #endif
10233b6c3722Schristos return 1;
10240cd9f4ecSchristos #endif /* SHA1 or SHA2 */
10250cd9f4ecSchristos
10263b6c3722Schristos #ifdef USE_ECDSA
10273b6c3722Schristos case LDNS_ECDSAP256SHA256:
10283b6c3722Schristos case LDNS_ECDSAP384SHA384:
10293b6c3722Schristos return PK11_TokenExists(CKM_ECDSA);
10303b6c3722Schristos #endif
10313b6c3722Schristos case LDNS_ECC_GOST:
10323b6c3722Schristos default:
10333b6c3722Schristos return 0;
10343b6c3722Schristos }
10353b6c3722Schristos }
10363b6c3722Schristos
10373b6c3722Schristos /* return a new public key for NSS */
nss_key_create(KeyType ktype)10383b6c3722Schristos static SECKEYPublicKey* nss_key_create(KeyType ktype)
10393b6c3722Schristos {
10403b6c3722Schristos SECKEYPublicKey* key;
10413b6c3722Schristos PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
10423b6c3722Schristos if(!arena) {
10433b6c3722Schristos log_err("out of memory, PORT_NewArena failed");
10443b6c3722Schristos return NULL;
10453b6c3722Schristos }
10463b6c3722Schristos key = PORT_ArenaZNew(arena, SECKEYPublicKey);
10473b6c3722Schristos if(!key) {
10483b6c3722Schristos log_err("out of memory, PORT_ArenaZNew failed");
10493b6c3722Schristos PORT_FreeArena(arena, PR_FALSE);
10503b6c3722Schristos return NULL;
10513b6c3722Schristos }
10523b6c3722Schristos key->arena = arena;
10533b6c3722Schristos key->keyType = ktype;
10543b6c3722Schristos key->pkcs11Slot = NULL;
10553b6c3722Schristos key->pkcs11ID = CK_INVALID_HANDLE;
10563b6c3722Schristos return key;
10573b6c3722Schristos }
10583b6c3722Schristos
nss_buf2ecdsa(unsigned char * key,size_t len,int algo)10593b6c3722Schristos static SECKEYPublicKey* nss_buf2ecdsa(unsigned char* key, size_t len, int algo)
10603b6c3722Schristos {
10613b6c3722Schristos SECKEYPublicKey* pk;
10623b6c3722Schristos SECItem pub = {siBuffer, NULL, 0};
10633b6c3722Schristos SECItem params = {siBuffer, NULL, 0};
10643b6c3722Schristos static unsigned char param256[] = {
10653b6c3722Schristos /* OBJECTIDENTIFIER 1.2.840.10045.3.1.7 (P-256)
10663b6c3722Schristos * {iso(1) member-body(2) us(840) ansi-x962(10045) curves(3) prime(1) prime256v1(7)} */
10673b6c3722Schristos 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
10683b6c3722Schristos };
10693b6c3722Schristos static unsigned char param384[] = {
10703b6c3722Schristos /* OBJECTIDENTIFIER 1.3.132.0.34 (P-384)
10713b6c3722Schristos * {iso(1) identified-organization(3) certicom(132) curve(0) ansip384r1(34)} */
10723b6c3722Schristos 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22
10733b6c3722Schristos };
10743b6c3722Schristos unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
10753b6c3722Schristos
10763b6c3722Schristos /* check length, which uncompressed must be 2 bignums */
10773b6c3722Schristos if(algo == LDNS_ECDSAP256SHA256) {
10783b6c3722Schristos if(len != 2*256/8) return NULL;
10793b6c3722Schristos /* ECCurve_X9_62_PRIME_256V1 */
10803b6c3722Schristos } else if(algo == LDNS_ECDSAP384SHA384) {
10813b6c3722Schristos if(len != 2*384/8) return NULL;
10823b6c3722Schristos /* ECCurve_X9_62_PRIME_384R1 */
10833b6c3722Schristos } else return NULL;
10843b6c3722Schristos
10853b6c3722Schristos buf[0] = 0x04; /* POINT_FORM_UNCOMPRESSED */
10863b6c3722Schristos memmove(buf+1, key, len);
10873b6c3722Schristos pub.data = buf;
10883b6c3722Schristos pub.len = len+1;
10893b6c3722Schristos if(algo == LDNS_ECDSAP256SHA256) {
10903b6c3722Schristos params.data = param256;
10913b6c3722Schristos params.len = sizeof(param256);
10923b6c3722Schristos } else {
10933b6c3722Schristos params.data = param384;
10943b6c3722Schristos params.len = sizeof(param384);
10953b6c3722Schristos }
10963b6c3722Schristos
10973b6c3722Schristos pk = nss_key_create(ecKey);
10983b6c3722Schristos if(!pk)
10993b6c3722Schristos return NULL;
11003b6c3722Schristos pk->u.ec.size = (len/2)*8;
11013b6c3722Schristos if(SECITEM_CopyItem(pk->arena, &pk->u.ec.publicValue, &pub)) {
11023b6c3722Schristos SECKEY_DestroyPublicKey(pk);
11033b6c3722Schristos return NULL;
11043b6c3722Schristos }
11053b6c3722Schristos if(SECITEM_CopyItem(pk->arena, &pk->u.ec.DEREncodedParams, ¶ms)) {
11063b6c3722Schristos SECKEY_DestroyPublicKey(pk);
11073b6c3722Schristos return NULL;
11083b6c3722Schristos }
11093b6c3722Schristos
11103b6c3722Schristos return pk;
11113b6c3722Schristos }
11123b6c3722Schristos
1113d0eba39bSchristos #if defined(USE_DSA) && defined(USE_SHA1)
nss_buf2dsa(unsigned char * key,size_t len)11143b6c3722Schristos static SECKEYPublicKey* nss_buf2dsa(unsigned char* key, size_t len)
11153b6c3722Schristos {
11163b6c3722Schristos SECKEYPublicKey* pk;
11173b6c3722Schristos uint8_t T;
11183b6c3722Schristos uint16_t length;
11193b6c3722Schristos uint16_t offset;
11203b6c3722Schristos SECItem Q = {siBuffer, NULL, 0};
11213b6c3722Schristos SECItem P = {siBuffer, NULL, 0};
11223b6c3722Schristos SECItem G = {siBuffer, NULL, 0};
11233b6c3722Schristos SECItem Y = {siBuffer, NULL, 0};
11243b6c3722Schristos
11253b6c3722Schristos if(len == 0)
11263b6c3722Schristos return NULL;
11273b6c3722Schristos T = (uint8_t)key[0];
11283b6c3722Schristos length = (64 + T * 8);
11293b6c3722Schristos offset = 1;
11303b6c3722Schristos
11313b6c3722Schristos if (T > 8) {
11323b6c3722Schristos return NULL;
11333b6c3722Schristos }
11343b6c3722Schristos if(len < (size_t)1 + SHA1_LENGTH + 3*length)
11353b6c3722Schristos return NULL;
11363b6c3722Schristos
11373b6c3722Schristos Q.data = key+offset;
11383b6c3722Schristos Q.len = SHA1_LENGTH;
11393b6c3722Schristos offset += SHA1_LENGTH;
11403b6c3722Schristos
11413b6c3722Schristos P.data = key+offset;
11423b6c3722Schristos P.len = length;
11433b6c3722Schristos offset += length;
11443b6c3722Schristos
11453b6c3722Schristos G.data = key+offset;
11463b6c3722Schristos G.len = length;
11473b6c3722Schristos offset += length;
11483b6c3722Schristos
11493b6c3722Schristos Y.data = key+offset;
11503b6c3722Schristos Y.len = length;
11513b6c3722Schristos offset += length;
11523b6c3722Schristos
11533b6c3722Schristos pk = nss_key_create(dsaKey);
11543b6c3722Schristos if(!pk)
11553b6c3722Schristos return NULL;
11563b6c3722Schristos if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.prime, &P)) {
11573b6c3722Schristos SECKEY_DestroyPublicKey(pk);
11583b6c3722Schristos return NULL;
11593b6c3722Schristos }
11603b6c3722Schristos if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.subPrime, &Q)) {
11613b6c3722Schristos SECKEY_DestroyPublicKey(pk);
11623b6c3722Schristos return NULL;
11633b6c3722Schristos }
11643b6c3722Schristos if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.base, &G)) {
11653b6c3722Schristos SECKEY_DestroyPublicKey(pk);
11663b6c3722Schristos return NULL;
11673b6c3722Schristos }
11683b6c3722Schristos if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.publicValue, &Y)) {
11693b6c3722Schristos SECKEY_DestroyPublicKey(pk);
11703b6c3722Schristos return NULL;
11713b6c3722Schristos }
11723b6c3722Schristos return pk;
11733b6c3722Schristos }
1174d0eba39bSchristos #endif /* USE_DSA && USE_SHA1 */
11753b6c3722Schristos
nss_buf2rsa(unsigned char * key,size_t len)11763b6c3722Schristos static SECKEYPublicKey* nss_buf2rsa(unsigned char* key, size_t len)
11773b6c3722Schristos {
11783b6c3722Schristos SECKEYPublicKey* pk;
11793b6c3722Schristos uint16_t exp;
11803b6c3722Schristos uint16_t offset;
11813b6c3722Schristos uint16_t int16;
11823b6c3722Schristos SECItem modulus = {siBuffer, NULL, 0};
11833b6c3722Schristos SECItem exponent = {siBuffer, NULL, 0};
11843b6c3722Schristos if(len == 0)
11853b6c3722Schristos return NULL;
11863b6c3722Schristos if(key[0] == 0) {
11873b6c3722Schristos if(len < 3)
11883b6c3722Schristos return NULL;
11893b6c3722Schristos /* the exponent is too large so it's places further */
11903b6c3722Schristos memmove(&int16, key+1, 2);
11913b6c3722Schristos exp = ntohs(int16);
11923b6c3722Schristos offset = 3;
11933b6c3722Schristos } else {
11943b6c3722Schristos exp = key[0];
11953b6c3722Schristos offset = 1;
11963b6c3722Schristos }
11973b6c3722Schristos
11983b6c3722Schristos /* key length at least one */
11993b6c3722Schristos if(len < (size_t)offset + exp + 1)
12003b6c3722Schristos return NULL;
12013b6c3722Schristos
12023b6c3722Schristos exponent.data = key+offset;
12033b6c3722Schristos exponent.len = exp;
12043b6c3722Schristos offset += exp;
12053b6c3722Schristos modulus.data = key+offset;
12063b6c3722Schristos modulus.len = (len - offset);
12073b6c3722Schristos
12083b6c3722Schristos pk = nss_key_create(rsaKey);
12093b6c3722Schristos if(!pk)
12103b6c3722Schristos return NULL;
12113b6c3722Schristos if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.modulus, &modulus)) {
12123b6c3722Schristos SECKEY_DestroyPublicKey(pk);
12133b6c3722Schristos return NULL;
12143b6c3722Schristos }
12153b6c3722Schristos if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.publicExponent, &exponent)) {
12163b6c3722Schristos SECKEY_DestroyPublicKey(pk);
12173b6c3722Schristos return NULL;
12183b6c3722Schristos }
12193b6c3722Schristos return pk;
12203b6c3722Schristos }
12213b6c3722Schristos
12223b6c3722Schristos /**
12233b6c3722Schristos * Setup key and digest for verification. Adjust sig if necessary.
12243b6c3722Schristos *
12253b6c3722Schristos * @param algo: key algorithm
12263b6c3722Schristos * @param evp_key: EVP PKEY public key to create.
12273b6c3722Schristos * @param digest_type: digest type to use
12283b6c3722Schristos * @param key: key to setup for.
12293b6c3722Schristos * @param keylen: length of key.
12303b6c3722Schristos * @param prefix: if returned, the ASN prefix for the hashblob.
12313b6c3722Schristos * @param prefixlen: length of the prefix.
12323b6c3722Schristos * @return false on failure.
12333b6c3722Schristos */
12343b6c3722Schristos static int
nss_setup_key_digest(int algo,SECKEYPublicKey ** pubkey,HASH_HashType * htype,unsigned char * key,size_t keylen,unsigned char ** prefix,size_t * prefixlen)12353b6c3722Schristos nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
12363b6c3722Schristos unsigned char* key, size_t keylen, unsigned char** prefix,
12373b6c3722Schristos size_t* prefixlen)
12383b6c3722Schristos {
12393b6c3722Schristos /* uses libNSS */
12403b6c3722Schristos
12413b6c3722Schristos /* hash prefix for md5, RFC2537 */
12423b6c3722Schristos static unsigned char p_md5[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a,
12433b6c3722Schristos 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
12443b6c3722Schristos /* hash prefix to prepend to hash output, from RFC3110 */
12453b6c3722Schristos static unsigned char p_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B,
12463b6c3722Schristos 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14};
12473b6c3722Schristos /* from RFC5702 */
12483b6c3722Schristos static unsigned char p_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
12493b6c3722Schristos 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
12503b6c3722Schristos static unsigned char p_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
12513b6c3722Schristos 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
12523b6c3722Schristos /* from RFC6234 */
12533b6c3722Schristos /* for future RSASHA384 ..
12543b6c3722Schristos static unsigned char p_sha384[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
12553b6c3722Schristos 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
12563b6c3722Schristos */
12573b6c3722Schristos
12583b6c3722Schristos switch(algo) {
12590cd9f4ecSchristos
12600cd9f4ecSchristos #if defined(USE_SHA1) || defined(USE_SHA2)
12610cd9f4ecSchristos #if defined(USE_DSA) && defined(USE_SHA1)
12623b6c3722Schristos case LDNS_DSA:
12633b6c3722Schristos case LDNS_DSA_NSEC3:
12643b6c3722Schristos *pubkey = nss_buf2dsa(key, keylen);
12653b6c3722Schristos if(!*pubkey) {
12663b6c3722Schristos log_err("verify: malloc failure in crypto");
12673b6c3722Schristos return 0;
12683b6c3722Schristos }
12693b6c3722Schristos *htype = HASH_AlgSHA1;
12703b6c3722Schristos /* no prefix for DSA verification */
12713b6c3722Schristos break;
12723b6c3722Schristos #endif
12730cd9f4ecSchristos #ifdef USE_SHA1
12743b6c3722Schristos case LDNS_RSASHA1:
12753b6c3722Schristos case LDNS_RSASHA1_NSEC3:
12760cd9f4ecSchristos #endif
12773b6c3722Schristos #ifdef USE_SHA2
12783b6c3722Schristos case LDNS_RSASHA256:
12793b6c3722Schristos #endif
12803b6c3722Schristos #ifdef USE_SHA2
12813b6c3722Schristos case LDNS_RSASHA512:
12823b6c3722Schristos #endif
12833b6c3722Schristos *pubkey = nss_buf2rsa(key, keylen);
12843b6c3722Schristos if(!*pubkey) {
12853b6c3722Schristos log_err("verify: malloc failure in crypto");
12863b6c3722Schristos return 0;
12873b6c3722Schristos }
12883b6c3722Schristos /* select SHA version */
12893b6c3722Schristos #ifdef USE_SHA2
12903b6c3722Schristos if(algo == LDNS_RSASHA256) {
12913b6c3722Schristos *htype = HASH_AlgSHA256;
12923b6c3722Schristos *prefix = p_sha256;
12933b6c3722Schristos *prefixlen = sizeof(p_sha256);
12943b6c3722Schristos } else
12953b6c3722Schristos #endif
12963b6c3722Schristos #ifdef USE_SHA2
12973b6c3722Schristos if(algo == LDNS_RSASHA512) {
12983b6c3722Schristos *htype = HASH_AlgSHA512;
12993b6c3722Schristos *prefix = p_sha512;
13003b6c3722Schristos *prefixlen = sizeof(p_sha512);
13013b6c3722Schristos } else
13023b6c3722Schristos #endif
13030cd9f4ecSchristos #ifdef USE_SHA1
13043b6c3722Schristos {
13053b6c3722Schristos *htype = HASH_AlgSHA1;
13063b6c3722Schristos *prefix = p_sha1;
13073b6c3722Schristos *prefixlen = sizeof(p_sha1);
13083b6c3722Schristos }
13090cd9f4ecSchristos #else
13100cd9f4ecSchristos {
13110cd9f4ecSchristos verbose(VERB_QUERY, "verify: no digest algo");
13120cd9f4ecSchristos return 0;
13130cd9f4ecSchristos }
13140cd9f4ecSchristos #endif
13153b6c3722Schristos
13163b6c3722Schristos break;
13170cd9f4ecSchristos #endif /* SHA1 or SHA2 */
13180cd9f4ecSchristos
13193b6c3722Schristos case LDNS_RSAMD5:
13203b6c3722Schristos *pubkey = nss_buf2rsa(key, keylen);
13213b6c3722Schristos if(!*pubkey) {
13223b6c3722Schristos log_err("verify: malloc failure in crypto");
13233b6c3722Schristos return 0;
13243b6c3722Schristos }
13253b6c3722Schristos *htype = HASH_AlgMD5;
13263b6c3722Schristos *prefix = p_md5;
13273b6c3722Schristos *prefixlen = sizeof(p_md5);
13283b6c3722Schristos
13293b6c3722Schristos break;
13303b6c3722Schristos #ifdef USE_ECDSA
13313b6c3722Schristos case LDNS_ECDSAP256SHA256:
13323b6c3722Schristos *pubkey = nss_buf2ecdsa(key, keylen,
13333b6c3722Schristos LDNS_ECDSAP256SHA256);
13343b6c3722Schristos if(!*pubkey) {
13353b6c3722Schristos log_err("verify: malloc failure in crypto");
13363b6c3722Schristos return 0;
13373b6c3722Schristos }
13383b6c3722Schristos *htype = HASH_AlgSHA256;
13393b6c3722Schristos /* no prefix for DSA verification */
13403b6c3722Schristos break;
13413b6c3722Schristos case LDNS_ECDSAP384SHA384:
13423b6c3722Schristos *pubkey = nss_buf2ecdsa(key, keylen,
13433b6c3722Schristos LDNS_ECDSAP384SHA384);
13443b6c3722Schristos if(!*pubkey) {
13453b6c3722Schristos log_err("verify: malloc failure in crypto");
13463b6c3722Schristos return 0;
13473b6c3722Schristos }
13483b6c3722Schristos *htype = HASH_AlgSHA384;
13493b6c3722Schristos /* no prefix for DSA verification */
13503b6c3722Schristos break;
13513b6c3722Schristos #endif /* USE_ECDSA */
13523b6c3722Schristos case LDNS_ECC_GOST:
13533b6c3722Schristos default:
13543b6c3722Schristos verbose(VERB_QUERY, "verify: unknown algorithm %d",
13553b6c3722Schristos algo);
13563b6c3722Schristos return 0;
13573b6c3722Schristos }
13583b6c3722Schristos return 1;
13593b6c3722Schristos }
13603b6c3722Schristos
13613b6c3722Schristos /**
13623b6c3722Schristos * Check a canonical sig+rrset and signature against a dnskey
13633b6c3722Schristos * @param buf: buffer with data to verify, the first rrsig part and the
13643b6c3722Schristos * canonicalized rrset.
13653b6c3722Schristos * @param algo: DNSKEY algorithm.
13663b6c3722Schristos * @param sigblock: signature rdata field from RRSIG
13673b6c3722Schristos * @param sigblock_len: length of sigblock data.
13683b6c3722Schristos * @param key: public key data from DNSKEY RR.
13693b6c3722Schristos * @param keylen: length of keydata.
13703b6c3722Schristos * @param reason: bogus reason in more detail.
13713b6c3722Schristos * @return secure if verification succeeded, bogus on crypto failure,
13723b6c3722Schristos * unchecked on format errors and alloc failures.
13733b6c3722Schristos */
13743b6c3722Schristos enum sec_status
verify_canonrrset(sldns_buffer * buf,int algo,unsigned char * sigblock,unsigned int sigblock_len,unsigned char * key,unsigned int keylen,char ** reason)13753b6c3722Schristos verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
13763b6c3722Schristos unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
13773b6c3722Schristos char** reason)
13783b6c3722Schristos {
13793b6c3722Schristos /* uses libNSS */
13803b6c3722Schristos /* large enough for the different hashes */
13813b6c3722Schristos unsigned char hash[HASH_LENGTH_MAX];
13823b6c3722Schristos unsigned char hash2[HASH_LENGTH_MAX*2];
13833b6c3722Schristos HASH_HashType htype = 0;
13843b6c3722Schristos SECKEYPublicKey* pubkey = NULL;
13853b6c3722Schristos SECItem secsig = {siBuffer, sigblock, sigblock_len};
13863b6c3722Schristos SECItem sechash = {siBuffer, hash, 0};
13873b6c3722Schristos SECStatus res;
13883b6c3722Schristos unsigned char* prefix = NULL; /* prefix for hash, RFC3110, RFC5702 */
13893b6c3722Schristos size_t prefixlen = 0;
13903b6c3722Schristos int err;
13913b6c3722Schristos
13923b6c3722Schristos if(!nss_setup_key_digest(algo, &pubkey, &htype, key, keylen,
13933b6c3722Schristos &prefix, &prefixlen)) {
13943b6c3722Schristos verbose(VERB_QUERY, "verify: failed to setup key");
13953b6c3722Schristos *reason = "use of key for crypto failed";
13963b6c3722Schristos SECKEY_DestroyPublicKey(pubkey);
13973b6c3722Schristos return sec_status_bogus;
13983b6c3722Schristos }
13993b6c3722Schristos
14000cd9f4ecSchristos #if defined(USE_DSA) && defined(USE_SHA1)
14013b6c3722Schristos /* need to convert DSA, ECDSA signatures? */
14023b6c3722Schristos if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) {
14033b6c3722Schristos if(sigblock_len == 1+2*SHA1_LENGTH) {
14043b6c3722Schristos secsig.data ++;
14053b6c3722Schristos secsig.len --;
14063b6c3722Schristos } else {
14073b6c3722Schristos SECItem* p = DSAU_DecodeDerSig(&secsig);
14083b6c3722Schristos if(!p) {
14093b6c3722Schristos verbose(VERB_QUERY, "verify: failed DER decode");
14103b6c3722Schristos *reason = "signature DER decode failed";
14113b6c3722Schristos SECKEY_DestroyPublicKey(pubkey);
14123b6c3722Schristos return sec_status_bogus;
14133b6c3722Schristos }
14143b6c3722Schristos if(SECITEM_CopyItem(pubkey->arena, &secsig, p)) {
14153b6c3722Schristos log_err("alloc failure in DER decode");
14163b6c3722Schristos SECKEY_DestroyPublicKey(pubkey);
14173b6c3722Schristos SECITEM_FreeItem(p, PR_TRUE);
14183b6c3722Schristos return sec_status_unchecked;
14193b6c3722Schristos }
14203b6c3722Schristos SECITEM_FreeItem(p, PR_TRUE);
14213b6c3722Schristos }
14223b6c3722Schristos }
14233b6c3722Schristos #endif /* USE_DSA */
14243b6c3722Schristos
14253b6c3722Schristos /* do the signature cryptography work */
14263b6c3722Schristos /* hash the data */
14273b6c3722Schristos sechash.len = HASH_ResultLen(htype);
14283b6c3722Schristos if(sechash.len > sizeof(hash)) {
14293b6c3722Schristos verbose(VERB_QUERY, "verify: hash too large for buffer");
14303b6c3722Schristos SECKEY_DestroyPublicKey(pubkey);
14313b6c3722Schristos return sec_status_unchecked;
14323b6c3722Schristos }
14333b6c3722Schristos if(HASH_HashBuf(htype, hash, (unsigned char*)sldns_buffer_begin(buf),
14343b6c3722Schristos (unsigned int)sldns_buffer_limit(buf)) != SECSuccess) {
14353b6c3722Schristos verbose(VERB_QUERY, "verify: HASH_HashBuf failed");
14363b6c3722Schristos SECKEY_DestroyPublicKey(pubkey);
14373b6c3722Schristos return sec_status_unchecked;
14383b6c3722Schristos }
14393b6c3722Schristos if(prefix) {
14403b6c3722Schristos int hashlen = sechash.len;
14413b6c3722Schristos if(prefixlen+hashlen > sizeof(hash2)) {
14423b6c3722Schristos verbose(VERB_QUERY, "verify: hashprefix too large");
14433b6c3722Schristos SECKEY_DestroyPublicKey(pubkey);
14443b6c3722Schristos return sec_status_unchecked;
14453b6c3722Schristos }
14463b6c3722Schristos sechash.data = hash2;
14473b6c3722Schristos sechash.len = prefixlen+hashlen;
14483b6c3722Schristos memcpy(sechash.data, prefix, prefixlen);
14493b6c3722Schristos memmove(sechash.data+prefixlen, hash, hashlen);
14503b6c3722Schristos }
14513b6c3722Schristos
14523b6c3722Schristos /* verify the signature */
14533b6c3722Schristos res = PK11_Verify(pubkey, &secsig, &sechash, NULL /*wincx*/);
14543b6c3722Schristos SECKEY_DestroyPublicKey(pubkey);
14553b6c3722Schristos
14563b6c3722Schristos if(res == SECSuccess) {
14573b6c3722Schristos return sec_status_secure;
14583b6c3722Schristos }
14593b6c3722Schristos err = PORT_GetError();
14603b6c3722Schristos if(err != SEC_ERROR_BAD_SIGNATURE) {
14613b6c3722Schristos /* failed to verify */
14623b6c3722Schristos verbose(VERB_QUERY, "verify: PK11_Verify failed: %s",
14633b6c3722Schristos PORT_ErrorToString(err));
14643b6c3722Schristos /* if it is not supported, like ECC is removed, we get,
14653b6c3722Schristos * SEC_ERROR_NO_MODULE */
14663b6c3722Schristos if(err == SEC_ERROR_NO_MODULE)
14673b6c3722Schristos return sec_status_unchecked;
14683b6c3722Schristos /* but other errors are commonly returned
14693b6c3722Schristos * for a bad signature from NSS. Thus we return bogus,
14703b6c3722Schristos * not unchecked */
14713b6c3722Schristos *reason = "signature crypto failed";
14723b6c3722Schristos return sec_status_bogus;
14733b6c3722Schristos }
14743b6c3722Schristos verbose(VERB_QUERY, "verify: signature mismatch: %s",
14753b6c3722Schristos PORT_ErrorToString(err));
14763b6c3722Schristos *reason = "signature crypto failed";
14773b6c3722Schristos return sec_status_bogus;
14783b6c3722Schristos }
14793b6c3722Schristos
14803b6c3722Schristos #elif defined(HAVE_NETTLE)
14813b6c3722Schristos
14823b6c3722Schristos #include "sha.h"
14833b6c3722Schristos #include "bignum.h"
14843b6c3722Schristos #include "macros.h"
14853b6c3722Schristos #include "rsa.h"
14863b6c3722Schristos #include "dsa.h"
14870cd9f4ecSchristos #ifdef HAVE_NETTLE_DSA_COMPAT_H
14880cd9f4ecSchristos #include "dsa-compat.h"
14890cd9f4ecSchristos #endif
14903b6c3722Schristos #include "asn1.h"
14913b6c3722Schristos #ifdef USE_ECDSA
14923b6c3722Schristos #include "ecdsa.h"
14933b6c3722Schristos #include "ecc-curve.h"
14943b6c3722Schristos #endif
14950cd9f4ecSchristos #ifdef HAVE_NETTLE_EDDSA_H
14960cd9f4ecSchristos #include "eddsa.h"
14970cd9f4ecSchristos #endif
14983b6c3722Schristos
14993b6c3722Schristos static int
_digest_nettle(int algo,uint8_t * buf,size_t len,unsigned char * res)15003b6c3722Schristos _digest_nettle(int algo, uint8_t* buf, size_t len,
15013b6c3722Schristos unsigned char* res)
15023b6c3722Schristos {
15033b6c3722Schristos switch(algo) {
15043b6c3722Schristos case SHA1_DIGEST_SIZE:
15053b6c3722Schristos {
15063b6c3722Schristos struct sha1_ctx ctx;
15073b6c3722Schristos sha1_init(&ctx);
15083b6c3722Schristos sha1_update(&ctx, len, buf);
15093b6c3722Schristos sha1_digest(&ctx, SHA1_DIGEST_SIZE, res);
15103b6c3722Schristos return 1;
15113b6c3722Schristos }
15123b6c3722Schristos case SHA256_DIGEST_SIZE:
15133b6c3722Schristos {
15143b6c3722Schristos struct sha256_ctx ctx;
15153b6c3722Schristos sha256_init(&ctx);
15163b6c3722Schristos sha256_update(&ctx, len, buf);
15173b6c3722Schristos sha256_digest(&ctx, SHA256_DIGEST_SIZE, res);
15183b6c3722Schristos return 1;
15193b6c3722Schristos }
15203b6c3722Schristos case SHA384_DIGEST_SIZE:
15213b6c3722Schristos {
15223b6c3722Schristos struct sha384_ctx ctx;
15233b6c3722Schristos sha384_init(&ctx);
15243b6c3722Schristos sha384_update(&ctx, len, buf);
15253b6c3722Schristos sha384_digest(&ctx, SHA384_DIGEST_SIZE, res);
15263b6c3722Schristos return 1;
15273b6c3722Schristos }
15283b6c3722Schristos case SHA512_DIGEST_SIZE:
15293b6c3722Schristos {
15303b6c3722Schristos struct sha512_ctx ctx;
15313b6c3722Schristos sha512_init(&ctx);
15323b6c3722Schristos sha512_update(&ctx, len, buf);
15333b6c3722Schristos sha512_digest(&ctx, SHA512_DIGEST_SIZE, res);
15343b6c3722Schristos return 1;
15353b6c3722Schristos }
15363b6c3722Schristos default:
15373b6c3722Schristos break;
15383b6c3722Schristos }
15393b6c3722Schristos return 0;
15403b6c3722Schristos }
15413b6c3722Schristos
15423b6c3722Schristos /* return size of digest if supported, or 0 otherwise */
15433b6c3722Schristos size_t
nsec3_hash_algo_size_supported(int id)15443b6c3722Schristos nsec3_hash_algo_size_supported(int id)
15453b6c3722Schristos {
15463b6c3722Schristos switch(id) {
15473b6c3722Schristos case NSEC3_HASH_SHA1:
15483b6c3722Schristos return SHA1_DIGEST_SIZE;
15493b6c3722Schristos default:
15503b6c3722Schristos return 0;
15513b6c3722Schristos }
15523b6c3722Schristos }
15533b6c3722Schristos
15543b6c3722Schristos /* perform nsec3 hash. return false on failure */
15553b6c3722Schristos int
secalgo_nsec3_hash(int algo,unsigned char * buf,size_t len,unsigned char * res)15563b6c3722Schristos secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
15573b6c3722Schristos unsigned char* res)
15583b6c3722Schristos {
15593b6c3722Schristos switch(algo) {
15603b6c3722Schristos case NSEC3_HASH_SHA1:
15613b6c3722Schristos return _digest_nettle(SHA1_DIGEST_SIZE, (uint8_t*)buf, len,
15623b6c3722Schristos res);
15633b6c3722Schristos default:
15643b6c3722Schristos return 0;
15653b6c3722Schristos }
15663b6c3722Schristos }
15673b6c3722Schristos
15683b6c3722Schristos void
secalgo_hash_sha256(unsigned char * buf,size_t len,unsigned char * res)15693b6c3722Schristos secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
15703b6c3722Schristos {
15713b6c3722Schristos _digest_nettle(SHA256_DIGEST_SIZE, (uint8_t*)buf, len, res);
15723b6c3722Schristos }
15733b6c3722Schristos
1574*7a540f2bSchristos /** secalgo hash structure */
1575*7a540f2bSchristos struct secalgo_hash {
1576*7a540f2bSchristos /** if it is 384 or 512 */
1577*7a540f2bSchristos int active;
1578*7a540f2bSchristos /** context for sha384 */
1579*7a540f2bSchristos struct sha384_ctx ctx384;
1580*7a540f2bSchristos /** context for sha512 */
1581*7a540f2bSchristos struct sha512_ctx ctx512;
1582*7a540f2bSchristos };
1583*7a540f2bSchristos
secalgo_hash_create_sha384(void)1584*7a540f2bSchristos struct secalgo_hash* secalgo_hash_create_sha384(void)
1585*7a540f2bSchristos {
1586*7a540f2bSchristos struct secalgo_hash* h = calloc(1, sizeof(*h));
1587*7a540f2bSchristos if(!h)
1588*7a540f2bSchristos return NULL;
1589*7a540f2bSchristos h->active = 384;
1590*7a540f2bSchristos sha384_init(&h->ctx384);
1591*7a540f2bSchristos return h;
1592*7a540f2bSchristos }
1593*7a540f2bSchristos
secalgo_hash_create_sha512(void)1594*7a540f2bSchristos struct secalgo_hash* secalgo_hash_create_sha512(void)
1595*7a540f2bSchristos {
1596*7a540f2bSchristos struct secalgo_hash* h = calloc(1, sizeof(*h));
1597*7a540f2bSchristos if(!h)
1598*7a540f2bSchristos return NULL;
1599*7a540f2bSchristos h->active = 512;
1600*7a540f2bSchristos sha512_init(&h->ctx512);
1601*7a540f2bSchristos return h;
1602*7a540f2bSchristos }
1603*7a540f2bSchristos
secalgo_hash_update(struct secalgo_hash * hash,uint8_t * data,size_t len)1604*7a540f2bSchristos int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len)
1605*7a540f2bSchristos {
1606*7a540f2bSchristos if(hash->active == 384) {
1607*7a540f2bSchristos sha384_update(&hash->ctx384, len, data);
1608*7a540f2bSchristos } else if(hash->active == 512) {
1609*7a540f2bSchristos sha512_update(&hash->ctx512, len, data);
1610*7a540f2bSchristos } else {
1611*7a540f2bSchristos return 0;
1612*7a540f2bSchristos }
1613*7a540f2bSchristos return 1;
1614*7a540f2bSchristos }
1615*7a540f2bSchristos
secalgo_hash_final(struct secalgo_hash * hash,uint8_t * result,size_t maxlen,size_t * resultlen)1616*7a540f2bSchristos int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result,
1617*7a540f2bSchristos size_t maxlen, size_t* resultlen)
1618*7a540f2bSchristos {
1619*7a540f2bSchristos if(hash->active == 384) {
1620*7a540f2bSchristos if(SHA384_DIGEST_SIZE > maxlen) {
1621*7a540f2bSchristos *resultlen = 0;
1622*7a540f2bSchristos log_err("secalgo_hash_final: hash buffer too small");
1623*7a540f2bSchristos return 0;
1624*7a540f2bSchristos }
1625*7a540f2bSchristos *resultlen = SHA384_DIGEST_SIZE;
1626*7a540f2bSchristos sha384_digest(&hash->ctx384, SHA384_DIGEST_SIZE,
1627*7a540f2bSchristos (unsigned char*)result);
1628*7a540f2bSchristos } else if(hash->active == 512) {
1629*7a540f2bSchristos if(SHA512_DIGEST_SIZE > maxlen) {
1630*7a540f2bSchristos *resultlen = 0;
1631*7a540f2bSchristos log_err("secalgo_hash_final: hash buffer too small");
1632*7a540f2bSchristos return 0;
1633*7a540f2bSchristos }
1634*7a540f2bSchristos *resultlen = SHA512_DIGEST_SIZE;
1635*7a540f2bSchristos sha512_digest(&hash->ctx512, SHA512_DIGEST_SIZE,
1636*7a540f2bSchristos (unsigned char*)result);
1637*7a540f2bSchristos } else {
1638*7a540f2bSchristos *resultlen = 0;
1639*7a540f2bSchristos return 0;
1640*7a540f2bSchristos }
1641*7a540f2bSchristos return 1;
1642*7a540f2bSchristos }
1643*7a540f2bSchristos
secalgo_hash_delete(struct secalgo_hash * hash)1644*7a540f2bSchristos void secalgo_hash_delete(struct secalgo_hash* hash)
1645*7a540f2bSchristos {
1646*7a540f2bSchristos if(!hash) return;
1647*7a540f2bSchristos free(hash);
1648*7a540f2bSchristos }
1649*7a540f2bSchristos
16503b6c3722Schristos /**
16513b6c3722Schristos * Return size of DS digest according to its hash algorithm.
16523b6c3722Schristos * @param algo: DS digest algo.
16533b6c3722Schristos * @return size in bytes of digest, or 0 if not supported.
16543b6c3722Schristos */
16553b6c3722Schristos size_t
ds_digest_size_supported(int algo)16563b6c3722Schristos ds_digest_size_supported(int algo)
16573b6c3722Schristos {
16583b6c3722Schristos switch(algo) {
16593b6c3722Schristos case LDNS_SHA1:
16600cd9f4ecSchristos #ifdef USE_SHA1
16613b6c3722Schristos return SHA1_DIGEST_SIZE;
16620cd9f4ecSchristos #else
16630cd9f4ecSchristos if(fake_sha1) return 20;
16640cd9f4ecSchristos return 0;
16650cd9f4ecSchristos #endif
16663b6c3722Schristos #ifdef USE_SHA2
16673b6c3722Schristos case LDNS_SHA256:
16683b6c3722Schristos return SHA256_DIGEST_SIZE;
16693b6c3722Schristos #endif
16703b6c3722Schristos #ifdef USE_ECDSA
16713b6c3722Schristos case LDNS_SHA384:
16723b6c3722Schristos return SHA384_DIGEST_SIZE;
16733b6c3722Schristos #endif
16743b6c3722Schristos /* GOST not supported */
16753b6c3722Schristos case LDNS_HASH_GOST:
16763b6c3722Schristos default:
16773b6c3722Schristos break;
16783b6c3722Schristos }
16793b6c3722Schristos return 0;
16803b6c3722Schristos }
16813b6c3722Schristos
16823b6c3722Schristos int
secalgo_ds_digest(int algo,unsigned char * buf,size_t len,unsigned char * res)16833b6c3722Schristos secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
16843b6c3722Schristos unsigned char* res)
16853b6c3722Schristos {
16863b6c3722Schristos switch(algo) {
16870cd9f4ecSchristos #ifdef USE_SHA1
16883b6c3722Schristos case LDNS_SHA1:
16893b6c3722Schristos return _digest_nettle(SHA1_DIGEST_SIZE, buf, len, res);
16900cd9f4ecSchristos #endif
16913b6c3722Schristos #if defined(USE_SHA2)
16923b6c3722Schristos case LDNS_SHA256:
16933b6c3722Schristos return _digest_nettle(SHA256_DIGEST_SIZE, buf, len, res);
16943b6c3722Schristos #endif
16953b6c3722Schristos #ifdef USE_ECDSA
16963b6c3722Schristos case LDNS_SHA384:
16973b6c3722Schristos return _digest_nettle(SHA384_DIGEST_SIZE, buf, len, res);
16983b6c3722Schristos
16993b6c3722Schristos #endif
17003b6c3722Schristos case LDNS_HASH_GOST:
17013b6c3722Schristos default:
17023b6c3722Schristos verbose(VERB_QUERY, "unknown DS digest algorithm %d",
17033b6c3722Schristos algo);
17043b6c3722Schristos break;
17053b6c3722Schristos }
17063b6c3722Schristos return 0;
17073b6c3722Schristos }
17083b6c3722Schristos
17093b6c3722Schristos int
dnskey_algo_id_is_supported(int id)17103b6c3722Schristos dnskey_algo_id_is_supported(int id)
17113b6c3722Schristos {
17123b6c3722Schristos /* uses libnettle */
17133b6c3722Schristos switch(id) {
17143b6c3722Schristos case LDNS_DSA:
17153b6c3722Schristos case LDNS_DSA_NSEC3:
1716d0eba39bSchristos #if defined(USE_DSA) && defined(USE_SHA1)
1717d0eba39bSchristos return 1;
1718d0eba39bSchristos #else
1719d0eba39bSchristos if(fake_dsa || fake_sha1) return 1;
1720d0eba39bSchristos return 0;
17213b6c3722Schristos #endif
17223b6c3722Schristos case LDNS_RSASHA1:
17233b6c3722Schristos case LDNS_RSASHA1_NSEC3:
1724d0eba39bSchristos #ifdef USE_SHA1
1725d0eba39bSchristos return 1;
1726d0eba39bSchristos #else
1727d0eba39bSchristos if(fake_sha1) return 1;
1728d0eba39bSchristos return 0;
17290cd9f4ecSchristos #endif
17303b6c3722Schristos #ifdef USE_SHA2
17313b6c3722Schristos case LDNS_RSASHA256:
17323b6c3722Schristos case LDNS_RSASHA512:
17333b6c3722Schristos #endif
17343b6c3722Schristos #ifdef USE_ECDSA
17353b6c3722Schristos case LDNS_ECDSAP256SHA256:
17363b6c3722Schristos case LDNS_ECDSAP384SHA384:
17373b6c3722Schristos #endif
17383b6c3722Schristos return 1;
17390cd9f4ecSchristos #ifdef USE_ED25519
17400cd9f4ecSchristos case LDNS_ED25519:
17410cd9f4ecSchristos return 1;
17420cd9f4ecSchristos #endif
17433b6c3722Schristos case LDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */
17443b6c3722Schristos case LDNS_ECC_GOST:
17453b6c3722Schristos default:
17463b6c3722Schristos return 0;
17473b6c3722Schristos }
17483b6c3722Schristos }
17493b6c3722Schristos
17500cd9f4ecSchristos #if defined(USE_DSA) && defined(USE_SHA1)
17513b6c3722Schristos static char *
_verify_nettle_dsa(sldns_buffer * buf,unsigned char * sigblock,unsigned int sigblock_len,unsigned char * key,unsigned int keylen)17523b6c3722Schristos _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
17533b6c3722Schristos unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
17543b6c3722Schristos {
17553b6c3722Schristos uint8_t digest[SHA1_DIGEST_SIZE];
17560cd9f4ecSchristos uint8_t key_t_value;
17573b6c3722Schristos int res = 0;
17583b6c3722Schristos size_t offset;
17593b6c3722Schristos struct dsa_public_key pubkey;
17603b6c3722Schristos struct dsa_signature signature;
17613b6c3722Schristos unsigned int expected_len;
17623b6c3722Schristos
17633b6c3722Schristos /* Extract DSA signature from the record */
17643b6c3722Schristos nettle_dsa_signature_init(&signature);
17653b6c3722Schristos /* Signature length: 41 bytes - RFC 2536 sec. 3 */
17663b6c3722Schristos if(sigblock_len == 41) {
17673b6c3722Schristos if(key[0] != sigblock[0])
17683b6c3722Schristos return "invalid T value in DSA signature or pubkey";
17693b6c3722Schristos nettle_mpz_set_str_256_u(signature.r, 20, sigblock+1);
17703b6c3722Schristos nettle_mpz_set_str_256_u(signature.s, 20, sigblock+1+20);
17713b6c3722Schristos } else {
17723b6c3722Schristos /* DER encoded, decode the ASN1 notated R and S bignums */
17733b6c3722Schristos /* SEQUENCE { r INTEGER, s INTEGER } */
17743b6c3722Schristos struct asn1_der_iterator i, seq;
17753b6c3722Schristos if(asn1_der_iterator_first(&i, sigblock_len,
17763b6c3722Schristos (uint8_t*)sigblock) != ASN1_ITERATOR_CONSTRUCTED
17773b6c3722Schristos || i.type != ASN1_SEQUENCE)
17783b6c3722Schristos return "malformed DER encoded DSA signature";
17793b6c3722Schristos /* decode this element of i using the seq iterator */
17803b6c3722Schristos if(asn1_der_decode_constructed(&i, &seq) !=
17813b6c3722Schristos ASN1_ITERATOR_PRIMITIVE || seq.type != ASN1_INTEGER)
17823b6c3722Schristos return "malformed DER encoded DSA signature";
17833b6c3722Schristos if(!asn1_der_get_bignum(&seq, signature.r, 20*8))
17843b6c3722Schristos return "malformed DER encoded DSA signature";
17853b6c3722Schristos if(asn1_der_iterator_next(&seq) != ASN1_ITERATOR_PRIMITIVE
17863b6c3722Schristos || seq.type != ASN1_INTEGER)
17873b6c3722Schristos return "malformed DER encoded DSA signature";
17883b6c3722Schristos if(!asn1_der_get_bignum(&seq, signature.s, 20*8))
17893b6c3722Schristos return "malformed DER encoded DSA signature";
17903b6c3722Schristos if(asn1_der_iterator_next(&i) != ASN1_ITERATOR_END)
17913b6c3722Schristos return "malformed DER encoded DSA signature";
17923b6c3722Schristos }
17933b6c3722Schristos
17943b6c3722Schristos /* Validate T values constraints - RFC 2536 sec. 2 & sec. 3 */
17950cd9f4ecSchristos key_t_value = key[0];
17960cd9f4ecSchristos if (key_t_value > 8) {
17973b6c3722Schristos return "invalid T value in DSA pubkey";
17983b6c3722Schristos }
17993b6c3722Schristos
18003b6c3722Schristos /* Pubkey minimum length: 21 bytes - RFC 2536 sec. 2 */
18013b6c3722Schristos if (keylen < 21) {
18023b6c3722Schristos return "DSA pubkey too short";
18033b6c3722Schristos }
18043b6c3722Schristos
18053b6c3722Schristos expected_len = 1 + /* T */
18063b6c3722Schristos 20 + /* Q */
18070cd9f4ecSchristos (64 + key_t_value*8) + /* P */
18080cd9f4ecSchristos (64 + key_t_value*8) + /* G */
18090cd9f4ecSchristos (64 + key_t_value*8); /* Y */
18103b6c3722Schristos if (keylen != expected_len ) {
18113b6c3722Schristos return "invalid DSA pubkey length";
18123b6c3722Schristos }
18133b6c3722Schristos
18143b6c3722Schristos /* Extract DSA pubkey from the record */
18153b6c3722Schristos nettle_dsa_public_key_init(&pubkey);
18163b6c3722Schristos offset = 1;
18173b6c3722Schristos nettle_mpz_set_str_256_u(pubkey.q, 20, key+offset);
18183b6c3722Schristos offset += 20;
18190cd9f4ecSchristos nettle_mpz_set_str_256_u(pubkey.p, (64 + key_t_value*8), key+offset);
18200cd9f4ecSchristos offset += (64 + key_t_value*8);
18210cd9f4ecSchristos nettle_mpz_set_str_256_u(pubkey.g, (64 + key_t_value*8), key+offset);
18220cd9f4ecSchristos offset += (64 + key_t_value*8);
18230cd9f4ecSchristos nettle_mpz_set_str_256_u(pubkey.y, (64 + key_t_value*8), key+offset);
18243b6c3722Schristos
18253b6c3722Schristos /* Digest content of "buf" and verify its DSA signature in "sigblock"*/
18263b6c3722Schristos res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
18273b6c3722Schristos (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
18283b6c3722Schristos res &= dsa_sha1_verify_digest(&pubkey, digest, &signature);
18293b6c3722Schristos
18303b6c3722Schristos /* Clear and return */
18313b6c3722Schristos nettle_dsa_signature_clear(&signature);
18323b6c3722Schristos nettle_dsa_public_key_clear(&pubkey);
18333b6c3722Schristos if (!res)
18343b6c3722Schristos return "DSA signature verification failed";
18353b6c3722Schristos else
18363b6c3722Schristos return NULL;
18373b6c3722Schristos }
18380cd9f4ecSchristos #endif /* USE_DSA */
18393b6c3722Schristos
18403b6c3722Schristos static char *
_verify_nettle_rsa(sldns_buffer * buf,unsigned int digest_size,char * sigblock,unsigned int sigblock_len,uint8_t * key,unsigned int keylen)18413b6c3722Schristos _verify_nettle_rsa(sldns_buffer* buf, unsigned int digest_size, char* sigblock,
18423b6c3722Schristos unsigned int sigblock_len, uint8_t* key, unsigned int keylen)
18433b6c3722Schristos {
18443b6c3722Schristos uint16_t exp_len = 0;
18453b6c3722Schristos size_t exp_offset = 0, mod_offset = 0;
18463b6c3722Schristos struct rsa_public_key pubkey;
18473b6c3722Schristos mpz_t signature;
18483b6c3722Schristos int res = 0;
18493b6c3722Schristos
18503b6c3722Schristos /* RSA pubkey parsing as per RFC 3110 sec. 2 */
18513b6c3722Schristos if( keylen <= 1) {
18523b6c3722Schristos return "null RSA key";
18533b6c3722Schristos }
18543b6c3722Schristos if (key[0] != 0) {
18553b6c3722Schristos /* 1-byte length */
18563b6c3722Schristos exp_len = key[0];
18573b6c3722Schristos exp_offset = 1;
18583b6c3722Schristos } else {
18593b6c3722Schristos /* 1-byte NUL + 2-bytes exponent length */
18603b6c3722Schristos if (keylen < 3) {
18613b6c3722Schristos return "incorrect RSA key length";
18623b6c3722Schristos }
18633b6c3722Schristos exp_len = READ_UINT16(key+1);
18643b6c3722Schristos if (exp_len == 0)
18653b6c3722Schristos return "null RSA exponent length";
18663b6c3722Schristos exp_offset = 3;
18673b6c3722Schristos }
18683b6c3722Schristos /* Check that we are not over-running input length */
18693b6c3722Schristos if (keylen < exp_offset + exp_len + 1) {
18703b6c3722Schristos return "RSA key content shorter than expected";
18713b6c3722Schristos }
18723b6c3722Schristos mod_offset = exp_offset + exp_len;
18733b6c3722Schristos nettle_rsa_public_key_init(&pubkey);
18743b6c3722Schristos pubkey.size = keylen - mod_offset;
18753b6c3722Schristos nettle_mpz_set_str_256_u(pubkey.e, exp_len, &key[exp_offset]);
18763b6c3722Schristos nettle_mpz_set_str_256_u(pubkey.n, pubkey.size, &key[mod_offset]);
18773b6c3722Schristos
18783b6c3722Schristos /* Digest content of "buf" and verify its RSA signature in "sigblock"*/
18793b6c3722Schristos nettle_mpz_init_set_str_256_u(signature, sigblock_len, (uint8_t*)sigblock);
18803b6c3722Schristos switch (digest_size) {
18813b6c3722Schristos case SHA1_DIGEST_SIZE:
18823b6c3722Schristos {
18833b6c3722Schristos uint8_t digest[SHA1_DIGEST_SIZE];
18843b6c3722Schristos res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
18853b6c3722Schristos (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
18863b6c3722Schristos res &= rsa_sha1_verify_digest(&pubkey, digest, signature);
18873b6c3722Schristos break;
18883b6c3722Schristos }
18893b6c3722Schristos case SHA256_DIGEST_SIZE:
18903b6c3722Schristos {
18913b6c3722Schristos uint8_t digest[SHA256_DIGEST_SIZE];
18923b6c3722Schristos res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
18933b6c3722Schristos (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
18943b6c3722Schristos res &= rsa_sha256_verify_digest(&pubkey, digest, signature);
18953b6c3722Schristos break;
18963b6c3722Schristos }
18973b6c3722Schristos case SHA512_DIGEST_SIZE:
18983b6c3722Schristos {
18993b6c3722Schristos uint8_t digest[SHA512_DIGEST_SIZE];
19003b6c3722Schristos res = _digest_nettle(SHA512_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
19013b6c3722Schristos (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
19023b6c3722Schristos res &= rsa_sha512_verify_digest(&pubkey, digest, signature);
19033b6c3722Schristos break;
19043b6c3722Schristos }
19053b6c3722Schristos default:
19063b6c3722Schristos break;
19073b6c3722Schristos }
19083b6c3722Schristos
19093b6c3722Schristos /* Clear and return */
19103b6c3722Schristos nettle_rsa_public_key_clear(&pubkey);
19113b6c3722Schristos mpz_clear(signature);
19123b6c3722Schristos if (!res) {
19133b6c3722Schristos return "RSA signature verification failed";
19143b6c3722Schristos } else {
19153b6c3722Schristos return NULL;
19163b6c3722Schristos }
19173b6c3722Schristos }
19183b6c3722Schristos
19193b6c3722Schristos #ifdef USE_ECDSA
19203b6c3722Schristos static char *
_verify_nettle_ecdsa(sldns_buffer * buf,unsigned int digest_size,unsigned char * sigblock,unsigned int sigblock_len,unsigned char * key,unsigned int keylen)19213b6c3722Schristos _verify_nettle_ecdsa(sldns_buffer* buf, unsigned int digest_size, unsigned char* sigblock,
19223b6c3722Schristos unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
19233b6c3722Schristos {
19243b6c3722Schristos int res = 0;
19253b6c3722Schristos struct ecc_point pubkey;
19263b6c3722Schristos struct dsa_signature signature;
19273b6c3722Schristos
19283b6c3722Schristos /* Always matched strength, as per RFC 6605 sec. 1 */
19293b6c3722Schristos if (sigblock_len != 2*digest_size || keylen != 2*digest_size) {
19303b6c3722Schristos return "wrong ECDSA signature length";
19313b6c3722Schristos }
19323b6c3722Schristos
19333b6c3722Schristos /* Parse ECDSA signature as per RFC 6605 sec. 4 */
19343b6c3722Schristos nettle_dsa_signature_init(&signature);
19353b6c3722Schristos switch (digest_size) {
19363b6c3722Schristos case SHA256_DIGEST_SIZE:
19373b6c3722Schristos {
19383b6c3722Schristos uint8_t digest[SHA256_DIGEST_SIZE];
19393b6c3722Schristos mpz_t x, y;
194001049ae6Schristos nettle_ecc_point_init(&pubkey, nettle_get_secp_256r1());
19413b6c3722Schristos nettle_mpz_init_set_str_256_u(x, SHA256_DIGEST_SIZE, key);
19423b6c3722Schristos nettle_mpz_init_set_str_256_u(y, SHA256_DIGEST_SIZE, key+SHA256_DIGEST_SIZE);
19433b6c3722Schristos nettle_mpz_set_str_256_u(signature.r, SHA256_DIGEST_SIZE, sigblock);
19443b6c3722Schristos nettle_mpz_set_str_256_u(signature.s, SHA256_DIGEST_SIZE, sigblock+SHA256_DIGEST_SIZE);
19453b6c3722Schristos res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
19463b6c3722Schristos (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
19473b6c3722Schristos res &= nettle_ecc_point_set(&pubkey, x, y);
19483b6c3722Schristos res &= nettle_ecdsa_verify (&pubkey, SHA256_DIGEST_SIZE, digest, &signature);
19493b6c3722Schristos mpz_clear(x);
19503b6c3722Schristos mpz_clear(y);
1951d0eba39bSchristos nettle_ecc_point_clear(&pubkey);
19523b6c3722Schristos break;
19533b6c3722Schristos }
19543b6c3722Schristos case SHA384_DIGEST_SIZE:
19553b6c3722Schristos {
19563b6c3722Schristos uint8_t digest[SHA384_DIGEST_SIZE];
19573b6c3722Schristos mpz_t x, y;
195801049ae6Schristos nettle_ecc_point_init(&pubkey, nettle_get_secp_384r1());
19593b6c3722Schristos nettle_mpz_init_set_str_256_u(x, SHA384_DIGEST_SIZE, key);
19603b6c3722Schristos nettle_mpz_init_set_str_256_u(y, SHA384_DIGEST_SIZE, key+SHA384_DIGEST_SIZE);
19613b6c3722Schristos nettle_mpz_set_str_256_u(signature.r, SHA384_DIGEST_SIZE, sigblock);
19623b6c3722Schristos nettle_mpz_set_str_256_u(signature.s, SHA384_DIGEST_SIZE, sigblock+SHA384_DIGEST_SIZE);
19633b6c3722Schristos res = _digest_nettle(SHA384_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
19643b6c3722Schristos (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
19653b6c3722Schristos res &= nettle_ecc_point_set(&pubkey, x, y);
19663b6c3722Schristos res &= nettle_ecdsa_verify (&pubkey, SHA384_DIGEST_SIZE, digest, &signature);
19673b6c3722Schristos mpz_clear(x);
19683b6c3722Schristos mpz_clear(y);
19693b6c3722Schristos nettle_ecc_point_clear(&pubkey);
19703b6c3722Schristos break;
19713b6c3722Schristos }
19723b6c3722Schristos default:
19733b6c3722Schristos return "unknown ECDSA algorithm";
19743b6c3722Schristos }
19753b6c3722Schristos
19763b6c3722Schristos /* Clear and return */
19773b6c3722Schristos nettle_dsa_signature_clear(&signature);
19783b6c3722Schristos if (!res)
19793b6c3722Schristos return "ECDSA signature verification failed";
19803b6c3722Schristos else
19813b6c3722Schristos return NULL;
19823b6c3722Schristos }
19833b6c3722Schristos #endif
19843b6c3722Schristos
19850cd9f4ecSchristos #ifdef USE_ED25519
19860cd9f4ecSchristos static char *
_verify_nettle_ed25519(sldns_buffer * buf,unsigned char * sigblock,unsigned int sigblock_len,unsigned char * key,unsigned int keylen)19870cd9f4ecSchristos _verify_nettle_ed25519(sldns_buffer* buf, unsigned char* sigblock,
19880cd9f4ecSchristos unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
19890cd9f4ecSchristos {
19900cd9f4ecSchristos int res = 0;
19910cd9f4ecSchristos
19920cd9f4ecSchristos if(sigblock_len != ED25519_SIGNATURE_SIZE) {
19930cd9f4ecSchristos return "wrong ED25519 signature length";
19940cd9f4ecSchristos }
19950cd9f4ecSchristos if(keylen != ED25519_KEY_SIZE) {
19960cd9f4ecSchristos return "wrong ED25519 key length";
19970cd9f4ecSchristos }
19980cd9f4ecSchristos
19990cd9f4ecSchristos res = ed25519_sha512_verify((uint8_t*)key, sldns_buffer_limit(buf),
20000cd9f4ecSchristos sldns_buffer_begin(buf), (uint8_t*)sigblock);
20010cd9f4ecSchristos
20020cd9f4ecSchristos if (!res)
20030cd9f4ecSchristos return "ED25519 signature verification failed";
20040cd9f4ecSchristos else
20050cd9f4ecSchristos return NULL;
20060cd9f4ecSchristos }
20070cd9f4ecSchristos #endif
20080cd9f4ecSchristos
20093b6c3722Schristos /**
20103b6c3722Schristos * Check a canonical sig+rrset and signature against a dnskey
20113b6c3722Schristos * @param buf: buffer with data to verify, the first rrsig part and the
20123b6c3722Schristos * canonicalized rrset.
20133b6c3722Schristos * @param algo: DNSKEY algorithm.
20143b6c3722Schristos * @param sigblock: signature rdata field from RRSIG
20153b6c3722Schristos * @param sigblock_len: length of sigblock data.
20163b6c3722Schristos * @param key: public key data from DNSKEY RR.
20173b6c3722Schristos * @param keylen: length of keydata.
20183b6c3722Schristos * @param reason: bogus reason in more detail.
20193b6c3722Schristos * @return secure if verification succeeded, bogus on crypto failure,
20203b6c3722Schristos * unchecked on format errors and alloc failures.
20213b6c3722Schristos */
20223b6c3722Schristos enum sec_status
verify_canonrrset(sldns_buffer * buf,int algo,unsigned char * sigblock,unsigned int sigblock_len,unsigned char * key,unsigned int keylen,char ** reason)20233b6c3722Schristos verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
20243b6c3722Schristos unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
20253b6c3722Schristos char** reason)
20263b6c3722Schristos {
20273b6c3722Schristos unsigned int digest_size = 0;
20283b6c3722Schristos
20293b6c3722Schristos if (sigblock_len == 0 || keylen == 0) {
20303b6c3722Schristos *reason = "null signature";
20313b6c3722Schristos return sec_status_bogus;
20323b6c3722Schristos }
20333b6c3722Schristos
2034d0eba39bSchristos #ifndef USE_DSA
2035d0eba39bSchristos if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1))
2036d0eba39bSchristos return sec_status_secure;
2037d0eba39bSchristos #endif
2038d0eba39bSchristos #ifndef USE_SHA1
2039d0eba39bSchristos if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3))
2040d0eba39bSchristos return sec_status_secure;
2041d0eba39bSchristos #endif
2042d0eba39bSchristos
20433b6c3722Schristos switch(algo) {
20440cd9f4ecSchristos #if defined(USE_DSA) && defined(USE_SHA1)
20453b6c3722Schristos case LDNS_DSA:
20463b6c3722Schristos case LDNS_DSA_NSEC3:
20473b6c3722Schristos *reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen);
20483b6c3722Schristos if (*reason != NULL)
20493b6c3722Schristos return sec_status_bogus;
20503b6c3722Schristos else
20513b6c3722Schristos return sec_status_secure;
20523b6c3722Schristos #endif /* USE_DSA */
20533b6c3722Schristos
20540cd9f4ecSchristos #ifdef USE_SHA1
20553b6c3722Schristos case LDNS_RSASHA1:
20563b6c3722Schristos case LDNS_RSASHA1_NSEC3:
20573b6c3722Schristos digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE);
20580cd9f4ecSchristos #endif
20590cd9f4ecSchristos /* double fallthrough annotation to please gcc parser */
20600cd9f4ecSchristos /* fallthrough */
20613b6c3722Schristos #ifdef USE_SHA2
20620cd9f4ecSchristos /* fallthrough */
20633b6c3722Schristos case LDNS_RSASHA256:
20643b6c3722Schristos digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
20650cd9f4ecSchristos /* fallthrough */
20663b6c3722Schristos case LDNS_RSASHA512:
20673b6c3722Schristos digest_size = (digest_size ? digest_size : SHA512_DIGEST_SIZE);
20683b6c3722Schristos
20693b6c3722Schristos #endif
20703b6c3722Schristos *reason = _verify_nettle_rsa(buf, digest_size, (char*)sigblock,
20713b6c3722Schristos sigblock_len, key, keylen);
20723b6c3722Schristos if (*reason != NULL)
20733b6c3722Schristos return sec_status_bogus;
20743b6c3722Schristos else
20753b6c3722Schristos return sec_status_secure;
20763b6c3722Schristos
20773b6c3722Schristos #ifdef USE_ECDSA
20783b6c3722Schristos case LDNS_ECDSAP256SHA256:
20793b6c3722Schristos digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
20800cd9f4ecSchristos /* fallthrough */
20813b6c3722Schristos case LDNS_ECDSAP384SHA384:
20823b6c3722Schristos digest_size = (digest_size ? digest_size : SHA384_DIGEST_SIZE);
20833b6c3722Schristos *reason = _verify_nettle_ecdsa(buf, digest_size, sigblock,
20843b6c3722Schristos sigblock_len, key, keylen);
20853b6c3722Schristos if (*reason != NULL)
20863b6c3722Schristos return sec_status_bogus;
20873b6c3722Schristos else
20883b6c3722Schristos return sec_status_secure;
20893b6c3722Schristos #endif
20900cd9f4ecSchristos #ifdef USE_ED25519
20910cd9f4ecSchristos case LDNS_ED25519:
20920cd9f4ecSchristos *reason = _verify_nettle_ed25519(buf, sigblock, sigblock_len,
20930cd9f4ecSchristos key, keylen);
20940cd9f4ecSchristos if (*reason != NULL)
20950cd9f4ecSchristos return sec_status_bogus;
20960cd9f4ecSchristos else
20970cd9f4ecSchristos return sec_status_secure;
20980cd9f4ecSchristos #endif
20993b6c3722Schristos case LDNS_RSAMD5:
21003b6c3722Schristos case LDNS_ECC_GOST:
21013b6c3722Schristos default:
21023b6c3722Schristos *reason = "unable to verify signature, unknown algorithm";
21033b6c3722Schristos return sec_status_bogus;
21043b6c3722Schristos }
21053b6c3722Schristos }
21063b6c3722Schristos
21073b6c3722Schristos #endif /* HAVE_SSL or HAVE_NSS or HAVE_NETTLE */
2108