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