18ed2b524SDag-Erling Smørgrav /*
28ed2b524SDag-Erling Smørgrav * validator/val_secalgo.c - validator security algorithm functions.
38ed2b524SDag-Erling Smørgrav *
48ed2b524SDag-Erling Smørgrav * Copyright (c) 2012, NLnet Labs. All rights reserved.
58ed2b524SDag-Erling Smørgrav *
68ed2b524SDag-Erling Smørgrav * This software is open source.
78ed2b524SDag-Erling Smørgrav *
88ed2b524SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without
98ed2b524SDag-Erling Smørgrav * modification, are permitted provided that the following conditions
108ed2b524SDag-Erling Smørgrav * are met:
118ed2b524SDag-Erling Smørgrav *
128ed2b524SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice,
138ed2b524SDag-Erling Smørgrav * this list of conditions and the following disclaimer.
148ed2b524SDag-Erling Smørgrav *
158ed2b524SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice,
168ed2b524SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation
178ed2b524SDag-Erling Smørgrav * and/or other materials provided with the distribution.
188ed2b524SDag-Erling Smørgrav *
198ed2b524SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may
208ed2b524SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without
218ed2b524SDag-Erling Smørgrav * specific prior written permission.
228ed2b524SDag-Erling Smørgrav *
238ed2b524SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2417d15b25SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2517d15b25SDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2617d15b25SDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2717d15b25SDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2817d15b25SDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2917d15b25SDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3017d15b25SDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3117d15b25SDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3217d15b25SDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3317d15b25SDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
348ed2b524SDag-Erling Smørgrav */
358ed2b524SDag-Erling Smørgrav
368ed2b524SDag-Erling Smørgrav /**
378ed2b524SDag-Erling Smørgrav * \file
388ed2b524SDag-Erling Smørgrav *
398ed2b524SDag-Erling Smørgrav * This file contains helper functions for the validator module.
408ed2b524SDag-Erling Smørgrav * These functions take raw data buffers, formatted for crypto verification,
418ed2b524SDag-Erling Smørgrav * and do the library calls (for the crypto library in use).
428ed2b524SDag-Erling Smørgrav */
438ed2b524SDag-Erling Smørgrav #include "config.h"
446480faa8SDag-Erling Smørgrav /* packed_rrset on top to define enum types (forced by c99 standard) */
458ed2b524SDag-Erling Smørgrav #include "util/data/packed_rrset.h"
466480faa8SDag-Erling Smørgrav #include "validator/val_secalgo.h"
4705ab2901SDag-Erling Smørgrav #include "validator/val_nsec3.h"
488ed2b524SDag-Erling Smørgrav #include "util/log.h"
4909a3aaf3SDag-Erling Smørgrav #include "sldns/rrdef.h"
5009a3aaf3SDag-Erling Smørgrav #include "sldns/keyraw.h"
5109a3aaf3SDag-Erling Smørgrav #include "sldns/sbuffer.h"
528ed2b524SDag-Erling Smørgrav
5305ab2901SDag-Erling Smørgrav #if !defined(HAVE_SSL) && !defined(HAVE_NSS) && !defined(HAVE_NETTLE)
548ed2b524SDag-Erling Smørgrav #error "Need crypto library to do digital signature cryptography"
558ed2b524SDag-Erling Smørgrav #endif
568ed2b524SDag-Erling Smørgrav
57091e9e46SCy Schubert /** fake DSA support for unit tests */
58091e9e46SCy Schubert int fake_dsa = 0;
59091e9e46SCy Schubert /** fake SHA1 support for unit tests */
60091e9e46SCy Schubert int fake_sha1 = 0;
61091e9e46SCy Schubert
628ed2b524SDag-Erling Smørgrav /* OpenSSL implementation */
638ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL
648ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ERR_H
658ed2b524SDag-Erling Smørgrav #include <openssl/err.h>
668ed2b524SDag-Erling Smørgrav #endif
678ed2b524SDag-Erling Smørgrav
688ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_RAND_H
698ed2b524SDag-Erling Smørgrav #include <openssl/rand.h>
708ed2b524SDag-Erling Smørgrav #endif
718ed2b524SDag-Erling Smørgrav
728ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_CONF_H
738ed2b524SDag-Erling Smørgrav #include <openssl/conf.h>
748ed2b524SDag-Erling Smørgrav #endif
758ed2b524SDag-Erling Smørgrav
768ed2b524SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ENGINE_H
778ed2b524SDag-Erling Smørgrav #include <openssl/engine.h>
788ed2b524SDag-Erling Smørgrav #endif
798ed2b524SDag-Erling Smørgrav
8025039b37SCy Schubert #if defined(HAVE_OPENSSL_DSA_H) && defined(USE_DSA)
8125039b37SCy Schubert #include <openssl/dsa.h>
8225039b37SCy Schubert #endif
8325039b37SCy Schubert
84a755b6f6SDag-Erling Smørgrav /**
85a755b6f6SDag-Erling Smørgrav * Output a libcrypto openssl error to the logfile.
86a755b6f6SDag-Erling Smørgrav * @param str: string to add to it.
87a755b6f6SDag-Erling Smørgrav * @param e: the error to output, error number from ERR_get_error().
88a755b6f6SDag-Erling Smørgrav */
89a755b6f6SDag-Erling Smørgrav static void
log_crypto_error(const char * str,unsigned long e)90a755b6f6SDag-Erling Smørgrav log_crypto_error(const char* str, unsigned long e)
91a755b6f6SDag-Erling Smørgrav {
92a755b6f6SDag-Erling Smørgrav char buf[128];
93a755b6f6SDag-Erling Smørgrav /* or use ERR_error_string if ERR_error_string_n is not avail TODO */
94a755b6f6SDag-Erling Smørgrav ERR_error_string_n(e, buf, sizeof(buf));
95a755b6f6SDag-Erling Smørgrav /* buf now contains */
96a755b6f6SDag-Erling Smørgrav /* error:[error code]:[library name]:[function name]:[reason string] */
97a755b6f6SDag-Erling Smørgrav log_err("%s crypto %s", str, buf);
98a755b6f6SDag-Erling Smørgrav }
99a755b6f6SDag-Erling Smørgrav
1000a92a9fcSCy Schubert /**
1010a92a9fcSCy Schubert * Output a libcrypto openssl error to the logfile as a debug message.
1020a92a9fcSCy Schubert * @param level: debug level to use in verbose() call
1030a92a9fcSCy Schubert * @param str: string to add to it.
1040a92a9fcSCy Schubert * @param e: the error to output, error number from ERR_get_error().
1050a92a9fcSCy Schubert */
1060a92a9fcSCy Schubert static void
log_crypto_verbose(enum verbosity_value level,const char * str,unsigned long e)1070a92a9fcSCy Schubert log_crypto_verbose(enum verbosity_value level, const char* str, unsigned long e)
1080a92a9fcSCy Schubert {
1090a92a9fcSCy Schubert char buf[128];
1100a92a9fcSCy Schubert /* or use ERR_error_string if ERR_error_string_n is not avail TODO */
1110a92a9fcSCy Schubert ERR_error_string_n(e, buf, sizeof(buf));
1120a92a9fcSCy Schubert /* buf now contains */
1130a92a9fcSCy Schubert /* error:[error code]:[library name]:[function name]:[reason string] */
1140a92a9fcSCy Schubert verbose(level, "%s crypto %s", str, buf);
1150a92a9fcSCy Schubert }
1160a92a9fcSCy Schubert
11705ab2901SDag-Erling Smørgrav /* return size of digest if supported, or 0 otherwise */
11805ab2901SDag-Erling Smørgrav size_t
nsec3_hash_algo_size_supported(int id)11905ab2901SDag-Erling Smørgrav nsec3_hash_algo_size_supported(int id)
12005ab2901SDag-Erling Smørgrav {
12105ab2901SDag-Erling Smørgrav switch(id) {
12205ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1:
12305ab2901SDag-Erling Smørgrav return SHA_DIGEST_LENGTH;
12405ab2901SDag-Erling Smørgrav default:
12505ab2901SDag-Erling Smørgrav return 0;
12605ab2901SDag-Erling Smørgrav }
12705ab2901SDag-Erling Smørgrav }
12805ab2901SDag-Erling Smørgrav
12905ab2901SDag-Erling Smørgrav /* perform nsec3 hash. return false on failure */
13005ab2901SDag-Erling Smørgrav int
secalgo_nsec3_hash(int algo,unsigned char * buf,size_t len,unsigned char * res)13105ab2901SDag-Erling Smørgrav secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
13205ab2901SDag-Erling Smørgrav unsigned char* res)
13305ab2901SDag-Erling Smørgrav {
13405ab2901SDag-Erling Smørgrav switch(algo) {
13505ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1:
136a755b6f6SDag-Erling Smørgrav #ifdef OPENSSL_FIPS
137a755b6f6SDag-Erling Smørgrav if(!sldns_digest_evp(buf, len, res, EVP_sha1()))
138a755b6f6SDag-Erling Smørgrav log_crypto_error("could not digest with EVP_sha1",
139a755b6f6SDag-Erling Smørgrav ERR_get_error());
140a755b6f6SDag-Erling Smørgrav #else
14105ab2901SDag-Erling Smørgrav (void)SHA1(buf, len, res);
142a755b6f6SDag-Erling Smørgrav #endif
14305ab2901SDag-Erling Smørgrav return 1;
14405ab2901SDag-Erling Smørgrav default:
14505ab2901SDag-Erling Smørgrav return 0;
14605ab2901SDag-Erling Smørgrav }
14705ab2901SDag-Erling Smørgrav }
14805ab2901SDag-Erling Smørgrav
149e2d15004SDag-Erling Smørgrav void
secalgo_hash_sha256(unsigned char * buf,size_t len,unsigned char * res)150e2d15004SDag-Erling Smørgrav secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
151e2d15004SDag-Erling Smørgrav {
152a755b6f6SDag-Erling Smørgrav #ifdef OPENSSL_FIPS
153a755b6f6SDag-Erling Smørgrav if(!sldns_digest_evp(buf, len, res, EVP_sha256()))
154a755b6f6SDag-Erling Smørgrav log_crypto_error("could not digest with EVP_sha256",
155a755b6f6SDag-Erling Smørgrav ERR_get_error());
156a755b6f6SDag-Erling Smørgrav #else
157e2d15004SDag-Erling Smørgrav (void)SHA256(buf, len, res);
158a755b6f6SDag-Erling Smørgrav #endif
159e2d15004SDag-Erling Smørgrav }
160e2d15004SDag-Erling Smørgrav
1615469a995SCy Schubert /** hash structure for keeping track of running hashes */
1625469a995SCy Schubert struct secalgo_hash {
1635469a995SCy Schubert /** the openssl message digest context */
1645469a995SCy Schubert EVP_MD_CTX* ctx;
1655469a995SCy Schubert };
1665469a995SCy Schubert
1675469a995SCy Schubert /** create secalgo hash with hash type */
secalgo_hash_create_md(const EVP_MD * md)1685469a995SCy Schubert static struct secalgo_hash* secalgo_hash_create_md(const EVP_MD* md)
1695469a995SCy Schubert {
1705469a995SCy Schubert struct secalgo_hash* h;
1715469a995SCy Schubert if(!md)
1725469a995SCy Schubert return NULL;
1735469a995SCy Schubert h = calloc(1, sizeof(*h));
1745469a995SCy Schubert if(!h)
1755469a995SCy Schubert return NULL;
1765469a995SCy Schubert h->ctx = EVP_MD_CTX_create();
1775469a995SCy Schubert if(!h->ctx) {
1785469a995SCy Schubert free(h);
1795469a995SCy Schubert return NULL;
1805469a995SCy Schubert }
1815469a995SCy Schubert if(!EVP_DigestInit_ex(h->ctx, md, NULL)) {
1825469a995SCy Schubert EVP_MD_CTX_destroy(h->ctx);
1835469a995SCy Schubert free(h);
1845469a995SCy Schubert return NULL;
1855469a995SCy Schubert }
1865469a995SCy Schubert return h;
1875469a995SCy Schubert }
1885469a995SCy Schubert
secalgo_hash_create_sha384(void)1895469a995SCy Schubert struct secalgo_hash* secalgo_hash_create_sha384(void)
1905469a995SCy Schubert {
1915469a995SCy Schubert return secalgo_hash_create_md(EVP_sha384());
1925469a995SCy Schubert }
1935469a995SCy Schubert
secalgo_hash_create_sha512(void)1945469a995SCy Schubert struct secalgo_hash* secalgo_hash_create_sha512(void)
1955469a995SCy Schubert {
1965469a995SCy Schubert return secalgo_hash_create_md(EVP_sha512());
1975469a995SCy Schubert }
1985469a995SCy Schubert
secalgo_hash_update(struct secalgo_hash * hash,uint8_t * data,size_t len)1995469a995SCy Schubert int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len)
2005469a995SCy Schubert {
2015469a995SCy Schubert return EVP_DigestUpdate(hash->ctx, (unsigned char*)data,
2025469a995SCy Schubert (unsigned int)len);
2035469a995SCy Schubert }
2045469a995SCy Schubert
secalgo_hash_final(struct secalgo_hash * hash,uint8_t * result,size_t maxlen,size_t * resultlen)2055469a995SCy Schubert int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result,
2065469a995SCy Schubert size_t maxlen, size_t* resultlen)
2075469a995SCy Schubert {
2085469a995SCy Schubert if(EVP_MD_CTX_size(hash->ctx) > (int)maxlen) {
2095469a995SCy Schubert *resultlen = 0;
2105469a995SCy Schubert log_err("secalgo_hash_final: hash buffer too small");
2115469a995SCy Schubert return 0;
2125469a995SCy Schubert }
2135469a995SCy Schubert *resultlen = EVP_MD_CTX_size(hash->ctx);
2145469a995SCy Schubert return EVP_DigestFinal_ex(hash->ctx, result, NULL);
2155469a995SCy Schubert }
2165469a995SCy Schubert
secalgo_hash_delete(struct secalgo_hash * hash)2175469a995SCy Schubert void secalgo_hash_delete(struct secalgo_hash* hash)
2185469a995SCy Schubert {
2195469a995SCy Schubert if(!hash) return;
2205469a995SCy Schubert EVP_MD_CTX_destroy(hash->ctx);
2215469a995SCy Schubert free(hash);
2225469a995SCy Schubert }
2235469a995SCy Schubert
2248ed2b524SDag-Erling Smørgrav /**
2258ed2b524SDag-Erling Smørgrav * Return size of DS digest according to its hash algorithm.
2268ed2b524SDag-Erling Smørgrav * @param algo: DS digest algo.
2278ed2b524SDag-Erling Smørgrav * @return size in bytes of digest, or 0 if not supported.
2288ed2b524SDag-Erling Smørgrav */
2298ed2b524SDag-Erling Smørgrav size_t
ds_digest_size_supported(int algo)2308ed2b524SDag-Erling Smørgrav ds_digest_size_supported(int algo)
2318ed2b524SDag-Erling Smørgrav {
2328ed2b524SDag-Erling Smørgrav switch(algo) {
2338ed2b524SDag-Erling Smørgrav case LDNS_SHA1:
23465b390aaSDag-Erling Smørgrav #if defined(HAVE_EVP_SHA1) && defined(USE_SHA1)
2350a92a9fcSCy Schubert #ifdef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED
2360a92a9fcSCy Schubert if (EVP_default_properties_is_fips_enabled(NULL))
2370a92a9fcSCy Schubert return 0;
2380a92a9fcSCy Schubert #endif
2398ed2b524SDag-Erling Smørgrav return SHA_DIGEST_LENGTH;
24065b390aaSDag-Erling Smørgrav #else
24165b390aaSDag-Erling Smørgrav if(fake_sha1) return 20;
24265b390aaSDag-Erling Smørgrav return 0;
2438ed2b524SDag-Erling Smørgrav #endif
2448ed2b524SDag-Erling Smørgrav #ifdef HAVE_EVP_SHA256
2458ed2b524SDag-Erling Smørgrav case LDNS_SHA256:
2468ed2b524SDag-Erling Smørgrav return SHA256_DIGEST_LENGTH;
2478ed2b524SDag-Erling Smørgrav #endif
2488ed2b524SDag-Erling Smørgrav #ifdef USE_GOST
2498ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST:
250f61ef7f6SDag-Erling Smørgrav /* we support GOST if it can be loaded */
251f61ef7f6SDag-Erling Smørgrav (void)sldns_key_EVP_load_gost_id();
2528ed2b524SDag-Erling Smørgrav if(EVP_get_digestbyname("md_gost94"))
2538ed2b524SDag-Erling Smørgrav return 32;
2548ed2b524SDag-Erling Smørgrav else return 0;
2558ed2b524SDag-Erling Smørgrav #endif
2568ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA
2578ed2b524SDag-Erling Smørgrav case LDNS_SHA384:
2588ed2b524SDag-Erling Smørgrav return SHA384_DIGEST_LENGTH;
2598ed2b524SDag-Erling Smørgrav #endif
2608ed2b524SDag-Erling Smørgrav default: break;
2618ed2b524SDag-Erling Smørgrav }
2628ed2b524SDag-Erling Smørgrav return 0;
2638ed2b524SDag-Erling Smørgrav }
2648ed2b524SDag-Erling Smørgrav
2658ed2b524SDag-Erling Smørgrav #ifdef USE_GOST
2668ed2b524SDag-Erling Smørgrav /** Perform GOST hash */
2678ed2b524SDag-Erling Smørgrav static int
do_gost94(unsigned char * data,size_t len,unsigned char * dest)2688ed2b524SDag-Erling Smørgrav do_gost94(unsigned char* data, size_t len, unsigned char* dest)
2698ed2b524SDag-Erling Smørgrav {
2708ed2b524SDag-Erling Smørgrav const EVP_MD* md = EVP_get_digestbyname("md_gost94");
2718ed2b524SDag-Erling Smørgrav if(!md)
2728ed2b524SDag-Erling Smørgrav return 0;
27317d15b25SDag-Erling Smørgrav return sldns_digest_evp(data, (unsigned int)len, dest, md);
2748ed2b524SDag-Erling Smørgrav }
2758ed2b524SDag-Erling Smørgrav #endif
2768ed2b524SDag-Erling Smørgrav
2778ed2b524SDag-Erling Smørgrav int
secalgo_ds_digest(int algo,unsigned char * buf,size_t len,unsigned char * res)2788ed2b524SDag-Erling Smørgrav secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
2798ed2b524SDag-Erling Smørgrav unsigned char* res)
2808ed2b524SDag-Erling Smørgrav {
2818ed2b524SDag-Erling Smørgrav switch(algo) {
28265b390aaSDag-Erling Smørgrav #if defined(HAVE_EVP_SHA1) && defined(USE_SHA1)
2838ed2b524SDag-Erling Smørgrav case LDNS_SHA1:
284a755b6f6SDag-Erling Smørgrav #ifdef OPENSSL_FIPS
285a755b6f6SDag-Erling Smørgrav if(!sldns_digest_evp(buf, len, res, EVP_sha1()))
286a755b6f6SDag-Erling Smørgrav log_crypto_error("could not digest with EVP_sha1",
287a755b6f6SDag-Erling Smørgrav ERR_get_error());
288a755b6f6SDag-Erling Smørgrav #else
2898ed2b524SDag-Erling Smørgrav (void)SHA1(buf, len, res);
290a755b6f6SDag-Erling Smørgrav #endif
2918ed2b524SDag-Erling Smørgrav return 1;
2928ed2b524SDag-Erling Smørgrav #endif
2938ed2b524SDag-Erling Smørgrav #ifdef HAVE_EVP_SHA256
2948ed2b524SDag-Erling Smørgrav case LDNS_SHA256:
295a755b6f6SDag-Erling Smørgrav #ifdef OPENSSL_FIPS
296a755b6f6SDag-Erling Smørgrav if(!sldns_digest_evp(buf, len, res, EVP_sha256()))
297a755b6f6SDag-Erling Smørgrav log_crypto_error("could not digest with EVP_sha256",
298a755b6f6SDag-Erling Smørgrav ERR_get_error());
299a755b6f6SDag-Erling Smørgrav #else
3008ed2b524SDag-Erling Smørgrav (void)SHA256(buf, len, res);
301a755b6f6SDag-Erling Smørgrav #endif
3028ed2b524SDag-Erling Smørgrav return 1;
3038ed2b524SDag-Erling Smørgrav #endif
3048ed2b524SDag-Erling Smørgrav #ifdef USE_GOST
3058ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST:
3068ed2b524SDag-Erling Smørgrav if(do_gost94(buf, len, res))
3078ed2b524SDag-Erling Smørgrav return 1;
3088ed2b524SDag-Erling Smørgrav break;
3098ed2b524SDag-Erling Smørgrav #endif
3108ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA
3118ed2b524SDag-Erling Smørgrav case LDNS_SHA384:
312a755b6f6SDag-Erling Smørgrav #ifdef OPENSSL_FIPS
313a755b6f6SDag-Erling Smørgrav if(!sldns_digest_evp(buf, len, res, EVP_sha384()))
314a755b6f6SDag-Erling Smørgrav log_crypto_error("could not digest with EVP_sha384",
315a755b6f6SDag-Erling Smørgrav ERR_get_error());
316a755b6f6SDag-Erling Smørgrav #else
3178ed2b524SDag-Erling Smørgrav (void)SHA384(buf, len, res);
318a755b6f6SDag-Erling Smørgrav #endif
3198ed2b524SDag-Erling Smørgrav return 1;
3208ed2b524SDag-Erling Smørgrav #endif
3218ed2b524SDag-Erling Smørgrav default:
3228ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "unknown DS digest algorithm %d",
3238ed2b524SDag-Erling Smørgrav algo);
3248ed2b524SDag-Erling Smørgrav break;
3258ed2b524SDag-Erling Smørgrav }
3268ed2b524SDag-Erling Smørgrav return 0;
3278ed2b524SDag-Erling Smørgrav }
3288ed2b524SDag-Erling Smørgrav
3298ed2b524SDag-Erling Smørgrav /** return true if DNSKEY algorithm id is supported */
3308ed2b524SDag-Erling Smørgrav int
dnskey_algo_id_is_supported(int id)3318ed2b524SDag-Erling Smørgrav dnskey_algo_id_is_supported(int id)
3328ed2b524SDag-Erling Smørgrav {
3338ed2b524SDag-Erling Smørgrav switch(id) {
3348ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5:
3358ed2b524SDag-Erling Smørgrav /* RFC 6725 deprecates RSAMD5 */
3368ed2b524SDag-Erling Smørgrav return 0;
3378ed2b524SDag-Erling Smørgrav case LDNS_DSA:
3388ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3:
33965b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1)
340bc892140SDag-Erling Smørgrav return 1;
341bc892140SDag-Erling Smørgrav #else
34265b390aaSDag-Erling Smørgrav if(fake_dsa || fake_sha1) return 1;
343bc892140SDag-Erling Smørgrav return 0;
344e2d15004SDag-Erling Smørgrav #endif
34565b390aaSDag-Erling Smørgrav
3468ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1:
3478ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3:
34865b390aaSDag-Erling Smørgrav #ifdef USE_SHA1
3490a92a9fcSCy Schubert #ifdef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED
3500a92a9fcSCy Schubert return !EVP_default_properties_is_fips_enabled(NULL);
3510a92a9fcSCy Schubert #else
35265b390aaSDag-Erling Smørgrav return 1;
3530a92a9fcSCy Schubert #endif
35465b390aaSDag-Erling Smørgrav #else
35565b390aaSDag-Erling Smørgrav if(fake_sha1) return 1;
35665b390aaSDag-Erling Smørgrav return 0;
35765b390aaSDag-Erling Smørgrav #endif
35865b390aaSDag-Erling Smørgrav
3598ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
3608ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256:
3618ed2b524SDag-Erling Smørgrav #endif
3628ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
3638ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512:
3648ed2b524SDag-Erling Smørgrav #endif
3658ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA
3668ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256:
3678ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384:
3688ed2b524SDag-Erling Smørgrav #endif
3690a92a9fcSCy Schubert #if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA)
3700a92a9fcSCy Schubert return 1;
3710a92a9fcSCy Schubert #endif
372c7f4d7adSDag-Erling Smørgrav #ifdef USE_ED25519
373c7f4d7adSDag-Erling Smørgrav case LDNS_ED25519:
374c7f4d7adSDag-Erling Smørgrav #endif
3750fb34990SDag-Erling Smørgrav #ifdef USE_ED448
3760fb34990SDag-Erling Smørgrav case LDNS_ED448:
3770fb34990SDag-Erling Smørgrav #endif
3780a92a9fcSCy Schubert #if defined(USE_ED25519) || defined(USE_ED448)
3790a92a9fcSCy Schubert #ifdef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED
3800a92a9fcSCy Schubert return !EVP_default_properties_is_fips_enabled(NULL);
3810a92a9fcSCy Schubert #else
3828ed2b524SDag-Erling Smørgrav return 1;
38365b390aaSDag-Erling Smørgrav #endif
3840a92a9fcSCy Schubert #endif
38565b390aaSDag-Erling Smørgrav
3868ed2b524SDag-Erling Smørgrav #ifdef USE_GOST
3878ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST:
3888ed2b524SDag-Erling Smørgrav /* we support GOST if it can be loaded */
38917d15b25SDag-Erling Smørgrav return sldns_key_EVP_load_gost_id();
3908ed2b524SDag-Erling Smørgrav #endif
3918ed2b524SDag-Erling Smørgrav default:
3928ed2b524SDag-Erling Smørgrav return 0;
3938ed2b524SDag-Erling Smørgrav }
3948ed2b524SDag-Erling Smørgrav }
3958ed2b524SDag-Erling Smørgrav
396e2d15004SDag-Erling Smørgrav #ifdef USE_DSA
3978ed2b524SDag-Erling Smørgrav /**
3988ed2b524SDag-Erling Smørgrav * Setup DSA key digest in DER encoding ...
3998ed2b524SDag-Erling Smørgrav * @param sig: input is signature output alloced ptr (unless failure).
4008ed2b524SDag-Erling Smørgrav * caller must free alloced ptr if this routine returns true.
4018ed2b524SDag-Erling Smørgrav * @param len: input is initial siglen, output is output len.
4028ed2b524SDag-Erling Smørgrav * @return false on failure.
4038ed2b524SDag-Erling Smørgrav */
4048ed2b524SDag-Erling Smørgrav static int
setup_dsa_sig(unsigned char ** sig,unsigned int * len)4058ed2b524SDag-Erling Smørgrav setup_dsa_sig(unsigned char** sig, unsigned int* len)
4068ed2b524SDag-Erling Smørgrav {
4078ed2b524SDag-Erling Smørgrav unsigned char* orig = *sig;
4088ed2b524SDag-Erling Smørgrav unsigned int origlen = *len;
4098ed2b524SDag-Erling Smørgrav int newlen;
4108ed2b524SDag-Erling Smørgrav BIGNUM *R, *S;
4118ed2b524SDag-Erling Smørgrav DSA_SIG *dsasig;
4128ed2b524SDag-Erling Smørgrav
4138ed2b524SDag-Erling Smørgrav /* extract the R and S field from the sig buffer */
4148ed2b524SDag-Erling Smørgrav if(origlen < 1 + 2*SHA_DIGEST_LENGTH)
4158ed2b524SDag-Erling Smørgrav return 0;
4168ed2b524SDag-Erling Smørgrav R = BN_new();
4178ed2b524SDag-Erling Smørgrav if(!R) return 0;
4188ed2b524SDag-Erling Smørgrav (void) BN_bin2bn(orig + 1, SHA_DIGEST_LENGTH, R);
4198ed2b524SDag-Erling Smørgrav S = BN_new();
4208ed2b524SDag-Erling Smørgrav if(!S) return 0;
4218ed2b524SDag-Erling Smørgrav (void) BN_bin2bn(orig + 21, SHA_DIGEST_LENGTH, S);
4228ed2b524SDag-Erling Smørgrav dsasig = DSA_SIG_new();
4238ed2b524SDag-Erling Smørgrav if(!dsasig) return 0;
4248ed2b524SDag-Erling Smørgrav
425bc892140SDag-Erling Smørgrav #ifdef HAVE_DSA_SIG_SET0
426*56850988SCy Schubert if(!DSA_SIG_set0(dsasig, R, S)) {
427*56850988SCy Schubert DSA_SIG_free(dsasig);
428*56850988SCy Schubert return 0;
429*56850988SCy Schubert }
430bc892140SDag-Erling Smørgrav #else
4310eefd307SCy Schubert # ifndef S_SPLINT_S
4328ed2b524SDag-Erling Smørgrav dsasig->r = R;
4338ed2b524SDag-Erling Smørgrav dsasig->s = S;
4340eefd307SCy Schubert # endif /* S_SPLINT_S */
435bc892140SDag-Erling Smørgrav #endif
4368ed2b524SDag-Erling Smørgrav *sig = NULL;
4378ed2b524SDag-Erling Smørgrav newlen = i2d_DSA_SIG(dsasig, sig);
4388ed2b524SDag-Erling Smørgrav if(newlen < 0) {
4398ed2b524SDag-Erling Smørgrav DSA_SIG_free(dsasig);
4408ed2b524SDag-Erling Smørgrav free(*sig);
4418ed2b524SDag-Erling Smørgrav return 0;
4428ed2b524SDag-Erling Smørgrav }
4438ed2b524SDag-Erling Smørgrav *len = (unsigned int)newlen;
4448ed2b524SDag-Erling Smørgrav DSA_SIG_free(dsasig);
4458ed2b524SDag-Erling Smørgrav return 1;
4468ed2b524SDag-Erling Smørgrav }
447e2d15004SDag-Erling Smørgrav #endif /* USE_DSA */
4488ed2b524SDag-Erling Smørgrav
4498ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA
4508ed2b524SDag-Erling Smørgrav /**
4518ed2b524SDag-Erling Smørgrav * Setup the ECDSA signature in its encoding that the library wants.
4528ed2b524SDag-Erling Smørgrav * Converts from plain numbers to ASN formatted.
4538ed2b524SDag-Erling Smørgrav * @param sig: input is signature, output alloced ptr (unless failure).
4548ed2b524SDag-Erling Smørgrav * caller must free alloced ptr if this routine returns true.
4558ed2b524SDag-Erling Smørgrav * @param len: input is initial siglen, output is output len.
4568ed2b524SDag-Erling Smørgrav * @return false on failure.
4578ed2b524SDag-Erling Smørgrav */
4588ed2b524SDag-Erling Smørgrav static int
setup_ecdsa_sig(unsigned char ** sig,unsigned int * len)4598ed2b524SDag-Erling Smørgrav setup_ecdsa_sig(unsigned char** sig, unsigned int* len)
4608ed2b524SDag-Erling Smørgrav {
461e2d15004SDag-Erling Smørgrav /* convert from two BIGNUMs in the rdata buffer, to ASN notation.
4628a384985SDag-Erling Smørgrav * ASN preamble: 30440220 <R 32bytefor256> 0220 <S 32bytefor256>
463e2d15004SDag-Erling Smørgrav * the '20' is the length of that field (=bnsize).
464e2d15004SDag-Erling Smørgrav i * the '44' is the total remaining length.
465e2d15004SDag-Erling Smørgrav * if negative, start with leading zero.
466e2d15004SDag-Erling Smørgrav * if starts with 00s, remove them from the number.
467e2d15004SDag-Erling Smørgrav */
468e2d15004SDag-Erling Smørgrav uint8_t pre[] = {0x30, 0x44, 0x02, 0x20};
469e2d15004SDag-Erling Smørgrav int pre_len = 4;
470e2d15004SDag-Erling Smørgrav uint8_t mid[] = {0x02, 0x20};
471e2d15004SDag-Erling Smørgrav int mid_len = 2;
472e2d15004SDag-Erling Smørgrav int raw_sig_len, r_high, s_high, r_rem=0, s_rem=0;
4738ed2b524SDag-Erling Smørgrav int bnsize = (int)((*len)/2);
474e2d15004SDag-Erling Smørgrav unsigned char* d = *sig;
475e2d15004SDag-Erling Smørgrav uint8_t* p;
4768ed2b524SDag-Erling Smørgrav /* if too short or not even length, fails */
4778ed2b524SDag-Erling Smørgrav if(*len < 16 || bnsize*2 != (int)*len)
4788ed2b524SDag-Erling Smørgrav return 0;
4798ed2b524SDag-Erling Smørgrav
480e2d15004SDag-Erling Smørgrav /* strip leading zeroes from r (but not last one) */
481e2d15004SDag-Erling Smørgrav while(r_rem < bnsize-1 && d[r_rem] == 0)
482e2d15004SDag-Erling Smørgrav r_rem++;
483e2d15004SDag-Erling Smørgrav /* strip leading zeroes from s (but not last one) */
484e2d15004SDag-Erling Smørgrav while(s_rem < bnsize-1 && d[bnsize+s_rem] == 0)
485e2d15004SDag-Erling Smørgrav s_rem++;
486e2d15004SDag-Erling Smørgrav
487e2d15004SDag-Erling Smørgrav r_high = ((d[0+r_rem]&0x80)?1:0);
488e2d15004SDag-Erling Smørgrav s_high = ((d[bnsize+s_rem]&0x80)?1:0);
489e2d15004SDag-Erling Smørgrav raw_sig_len = pre_len + r_high + bnsize - r_rem + mid_len +
490e2d15004SDag-Erling Smørgrav s_high + bnsize - s_rem;
491e2d15004SDag-Erling Smørgrav *sig = (unsigned char*)malloc((size_t)raw_sig_len);
492e2d15004SDag-Erling Smørgrav if(!*sig)
4938ed2b524SDag-Erling Smørgrav return 0;
494e2d15004SDag-Erling Smørgrav p = (uint8_t*)*sig;
495e2d15004SDag-Erling Smørgrav p[0] = pre[0];
496e2d15004SDag-Erling Smørgrav p[1] = (uint8_t)(raw_sig_len-2);
497e2d15004SDag-Erling Smørgrav p[2] = pre[2];
498e2d15004SDag-Erling Smørgrav p[3] = (uint8_t)(bnsize + r_high - r_rem);
499e2d15004SDag-Erling Smørgrav p += 4;
500e2d15004SDag-Erling Smørgrav if(r_high) {
501e2d15004SDag-Erling Smørgrav *p = 0;
502e2d15004SDag-Erling Smørgrav p += 1;
5038ed2b524SDag-Erling Smørgrav }
504e2d15004SDag-Erling Smørgrav memmove(p, d+r_rem, (size_t)bnsize-r_rem);
505e2d15004SDag-Erling Smørgrav p += bnsize-r_rem;
506e2d15004SDag-Erling Smørgrav memmove(p, mid, (size_t)mid_len-1);
507e2d15004SDag-Erling Smørgrav p += mid_len-1;
508e2d15004SDag-Erling Smørgrav *p = (uint8_t)(bnsize + s_high - s_rem);
509e2d15004SDag-Erling Smørgrav p += 1;
510e2d15004SDag-Erling Smørgrav if(s_high) {
511e2d15004SDag-Erling Smørgrav *p = 0;
512e2d15004SDag-Erling Smørgrav p += 1;
513e2d15004SDag-Erling Smørgrav }
514e2d15004SDag-Erling Smørgrav memmove(p, d+bnsize+s_rem, (size_t)bnsize-s_rem);
515e2d15004SDag-Erling Smørgrav *len = (unsigned int)raw_sig_len;
5168ed2b524SDag-Erling Smørgrav return 1;
5178ed2b524SDag-Erling Smørgrav }
5188ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */
5198ed2b524SDag-Erling Smørgrav
520b5663de9SDag-Erling Smørgrav #ifdef USE_ECDSA_EVP_WORKAROUND
521b5663de9SDag-Erling Smørgrav static EVP_MD ecdsa_evp_256_md;
522b5663de9SDag-Erling Smørgrav static EVP_MD ecdsa_evp_384_md;
ecdsa_evp_workaround_init(void)523b5663de9SDag-Erling Smørgrav void ecdsa_evp_workaround_init(void)
524b5663de9SDag-Erling Smørgrav {
525b5663de9SDag-Erling Smørgrav /* openssl before 1.0.0 fixes RSA with the SHA256
526b5663de9SDag-Erling Smørgrav * hash in EVP. We create one for ecdsa_sha256 */
527b5663de9SDag-Erling Smørgrav ecdsa_evp_256_md = *EVP_sha256();
528b5663de9SDag-Erling Smørgrav ecdsa_evp_256_md.required_pkey_type[0] = EVP_PKEY_EC;
529b5663de9SDag-Erling Smørgrav ecdsa_evp_256_md.verify = (void*)ECDSA_verify;
530b5663de9SDag-Erling Smørgrav
531b5663de9SDag-Erling Smørgrav ecdsa_evp_384_md = *EVP_sha384();
532b5663de9SDag-Erling Smørgrav ecdsa_evp_384_md.required_pkey_type[0] = EVP_PKEY_EC;
533b5663de9SDag-Erling Smørgrav ecdsa_evp_384_md.verify = (void*)ECDSA_verify;
534b5663de9SDag-Erling Smørgrav }
535b5663de9SDag-Erling Smørgrav #endif /* USE_ECDSA_EVP_WORKAROUND */
536b5663de9SDag-Erling Smørgrav
5378ed2b524SDag-Erling Smørgrav /**
5388ed2b524SDag-Erling Smørgrav * Setup key and digest for verification. Adjust sig if necessary.
5398ed2b524SDag-Erling Smørgrav *
5408ed2b524SDag-Erling Smørgrav * @param algo: key algorithm
5418ed2b524SDag-Erling Smørgrav * @param evp_key: EVP PKEY public key to create.
5428ed2b524SDag-Erling Smørgrav * @param digest_type: digest type to use
5438ed2b524SDag-Erling Smørgrav * @param key: key to setup for.
5448ed2b524SDag-Erling Smørgrav * @param keylen: length of key.
5458ed2b524SDag-Erling Smørgrav * @return false on failure.
5468ed2b524SDag-Erling Smørgrav */
5478ed2b524SDag-Erling Smørgrav static int
setup_key_digest(int algo,EVP_PKEY ** evp_key,const EVP_MD ** digest_type,unsigned char * key,size_t keylen)5488ed2b524SDag-Erling Smørgrav setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
5498ed2b524SDag-Erling Smørgrav unsigned char* key, size_t keylen)
5508ed2b524SDag-Erling Smørgrav {
5518ed2b524SDag-Erling Smørgrav switch(algo) {
55265b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1)
5538ed2b524SDag-Erling Smørgrav case LDNS_DSA:
5548ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3:
5555469a995SCy Schubert *evp_key = sldns_key_dsa2pkey_raw(key, keylen);
5568ed2b524SDag-Erling Smørgrav if(!*evp_key) {
5575469a995SCy Schubert verbose(VERB_QUERY, "verify: sldns_key_dsa2pkey failed");
5588ed2b524SDag-Erling Smørgrav return 0;
5598ed2b524SDag-Erling Smørgrav }
560bc892140SDag-Erling Smørgrav #ifdef HAVE_EVP_DSS1
5618ed2b524SDag-Erling Smørgrav *digest_type = EVP_dss1();
562bc892140SDag-Erling Smørgrav #else
563bc892140SDag-Erling Smørgrav *digest_type = EVP_sha1();
564bc892140SDag-Erling Smørgrav #endif
5658ed2b524SDag-Erling Smørgrav
5668ed2b524SDag-Erling Smørgrav break;
56765b390aaSDag-Erling Smørgrav #endif /* USE_DSA && USE_SHA1 */
56865b390aaSDag-Erling Smørgrav
56965b390aaSDag-Erling Smørgrav #if defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2))
57065b390aaSDag-Erling Smørgrav #ifdef USE_SHA1
5718ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1:
5728ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3:
57365b390aaSDag-Erling Smørgrav #endif
5748ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
5758ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256:
5768ed2b524SDag-Erling Smørgrav #endif
5778ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
5788ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512:
5798ed2b524SDag-Erling Smørgrav #endif
5805469a995SCy Schubert *evp_key = sldns_key_rsa2pkey_raw(key, keylen);
5818ed2b524SDag-Erling Smørgrav if(!*evp_key) {
5825469a995SCy Schubert verbose(VERB_QUERY, "verify: sldns_key_rsa2pkey SHA failed");
5838ed2b524SDag-Erling Smørgrav return 0;
5848ed2b524SDag-Erling Smørgrav }
5858ed2b524SDag-Erling Smørgrav
5868ed2b524SDag-Erling Smørgrav /* select SHA version */
5878ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
5888ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA256)
5898ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha256();
5908ed2b524SDag-Erling Smørgrav else
5918ed2b524SDag-Erling Smørgrav #endif
5928ed2b524SDag-Erling Smørgrav #if defined(HAVE_EVP_SHA512) && defined(USE_SHA2)
5938ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA512)
5948ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha512();
5958ed2b524SDag-Erling Smørgrav else
5968ed2b524SDag-Erling Smørgrav #endif
59765b390aaSDag-Erling Smørgrav #ifdef USE_SHA1
5988ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha1();
59965b390aaSDag-Erling Smørgrav #else
60065b390aaSDag-Erling Smørgrav { verbose(VERB_QUERY, "no digest available"); return 0; }
60165b390aaSDag-Erling Smørgrav #endif
6028ed2b524SDag-Erling Smørgrav break;
60365b390aaSDag-Erling Smørgrav #endif /* defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) */
60465b390aaSDag-Erling Smørgrav
6058ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5:
6065469a995SCy Schubert *evp_key = sldns_key_rsa2pkey_raw(key, keylen);
6078ed2b524SDag-Erling Smørgrav if(!*evp_key) {
6085469a995SCy Schubert verbose(VERB_QUERY, "verify: sldns_key_rsa2pkey MD5 failed");
6098ed2b524SDag-Erling Smørgrav return 0;
6108ed2b524SDag-Erling Smørgrav }
6118ed2b524SDag-Erling Smørgrav *digest_type = EVP_md5();
6128ed2b524SDag-Erling Smørgrav
6138ed2b524SDag-Erling Smørgrav break;
6148ed2b524SDag-Erling Smørgrav #ifdef USE_GOST
6158ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST:
61617d15b25SDag-Erling Smørgrav *evp_key = sldns_gost2pkey_raw(key, keylen);
6178ed2b524SDag-Erling Smørgrav if(!*evp_key) {
6188ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: "
61917d15b25SDag-Erling Smørgrav "sldns_gost2pkey_raw failed");
6208ed2b524SDag-Erling Smørgrav return 0;
6218ed2b524SDag-Erling Smørgrav }
6228ed2b524SDag-Erling Smørgrav *digest_type = EVP_get_digestbyname("md_gost94");
6238ed2b524SDag-Erling Smørgrav if(!*digest_type) {
6248ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: "
6258ed2b524SDag-Erling Smørgrav "EVP_getdigest md_gost94 failed");
6268ed2b524SDag-Erling Smørgrav return 0;
6278ed2b524SDag-Erling Smørgrav }
6288ed2b524SDag-Erling Smørgrav break;
6298ed2b524SDag-Erling Smørgrav #endif
6308ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA
6318ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256:
63217d15b25SDag-Erling Smørgrav *evp_key = sldns_ecdsa2pkey_raw(key, keylen,
6338ed2b524SDag-Erling Smørgrav LDNS_ECDSAP256SHA256);
6348ed2b524SDag-Erling Smørgrav if(!*evp_key) {
6358ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: "
63617d15b25SDag-Erling Smørgrav "sldns_ecdsa2pkey_raw failed");
6378ed2b524SDag-Erling Smørgrav return 0;
6388ed2b524SDag-Erling Smørgrav }
6398ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA_EVP_WORKAROUND
640b5663de9SDag-Erling Smørgrav *digest_type = &ecdsa_evp_256_md;
6418ed2b524SDag-Erling Smørgrav #else
6428ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha256();
6438ed2b524SDag-Erling Smørgrav #endif
6448ed2b524SDag-Erling Smørgrav break;
6458ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384:
64617d15b25SDag-Erling Smørgrav *evp_key = sldns_ecdsa2pkey_raw(key, keylen,
6478ed2b524SDag-Erling Smørgrav LDNS_ECDSAP384SHA384);
6488ed2b524SDag-Erling Smørgrav if(!*evp_key) {
6498ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: "
65017d15b25SDag-Erling Smørgrav "sldns_ecdsa2pkey_raw failed");
6518ed2b524SDag-Erling Smørgrav return 0;
6528ed2b524SDag-Erling Smørgrav }
6538ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA_EVP_WORKAROUND
654b5663de9SDag-Erling Smørgrav *digest_type = &ecdsa_evp_384_md;
6558ed2b524SDag-Erling Smørgrav #else
6568ed2b524SDag-Erling Smørgrav *digest_type = EVP_sha384();
6578ed2b524SDag-Erling Smørgrav #endif
6588ed2b524SDag-Erling Smørgrav break;
6598ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */
660c7f4d7adSDag-Erling Smørgrav #ifdef USE_ED25519
661c7f4d7adSDag-Erling Smørgrav case LDNS_ED25519:
662c7f4d7adSDag-Erling Smørgrav *evp_key = sldns_ed255192pkey_raw(key, keylen);
663c7f4d7adSDag-Erling Smørgrav if(!*evp_key) {
664c7f4d7adSDag-Erling Smørgrav verbose(VERB_QUERY, "verify: "
665c7f4d7adSDag-Erling Smørgrav "sldns_ed255192pkey_raw failed");
666c7f4d7adSDag-Erling Smørgrav return 0;
667c7f4d7adSDag-Erling Smørgrav }
668c7f4d7adSDag-Erling Smørgrav *digest_type = NULL;
669c7f4d7adSDag-Erling Smørgrav break;
670c7f4d7adSDag-Erling Smørgrav #endif /* USE_ED25519 */
6710fb34990SDag-Erling Smørgrav #ifdef USE_ED448
6720fb34990SDag-Erling Smørgrav case LDNS_ED448:
6730fb34990SDag-Erling Smørgrav *evp_key = sldns_ed4482pkey_raw(key, keylen);
6740fb34990SDag-Erling Smørgrav if(!*evp_key) {
6750fb34990SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: "
6760fb34990SDag-Erling Smørgrav "sldns_ed4482pkey_raw failed");
6770fb34990SDag-Erling Smørgrav return 0;
6780fb34990SDag-Erling Smørgrav }
6790fb34990SDag-Erling Smørgrav *digest_type = NULL;
6800fb34990SDag-Erling Smørgrav break;
6810fb34990SDag-Erling Smørgrav #endif /* USE_ED448 */
6828ed2b524SDag-Erling Smørgrav default:
6838ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: unknown algorithm %d",
6848ed2b524SDag-Erling Smørgrav algo);
6858ed2b524SDag-Erling Smørgrav return 0;
6868ed2b524SDag-Erling Smørgrav }
6878ed2b524SDag-Erling Smørgrav return 1;
6888ed2b524SDag-Erling Smørgrav }
6898ed2b524SDag-Erling Smørgrav
6900a92a9fcSCy Schubert static void
digest_ctx_free(EVP_MD_CTX * ctx,EVP_PKEY * evp_key,unsigned char * sigblock,int dofree,int docrypto_free)6910a92a9fcSCy Schubert digest_ctx_free(EVP_MD_CTX* ctx, EVP_PKEY *evp_key,
6920a92a9fcSCy Schubert unsigned char* sigblock, int dofree, int docrypto_free)
6930a92a9fcSCy Schubert {
6940a92a9fcSCy Schubert #ifdef HAVE_EVP_MD_CTX_NEW
6950a92a9fcSCy Schubert EVP_MD_CTX_destroy(ctx);
6960a92a9fcSCy Schubert #else
6970a92a9fcSCy Schubert EVP_MD_CTX_cleanup(ctx);
6980a92a9fcSCy Schubert free(ctx);
6990a92a9fcSCy Schubert #endif
7000a92a9fcSCy Schubert EVP_PKEY_free(evp_key);
7010a92a9fcSCy Schubert if(dofree) free(sigblock);
7020a92a9fcSCy Schubert else if(docrypto_free) OPENSSL_free(sigblock);
7030a92a9fcSCy Schubert }
7040a92a9fcSCy Schubert
7050a92a9fcSCy Schubert static enum sec_status
digest_error_status(const char * str)7060a92a9fcSCy Schubert digest_error_status(const char *str)
7070a92a9fcSCy Schubert {
7080a92a9fcSCy Schubert unsigned long e = ERR_get_error();
7090a92a9fcSCy Schubert #ifdef EVP_R_INVALID_DIGEST
7100a92a9fcSCy Schubert if (ERR_GET_LIB(e) == ERR_LIB_EVP &&
7110a92a9fcSCy Schubert ERR_GET_REASON(e) == EVP_R_INVALID_DIGEST) {
7120a92a9fcSCy Schubert log_crypto_verbose(VERB_ALGO, str, e);
7130a92a9fcSCy Schubert return sec_status_indeterminate;
7140a92a9fcSCy Schubert }
7150a92a9fcSCy Schubert #endif
7160a92a9fcSCy Schubert log_crypto_verbose(VERB_QUERY, str, e);
7170a92a9fcSCy Schubert return sec_status_unchecked;
7180a92a9fcSCy Schubert }
7190a92a9fcSCy Schubert
7208ed2b524SDag-Erling Smørgrav /**
7218ed2b524SDag-Erling Smørgrav * Check a canonical sig+rrset and signature against a dnskey
7228ed2b524SDag-Erling Smørgrav * @param buf: buffer with data to verify, the first rrsig part and the
7238ed2b524SDag-Erling Smørgrav * canonicalized rrset.
7248ed2b524SDag-Erling Smørgrav * @param algo: DNSKEY algorithm.
7258ed2b524SDag-Erling Smørgrav * @param sigblock: signature rdata field from RRSIG
7268ed2b524SDag-Erling Smørgrav * @param sigblock_len: length of sigblock data.
7278ed2b524SDag-Erling Smørgrav * @param key: public key data from DNSKEY RR.
7288ed2b524SDag-Erling Smørgrav * @param keylen: length of keydata.
7298ed2b524SDag-Erling Smørgrav * @param reason: bogus reason in more detail.
7308ed2b524SDag-Erling Smørgrav * @return secure if verification succeeded, bogus on crypto failure,
7310a92a9fcSCy Schubert * unchecked on format errors and alloc failures, indeterminate
7320a92a9fcSCy Schubert * if digest is not supported by the crypto library (openssl3+ only).
7338ed2b524SDag-Erling Smørgrav */
7348ed2b524SDag-Erling Smørgrav enum sec_status
verify_canonrrset(sldns_buffer * buf,int algo,unsigned char * sigblock,unsigned int sigblock_len,unsigned char * key,unsigned int keylen,char ** reason)73517d15b25SDag-Erling Smørgrav verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
7368ed2b524SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
7378ed2b524SDag-Erling Smørgrav char** reason)
7388ed2b524SDag-Erling Smørgrav {
7398ed2b524SDag-Erling Smørgrav const EVP_MD *digest_type;
740e2d15004SDag-Erling Smørgrav EVP_MD_CTX* ctx;
741e2d15004SDag-Erling Smørgrav int res, dofree = 0, docrypto_free = 0;
7428ed2b524SDag-Erling Smørgrav EVP_PKEY *evp_key = NULL;
7438ed2b524SDag-Erling Smørgrav
744bc892140SDag-Erling Smørgrav #ifndef USE_DSA
74565b390aaSDag-Erling Smørgrav if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1))
74665b390aaSDag-Erling Smørgrav return sec_status_secure;
74765b390aaSDag-Erling Smørgrav #endif
74865b390aaSDag-Erling Smørgrav #ifndef USE_SHA1
74965b390aaSDag-Erling Smørgrav if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3))
750bc892140SDag-Erling Smørgrav return sec_status_secure;
751bc892140SDag-Erling Smørgrav #endif
752bc892140SDag-Erling Smørgrav
7538ed2b524SDag-Erling Smørgrav if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) {
7548ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup key");
7558ed2b524SDag-Erling Smørgrav *reason = "use of key for crypto failed";
7568ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key);
7578ed2b524SDag-Erling Smørgrav return sec_status_bogus;
7588ed2b524SDag-Erling Smørgrav }
759e2d15004SDag-Erling Smørgrav #ifdef USE_DSA
7608ed2b524SDag-Erling Smørgrav /* if it is a DSA signature in bind format, convert to DER format */
7618ed2b524SDag-Erling Smørgrav if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&
7628ed2b524SDag-Erling Smørgrav sigblock_len == 1+2*SHA_DIGEST_LENGTH) {
7638ed2b524SDag-Erling Smørgrav if(!setup_dsa_sig(&sigblock, &sigblock_len)) {
7648ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup DSA sig");
7658ed2b524SDag-Erling Smørgrav *reason = "use of key for DSA crypto failed";
7668ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key);
7678ed2b524SDag-Erling Smørgrav return sec_status_bogus;
7688ed2b524SDag-Erling Smørgrav }
769e2d15004SDag-Erling Smørgrav docrypto_free = 1;
7708ed2b524SDag-Erling Smørgrav }
771e2d15004SDag-Erling Smørgrav #endif
772e2d15004SDag-Erling Smørgrav #if defined(USE_ECDSA) && defined(USE_DSA)
773e2d15004SDag-Erling Smørgrav else
774e2d15004SDag-Erling Smørgrav #endif
7758ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA
776e2d15004SDag-Erling Smørgrav if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) {
7778ed2b524SDag-Erling Smørgrav /* EVP uses ASN prefix on sig, which is not in the wire data */
7788ed2b524SDag-Erling Smørgrav if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) {
7798ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup ECDSA sig");
7808ed2b524SDag-Erling Smørgrav *reason = "use of signature for ECDSA crypto failed";
7818ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key);
7828ed2b524SDag-Erling Smørgrav return sec_status_bogus;
7838ed2b524SDag-Erling Smørgrav }
7848ed2b524SDag-Erling Smørgrav dofree = 1;
7858ed2b524SDag-Erling Smørgrav }
7868ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */
7878ed2b524SDag-Erling Smørgrav
7888ed2b524SDag-Erling Smørgrav /* do the signature cryptography work */
789e2d15004SDag-Erling Smørgrav #ifdef HAVE_EVP_MD_CTX_NEW
790e2d15004SDag-Erling Smørgrav ctx = EVP_MD_CTX_new();
791e2d15004SDag-Erling Smørgrav #else
792e2d15004SDag-Erling Smørgrav ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx));
793e2d15004SDag-Erling Smørgrav if(ctx) EVP_MD_CTX_init(ctx);
794e2d15004SDag-Erling Smørgrav #endif
795e2d15004SDag-Erling Smørgrav if(!ctx) {
796e2d15004SDag-Erling Smørgrav log_err("EVP_MD_CTX_new: malloc failure");
7978ed2b524SDag-Erling Smørgrav EVP_PKEY_free(evp_key);
7988ed2b524SDag-Erling Smørgrav if(dofree) free(sigblock);
799b5663de9SDag-Erling Smørgrav else if(docrypto_free) OPENSSL_free(sigblock);
8008ed2b524SDag-Erling Smørgrav return sec_status_unchecked;
8018ed2b524SDag-Erling Smørgrav }
802c7f4d7adSDag-Erling Smørgrav #ifndef HAVE_EVP_DIGESTVERIFY
803c7f4d7adSDag-Erling Smørgrav if(EVP_DigestInit(ctx, digest_type) == 0) {
8040a92a9fcSCy Schubert enum sec_status sec;
8050a92a9fcSCy Schubert sec = digest_error_status("verify: EVP_DigestInit failed");
8060a92a9fcSCy Schubert digest_ctx_free(ctx, evp_key, sigblock,
8070a92a9fcSCy Schubert dofree, docrypto_free);
8080a92a9fcSCy Schubert return sec;
809e2d15004SDag-Erling Smørgrav }
810c7f4d7adSDag-Erling Smørgrav if(EVP_DigestUpdate(ctx, (unsigned char*)sldns_buffer_begin(buf),
81117d15b25SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf)) == 0) {
8120a92a9fcSCy Schubert log_crypto_verbose(VERB_QUERY, "verify: EVP_DigestUpdate failed",
8130a92a9fcSCy Schubert ERR_get_error());
8140a92a9fcSCy Schubert digest_ctx_free(ctx, evp_key, sigblock,
8150a92a9fcSCy Schubert dofree, docrypto_free);
8168ed2b524SDag-Erling Smørgrav return sec_status_unchecked;
8178ed2b524SDag-Erling Smørgrav }
8188ed2b524SDag-Erling Smørgrav
819e2d15004SDag-Erling Smørgrav res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key);
820c7f4d7adSDag-Erling Smørgrav #else /* HAVE_EVP_DIGESTVERIFY */
821c7f4d7adSDag-Erling Smørgrav if(EVP_DigestVerifyInit(ctx, NULL, digest_type, NULL, evp_key) == 0) {
8220a92a9fcSCy Schubert enum sec_status sec;
8230a92a9fcSCy Schubert sec = digest_error_status("verify: EVP_DigestVerifyInit failed");
8240a92a9fcSCy Schubert digest_ctx_free(ctx, evp_key, sigblock,
8250a92a9fcSCy Schubert dofree, docrypto_free);
8260a92a9fcSCy Schubert return sec;
827c7f4d7adSDag-Erling Smørgrav }
828c7f4d7adSDag-Erling Smørgrav res = EVP_DigestVerify(ctx, sigblock, sigblock_len,
829c7f4d7adSDag-Erling Smørgrav (unsigned char*)sldns_buffer_begin(buf),
830c7f4d7adSDag-Erling Smørgrav sldns_buffer_limit(buf));
831c7f4d7adSDag-Erling Smørgrav #endif
8320a92a9fcSCy Schubert digest_ctx_free(ctx, evp_key, sigblock,
8330a92a9fcSCy Schubert dofree, docrypto_free);
8348ed2b524SDag-Erling Smørgrav
8358ed2b524SDag-Erling Smørgrav if(res == 1) {
8368ed2b524SDag-Erling Smørgrav return sec_status_secure;
8378ed2b524SDag-Erling Smørgrav } else if(res == 0) {
8388ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: signature mismatch");
8398ed2b524SDag-Erling Smørgrav *reason = "signature crypto failed";
8408ed2b524SDag-Erling Smørgrav return sec_status_bogus;
8418ed2b524SDag-Erling Smørgrav }
8428ed2b524SDag-Erling Smørgrav
8438ed2b524SDag-Erling Smørgrav log_crypto_error("verify:", ERR_get_error());
8448ed2b524SDag-Erling Smørgrav return sec_status_unchecked;
8458ed2b524SDag-Erling Smørgrav }
8468ed2b524SDag-Erling Smørgrav
8478ed2b524SDag-Erling Smørgrav /**************************************************/
8488ed2b524SDag-Erling Smørgrav #elif defined(HAVE_NSS)
8498ed2b524SDag-Erling Smørgrav /* libnss implementation */
8508ed2b524SDag-Erling Smørgrav /* nss3 */
8518ed2b524SDag-Erling Smørgrav #include "sechash.h"
8528ed2b524SDag-Erling Smørgrav #include "pk11pub.h"
8538ed2b524SDag-Erling Smørgrav #include "keyhi.h"
8548ed2b524SDag-Erling Smørgrav #include "secerr.h"
8558ed2b524SDag-Erling Smørgrav #include "cryptohi.h"
8568ed2b524SDag-Erling Smørgrav /* nspr4 */
8578ed2b524SDag-Erling Smørgrav #include "prerror.h"
8588ed2b524SDag-Erling Smørgrav
85905ab2901SDag-Erling Smørgrav /* return size of digest if supported, or 0 otherwise */
86005ab2901SDag-Erling Smørgrav size_t
nsec3_hash_algo_size_supported(int id)86105ab2901SDag-Erling Smørgrav nsec3_hash_algo_size_supported(int id)
86205ab2901SDag-Erling Smørgrav {
86305ab2901SDag-Erling Smørgrav switch(id) {
86405ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1:
86505ab2901SDag-Erling Smørgrav return SHA1_LENGTH;
86605ab2901SDag-Erling Smørgrav default:
86705ab2901SDag-Erling Smørgrav return 0;
86805ab2901SDag-Erling Smørgrav }
86905ab2901SDag-Erling Smørgrav }
87005ab2901SDag-Erling Smørgrav
87105ab2901SDag-Erling Smørgrav /* perform nsec3 hash. return false on failure */
87205ab2901SDag-Erling Smørgrav int
secalgo_nsec3_hash(int algo,unsigned char * buf,size_t len,unsigned char * res)87305ab2901SDag-Erling Smørgrav secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
87405ab2901SDag-Erling Smørgrav unsigned char* res)
87505ab2901SDag-Erling Smørgrav {
87605ab2901SDag-Erling Smørgrav switch(algo) {
87705ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1:
87805ab2901SDag-Erling Smørgrav (void)HASH_HashBuf(HASH_AlgSHA1, res, buf, (unsigned long)len);
87905ab2901SDag-Erling Smørgrav return 1;
88005ab2901SDag-Erling Smørgrav default:
88105ab2901SDag-Erling Smørgrav return 0;
88205ab2901SDag-Erling Smørgrav }
88305ab2901SDag-Erling Smørgrav }
88405ab2901SDag-Erling Smørgrav
885e2d15004SDag-Erling Smørgrav void
secalgo_hash_sha256(unsigned char * buf,size_t len,unsigned char * res)886e2d15004SDag-Erling Smørgrav secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
887e2d15004SDag-Erling Smørgrav {
888e2d15004SDag-Erling Smørgrav (void)HASH_HashBuf(HASH_AlgSHA256, res, buf, (unsigned long)len);
889e2d15004SDag-Erling Smørgrav }
890e2d15004SDag-Erling Smørgrav
8915469a995SCy Schubert /** the secalgo hash structure */
8925469a995SCy Schubert struct secalgo_hash {
8935469a995SCy Schubert /** hash context */
8945469a995SCy Schubert HASHContext* ctx;
8955469a995SCy Schubert };
8965469a995SCy Schubert
8975469a995SCy Schubert /** create hash struct of type */
secalgo_hash_create_type(HASH_HashType tp)8985469a995SCy Schubert static struct secalgo_hash* secalgo_hash_create_type(HASH_HashType tp)
8995469a995SCy Schubert {
9005469a995SCy Schubert struct secalgo_hash* h = calloc(1, sizeof(*h));
9015469a995SCy Schubert if(!h)
9025469a995SCy Schubert return NULL;
9035469a995SCy Schubert h->ctx = HASH_Create(tp);
9045469a995SCy Schubert if(!h->ctx) {
9055469a995SCy Schubert free(h);
9065469a995SCy Schubert return NULL;
9075469a995SCy Schubert }
9085469a995SCy Schubert return h;
9095469a995SCy Schubert }
9105469a995SCy Schubert
secalgo_hash_create_sha384(void)9115469a995SCy Schubert struct secalgo_hash* secalgo_hash_create_sha384(void)
9125469a995SCy Schubert {
9135469a995SCy Schubert return secalgo_hash_create_type(HASH_AlgSHA384);
9145469a995SCy Schubert }
9155469a995SCy Schubert
secalgo_hash_create_sha512(void)9165469a995SCy Schubert struct secalgo_hash* secalgo_hash_create_sha512(void)
9175469a995SCy Schubert {
9185469a995SCy Schubert return secalgo_hash_create_type(HASH_AlgSHA512);
9195469a995SCy Schubert }
9205469a995SCy Schubert
secalgo_hash_update(struct secalgo_hash * hash,uint8_t * data,size_t len)9215469a995SCy Schubert int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len)
9225469a995SCy Schubert {
9235469a995SCy Schubert HASH_Update(hash->ctx, (unsigned char*)data, (unsigned int)len);
9245469a995SCy Schubert return 1;
9255469a995SCy Schubert }
9265469a995SCy Schubert
secalgo_hash_final(struct secalgo_hash * hash,uint8_t * result,size_t maxlen,size_t * resultlen)9275469a995SCy Schubert int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result,
9285469a995SCy Schubert size_t maxlen, size_t* resultlen)
9295469a995SCy Schubert {
9305469a995SCy Schubert unsigned int reslen = 0;
9315469a995SCy Schubert if(HASH_ResultLenContext(hash->ctx) > (unsigned int)maxlen) {
9325469a995SCy Schubert *resultlen = 0;
9335469a995SCy Schubert log_err("secalgo_hash_final: hash buffer too small");
9345469a995SCy Schubert return 0;
9355469a995SCy Schubert }
9365469a995SCy Schubert HASH_End(hash->ctx, (unsigned char*)result, &reslen,
9375469a995SCy Schubert (unsigned int)maxlen);
9385469a995SCy Schubert *resultlen = (size_t)reslen;
9395469a995SCy Schubert return 1;
9405469a995SCy Schubert }
9415469a995SCy Schubert
secalgo_hash_delete(struct secalgo_hash * hash)9425469a995SCy Schubert void secalgo_hash_delete(struct secalgo_hash* hash)
9435469a995SCy Schubert {
9445469a995SCy Schubert if(!hash) return;
9455469a995SCy Schubert HASH_Destroy(hash->ctx);
9465469a995SCy Schubert free(hash);
9475469a995SCy Schubert }
9485469a995SCy Schubert
9498ed2b524SDag-Erling Smørgrav size_t
ds_digest_size_supported(int algo)9508ed2b524SDag-Erling Smørgrav ds_digest_size_supported(int algo)
9518ed2b524SDag-Erling Smørgrav {
9528ed2b524SDag-Erling Smørgrav /* uses libNSS */
9538ed2b524SDag-Erling Smørgrav switch(algo) {
95465b390aaSDag-Erling Smørgrav #ifdef USE_SHA1
9558ed2b524SDag-Erling Smørgrav case LDNS_SHA1:
9568ed2b524SDag-Erling Smørgrav return SHA1_LENGTH;
95765b390aaSDag-Erling Smørgrav #endif
9588ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2
9598ed2b524SDag-Erling Smørgrav case LDNS_SHA256:
9608ed2b524SDag-Erling Smørgrav return SHA256_LENGTH;
9618ed2b524SDag-Erling Smørgrav #endif
9628ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA
9638ed2b524SDag-Erling Smørgrav case LDNS_SHA384:
9648ed2b524SDag-Erling Smørgrav return SHA384_LENGTH;
9658ed2b524SDag-Erling Smørgrav #endif
9668ed2b524SDag-Erling Smørgrav /* GOST not supported in NSS */
9678ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST:
9688ed2b524SDag-Erling Smørgrav default: break;
9698ed2b524SDag-Erling Smørgrav }
9708ed2b524SDag-Erling Smørgrav return 0;
9718ed2b524SDag-Erling Smørgrav }
9728ed2b524SDag-Erling Smørgrav
9738ed2b524SDag-Erling Smørgrav int
secalgo_ds_digest(int algo,unsigned char * buf,size_t len,unsigned char * res)9748ed2b524SDag-Erling Smørgrav secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
9758ed2b524SDag-Erling Smørgrav unsigned char* res)
9768ed2b524SDag-Erling Smørgrav {
9778ed2b524SDag-Erling Smørgrav /* uses libNSS */
9788ed2b524SDag-Erling Smørgrav switch(algo) {
97965b390aaSDag-Erling Smørgrav #ifdef USE_SHA1
9808ed2b524SDag-Erling Smørgrav case LDNS_SHA1:
9818ed2b524SDag-Erling Smørgrav return HASH_HashBuf(HASH_AlgSHA1, res, buf, len)
9828ed2b524SDag-Erling Smørgrav == SECSuccess;
98365b390aaSDag-Erling Smørgrav #endif
9848ed2b524SDag-Erling Smørgrav #if defined(USE_SHA2)
9858ed2b524SDag-Erling Smørgrav case LDNS_SHA256:
9868ed2b524SDag-Erling Smørgrav return HASH_HashBuf(HASH_AlgSHA256, res, buf, len)
9878ed2b524SDag-Erling Smørgrav == SECSuccess;
9888ed2b524SDag-Erling Smørgrav #endif
9898ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA
9908ed2b524SDag-Erling Smørgrav case LDNS_SHA384:
9918ed2b524SDag-Erling Smørgrav return HASH_HashBuf(HASH_AlgSHA384, res, buf, len)
9928ed2b524SDag-Erling Smørgrav == SECSuccess;
9938ed2b524SDag-Erling Smørgrav #endif
9948ed2b524SDag-Erling Smørgrav case LDNS_HASH_GOST:
9958ed2b524SDag-Erling Smørgrav default:
9968ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "unknown DS digest algorithm %d",
9978ed2b524SDag-Erling Smørgrav algo);
9988ed2b524SDag-Erling Smørgrav break;
9998ed2b524SDag-Erling Smørgrav }
10008ed2b524SDag-Erling Smørgrav return 0;
10018ed2b524SDag-Erling Smørgrav }
10028ed2b524SDag-Erling Smørgrav
10038ed2b524SDag-Erling Smørgrav int
dnskey_algo_id_is_supported(int id)10048ed2b524SDag-Erling Smørgrav dnskey_algo_id_is_supported(int id)
10058ed2b524SDag-Erling Smørgrav {
10068ed2b524SDag-Erling Smørgrav /* uses libNSS */
10078ed2b524SDag-Erling Smørgrav switch(id) {
10088ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5:
10098ed2b524SDag-Erling Smørgrav /* RFC 6725 deprecates RSAMD5 */
10108ed2b524SDag-Erling Smørgrav return 0;
101165b390aaSDag-Erling Smørgrav #if defined(USE_SHA1) || defined(USE_SHA2)
101265b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1)
10138ed2b524SDag-Erling Smørgrav case LDNS_DSA:
10148ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3:
1015e2d15004SDag-Erling Smørgrav #endif
101665b390aaSDag-Erling Smørgrav #ifdef USE_SHA1
10178ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1:
10188ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3:
101965b390aaSDag-Erling Smørgrav #endif
10208ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2
10218ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256:
10228ed2b524SDag-Erling Smørgrav #endif
10238ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2
10248ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512:
10258ed2b524SDag-Erling Smørgrav #endif
10268ed2b524SDag-Erling Smørgrav return 1;
102765b390aaSDag-Erling Smørgrav #endif /* SHA1 or SHA2 */
102865b390aaSDag-Erling Smørgrav
10298ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA
10308ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256:
10318ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384:
10328ed2b524SDag-Erling Smørgrav return PK11_TokenExists(CKM_ECDSA);
10338ed2b524SDag-Erling Smørgrav #endif
10348ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST:
10358ed2b524SDag-Erling Smørgrav default:
10368ed2b524SDag-Erling Smørgrav return 0;
10378ed2b524SDag-Erling Smørgrav }
10388ed2b524SDag-Erling Smørgrav }
10398ed2b524SDag-Erling Smørgrav
10408ed2b524SDag-Erling Smørgrav /* return a new public key for NSS */
nss_key_create(KeyType ktype)10418ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_key_create(KeyType ktype)
10428ed2b524SDag-Erling Smørgrav {
10438ed2b524SDag-Erling Smørgrav SECKEYPublicKey* key;
10448ed2b524SDag-Erling Smørgrav PLArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
10458ed2b524SDag-Erling Smørgrav if(!arena) {
10468ed2b524SDag-Erling Smørgrav log_err("out of memory, PORT_NewArena failed");
10478ed2b524SDag-Erling Smørgrav return NULL;
10488ed2b524SDag-Erling Smørgrav }
10498ed2b524SDag-Erling Smørgrav key = PORT_ArenaZNew(arena, SECKEYPublicKey);
10508ed2b524SDag-Erling Smørgrav if(!key) {
10518ed2b524SDag-Erling Smørgrav log_err("out of memory, PORT_ArenaZNew failed");
10528ed2b524SDag-Erling Smørgrav PORT_FreeArena(arena, PR_FALSE);
10538ed2b524SDag-Erling Smørgrav return NULL;
10548ed2b524SDag-Erling Smørgrav }
10558ed2b524SDag-Erling Smørgrav key->arena = arena;
10568ed2b524SDag-Erling Smørgrav key->keyType = ktype;
10578ed2b524SDag-Erling Smørgrav key->pkcs11Slot = NULL;
10588ed2b524SDag-Erling Smørgrav key->pkcs11ID = CK_INVALID_HANDLE;
10598ed2b524SDag-Erling Smørgrav return key;
10608ed2b524SDag-Erling Smørgrav }
10618ed2b524SDag-Erling Smørgrav
nss_buf2ecdsa(unsigned char * key,size_t len,int algo)10628ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_buf2ecdsa(unsigned char* key, size_t len, int algo)
10638ed2b524SDag-Erling Smørgrav {
10648ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pk;
10658ed2b524SDag-Erling Smørgrav SECItem pub = {siBuffer, NULL, 0};
10668ed2b524SDag-Erling Smørgrav SECItem params = {siBuffer, NULL, 0};
106717d15b25SDag-Erling Smørgrav static unsigned char param256[] = {
10688ed2b524SDag-Erling Smørgrav /* OBJECTIDENTIFIER 1.2.840.10045.3.1.7 (P-256)
10698ed2b524SDag-Erling Smørgrav * {iso(1) member-body(2) us(840) ansi-x962(10045) curves(3) prime(1) prime256v1(7)} */
10708ed2b524SDag-Erling Smørgrav 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
10718ed2b524SDag-Erling Smørgrav };
107217d15b25SDag-Erling Smørgrav static unsigned char param384[] = {
10738ed2b524SDag-Erling Smørgrav /* OBJECTIDENTIFIER 1.3.132.0.34 (P-384)
10748ed2b524SDag-Erling Smørgrav * {iso(1) identified-organization(3) certicom(132) curve(0) ansip384r1(34)} */
10758ed2b524SDag-Erling Smørgrav 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22
10768ed2b524SDag-Erling Smørgrav };
10778ed2b524SDag-Erling Smørgrav unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
10788ed2b524SDag-Erling Smørgrav
10798ed2b524SDag-Erling Smørgrav /* check length, which uncompressed must be 2 bignums */
10808ed2b524SDag-Erling Smørgrav if(algo == LDNS_ECDSAP256SHA256) {
10818ed2b524SDag-Erling Smørgrav if(len != 2*256/8) return NULL;
10828ed2b524SDag-Erling Smørgrav /* ECCurve_X9_62_PRIME_256V1 */
10838ed2b524SDag-Erling Smørgrav } else if(algo == LDNS_ECDSAP384SHA384) {
10848ed2b524SDag-Erling Smørgrav if(len != 2*384/8) return NULL;
10858ed2b524SDag-Erling Smørgrav /* ECCurve_X9_62_PRIME_384R1 */
10868ed2b524SDag-Erling Smørgrav } else return NULL;
10878ed2b524SDag-Erling Smørgrav
10888ed2b524SDag-Erling Smørgrav buf[0] = 0x04; /* POINT_FORM_UNCOMPRESSED */
10898ed2b524SDag-Erling Smørgrav memmove(buf+1, key, len);
10908ed2b524SDag-Erling Smørgrav pub.data = buf;
10918ed2b524SDag-Erling Smørgrav pub.len = len+1;
10928ed2b524SDag-Erling Smørgrav if(algo == LDNS_ECDSAP256SHA256) {
10938ed2b524SDag-Erling Smørgrav params.data = param256;
10948ed2b524SDag-Erling Smørgrav params.len = sizeof(param256);
10958ed2b524SDag-Erling Smørgrav } else {
10968ed2b524SDag-Erling Smørgrav params.data = param384;
10978ed2b524SDag-Erling Smørgrav params.len = sizeof(param384);
10988ed2b524SDag-Erling Smørgrav }
10998ed2b524SDag-Erling Smørgrav
11008ed2b524SDag-Erling Smørgrav pk = nss_key_create(ecKey);
11018ed2b524SDag-Erling Smørgrav if(!pk)
11028ed2b524SDag-Erling Smørgrav return NULL;
11038ed2b524SDag-Erling Smørgrav pk->u.ec.size = (len/2)*8;
11048ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.ec.publicValue, &pub)) {
11058ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk);
11068ed2b524SDag-Erling Smørgrav return NULL;
11078ed2b524SDag-Erling Smørgrav }
11088ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.ec.DEREncodedParams, ¶ms)) {
11098ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk);
11108ed2b524SDag-Erling Smørgrav return NULL;
11118ed2b524SDag-Erling Smørgrav }
11128ed2b524SDag-Erling Smørgrav
11138ed2b524SDag-Erling Smørgrav return pk;
11148ed2b524SDag-Erling Smørgrav }
11158ed2b524SDag-Erling Smørgrav
1116369c6923SCy Schubert #if defined(USE_DSA) && defined(USE_SHA1)
nss_buf2dsa(unsigned char * key,size_t len)11178ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_buf2dsa(unsigned char* key, size_t len)
11188ed2b524SDag-Erling Smørgrav {
11198ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pk;
11208ed2b524SDag-Erling Smørgrav uint8_t T;
11218ed2b524SDag-Erling Smørgrav uint16_t length;
11228ed2b524SDag-Erling Smørgrav uint16_t offset;
11238ed2b524SDag-Erling Smørgrav SECItem Q = {siBuffer, NULL, 0};
11248ed2b524SDag-Erling Smørgrav SECItem P = {siBuffer, NULL, 0};
11258ed2b524SDag-Erling Smørgrav SECItem G = {siBuffer, NULL, 0};
11268ed2b524SDag-Erling Smørgrav SECItem Y = {siBuffer, NULL, 0};
11278ed2b524SDag-Erling Smørgrav
11288ed2b524SDag-Erling Smørgrav if(len == 0)
11298ed2b524SDag-Erling Smørgrav return NULL;
11308ed2b524SDag-Erling Smørgrav T = (uint8_t)key[0];
11318ed2b524SDag-Erling Smørgrav length = (64 + T * 8);
11328ed2b524SDag-Erling Smørgrav offset = 1;
11338ed2b524SDag-Erling Smørgrav
11348ed2b524SDag-Erling Smørgrav if (T > 8) {
11358ed2b524SDag-Erling Smørgrav return NULL;
11368ed2b524SDag-Erling Smørgrav }
11378ed2b524SDag-Erling Smørgrav if(len < (size_t)1 + SHA1_LENGTH + 3*length)
11388ed2b524SDag-Erling Smørgrav return NULL;
11398ed2b524SDag-Erling Smørgrav
11408ed2b524SDag-Erling Smørgrav Q.data = key+offset;
11418ed2b524SDag-Erling Smørgrav Q.len = SHA1_LENGTH;
11428ed2b524SDag-Erling Smørgrav offset += SHA1_LENGTH;
11438ed2b524SDag-Erling Smørgrav
11448ed2b524SDag-Erling Smørgrav P.data = key+offset;
11458ed2b524SDag-Erling Smørgrav P.len = length;
11468ed2b524SDag-Erling Smørgrav offset += length;
11478ed2b524SDag-Erling Smørgrav
11488ed2b524SDag-Erling Smørgrav G.data = key+offset;
11498ed2b524SDag-Erling Smørgrav G.len = length;
11508ed2b524SDag-Erling Smørgrav offset += length;
11518ed2b524SDag-Erling Smørgrav
11528ed2b524SDag-Erling Smørgrav Y.data = key+offset;
11538ed2b524SDag-Erling Smørgrav Y.len = length;
11548ed2b524SDag-Erling Smørgrav offset += length;
11558ed2b524SDag-Erling Smørgrav
11568ed2b524SDag-Erling Smørgrav pk = nss_key_create(dsaKey);
11578ed2b524SDag-Erling Smørgrav if(!pk)
11588ed2b524SDag-Erling Smørgrav return NULL;
11598ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.prime, &P)) {
11608ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk);
11618ed2b524SDag-Erling Smørgrav return NULL;
11628ed2b524SDag-Erling Smørgrav }
11638ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.subPrime, &Q)) {
11648ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk);
11658ed2b524SDag-Erling Smørgrav return NULL;
11668ed2b524SDag-Erling Smørgrav }
11678ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.params.base, &G)) {
11688ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk);
11698ed2b524SDag-Erling Smørgrav return NULL;
11708ed2b524SDag-Erling Smørgrav }
11718ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.dsa.publicValue, &Y)) {
11728ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk);
11738ed2b524SDag-Erling Smørgrav return NULL;
11748ed2b524SDag-Erling Smørgrav }
11758ed2b524SDag-Erling Smørgrav return pk;
11768ed2b524SDag-Erling Smørgrav }
1177369c6923SCy Schubert #endif /* USE_DSA && USE_SHA1 */
11788ed2b524SDag-Erling Smørgrav
nss_buf2rsa(unsigned char * key,size_t len)11798ed2b524SDag-Erling Smørgrav static SECKEYPublicKey* nss_buf2rsa(unsigned char* key, size_t len)
11808ed2b524SDag-Erling Smørgrav {
11818ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pk;
11828ed2b524SDag-Erling Smørgrav uint16_t exp;
11838ed2b524SDag-Erling Smørgrav uint16_t offset;
11848ed2b524SDag-Erling Smørgrav uint16_t int16;
11858ed2b524SDag-Erling Smørgrav SECItem modulus = {siBuffer, NULL, 0};
11868ed2b524SDag-Erling Smørgrav SECItem exponent = {siBuffer, NULL, 0};
11878ed2b524SDag-Erling Smørgrav if(len == 0)
11888ed2b524SDag-Erling Smørgrav return NULL;
11898ed2b524SDag-Erling Smørgrav if(key[0] == 0) {
11908ed2b524SDag-Erling Smørgrav if(len < 3)
11918ed2b524SDag-Erling Smørgrav return NULL;
11928ed2b524SDag-Erling Smørgrav /* the exponent is too large so it's places further */
11938ed2b524SDag-Erling Smørgrav memmove(&int16, key+1, 2);
11948ed2b524SDag-Erling Smørgrav exp = ntohs(int16);
11958ed2b524SDag-Erling Smørgrav offset = 3;
11968ed2b524SDag-Erling Smørgrav } else {
11978ed2b524SDag-Erling Smørgrav exp = key[0];
11988ed2b524SDag-Erling Smørgrav offset = 1;
11998ed2b524SDag-Erling Smørgrav }
12008ed2b524SDag-Erling Smørgrav
12018ed2b524SDag-Erling Smørgrav /* key length at least one */
12028ed2b524SDag-Erling Smørgrav if(len < (size_t)offset + exp + 1)
12038ed2b524SDag-Erling Smørgrav return NULL;
12048ed2b524SDag-Erling Smørgrav
12058ed2b524SDag-Erling Smørgrav exponent.data = key+offset;
12068ed2b524SDag-Erling Smørgrav exponent.len = exp;
12078ed2b524SDag-Erling Smørgrav offset += exp;
12088ed2b524SDag-Erling Smørgrav modulus.data = key+offset;
12098ed2b524SDag-Erling Smørgrav modulus.len = (len - offset);
12108ed2b524SDag-Erling Smørgrav
12118ed2b524SDag-Erling Smørgrav pk = nss_key_create(rsaKey);
12128ed2b524SDag-Erling Smørgrav if(!pk)
12138ed2b524SDag-Erling Smørgrav return NULL;
12148ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.modulus, &modulus)) {
12158ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk);
12168ed2b524SDag-Erling Smørgrav return NULL;
12178ed2b524SDag-Erling Smørgrav }
12188ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pk->arena, &pk->u.rsa.publicExponent, &exponent)) {
12198ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pk);
12208ed2b524SDag-Erling Smørgrav return NULL;
12218ed2b524SDag-Erling Smørgrav }
12228ed2b524SDag-Erling Smørgrav return pk;
12238ed2b524SDag-Erling Smørgrav }
12248ed2b524SDag-Erling Smørgrav
12258ed2b524SDag-Erling Smørgrav /**
12268ed2b524SDag-Erling Smørgrav * Setup key and digest for verification. Adjust sig if necessary.
12278ed2b524SDag-Erling Smørgrav *
12288ed2b524SDag-Erling Smørgrav * @param algo: key algorithm
12298ed2b524SDag-Erling Smørgrav * @param evp_key: EVP PKEY public key to create.
12308ed2b524SDag-Erling Smørgrav * @param digest_type: digest type to use
12318ed2b524SDag-Erling Smørgrav * @param key: key to setup for.
12328ed2b524SDag-Erling Smørgrav * @param keylen: length of key.
12338ed2b524SDag-Erling Smørgrav * @param prefix: if returned, the ASN prefix for the hashblob.
12348ed2b524SDag-Erling Smørgrav * @param prefixlen: length of the prefix.
12358ed2b524SDag-Erling Smørgrav * @return false on failure.
12368ed2b524SDag-Erling Smørgrav */
12378ed2b524SDag-Erling Smørgrav static int
nss_setup_key_digest(int algo,SECKEYPublicKey ** pubkey,HASH_HashType * htype,unsigned char * key,size_t keylen,unsigned char ** prefix,size_t * prefixlen)12388ed2b524SDag-Erling Smørgrav nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
12398ed2b524SDag-Erling Smørgrav unsigned char* key, size_t keylen, unsigned char** prefix,
12408ed2b524SDag-Erling Smørgrav size_t* prefixlen)
12418ed2b524SDag-Erling Smørgrav {
12428ed2b524SDag-Erling Smørgrav /* uses libNSS */
12438ed2b524SDag-Erling Smørgrav
12448ed2b524SDag-Erling Smørgrav /* hash prefix for md5, RFC2537 */
124517d15b25SDag-Erling Smørgrav static unsigned char p_md5[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a,
12468ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10};
12478ed2b524SDag-Erling Smørgrav /* hash prefix to prepend to hash output, from RFC3110 */
124817d15b25SDag-Erling Smørgrav static unsigned char p_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B,
12498ed2b524SDag-Erling Smørgrav 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14};
12508ed2b524SDag-Erling Smørgrav /* from RFC5702 */
125117d15b25SDag-Erling Smørgrav static unsigned char p_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
12528ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
125317d15b25SDag-Erling Smørgrav static unsigned char p_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
12548ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
12558ed2b524SDag-Erling Smørgrav /* from RFC6234 */
12568ed2b524SDag-Erling Smørgrav /* for future RSASHA384 ..
125717d15b25SDag-Erling Smørgrav static unsigned char p_sha384[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60,
12588ed2b524SDag-Erling Smørgrav 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
12598ed2b524SDag-Erling Smørgrav */
12608ed2b524SDag-Erling Smørgrav
12618ed2b524SDag-Erling Smørgrav switch(algo) {
126265b390aaSDag-Erling Smørgrav
126365b390aaSDag-Erling Smørgrav #if defined(USE_SHA1) || defined(USE_SHA2)
126465b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1)
12658ed2b524SDag-Erling Smørgrav case LDNS_DSA:
12668ed2b524SDag-Erling Smørgrav case LDNS_DSA_NSEC3:
12678ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2dsa(key, keylen);
12688ed2b524SDag-Erling Smørgrav if(!*pubkey) {
12698ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto");
12708ed2b524SDag-Erling Smørgrav return 0;
12718ed2b524SDag-Erling Smørgrav }
12728ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA1;
12738ed2b524SDag-Erling Smørgrav /* no prefix for DSA verification */
12748ed2b524SDag-Erling Smørgrav break;
1275e2d15004SDag-Erling Smørgrav #endif
127665b390aaSDag-Erling Smørgrav #ifdef USE_SHA1
12778ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1:
12788ed2b524SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3:
127965b390aaSDag-Erling Smørgrav #endif
12808ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2
12818ed2b524SDag-Erling Smørgrav case LDNS_RSASHA256:
12828ed2b524SDag-Erling Smørgrav #endif
12838ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2
12848ed2b524SDag-Erling Smørgrav case LDNS_RSASHA512:
12858ed2b524SDag-Erling Smørgrav #endif
12868ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2rsa(key, keylen);
12878ed2b524SDag-Erling Smørgrav if(!*pubkey) {
12888ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto");
12898ed2b524SDag-Erling Smørgrav return 0;
12908ed2b524SDag-Erling Smørgrav }
12918ed2b524SDag-Erling Smørgrav /* select SHA version */
12928ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2
12938ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA256) {
12948ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA256;
12958ed2b524SDag-Erling Smørgrav *prefix = p_sha256;
12968ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_sha256);
12978ed2b524SDag-Erling Smørgrav } else
12988ed2b524SDag-Erling Smørgrav #endif
12998ed2b524SDag-Erling Smørgrav #ifdef USE_SHA2
13008ed2b524SDag-Erling Smørgrav if(algo == LDNS_RSASHA512) {
13018ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA512;
13028ed2b524SDag-Erling Smørgrav *prefix = p_sha512;
13038ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_sha512);
13048ed2b524SDag-Erling Smørgrav } else
13058ed2b524SDag-Erling Smørgrav #endif
130665b390aaSDag-Erling Smørgrav #ifdef USE_SHA1
13078ed2b524SDag-Erling Smørgrav {
13088ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA1;
13098ed2b524SDag-Erling Smørgrav *prefix = p_sha1;
13108ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_sha1);
13118ed2b524SDag-Erling Smørgrav }
131265b390aaSDag-Erling Smørgrav #else
131365b390aaSDag-Erling Smørgrav {
131465b390aaSDag-Erling Smørgrav verbose(VERB_QUERY, "verify: no digest algo");
131565b390aaSDag-Erling Smørgrav return 0;
131665b390aaSDag-Erling Smørgrav }
131765b390aaSDag-Erling Smørgrav #endif
13188ed2b524SDag-Erling Smørgrav
13198ed2b524SDag-Erling Smørgrav break;
132065b390aaSDag-Erling Smørgrav #endif /* SHA1 or SHA2 */
132165b390aaSDag-Erling Smørgrav
13228ed2b524SDag-Erling Smørgrav case LDNS_RSAMD5:
13238ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2rsa(key, keylen);
13248ed2b524SDag-Erling Smørgrav if(!*pubkey) {
13258ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto");
13268ed2b524SDag-Erling Smørgrav return 0;
13278ed2b524SDag-Erling Smørgrav }
13288ed2b524SDag-Erling Smørgrav *htype = HASH_AlgMD5;
13298ed2b524SDag-Erling Smørgrav *prefix = p_md5;
13308ed2b524SDag-Erling Smørgrav *prefixlen = sizeof(p_md5);
13318ed2b524SDag-Erling Smørgrav
13328ed2b524SDag-Erling Smørgrav break;
13338ed2b524SDag-Erling Smørgrav #ifdef USE_ECDSA
13348ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256:
13358ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2ecdsa(key, keylen,
13368ed2b524SDag-Erling Smørgrav LDNS_ECDSAP256SHA256);
13378ed2b524SDag-Erling Smørgrav if(!*pubkey) {
13388ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto");
13398ed2b524SDag-Erling Smørgrav return 0;
13408ed2b524SDag-Erling Smørgrav }
13418ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA256;
13428ed2b524SDag-Erling Smørgrav /* no prefix for DSA verification */
13438ed2b524SDag-Erling Smørgrav break;
13448ed2b524SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384:
13458ed2b524SDag-Erling Smørgrav *pubkey = nss_buf2ecdsa(key, keylen,
13468ed2b524SDag-Erling Smørgrav LDNS_ECDSAP384SHA384);
13478ed2b524SDag-Erling Smørgrav if(!*pubkey) {
13488ed2b524SDag-Erling Smørgrav log_err("verify: malloc failure in crypto");
13498ed2b524SDag-Erling Smørgrav return 0;
13508ed2b524SDag-Erling Smørgrav }
13518ed2b524SDag-Erling Smørgrav *htype = HASH_AlgSHA384;
13528ed2b524SDag-Erling Smørgrav /* no prefix for DSA verification */
13538ed2b524SDag-Erling Smørgrav break;
13548ed2b524SDag-Erling Smørgrav #endif /* USE_ECDSA */
13558ed2b524SDag-Erling Smørgrav case LDNS_ECC_GOST:
13568ed2b524SDag-Erling Smørgrav default:
13578ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: unknown algorithm %d",
13588ed2b524SDag-Erling Smørgrav algo);
13598ed2b524SDag-Erling Smørgrav return 0;
13608ed2b524SDag-Erling Smørgrav }
13618ed2b524SDag-Erling Smørgrav return 1;
13628ed2b524SDag-Erling Smørgrav }
13638ed2b524SDag-Erling Smørgrav
13648ed2b524SDag-Erling Smørgrav /**
13658ed2b524SDag-Erling Smørgrav * Check a canonical sig+rrset and signature against a dnskey
13668ed2b524SDag-Erling Smørgrav * @param buf: buffer with data to verify, the first rrsig part and the
13678ed2b524SDag-Erling Smørgrav * canonicalized rrset.
13688ed2b524SDag-Erling Smørgrav * @param algo: DNSKEY algorithm.
13698ed2b524SDag-Erling Smørgrav * @param sigblock: signature rdata field from RRSIG
13708ed2b524SDag-Erling Smørgrav * @param sigblock_len: length of sigblock data.
13718ed2b524SDag-Erling Smørgrav * @param key: public key data from DNSKEY RR.
13728ed2b524SDag-Erling Smørgrav * @param keylen: length of keydata.
13738ed2b524SDag-Erling Smørgrav * @param reason: bogus reason in more detail.
13748ed2b524SDag-Erling Smørgrav * @return secure if verification succeeded, bogus on crypto failure,
13758ed2b524SDag-Erling Smørgrav * unchecked on format errors and alloc failures.
13768ed2b524SDag-Erling Smørgrav */
13778ed2b524SDag-Erling Smørgrav enum sec_status
verify_canonrrset(sldns_buffer * buf,int algo,unsigned char * sigblock,unsigned int sigblock_len,unsigned char * key,unsigned int keylen,char ** reason)137817d15b25SDag-Erling Smørgrav verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
13798ed2b524SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
13808ed2b524SDag-Erling Smørgrav char** reason)
13818ed2b524SDag-Erling Smørgrav {
13828ed2b524SDag-Erling Smørgrav /* uses libNSS */
13838ed2b524SDag-Erling Smørgrav /* large enough for the different hashes */
13848ed2b524SDag-Erling Smørgrav unsigned char hash[HASH_LENGTH_MAX];
13858ed2b524SDag-Erling Smørgrav unsigned char hash2[HASH_LENGTH_MAX*2];
13868ed2b524SDag-Erling Smørgrav HASH_HashType htype = 0;
13878ed2b524SDag-Erling Smørgrav SECKEYPublicKey* pubkey = NULL;
13888ed2b524SDag-Erling Smørgrav SECItem secsig = {siBuffer, sigblock, sigblock_len};
13898ed2b524SDag-Erling Smørgrav SECItem sechash = {siBuffer, hash, 0};
13908ed2b524SDag-Erling Smørgrav SECStatus res;
13918ed2b524SDag-Erling Smørgrav unsigned char* prefix = NULL; /* prefix for hash, RFC3110, RFC5702 */
13928ed2b524SDag-Erling Smørgrav size_t prefixlen = 0;
13938ed2b524SDag-Erling Smørgrav int err;
13948ed2b524SDag-Erling Smørgrav
13958ed2b524SDag-Erling Smørgrav if(!nss_setup_key_digest(algo, &pubkey, &htype, key, keylen,
13968ed2b524SDag-Erling Smørgrav &prefix, &prefixlen)) {
13978ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed to setup key");
13988ed2b524SDag-Erling Smørgrav *reason = "use of key for crypto failed";
13998ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey);
14008ed2b524SDag-Erling Smørgrav return sec_status_bogus;
14018ed2b524SDag-Erling Smørgrav }
14028ed2b524SDag-Erling Smørgrav
140365b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1)
14048ed2b524SDag-Erling Smørgrav /* need to convert DSA, ECDSA signatures? */
14058ed2b524SDag-Erling Smørgrav if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) {
14068ed2b524SDag-Erling Smørgrav if(sigblock_len == 1+2*SHA1_LENGTH) {
14078ed2b524SDag-Erling Smørgrav secsig.data ++;
14088ed2b524SDag-Erling Smørgrav secsig.len --;
14098ed2b524SDag-Erling Smørgrav } else {
14108ed2b524SDag-Erling Smørgrav SECItem* p = DSAU_DecodeDerSig(&secsig);
14118ed2b524SDag-Erling Smørgrav if(!p) {
14128ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: failed DER decode");
14138ed2b524SDag-Erling Smørgrav *reason = "signature DER decode failed";
14148ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey);
14158ed2b524SDag-Erling Smørgrav return sec_status_bogus;
14168ed2b524SDag-Erling Smørgrav }
14178ed2b524SDag-Erling Smørgrav if(SECITEM_CopyItem(pubkey->arena, &secsig, p)) {
14188ed2b524SDag-Erling Smørgrav log_err("alloc failure in DER decode");
14198ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey);
14208ed2b524SDag-Erling Smørgrav SECITEM_FreeItem(p, PR_TRUE);
14218ed2b524SDag-Erling Smørgrav return sec_status_unchecked;
14228ed2b524SDag-Erling Smørgrav }
14238ed2b524SDag-Erling Smørgrav SECITEM_FreeItem(p, PR_TRUE);
14248ed2b524SDag-Erling Smørgrav }
14258ed2b524SDag-Erling Smørgrav }
1426e2d15004SDag-Erling Smørgrav #endif /* USE_DSA */
14278ed2b524SDag-Erling Smørgrav
14288ed2b524SDag-Erling Smørgrav /* do the signature cryptography work */
14298ed2b524SDag-Erling Smørgrav /* hash the data */
14308ed2b524SDag-Erling Smørgrav sechash.len = HASH_ResultLen(htype);
14318ed2b524SDag-Erling Smørgrav if(sechash.len > sizeof(hash)) {
14328ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: hash too large for buffer");
14338ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey);
14348ed2b524SDag-Erling Smørgrav return sec_status_unchecked;
14358ed2b524SDag-Erling Smørgrav }
143617d15b25SDag-Erling Smørgrav if(HASH_HashBuf(htype, hash, (unsigned char*)sldns_buffer_begin(buf),
143717d15b25SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf)) != SECSuccess) {
14388ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: HASH_HashBuf failed");
14398ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey);
14408ed2b524SDag-Erling Smørgrav return sec_status_unchecked;
14418ed2b524SDag-Erling Smørgrav }
14428ed2b524SDag-Erling Smørgrav if(prefix) {
14438ed2b524SDag-Erling Smørgrav int hashlen = sechash.len;
14448ed2b524SDag-Erling Smørgrav if(prefixlen+hashlen > sizeof(hash2)) {
14458ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: hashprefix too large");
14468ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey);
14478ed2b524SDag-Erling Smørgrav return sec_status_unchecked;
14488ed2b524SDag-Erling Smørgrav }
14498ed2b524SDag-Erling Smørgrav sechash.data = hash2;
14508ed2b524SDag-Erling Smørgrav sechash.len = prefixlen+hashlen;
14518ed2b524SDag-Erling Smørgrav memcpy(sechash.data, prefix, prefixlen);
14528ed2b524SDag-Erling Smørgrav memmove(sechash.data+prefixlen, hash, hashlen);
14538ed2b524SDag-Erling Smørgrav }
14548ed2b524SDag-Erling Smørgrav
14558ed2b524SDag-Erling Smørgrav /* verify the signature */
14568ed2b524SDag-Erling Smørgrav res = PK11_Verify(pubkey, &secsig, &sechash, NULL /*wincx*/);
14578ed2b524SDag-Erling Smørgrav SECKEY_DestroyPublicKey(pubkey);
14588ed2b524SDag-Erling Smørgrav
14598ed2b524SDag-Erling Smørgrav if(res == SECSuccess) {
14608ed2b524SDag-Erling Smørgrav return sec_status_secure;
14618ed2b524SDag-Erling Smørgrav }
14628ed2b524SDag-Erling Smørgrav err = PORT_GetError();
14638ed2b524SDag-Erling Smørgrav if(err != SEC_ERROR_BAD_SIGNATURE) {
14648ed2b524SDag-Erling Smørgrav /* failed to verify */
14658ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: PK11_Verify failed: %s",
14668ed2b524SDag-Erling Smørgrav PORT_ErrorToString(err));
14678ed2b524SDag-Erling Smørgrav /* if it is not supported, like ECC is removed, we get,
14688ed2b524SDag-Erling Smørgrav * SEC_ERROR_NO_MODULE */
14698ed2b524SDag-Erling Smørgrav if(err == SEC_ERROR_NO_MODULE)
14708ed2b524SDag-Erling Smørgrav return sec_status_unchecked;
14718ed2b524SDag-Erling Smørgrav /* but other errors are commonly returned
14728ed2b524SDag-Erling Smørgrav * for a bad signature from NSS. Thus we return bogus,
14738ed2b524SDag-Erling Smørgrav * not unchecked */
14748ed2b524SDag-Erling Smørgrav *reason = "signature crypto failed";
14758ed2b524SDag-Erling Smørgrav return sec_status_bogus;
14768ed2b524SDag-Erling Smørgrav }
14778ed2b524SDag-Erling Smørgrav verbose(VERB_QUERY, "verify: signature mismatch: %s",
14788ed2b524SDag-Erling Smørgrav PORT_ErrorToString(err));
14798ed2b524SDag-Erling Smørgrav *reason = "signature crypto failed";
14808ed2b524SDag-Erling Smørgrav return sec_status_bogus;
14818ed2b524SDag-Erling Smørgrav }
14828ed2b524SDag-Erling Smørgrav
148305ab2901SDag-Erling Smørgrav #elif defined(HAVE_NETTLE)
14848ed2b524SDag-Erling Smørgrav
148505ab2901SDag-Erling Smørgrav #include "sha.h"
148605ab2901SDag-Erling Smørgrav #include "bignum.h"
148705ab2901SDag-Erling Smørgrav #include "macros.h"
148805ab2901SDag-Erling Smørgrav #include "rsa.h"
148905ab2901SDag-Erling Smørgrav #include "dsa.h"
1490b5663de9SDag-Erling Smørgrav #ifdef HAVE_NETTLE_DSA_COMPAT_H
1491b5663de9SDag-Erling Smørgrav #include "dsa-compat.h"
1492b5663de9SDag-Erling Smørgrav #endif
149305ab2901SDag-Erling Smørgrav #include "asn1.h"
149405ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA
149505ab2901SDag-Erling Smørgrav #include "ecdsa.h"
149605ab2901SDag-Erling Smørgrav #include "ecc-curve.h"
149705ab2901SDag-Erling Smørgrav #endif
1498971980c3SDag-Erling Smørgrav #ifdef HAVE_NETTLE_EDDSA_H
1499971980c3SDag-Erling Smørgrav #include "eddsa.h"
1500971980c3SDag-Erling Smørgrav #endif
150105ab2901SDag-Erling Smørgrav
150205ab2901SDag-Erling Smørgrav static int
_digest_nettle(int algo,uint8_t * buf,size_t len,unsigned char * res)150305ab2901SDag-Erling Smørgrav _digest_nettle(int algo, uint8_t* buf, size_t len,
150405ab2901SDag-Erling Smørgrav unsigned char* res)
150505ab2901SDag-Erling Smørgrav {
150605ab2901SDag-Erling Smørgrav switch(algo) {
150705ab2901SDag-Erling Smørgrav case SHA1_DIGEST_SIZE:
150805ab2901SDag-Erling Smørgrav {
150905ab2901SDag-Erling Smørgrav struct sha1_ctx ctx;
151005ab2901SDag-Erling Smørgrav sha1_init(&ctx);
151105ab2901SDag-Erling Smørgrav sha1_update(&ctx, len, buf);
151205ab2901SDag-Erling Smørgrav sha1_digest(&ctx, SHA1_DIGEST_SIZE, res);
151305ab2901SDag-Erling Smørgrav return 1;
151405ab2901SDag-Erling Smørgrav }
151505ab2901SDag-Erling Smørgrav case SHA256_DIGEST_SIZE:
151605ab2901SDag-Erling Smørgrav {
151705ab2901SDag-Erling Smørgrav struct sha256_ctx ctx;
151805ab2901SDag-Erling Smørgrav sha256_init(&ctx);
151905ab2901SDag-Erling Smørgrav sha256_update(&ctx, len, buf);
152005ab2901SDag-Erling Smørgrav sha256_digest(&ctx, SHA256_DIGEST_SIZE, res);
152105ab2901SDag-Erling Smørgrav return 1;
152205ab2901SDag-Erling Smørgrav }
152305ab2901SDag-Erling Smørgrav case SHA384_DIGEST_SIZE:
152405ab2901SDag-Erling Smørgrav {
152505ab2901SDag-Erling Smørgrav struct sha384_ctx ctx;
152605ab2901SDag-Erling Smørgrav sha384_init(&ctx);
152705ab2901SDag-Erling Smørgrav sha384_update(&ctx, len, buf);
152805ab2901SDag-Erling Smørgrav sha384_digest(&ctx, SHA384_DIGEST_SIZE, res);
152905ab2901SDag-Erling Smørgrav return 1;
153005ab2901SDag-Erling Smørgrav }
153105ab2901SDag-Erling Smørgrav case SHA512_DIGEST_SIZE:
153205ab2901SDag-Erling Smørgrav {
153305ab2901SDag-Erling Smørgrav struct sha512_ctx ctx;
153405ab2901SDag-Erling Smørgrav sha512_init(&ctx);
153505ab2901SDag-Erling Smørgrav sha512_update(&ctx, len, buf);
153605ab2901SDag-Erling Smørgrav sha512_digest(&ctx, SHA512_DIGEST_SIZE, res);
153705ab2901SDag-Erling Smørgrav return 1;
153805ab2901SDag-Erling Smørgrav }
153905ab2901SDag-Erling Smørgrav default:
154005ab2901SDag-Erling Smørgrav break;
154105ab2901SDag-Erling Smørgrav }
154205ab2901SDag-Erling Smørgrav return 0;
154305ab2901SDag-Erling Smørgrav }
154405ab2901SDag-Erling Smørgrav
154505ab2901SDag-Erling Smørgrav /* return size of digest if supported, or 0 otherwise */
154605ab2901SDag-Erling Smørgrav size_t
nsec3_hash_algo_size_supported(int id)154705ab2901SDag-Erling Smørgrav nsec3_hash_algo_size_supported(int id)
154805ab2901SDag-Erling Smørgrav {
154905ab2901SDag-Erling Smørgrav switch(id) {
155005ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1:
155105ab2901SDag-Erling Smørgrav return SHA1_DIGEST_SIZE;
155205ab2901SDag-Erling Smørgrav default:
155305ab2901SDag-Erling Smørgrav return 0;
155405ab2901SDag-Erling Smørgrav }
155505ab2901SDag-Erling Smørgrav }
155605ab2901SDag-Erling Smørgrav
155705ab2901SDag-Erling Smørgrav /* perform nsec3 hash. return false on failure */
155805ab2901SDag-Erling Smørgrav int
secalgo_nsec3_hash(int algo,unsigned char * buf,size_t len,unsigned char * res)155905ab2901SDag-Erling Smørgrav secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
156005ab2901SDag-Erling Smørgrav unsigned char* res)
156105ab2901SDag-Erling Smørgrav {
156205ab2901SDag-Erling Smørgrav switch(algo) {
156305ab2901SDag-Erling Smørgrav case NSEC3_HASH_SHA1:
156405ab2901SDag-Erling Smørgrav return _digest_nettle(SHA1_DIGEST_SIZE, (uint8_t*)buf, len,
156505ab2901SDag-Erling Smørgrav res);
156605ab2901SDag-Erling Smørgrav default:
156705ab2901SDag-Erling Smørgrav return 0;
156805ab2901SDag-Erling Smørgrav }
156905ab2901SDag-Erling Smørgrav }
157005ab2901SDag-Erling Smørgrav
1571e2d15004SDag-Erling Smørgrav void
secalgo_hash_sha256(unsigned char * buf,size_t len,unsigned char * res)1572e2d15004SDag-Erling Smørgrav secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
1573e2d15004SDag-Erling Smørgrav {
1574e2d15004SDag-Erling Smørgrav _digest_nettle(SHA256_DIGEST_SIZE, (uint8_t*)buf, len, res);
1575e2d15004SDag-Erling Smørgrav }
1576e2d15004SDag-Erling Smørgrav
15775469a995SCy Schubert /** secalgo hash structure */
15785469a995SCy Schubert struct secalgo_hash {
15795469a995SCy Schubert /** if it is 384 or 512 */
15805469a995SCy Schubert int active;
15815469a995SCy Schubert /** context for sha384 */
15825469a995SCy Schubert struct sha384_ctx ctx384;
15835469a995SCy Schubert /** context for sha512 */
15845469a995SCy Schubert struct sha512_ctx ctx512;
15855469a995SCy Schubert };
15865469a995SCy Schubert
secalgo_hash_create_sha384(void)15875469a995SCy Schubert struct secalgo_hash* secalgo_hash_create_sha384(void)
15885469a995SCy Schubert {
15895469a995SCy Schubert struct secalgo_hash* h = calloc(1, sizeof(*h));
15905469a995SCy Schubert if(!h)
15915469a995SCy Schubert return NULL;
15925469a995SCy Schubert h->active = 384;
15935469a995SCy Schubert sha384_init(&h->ctx384);
15945469a995SCy Schubert return h;
15955469a995SCy Schubert }
15965469a995SCy Schubert
secalgo_hash_create_sha512(void)15975469a995SCy Schubert struct secalgo_hash* secalgo_hash_create_sha512(void)
15985469a995SCy Schubert {
15995469a995SCy Schubert struct secalgo_hash* h = calloc(1, sizeof(*h));
16005469a995SCy Schubert if(!h)
16015469a995SCy Schubert return NULL;
16025469a995SCy Schubert h->active = 512;
16035469a995SCy Schubert sha512_init(&h->ctx512);
16045469a995SCy Schubert return h;
16055469a995SCy Schubert }
16065469a995SCy Schubert
secalgo_hash_update(struct secalgo_hash * hash,uint8_t * data,size_t len)16075469a995SCy Schubert int secalgo_hash_update(struct secalgo_hash* hash, uint8_t* data, size_t len)
16085469a995SCy Schubert {
16095469a995SCy Schubert if(hash->active == 384) {
16105469a995SCy Schubert sha384_update(&hash->ctx384, len, data);
16115469a995SCy Schubert } else if(hash->active == 512) {
16125469a995SCy Schubert sha512_update(&hash->ctx512, len, data);
16135469a995SCy Schubert } else {
16145469a995SCy Schubert return 0;
16155469a995SCy Schubert }
16165469a995SCy Schubert return 1;
16175469a995SCy Schubert }
16185469a995SCy Schubert
secalgo_hash_final(struct secalgo_hash * hash,uint8_t * result,size_t maxlen,size_t * resultlen)16195469a995SCy Schubert int secalgo_hash_final(struct secalgo_hash* hash, uint8_t* result,
16205469a995SCy Schubert size_t maxlen, size_t* resultlen)
16215469a995SCy Schubert {
16225469a995SCy Schubert if(hash->active == 384) {
16235469a995SCy Schubert if(SHA384_DIGEST_SIZE > maxlen) {
16245469a995SCy Schubert *resultlen = 0;
16255469a995SCy Schubert log_err("secalgo_hash_final: hash buffer too small");
16265469a995SCy Schubert return 0;
16275469a995SCy Schubert }
16285469a995SCy Schubert *resultlen = SHA384_DIGEST_SIZE;
16295469a995SCy Schubert sha384_digest(&hash->ctx384, SHA384_DIGEST_SIZE,
16305469a995SCy Schubert (unsigned char*)result);
16315469a995SCy Schubert } else if(hash->active == 512) {
16325469a995SCy Schubert if(SHA512_DIGEST_SIZE > maxlen) {
16335469a995SCy Schubert *resultlen = 0;
16345469a995SCy Schubert log_err("secalgo_hash_final: hash buffer too small");
16355469a995SCy Schubert return 0;
16365469a995SCy Schubert }
16375469a995SCy Schubert *resultlen = SHA512_DIGEST_SIZE;
16385469a995SCy Schubert sha512_digest(&hash->ctx512, SHA512_DIGEST_SIZE,
16395469a995SCy Schubert (unsigned char*)result);
16405469a995SCy Schubert } else {
16415469a995SCy Schubert *resultlen = 0;
16425469a995SCy Schubert return 0;
16435469a995SCy Schubert }
16445469a995SCy Schubert return 1;
16455469a995SCy Schubert }
16465469a995SCy Schubert
secalgo_hash_delete(struct secalgo_hash * hash)16475469a995SCy Schubert void secalgo_hash_delete(struct secalgo_hash* hash)
16485469a995SCy Schubert {
16495469a995SCy Schubert if(!hash) return;
16505469a995SCy Schubert free(hash);
16515469a995SCy Schubert }
16525469a995SCy Schubert
165305ab2901SDag-Erling Smørgrav /**
165405ab2901SDag-Erling Smørgrav * Return size of DS digest according to its hash algorithm.
165505ab2901SDag-Erling Smørgrav * @param algo: DS digest algo.
165605ab2901SDag-Erling Smørgrav * @return size in bytes of digest, or 0 if not supported.
165705ab2901SDag-Erling Smørgrav */
165805ab2901SDag-Erling Smørgrav size_t
ds_digest_size_supported(int algo)165905ab2901SDag-Erling Smørgrav ds_digest_size_supported(int algo)
166005ab2901SDag-Erling Smørgrav {
166105ab2901SDag-Erling Smørgrav switch(algo) {
166205ab2901SDag-Erling Smørgrav case LDNS_SHA1:
166365b390aaSDag-Erling Smørgrav #ifdef USE_SHA1
166405ab2901SDag-Erling Smørgrav return SHA1_DIGEST_SIZE;
166565b390aaSDag-Erling Smørgrav #else
166665b390aaSDag-Erling Smørgrav if(fake_sha1) return 20;
166765b390aaSDag-Erling Smørgrav return 0;
166865b390aaSDag-Erling Smørgrav #endif
166905ab2901SDag-Erling Smørgrav #ifdef USE_SHA2
167005ab2901SDag-Erling Smørgrav case LDNS_SHA256:
167105ab2901SDag-Erling Smørgrav return SHA256_DIGEST_SIZE;
167205ab2901SDag-Erling Smørgrav #endif
167305ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA
167405ab2901SDag-Erling Smørgrav case LDNS_SHA384:
167505ab2901SDag-Erling Smørgrav return SHA384_DIGEST_SIZE;
167605ab2901SDag-Erling Smørgrav #endif
167705ab2901SDag-Erling Smørgrav /* GOST not supported */
167805ab2901SDag-Erling Smørgrav case LDNS_HASH_GOST:
167905ab2901SDag-Erling Smørgrav default:
168005ab2901SDag-Erling Smørgrav break;
168105ab2901SDag-Erling Smørgrav }
168205ab2901SDag-Erling Smørgrav return 0;
168305ab2901SDag-Erling Smørgrav }
168405ab2901SDag-Erling Smørgrav
168505ab2901SDag-Erling Smørgrav int
secalgo_ds_digest(int algo,unsigned char * buf,size_t len,unsigned char * res)168605ab2901SDag-Erling Smørgrav secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
168705ab2901SDag-Erling Smørgrav unsigned char* res)
168805ab2901SDag-Erling Smørgrav {
168905ab2901SDag-Erling Smørgrav switch(algo) {
169065b390aaSDag-Erling Smørgrav #ifdef USE_SHA1
169105ab2901SDag-Erling Smørgrav case LDNS_SHA1:
169205ab2901SDag-Erling Smørgrav return _digest_nettle(SHA1_DIGEST_SIZE, buf, len, res);
169365b390aaSDag-Erling Smørgrav #endif
169405ab2901SDag-Erling Smørgrav #if defined(USE_SHA2)
169505ab2901SDag-Erling Smørgrav case LDNS_SHA256:
169605ab2901SDag-Erling Smørgrav return _digest_nettle(SHA256_DIGEST_SIZE, buf, len, res);
169705ab2901SDag-Erling Smørgrav #endif
169805ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA
169905ab2901SDag-Erling Smørgrav case LDNS_SHA384:
170005ab2901SDag-Erling Smørgrav return _digest_nettle(SHA384_DIGEST_SIZE, buf, len, res);
170105ab2901SDag-Erling Smørgrav
170205ab2901SDag-Erling Smørgrav #endif
170305ab2901SDag-Erling Smørgrav case LDNS_HASH_GOST:
170405ab2901SDag-Erling Smørgrav default:
170505ab2901SDag-Erling Smørgrav verbose(VERB_QUERY, "unknown DS digest algorithm %d",
170605ab2901SDag-Erling Smørgrav algo);
170705ab2901SDag-Erling Smørgrav break;
170805ab2901SDag-Erling Smørgrav }
170905ab2901SDag-Erling Smørgrav return 0;
171005ab2901SDag-Erling Smørgrav }
171105ab2901SDag-Erling Smørgrav
171205ab2901SDag-Erling Smørgrav int
dnskey_algo_id_is_supported(int id)171305ab2901SDag-Erling Smørgrav dnskey_algo_id_is_supported(int id)
171405ab2901SDag-Erling Smørgrav {
171505ab2901SDag-Erling Smørgrav /* uses libnettle */
171605ab2901SDag-Erling Smørgrav switch(id) {
171705ab2901SDag-Erling Smørgrav case LDNS_DSA:
171805ab2901SDag-Erling Smørgrav case LDNS_DSA_NSEC3:
1719091e9e46SCy Schubert #if defined(USE_DSA) && defined(USE_SHA1)
1720091e9e46SCy Schubert return 1;
1721091e9e46SCy Schubert #else
1722091e9e46SCy Schubert if(fake_dsa || fake_sha1) return 1;
1723091e9e46SCy Schubert return 0;
1724e2d15004SDag-Erling Smørgrav #endif
172505ab2901SDag-Erling Smørgrav case LDNS_RSASHA1:
172605ab2901SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3:
1727091e9e46SCy Schubert #ifdef USE_SHA1
1728091e9e46SCy Schubert return 1;
1729091e9e46SCy Schubert #else
1730091e9e46SCy Schubert if(fake_sha1) return 1;
1731091e9e46SCy Schubert return 0;
173265b390aaSDag-Erling Smørgrav #endif
173305ab2901SDag-Erling Smørgrav #ifdef USE_SHA2
173405ab2901SDag-Erling Smørgrav case LDNS_RSASHA256:
173505ab2901SDag-Erling Smørgrav case LDNS_RSASHA512:
173605ab2901SDag-Erling Smørgrav #endif
173705ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA
173805ab2901SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256:
173905ab2901SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384:
174005ab2901SDag-Erling Smørgrav #endif
174105ab2901SDag-Erling Smørgrav return 1;
1742971980c3SDag-Erling Smørgrav #ifdef USE_ED25519
1743971980c3SDag-Erling Smørgrav case LDNS_ED25519:
1744971980c3SDag-Erling Smørgrav return 1;
1745971980c3SDag-Erling Smørgrav #endif
174605ab2901SDag-Erling Smørgrav case LDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */
174705ab2901SDag-Erling Smørgrav case LDNS_ECC_GOST:
174805ab2901SDag-Erling Smørgrav default:
174905ab2901SDag-Erling Smørgrav return 0;
175005ab2901SDag-Erling Smørgrav }
175105ab2901SDag-Erling Smørgrav }
175205ab2901SDag-Erling Smørgrav
175365b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1)
175405ab2901SDag-Erling Smørgrav static char *
_verify_nettle_dsa(sldns_buffer * buf,unsigned char * sigblock,unsigned int sigblock_len,unsigned char * key,unsigned int keylen)175505ab2901SDag-Erling Smørgrav _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
175605ab2901SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
175705ab2901SDag-Erling Smørgrav {
175805ab2901SDag-Erling Smørgrav uint8_t digest[SHA1_DIGEST_SIZE];
17593005e0a3SDag-Erling Smørgrav uint8_t key_t_value;
176005ab2901SDag-Erling Smørgrav int res = 0;
176105ab2901SDag-Erling Smørgrav size_t offset;
176205ab2901SDag-Erling Smørgrav struct dsa_public_key pubkey;
176305ab2901SDag-Erling Smørgrav struct dsa_signature signature;
176405ab2901SDag-Erling Smørgrav unsigned int expected_len;
176505ab2901SDag-Erling Smørgrav
176605ab2901SDag-Erling Smørgrav /* Extract DSA signature from the record */
176705ab2901SDag-Erling Smørgrav nettle_dsa_signature_init(&signature);
176805ab2901SDag-Erling Smørgrav /* Signature length: 41 bytes - RFC 2536 sec. 3 */
176905ab2901SDag-Erling Smørgrav if(sigblock_len == 41) {
177005ab2901SDag-Erling Smørgrav if(key[0] != sigblock[0])
177105ab2901SDag-Erling Smørgrav return "invalid T value in DSA signature or pubkey";
177205ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.r, 20, sigblock+1);
177305ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.s, 20, sigblock+1+20);
177405ab2901SDag-Erling Smørgrav } else {
177505ab2901SDag-Erling Smørgrav /* DER encoded, decode the ASN1 notated R and S bignums */
177605ab2901SDag-Erling Smørgrav /* SEQUENCE { r INTEGER, s INTEGER } */
177705ab2901SDag-Erling Smørgrav struct asn1_der_iterator i, seq;
177805ab2901SDag-Erling Smørgrav if(asn1_der_iterator_first(&i, sigblock_len,
177905ab2901SDag-Erling Smørgrav (uint8_t*)sigblock) != ASN1_ITERATOR_CONSTRUCTED
178005ab2901SDag-Erling Smørgrav || i.type != ASN1_SEQUENCE)
178105ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature";
178205ab2901SDag-Erling Smørgrav /* decode this element of i using the seq iterator */
178305ab2901SDag-Erling Smørgrav if(asn1_der_decode_constructed(&i, &seq) !=
178405ab2901SDag-Erling Smørgrav ASN1_ITERATOR_PRIMITIVE || seq.type != ASN1_INTEGER)
178505ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature";
178605ab2901SDag-Erling Smørgrav if(!asn1_der_get_bignum(&seq, signature.r, 20*8))
178705ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature";
178805ab2901SDag-Erling Smørgrav if(asn1_der_iterator_next(&seq) != ASN1_ITERATOR_PRIMITIVE
178905ab2901SDag-Erling Smørgrav || seq.type != ASN1_INTEGER)
179005ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature";
179105ab2901SDag-Erling Smørgrav if(!asn1_der_get_bignum(&seq, signature.s, 20*8))
179205ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature";
179305ab2901SDag-Erling Smørgrav if(asn1_der_iterator_next(&i) != ASN1_ITERATOR_END)
179405ab2901SDag-Erling Smørgrav return "malformed DER encoded DSA signature";
179505ab2901SDag-Erling Smørgrav }
179605ab2901SDag-Erling Smørgrav
179705ab2901SDag-Erling Smørgrav /* Validate T values constraints - RFC 2536 sec. 2 & sec. 3 */
17983005e0a3SDag-Erling Smørgrav key_t_value = key[0];
17993005e0a3SDag-Erling Smørgrav if (key_t_value > 8) {
180005ab2901SDag-Erling Smørgrav return "invalid T value in DSA pubkey";
180105ab2901SDag-Erling Smørgrav }
180205ab2901SDag-Erling Smørgrav
180305ab2901SDag-Erling Smørgrav /* Pubkey minimum length: 21 bytes - RFC 2536 sec. 2 */
180405ab2901SDag-Erling Smørgrav if (keylen < 21) {
180505ab2901SDag-Erling Smørgrav return "DSA pubkey too short";
180605ab2901SDag-Erling Smørgrav }
180705ab2901SDag-Erling Smørgrav
180805ab2901SDag-Erling Smørgrav expected_len = 1 + /* T */
180905ab2901SDag-Erling Smørgrav 20 + /* Q */
18103005e0a3SDag-Erling Smørgrav (64 + key_t_value*8) + /* P */
18113005e0a3SDag-Erling Smørgrav (64 + key_t_value*8) + /* G */
18123005e0a3SDag-Erling Smørgrav (64 + key_t_value*8); /* Y */
181305ab2901SDag-Erling Smørgrav if (keylen != expected_len ) {
181405ab2901SDag-Erling Smørgrav return "invalid DSA pubkey length";
181505ab2901SDag-Erling Smørgrav }
181605ab2901SDag-Erling Smørgrav
181705ab2901SDag-Erling Smørgrav /* Extract DSA pubkey from the record */
181805ab2901SDag-Erling Smørgrav nettle_dsa_public_key_init(&pubkey);
181905ab2901SDag-Erling Smørgrav offset = 1;
182005ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.q, 20, key+offset);
182105ab2901SDag-Erling Smørgrav offset += 20;
18223005e0a3SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.p, (64 + key_t_value*8), key+offset);
18233005e0a3SDag-Erling Smørgrav offset += (64 + key_t_value*8);
18243005e0a3SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.g, (64 + key_t_value*8), key+offset);
18253005e0a3SDag-Erling Smørgrav offset += (64 + key_t_value*8);
18263005e0a3SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.y, (64 + key_t_value*8), key+offset);
182705ab2901SDag-Erling Smørgrav
182805ab2901SDag-Erling Smørgrav /* Digest content of "buf" and verify its DSA signature in "sigblock"*/
182905ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
183005ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
183105ab2901SDag-Erling Smørgrav res &= dsa_sha1_verify_digest(&pubkey, digest, &signature);
183205ab2901SDag-Erling Smørgrav
183305ab2901SDag-Erling Smørgrav /* Clear and return */
183405ab2901SDag-Erling Smørgrav nettle_dsa_signature_clear(&signature);
183505ab2901SDag-Erling Smørgrav nettle_dsa_public_key_clear(&pubkey);
183605ab2901SDag-Erling Smørgrav if (!res)
183705ab2901SDag-Erling Smørgrav return "DSA signature verification failed";
183805ab2901SDag-Erling Smørgrav else
183905ab2901SDag-Erling Smørgrav return NULL;
184005ab2901SDag-Erling Smørgrav }
1841b5663de9SDag-Erling Smørgrav #endif /* USE_DSA */
184205ab2901SDag-Erling Smørgrav
184305ab2901SDag-Erling Smørgrav static char *
_verify_nettle_rsa(sldns_buffer * buf,unsigned int digest_size,char * sigblock,unsigned int sigblock_len,uint8_t * key,unsigned int keylen)184405ab2901SDag-Erling Smørgrav _verify_nettle_rsa(sldns_buffer* buf, unsigned int digest_size, char* sigblock,
184505ab2901SDag-Erling Smørgrav unsigned int sigblock_len, uint8_t* key, unsigned int keylen)
184605ab2901SDag-Erling Smørgrav {
184705ab2901SDag-Erling Smørgrav uint16_t exp_len = 0;
184805ab2901SDag-Erling Smørgrav size_t exp_offset = 0, mod_offset = 0;
184905ab2901SDag-Erling Smørgrav struct rsa_public_key pubkey;
185005ab2901SDag-Erling Smørgrav mpz_t signature;
185105ab2901SDag-Erling Smørgrav int res = 0;
185205ab2901SDag-Erling Smørgrav
185305ab2901SDag-Erling Smørgrav /* RSA pubkey parsing as per RFC 3110 sec. 2 */
185405ab2901SDag-Erling Smørgrav if( keylen <= 1) {
185505ab2901SDag-Erling Smørgrav return "null RSA key";
185605ab2901SDag-Erling Smørgrav }
185705ab2901SDag-Erling Smørgrav if (key[0] != 0) {
185805ab2901SDag-Erling Smørgrav /* 1-byte length */
185905ab2901SDag-Erling Smørgrav exp_len = key[0];
186005ab2901SDag-Erling Smørgrav exp_offset = 1;
186105ab2901SDag-Erling Smørgrav } else {
186205ab2901SDag-Erling Smørgrav /* 1-byte NUL + 2-bytes exponent length */
186305ab2901SDag-Erling Smørgrav if (keylen < 3) {
186405ab2901SDag-Erling Smørgrav return "incorrect RSA key length";
186505ab2901SDag-Erling Smørgrav }
186605ab2901SDag-Erling Smørgrav exp_len = READ_UINT16(key+1);
186705ab2901SDag-Erling Smørgrav if (exp_len == 0)
186805ab2901SDag-Erling Smørgrav return "null RSA exponent length";
186905ab2901SDag-Erling Smørgrav exp_offset = 3;
187005ab2901SDag-Erling Smørgrav }
187105ab2901SDag-Erling Smørgrav /* Check that we are not over-running input length */
187205ab2901SDag-Erling Smørgrav if (keylen < exp_offset + exp_len + 1) {
187305ab2901SDag-Erling Smørgrav return "RSA key content shorter than expected";
187405ab2901SDag-Erling Smørgrav }
187505ab2901SDag-Erling Smørgrav mod_offset = exp_offset + exp_len;
187605ab2901SDag-Erling Smørgrav nettle_rsa_public_key_init(&pubkey);
187705ab2901SDag-Erling Smørgrav pubkey.size = keylen - mod_offset;
187805ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.e, exp_len, &key[exp_offset]);
187905ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(pubkey.n, pubkey.size, &key[mod_offset]);
188005ab2901SDag-Erling Smørgrav
188105ab2901SDag-Erling Smørgrav /* Digest content of "buf" and verify its RSA signature in "sigblock"*/
188205ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(signature, sigblock_len, (uint8_t*)sigblock);
188305ab2901SDag-Erling Smørgrav switch (digest_size) {
188405ab2901SDag-Erling Smørgrav case SHA1_DIGEST_SIZE:
188505ab2901SDag-Erling Smørgrav {
188605ab2901SDag-Erling Smørgrav uint8_t digest[SHA1_DIGEST_SIZE];
188705ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
188805ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
188905ab2901SDag-Erling Smørgrav res &= rsa_sha1_verify_digest(&pubkey, digest, signature);
189005ab2901SDag-Erling Smørgrav break;
189105ab2901SDag-Erling Smørgrav }
189205ab2901SDag-Erling Smørgrav case SHA256_DIGEST_SIZE:
189305ab2901SDag-Erling Smørgrav {
189405ab2901SDag-Erling Smørgrav uint8_t digest[SHA256_DIGEST_SIZE];
189505ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
189605ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
189705ab2901SDag-Erling Smørgrav res &= rsa_sha256_verify_digest(&pubkey, digest, signature);
189805ab2901SDag-Erling Smørgrav break;
189905ab2901SDag-Erling Smørgrav }
190005ab2901SDag-Erling Smørgrav case SHA512_DIGEST_SIZE:
190105ab2901SDag-Erling Smørgrav {
190205ab2901SDag-Erling Smørgrav uint8_t digest[SHA512_DIGEST_SIZE];
190305ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA512_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
190405ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
190505ab2901SDag-Erling Smørgrav res &= rsa_sha512_verify_digest(&pubkey, digest, signature);
190605ab2901SDag-Erling Smørgrav break;
190705ab2901SDag-Erling Smørgrav }
190805ab2901SDag-Erling Smørgrav default:
190905ab2901SDag-Erling Smørgrav break;
191005ab2901SDag-Erling Smørgrav }
191105ab2901SDag-Erling Smørgrav
191205ab2901SDag-Erling Smørgrav /* Clear and return */
191305ab2901SDag-Erling Smørgrav nettle_rsa_public_key_clear(&pubkey);
191405ab2901SDag-Erling Smørgrav mpz_clear(signature);
191505ab2901SDag-Erling Smørgrav if (!res) {
191605ab2901SDag-Erling Smørgrav return "RSA signature verification failed";
191705ab2901SDag-Erling Smørgrav } else {
191805ab2901SDag-Erling Smørgrav return NULL;
191905ab2901SDag-Erling Smørgrav }
192005ab2901SDag-Erling Smørgrav }
192105ab2901SDag-Erling Smørgrav
192205ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA
192305ab2901SDag-Erling Smørgrav static char *
_verify_nettle_ecdsa(sldns_buffer * buf,unsigned int digest_size,unsigned char * sigblock,unsigned int sigblock_len,unsigned char * key,unsigned int keylen)192405ab2901SDag-Erling Smørgrav _verify_nettle_ecdsa(sldns_buffer* buf, unsigned int digest_size, unsigned char* sigblock,
192505ab2901SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
192605ab2901SDag-Erling Smørgrav {
192705ab2901SDag-Erling Smørgrav int res = 0;
192805ab2901SDag-Erling Smørgrav struct ecc_point pubkey;
192905ab2901SDag-Erling Smørgrav struct dsa_signature signature;
193005ab2901SDag-Erling Smørgrav
193105ab2901SDag-Erling Smørgrav /* Always matched strength, as per RFC 6605 sec. 1 */
193205ab2901SDag-Erling Smørgrav if (sigblock_len != 2*digest_size || keylen != 2*digest_size) {
193305ab2901SDag-Erling Smørgrav return "wrong ECDSA signature length";
193405ab2901SDag-Erling Smørgrav }
193505ab2901SDag-Erling Smørgrav
193605ab2901SDag-Erling Smørgrav /* Parse ECDSA signature as per RFC 6605 sec. 4 */
193705ab2901SDag-Erling Smørgrav nettle_dsa_signature_init(&signature);
193805ab2901SDag-Erling Smørgrav switch (digest_size) {
193905ab2901SDag-Erling Smørgrav case SHA256_DIGEST_SIZE:
194005ab2901SDag-Erling Smørgrav {
194105ab2901SDag-Erling Smørgrav uint8_t digest[SHA256_DIGEST_SIZE];
194205ab2901SDag-Erling Smørgrav mpz_t x, y;
19430eefd307SCy Schubert nettle_ecc_point_init(&pubkey, nettle_get_secp_256r1());
194405ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(x, SHA256_DIGEST_SIZE, key);
194505ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(y, SHA256_DIGEST_SIZE, key+SHA256_DIGEST_SIZE);
194605ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.r, SHA256_DIGEST_SIZE, sigblock);
194705ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.s, SHA256_DIGEST_SIZE, sigblock+SHA256_DIGEST_SIZE);
194805ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
194905ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
195005ab2901SDag-Erling Smørgrav res &= nettle_ecc_point_set(&pubkey, x, y);
195105ab2901SDag-Erling Smørgrav res &= nettle_ecdsa_verify (&pubkey, SHA256_DIGEST_SIZE, digest, &signature);
195205ab2901SDag-Erling Smørgrav mpz_clear(x);
195305ab2901SDag-Erling Smørgrav mpz_clear(y);
195425039b37SCy Schubert nettle_ecc_point_clear(&pubkey);
195505ab2901SDag-Erling Smørgrav break;
195605ab2901SDag-Erling Smørgrav }
195705ab2901SDag-Erling Smørgrav case SHA384_DIGEST_SIZE:
195805ab2901SDag-Erling Smørgrav {
195905ab2901SDag-Erling Smørgrav uint8_t digest[SHA384_DIGEST_SIZE];
196005ab2901SDag-Erling Smørgrav mpz_t x, y;
19610eefd307SCy Schubert nettle_ecc_point_init(&pubkey, nettle_get_secp_384r1());
196205ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(x, SHA384_DIGEST_SIZE, key);
196305ab2901SDag-Erling Smørgrav nettle_mpz_init_set_str_256_u(y, SHA384_DIGEST_SIZE, key+SHA384_DIGEST_SIZE);
196405ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.r, SHA384_DIGEST_SIZE, sigblock);
196505ab2901SDag-Erling Smørgrav nettle_mpz_set_str_256_u(signature.s, SHA384_DIGEST_SIZE, sigblock+SHA384_DIGEST_SIZE);
196605ab2901SDag-Erling Smørgrav res = _digest_nettle(SHA384_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
196705ab2901SDag-Erling Smørgrav (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
196805ab2901SDag-Erling Smørgrav res &= nettle_ecc_point_set(&pubkey, x, y);
196905ab2901SDag-Erling Smørgrav res &= nettle_ecdsa_verify (&pubkey, SHA384_DIGEST_SIZE, digest, &signature);
197005ab2901SDag-Erling Smørgrav mpz_clear(x);
197105ab2901SDag-Erling Smørgrav mpz_clear(y);
197205ab2901SDag-Erling Smørgrav nettle_ecc_point_clear(&pubkey);
197305ab2901SDag-Erling Smørgrav break;
197405ab2901SDag-Erling Smørgrav }
197505ab2901SDag-Erling Smørgrav default:
197605ab2901SDag-Erling Smørgrav return "unknown ECDSA algorithm";
197705ab2901SDag-Erling Smørgrav }
197805ab2901SDag-Erling Smørgrav
197905ab2901SDag-Erling Smørgrav /* Clear and return */
198005ab2901SDag-Erling Smørgrav nettle_dsa_signature_clear(&signature);
198105ab2901SDag-Erling Smørgrav if (!res)
198205ab2901SDag-Erling Smørgrav return "ECDSA signature verification failed";
198305ab2901SDag-Erling Smørgrav else
198405ab2901SDag-Erling Smørgrav return NULL;
198505ab2901SDag-Erling Smørgrav }
198605ab2901SDag-Erling Smørgrav #endif
198705ab2901SDag-Erling Smørgrav
1988971980c3SDag-Erling Smørgrav #ifdef USE_ED25519
1989971980c3SDag-Erling Smørgrav static char *
_verify_nettle_ed25519(sldns_buffer * buf,unsigned char * sigblock,unsigned int sigblock_len,unsigned char * key,unsigned int keylen)1990971980c3SDag-Erling Smørgrav _verify_nettle_ed25519(sldns_buffer* buf, unsigned char* sigblock,
1991971980c3SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
1992971980c3SDag-Erling Smørgrav {
1993971980c3SDag-Erling Smørgrav int res = 0;
1994971980c3SDag-Erling Smørgrav
1995971980c3SDag-Erling Smørgrav if(sigblock_len != ED25519_SIGNATURE_SIZE) {
1996971980c3SDag-Erling Smørgrav return "wrong ED25519 signature length";
1997971980c3SDag-Erling Smørgrav }
1998971980c3SDag-Erling Smørgrav if(keylen != ED25519_KEY_SIZE) {
1999971980c3SDag-Erling Smørgrav return "wrong ED25519 key length";
2000971980c3SDag-Erling Smørgrav }
2001971980c3SDag-Erling Smørgrav
2002971980c3SDag-Erling Smørgrav res = ed25519_sha512_verify((uint8_t*)key, sldns_buffer_limit(buf),
2003971980c3SDag-Erling Smørgrav sldns_buffer_begin(buf), (uint8_t*)sigblock);
2004971980c3SDag-Erling Smørgrav
2005971980c3SDag-Erling Smørgrav if (!res)
2006971980c3SDag-Erling Smørgrav return "ED25519 signature verification failed";
2007971980c3SDag-Erling Smørgrav else
2008971980c3SDag-Erling Smørgrav return NULL;
2009971980c3SDag-Erling Smørgrav }
2010971980c3SDag-Erling Smørgrav #endif
2011971980c3SDag-Erling Smørgrav
201205ab2901SDag-Erling Smørgrav /**
201305ab2901SDag-Erling Smørgrav * Check a canonical sig+rrset and signature against a dnskey
201405ab2901SDag-Erling Smørgrav * @param buf: buffer with data to verify, the first rrsig part and the
201505ab2901SDag-Erling Smørgrav * canonicalized rrset.
201605ab2901SDag-Erling Smørgrav * @param algo: DNSKEY algorithm.
201705ab2901SDag-Erling Smørgrav * @param sigblock: signature rdata field from RRSIG
201805ab2901SDag-Erling Smørgrav * @param sigblock_len: length of sigblock data.
201905ab2901SDag-Erling Smørgrav * @param key: public key data from DNSKEY RR.
202005ab2901SDag-Erling Smørgrav * @param keylen: length of keydata.
202105ab2901SDag-Erling Smørgrav * @param reason: bogus reason in more detail.
202205ab2901SDag-Erling Smørgrav * @return secure if verification succeeded, bogus on crypto failure,
202305ab2901SDag-Erling Smørgrav * unchecked on format errors and alloc failures.
202405ab2901SDag-Erling Smørgrav */
202505ab2901SDag-Erling Smørgrav enum sec_status
verify_canonrrset(sldns_buffer * buf,int algo,unsigned char * sigblock,unsigned int sigblock_len,unsigned char * key,unsigned int keylen,char ** reason)202605ab2901SDag-Erling Smørgrav verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
202705ab2901SDag-Erling Smørgrav unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
202805ab2901SDag-Erling Smørgrav char** reason)
202905ab2901SDag-Erling Smørgrav {
203005ab2901SDag-Erling Smørgrav unsigned int digest_size = 0;
203105ab2901SDag-Erling Smørgrav
203205ab2901SDag-Erling Smørgrav if (sigblock_len == 0 || keylen == 0) {
203305ab2901SDag-Erling Smørgrav *reason = "null signature";
203405ab2901SDag-Erling Smørgrav return sec_status_bogus;
203505ab2901SDag-Erling Smørgrav }
203605ab2901SDag-Erling Smørgrav
2037091e9e46SCy Schubert #ifndef USE_DSA
2038091e9e46SCy Schubert if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1))
2039091e9e46SCy Schubert return sec_status_secure;
2040091e9e46SCy Schubert #endif
2041091e9e46SCy Schubert #ifndef USE_SHA1
2042091e9e46SCy Schubert if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3))
2043091e9e46SCy Schubert return sec_status_secure;
2044091e9e46SCy Schubert #endif
2045091e9e46SCy Schubert
204605ab2901SDag-Erling Smørgrav switch(algo) {
204765b390aaSDag-Erling Smørgrav #if defined(USE_DSA) && defined(USE_SHA1)
204805ab2901SDag-Erling Smørgrav case LDNS_DSA:
204905ab2901SDag-Erling Smørgrav case LDNS_DSA_NSEC3:
205005ab2901SDag-Erling Smørgrav *reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen);
205105ab2901SDag-Erling Smørgrav if (*reason != NULL)
205205ab2901SDag-Erling Smørgrav return sec_status_bogus;
205305ab2901SDag-Erling Smørgrav else
205405ab2901SDag-Erling Smørgrav return sec_status_secure;
2055e2d15004SDag-Erling Smørgrav #endif /* USE_DSA */
205605ab2901SDag-Erling Smørgrav
205765b390aaSDag-Erling Smørgrav #ifdef USE_SHA1
205805ab2901SDag-Erling Smørgrav case LDNS_RSASHA1:
205905ab2901SDag-Erling Smørgrav case LDNS_RSASHA1_NSEC3:
206005ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE);
206165b390aaSDag-Erling Smørgrav #endif
2062971980c3SDag-Erling Smørgrav /* double fallthrough annotation to please gcc parser */
2063*56850988SCy Schubert ATTR_FALLTHROUGH
2064971980c3SDag-Erling Smørgrav /* fallthrough */
206505ab2901SDag-Erling Smørgrav #ifdef USE_SHA2
2066971980c3SDag-Erling Smørgrav /* fallthrough */
206705ab2901SDag-Erling Smørgrav case LDNS_RSASHA256:
206805ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
2069*56850988SCy Schubert ATTR_FALLTHROUGH
2070971980c3SDag-Erling Smørgrav /* fallthrough */
207105ab2901SDag-Erling Smørgrav case LDNS_RSASHA512:
207205ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA512_DIGEST_SIZE);
207305ab2901SDag-Erling Smørgrav
207405ab2901SDag-Erling Smørgrav #endif
207505ab2901SDag-Erling Smørgrav *reason = _verify_nettle_rsa(buf, digest_size, (char*)sigblock,
207605ab2901SDag-Erling Smørgrav sigblock_len, key, keylen);
207705ab2901SDag-Erling Smørgrav if (*reason != NULL)
207805ab2901SDag-Erling Smørgrav return sec_status_bogus;
207905ab2901SDag-Erling Smørgrav else
208005ab2901SDag-Erling Smørgrav return sec_status_secure;
208105ab2901SDag-Erling Smørgrav
208205ab2901SDag-Erling Smørgrav #ifdef USE_ECDSA
208305ab2901SDag-Erling Smørgrav case LDNS_ECDSAP256SHA256:
208405ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
2085*56850988SCy Schubert ATTR_FALLTHROUGH
2086971980c3SDag-Erling Smørgrav /* fallthrough */
208705ab2901SDag-Erling Smørgrav case LDNS_ECDSAP384SHA384:
208805ab2901SDag-Erling Smørgrav digest_size = (digest_size ? digest_size : SHA384_DIGEST_SIZE);
208905ab2901SDag-Erling Smørgrav *reason = _verify_nettle_ecdsa(buf, digest_size, sigblock,
209005ab2901SDag-Erling Smørgrav sigblock_len, key, keylen);
209105ab2901SDag-Erling Smørgrav if (*reason != NULL)
209205ab2901SDag-Erling Smørgrav return sec_status_bogus;
209305ab2901SDag-Erling Smørgrav else
209405ab2901SDag-Erling Smørgrav return sec_status_secure;
209505ab2901SDag-Erling Smørgrav #endif
2096971980c3SDag-Erling Smørgrav #ifdef USE_ED25519
2097971980c3SDag-Erling Smørgrav case LDNS_ED25519:
2098971980c3SDag-Erling Smørgrav *reason = _verify_nettle_ed25519(buf, sigblock, sigblock_len,
2099971980c3SDag-Erling Smørgrav key, keylen);
2100971980c3SDag-Erling Smørgrav if (*reason != NULL)
2101971980c3SDag-Erling Smørgrav return sec_status_bogus;
2102971980c3SDag-Erling Smørgrav else
2103971980c3SDag-Erling Smørgrav return sec_status_secure;
2104971980c3SDag-Erling Smørgrav #endif
210505ab2901SDag-Erling Smørgrav case LDNS_RSAMD5:
210605ab2901SDag-Erling Smørgrav case LDNS_ECC_GOST:
210705ab2901SDag-Erling Smørgrav default:
210805ab2901SDag-Erling Smørgrav *reason = "unable to verify signature, unknown algorithm";
210905ab2901SDag-Erling Smørgrav return sec_status_bogus;
211005ab2901SDag-Erling Smørgrav }
211105ab2901SDag-Erling Smørgrav }
211205ab2901SDag-Erling Smørgrav
211305ab2901SDag-Erling Smørgrav #endif /* HAVE_SSL or HAVE_NSS or HAVE_NETTLE */
2114