xref: /openbsd-src/sbin/unwind/libunbound/validator/val_secalgo.c (revision 7037e34cdfd270b3989fb1829c7cd3439048bd3a)
1ae8c6e27Sflorian /*
2ae8c6e27Sflorian  * validator/val_secalgo.c - validator security algorithm functions.
3ae8c6e27Sflorian  *
4ae8c6e27Sflorian  * Copyright (c) 2012, NLnet Labs. All rights reserved.
5ae8c6e27Sflorian  *
6ae8c6e27Sflorian  * This software is open source.
7ae8c6e27Sflorian  *
8ae8c6e27Sflorian  * Redistribution and use in source and binary forms, with or without
9ae8c6e27Sflorian  * modification, are permitted provided that the following conditions
10ae8c6e27Sflorian  * are met:
11ae8c6e27Sflorian  *
12ae8c6e27Sflorian  * Redistributions of source code must retain the above copyright notice,
13ae8c6e27Sflorian  * this list of conditions and the following disclaimer.
14ae8c6e27Sflorian  *
15ae8c6e27Sflorian  * Redistributions in binary form must reproduce the above copyright notice,
16ae8c6e27Sflorian  * this list of conditions and the following disclaimer in the documentation
17ae8c6e27Sflorian  * and/or other materials provided with the distribution.
18ae8c6e27Sflorian  *
19ae8c6e27Sflorian  * Neither the name of the NLNET LABS nor the names of its contributors may
20ae8c6e27Sflorian  * be used to endorse or promote products derived from this software without
21ae8c6e27Sflorian  * specific prior written permission.
22ae8c6e27Sflorian  *
23ae8c6e27Sflorian  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24ae8c6e27Sflorian  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25ae8c6e27Sflorian  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26ae8c6e27Sflorian  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27ae8c6e27Sflorian  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28ae8c6e27Sflorian  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29ae8c6e27Sflorian  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30ae8c6e27Sflorian  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31ae8c6e27Sflorian  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32ae8c6e27Sflorian  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33ae8c6e27Sflorian  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34ae8c6e27Sflorian  */
35ae8c6e27Sflorian 
36ae8c6e27Sflorian /**
37ae8c6e27Sflorian  * \file
38ae8c6e27Sflorian  *
39ae8c6e27Sflorian  * This file contains helper functions for the validator module.
40ae8c6e27Sflorian  * These functions take raw data buffers, formatted for crypto verification,
41ae8c6e27Sflorian  * and do the library calls (for the crypto library in use).
42ae8c6e27Sflorian  */
43ae8c6e27Sflorian #include "config.h"
44ae8c6e27Sflorian /* packed_rrset on top to define enum types (forced by c99 standard) */
45ae8c6e27Sflorian #include "util/data/packed_rrset.h"
46ae8c6e27Sflorian #include "validator/val_secalgo.h"
47ae8c6e27Sflorian #include "validator/val_nsec3.h"
48ae8c6e27Sflorian #include "util/log.h"
49ae8c6e27Sflorian #include "sldns/rrdef.h"
50ae8c6e27Sflorian #include "sldns/keyraw.h"
51ae8c6e27Sflorian #include "sldns/sbuffer.h"
52ae8c6e27Sflorian 
53ae8c6e27Sflorian #if !defined(HAVE_SSL) && !defined(HAVE_NSS) && !defined(HAVE_NETTLE)
54ae8c6e27Sflorian #error "Need crypto library to do digital signature cryptography"
55ae8c6e27Sflorian #endif
56ae8c6e27Sflorian 
57d32eb43cSflorian /** fake DSA support for unit tests */
58d32eb43cSflorian int fake_dsa = 0;
59d32eb43cSflorian /** fake SHA1 support for unit tests */
60d32eb43cSflorian int fake_sha1 = 0;
61d32eb43cSflorian 
62ae8c6e27Sflorian /* OpenSSL implementation */
63ae8c6e27Sflorian #ifdef HAVE_SSL
64ae8c6e27Sflorian #ifdef HAVE_OPENSSL_ERR_H
65ae8c6e27Sflorian #include <openssl/err.h>
66ae8c6e27Sflorian #endif
67ae8c6e27Sflorian 
68ae8c6e27Sflorian #ifdef HAVE_OPENSSL_RAND_H
69ae8c6e27Sflorian #include <openssl/rand.h>
70ae8c6e27Sflorian #endif
71ae8c6e27Sflorian 
72ae8c6e27Sflorian #ifdef HAVE_OPENSSL_CONF_H
73ae8c6e27Sflorian #include <openssl/conf.h>
74ae8c6e27Sflorian #endif
75ae8c6e27Sflorian 
76ae8c6e27Sflorian #ifdef HAVE_OPENSSL_ENGINE_H
77ae8c6e27Sflorian #include <openssl/engine.h>
78ae8c6e27Sflorian #endif
79ae8c6e27Sflorian 
80e47fef9eSflorian #if defined(HAVE_OPENSSL_DSA_H) && defined(USE_DSA)
81e47fef9eSflorian #include <openssl/dsa.h>
82e47fef9eSflorian #endif
83e47fef9eSflorian 
84ae8c6e27Sflorian /**
85ae8c6e27Sflorian  * Output a libcrypto openssl error to the logfile.
86ae8c6e27Sflorian  * @param str: string to add to it.
87ae8c6e27Sflorian  * @param e: the error to output, error number from ERR_get_error().
88ae8c6e27Sflorian  */
89ae8c6e27Sflorian static void
90ae8c6e27Sflorian log_crypto_error(const char* str, unsigned long e)
91ae8c6e27Sflorian {
92ae8c6e27Sflorian 	char buf[128];
93ae8c6e27Sflorian 	/* or use ERR_error_string if ERR_error_string_n is not avail TODO */
94ae8c6e27Sflorian 	ERR_error_string_n(e, buf, sizeof(buf));
95ae8c6e27Sflorian 	/* buf now contains */
96ae8c6e27Sflorian 	/* error:[error code]:[library name]:[function name]:[reason string] */
97ae8c6e27Sflorian 	log_err("%s crypto %s", str, buf);
98ae8c6e27Sflorian }
99ae8c6e27Sflorian 
1006d08cb1bSflorian /**
1016d08cb1bSflorian  * Output a libcrypto openssl error to the logfile as a debug message.
1026d08cb1bSflorian  * @param level: debug level to use in verbose() call
1036d08cb1bSflorian  * @param str: string to add to it.
1046d08cb1bSflorian  * @param e: the error to output, error number from ERR_get_error().
1056d08cb1bSflorian  */
1066d08cb1bSflorian static void
1076d08cb1bSflorian log_crypto_verbose(enum verbosity_value level, const char* str, unsigned long e)
1086d08cb1bSflorian {
1096d08cb1bSflorian 	char buf[128];
1106d08cb1bSflorian 	/* or use ERR_error_string if ERR_error_string_n is not avail TODO */
1116d08cb1bSflorian 	ERR_error_string_n(e, buf, sizeof(buf));
1126d08cb1bSflorian 	/* buf now contains */
1136d08cb1bSflorian 	/* error:[error code]:[library name]:[function name]:[reason string] */
1146d08cb1bSflorian 	verbose(level, "%s crypto %s", str, buf);
1156d08cb1bSflorian }
1166d08cb1bSflorian 
117ae8c6e27Sflorian /* return size of digest if supported, or 0 otherwise */
118ae8c6e27Sflorian size_t
119ae8c6e27Sflorian nsec3_hash_algo_size_supported(int id)
120ae8c6e27Sflorian {
121ae8c6e27Sflorian 	switch(id) {
122ae8c6e27Sflorian 	case NSEC3_HASH_SHA1:
123ae8c6e27Sflorian 		return SHA_DIGEST_LENGTH;
124ae8c6e27Sflorian 	default:
125ae8c6e27Sflorian 		return 0;
126ae8c6e27Sflorian 	}
127ae8c6e27Sflorian }
128ae8c6e27Sflorian 
129ae8c6e27Sflorian /* perform nsec3 hash. return false on failure */
130ae8c6e27Sflorian int
131ae8c6e27Sflorian secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
132ae8c6e27Sflorian         unsigned char* res)
133ae8c6e27Sflorian {
134ae8c6e27Sflorian 	switch(algo) {
135ae8c6e27Sflorian 	case NSEC3_HASH_SHA1:
136ae8c6e27Sflorian #ifdef OPENSSL_FIPS
137ae8c6e27Sflorian 		if(!sldns_digest_evp(buf, len, res, EVP_sha1()))
138ae8c6e27Sflorian 			log_crypto_error("could not digest with EVP_sha1",
139ae8c6e27Sflorian 				ERR_get_error());
140ae8c6e27Sflorian #else
141ae8c6e27Sflorian 		(void)SHA1(buf, len, res);
142ae8c6e27Sflorian #endif
143ae8c6e27Sflorian 		return 1;
144ae8c6e27Sflorian 	default:
145ae8c6e27Sflorian 		return 0;
146ae8c6e27Sflorian 	}
147ae8c6e27Sflorian }
148ae8c6e27Sflorian 
149ae8c6e27Sflorian void
150ae8c6e27Sflorian secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
151ae8c6e27Sflorian {
152ae8c6e27Sflorian #ifdef OPENSSL_FIPS
153ae8c6e27Sflorian 	if(!sldns_digest_evp(buf, len, res, EVP_sha256()))
154ae8c6e27Sflorian 		log_crypto_error("could not digest with EVP_sha256",
155ae8c6e27Sflorian 			ERR_get_error());
156ae8c6e27Sflorian #else
157ae8c6e27Sflorian 	(void)SHA256(buf, len, res);
158ae8c6e27Sflorian #endif
159ae8c6e27Sflorian }
160ae8c6e27Sflorian 
161411c5950Sflorian /** hash structure for keeping track of running hashes */
162411c5950Sflorian struct secalgo_hash {
163411c5950Sflorian 	/** the openssl message digest context */
164411c5950Sflorian 	EVP_MD_CTX* ctx;
165411c5950Sflorian };
166411c5950Sflorian 
167411c5950Sflorian /** create secalgo hash with hash type */
168411c5950Sflorian static struct secalgo_hash* secalgo_hash_create_md(const EVP_MD* md)
169411c5950Sflorian {
170411c5950Sflorian 	struct secalgo_hash* h;
171411c5950Sflorian 	if(!md)
172411c5950Sflorian 		return NULL;
173411c5950Sflorian 	h = calloc(1, sizeof(*h));
174411c5950Sflorian 	if(!h)
175411c5950Sflorian 		return NULL;
176411c5950Sflorian 	h->ctx = EVP_MD_CTX_create();
177411c5950Sflorian 	if(!h->ctx) {
178411c5950Sflorian 		free(h);
179411c5950Sflorian 		return NULL;
180411c5950Sflorian 	}
181411c5950Sflorian 	if(!EVP_DigestInit_ex(h->ctx, md, NULL)) {
182411c5950Sflorian 		EVP_MD_CTX_destroy(h->ctx);
183411c5950Sflorian 		free(h);
184411c5950Sflorian 		return NULL;
185411c5950Sflorian 	}
186411c5950Sflorian 	return h;
187411c5950Sflorian }
188411c5950Sflorian 
189411c5950Sflorian struct secalgo_hash* secalgo_hash_create_sha384(void)
190411c5950Sflorian {
191411c5950Sflorian 	return secalgo_hash_create_md(EVP_sha384());
192411c5950Sflorian }
193411c5950Sflorian 
194411c5950Sflorian struct secalgo_hash* secalgo_hash_create_sha512(void)
195411c5950Sflorian {
196411c5950Sflorian 	return secalgo_hash_create_md(EVP_sha512());
197411c5950Sflorian }
198411c5950Sflorian 
199411c5950Sflorian int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len)
200411c5950Sflorian {
201411c5950Sflorian 	return EVP_DigestUpdate(hash->ctx, (unsigned char*)data,
202411c5950Sflorian 		(unsigned int)len);
203411c5950Sflorian }
204411c5950Sflorian 
205411c5950Sflorian int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result,
206411c5950Sflorian         size_t maxlen, size_t* resultlen)
207411c5950Sflorian {
208411c5950Sflorian 	if(EVP_MD_CTX_size(hash->ctx) > (int)maxlen) {
209411c5950Sflorian 		*resultlen = 0;
210411c5950Sflorian 		log_err("secalgo_hash_final: hash buffer too small");
211411c5950Sflorian 		return 0;
212411c5950Sflorian 	}
213411c5950Sflorian 	*resultlen = EVP_MD_CTX_size(hash->ctx);
214411c5950Sflorian 	return EVP_DigestFinal_ex(hash->ctx, result, NULL);
215411c5950Sflorian }
216411c5950Sflorian 
217411c5950Sflorian void secalgo_hash_delete(struct secalgo_hash* hash)
218411c5950Sflorian {
219411c5950Sflorian 	if(!hash) return;
220411c5950Sflorian 	EVP_MD_CTX_destroy(hash->ctx);
221411c5950Sflorian 	free(hash);
222411c5950Sflorian }
223411c5950Sflorian 
224ae8c6e27Sflorian /**
225ae8c6e27Sflorian  * Return size of DS digest according to its hash algorithm.
226ae8c6e27Sflorian  * @param algo: DS digest algo.
227ae8c6e27Sflorian  * @return size in bytes of digest, or 0 if not supported.
228ae8c6e27Sflorian  */
229ae8c6e27Sflorian size_t
230ae8c6e27Sflorian ds_digest_size_supported(int algo)
231ae8c6e27Sflorian {
232ae8c6e27Sflorian 	switch(algo) {
233ae8c6e27Sflorian 		case LDNS_SHA1:
234ae8c6e27Sflorian #if defined(HAVE_EVP_SHA1) && defined(USE_SHA1)
2356d08cb1bSflorian #ifdef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED
2366d08cb1bSflorian 			if (EVP_default_properties_is_fips_enabled(NULL))
2376d08cb1bSflorian 				return 0;
2386d08cb1bSflorian #endif
239ae8c6e27Sflorian 			return SHA_DIGEST_LENGTH;
240ae8c6e27Sflorian #else
241ae8c6e27Sflorian 			if(fake_sha1) return 20;
242ae8c6e27Sflorian 			return 0;
243ae8c6e27Sflorian #endif
244ae8c6e27Sflorian #ifdef HAVE_EVP_SHA256
245ae8c6e27Sflorian 		case LDNS_SHA256:
246ae8c6e27Sflorian 			return SHA256_DIGEST_LENGTH;
247ae8c6e27Sflorian #endif
248ae8c6e27Sflorian #ifdef USE_GOST
249ae8c6e27Sflorian 		case LDNS_HASH_GOST:
250ae8c6e27Sflorian 			/* we support GOST if it can be loaded */
251ae8c6e27Sflorian 			(void)sldns_key_EVP_load_gost_id();
252ae8c6e27Sflorian 			if(EVP_get_digestbyname("md_gost94"))
253ae8c6e27Sflorian 				return 32;
254ae8c6e27Sflorian 			else	return 0;
255ae8c6e27Sflorian #endif
256ae8c6e27Sflorian #ifdef USE_ECDSA
257ae8c6e27Sflorian 		case LDNS_SHA384:
258ae8c6e27Sflorian 			return SHA384_DIGEST_LENGTH;
259ae8c6e27Sflorian #endif
260ae8c6e27Sflorian 		default: break;
261ae8c6e27Sflorian 	}
262ae8c6e27Sflorian 	return 0;
263ae8c6e27Sflorian }
264ae8c6e27Sflorian 
265ae8c6e27Sflorian #ifdef USE_GOST
266ae8c6e27Sflorian /** Perform GOST hash */
267ae8c6e27Sflorian static int
268ae8c6e27Sflorian do_gost94(unsigned char* data, size_t len, unsigned char* dest)
269ae8c6e27Sflorian {
270ae8c6e27Sflorian 	const EVP_MD* md = EVP_get_digestbyname("md_gost94");
271ae8c6e27Sflorian 	if(!md)
272ae8c6e27Sflorian 		return 0;
273ae8c6e27Sflorian 	return sldns_digest_evp(data, (unsigned int)len, dest, md);
274ae8c6e27Sflorian }
275ae8c6e27Sflorian #endif
276ae8c6e27Sflorian 
277ae8c6e27Sflorian int
278ae8c6e27Sflorian secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
279ae8c6e27Sflorian 	unsigned char* res)
280ae8c6e27Sflorian {
281ae8c6e27Sflorian 	switch(algo) {
282ae8c6e27Sflorian #if defined(HAVE_EVP_SHA1) && defined(USE_SHA1)
283ae8c6e27Sflorian 		case LDNS_SHA1:
284ae8c6e27Sflorian #ifdef OPENSSL_FIPS
285ae8c6e27Sflorian 			if(!sldns_digest_evp(buf, len, res, EVP_sha1()))
286ae8c6e27Sflorian 				log_crypto_error("could not digest with EVP_sha1",
287ae8c6e27Sflorian 					ERR_get_error());
288ae8c6e27Sflorian #else
289ae8c6e27Sflorian 			(void)SHA1(buf, len, res);
290ae8c6e27Sflorian #endif
291ae8c6e27Sflorian 			return 1;
292ae8c6e27Sflorian #endif
293ae8c6e27Sflorian #ifdef HAVE_EVP_SHA256
294ae8c6e27Sflorian 		case LDNS_SHA256:
295ae8c6e27Sflorian #ifdef OPENSSL_FIPS
296ae8c6e27Sflorian 			if(!sldns_digest_evp(buf, len, res, EVP_sha256()))
297ae8c6e27Sflorian 				log_crypto_error("could not digest with EVP_sha256",
298ae8c6e27Sflorian 					ERR_get_error());
299ae8c6e27Sflorian #else
300ae8c6e27Sflorian 			(void)SHA256(buf, len, res);
301ae8c6e27Sflorian #endif
302ae8c6e27Sflorian 			return 1;
303ae8c6e27Sflorian #endif
304ae8c6e27Sflorian #ifdef USE_GOST
305ae8c6e27Sflorian 		case LDNS_HASH_GOST:
306ae8c6e27Sflorian 			if(do_gost94(buf, len, res))
307ae8c6e27Sflorian 				return 1;
308ae8c6e27Sflorian 			break;
309ae8c6e27Sflorian #endif
310ae8c6e27Sflorian #ifdef USE_ECDSA
311ae8c6e27Sflorian 		case LDNS_SHA384:
312ae8c6e27Sflorian #ifdef OPENSSL_FIPS
313ae8c6e27Sflorian 			if(!sldns_digest_evp(buf, len, res, EVP_sha384()))
314ae8c6e27Sflorian 				log_crypto_error("could not digest with EVP_sha384",
315ae8c6e27Sflorian 					ERR_get_error());
316ae8c6e27Sflorian #else
317ae8c6e27Sflorian 			(void)SHA384(buf, len, res);
318ae8c6e27Sflorian #endif
319ae8c6e27Sflorian 			return 1;
320ae8c6e27Sflorian #endif
321ae8c6e27Sflorian 		default:
322ae8c6e27Sflorian 			verbose(VERB_QUERY, "unknown DS digest algorithm %d",
323ae8c6e27Sflorian 				algo);
324ae8c6e27Sflorian 			break;
325ae8c6e27Sflorian 	}
326ae8c6e27Sflorian 	return 0;
327ae8c6e27Sflorian }
328ae8c6e27Sflorian 
329ae8c6e27Sflorian /** return true if DNSKEY algorithm id is supported */
330ae8c6e27Sflorian int
331ae8c6e27Sflorian dnskey_algo_id_is_supported(int id)
332ae8c6e27Sflorian {
333ae8c6e27Sflorian 	switch(id) {
334ae8c6e27Sflorian 	case LDNS_RSAMD5:
335ae8c6e27Sflorian 		/* RFC 6725 deprecates RSAMD5 */
336ae8c6e27Sflorian 		return 0;
337ae8c6e27Sflorian 	case LDNS_DSA:
338ae8c6e27Sflorian 	case LDNS_DSA_NSEC3:
339ae8c6e27Sflorian #if defined(USE_DSA) && defined(USE_SHA1)
340ae8c6e27Sflorian 		return 1;
341ae8c6e27Sflorian #else
342ae8c6e27Sflorian 		if(fake_dsa || fake_sha1) return 1;
343ae8c6e27Sflorian 		return 0;
344ae8c6e27Sflorian #endif
345ae8c6e27Sflorian 
346ae8c6e27Sflorian 	case LDNS_RSASHA1:
347ae8c6e27Sflorian 	case LDNS_RSASHA1_NSEC3:
348ae8c6e27Sflorian #ifdef USE_SHA1
3496d08cb1bSflorian #ifdef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED
3506d08cb1bSflorian 		return !EVP_default_properties_is_fips_enabled(NULL);
3516d08cb1bSflorian #else
352ae8c6e27Sflorian 		return 1;
3536d08cb1bSflorian #endif
354ae8c6e27Sflorian #else
355ae8c6e27Sflorian 		if(fake_sha1) return 1;
356ae8c6e27Sflorian 		return 0;
357ae8c6e27Sflorian #endif
358ae8c6e27Sflorian 
359ae8c6e27Sflorian #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
360ae8c6e27Sflorian 	case LDNS_RSASHA256:
361ae8c6e27Sflorian #endif
362ae8c6e27Sflorian #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
363ae8c6e27Sflorian 	case LDNS_RSASHA512:
364ae8c6e27Sflorian #endif
365ae8c6e27Sflorian #ifdef USE_ECDSA
366ae8c6e27Sflorian 	case LDNS_ECDSAP256SHA256:
367ae8c6e27Sflorian 	case LDNS_ECDSAP384SHA384:
368ae8c6e27Sflorian #endif
3696d08cb1bSflorian #if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA)
3706d08cb1bSflorian 		return 1;
3716d08cb1bSflorian #endif
372ae8c6e27Sflorian #ifdef USE_ED25519
373ae8c6e27Sflorian 	case LDNS_ED25519:
374ae8c6e27Sflorian #endif
375ae8c6e27Sflorian #ifdef USE_ED448
376ae8c6e27Sflorian 	case LDNS_ED448:
377ae8c6e27Sflorian #endif
3786d08cb1bSflorian #if defined(USE_ED25519) || defined(USE_ED448)
3796d08cb1bSflorian #ifdef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED
3806d08cb1bSflorian 		return !EVP_default_properties_is_fips_enabled(NULL);
3816d08cb1bSflorian #else
382ae8c6e27Sflorian 		return 1;
383ae8c6e27Sflorian #endif
3846d08cb1bSflorian #endif
385ae8c6e27Sflorian 
386ae8c6e27Sflorian #ifdef USE_GOST
387ae8c6e27Sflorian 	case LDNS_ECC_GOST:
388ae8c6e27Sflorian 		/* we support GOST if it can be loaded */
389ae8c6e27Sflorian 		return sldns_key_EVP_load_gost_id();
390ae8c6e27Sflorian #endif
391ae8c6e27Sflorian 	default:
392ae8c6e27Sflorian 		return 0;
393ae8c6e27Sflorian 	}
394ae8c6e27Sflorian }
395ae8c6e27Sflorian 
396ae8c6e27Sflorian #ifdef USE_DSA
397ae8c6e27Sflorian /**
398ae8c6e27Sflorian  * Setup DSA key digest in DER encoding ...
399ae8c6e27Sflorian  * @param sig: input is signature output alloced ptr (unless failure).
400ae8c6e27Sflorian  * 	caller must free alloced ptr if this routine returns true.
401ae8c6e27Sflorian  * @param len: input is initial siglen, output is output len.
402ae8c6e27Sflorian  * @return false on failure.
403ae8c6e27Sflorian  */
404ae8c6e27Sflorian static int
405ae8c6e27Sflorian setup_dsa_sig(unsigned char** sig, unsigned int* len)
406ae8c6e27Sflorian {
407ae8c6e27Sflorian 	unsigned char* orig = *sig;
408ae8c6e27Sflorian 	unsigned int origlen = *len;
409ae8c6e27Sflorian 	int newlen;
410ae8c6e27Sflorian 	BIGNUM *R, *S;
411ae8c6e27Sflorian 	DSA_SIG *dsasig;
412ae8c6e27Sflorian 
413ae8c6e27Sflorian 	/* extract the R and S field from the sig buffer */
414ae8c6e27Sflorian 	if(origlen < 1 + 2*SHA_DIGEST_LENGTH)
415ae8c6e27Sflorian 		return 0;
416ae8c6e27Sflorian 	R = BN_new();
417ae8c6e27Sflorian 	if(!R) return 0;
418ae8c6e27Sflorian 	(void) BN_bin2bn(orig + 1, SHA_DIGEST_LENGTH, R);
419ae8c6e27Sflorian 	S = BN_new();
420ae8c6e27Sflorian 	if(!S) return 0;
421ae8c6e27Sflorian 	(void) BN_bin2bn(orig + 21, SHA_DIGEST_LENGTH, S);
422ae8c6e27Sflorian 	dsasig = DSA_SIG_new();
423ae8c6e27Sflorian 	if(!dsasig) return 0;
424ae8c6e27Sflorian 
425ae8c6e27Sflorian #ifdef HAVE_DSA_SIG_SET0
426*7037e34cSflorian 	if(!DSA_SIG_set0(dsasig, R, S)) {
427*7037e34cSflorian 		DSA_SIG_free(dsasig);
428*7037e34cSflorian 		return 0;
429*7037e34cSflorian 	}
430ae8c6e27Sflorian #else
43157403691Sflorian #  ifndef S_SPLINT_S
432ae8c6e27Sflorian 	dsasig->r = R;
433ae8c6e27Sflorian 	dsasig->s = S;
43457403691Sflorian #  endif /* S_SPLINT_S */
435ae8c6e27Sflorian #endif
436ae8c6e27Sflorian 	*sig = NULL;
437ae8c6e27Sflorian 	newlen = i2d_DSA_SIG(dsasig, sig);
438ae8c6e27Sflorian 	if(newlen < 0) {
439ae8c6e27Sflorian 		DSA_SIG_free(dsasig);
440ae8c6e27Sflorian 		free(*sig);
441ae8c6e27Sflorian 		return 0;
442ae8c6e27Sflorian 	}
443ae8c6e27Sflorian 	*len = (unsigned int)newlen;
444ae8c6e27Sflorian 	DSA_SIG_free(dsasig);
445ae8c6e27Sflorian 	return 1;
446ae8c6e27Sflorian }
447ae8c6e27Sflorian #endif /* USE_DSA */
448ae8c6e27Sflorian 
449ae8c6e27Sflorian #ifdef USE_ECDSA
450ae8c6e27Sflorian /**
451ae8c6e27Sflorian  * Setup the ECDSA signature in its encoding that the library wants.
452ae8c6e27Sflorian  * Converts from plain numbers to ASN formatted.
453ae8c6e27Sflorian  * @param sig: input is signature, output alloced ptr (unless failure).
454ae8c6e27Sflorian  * 	caller must free alloced ptr if this routine returns true.
455ae8c6e27Sflorian  * @param len: input is initial siglen, output is output len.
456ae8c6e27Sflorian  * @return false on failure.
457ae8c6e27Sflorian  */
458ae8c6e27Sflorian static int
459ae8c6e27Sflorian setup_ecdsa_sig(unsigned char** sig, unsigned int* len)
460ae8c6e27Sflorian {
461ae8c6e27Sflorian         /* convert from two BIGNUMs in the rdata buffer, to ASN notation.
462ae8c6e27Sflorian 	 * ASN preamble: 30440220 <R 32bytefor256> 0220 <S 32bytefor256>
463ae8c6e27Sflorian 	 * the '20' is the length of that field (=bnsize).
464ae8c6e27Sflorian i	 * the '44' is the total remaining length.
465ae8c6e27Sflorian 	 * if negative, start with leading zero.
466ae8c6e27Sflorian 	 * if starts with 00s, remove them from the number.
467ae8c6e27Sflorian 	 */
468ae8c6e27Sflorian         uint8_t pre[] = {0x30, 0x44, 0x02, 0x20};
469ae8c6e27Sflorian         int pre_len = 4;
470ae8c6e27Sflorian         uint8_t mid[] = {0x02, 0x20};
471ae8c6e27Sflorian         int mid_len = 2;
472ae8c6e27Sflorian         int raw_sig_len, r_high, s_high, r_rem=0, s_rem=0;
473ae8c6e27Sflorian 	int bnsize = (int)((*len)/2);
474ae8c6e27Sflorian         unsigned char* d = *sig;
475ae8c6e27Sflorian 	uint8_t* p;
476ae8c6e27Sflorian 	/* if too short or not even length, fails */
477ae8c6e27Sflorian 	if(*len < 16 || bnsize*2 != (int)*len)
478ae8c6e27Sflorian 		return 0;
479ae8c6e27Sflorian 
480ae8c6e27Sflorian         /* strip leading zeroes from r (but not last one) */
481ae8c6e27Sflorian         while(r_rem < bnsize-1 && d[r_rem] == 0)
482ae8c6e27Sflorian                 r_rem++;
483ae8c6e27Sflorian         /* strip leading zeroes from s (but not last one) */
484ae8c6e27Sflorian         while(s_rem < bnsize-1 && d[bnsize+s_rem] == 0)
485ae8c6e27Sflorian                 s_rem++;
486ae8c6e27Sflorian 
487ae8c6e27Sflorian         r_high = ((d[0+r_rem]&0x80)?1:0);
488ae8c6e27Sflorian         s_high = ((d[bnsize+s_rem]&0x80)?1:0);
489ae8c6e27Sflorian         raw_sig_len = pre_len + r_high + bnsize - r_rem + mid_len +
490ae8c6e27Sflorian                 s_high + bnsize - s_rem;
491ae8c6e27Sflorian 	*sig = (unsigned char*)malloc((size_t)raw_sig_len);
492ae8c6e27Sflorian 	if(!*sig)
493ae8c6e27Sflorian 		return 0;
494ae8c6e27Sflorian 	p = (uint8_t*)*sig;
495ae8c6e27Sflorian 	p[0] = pre[0];
496ae8c6e27Sflorian 	p[1] = (uint8_t)(raw_sig_len-2);
497ae8c6e27Sflorian 	p[2] = pre[2];
498ae8c6e27Sflorian 	p[3] = (uint8_t)(bnsize + r_high - r_rem);
499ae8c6e27Sflorian 	p += 4;
500ae8c6e27Sflorian 	if(r_high) {
501ae8c6e27Sflorian 		*p = 0;
502ae8c6e27Sflorian 		p += 1;
503ae8c6e27Sflorian 	}
504ae8c6e27Sflorian 	memmove(p, d+r_rem, (size_t)bnsize-r_rem);
505ae8c6e27Sflorian 	p += bnsize-r_rem;
506ae8c6e27Sflorian 	memmove(p, mid, (size_t)mid_len-1);
507ae8c6e27Sflorian 	p += mid_len-1;
508ae8c6e27Sflorian 	*p = (uint8_t)(bnsize + s_high - s_rem);
509ae8c6e27Sflorian 	p += 1;
510ae8c6e27Sflorian         if(s_high) {
511ae8c6e27Sflorian 		*p = 0;
512ae8c6e27Sflorian 		p += 1;
513ae8c6e27Sflorian 	}
514ae8c6e27Sflorian 	memmove(p, d+bnsize+s_rem, (size_t)bnsize-s_rem);
515ae8c6e27Sflorian 	*len = (unsigned int)raw_sig_len;
516ae8c6e27Sflorian 	return 1;
517ae8c6e27Sflorian }
518ae8c6e27Sflorian #endif /* USE_ECDSA */
519ae8c6e27Sflorian 
520ae8c6e27Sflorian #ifdef USE_ECDSA_EVP_WORKAROUND
521ae8c6e27Sflorian static EVP_MD ecdsa_evp_256_md;
522ae8c6e27Sflorian static EVP_MD ecdsa_evp_384_md;
523ae8c6e27Sflorian void ecdsa_evp_workaround_init(void)
524ae8c6e27Sflorian {
525ae8c6e27Sflorian 	/* openssl before 1.0.0 fixes RSA with the SHA256
526ae8c6e27Sflorian 	 * hash in EVP.  We create one for ecdsa_sha256 */
527ae8c6e27Sflorian 	ecdsa_evp_256_md = *EVP_sha256();
528ae8c6e27Sflorian 	ecdsa_evp_256_md.required_pkey_type[0] = EVP_PKEY_EC;
529ae8c6e27Sflorian 	ecdsa_evp_256_md.verify = (void*)ECDSA_verify;
530ae8c6e27Sflorian 
531ae8c6e27Sflorian 	ecdsa_evp_384_md = *EVP_sha384();
532ae8c6e27Sflorian 	ecdsa_evp_384_md.required_pkey_type[0] = EVP_PKEY_EC;
533ae8c6e27Sflorian 	ecdsa_evp_384_md.verify = (void*)ECDSA_verify;
534ae8c6e27Sflorian }
535ae8c6e27Sflorian #endif /* USE_ECDSA_EVP_WORKAROUND */
536ae8c6e27Sflorian 
537ae8c6e27Sflorian /**
538ae8c6e27Sflorian  * Setup key and digest for verification. Adjust sig if necessary.
539ae8c6e27Sflorian  *
540ae8c6e27Sflorian  * @param algo: key algorithm
541ae8c6e27Sflorian  * @param evp_key: EVP PKEY public key to create.
542ae8c6e27Sflorian  * @param digest_type: digest type to use
543ae8c6e27Sflorian  * @param key: key to setup for.
544ae8c6e27Sflorian  * @param keylen: length of key.
545ae8c6e27Sflorian  * @return false on failure.
546ae8c6e27Sflorian  */
547ae8c6e27Sflorian static int
548ae8c6e27Sflorian setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
549ae8c6e27Sflorian 	unsigned char* key, size_t keylen)
550ae8c6e27Sflorian {
551ae8c6e27Sflorian 	switch(algo) {
552ae8c6e27Sflorian #if defined(USE_DSA) && defined(USE_SHA1)
553ae8c6e27Sflorian 		case LDNS_DSA:
554ae8c6e27Sflorian 		case LDNS_DSA_NSEC3:
555411c5950Sflorian 			*evp_key = sldns_key_dsa2pkey_raw(key, keylen);
556ae8c6e27Sflorian 			if(!*evp_key) {
557411c5950Sflorian 				verbose(VERB_QUERY, "verify: sldns_key_dsa2pkey failed");
558ae8c6e27Sflorian 				return 0;
559ae8c6e27Sflorian 			}
560ae8c6e27Sflorian #ifdef HAVE_EVP_DSS1
561ae8c6e27Sflorian 			*digest_type = EVP_dss1();
562ae8c6e27Sflorian #else
563ae8c6e27Sflorian 			*digest_type = EVP_sha1();
564ae8c6e27Sflorian #endif
565ae8c6e27Sflorian 
566ae8c6e27Sflorian 			break;
567ae8c6e27Sflorian #endif /* USE_DSA && USE_SHA1 */
568ae8c6e27Sflorian 
569ae8c6e27Sflorian #if defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2))
570ae8c6e27Sflorian #ifdef USE_SHA1
571ae8c6e27Sflorian 		case LDNS_RSASHA1:
572ae8c6e27Sflorian 		case LDNS_RSASHA1_NSEC3:
573ae8c6e27Sflorian #endif
574ae8c6e27Sflorian #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
575ae8c6e27Sflorian 		case LDNS_RSASHA256:
576ae8c6e27Sflorian #endif
577ae8c6e27Sflorian #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
578ae8c6e27Sflorian 		case LDNS_RSASHA512:
579ae8c6e27Sflorian #endif
580411c5950Sflorian 			*evp_key = sldns_key_rsa2pkey_raw(key, keylen);
581ae8c6e27Sflorian 			if(!*evp_key) {
582411c5950Sflorian 				verbose(VERB_QUERY, "verify: sldns_key_rsa2pkey SHA failed");
583ae8c6e27Sflorian 				return 0;
584ae8c6e27Sflorian 			}
585ae8c6e27Sflorian 
586ae8c6e27Sflorian 			/* select SHA version */
587ae8c6e27Sflorian #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
588ae8c6e27Sflorian 			if(algo == LDNS_RSASHA256)
589ae8c6e27Sflorian 				*digest_type = EVP_sha256();
590ae8c6e27Sflorian 			else
591ae8c6e27Sflorian #endif
592ae8c6e27Sflorian #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
593ae8c6e27Sflorian 				if(algo == LDNS_RSASHA512)
594ae8c6e27Sflorian 				*digest_type = EVP_sha512();
595ae8c6e27Sflorian 			else
596ae8c6e27Sflorian #endif
597ae8c6e27Sflorian #ifdef USE_SHA1
598ae8c6e27Sflorian 				*digest_type = EVP_sha1();
599ae8c6e27Sflorian #else
600ae8c6e27Sflorian 				{ verbose(VERB_QUERY, "no digest available"); return 0; }
601ae8c6e27Sflorian #endif
602ae8c6e27Sflorian 			break;
603ae8c6e27Sflorian #endif /* defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) */
604ae8c6e27Sflorian 
605ae8c6e27Sflorian 		case LDNS_RSAMD5:
606411c5950Sflorian 			*evp_key = sldns_key_rsa2pkey_raw(key, keylen);
607ae8c6e27Sflorian 			if(!*evp_key) {
608411c5950Sflorian 				verbose(VERB_QUERY, "verify: sldns_key_rsa2pkey MD5 failed");
609ae8c6e27Sflorian 				return 0;
610ae8c6e27Sflorian 			}
611ae8c6e27Sflorian 			*digest_type = EVP_md5();
612ae8c6e27Sflorian 
613ae8c6e27Sflorian 			break;
614ae8c6e27Sflorian #ifdef USE_GOST
615ae8c6e27Sflorian 		case LDNS_ECC_GOST:
616ae8c6e27Sflorian 			*evp_key = sldns_gost2pkey_raw(key, keylen);
617ae8c6e27Sflorian 			if(!*evp_key) {
618ae8c6e27Sflorian 				verbose(VERB_QUERY, "verify: "
619ae8c6e27Sflorian 					"sldns_gost2pkey_raw failed");
620ae8c6e27Sflorian 				return 0;
621ae8c6e27Sflorian 			}
622ae8c6e27Sflorian 			*digest_type = EVP_get_digestbyname("md_gost94");
623ae8c6e27Sflorian 			if(!*digest_type) {
624ae8c6e27Sflorian 				verbose(VERB_QUERY, "verify: "
625ae8c6e27Sflorian 					"EVP_getdigest md_gost94 failed");
626ae8c6e27Sflorian 				return 0;
627ae8c6e27Sflorian 			}
628ae8c6e27Sflorian 			break;
629ae8c6e27Sflorian #endif
630ae8c6e27Sflorian #ifdef USE_ECDSA
631ae8c6e27Sflorian 		case LDNS_ECDSAP256SHA256:
632ae8c6e27Sflorian 			*evp_key = sldns_ecdsa2pkey_raw(key, keylen,
633ae8c6e27Sflorian 				LDNS_ECDSAP256SHA256);
634ae8c6e27Sflorian 			if(!*evp_key) {
635ae8c6e27Sflorian 				verbose(VERB_QUERY, "verify: "
636ae8c6e27Sflorian 					"sldns_ecdsa2pkey_raw failed");
637ae8c6e27Sflorian 				return 0;
638ae8c6e27Sflorian 			}
639ae8c6e27Sflorian #ifdef USE_ECDSA_EVP_WORKAROUND
640ae8c6e27Sflorian 			*digest_type = &ecdsa_evp_256_md;
641ae8c6e27Sflorian #else
642ae8c6e27Sflorian 			*digest_type = EVP_sha256();
643ae8c6e27Sflorian #endif
644ae8c6e27Sflorian 			break;
645ae8c6e27Sflorian 		case LDNS_ECDSAP384SHA384:
646ae8c6e27Sflorian 			*evp_key = sldns_ecdsa2pkey_raw(key, keylen,
647ae8c6e27Sflorian 				LDNS_ECDSAP384SHA384);
648ae8c6e27Sflorian 			if(!*evp_key) {
649ae8c6e27Sflorian 				verbose(VERB_QUERY, "verify: "
650ae8c6e27Sflorian 					"sldns_ecdsa2pkey_raw failed");
651ae8c6e27Sflorian 				return 0;
652ae8c6e27Sflorian 			}
653ae8c6e27Sflorian #ifdef USE_ECDSA_EVP_WORKAROUND
654ae8c6e27Sflorian 			*digest_type = &ecdsa_evp_384_md;
655ae8c6e27Sflorian #else
656ae8c6e27Sflorian 			*digest_type = EVP_sha384();
657ae8c6e27Sflorian #endif
658ae8c6e27Sflorian 			break;
659ae8c6e27Sflorian #endif /* USE_ECDSA */
660ae8c6e27Sflorian #ifdef USE_ED25519
661ae8c6e27Sflorian 		case LDNS_ED25519:
662ae8c6e27Sflorian 			*evp_key = sldns_ed255192pkey_raw(key, keylen);
663ae8c6e27Sflorian 			if(!*evp_key) {
664ae8c6e27Sflorian 				verbose(VERB_QUERY, "verify: "
665ae8c6e27Sflorian 					"sldns_ed255192pkey_raw failed");
666ae8c6e27Sflorian 				return 0;
667ae8c6e27Sflorian 			}
668ae8c6e27Sflorian 			*digest_type = NULL;
669ae8c6e27Sflorian 			break;
670ae8c6e27Sflorian #endif /* USE_ED25519 */
671ae8c6e27Sflorian #ifdef USE_ED448
672ae8c6e27Sflorian 		case LDNS_ED448:
673ae8c6e27Sflorian 			*evp_key = sldns_ed4482pkey_raw(key, keylen);
674ae8c6e27Sflorian 			if(!*evp_key) {
675ae8c6e27Sflorian 				verbose(VERB_QUERY, "verify: "
676ae8c6e27Sflorian 					"sldns_ed4482pkey_raw failed");
677ae8c6e27Sflorian 				return 0;
678ae8c6e27Sflorian 			}
679ae8c6e27Sflorian 			*digest_type = NULL;
680ae8c6e27Sflorian 			break;
681ae8c6e27Sflorian #endif /* USE_ED448 */
682ae8c6e27Sflorian 		default:
683ae8c6e27Sflorian 			verbose(VERB_QUERY, "verify: unknown algorithm %d",
684ae8c6e27Sflorian 				algo);
685ae8c6e27Sflorian 			return 0;
686ae8c6e27Sflorian 	}
687ae8c6e27Sflorian 	return 1;
688ae8c6e27Sflorian }
689ae8c6e27Sflorian 
6906d08cb1bSflorian static void
6916d08cb1bSflorian digest_ctx_free(EVP_MD_CTX* ctx, EVP_PKEY *evp_key,
6926d08cb1bSflorian 	unsigned char* sigblock, int dofree, int docrypto_free)
6936d08cb1bSflorian {
6946d08cb1bSflorian #ifdef HAVE_EVP_MD_CTX_NEW
6956d08cb1bSflorian 	EVP_MD_CTX_destroy(ctx);
6966d08cb1bSflorian #else
6976d08cb1bSflorian 	EVP_MD_CTX_cleanup(ctx);
6986d08cb1bSflorian 	free(ctx);
6996d08cb1bSflorian #endif
7006d08cb1bSflorian 	EVP_PKEY_free(evp_key);
7016d08cb1bSflorian 	if(dofree) free(sigblock);
7026d08cb1bSflorian 	else if(docrypto_free) OPENSSL_free(sigblock);
7036d08cb1bSflorian }
7046d08cb1bSflorian 
7056d08cb1bSflorian static enum sec_status
7066d08cb1bSflorian digest_error_status(const char *str)
7076d08cb1bSflorian {
7086d08cb1bSflorian 	unsigned long e = ERR_get_error();
7096d08cb1bSflorian #ifdef EVP_R_INVALID_DIGEST
7106d08cb1bSflorian 	if (ERR_GET_LIB(e) == ERR_LIB_EVP &&
7116d08cb1bSflorian 		ERR_GET_REASON(e) == EVP_R_INVALID_DIGEST) {
7126d08cb1bSflorian 		log_crypto_verbose(VERB_ALGO, str, e);
7136d08cb1bSflorian 		return sec_status_indeterminate;
7146d08cb1bSflorian 	}
7156d08cb1bSflorian #endif
7166d08cb1bSflorian 	log_crypto_verbose(VERB_QUERY, str, e);
7176d08cb1bSflorian 	return sec_status_unchecked;
7186d08cb1bSflorian }
7196d08cb1bSflorian 
720ae8c6e27Sflorian /**
721ae8c6e27Sflorian  * Check a canonical sig+rrset and signature against a dnskey
722ae8c6e27Sflorian  * @param buf: buffer with data to verify, the first rrsig part and the
723ae8c6e27Sflorian  *	canonicalized rrset.
724ae8c6e27Sflorian  * @param algo: DNSKEY algorithm.
725ae8c6e27Sflorian  * @param sigblock: signature rdata field from RRSIG
726ae8c6e27Sflorian  * @param sigblock_len: length of sigblock data.
727ae8c6e27Sflorian  * @param key: public key data from DNSKEY RR.
728ae8c6e27Sflorian  * @param keylen: length of keydata.
729ae8c6e27Sflorian  * @param reason: bogus reason in more detail.
730ae8c6e27Sflorian  * @return secure if verification succeeded, bogus on crypto failure,
7316d08cb1bSflorian  *	unchecked on format errors and alloc failures, indeterminate
7326d08cb1bSflorian  *	if digest is not supported by the crypto library (openssl3+ only).
733ae8c6e27Sflorian  */
734ae8c6e27Sflorian enum sec_status
735ae8c6e27Sflorian verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
736ae8c6e27Sflorian 	unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
737ae8c6e27Sflorian 	char** reason)
738ae8c6e27Sflorian {
739ae8c6e27Sflorian 	const EVP_MD *digest_type;
740ae8c6e27Sflorian 	EVP_MD_CTX* ctx;
741ae8c6e27Sflorian 	int res, dofree = 0, docrypto_free = 0;
742ae8c6e27Sflorian 	EVP_PKEY *evp_key = NULL;
743ae8c6e27Sflorian 
744ae8c6e27Sflorian #ifndef USE_DSA
745ae8c6e27Sflorian 	if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1))
746ae8c6e27Sflorian 		return sec_status_secure;
747ae8c6e27Sflorian #endif
748ae8c6e27Sflorian #ifndef USE_SHA1
749ae8c6e27Sflorian 	if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3))
750ae8c6e27Sflorian 		return sec_status_secure;
751ae8c6e27Sflorian #endif
752ae8c6e27Sflorian 
753ae8c6e27Sflorian 	if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) {
754ae8c6e27Sflorian 		verbose(VERB_QUERY, "verify: failed to setup key");
755ae8c6e27Sflorian 		*reason = "use of key for crypto failed";
756ae8c6e27Sflorian 		EVP_PKEY_free(evp_key);
757ae8c6e27Sflorian 		return sec_status_bogus;
758ae8c6e27Sflorian 	}
759ae8c6e27Sflorian #ifdef USE_DSA
760ae8c6e27Sflorian 	/* if it is a DSA signature in bind format, convert to DER format */
761ae8c6e27Sflorian 	if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&
762ae8c6e27Sflorian 		sigblock_len == 1+2*SHA_DIGEST_LENGTH) {
763ae8c6e27Sflorian 		if(!setup_dsa_sig(&sigblock, &sigblock_len)) {
764ae8c6e27Sflorian 			verbose(VERB_QUERY, "verify: failed to setup DSA sig");
765ae8c6e27Sflorian 			*reason = "use of key for DSA crypto failed";
766ae8c6e27Sflorian 			EVP_PKEY_free(evp_key);
767ae8c6e27Sflorian 			return sec_status_bogus;
768ae8c6e27Sflorian 		}
769ae8c6e27Sflorian 		docrypto_free = 1;
770ae8c6e27Sflorian 	}
771ae8c6e27Sflorian #endif
772ae8c6e27Sflorian #if defined(USE_ECDSA) && defined(USE_DSA)
773ae8c6e27Sflorian 	else
774ae8c6e27Sflorian #endif
775ae8c6e27Sflorian #ifdef USE_ECDSA
776ae8c6e27Sflorian 	if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) {
777ae8c6e27Sflorian 		/* EVP uses ASN prefix on sig, which is not in the wire data */
778ae8c6e27Sflorian 		if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) {
779ae8c6e27Sflorian 			verbose(VERB_QUERY, "verify: failed to setup ECDSA sig");
780ae8c6e27Sflorian 			*reason = "use of signature for ECDSA crypto failed";
781ae8c6e27Sflorian 			EVP_PKEY_free(evp_key);
782ae8c6e27Sflorian 			return sec_status_bogus;
783ae8c6e27Sflorian 		}
784ae8c6e27Sflorian 		dofree = 1;
785ae8c6e27Sflorian 	}
786ae8c6e27Sflorian #endif /* USE_ECDSA */
787ae8c6e27Sflorian 
788ae8c6e27Sflorian 	/* do the signature cryptography work */
789ae8c6e27Sflorian #ifdef HAVE_EVP_MD_CTX_NEW
790ae8c6e27Sflorian 	ctx = EVP_MD_CTX_new();
791ae8c6e27Sflorian #else
792ae8c6e27Sflorian 	ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx));
793ae8c6e27Sflorian 	if(ctx) EVP_MD_CTX_init(ctx);
794ae8c6e27Sflorian #endif
795ae8c6e27Sflorian 	if(!ctx) {
796ae8c6e27Sflorian 		log_err("EVP_MD_CTX_new: malloc failure");
797ae8c6e27Sflorian 		EVP_PKEY_free(evp_key);
798ae8c6e27Sflorian 		if(dofree) free(sigblock);
799ae8c6e27Sflorian 		else if(docrypto_free) OPENSSL_free(sigblock);
800ae8c6e27Sflorian 		return sec_status_unchecked;
801ae8c6e27Sflorian 	}
802ae8c6e27Sflorian #ifndef HAVE_EVP_DIGESTVERIFY
803ae8c6e27Sflorian 	if(EVP_DigestInit(ctx, digest_type) == 0) {
8046d08cb1bSflorian 		enum sec_status sec;
8056d08cb1bSflorian 		sec = digest_error_status("verify: EVP_DigestInit failed");
8066d08cb1bSflorian 		digest_ctx_free(ctx, evp_key, sigblock,
8076d08cb1bSflorian 			dofree, docrypto_free);
8086d08cb1bSflorian 		return sec;
809ae8c6e27Sflorian 	}
810ae8c6e27Sflorian 	if(EVP_DigestUpdate(ctx, (unsigned char*)sldns_buffer_begin(buf),
811ae8c6e27Sflorian 		(unsigned int)sldns_buffer_limit(buf)) == 0) {
8126d08cb1bSflorian 		log_crypto_verbose(VERB_QUERY, "verify: EVP_DigestUpdate failed",
8136d08cb1bSflorian 			ERR_get_error());
8146d08cb1bSflorian 		digest_ctx_free(ctx, evp_key, sigblock,
8156d08cb1bSflorian 			dofree, docrypto_free);
816ae8c6e27Sflorian 		return sec_status_unchecked;
817ae8c6e27Sflorian 	}
818ae8c6e27Sflorian 
819ae8c6e27Sflorian 	res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key);
820ae8c6e27Sflorian #else /* HAVE_EVP_DIGESTVERIFY */
821ae8c6e27Sflorian 	if(EVP_DigestVerifyInit(ctx, NULL, digest_type, NULL, evp_key) == 0) {
8226d08cb1bSflorian 		enum sec_status sec;
8236d08cb1bSflorian 		sec = digest_error_status("verify: EVP_DigestVerifyInit failed");
8246d08cb1bSflorian 		digest_ctx_free(ctx, evp_key, sigblock,
8256d08cb1bSflorian 			dofree, docrypto_free);
8266d08cb1bSflorian 		return sec;
827ae8c6e27Sflorian 	}
828ae8c6e27Sflorian 	res = EVP_DigestVerify(ctx, sigblock, sigblock_len,
829ae8c6e27Sflorian 		(unsigned char*)sldns_buffer_begin(buf),
830ae8c6e27Sflorian 		sldns_buffer_limit(buf));
831ae8c6e27Sflorian #endif
8326d08cb1bSflorian 	digest_ctx_free(ctx, evp_key, sigblock,
8336d08cb1bSflorian 		dofree, docrypto_free);
834ae8c6e27Sflorian 
835ae8c6e27Sflorian 	if(res == 1) {
836ae8c6e27Sflorian 		return sec_status_secure;
837ae8c6e27Sflorian 	} else if(res == 0) {
838ae8c6e27Sflorian 		verbose(VERB_QUERY, "verify: signature mismatch");
839ae8c6e27Sflorian 		*reason = "signature crypto failed";
840ae8c6e27Sflorian 		return sec_status_bogus;
841ae8c6e27Sflorian 	}
842ae8c6e27Sflorian 
843ae8c6e27Sflorian 	log_crypto_error("verify:", ERR_get_error());
844ae8c6e27Sflorian 	return sec_status_unchecked;
845ae8c6e27Sflorian }
846ae8c6e27Sflorian 
847ae8c6e27Sflorian /**************************************************/
848ae8c6e27Sflorian #elif defined(HAVE_NSS)
849ae8c6e27Sflorian /* libnss implementation */
850ae8c6e27Sflorian /* nss3 */
851ae8c6e27Sflorian #include "sechash.h"
852ae8c6e27Sflorian #include "pk11pub.h"
853ae8c6e27Sflorian #include "keyhi.h"
854ae8c6e27Sflorian #include "secerr.h"
855ae8c6e27Sflorian #include "cryptohi.h"
856ae8c6e27Sflorian /* nspr4 */
857ae8c6e27Sflorian #include "prerror.h"
858ae8c6e27Sflorian 
859ae8c6e27Sflorian /* return size of digest if supported, or 0 otherwise */
860ae8c6e27Sflorian size_t
861ae8c6e27Sflorian nsec3_hash_algo_size_supported(int id)
862ae8c6e27Sflorian {
863ae8c6e27Sflorian 	switch(id) {
864ae8c6e27Sflorian 	case NSEC3_HASH_SHA1:
865ae8c6e27Sflorian 		return SHA1_LENGTH;
866ae8c6e27Sflorian 	default:
867ae8c6e27Sflorian 		return 0;
868ae8c6e27Sflorian 	}
869ae8c6e27Sflorian }
870ae8c6e27Sflorian 
871ae8c6e27Sflorian /* perform nsec3 hash. return false on failure */
872ae8c6e27Sflorian int
873ae8c6e27Sflorian secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
874ae8c6e27Sflorian         unsigned char* res)
875ae8c6e27Sflorian {
876ae8c6e27Sflorian 	switch(algo) {
877ae8c6e27Sflorian 	case NSEC3_HASH_SHA1:
878ae8c6e27Sflorian 		(void)HASH_HashBuf(HASH_AlgSHA1, res, buf, (unsigned long)len);
879ae8c6e27Sflorian 		return 1;
880ae8c6e27Sflorian 	default:
881ae8c6e27Sflorian 		return 0;
882ae8c6e27Sflorian 	}
883ae8c6e27Sflorian }
884ae8c6e27Sflorian 
885ae8c6e27Sflorian void
886ae8c6e27Sflorian secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
887ae8c6e27Sflorian {
888ae8c6e27Sflorian 	(void)HASH_HashBuf(HASH_AlgSHA256, res, buf, (unsigned long)len);
889ae8c6e27Sflorian }
890ae8c6e27Sflorian 
891411c5950Sflorian /** the secalgo hash structure */
892411c5950Sflorian struct secalgo_hash {
893411c5950Sflorian 	/** hash context */
894411c5950Sflorian 	HASHContext* ctx;
895411c5950Sflorian };
896411c5950Sflorian 
897411c5950Sflorian /** create hash struct of type */
898411c5950Sflorian static struct secalgo_hash* secalgo_hash_create_type(HASH_HashType tp)
899411c5950Sflorian {
900411c5950Sflorian 	struct secalgo_hash* h = calloc(1, sizeof(*h));
901411c5950Sflorian 	if(!h)
902411c5950Sflorian 		return NULL;
903411c5950Sflorian 	h->ctx = HASH_Create(tp);
904411c5950Sflorian 	if(!h->ctx) {
905411c5950Sflorian 		free(h);
906411c5950Sflorian 		return NULL;
907411c5950Sflorian 	}
908411c5950Sflorian 	return h;
909411c5950Sflorian }
910411c5950Sflorian 
911411c5950Sflorian struct secalgo_hash* secalgo_hash_create_sha384(void)
912411c5950Sflorian {
913411c5950Sflorian 	return secalgo_hash_create_type(HASH_AlgSHA384);
914411c5950Sflorian }
915411c5950Sflorian 
916411c5950Sflorian struct secalgo_hash* secalgo_hash_create_sha512(void)
917411c5950Sflorian {
918411c5950Sflorian 	return secalgo_hash_create_type(HASH_AlgSHA512);
919411c5950Sflorian }
920411c5950Sflorian 
921411c5950Sflorian int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len)
922411c5950Sflorian {
923411c5950Sflorian 	HASH_Update(hash->ctx, (unsigned char*)data, (unsigned int)len);
924411c5950Sflorian 	return 1;
925411c5950Sflorian }
926411c5950Sflorian 
927411c5950Sflorian int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result,
928411c5950Sflorian         size_t maxlen, size_t* resultlen)
929411c5950Sflorian {
930411c5950Sflorian 	unsigned int reslen = 0;
931411c5950Sflorian 	if(HASH_ResultLenContext(hash->ctx) > (unsigned int)maxlen) {
932411c5950Sflorian 		*resultlen = 0;
933411c5950Sflorian 		log_err("secalgo_hash_final: hash buffer too small");
934411c5950Sflorian 		return 0;
935411c5950Sflorian 	}
936411c5950Sflorian 	HASH_End(hash->ctx, (unsigned char*)result, &reslen,
937411c5950Sflorian 		(unsigned int)maxlen);
938411c5950Sflorian 	*resultlen = (size_t)reslen;
939411c5950Sflorian 	return 1;
940411c5950Sflorian }
941411c5950Sflorian 
942411c5950Sflorian void secalgo_hash_delete(struct secalgo_hash* hash)
943411c5950Sflorian {
944411c5950Sflorian 	if(!hash) return;
945411c5950Sflorian 	HASH_Destroy(hash->ctx);
946411c5950Sflorian 	free(hash);
947411c5950Sflorian }
948411c5950Sflorian 
949ae8c6e27Sflorian size_t
950ae8c6e27Sflorian ds_digest_size_supported(int algo)
951ae8c6e27Sflorian {
952ae8c6e27Sflorian 	/* uses libNSS */
953ae8c6e27Sflorian 	switch(algo) {
954ae8c6e27Sflorian #ifdef USE_SHA1
955ae8c6e27Sflorian 		case LDNS_SHA1:
956ae8c6e27Sflorian 			return SHA1_LENGTH;
957ae8c6e27Sflorian #endif
958ae8c6e27Sflorian #ifdef USE_SHA2
959ae8c6e27Sflorian 		case LDNS_SHA256:
960ae8c6e27Sflorian 			return SHA256_LENGTH;
961ae8c6e27Sflorian #endif
962ae8c6e27Sflorian #ifdef USE_ECDSA
963ae8c6e27Sflorian 		case LDNS_SHA384:
964ae8c6e27Sflorian 			return SHA384_LENGTH;
965ae8c6e27Sflorian #endif
966ae8c6e27Sflorian 		/* GOST not supported in NSS */
967ae8c6e27Sflorian 		case LDNS_HASH_GOST:
968ae8c6e27Sflorian 		default: break;
969ae8c6e27Sflorian 	}
970ae8c6e27Sflorian 	return 0;
971ae8c6e27Sflorian }
972ae8c6e27Sflorian 
973ae8c6e27Sflorian int
974ae8c6e27Sflorian secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
975ae8c6e27Sflorian 	unsigned char* res)
976ae8c6e27Sflorian {
977ae8c6e27Sflorian 	/* uses libNSS */
978ae8c6e27Sflorian 	switch(algo) {
979ae8c6e27Sflorian #ifdef USE_SHA1
980ae8c6e27Sflorian 		case LDNS_SHA1:
981ae8c6e27Sflorian 			return HASH_HashBuf(HASH_AlgSHA1, res, buf, len)
982ae8c6e27Sflorian 				== SECSuccess;
983ae8c6e27Sflorian #endif
984ae8c6e27Sflorian #if defined(USE_SHA2)
985ae8c6e27Sflorian 		case LDNS_SHA256:
986ae8c6e27Sflorian 			return HASH_HashBuf(HASH_AlgSHA256, res, buf, len)
987ae8c6e27Sflorian 				== SECSuccess;
988ae8c6e27Sflorian #endif
989ae8c6e27Sflorian #ifdef USE_ECDSA
990ae8c6e27Sflorian 		case LDNS_SHA384:
991ae8c6e27Sflorian 			return HASH_HashBuf(HASH_AlgSHA384, res, buf, len)
992ae8c6e27Sflorian 				== SECSuccess;
993ae8c6e27Sflorian #endif
994ae8c6e27Sflorian 		case LDNS_HASH_GOST:
995ae8c6e27Sflorian 		default:
996ae8c6e27Sflorian 			verbose(VERB_QUERY, "unknown DS digest algorithm %d",
997ae8c6e27Sflorian 				algo);
998ae8c6e27Sflorian 			break;
999ae8c6e27Sflorian 	}
1000ae8c6e27Sflorian 	return 0;
1001ae8c6e27Sflorian }
1002ae8c6e27Sflorian 
1003ae8c6e27Sflorian int
1004ae8c6e27Sflorian dnskey_algo_id_is_supported(int id)
1005ae8c6e27Sflorian {
1006ae8c6e27Sflorian 	/* uses libNSS */
1007ae8c6e27Sflorian 	switch(id) {
1008ae8c6e27Sflorian 	case LDNS_RSAMD5:
1009ae8c6e27Sflorian 		/* RFC 6725 deprecates RSAMD5 */
1010ae8c6e27Sflorian 		return 0;
1011ae8c6e27Sflorian #if defined(USE_SHA1) || defined(USE_SHA2)
1012ae8c6e27Sflorian #if defined(USE_DSA) && defined(USE_SHA1)
1013ae8c6e27Sflorian 	case LDNS_DSA:
1014ae8c6e27Sflorian 	case LDNS_DSA_NSEC3:
1015ae8c6e27Sflorian #endif
1016ae8c6e27Sflorian #ifdef USE_SHA1
1017ae8c6e27Sflorian 	case LDNS_RSASHA1:
1018ae8c6e27Sflorian 	case LDNS_RSASHA1_NSEC3:
1019ae8c6e27Sflorian #endif
1020ae8c6e27Sflorian #ifdef USE_SHA2
1021ae8c6e27Sflorian 	case LDNS_RSASHA256:
1022ae8c6e27Sflorian #endif
1023ae8c6e27Sflorian #ifdef USE_SHA2
1024ae8c6e27Sflorian 	case LDNS_RSASHA512:
1025ae8c6e27Sflorian #endif
1026ae8c6e27Sflorian 		return 1;
1027ae8c6e27Sflorian #endif /* SHA1 or SHA2 */
1028ae8c6e27Sflorian 
1029ae8c6e27Sflorian #ifdef USE_ECDSA
1030ae8c6e27Sflorian 	case LDNS_ECDSAP256SHA256:
1031ae8c6e27Sflorian 	case LDNS_ECDSAP384SHA384:
1032ae8c6e27Sflorian 		return PK11_TokenExists(CKM_ECDSA);
1033ae8c6e27Sflorian #endif
1034ae8c6e27Sflorian 	case LDNS_ECC_GOST:
1035ae8c6e27Sflorian 	default:
1036ae8c6e27Sflorian 		return 0;
1037ae8c6e27Sflorian 	}
1038ae8c6e27Sflorian }
1039ae8c6e27Sflorian 
1040ae8c6e27Sflorian /* return a new public key for NSS */
1041ae8c6e27Sflorian static SECKEYPublicKey* nss_key_create(KeyType ktype)
1042ae8c6e27Sflorian {
1043ae8c6e27Sflorian 	SECKEYPublicKey* key;
1044ae8c6e27Sflorian 	PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1045ae8c6e27Sflorian 	if(!arena) {
1046ae8c6e27Sflorian 		log_err("out of memory, PORT_NewArena failed");
1047ae8c6e27Sflorian 		return NULL;
1048ae8c6e27Sflorian 	}
1049ae8c6e27Sflorian 	key = PORT_ArenaZNew(arena, SECKEYPublicKey);
1050ae8c6e27Sflorian 	if(!key) {
1051ae8c6e27Sflorian 		log_err("out of memory, PORT_ArenaZNew failed");
1052ae8c6e27Sflorian 		PORT_FreeArena(arena, PR_FALSE);
1053ae8c6e27Sflorian 		return NULL;
1054ae8c6e27Sflorian 	}
1055ae8c6e27Sflorian 	key->arena = arena;
1056ae8c6e27Sflorian 	key->keyType = ktype;
1057ae8c6e27Sflorian 	key->pkcs11Slot = NULL;
1058ae8c6e27Sflorian 	key->pkcs11ID = CK_INVALID_HANDLE;
1059ae8c6e27Sflorian 	return key;
1060ae8c6e27Sflorian }
1061ae8c6e27Sflorian 
1062ae8c6e27Sflorian static SECKEYPublicKey* nss_buf2ecdsa(unsigned char* key, size_t len, int algo)
1063ae8c6e27Sflorian {
1064ae8c6e27Sflorian 	SECKEYPublicKey* pk;
1065ae8c6e27Sflorian 	SECItem pub = {siBuffer, NULL, 0};
1066ae8c6e27Sflorian 	SECItem params = {siBuffer, NULL, 0};
1067ae8c6e27Sflorian 	static unsigned char param256[] = {
1068ae8c6e27Sflorian 		/* OBJECTIDENTIFIER 1.2.840.10045.3.1.7 (P-256)
1069ae8c6e27Sflorian 		 * {iso(1) member-body(2) us(840) ansi-x962(10045) curves(3) prime(1) prime256v1(7)} */
1070ae8c6e27Sflorian 		0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
1071ae8c6e27Sflorian 	};
1072ae8c6e27Sflorian 	static unsigned char param384[] = {
1073ae8c6e27Sflorian 		/* OBJECTIDENTIFIER 1.3.132.0.34 (P-384)
1074ae8c6e27Sflorian 		 * {iso(1) identified-organization(3) certicom(132) curve(0) ansip384r1(34)} */
1075ae8c6e27Sflorian 		0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22
1076ae8c6e27Sflorian 	};
1077ae8c6e27Sflorian 	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
1078ae8c6e27Sflorian 
1079ae8c6e27Sflorian 	/* check length, which uncompressed must be 2 bignums */
1080ae8c6e27Sflorian 	if(algo == LDNS_ECDSAP256SHA256) {
1081ae8c6e27Sflorian 		if(len != 2*256/8) return NULL;
1082ae8c6e27Sflorian 		/* ECCurve_X9_62_PRIME_256V1 */
1083ae8c6e27Sflorian 	} else if(algo == LDNS_ECDSAP384SHA384) {
1084ae8c6e27Sflorian 		if(len != 2*384/8) return NULL;
1085ae8c6e27Sflorian 		/* ECCurve_X9_62_PRIME_384R1 */
1086ae8c6e27Sflorian 	} else    return NULL;
1087ae8c6e27Sflorian 
1088ae8c6e27Sflorian 	buf[0] = 0x04; /* POINT_FORM_UNCOMPRESSED */
1089ae8c6e27Sflorian 	memmove(buf+1, key, len);
1090ae8c6e27Sflorian 	pub.data = buf;
1091ae8c6e27Sflorian 	pub.len = len+1;
1092ae8c6e27Sflorian 	if(algo == LDNS_ECDSAP256SHA256) {
1093ae8c6e27Sflorian 		params.data = param256;
1094ae8c6e27Sflorian 		params.len = sizeof(param256);
1095ae8c6e27Sflorian 	} else {
1096ae8c6e27Sflorian 		params.data = param384;
1097ae8c6e27Sflorian 		params.len = sizeof(param384);
1098ae8c6e27Sflorian 	}
1099ae8c6e27Sflorian 
1100ae8c6e27Sflorian 	pk = nss_key_create(ecKey);
1101ae8c6e27Sflorian 	if(!pk)
1102ae8c6e27Sflorian 		return NULL;
1103ae8c6e27Sflorian 	pk->u.ec.size = (len/2)*8;
1104ae8c6e27Sflorian 	if(SECITEM_CopyItem(pk->arena, &pk->u.ec.publicValue, &pub)) {
1105ae8c6e27Sflorian 		SECKEY_DestroyPublicKey(pk);
1106ae8c6e27Sflorian 		return NULL;
1107ae8c6e27Sflorian 	}
1108ae8c6e27Sflorian 	if(SECITEM_CopyItem(pk->arena, &pk->u.ec.DEREncodedParams, &params)) {
1109ae8c6e27Sflorian 		SECKEY_DestroyPublicKey(pk);
1110ae8c6e27Sflorian 		return NULL;
1111ae8c6e27Sflorian 	}
1112ae8c6e27Sflorian 
1113ae8c6e27Sflorian 	return pk;
1114ae8c6e27Sflorian }
1115ae8c6e27Sflorian 
1116853e076fSflorian #if defined(USE_DSA) && defined(USE_SHA1)
1117ae8c6e27Sflorian static SECKEYPublicKey* nss_buf2dsa(unsigned char* key, size_t len)
1118ae8c6e27Sflorian {
1119ae8c6e27Sflorian 	SECKEYPublicKey* pk;
1120ae8c6e27Sflorian 	uint8_t T;
1121ae8c6e27Sflorian 	uint16_t length;
1122ae8c6e27Sflorian 	uint16_t offset;
1123ae8c6e27Sflorian 	SECItem Q = {siBuffer, NULL, 0};
1124ae8c6e27Sflorian 	SECItem P = {siBuffer, NULL, 0};
1125ae8c6e27Sflorian 	SECItem G = {siBuffer, NULL, 0};
1126ae8c6e27Sflorian 	SECItem Y = {siBuffer, NULL, 0};
1127ae8c6e27Sflorian 
1128ae8c6e27Sflorian 	if(len == 0)
1129ae8c6e27Sflorian 		return NULL;
1130ae8c6e27Sflorian 	T = (uint8_t)key[0];
1131ae8c6e27Sflorian 	length = (64 + T * 8);
1132ae8c6e27Sflorian 	offset = 1;
1133ae8c6e27Sflorian 
1134ae8c6e27Sflorian 	if (T > 8) {
1135ae8c6e27Sflorian 		return NULL;
1136ae8c6e27Sflorian 	}
1137ae8c6e27Sflorian 	if(len < (size_t)1 + SHA1_LENGTH + 3*length)
1138ae8c6e27Sflorian 		return NULL;
1139ae8c6e27Sflorian 
1140ae8c6e27Sflorian 	Q.data = key+offset;
1141ae8c6e27Sflorian 	Q.len = SHA1_LENGTH;
1142ae8c6e27Sflorian 	offset += SHA1_LENGTH;
1143ae8c6e27Sflorian 
1144ae8c6e27Sflorian 	P.data = key+offset;
1145ae8c6e27Sflorian 	P.len = length;
1146ae8c6e27Sflorian 	offset += length;
1147ae8c6e27Sflorian 
1148ae8c6e27Sflorian 	G.data = key+offset;
1149ae8c6e27Sflorian 	G.len = length;
1150ae8c6e27Sflorian 	offset += length;
1151ae8c6e27Sflorian 
1152ae8c6e27Sflorian 	Y.data = key+offset;
1153ae8c6e27Sflorian 	Y.len = length;
1154ae8c6e27Sflorian 	offset += length;
1155ae8c6e27Sflorian 
1156ae8c6e27Sflorian 	pk = nss_key_create(dsaKey);
1157ae8c6e27Sflorian 	if(!pk)
1158ae8c6e27Sflorian 		return NULL;
1159ae8c6e27Sflorian 	if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.prime, &P)) {
1160ae8c6e27Sflorian 		SECKEY_DestroyPublicKey(pk);
1161ae8c6e27Sflorian 		return NULL;
1162ae8c6e27Sflorian 	}
1163ae8c6e27Sflorian 	if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.subPrime, &Q)) {
1164ae8c6e27Sflorian 		SECKEY_DestroyPublicKey(pk);
1165ae8c6e27Sflorian 		return NULL;
1166ae8c6e27Sflorian 	}
1167ae8c6e27Sflorian 	if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.base, &G)) {
1168ae8c6e27Sflorian 		SECKEY_DestroyPublicKey(pk);
1169ae8c6e27Sflorian 		return NULL;
1170ae8c6e27Sflorian 	}
1171ae8c6e27Sflorian 	if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.publicValue, &Y)) {
1172ae8c6e27Sflorian 		SECKEY_DestroyPublicKey(pk);
1173ae8c6e27Sflorian 		return NULL;
1174ae8c6e27Sflorian 	}
1175ae8c6e27Sflorian 	return pk;
1176ae8c6e27Sflorian }
1177853e076fSflorian #endif /* USE_DSA && USE_SHA1 */
1178ae8c6e27Sflorian 
1179ae8c6e27Sflorian static SECKEYPublicKey* nss_buf2rsa(unsigned char* key, size_t len)
1180ae8c6e27Sflorian {
1181ae8c6e27Sflorian 	SECKEYPublicKey* pk;
1182ae8c6e27Sflorian 	uint16_t exp;
1183ae8c6e27Sflorian 	uint16_t offset;
1184ae8c6e27Sflorian 	uint16_t int16;
1185ae8c6e27Sflorian 	SECItem modulus = {siBuffer, NULL, 0};
1186ae8c6e27Sflorian 	SECItem exponent = {siBuffer, NULL, 0};
1187ae8c6e27Sflorian 	if(len == 0)
1188ae8c6e27Sflorian 		return NULL;
1189ae8c6e27Sflorian 	if(key[0] == 0) {
1190ae8c6e27Sflorian 		if(len < 3)
1191ae8c6e27Sflorian 			return NULL;
1192ae8c6e27Sflorian 		/* the exponent is too large so it's places further */
1193ae8c6e27Sflorian 		memmove(&int16, key+1, 2);
1194ae8c6e27Sflorian 		exp = ntohs(int16);
1195ae8c6e27Sflorian 		offset = 3;
1196ae8c6e27Sflorian 	} else {
1197ae8c6e27Sflorian 		exp = key[0];
1198ae8c6e27Sflorian 		offset = 1;
1199ae8c6e27Sflorian 	}
1200ae8c6e27Sflorian 
1201ae8c6e27Sflorian 	/* key length at least one */
1202ae8c6e27Sflorian 	if(len < (size_t)offset + exp + 1)
1203ae8c6e27Sflorian 		return NULL;
1204ae8c6e27Sflorian 
1205ae8c6e27Sflorian 	exponent.data = key+offset;
1206ae8c6e27Sflorian 	exponent.len = exp;
1207ae8c6e27Sflorian 	offset += exp;
1208ae8c6e27Sflorian 	modulus.data = key+offset;
1209ae8c6e27Sflorian 	modulus.len = (len - offset);
1210ae8c6e27Sflorian 
1211ae8c6e27Sflorian 	pk = nss_key_create(rsaKey);
1212ae8c6e27Sflorian 	if(!pk)
1213ae8c6e27Sflorian 		return NULL;
1214ae8c6e27Sflorian 	if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.modulus, &modulus)) {
1215ae8c6e27Sflorian 		SECKEY_DestroyPublicKey(pk);
1216ae8c6e27Sflorian 		return NULL;
1217ae8c6e27Sflorian 	}
1218ae8c6e27Sflorian 	if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.publicExponent, &exponent)) {
1219ae8c6e27Sflorian 		SECKEY_DestroyPublicKey(pk);
1220ae8c6e27Sflorian 		return NULL;
1221ae8c6e27Sflorian 	}
1222ae8c6e27Sflorian 	return pk;
1223ae8c6e27Sflorian }
1224ae8c6e27Sflorian 
1225ae8c6e27Sflorian /**
1226ae8c6e27Sflorian  * Setup key and digest for verification. Adjust sig if necessary.
1227ae8c6e27Sflorian  *
1228ae8c6e27Sflorian  * @param algo: key algorithm
1229ae8c6e27Sflorian  * @param evp_key: EVP PKEY public key to create.
1230ae8c6e27Sflorian  * @param digest_type: digest type to use
1231ae8c6e27Sflorian  * @param key: key to setup for.
1232ae8c6e27Sflorian  * @param keylen: length of key.
1233ae8c6e27Sflorian  * @param prefix: if returned, the ASN prefix for the hashblob.
1234ae8c6e27Sflorian  * @param prefixlen: length of the prefix.
1235ae8c6e27Sflorian  * @return false on failure.
1236ae8c6e27Sflorian  */
1237ae8c6e27Sflorian static int
1238ae8c6e27Sflorian nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
1239ae8c6e27Sflorian 	unsigned char* key, size_t keylen, unsigned char** prefix,
1240ae8c6e27Sflorian 	size_t* prefixlen)
1241ae8c6e27Sflorian {
1242ae8c6e27Sflorian 	/* uses libNSS */
1243ae8c6e27Sflorian 
1244ae8c6e27Sflorian 	/* hash prefix for md5, RFC2537 */
1245ae8c6e27Sflorian 	static unsigned char p_md5[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a,
1246ae8c6e27Sflorian 	0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
1247ae8c6e27Sflorian 	/* hash prefix to prepend to hash output, from RFC3110 */
1248ae8c6e27Sflorian 	static unsigned char p_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B,
1249ae8c6e27Sflorian 		0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14};
1250ae8c6e27Sflorian 	/* from RFC5702 */
1251ae8c6e27Sflorian 	static unsigned char p_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
1252ae8c6e27Sflorian 	0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
1253ae8c6e27Sflorian 	static unsigned char p_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
1254ae8c6e27Sflorian 	0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
1255ae8c6e27Sflorian 	/* from RFC6234 */
1256ae8c6e27Sflorian 	/* for future RSASHA384 ..
1257ae8c6e27Sflorian 	static unsigned char p_sha384[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
1258ae8c6e27Sflorian 	0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
1259ae8c6e27Sflorian 	*/
1260ae8c6e27Sflorian 
1261ae8c6e27Sflorian 	switch(algo) {
1262ae8c6e27Sflorian 
1263ae8c6e27Sflorian #if defined(USE_SHA1) || defined(USE_SHA2)
1264ae8c6e27Sflorian #if defined(USE_DSA) && defined(USE_SHA1)
1265ae8c6e27Sflorian 		case LDNS_DSA:
1266ae8c6e27Sflorian 		case LDNS_DSA_NSEC3:
1267ae8c6e27Sflorian 			*pubkey = nss_buf2dsa(key, keylen);
1268ae8c6e27Sflorian 			if(!*pubkey) {
1269ae8c6e27Sflorian 				log_err("verify: malloc failure in crypto");
1270ae8c6e27Sflorian 				return 0;
1271ae8c6e27Sflorian 			}
1272ae8c6e27Sflorian 			*htype = HASH_AlgSHA1;
1273ae8c6e27Sflorian 			/* no prefix for DSA verification */
1274ae8c6e27Sflorian 			break;
1275ae8c6e27Sflorian #endif
1276ae8c6e27Sflorian #ifdef USE_SHA1
1277ae8c6e27Sflorian 		case LDNS_RSASHA1:
1278ae8c6e27Sflorian 		case LDNS_RSASHA1_NSEC3:
1279ae8c6e27Sflorian #endif
1280ae8c6e27Sflorian #ifdef USE_SHA2
1281ae8c6e27Sflorian 		case LDNS_RSASHA256:
1282ae8c6e27Sflorian #endif
1283ae8c6e27Sflorian #ifdef USE_SHA2
1284ae8c6e27Sflorian 		case LDNS_RSASHA512:
1285ae8c6e27Sflorian #endif
1286ae8c6e27Sflorian 			*pubkey = nss_buf2rsa(key, keylen);
1287ae8c6e27Sflorian 			if(!*pubkey) {
1288ae8c6e27Sflorian 				log_err("verify: malloc failure in crypto");
1289ae8c6e27Sflorian 				return 0;
1290ae8c6e27Sflorian 			}
1291ae8c6e27Sflorian 			/* select SHA version */
1292ae8c6e27Sflorian #ifdef USE_SHA2
1293ae8c6e27Sflorian 			if(algo == LDNS_RSASHA256) {
1294ae8c6e27Sflorian 				*htype = HASH_AlgSHA256;
1295ae8c6e27Sflorian 				*prefix = p_sha256;
1296ae8c6e27Sflorian 				*prefixlen = sizeof(p_sha256);
1297ae8c6e27Sflorian 			} else
1298ae8c6e27Sflorian #endif
1299ae8c6e27Sflorian #ifdef USE_SHA2
1300ae8c6e27Sflorian 				if(algo == LDNS_RSASHA512) {
1301ae8c6e27Sflorian 				*htype = HASH_AlgSHA512;
1302ae8c6e27Sflorian 				*prefix = p_sha512;
1303ae8c6e27Sflorian 				*prefixlen = sizeof(p_sha512);
1304ae8c6e27Sflorian 			} else
1305ae8c6e27Sflorian #endif
1306ae8c6e27Sflorian #ifdef USE_SHA1
1307ae8c6e27Sflorian 			{
1308ae8c6e27Sflorian 				*htype = HASH_AlgSHA1;
1309ae8c6e27Sflorian 				*prefix = p_sha1;
1310ae8c6e27Sflorian 				*prefixlen = sizeof(p_sha1);
1311ae8c6e27Sflorian 			}
1312ae8c6e27Sflorian #else
1313ae8c6e27Sflorian 			{
1314ae8c6e27Sflorian 				verbose(VERB_QUERY, "verify: no digest algo");
1315ae8c6e27Sflorian 				return 0;
1316ae8c6e27Sflorian 			}
1317ae8c6e27Sflorian #endif
1318ae8c6e27Sflorian 
1319ae8c6e27Sflorian 			break;
1320ae8c6e27Sflorian #endif /* SHA1 or SHA2 */
1321ae8c6e27Sflorian 
1322ae8c6e27Sflorian 		case LDNS_RSAMD5:
1323ae8c6e27Sflorian 			*pubkey = nss_buf2rsa(key, keylen);
1324ae8c6e27Sflorian 			if(!*pubkey) {
1325ae8c6e27Sflorian 				log_err("verify: malloc failure in crypto");
1326ae8c6e27Sflorian 				return 0;
1327ae8c6e27Sflorian 			}
1328ae8c6e27Sflorian 			*htype = HASH_AlgMD5;
1329ae8c6e27Sflorian 			*prefix = p_md5;
1330ae8c6e27Sflorian 			*prefixlen = sizeof(p_md5);
1331ae8c6e27Sflorian 
1332ae8c6e27Sflorian 			break;
1333ae8c6e27Sflorian #ifdef USE_ECDSA
1334ae8c6e27Sflorian 		case LDNS_ECDSAP256SHA256:
1335ae8c6e27Sflorian 			*pubkey = nss_buf2ecdsa(key, keylen,
1336ae8c6e27Sflorian 				LDNS_ECDSAP256SHA256);
1337ae8c6e27Sflorian 			if(!*pubkey) {
1338ae8c6e27Sflorian 				log_err("verify: malloc failure in crypto");
1339ae8c6e27Sflorian 				return 0;
1340ae8c6e27Sflorian 			}
1341ae8c6e27Sflorian 			*htype = HASH_AlgSHA256;
1342ae8c6e27Sflorian 			/* no prefix for DSA verification */
1343ae8c6e27Sflorian 			break;
1344ae8c6e27Sflorian 		case LDNS_ECDSAP384SHA384:
1345ae8c6e27Sflorian 			*pubkey = nss_buf2ecdsa(key, keylen,
1346ae8c6e27Sflorian 				LDNS_ECDSAP384SHA384);
1347ae8c6e27Sflorian 			if(!*pubkey) {
1348ae8c6e27Sflorian 				log_err("verify: malloc failure in crypto");
1349ae8c6e27Sflorian 				return 0;
1350ae8c6e27Sflorian 			}
1351ae8c6e27Sflorian 			*htype = HASH_AlgSHA384;
1352ae8c6e27Sflorian 			/* no prefix for DSA verification */
1353ae8c6e27Sflorian 			break;
1354ae8c6e27Sflorian #endif /* USE_ECDSA */
1355ae8c6e27Sflorian 		case LDNS_ECC_GOST:
1356ae8c6e27Sflorian 		default:
1357ae8c6e27Sflorian 			verbose(VERB_QUERY, "verify: unknown algorithm %d",
1358ae8c6e27Sflorian 				algo);
1359ae8c6e27Sflorian 			return 0;
1360ae8c6e27Sflorian 	}
1361ae8c6e27Sflorian 	return 1;
1362ae8c6e27Sflorian }
1363ae8c6e27Sflorian 
1364ae8c6e27Sflorian /**
1365ae8c6e27Sflorian  * Check a canonical sig+rrset and signature against a dnskey
1366ae8c6e27Sflorian  * @param buf: buffer with data to verify, the first rrsig part and the
1367ae8c6e27Sflorian  *	canonicalized rrset.
1368ae8c6e27Sflorian  * @param algo: DNSKEY algorithm.
1369ae8c6e27Sflorian  * @param sigblock: signature rdata field from RRSIG
1370ae8c6e27Sflorian  * @param sigblock_len: length of sigblock data.
1371ae8c6e27Sflorian  * @param key: public key data from DNSKEY RR.
1372ae8c6e27Sflorian  * @param keylen: length of keydata.
1373ae8c6e27Sflorian  * @param reason: bogus reason in more detail.
1374ae8c6e27Sflorian  * @return secure if verification succeeded, bogus on crypto failure,
1375ae8c6e27Sflorian  *	unchecked on format errors and alloc failures.
1376ae8c6e27Sflorian  */
1377ae8c6e27Sflorian enum sec_status
1378ae8c6e27Sflorian verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
1379ae8c6e27Sflorian 	unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
1380ae8c6e27Sflorian 	char** reason)
1381ae8c6e27Sflorian {
1382ae8c6e27Sflorian 	/* uses libNSS */
1383ae8c6e27Sflorian 	/* large enough for the different hashes */
1384ae8c6e27Sflorian 	unsigned char hash[HASH_LENGTH_MAX];
1385ae8c6e27Sflorian 	unsigned char hash2[HASH_LENGTH_MAX*2];
1386ae8c6e27Sflorian 	HASH_HashType htype = 0;
1387ae8c6e27Sflorian 	SECKEYPublicKey* pubkey = NULL;
1388ae8c6e27Sflorian 	SECItem secsig = {siBuffer, sigblock, sigblock_len};
1389ae8c6e27Sflorian 	SECItem sechash = {siBuffer, hash, 0};
1390ae8c6e27Sflorian 	SECStatus res;
1391ae8c6e27Sflorian 	unsigned char* prefix = NULL; /* prefix for hash, RFC3110, RFC5702 */
1392ae8c6e27Sflorian 	size_t prefixlen = 0;
1393ae8c6e27Sflorian 	int err;
1394ae8c6e27Sflorian 
1395ae8c6e27Sflorian 	if(!nss_setup_key_digest(algo, &pubkey, &htype, key, keylen,
1396ae8c6e27Sflorian 		&prefix, &prefixlen)) {
1397ae8c6e27Sflorian 		verbose(VERB_QUERY, "verify: failed to setup key");
1398ae8c6e27Sflorian 		*reason = "use of key for crypto failed";
1399ae8c6e27Sflorian 		SECKEY_DestroyPublicKey(pubkey);
1400ae8c6e27Sflorian 		return sec_status_bogus;
1401ae8c6e27Sflorian 	}
1402ae8c6e27Sflorian 
1403ae8c6e27Sflorian #if defined(USE_DSA) && defined(USE_SHA1)
1404ae8c6e27Sflorian 	/* need to convert DSA, ECDSA signatures? */
1405ae8c6e27Sflorian 	if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) {
1406ae8c6e27Sflorian 		if(sigblock_len == 1+2*SHA1_LENGTH) {
1407ae8c6e27Sflorian 			secsig.data ++;
1408ae8c6e27Sflorian 			secsig.len --;
1409ae8c6e27Sflorian 		} else {
1410ae8c6e27Sflorian 			SECItem* p = DSAU_DecodeDerSig(&secsig);
1411ae8c6e27Sflorian 			if(!p) {
1412ae8c6e27Sflorian 				verbose(VERB_QUERY, "verify: failed DER decode");
1413ae8c6e27Sflorian 				*reason = "signature DER decode failed";
1414ae8c6e27Sflorian 				SECKEY_DestroyPublicKey(pubkey);
1415ae8c6e27Sflorian 				return sec_status_bogus;
1416ae8c6e27Sflorian 			}
1417ae8c6e27Sflorian 			if(SECITEM_CopyItem(pubkey->arena, &secsig, p)) {
1418ae8c6e27Sflorian 				log_err("alloc failure in DER decode");
1419ae8c6e27Sflorian 				SECKEY_DestroyPublicKey(pubkey);
1420ae8c6e27Sflorian 				SECITEM_FreeItem(p, PR_TRUE);
1421ae8c6e27Sflorian 				return sec_status_unchecked;
1422ae8c6e27Sflorian 			}
1423ae8c6e27Sflorian 			SECITEM_FreeItem(p, PR_TRUE);
1424ae8c6e27Sflorian 		}
1425ae8c6e27Sflorian 	}
1426ae8c6e27Sflorian #endif /* USE_DSA */
1427ae8c6e27Sflorian 
1428ae8c6e27Sflorian 	/* do the signature cryptography work */
1429ae8c6e27Sflorian 	/* hash the data */
1430ae8c6e27Sflorian 	sechash.len = HASH_ResultLen(htype);
1431ae8c6e27Sflorian 	if(sechash.len > sizeof(hash)) {
1432ae8c6e27Sflorian 		verbose(VERB_QUERY, "verify: hash too large for buffer");
1433ae8c6e27Sflorian 		SECKEY_DestroyPublicKey(pubkey);
1434ae8c6e27Sflorian 		return sec_status_unchecked;
1435ae8c6e27Sflorian 	}
1436ae8c6e27Sflorian 	if(HASH_HashBuf(htype, hash, (unsigned char*)sldns_buffer_begin(buf),
1437ae8c6e27Sflorian 		(unsigned int)sldns_buffer_limit(buf)) != SECSuccess) {
1438ae8c6e27Sflorian 		verbose(VERB_QUERY, "verify: HASH_HashBuf failed");
1439ae8c6e27Sflorian 		SECKEY_DestroyPublicKey(pubkey);
1440ae8c6e27Sflorian 		return sec_status_unchecked;
1441ae8c6e27Sflorian 	}
1442ae8c6e27Sflorian 	if(prefix) {
1443ae8c6e27Sflorian 		int hashlen = sechash.len;
1444ae8c6e27Sflorian 		if(prefixlen+hashlen > sizeof(hash2)) {
1445ae8c6e27Sflorian 			verbose(VERB_QUERY, "verify: hashprefix too large");
1446ae8c6e27Sflorian 			SECKEY_DestroyPublicKey(pubkey);
1447ae8c6e27Sflorian 			return sec_status_unchecked;
1448ae8c6e27Sflorian 		}
1449ae8c6e27Sflorian 		sechash.data = hash2;
1450ae8c6e27Sflorian 		sechash.len = prefixlen+hashlen;
1451ae8c6e27Sflorian 		memcpy(sechash.data, prefix, prefixlen);
1452ae8c6e27Sflorian 		memmove(sechash.data+prefixlen, hash, hashlen);
1453ae8c6e27Sflorian 	}
1454ae8c6e27Sflorian 
1455ae8c6e27Sflorian 	/* verify the signature */
1456ae8c6e27Sflorian 	res = PK11_Verify(pubkey, &secsig, &sechash, NULL /*wincx*/);
1457ae8c6e27Sflorian 	SECKEY_DestroyPublicKey(pubkey);
1458ae8c6e27Sflorian 
1459ae8c6e27Sflorian 	if(res == SECSuccess) {
1460ae8c6e27Sflorian 		return sec_status_secure;
1461ae8c6e27Sflorian 	}
1462ae8c6e27Sflorian 	err = PORT_GetError();
1463ae8c6e27Sflorian 	if(err != SEC_ERROR_BAD_SIGNATURE) {
1464ae8c6e27Sflorian 		/* failed to verify */
1465ae8c6e27Sflorian 		verbose(VERB_QUERY, "verify: PK11_Verify failed: %s",
1466ae8c6e27Sflorian 			PORT_ErrorToString(err));
1467ae8c6e27Sflorian 		/* if it is not supported, like ECC is removed, we get,
1468ae8c6e27Sflorian 		 * SEC_ERROR_NO_MODULE */
1469ae8c6e27Sflorian 		if(err == SEC_ERROR_NO_MODULE)
1470ae8c6e27Sflorian 			return sec_status_unchecked;
1471ae8c6e27Sflorian 		/* but other errors are commonly returned
1472ae8c6e27Sflorian 		 * for a bad signature from NSS.  Thus we return bogus,
1473ae8c6e27Sflorian 		 * not unchecked */
1474ae8c6e27Sflorian 		*reason = "signature crypto failed";
1475ae8c6e27Sflorian 		return sec_status_bogus;
1476ae8c6e27Sflorian 	}
1477ae8c6e27Sflorian 	verbose(VERB_QUERY, "verify: signature mismatch: %s",
1478ae8c6e27Sflorian 		PORT_ErrorToString(err));
1479ae8c6e27Sflorian 	*reason = "signature crypto failed";
1480ae8c6e27Sflorian 	return sec_status_bogus;
1481ae8c6e27Sflorian }
1482ae8c6e27Sflorian 
1483ae8c6e27Sflorian #elif defined(HAVE_NETTLE)
1484ae8c6e27Sflorian 
1485ae8c6e27Sflorian #include "sha.h"
1486ae8c6e27Sflorian #include "bignum.h"
1487ae8c6e27Sflorian #include "macros.h"
1488ae8c6e27Sflorian #include "rsa.h"
1489ae8c6e27Sflorian #include "dsa.h"
1490ae8c6e27Sflorian #ifdef HAVE_NETTLE_DSA_COMPAT_H
1491ae8c6e27Sflorian #include "dsa-compat.h"
1492ae8c6e27Sflorian #endif
1493ae8c6e27Sflorian #include "asn1.h"
1494ae8c6e27Sflorian #ifdef USE_ECDSA
1495ae8c6e27Sflorian #include "ecdsa.h"
1496ae8c6e27Sflorian #include "ecc-curve.h"
1497ae8c6e27Sflorian #endif
1498ae8c6e27Sflorian #ifdef HAVE_NETTLE_EDDSA_H
1499ae8c6e27Sflorian #include "eddsa.h"
1500ae8c6e27Sflorian #endif
1501ae8c6e27Sflorian 
1502ae8c6e27Sflorian static int
1503ae8c6e27Sflorian _digest_nettle(int algo, uint8_t* buf, size_t len,
1504ae8c6e27Sflorian 	unsigned char* res)
1505ae8c6e27Sflorian {
1506ae8c6e27Sflorian 	switch(algo) {
1507ae8c6e27Sflorian 		case SHA1_DIGEST_SIZE:
1508ae8c6e27Sflorian 		{
1509ae8c6e27Sflorian 			struct sha1_ctx ctx;
1510ae8c6e27Sflorian 			sha1_init(&ctx);
1511ae8c6e27Sflorian 			sha1_update(&ctx, len, buf);
1512ae8c6e27Sflorian 			sha1_digest(&ctx, SHA1_DIGEST_SIZE, res);
1513ae8c6e27Sflorian 			return 1;
1514ae8c6e27Sflorian 		}
1515ae8c6e27Sflorian 		case SHA256_DIGEST_SIZE:
1516ae8c6e27Sflorian 		{
1517ae8c6e27Sflorian 			struct sha256_ctx ctx;
1518ae8c6e27Sflorian 			sha256_init(&ctx);
1519ae8c6e27Sflorian 			sha256_update(&ctx, len, buf);
1520ae8c6e27Sflorian 			sha256_digest(&ctx, SHA256_DIGEST_SIZE, res);
1521ae8c6e27Sflorian 			return 1;
1522ae8c6e27Sflorian 		}
1523ae8c6e27Sflorian 		case SHA384_DIGEST_SIZE:
1524ae8c6e27Sflorian 		{
1525ae8c6e27Sflorian 			struct sha384_ctx ctx;
1526ae8c6e27Sflorian 			sha384_init(&ctx);
1527ae8c6e27Sflorian 			sha384_update(&ctx, len, buf);
1528ae8c6e27Sflorian 			sha384_digest(&ctx, SHA384_DIGEST_SIZE, res);
1529ae8c6e27Sflorian 			return 1;
1530ae8c6e27Sflorian 		}
1531ae8c6e27Sflorian 		case SHA512_DIGEST_SIZE:
1532ae8c6e27Sflorian 		{
1533ae8c6e27Sflorian 			struct sha512_ctx ctx;
1534ae8c6e27Sflorian 			sha512_init(&ctx);
1535ae8c6e27Sflorian 			sha512_update(&ctx, len, buf);
1536ae8c6e27Sflorian 			sha512_digest(&ctx, SHA512_DIGEST_SIZE, res);
1537ae8c6e27Sflorian 			return 1;
1538ae8c6e27Sflorian 		}
1539ae8c6e27Sflorian 		default:
1540ae8c6e27Sflorian 			break;
1541ae8c6e27Sflorian 	}
1542ae8c6e27Sflorian 	return 0;
1543ae8c6e27Sflorian }
1544ae8c6e27Sflorian 
1545ae8c6e27Sflorian /* return size of digest if supported, or 0 otherwise */
1546ae8c6e27Sflorian size_t
1547ae8c6e27Sflorian nsec3_hash_algo_size_supported(int id)
1548ae8c6e27Sflorian {
1549ae8c6e27Sflorian 	switch(id) {
1550ae8c6e27Sflorian 	case NSEC3_HASH_SHA1:
1551ae8c6e27Sflorian 		return SHA1_DIGEST_SIZE;
1552ae8c6e27Sflorian 	default:
1553ae8c6e27Sflorian 		return 0;
1554ae8c6e27Sflorian 	}
1555ae8c6e27Sflorian }
1556ae8c6e27Sflorian 
1557ae8c6e27Sflorian /* perform nsec3 hash. return false on failure */
1558ae8c6e27Sflorian int
1559ae8c6e27Sflorian secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
1560ae8c6e27Sflorian         unsigned char* res)
1561ae8c6e27Sflorian {
1562ae8c6e27Sflorian 	switch(algo) {
1563ae8c6e27Sflorian 	case NSEC3_HASH_SHA1:
1564ae8c6e27Sflorian 		return _digest_nettle(SHA1_DIGEST_SIZE, (uint8_t*)buf, len,
1565ae8c6e27Sflorian 			res);
1566ae8c6e27Sflorian 	default:
1567ae8c6e27Sflorian 		return 0;
1568ae8c6e27Sflorian 	}
1569ae8c6e27Sflorian }
1570ae8c6e27Sflorian 
1571ae8c6e27Sflorian void
1572ae8c6e27Sflorian secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
1573ae8c6e27Sflorian {
1574ae8c6e27Sflorian 	_digest_nettle(SHA256_DIGEST_SIZE, (uint8_t*)buf, len, res);
1575ae8c6e27Sflorian }
1576ae8c6e27Sflorian 
1577411c5950Sflorian /** secalgo hash structure */
1578411c5950Sflorian struct secalgo_hash {
1579411c5950Sflorian 	/** if it is 384 or 512 */
1580411c5950Sflorian 	int active;
1581411c5950Sflorian 	/** context for sha384 */
1582411c5950Sflorian 	struct sha384_ctx ctx384;
1583411c5950Sflorian 	/** context for sha512 */
1584411c5950Sflorian 	struct sha512_ctx ctx512;
1585411c5950Sflorian };
1586411c5950Sflorian 
1587411c5950Sflorian struct secalgo_hash* secalgo_hash_create_sha384(void)
1588411c5950Sflorian {
1589411c5950Sflorian 	struct secalgo_hash* h = calloc(1, sizeof(*h));
1590411c5950Sflorian 	if(!h)
1591411c5950Sflorian 		return NULL;
1592411c5950Sflorian 	h->active = 384;
1593411c5950Sflorian 	sha384_init(&h->ctx384);
1594411c5950Sflorian 	return h;
1595411c5950Sflorian }
1596411c5950Sflorian 
1597411c5950Sflorian struct secalgo_hash* secalgo_hash_create_sha512(void)
1598411c5950Sflorian {
1599411c5950Sflorian 	struct secalgo_hash* h = calloc(1, sizeof(*h));
1600411c5950Sflorian 	if(!h)
1601411c5950Sflorian 		return NULL;
1602411c5950Sflorian 	h->active = 512;
1603411c5950Sflorian 	sha512_init(&h->ctx512);
1604411c5950Sflorian 	return h;
1605411c5950Sflorian }
1606411c5950Sflorian 
1607411c5950Sflorian int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len)
1608411c5950Sflorian {
1609411c5950Sflorian 	if(hash->active == 384) {
1610411c5950Sflorian 		sha384_update(&hash->ctx384, len, data);
1611411c5950Sflorian 	} else if(hash->active == 512) {
1612411c5950Sflorian 		sha512_update(&hash->ctx512, len, data);
1613411c5950Sflorian 	} else {
1614411c5950Sflorian 		return 0;
1615411c5950Sflorian 	}
1616411c5950Sflorian 	return 1;
1617411c5950Sflorian }
1618411c5950Sflorian 
1619411c5950Sflorian int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result,
1620411c5950Sflorian         size_t maxlen, size_t* resultlen)
1621411c5950Sflorian {
1622411c5950Sflorian 	if(hash->active == 384) {
1623411c5950Sflorian 		if(SHA384_DIGEST_SIZE > maxlen) {
1624411c5950Sflorian 			*resultlen = 0;
1625411c5950Sflorian 			log_err("secalgo_hash_final: hash buffer too small");
1626411c5950Sflorian 			return 0;
1627411c5950Sflorian 		}
1628411c5950Sflorian 		*resultlen = SHA384_DIGEST_SIZE;
1629411c5950Sflorian 		sha384_digest(&hash->ctx384, SHA384_DIGEST_SIZE,
1630411c5950Sflorian 			(unsigned char*)result);
1631411c5950Sflorian 	} else if(hash->active == 512) {
1632411c5950Sflorian 		if(SHA512_DIGEST_SIZE > maxlen) {
1633411c5950Sflorian 			*resultlen = 0;
1634411c5950Sflorian 			log_err("secalgo_hash_final: hash buffer too small");
1635411c5950Sflorian 			return 0;
1636411c5950Sflorian 		}
1637411c5950Sflorian 		*resultlen = SHA512_DIGEST_SIZE;
1638411c5950Sflorian 		sha512_digest(&hash->ctx512, SHA512_DIGEST_SIZE,
1639411c5950Sflorian 			(unsigned char*)result);
1640411c5950Sflorian 	} else {
1641411c5950Sflorian 		*resultlen = 0;
1642411c5950Sflorian 		return 0;
1643411c5950Sflorian 	}
1644411c5950Sflorian 	return 1;
1645411c5950Sflorian }
1646411c5950Sflorian 
1647411c5950Sflorian void secalgo_hash_delete(struct secalgo_hash* hash)
1648411c5950Sflorian {
1649411c5950Sflorian 	if(!hash) return;
1650411c5950Sflorian 	free(hash);
1651411c5950Sflorian }
1652411c5950Sflorian 
1653ae8c6e27Sflorian /**
1654ae8c6e27Sflorian  * Return size of DS digest according to its hash algorithm.
1655ae8c6e27Sflorian  * @param algo: DS digest algo.
1656ae8c6e27Sflorian  * @return size in bytes of digest, or 0 if not supported.
1657ae8c6e27Sflorian  */
1658ae8c6e27Sflorian size_t
1659ae8c6e27Sflorian ds_digest_size_supported(int algo)
1660ae8c6e27Sflorian {
1661ae8c6e27Sflorian 	switch(algo) {
1662ae8c6e27Sflorian 		case LDNS_SHA1:
1663ae8c6e27Sflorian #ifdef USE_SHA1
1664ae8c6e27Sflorian 			return SHA1_DIGEST_SIZE;
1665ae8c6e27Sflorian #else
1666ae8c6e27Sflorian 			if(fake_sha1) return 20;
1667ae8c6e27Sflorian 			return 0;
1668ae8c6e27Sflorian #endif
1669ae8c6e27Sflorian #ifdef USE_SHA2
1670ae8c6e27Sflorian 		case LDNS_SHA256:
1671ae8c6e27Sflorian 			return SHA256_DIGEST_SIZE;
1672ae8c6e27Sflorian #endif
1673ae8c6e27Sflorian #ifdef USE_ECDSA
1674ae8c6e27Sflorian 		case LDNS_SHA384:
1675ae8c6e27Sflorian 			return SHA384_DIGEST_SIZE;
1676ae8c6e27Sflorian #endif
1677ae8c6e27Sflorian 		/* GOST not supported */
1678ae8c6e27Sflorian 		case LDNS_HASH_GOST:
1679ae8c6e27Sflorian 		default:
1680ae8c6e27Sflorian 			break;
1681ae8c6e27Sflorian 	}
1682ae8c6e27Sflorian 	return 0;
1683ae8c6e27Sflorian }
1684ae8c6e27Sflorian 
1685ae8c6e27Sflorian int
1686ae8c6e27Sflorian secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
1687ae8c6e27Sflorian 	unsigned char* res)
1688ae8c6e27Sflorian {
1689ae8c6e27Sflorian 	switch(algo) {
1690ae8c6e27Sflorian #ifdef USE_SHA1
1691ae8c6e27Sflorian 		case LDNS_SHA1:
1692ae8c6e27Sflorian 			return _digest_nettle(SHA1_DIGEST_SIZE, buf, len, res);
1693ae8c6e27Sflorian #endif
1694ae8c6e27Sflorian #if defined(USE_SHA2)
1695ae8c6e27Sflorian 		case LDNS_SHA256:
1696ae8c6e27Sflorian 			return _digest_nettle(SHA256_DIGEST_SIZE, buf, len, res);
1697ae8c6e27Sflorian #endif
1698ae8c6e27Sflorian #ifdef USE_ECDSA
1699ae8c6e27Sflorian 		case LDNS_SHA384:
1700ae8c6e27Sflorian 			return _digest_nettle(SHA384_DIGEST_SIZE, buf, len, res);
1701ae8c6e27Sflorian 
1702ae8c6e27Sflorian #endif
1703ae8c6e27Sflorian 		case LDNS_HASH_GOST:
1704ae8c6e27Sflorian 		default:
1705ae8c6e27Sflorian 			verbose(VERB_QUERY, "unknown DS digest algorithm %d",
1706ae8c6e27Sflorian 				algo);
1707ae8c6e27Sflorian 			break;
1708ae8c6e27Sflorian 	}
1709ae8c6e27Sflorian 	return 0;
1710ae8c6e27Sflorian }
1711ae8c6e27Sflorian 
1712ae8c6e27Sflorian int
1713ae8c6e27Sflorian dnskey_algo_id_is_supported(int id)
1714ae8c6e27Sflorian {
1715ae8c6e27Sflorian 	/* uses libnettle */
1716ae8c6e27Sflorian 	switch(id) {
1717ae8c6e27Sflorian 	case LDNS_DSA:
1718ae8c6e27Sflorian 	case LDNS_DSA_NSEC3:
1719d32eb43cSflorian #if defined(USE_DSA) && defined(USE_SHA1)
1720d32eb43cSflorian 		return 1;
1721d32eb43cSflorian #else
1722d32eb43cSflorian 		if(fake_dsa || fake_sha1) return 1;
1723d32eb43cSflorian 		return 0;
1724ae8c6e27Sflorian #endif
1725ae8c6e27Sflorian 	case LDNS_RSASHA1:
1726ae8c6e27Sflorian 	case LDNS_RSASHA1_NSEC3:
1727d32eb43cSflorian #ifdef USE_SHA1
1728d32eb43cSflorian 		return 1;
1729d32eb43cSflorian #else
1730d32eb43cSflorian 		if(fake_sha1) return 1;
1731d32eb43cSflorian 		return 0;
1732ae8c6e27Sflorian #endif
1733ae8c6e27Sflorian #ifdef USE_SHA2
1734ae8c6e27Sflorian 	case LDNS_RSASHA256:
1735ae8c6e27Sflorian 	case LDNS_RSASHA512:
1736ae8c6e27Sflorian #endif
1737ae8c6e27Sflorian #ifdef USE_ECDSA
1738ae8c6e27Sflorian 	case LDNS_ECDSAP256SHA256:
1739ae8c6e27Sflorian 	case LDNS_ECDSAP384SHA384:
1740ae8c6e27Sflorian #endif
1741ae8c6e27Sflorian 		return 1;
1742ae8c6e27Sflorian #ifdef USE_ED25519
1743ae8c6e27Sflorian 	case LDNS_ED25519:
1744ae8c6e27Sflorian 		return 1;
1745ae8c6e27Sflorian #endif
1746ae8c6e27Sflorian 	case LDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */
1747ae8c6e27Sflorian 	case LDNS_ECC_GOST:
1748ae8c6e27Sflorian 	default:
1749ae8c6e27Sflorian 		return 0;
1750ae8c6e27Sflorian 	}
1751ae8c6e27Sflorian }
1752ae8c6e27Sflorian 
1753ae8c6e27Sflorian #if defined(USE_DSA) && defined(USE_SHA1)
1754ae8c6e27Sflorian static char *
1755ae8c6e27Sflorian _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
1756ae8c6e27Sflorian 	unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
1757ae8c6e27Sflorian {
1758ae8c6e27Sflorian 	uint8_t digest[SHA1_DIGEST_SIZE];
1759ae8c6e27Sflorian 	uint8_t key_t_value;
1760ae8c6e27Sflorian 	int res = 0;
1761ae8c6e27Sflorian 	size_t offset;
1762ae8c6e27Sflorian 	struct dsa_public_key pubkey;
1763ae8c6e27Sflorian 	struct dsa_signature signature;
1764ae8c6e27Sflorian 	unsigned int expected_len;
1765ae8c6e27Sflorian 
1766ae8c6e27Sflorian 	/* Extract DSA signature from the record */
1767ae8c6e27Sflorian 	nettle_dsa_signature_init(&signature);
1768ae8c6e27Sflorian 	/* Signature length: 41 bytes - RFC 2536 sec. 3 */
1769ae8c6e27Sflorian 	if(sigblock_len == 41) {
1770ae8c6e27Sflorian 		if(key[0] != sigblock[0])
1771ae8c6e27Sflorian 			return "invalid T value in DSA signature or pubkey";
1772ae8c6e27Sflorian 		nettle_mpz_set_str_256_u(signature.r, 20, sigblock+1);
1773ae8c6e27Sflorian 		nettle_mpz_set_str_256_u(signature.s, 20, sigblock+1+20);
1774ae8c6e27Sflorian 	} else {
1775ae8c6e27Sflorian 		/* DER encoded, decode the ASN1 notated R and S bignums */
1776ae8c6e27Sflorian 		/* SEQUENCE { r INTEGER, s INTEGER } */
1777ae8c6e27Sflorian 		struct asn1_der_iterator i, seq;
1778ae8c6e27Sflorian 		if(asn1_der_iterator_first(&i, sigblock_len,
1779ae8c6e27Sflorian 			(uint8_t*)sigblock) != ASN1_ITERATOR_CONSTRUCTED
1780ae8c6e27Sflorian 			|| i.type != ASN1_SEQUENCE)
1781ae8c6e27Sflorian 			return "malformed DER encoded DSA signature";
1782ae8c6e27Sflorian 		/* decode this element of i using the seq iterator */
1783ae8c6e27Sflorian 		if(asn1_der_decode_constructed(&i, &seq) !=
1784ae8c6e27Sflorian 			ASN1_ITERATOR_PRIMITIVE || seq.type != ASN1_INTEGER)
1785ae8c6e27Sflorian 			return "malformed DER encoded DSA signature";
1786ae8c6e27Sflorian 		if(!asn1_der_get_bignum(&seq, signature.r, 20*8))
1787ae8c6e27Sflorian 			return "malformed DER encoded DSA signature";
1788ae8c6e27Sflorian 		if(asn1_der_iterator_next(&seq) != ASN1_ITERATOR_PRIMITIVE
1789ae8c6e27Sflorian 			|| seq.type != ASN1_INTEGER)
1790ae8c6e27Sflorian 			return "malformed DER encoded DSA signature";
1791ae8c6e27Sflorian 		if(!asn1_der_get_bignum(&seq, signature.s, 20*8))
1792ae8c6e27Sflorian 			return "malformed DER encoded DSA signature";
1793ae8c6e27Sflorian 		if(asn1_der_iterator_next(&i) != ASN1_ITERATOR_END)
1794ae8c6e27Sflorian 			return "malformed DER encoded DSA signature";
1795ae8c6e27Sflorian 	}
1796ae8c6e27Sflorian 
1797ae8c6e27Sflorian 	/* Validate T values constraints - RFC 2536 sec. 2 & sec. 3 */
1798ae8c6e27Sflorian 	key_t_value = key[0];
1799ae8c6e27Sflorian 	if (key_t_value > 8) {
1800ae8c6e27Sflorian 		return "invalid T value in DSA pubkey";
1801ae8c6e27Sflorian 	}
1802ae8c6e27Sflorian 
1803ae8c6e27Sflorian 	/* Pubkey minimum length: 21 bytes - RFC 2536 sec. 2 */
1804ae8c6e27Sflorian 	if (keylen < 21) {
1805ae8c6e27Sflorian 		return "DSA pubkey too short";
1806ae8c6e27Sflorian 	}
1807ae8c6e27Sflorian 
1808ae8c6e27Sflorian 	expected_len =   1 +		/* T */
1809ae8c6e27Sflorian 		        20 +		/* Q */
1810ae8c6e27Sflorian 		       (64 + key_t_value*8) +	/* P */
1811ae8c6e27Sflorian 		       (64 + key_t_value*8) +	/* G */
1812ae8c6e27Sflorian 		       (64 + key_t_value*8);	/* Y */
1813ae8c6e27Sflorian 	if (keylen != expected_len ) {
1814ae8c6e27Sflorian 		return "invalid DSA pubkey length";
1815ae8c6e27Sflorian 	}
1816ae8c6e27Sflorian 
1817ae8c6e27Sflorian 	/* Extract DSA pubkey from the record */
1818ae8c6e27Sflorian 	nettle_dsa_public_key_init(&pubkey);
1819ae8c6e27Sflorian 	offset = 1;
1820ae8c6e27Sflorian 	nettle_mpz_set_str_256_u(pubkey.q, 20, key+offset);
1821ae8c6e27Sflorian 	offset += 20;
1822ae8c6e27Sflorian 	nettle_mpz_set_str_256_u(pubkey.p, (64 + key_t_value*8), key+offset);
1823ae8c6e27Sflorian 	offset += (64 + key_t_value*8);
1824ae8c6e27Sflorian 	nettle_mpz_set_str_256_u(pubkey.g, (64 + key_t_value*8), key+offset);
1825ae8c6e27Sflorian 	offset += (64 + key_t_value*8);
1826ae8c6e27Sflorian 	nettle_mpz_set_str_256_u(pubkey.y, (64 + key_t_value*8), key+offset);
1827ae8c6e27Sflorian 
1828ae8c6e27Sflorian 	/* Digest content of "buf" and verify its DSA signature in "sigblock"*/
1829ae8c6e27Sflorian 	res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
1830ae8c6e27Sflorian 						(unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
1831ae8c6e27Sflorian 	res &= dsa_sha1_verify_digest(&pubkey, digest, &signature);
1832ae8c6e27Sflorian 
1833ae8c6e27Sflorian 	/* Clear and return */
1834ae8c6e27Sflorian 	nettle_dsa_signature_clear(&signature);
1835ae8c6e27Sflorian 	nettle_dsa_public_key_clear(&pubkey);
1836ae8c6e27Sflorian 	if (!res)
1837ae8c6e27Sflorian 		return "DSA signature verification failed";
1838ae8c6e27Sflorian 	else
1839ae8c6e27Sflorian 		return NULL;
1840ae8c6e27Sflorian }
1841ae8c6e27Sflorian #endif /* USE_DSA */
1842ae8c6e27Sflorian 
1843ae8c6e27Sflorian static char *
1844ae8c6e27Sflorian _verify_nettle_rsa(sldns_buffer* buf, unsigned int digest_size, char* sigblock,
1845ae8c6e27Sflorian 	unsigned int sigblock_len, uint8_t* key, unsigned int keylen)
1846ae8c6e27Sflorian {
1847ae8c6e27Sflorian 	uint16_t exp_len = 0;
1848ae8c6e27Sflorian 	size_t exp_offset = 0, mod_offset = 0;
1849ae8c6e27Sflorian 	struct rsa_public_key pubkey;
1850ae8c6e27Sflorian 	mpz_t signature;
1851ae8c6e27Sflorian 	int res = 0;
1852ae8c6e27Sflorian 
1853ae8c6e27Sflorian 	/* RSA pubkey parsing as per RFC 3110 sec. 2 */
1854ae8c6e27Sflorian 	if( keylen <= 1) {
1855ae8c6e27Sflorian 		return "null RSA key";
1856ae8c6e27Sflorian 	}
1857ae8c6e27Sflorian 	if (key[0] != 0) {
1858ae8c6e27Sflorian 		/* 1-byte length */
1859ae8c6e27Sflorian 		exp_len = key[0];
1860ae8c6e27Sflorian 		exp_offset = 1;
1861ae8c6e27Sflorian 	} else {
1862ae8c6e27Sflorian 		/* 1-byte NUL + 2-bytes exponent length */
1863ae8c6e27Sflorian 		if (keylen < 3) {
1864ae8c6e27Sflorian 			return "incorrect RSA key length";
1865ae8c6e27Sflorian 		}
1866ae8c6e27Sflorian 		exp_len = READ_UINT16(key+1);
1867ae8c6e27Sflorian 		if (exp_len == 0)
1868ae8c6e27Sflorian 			return "null RSA exponent length";
1869ae8c6e27Sflorian 		exp_offset = 3;
1870ae8c6e27Sflorian 	}
1871ae8c6e27Sflorian 	/* Check that we are not over-running input length */
1872ae8c6e27Sflorian 	if (keylen < exp_offset + exp_len + 1) {
1873ae8c6e27Sflorian 		return "RSA key content shorter than expected";
1874ae8c6e27Sflorian 	}
1875ae8c6e27Sflorian 	mod_offset = exp_offset + exp_len;
1876ae8c6e27Sflorian 	nettle_rsa_public_key_init(&pubkey);
1877ae8c6e27Sflorian 	pubkey.size = keylen - mod_offset;
1878ae8c6e27Sflorian 	nettle_mpz_set_str_256_u(pubkey.e, exp_len, &key[exp_offset]);
1879ae8c6e27Sflorian 	nettle_mpz_set_str_256_u(pubkey.n, pubkey.size, &key[mod_offset]);
1880ae8c6e27Sflorian 
1881ae8c6e27Sflorian 	/* Digest content of "buf" and verify its RSA signature in "sigblock"*/
1882ae8c6e27Sflorian 	nettle_mpz_init_set_str_256_u(signature, sigblock_len, (uint8_t*)sigblock);
1883ae8c6e27Sflorian 	switch (digest_size) {
1884ae8c6e27Sflorian 		case SHA1_DIGEST_SIZE:
1885ae8c6e27Sflorian 		{
1886ae8c6e27Sflorian 			uint8_t digest[SHA1_DIGEST_SIZE];
1887ae8c6e27Sflorian 			res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
1888ae8c6e27Sflorian 						(unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
1889ae8c6e27Sflorian 			res &= rsa_sha1_verify_digest(&pubkey, digest, signature);
1890ae8c6e27Sflorian 			break;
1891ae8c6e27Sflorian 		}
1892ae8c6e27Sflorian 		case SHA256_DIGEST_SIZE:
1893ae8c6e27Sflorian 		{
1894ae8c6e27Sflorian 			uint8_t digest[SHA256_DIGEST_SIZE];
1895ae8c6e27Sflorian 			res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
1896ae8c6e27Sflorian 						(unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
1897ae8c6e27Sflorian 			res &= rsa_sha256_verify_digest(&pubkey, digest, signature);
1898ae8c6e27Sflorian 			break;
1899ae8c6e27Sflorian 		}
1900ae8c6e27Sflorian 		case SHA512_DIGEST_SIZE:
1901ae8c6e27Sflorian 		{
1902ae8c6e27Sflorian 			uint8_t digest[SHA512_DIGEST_SIZE];
1903ae8c6e27Sflorian 			res = _digest_nettle(SHA512_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
1904ae8c6e27Sflorian 						(unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
1905ae8c6e27Sflorian 			res &= rsa_sha512_verify_digest(&pubkey, digest, signature);
1906ae8c6e27Sflorian 			break;
1907ae8c6e27Sflorian 		}
1908ae8c6e27Sflorian 		default:
1909ae8c6e27Sflorian 			break;
1910ae8c6e27Sflorian 	}
1911ae8c6e27Sflorian 
1912ae8c6e27Sflorian 	/* Clear and return */
1913ae8c6e27Sflorian 	nettle_rsa_public_key_clear(&pubkey);
1914ae8c6e27Sflorian 	mpz_clear(signature);
1915ae8c6e27Sflorian 	if (!res) {
1916ae8c6e27Sflorian 		return "RSA signature verification failed";
1917ae8c6e27Sflorian 	} else {
1918ae8c6e27Sflorian 		return NULL;
1919ae8c6e27Sflorian 	}
1920ae8c6e27Sflorian }
1921ae8c6e27Sflorian 
1922ae8c6e27Sflorian #ifdef USE_ECDSA
1923ae8c6e27Sflorian static char *
1924ae8c6e27Sflorian _verify_nettle_ecdsa(sldns_buffer* buf, unsigned int digest_size, unsigned char* sigblock,
1925ae8c6e27Sflorian 	unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
1926ae8c6e27Sflorian {
1927ae8c6e27Sflorian 	int res = 0;
1928ae8c6e27Sflorian 	struct ecc_point pubkey;
1929ae8c6e27Sflorian 	struct dsa_signature signature;
1930ae8c6e27Sflorian 
1931ae8c6e27Sflorian 	/* Always matched strength, as per RFC 6605 sec. 1 */
1932ae8c6e27Sflorian 	if (sigblock_len != 2*digest_size || keylen != 2*digest_size) {
1933ae8c6e27Sflorian 		return "wrong ECDSA signature length";
1934ae8c6e27Sflorian 	}
1935ae8c6e27Sflorian 
1936ae8c6e27Sflorian 	/* Parse ECDSA signature as per RFC 6605 sec. 4 */
1937ae8c6e27Sflorian 	nettle_dsa_signature_init(&signature);
1938ae8c6e27Sflorian 	switch (digest_size) {
1939ae8c6e27Sflorian 		case SHA256_DIGEST_SIZE:
1940ae8c6e27Sflorian 		{
1941ae8c6e27Sflorian 			uint8_t digest[SHA256_DIGEST_SIZE];
1942ae8c6e27Sflorian 			mpz_t x, y;
194357403691Sflorian 			nettle_ecc_point_init(&pubkey, nettle_get_secp_256r1());
1944ae8c6e27Sflorian 			nettle_mpz_init_set_str_256_u(x, SHA256_DIGEST_SIZE, key);
1945ae8c6e27Sflorian 			nettle_mpz_init_set_str_256_u(y, SHA256_DIGEST_SIZE, key+SHA256_DIGEST_SIZE);
1946ae8c6e27Sflorian 			nettle_mpz_set_str_256_u(signature.r, SHA256_DIGEST_SIZE, sigblock);
1947ae8c6e27Sflorian 			nettle_mpz_set_str_256_u(signature.s, SHA256_DIGEST_SIZE, sigblock+SHA256_DIGEST_SIZE);
1948ae8c6e27Sflorian 			res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
1949ae8c6e27Sflorian 						(unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
1950ae8c6e27Sflorian 			res &= nettle_ecc_point_set(&pubkey, x, y);
1951ae8c6e27Sflorian 			res &= nettle_ecdsa_verify (&pubkey, SHA256_DIGEST_SIZE, digest, &signature);
1952ae8c6e27Sflorian 			mpz_clear(x);
1953ae8c6e27Sflorian 			mpz_clear(y);
1954e47fef9eSflorian 			nettle_ecc_point_clear(&pubkey);
1955ae8c6e27Sflorian 			break;
1956ae8c6e27Sflorian 		}
1957ae8c6e27Sflorian 		case SHA384_DIGEST_SIZE:
1958ae8c6e27Sflorian 		{
1959ae8c6e27Sflorian 			uint8_t digest[SHA384_DIGEST_SIZE];
1960ae8c6e27Sflorian 			mpz_t x, y;
196157403691Sflorian 			nettle_ecc_point_init(&pubkey, nettle_get_secp_384r1());
1962ae8c6e27Sflorian 			nettle_mpz_init_set_str_256_u(x, SHA384_DIGEST_SIZE, key);
1963ae8c6e27Sflorian 			nettle_mpz_init_set_str_256_u(y, SHA384_DIGEST_SIZE, key+SHA384_DIGEST_SIZE);
1964ae8c6e27Sflorian 			nettle_mpz_set_str_256_u(signature.r, SHA384_DIGEST_SIZE, sigblock);
1965ae8c6e27Sflorian 			nettle_mpz_set_str_256_u(signature.s, SHA384_DIGEST_SIZE, sigblock+SHA384_DIGEST_SIZE);
1966ae8c6e27Sflorian 			res = _digest_nettle(SHA384_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
1967ae8c6e27Sflorian 						(unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
1968ae8c6e27Sflorian 			res &= nettle_ecc_point_set(&pubkey, x, y);
1969ae8c6e27Sflorian 			res &= nettle_ecdsa_verify (&pubkey, SHA384_DIGEST_SIZE, digest, &signature);
1970ae8c6e27Sflorian 			mpz_clear(x);
1971ae8c6e27Sflorian 			mpz_clear(y);
1972ae8c6e27Sflorian 			nettle_ecc_point_clear(&pubkey);
1973ae8c6e27Sflorian 			break;
1974ae8c6e27Sflorian 		}
1975ae8c6e27Sflorian 		default:
1976ae8c6e27Sflorian 			return "unknown ECDSA algorithm";
1977ae8c6e27Sflorian 	}
1978ae8c6e27Sflorian 
1979ae8c6e27Sflorian 	/* Clear and return */
1980ae8c6e27Sflorian 	nettle_dsa_signature_clear(&signature);
1981ae8c6e27Sflorian 	if (!res)
1982ae8c6e27Sflorian 		return "ECDSA signature verification failed";
1983ae8c6e27Sflorian 	else
1984ae8c6e27Sflorian 		return NULL;
1985ae8c6e27Sflorian }
1986ae8c6e27Sflorian #endif
1987ae8c6e27Sflorian 
1988ae8c6e27Sflorian #ifdef USE_ED25519
1989ae8c6e27Sflorian static char *
1990ae8c6e27Sflorian _verify_nettle_ed25519(sldns_buffer* buf, unsigned char* sigblock,
1991ae8c6e27Sflorian 	unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
1992ae8c6e27Sflorian {
1993ae8c6e27Sflorian 	int res = 0;
1994ae8c6e27Sflorian 
1995ae8c6e27Sflorian 	if(sigblock_len != ED25519_SIGNATURE_SIZE) {
1996ae8c6e27Sflorian 		return "wrong ED25519 signature length";
1997ae8c6e27Sflorian 	}
1998ae8c6e27Sflorian 	if(keylen != ED25519_KEY_SIZE) {
1999ae8c6e27Sflorian 		return "wrong ED25519 key length";
2000ae8c6e27Sflorian 	}
2001ae8c6e27Sflorian 
2002ae8c6e27Sflorian 	res = ed25519_sha512_verify((uint8_t*)key, sldns_buffer_limit(buf),
2003ae8c6e27Sflorian 		sldns_buffer_begin(buf), (uint8_t*)sigblock);
2004ae8c6e27Sflorian 
2005ae8c6e27Sflorian 	if (!res)
2006ae8c6e27Sflorian 		return "ED25519 signature verification failed";
2007ae8c6e27Sflorian 	else
2008ae8c6e27Sflorian 		return NULL;
2009ae8c6e27Sflorian }
2010ae8c6e27Sflorian #endif
2011ae8c6e27Sflorian 
2012ae8c6e27Sflorian /**
2013ae8c6e27Sflorian  * Check a canonical sig+rrset and signature against a dnskey
2014ae8c6e27Sflorian  * @param buf: buffer with data to verify, the first rrsig part and the
2015ae8c6e27Sflorian  *	canonicalized rrset.
2016ae8c6e27Sflorian  * @param algo: DNSKEY algorithm.
2017ae8c6e27Sflorian  * @param sigblock: signature rdata field from RRSIG
2018ae8c6e27Sflorian  * @param sigblock_len: length of sigblock data.
2019ae8c6e27Sflorian  * @param key: public key data from DNSKEY RR.
2020ae8c6e27Sflorian  * @param keylen: length of keydata.
2021ae8c6e27Sflorian  * @param reason: bogus reason in more detail.
2022ae8c6e27Sflorian  * @return secure if verification succeeded, bogus on crypto failure,
2023ae8c6e27Sflorian  *	unchecked on format errors and alloc failures.
2024ae8c6e27Sflorian  */
2025ae8c6e27Sflorian enum sec_status
2026ae8c6e27Sflorian verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
2027ae8c6e27Sflorian 	unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
2028ae8c6e27Sflorian 	char** reason)
2029ae8c6e27Sflorian {
2030ae8c6e27Sflorian 	unsigned int digest_size = 0;
2031ae8c6e27Sflorian 
2032ae8c6e27Sflorian 	if (sigblock_len == 0 || keylen == 0) {
2033ae8c6e27Sflorian 		*reason = "null signature";
2034ae8c6e27Sflorian 		return sec_status_bogus;
2035ae8c6e27Sflorian 	}
2036ae8c6e27Sflorian 
2037d32eb43cSflorian #ifndef USE_DSA
2038d32eb43cSflorian 	if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1))
2039d32eb43cSflorian 		return sec_status_secure;
2040d32eb43cSflorian #endif
2041d32eb43cSflorian #ifndef USE_SHA1
2042d32eb43cSflorian 	if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3))
2043d32eb43cSflorian 		return sec_status_secure;
2044d32eb43cSflorian #endif
2045d32eb43cSflorian 
2046ae8c6e27Sflorian 	switch(algo) {
2047ae8c6e27Sflorian #if defined(USE_DSA) && defined(USE_SHA1)
2048ae8c6e27Sflorian 	case LDNS_DSA:
2049ae8c6e27Sflorian 	case LDNS_DSA_NSEC3:
2050ae8c6e27Sflorian 		*reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen);
2051ae8c6e27Sflorian 		if (*reason != NULL)
2052ae8c6e27Sflorian 			return sec_status_bogus;
2053ae8c6e27Sflorian 		else
2054ae8c6e27Sflorian 			return sec_status_secure;
2055ae8c6e27Sflorian #endif /* USE_DSA */
2056ae8c6e27Sflorian 
2057ae8c6e27Sflorian #ifdef USE_SHA1
2058ae8c6e27Sflorian 	case LDNS_RSASHA1:
2059ae8c6e27Sflorian 	case LDNS_RSASHA1_NSEC3:
2060ae8c6e27Sflorian 		digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE);
2061ae8c6e27Sflorian #endif
2062ae8c6e27Sflorian 		/* double fallthrough annotation to please gcc parser */
2063*7037e34cSflorian 		ATTR_FALLTHROUGH
2064ae8c6e27Sflorian 		/* fallthrough */
2065ae8c6e27Sflorian #ifdef USE_SHA2
2066ae8c6e27Sflorian 		/* fallthrough */
2067ae8c6e27Sflorian 	case LDNS_RSASHA256:
2068ae8c6e27Sflorian 		digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
2069*7037e34cSflorian 		ATTR_FALLTHROUGH
2070ae8c6e27Sflorian 		/* fallthrough */
2071ae8c6e27Sflorian 	case LDNS_RSASHA512:
2072ae8c6e27Sflorian 		digest_size = (digest_size ? digest_size : SHA512_DIGEST_SIZE);
2073ae8c6e27Sflorian 
2074ae8c6e27Sflorian #endif
2075ae8c6e27Sflorian 		*reason = _verify_nettle_rsa(buf, digest_size, (char*)sigblock,
2076ae8c6e27Sflorian 						sigblock_len, key, keylen);
2077ae8c6e27Sflorian 		if (*reason != NULL)
2078ae8c6e27Sflorian 			return sec_status_bogus;
2079ae8c6e27Sflorian 		else
2080ae8c6e27Sflorian 			return sec_status_secure;
2081ae8c6e27Sflorian 
2082ae8c6e27Sflorian #ifdef USE_ECDSA
2083ae8c6e27Sflorian 	case LDNS_ECDSAP256SHA256:
2084ae8c6e27Sflorian 		digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
2085*7037e34cSflorian 		ATTR_FALLTHROUGH
2086ae8c6e27Sflorian 		/* fallthrough */
2087ae8c6e27Sflorian 	case LDNS_ECDSAP384SHA384:
2088ae8c6e27Sflorian 		digest_size = (digest_size ? digest_size : SHA384_DIGEST_SIZE);
2089ae8c6e27Sflorian 		*reason = _verify_nettle_ecdsa(buf, digest_size, sigblock,
2090ae8c6e27Sflorian 						sigblock_len, key, keylen);
2091ae8c6e27Sflorian 		if (*reason != NULL)
2092ae8c6e27Sflorian 			return sec_status_bogus;
2093ae8c6e27Sflorian 		else
2094ae8c6e27Sflorian 			return sec_status_secure;
2095ae8c6e27Sflorian #endif
2096ae8c6e27Sflorian #ifdef USE_ED25519
2097ae8c6e27Sflorian 	case LDNS_ED25519:
2098ae8c6e27Sflorian 		*reason = _verify_nettle_ed25519(buf, sigblock, sigblock_len,
2099ae8c6e27Sflorian 			key, keylen);
2100ae8c6e27Sflorian 		if (*reason != NULL)
2101ae8c6e27Sflorian 			return sec_status_bogus;
2102ae8c6e27Sflorian 		else
2103ae8c6e27Sflorian 			return sec_status_secure;
2104ae8c6e27Sflorian #endif
2105ae8c6e27Sflorian 	case LDNS_RSAMD5:
2106ae8c6e27Sflorian 	case LDNS_ECC_GOST:
2107ae8c6e27Sflorian 	default:
2108ae8c6e27Sflorian 		*reason = "unable to verify signature, unknown algorithm";
2109ae8c6e27Sflorian 		return sec_status_bogus;
2110ae8c6e27Sflorian 	}
2111ae8c6e27Sflorian }
2112ae8c6e27Sflorian 
2113ae8c6e27Sflorian #endif /* HAVE_SSL or HAVE_NSS or HAVE_NETTLE */
2114