2 * validator/val_secalgo.c - validator security algorithm functions.
4 * Copyright (c) 2012, NLnet Labs. All rights reserved.
6 * This software is open source.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
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.
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.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
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).
44 #include <ldns/ldns.h>
45 #include "validator/val_secalgo.h"
46 #include "util/data/packed_rrset.h"
49 #if !defined(HAVE_SSL) && !defined(HAVE_NSS)
50 #error "Need crypto library to do digital signature cryptography"
53 /* OpenSSL implementation */
55 #ifdef HAVE_OPENSSL_ERR_H
56 #include <openssl/err.h>
59 #ifdef HAVE_OPENSSL_RAND_H
60 #include <openssl/rand.h>
63 #ifdef HAVE_OPENSSL_CONF_H
64 #include <openssl/conf.h>
67 #ifdef HAVE_OPENSSL_ENGINE_H
68 #include <openssl/engine.h>
72 * Return size of DS digest according to its hash algorithm.
73 * @param algo: DS digest algo.
74 * @return size in bytes of digest, or 0 if not supported.
77 ds_digest_size_supported(int algo)
82 return SHA_DIGEST_LENGTH;
84 #ifdef HAVE_EVP_SHA256
86 return SHA256_DIGEST_LENGTH;
90 if(EVP_get_digestbyname("md_gost94"))
96 return SHA384_DIGEST_LENGTH;
104 /** Perform GOST hash */
106 do_gost94(unsigned char* data, size_t len, unsigned char* dest)
108 const EVP_MD* md = EVP_get_digestbyname("md_gost94");
111 return ldns_digest_evp(data, (unsigned int)len, dest, md);
116 secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
122 (void)SHA1(buf, len, res);
125 #ifdef HAVE_EVP_SHA256
127 (void)SHA256(buf, len, res);
132 if(do_gost94(buf, len, res))
138 (void)SHA384(buf, len, res);
142 verbose(VERB_QUERY, "unknown DS digest algorithm %d",
149 /** return true if DNSKEY algorithm id is supported */
151 dnskey_algo_id_is_supported(int id)
155 /* RFC 6725 deprecates RSAMD5 */
160 case LDNS_RSASHA1_NSEC3:
161 #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
164 #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
168 case LDNS_ECDSAP256SHA256:
169 case LDNS_ECDSAP384SHA384:
174 /* we support GOST if it can be loaded */
175 return ldns_key_EVP_load_gost_id();
183 * Output a libcrypto openssl error to the logfile.
184 * @param str: string to add to it.
185 * @param e: the error to output, error number from ERR_get_error().
188 log_crypto_error(const char* str, unsigned long e)
191 /* or use ERR_error_string if ERR_error_string_n is not avail TODO */
192 ERR_error_string_n(e, buf, sizeof(buf));
193 /* buf now contains */
194 /* error:[error code]:[library name]:[function name]:[reason string] */
195 log_err("%s crypto %s", str, buf);
199 * Setup DSA key digest in DER encoding ...
200 * @param sig: input is signature output alloced ptr (unless failure).
201 * caller must free alloced ptr if this routine returns true.
202 * @param len: input is initial siglen, output is output len.
203 * @return false on failure.
206 setup_dsa_sig(unsigned char** sig, unsigned int* len)
208 unsigned char* orig = *sig;
209 unsigned int origlen = *len;
214 /* extract the R and S field from the sig buffer */
215 if(origlen < 1 + 2*SHA_DIGEST_LENGTH)
219 (void) BN_bin2bn(orig + 1, SHA_DIGEST_LENGTH, R);
222 (void) BN_bin2bn(orig + 21, SHA_DIGEST_LENGTH, S);
223 dsasig = DSA_SIG_new();
224 if(!dsasig) return 0;
229 newlen = i2d_DSA_SIG(dsasig, sig);
231 DSA_SIG_free(dsasig);
235 *len = (unsigned int)newlen;
236 DSA_SIG_free(dsasig);
242 * Setup the ECDSA signature in its encoding that the library wants.
243 * Converts from plain numbers to ASN formatted.
244 * @param sig: input is signature, output alloced ptr (unless failure).
245 * caller must free alloced ptr if this routine returns true.
246 * @param len: input is initial siglen, output is output len.
247 * @return false on failure.
250 setup_ecdsa_sig(unsigned char** sig, unsigned int* len)
252 ECDSA_SIG* ecdsa_sig;
254 int bnsize = (int)((*len)/2);
255 /* if too short or not even length, fails */
256 if(*len < 16 || bnsize*2 != (int)*len)
258 /* use the raw data to parse two evenly long BIGNUMs, "r | s". */
259 ecdsa_sig = ECDSA_SIG_new();
260 if(!ecdsa_sig) return 0;
261 ecdsa_sig->r = BN_bin2bn(*sig, bnsize, ecdsa_sig->r);
262 ecdsa_sig->s = BN_bin2bn(*sig+bnsize, bnsize, ecdsa_sig->s);
263 if(!ecdsa_sig->r || !ecdsa_sig->s) {
264 ECDSA_SIG_free(ecdsa_sig);
268 /* spool it into ASN format */
270 newlen = i2d_ECDSA_SIG(ecdsa_sig, sig);
272 ECDSA_SIG_free(ecdsa_sig);
276 *len = (unsigned int)newlen;
277 ECDSA_SIG_free(ecdsa_sig);
280 #endif /* USE_ECDSA */
283 * Setup key and digest for verification. Adjust sig if necessary.
285 * @param algo: key algorithm
286 * @param evp_key: EVP PKEY public key to create.
287 * @param digest_type: digest type to use
288 * @param key: key to setup for.
289 * @param keylen: length of key.
290 * @return false on failure.
293 setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
294 unsigned char* key, size_t keylen)
302 *evp_key = EVP_PKEY_new();
304 log_err("verify: malloc failure in crypto");
307 dsa = ldns_key_buf2dsa_raw(key, keylen);
309 verbose(VERB_QUERY, "verify: "
310 "ldns_key_buf2dsa_raw failed");
313 if(EVP_PKEY_assign_DSA(*evp_key, dsa) == 0) {
314 verbose(VERB_QUERY, "verify: "
315 "EVP_PKEY_assign_DSA failed");
318 *digest_type = EVP_dss1();
322 case LDNS_RSASHA1_NSEC3:
323 #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
326 #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
329 *evp_key = EVP_PKEY_new();
331 log_err("verify: malloc failure in crypto");
334 rsa = ldns_key_buf2rsa_raw(key, keylen);
336 verbose(VERB_QUERY, "verify: "
337 "ldns_key_buf2rsa_raw SHA failed");
340 if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) {
341 verbose(VERB_QUERY, "verify: "
342 "EVP_PKEY_assign_RSA SHA failed");
346 /* select SHA version */
347 #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
348 if(algo == LDNS_RSASHA256)
349 *digest_type = EVP_sha256();
352 #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
353 if(algo == LDNS_RSASHA512)
354 *digest_type = EVP_sha512();
357 *digest_type = EVP_sha1();
361 *evp_key = EVP_PKEY_new();
363 log_err("verify: malloc failure in crypto");
366 rsa = ldns_key_buf2rsa_raw(key, keylen);
368 verbose(VERB_QUERY, "verify: "
369 "ldns_key_buf2rsa_raw MD5 failed");
372 if(EVP_PKEY_assign_RSA(*evp_key, rsa) == 0) {
373 verbose(VERB_QUERY, "verify: "
374 "EVP_PKEY_assign_RSA MD5 failed");
377 *digest_type = EVP_md5();
382 *evp_key = ldns_gost2pkey_raw(key, keylen);
384 verbose(VERB_QUERY, "verify: "
385 "ldns_gost2pkey_raw failed");
388 *digest_type = EVP_get_digestbyname("md_gost94");
390 verbose(VERB_QUERY, "verify: "
391 "EVP_getdigest md_gost94 failed");
397 case LDNS_ECDSAP256SHA256:
398 *evp_key = ldns_ecdsa2pkey_raw(key, keylen,
399 LDNS_ECDSAP256SHA256);
401 verbose(VERB_QUERY, "verify: "
402 "ldns_ecdsa2pkey_raw failed");
405 #ifdef USE_ECDSA_EVP_WORKAROUND
406 /* openssl before 1.0.0 fixes RSA with the SHA256
407 * hash in EVP. We create one for ecdsa_sha256 */
409 static int md_ecdsa_256_done = 0;
411 if(!md_ecdsa_256_done) {
412 EVP_MD m = *EVP_sha256();
413 md_ecdsa_256_done = 1;
414 m.required_pkey_type[0] = (*evp_key)->type;
415 m.verify = (void*)ECDSA_verify;
421 *digest_type = EVP_sha256();
424 case LDNS_ECDSAP384SHA384:
425 *evp_key = ldns_ecdsa2pkey_raw(key, keylen,
426 LDNS_ECDSAP384SHA384);
428 verbose(VERB_QUERY, "verify: "
429 "ldns_ecdsa2pkey_raw failed");
432 #ifdef USE_ECDSA_EVP_WORKAROUND
433 /* openssl before 1.0.0 fixes RSA with the SHA384
434 * hash in EVP. We create one for ecdsa_sha384 */
436 static int md_ecdsa_384_done = 0;
438 if(!md_ecdsa_384_done) {
439 EVP_MD m = *EVP_sha384();
440 md_ecdsa_384_done = 1;
441 m.required_pkey_type[0] = (*evp_key)->type;
442 m.verify = (void*)ECDSA_verify;
448 *digest_type = EVP_sha384();
451 #endif /* USE_ECDSA */
453 verbose(VERB_QUERY, "verify: unknown algorithm %d",
461 * Check a canonical sig+rrset and signature against a dnskey
462 * @param buf: buffer with data to verify, the first rrsig part and the
463 * canonicalized rrset.
464 * @param algo: DNSKEY algorithm.
465 * @param sigblock: signature rdata field from RRSIG
466 * @param sigblock_len: length of sigblock data.
467 * @param key: public key data from DNSKEY RR.
468 * @param keylen: length of keydata.
469 * @param reason: bogus reason in more detail.
470 * @return secure if verification succeeded, bogus on crypto failure,
471 * unchecked on format errors and alloc failures.
474 verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock,
475 unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
478 const EVP_MD *digest_type;
481 EVP_PKEY *evp_key = NULL;
483 if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) {
484 verbose(VERB_QUERY, "verify: failed to setup key");
485 *reason = "use of key for crypto failed";
486 EVP_PKEY_free(evp_key);
487 return sec_status_bogus;
489 /* if it is a DSA signature in bind format, convert to DER format */
490 if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&
491 sigblock_len == 1+2*SHA_DIGEST_LENGTH) {
492 if(!setup_dsa_sig(&sigblock, &sigblock_len)) {
493 verbose(VERB_QUERY, "verify: failed to setup DSA sig");
494 *reason = "use of key for DSA crypto failed";
495 EVP_PKEY_free(evp_key);
496 return sec_status_bogus;
501 else if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) {
502 /* EVP uses ASN prefix on sig, which is not in the wire data */
503 if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) {
504 verbose(VERB_QUERY, "verify: failed to setup ECDSA sig");
505 *reason = "use of signature for ECDSA crypto failed";
506 EVP_PKEY_free(evp_key);
507 return sec_status_bogus;
511 #endif /* USE_ECDSA */
513 /* do the signature cryptography work */
514 EVP_MD_CTX_init(&ctx);
515 if(EVP_VerifyInit(&ctx, digest_type) == 0) {
516 verbose(VERB_QUERY, "verify: EVP_VerifyInit failed");
517 EVP_PKEY_free(evp_key);
518 if(dofree) free(sigblock);
519 return sec_status_unchecked;
521 if(EVP_VerifyUpdate(&ctx, (unsigned char*)ldns_buffer_begin(buf),
522 (unsigned int)ldns_buffer_limit(buf)) == 0) {
523 verbose(VERB_QUERY, "verify: EVP_VerifyUpdate failed");
524 EVP_PKEY_free(evp_key);
525 if(dofree) free(sigblock);
526 return sec_status_unchecked;
529 res = EVP_VerifyFinal(&ctx, sigblock, sigblock_len, evp_key);
530 if(EVP_MD_CTX_cleanup(&ctx) == 0) {
531 verbose(VERB_QUERY, "verify: EVP_MD_CTX_cleanup failed");
532 EVP_PKEY_free(evp_key);
533 if(dofree) free(sigblock);
534 return sec_status_unchecked;
536 EVP_PKEY_free(evp_key);
542 return sec_status_secure;
543 } else if(res == 0) {
544 verbose(VERB_QUERY, "verify: signature mismatch");
545 *reason = "signature crypto failed";
546 return sec_status_bogus;
549 log_crypto_error("verify:", ERR_get_error());
550 return sec_status_unchecked;
553 /**************************************************/
554 #elif defined(HAVE_NSS)
555 /* libnss implementation */
561 #include "cryptohi.h"
566 ds_digest_size_supported(int algo)
574 return SHA256_LENGTH;
578 return SHA384_LENGTH;
580 /* GOST not supported in NSS */
588 secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
594 return HASH_HashBuf(HASH_AlgSHA1, res, buf, len)
596 #if defined(USE_SHA2)
598 return HASH_HashBuf(HASH_AlgSHA256, res, buf, len)
603 return HASH_HashBuf(HASH_AlgSHA384, res, buf, len)
608 verbose(VERB_QUERY, "unknown DS digest algorithm %d",
616 dnskey_algo_id_is_supported(int id)
621 /* RFC 6725 deprecates RSAMD5 */
626 case LDNS_RSASHA1_NSEC3:
635 case LDNS_ECDSAP256SHA256:
636 case LDNS_ECDSAP384SHA384:
637 return PK11_TokenExists(CKM_ECDSA);
645 /* return a new public key for NSS */
646 static SECKEYPublicKey* nss_key_create(KeyType ktype)
648 SECKEYPublicKey* key;
649 PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
651 log_err("out of memory, PORT_NewArena failed");
654 key = PORT_ArenaZNew(arena, SECKEYPublicKey);
656 log_err("out of memory, PORT_ArenaZNew failed");
657 PORT_FreeArena(arena, PR_FALSE);
661 key->keyType = ktype;
662 key->pkcs11Slot = NULL;
663 key->pkcs11ID = CK_INVALID_HANDLE;
667 static SECKEYPublicKey* nss_buf2ecdsa(unsigned char* key, size_t len, int algo)
670 SECItem pub = {siBuffer, NULL, 0};
671 SECItem params = {siBuffer, NULL, 0};
672 unsigned char param256[] = {
673 /* OBJECTIDENTIFIER 1.2.840.10045.3.1.7 (P-256)
674 * {iso(1) member-body(2) us(840) ansi-x962(10045) curves(3) prime(1) prime256v1(7)} */
675 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
677 unsigned char param384[] = {
678 /* OBJECTIDENTIFIER 1.3.132.0.34 (P-384)
679 * {iso(1) identified-organization(3) certicom(132) curve(0) ansip384r1(34)} */
680 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22
682 unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
684 /* check length, which uncompressed must be 2 bignums */
685 if(algo == LDNS_ECDSAP256SHA256) {
686 if(len != 2*256/8) return NULL;
687 /* ECCurve_X9_62_PRIME_256V1 */
688 } else if(algo == LDNS_ECDSAP384SHA384) {
689 if(len != 2*384/8) return NULL;
690 /* ECCurve_X9_62_PRIME_384R1 */
693 buf[0] = 0x04; /* POINT_FORM_UNCOMPRESSED */
694 memmove(buf+1, key, len);
697 if(algo == LDNS_ECDSAP256SHA256) {
698 params.data = param256;
699 params.len = sizeof(param256);
701 params.data = param384;
702 params.len = sizeof(param384);
705 pk = nss_key_create(ecKey);
708 pk->u.ec.size = (len/2)*8;
709 if(SECITEM_CopyItem(pk->arena, &pk->u.ec.publicValue, &pub)) {
710 SECKEY_DestroyPublicKey(pk);
713 if(SECITEM_CopyItem(pk->arena, &pk->u.ec.DEREncodedParams, ¶ms)) {
714 SECKEY_DestroyPublicKey(pk);
721 static SECKEYPublicKey* nss_buf2dsa(unsigned char* key, size_t len)
727 SECItem Q = {siBuffer, NULL, 0};
728 SECItem P = {siBuffer, NULL, 0};
729 SECItem G = {siBuffer, NULL, 0};
730 SECItem Y = {siBuffer, NULL, 0};
735 length = (64 + T * 8);
741 if(len < (size_t)1 + SHA1_LENGTH + 3*length)
746 offset += SHA1_LENGTH;
760 pk = nss_key_create(dsaKey);
763 if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.prime, &P)) {
764 SECKEY_DestroyPublicKey(pk);
767 if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.subPrime, &Q)) {
768 SECKEY_DestroyPublicKey(pk);
771 if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.base, &G)) {
772 SECKEY_DestroyPublicKey(pk);
775 if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.publicValue, &Y)) {
776 SECKEY_DestroyPublicKey(pk);
782 static SECKEYPublicKey* nss_buf2rsa(unsigned char* key, size_t len)
788 SECItem modulus = {siBuffer, NULL, 0};
789 SECItem exponent = {siBuffer, NULL, 0};
795 /* the exponent is too large so it's places further */
796 memmove(&int16, key+1, 2);
804 /* key length at least one */
805 if(len < (size_t)offset + exp + 1)
808 exponent.data = key+offset;
811 modulus.data = key+offset;
812 modulus.len = (len - offset);
814 pk = nss_key_create(rsaKey);
817 if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.modulus, &modulus)) {
818 SECKEY_DestroyPublicKey(pk);
821 if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.publicExponent, &exponent)) {
822 SECKEY_DestroyPublicKey(pk);
829 * Setup key and digest for verification. Adjust sig if necessary.
831 * @param algo: key algorithm
832 * @param evp_key: EVP PKEY public key to create.
833 * @param digest_type: digest type to use
834 * @param key: key to setup for.
835 * @param keylen: length of key.
836 * @param prefix: if returned, the ASN prefix for the hashblob.
837 * @param prefixlen: length of the prefix.
838 * @return false on failure.
841 nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
842 unsigned char* key, size_t keylen, unsigned char** prefix,
847 /* hash prefix for md5, RFC2537 */
848 unsigned char p_md5[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a,
849 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
850 /* hash prefix to prepend to hash output, from RFC3110 */
851 unsigned char p_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B,
852 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14};
854 unsigned char p_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
855 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
856 unsigned char p_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
857 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
859 /* for future RSASHA384 ..
860 unsigned char p_sha384[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
861 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
867 *pubkey = nss_buf2dsa(key, keylen);
869 log_err("verify: malloc failure in crypto");
872 *htype = HASH_AlgSHA1;
873 /* no prefix for DSA verification */
876 case LDNS_RSASHA1_NSEC3:
883 *pubkey = nss_buf2rsa(key, keylen);
885 log_err("verify: malloc failure in crypto");
888 /* select SHA version */
890 if(algo == LDNS_RSASHA256) {
891 *htype = HASH_AlgSHA256;
893 *prefixlen = sizeof(p_sha256);
897 if(algo == LDNS_RSASHA512) {
898 *htype = HASH_AlgSHA512;
900 *prefixlen = sizeof(p_sha512);
904 *htype = HASH_AlgSHA1;
906 *prefixlen = sizeof(p_sha1);
911 *pubkey = nss_buf2rsa(key, keylen);
913 log_err("verify: malloc failure in crypto");
916 *htype = HASH_AlgMD5;
918 *prefixlen = sizeof(p_md5);
922 case LDNS_ECDSAP256SHA256:
923 *pubkey = nss_buf2ecdsa(key, keylen,
924 LDNS_ECDSAP256SHA256);
926 log_err("verify: malloc failure in crypto");
929 *htype = HASH_AlgSHA256;
930 /* no prefix for DSA verification */
932 case LDNS_ECDSAP384SHA384:
933 *pubkey = nss_buf2ecdsa(key, keylen,
934 LDNS_ECDSAP384SHA384);
936 log_err("verify: malloc failure in crypto");
939 *htype = HASH_AlgSHA384;
940 /* no prefix for DSA verification */
942 #endif /* USE_ECDSA */
945 verbose(VERB_QUERY, "verify: unknown algorithm %d",
953 * Check a canonical sig+rrset and signature against a dnskey
954 * @param buf: buffer with data to verify, the first rrsig part and the
955 * canonicalized rrset.
956 * @param algo: DNSKEY algorithm.
957 * @param sigblock: signature rdata field from RRSIG
958 * @param sigblock_len: length of sigblock data.
959 * @param key: public key data from DNSKEY RR.
960 * @param keylen: length of keydata.
961 * @param reason: bogus reason in more detail.
962 * @return secure if verification succeeded, bogus on crypto failure,
963 * unchecked on format errors and alloc failures.
966 verify_canonrrset(ldns_buffer* buf, int algo, unsigned char* sigblock,
967 unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
971 /* large enough for the different hashes */
972 unsigned char hash[HASH_LENGTH_MAX];
973 unsigned char hash2[HASH_LENGTH_MAX*2];
974 HASH_HashType htype = 0;
975 SECKEYPublicKey* pubkey = NULL;
976 SECItem secsig = {siBuffer, sigblock, sigblock_len};
977 SECItem sechash = {siBuffer, hash, 0};
979 unsigned char* prefix = NULL; /* prefix for hash, RFC3110, RFC5702 */
980 size_t prefixlen = 0;
983 if(!nss_setup_key_digest(algo, &pubkey, &htype, key, keylen,
984 &prefix, &prefixlen)) {
985 verbose(VERB_QUERY, "verify: failed to setup key");
986 *reason = "use of key for crypto failed";
987 SECKEY_DestroyPublicKey(pubkey);
988 return sec_status_bogus;
991 /* need to convert DSA, ECDSA signatures? */
992 if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) {
993 if(sigblock_len == 1+2*SHA1_LENGTH) {
997 SECItem* p = DSAU_DecodeDerSig(&secsig);
999 verbose(VERB_QUERY, "verify: failed DER decode");
1000 *reason = "signature DER decode failed";
1001 SECKEY_DestroyPublicKey(pubkey);
1002 return sec_status_bogus;
1004 if(SECITEM_CopyItem(pubkey->arena, &secsig, p)) {
1005 log_err("alloc failure in DER decode");
1006 SECKEY_DestroyPublicKey(pubkey);
1007 SECITEM_FreeItem(p, PR_TRUE);
1008 return sec_status_unchecked;
1010 SECITEM_FreeItem(p, PR_TRUE);
1014 /* do the signature cryptography work */
1016 sechash.len = HASH_ResultLen(htype);
1017 if(sechash.len > sizeof(hash)) {
1018 verbose(VERB_QUERY, "verify: hash too large for buffer");
1019 SECKEY_DestroyPublicKey(pubkey);
1020 return sec_status_unchecked;
1022 if(HASH_HashBuf(htype, hash, (unsigned char*)ldns_buffer_begin(buf),
1023 (unsigned int)ldns_buffer_limit(buf)) != SECSuccess) {
1024 verbose(VERB_QUERY, "verify: HASH_HashBuf failed");
1025 SECKEY_DestroyPublicKey(pubkey);
1026 return sec_status_unchecked;
1029 int hashlen = sechash.len;
1030 if(prefixlen+hashlen > sizeof(hash2)) {
1031 verbose(VERB_QUERY, "verify: hashprefix too large");
1032 SECKEY_DestroyPublicKey(pubkey);
1033 return sec_status_unchecked;
1035 sechash.data = hash2;
1036 sechash.len = prefixlen+hashlen;
1037 memcpy(sechash.data, prefix, prefixlen);
1038 memmove(sechash.data+prefixlen, hash, hashlen);
1041 /* verify the signature */
1042 res = PK11_Verify(pubkey, &secsig, &sechash, NULL /*wincx*/);
1043 SECKEY_DestroyPublicKey(pubkey);
1045 if(res == SECSuccess) {
1046 return sec_status_secure;
1048 err = PORT_GetError();
1049 if(err != SEC_ERROR_BAD_SIGNATURE) {
1050 /* failed to verify */
1051 verbose(VERB_QUERY, "verify: PK11_Verify failed: %s",
1052 PORT_ErrorToString(err));
1053 /* if it is not supported, like ECC is removed, we get,
1054 * SEC_ERROR_NO_MODULE */
1055 if(err == SEC_ERROR_NO_MODULE)
1056 return sec_status_unchecked;
1057 /* but other errors are commonly returned
1058 * for a bad signature from NSS. Thus we return bogus,
1060 *reason = "signature crypto failed";
1061 return sec_status_bogus;
1063 verbose(VERB_QUERY, "verify: signature mismatch: %s",
1064 PORT_ErrorToString(err));
1065 *reason = "signature crypto failed";
1066 return sec_status_bogus;
1070 #endif /* HAVE_SSL or HAVE_NSS */