aboutsummaryrefslogtreecommitdiff
path: root/contrib/unbound/sldns/keyraw.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/unbound/sldns/keyraw.c')
-rw-r--r--contrib/unbound/sldns/keyraw.c719
1 files changed, 719 insertions, 0 deletions
diff --git a/contrib/unbound/sldns/keyraw.c b/contrib/unbound/sldns/keyraw.c
new file mode 100644
index 000000000000..42a9262a30da
--- /dev/null
+++ b/contrib/unbound/sldns/keyraw.c
@@ -0,0 +1,719 @@
+/*
+ * keyraw.c - raw key operations and conversions
+ *
+ * (c) NLnet Labs, 2004-2008
+ *
+ * See the file LICENSE for the license
+ */
+/**
+ * \file
+ * Implementation of raw DNSKEY functions (work on wire rdata).
+ */
+
+#include "config.h"
+#include "sldns/keyraw.h"
+#include "sldns/rrdef.h"
+
+#ifdef HAVE_SSL
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/md5.h>
+#ifdef HAVE_OPENSSL_ENGINE_H
+# include <openssl/engine.h>
+#endif
+#ifdef HAVE_OPENSSL_BN_H
+#include <openssl/bn.h>
+#endif
+#ifdef HAVE_OPENSSL_PARAM_BUILD_H
+# include <openssl/param_build.h>
+#else
+# ifdef HAVE_OPENSSL_RSA_H
+# include <openssl/rsa.h>
+# endif
+# ifdef HAVE_OPENSSL_DSA_H
+# include <openssl/dsa.h>
+# endif
+#endif
+#endif /* HAVE_SSL */
+
+size_t
+sldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
+ const size_t len, int alg)
+{
+ /* for DSA keys */
+ uint8_t t;
+
+ /* for RSA keys */
+ uint16_t exp;
+ uint16_t int16;
+
+ switch ((sldns_algorithm)alg) {
+ case LDNS_DSA:
+ case LDNS_DSA_NSEC3:
+ if (len > 0) {
+ t = keydata[0];
+ return (64 + t*8)*8;
+ } else {
+ return 0;
+ }
+ break;
+ case LDNS_RSAMD5:
+ case LDNS_RSASHA1:
+ case LDNS_RSASHA1_NSEC3:
+#ifdef USE_SHA2
+ case LDNS_RSASHA256:
+ case LDNS_RSASHA512:
+#endif
+ if (len > 0) {
+ if (keydata[0] == 0) {
+ /* big exponent */
+ if (len > 3) {
+ memmove(&int16, keydata + 1, 2);
+ exp = ntohs(int16);
+ return (len - exp - 3)*8;
+ } else {
+ return 0;
+ }
+ } else {
+ exp = keydata[0];
+ return (len-exp-1)*8;
+ }
+ } else {
+ return 0;
+ }
+ break;
+#ifdef USE_GOST
+ case LDNS_ECC_GOST:
+ return 512;
+#endif
+#ifdef USE_ECDSA
+ case LDNS_ECDSAP256SHA256:
+ return 256;
+ case LDNS_ECDSAP384SHA384:
+ return 384;
+#endif
+#ifdef USE_ED25519
+ case LDNS_ED25519:
+ return 256;
+#endif
+#ifdef USE_ED448
+ case LDNS_ED448:
+ return 456;
+#endif
+ default:
+ return 0;
+ }
+}
+
+uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize)
+{
+ if(keysize < 4) {
+ return 0;
+ }
+ /* look at the algorithm field, copied from 2535bis */
+ if (key[3] == LDNS_RSAMD5) {
+ uint16_t ac16 = 0;
+ if (keysize > 4) {
+ memmove(&ac16, key + keysize - 3, 2);
+ }
+ ac16 = ntohs(ac16);
+ return (uint16_t) ac16;
+ } else {
+ size_t i;
+ uint32_t ac32 = 0;
+ for (i = 0; i < keysize; ++i) {
+ ac32 += ((i & 1)) ? key[i] : key[i] << 8;
+ }
+ ac32 += (ac32 >> 16) & 0xFFFF;
+ return (uint16_t) (ac32 & 0xFFFF);
+ }
+}
+
+#ifdef HAVE_SSL
+#ifdef USE_GOST
+/** store GOST engine reference loaded into OpenSSL library */
+ENGINE* sldns_gost_engine = NULL;
+
+int
+sldns_key_EVP_load_gost_id(void)
+{
+ static int gost_id = 0;
+ const EVP_PKEY_ASN1_METHOD* meth;
+ ENGINE* e;
+
+ if(gost_id) return gost_id;
+
+ /* see if configuration loaded gost implementation from other engine*/
+ meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
+ if(meth) {
+ EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
+ return gost_id;
+ }
+
+ /* see if engine can be loaded already */
+ e = ENGINE_by_id("gost");
+ if(!e) {
+ /* load it ourself, in case statically linked */
+ ENGINE_load_builtin_engines();
+ ENGINE_load_dynamic();
+ e = ENGINE_by_id("gost");
+ }
+ if(!e) {
+ /* no gost engine in openssl */
+ return 0;
+ }
+ if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
+ ENGINE_finish(e);
+ ENGINE_free(e);
+ return 0;
+ }
+
+ meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
+ if(!meth) {
+ /* algo not found */
+ ENGINE_finish(e);
+ ENGINE_free(e);
+ return 0;
+ }
+ /* Note: do not ENGINE_finish and ENGINE_free the acquired engine
+ * on some platforms this frees up the meth and unloads gost stuff */
+ sldns_gost_engine = e;
+
+ EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
+ return gost_id;
+}
+
+void sldns_key_EVP_unload_gost(void)
+{
+ if(sldns_gost_engine) {
+ ENGINE_finish(sldns_gost_engine);
+ ENGINE_free(sldns_gost_engine);
+ sldns_gost_engine = NULL;
+ }
+}
+#endif /* USE_GOST */
+
+#ifdef USE_DSA
+/* Retrieve params as BIGNUM from raw buffer */
+static int
+sldns_key_dsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** p,
+ BIGNUM** q, BIGNUM** g, BIGNUM** y)
+{
+ uint8_t T;
+ uint16_t length;
+ uint16_t offset;
+
+ if(len == 0)
+ return 0;
+ T = (uint8_t)key[0];
+ length = (64 + T * 8);
+ offset = 1;
+
+ if (T > 8) {
+ return 0;
+ }
+ if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
+ return 0;
+
+ *q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
+ offset += SHA_DIGEST_LENGTH;
+
+ *p = BN_bin2bn(key+offset, (int)length, NULL);
+ offset += length;
+
+ *g = BN_bin2bn(key+offset, (int)length, NULL);
+ offset += length;
+
+ *y = BN_bin2bn(key+offset, (int)length, NULL);
+
+ if(!*q || !*p || !*g || !*y) {
+ BN_free(*q);
+ BN_free(*p);
+ BN_free(*g);
+ BN_free(*y);
+ return 0;
+ }
+ return 1;
+}
+
+#ifndef HAVE_OSSL_PARAM_BLD_NEW
+DSA *
+sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
+{
+ DSA *dsa;
+ BIGNUM *Q=NULL, *P=NULL, *G=NULL, *Y=NULL;
+ if(!sldns_key_dsa_buf_bignum(key, len, &P, &Q, &G, &Y)) {
+ return NULL;
+ }
+ /* create the key and set its properties */
+ if(!(dsa = DSA_new())) {
+ return NULL;
+ }
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x02070000f)
+#ifndef S_SPLINT_S
+ dsa->p = P;
+ dsa->q = Q;
+ dsa->g = G;
+ dsa->pub_key = Y;
+#endif /* splint */
+
+#else /* OPENSSL_VERSION_NUMBER */
+ if (!DSA_set0_pqg(dsa, P, Q, G)) {
+ /* QPG not yet attached, need to free */
+ BN_free(Q);
+ BN_free(P);
+ BN_free(G);
+
+ DSA_free(dsa);
+ BN_free(Y);
+ return NULL;
+ }
+ if (!DSA_set0_key(dsa, Y, NULL)) {
+ /* QPG attached, cleaned up by DSA_free() */
+ DSA_free(dsa);
+ BN_free(Y);
+ return NULL;
+ }
+#endif
+
+ return dsa;
+}
+#endif /* HAVE_OSSL_PARAM_BLD_NEW */
+
+EVP_PKEY *sldns_key_dsa2pkey_raw(unsigned char* key, size_t len)
+{
+#ifdef HAVE_OSSL_PARAM_BLD_NEW
+ EVP_PKEY* evp_key = NULL;
+ EVP_PKEY_CTX* ctx;
+ BIGNUM *p=NULL, *q=NULL, *g=NULL, *y=NULL;
+ OSSL_PARAM_BLD* param_bld;
+ OSSL_PARAM* params = NULL;
+ if(!sldns_key_dsa_buf_bignum(key, len, &p, &q, &g, &y)) {
+ return NULL;
+ }
+
+ param_bld = OSSL_PARAM_BLD_new();
+ if(!param_bld) {
+ BN_free(p);
+ BN_free(q);
+ BN_free(g);
+ BN_free(y);
+ return NULL;
+ }
+ if(!OSSL_PARAM_BLD_push_BN(param_bld, "p", p) ||
+ !OSSL_PARAM_BLD_push_BN(param_bld, "g", g) ||
+ !OSSL_PARAM_BLD_push_BN(param_bld, "q", q) ||
+ !OSSL_PARAM_BLD_push_BN(param_bld, "pub", y)) {
+ OSSL_PARAM_BLD_free(param_bld);
+ BN_free(p);
+ BN_free(q);
+ BN_free(g);
+ BN_free(y);
+ return NULL;
+ }
+ params = OSSL_PARAM_BLD_to_param(param_bld);
+ OSSL_PARAM_BLD_free(param_bld);
+
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL);
+ if(!ctx) {
+ OSSL_PARAM_free(params);
+ BN_free(p);
+ BN_free(q);
+ BN_free(g);
+ BN_free(y);
+ return NULL;
+ }
+ if(EVP_PKEY_fromdata_init(ctx) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ BN_free(p);
+ BN_free(q);
+ BN_free(g);
+ BN_free(y);
+ return NULL;
+ }
+ if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ BN_free(p);
+ BN_free(q);
+ BN_free(g);
+ BN_free(y);
+ return NULL;
+ }
+
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ BN_free(p);
+ BN_free(q);
+ BN_free(g);
+ BN_free(y);
+ return evp_key;
+#else
+ DSA* dsa;
+ EVP_PKEY* evp_key = EVP_PKEY_new();
+ if(!evp_key) {
+ return NULL;
+ }
+ dsa = sldns_key_buf2dsa_raw(key, len);
+ if(!dsa) {
+ EVP_PKEY_free(evp_key);
+ return NULL;
+ }
+ if(EVP_PKEY_assign_DSA(evp_key, dsa) == 0) {
+ DSA_free(dsa);
+ EVP_PKEY_free(evp_key);
+ return NULL;
+ }
+ return evp_key;
+#endif
+}
+#endif /* USE_DSA */
+
+/* Retrieve params as BIGNUM from raw buffer, n is modulus, e is exponent */
+static int
+sldns_key_rsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** n,
+ BIGNUM** e)
+{
+ uint16_t offset;
+ uint16_t exp;
+ uint16_t int16;
+
+ if (len == 0)
+ return 0;
+ if (key[0] == 0) {
+ if(len < 3)
+ return 0;
+ memmove(&int16, key+1, 2);
+ exp = ntohs(int16);
+ offset = 3;
+ } else {
+ exp = key[0];
+ offset = 1;
+ }
+
+ /* key length at least one */
+ if(len < (size_t)offset + exp + 1)
+ return 0;
+
+ /* Exponent */
+ *e = BN_new();
+ if(!*e) return 0;
+ (void) BN_bin2bn(key+offset, (int)exp, *e);
+ offset += exp;
+
+ /* Modulus */
+ *n = BN_new();
+ if(!*n) {
+ BN_free(*e);
+ return 0;
+ }
+ /* length of the buffer must match the key length! */
+ (void) BN_bin2bn(key+offset, (int)(len - offset), *n);
+ return 1;
+}
+
+#ifndef HAVE_OSSL_PARAM_BLD_NEW
+RSA *
+sldns_key_buf2rsa_raw(unsigned char* key, size_t len)
+{
+ BIGNUM* modulus = NULL;
+ BIGNUM* exponent = NULL;
+ RSA *rsa;
+ if(!sldns_key_rsa_buf_bignum(key, len, &modulus, &exponent))
+ return NULL;
+ rsa = RSA_new();
+ if(!rsa) {
+ BN_free(exponent);
+ BN_free(modulus);
+ return NULL;
+ }
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || \
+ (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x02070000f)
+#ifndef S_SPLINT_S
+ rsa->n = modulus;
+ rsa->e = exponent;
+#endif /* splint */
+
+#else /* OPENSSL_VERSION_NUMBER */
+ if (!RSA_set0_key(rsa, modulus, exponent, NULL)) {
+ BN_free(exponent);
+ BN_free(modulus);
+ RSA_free(rsa);
+ return NULL;
+ }
+#endif
+
+ return rsa;
+}
+#endif /* HAVE_OSSL_PARAM_BLD_NEW */
+
+EVP_PKEY* sldns_key_rsa2pkey_raw(unsigned char* key, size_t len)
+{
+#ifdef HAVE_OSSL_PARAM_BLD_NEW
+ EVP_PKEY* evp_key = NULL;
+ EVP_PKEY_CTX* ctx;
+ BIGNUM *n=NULL, *e=NULL;
+ OSSL_PARAM_BLD* param_bld;
+ OSSL_PARAM* params = NULL;
+
+ if(!sldns_key_rsa_buf_bignum(key, len, &n, &e)) {
+ return NULL;
+ }
+
+ param_bld = OSSL_PARAM_BLD_new();
+ if(!param_bld) {
+ BN_free(n);
+ BN_free(e);
+ return NULL;
+ }
+ if(!OSSL_PARAM_BLD_push_BN(param_bld, "n", n)) {
+ OSSL_PARAM_BLD_free(param_bld);
+ BN_free(n);
+ BN_free(e);
+ return NULL;
+ }
+ if(!OSSL_PARAM_BLD_push_BN(param_bld, "e", e)) {
+ OSSL_PARAM_BLD_free(param_bld);
+ BN_free(n);
+ BN_free(e);
+ return NULL;
+ }
+ params = OSSL_PARAM_BLD_to_param(param_bld);
+ OSSL_PARAM_BLD_free(param_bld);
+
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
+ if(!ctx) {
+ OSSL_PARAM_free(params);
+ BN_free(n);
+ BN_free(e);
+ return NULL;
+ }
+ if(EVP_PKEY_fromdata_init(ctx) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ BN_free(n);
+ BN_free(e);
+ return NULL;
+ }
+ if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ BN_free(n);
+ BN_free(e);
+ return NULL;
+ }
+
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ BN_free(n);
+ BN_free(e);
+ return evp_key;
+#else
+ RSA* rsa;
+ EVP_PKEY *evp_key = EVP_PKEY_new();
+ if(!evp_key) {
+ return NULL;
+ }
+ rsa = sldns_key_buf2rsa_raw(key, len);
+ if(!rsa) {
+ EVP_PKEY_free(evp_key);
+ return NULL;
+ }
+ if(EVP_PKEY_assign_RSA(evp_key, rsa) == 0) {
+ RSA_free(rsa);
+ EVP_PKEY_free(evp_key);
+ return NULL;
+ }
+ return evp_key;
+#endif
+}
+
+#ifdef USE_GOST
+EVP_PKEY*
+sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
+{
+ /* prefix header for X509 encoding */
+ uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
+ 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
+ 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
+ 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
+ unsigned char encoded[37+64];
+ const unsigned char* pp;
+ if(keylen != 64) {
+ /* key wrong size */
+ return NULL;
+ }
+
+ /* create evp_key */
+ memmove(encoded, asn, 37);
+ memmove(encoded+37, key, 64);
+ pp = (unsigned char*)&encoded[0];
+
+ return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
+}
+#endif /* USE_GOST */
+
+#ifdef USE_ECDSA
+EVP_PKEY*
+sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
+{
+#ifdef HAVE_OSSL_PARAM_BLD_NEW
+ unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
+ EVP_PKEY *evp_key = NULL;
+ EVP_PKEY_CTX* ctx;
+ OSSL_PARAM_BLD* param_bld;
+ OSSL_PARAM* params = NULL;
+ char* group = NULL;
+
+ /* check length, which uncompressed must be 2 bignums */
+ if(algo == LDNS_ECDSAP256SHA256) {
+ if(keylen != 2*256/8) return NULL;
+ group = "prime256v1";
+ } else if(algo == LDNS_ECDSAP384SHA384) {
+ if(keylen != 2*384/8) return NULL;
+ group = "P-384";
+ } else {
+ return NULL;
+ }
+ if(keylen+1 > sizeof(buf)) { /* sanity check */
+ return NULL;
+ }
+ /* prepend the 0x04 for uncompressed format */
+ buf[0] = POINT_CONVERSION_UNCOMPRESSED;
+ memmove(buf+1, key, keylen);
+
+ param_bld = OSSL_PARAM_BLD_new();
+ if(!param_bld) {
+ return NULL;
+ }
+ if(!OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", group, 0) ||
+ !OSSL_PARAM_BLD_push_octet_string(param_bld, "pub", buf, keylen+1)) {
+ OSSL_PARAM_BLD_free(param_bld);
+ return NULL;
+ }
+ params = OSSL_PARAM_BLD_to_param(param_bld);
+ OSSL_PARAM_BLD_free(param_bld);
+
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
+ if(!ctx) {
+ OSSL_PARAM_free(params);
+ return NULL;
+ }
+ if(EVP_PKEY_fromdata_init(ctx) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ return NULL;
+ }
+ if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) {
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ return NULL;
+ }
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_free(params);
+ return evp_key;
+#else
+ unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
+ const unsigned char* pp = buf;
+ EVP_PKEY *evp_key;
+ EC_KEY *ec;
+ /* check length, which uncompressed must be 2 bignums */
+ if(algo == LDNS_ECDSAP256SHA256) {
+ if(keylen != 2*256/8) return NULL;
+ ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+ } else if(algo == LDNS_ECDSAP384SHA384) {
+ if(keylen != 2*384/8) return NULL;
+ ec = EC_KEY_new_by_curve_name(NID_secp384r1);
+ } else ec = NULL;
+ if(!ec) return NULL;
+ if(keylen+1 > sizeof(buf)) { /* sanity check */
+ EC_KEY_free(ec);
+ return NULL;
+ }
+ /* prepend the 0x02 (from docs) (or actually 0x04 from implementation
+ * of openssl) for uncompressed data */
+ buf[0] = POINT_CONVERSION_UNCOMPRESSED;
+ memmove(buf+1, key, keylen);
+ if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
+ EC_KEY_free(ec);
+ return NULL;
+ }
+ evp_key = EVP_PKEY_new();
+ if(!evp_key) {
+ EC_KEY_free(ec);
+ return NULL;
+ }
+ if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
+ EVP_PKEY_free(evp_key);
+ EC_KEY_free(ec);
+ return NULL;
+ }
+ return evp_key;
+#endif /* HAVE_OSSL_PARAM_BLD_NEW */
+}
+#endif /* USE_ECDSA */
+
+#ifdef USE_ED25519
+EVP_PKEY*
+sldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
+{
+ /* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
+ uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
+ 0x70, 0x03, 0x21, 0x00};
+ int pre_len = 12;
+ uint8_t buf[256];
+ EVP_PKEY *evp_key;
+ /* pp gets modified by d2i() */
+ const unsigned char* pp = (unsigned char*)buf;
+ if(keylen != 32 || keylen + pre_len > sizeof(buf))
+ return NULL; /* wrong length */
+ memmove(buf, pre, pre_len);
+ memmove(buf+pre_len, key, keylen);
+ evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
+ return evp_key;
+}
+#endif /* USE_ED25519 */
+
+#ifdef USE_ED448
+EVP_PKEY*
+sldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
+{
+ /* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
+ uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
+ 0x71, 0x03, 0x3a, 0x00};
+ int pre_len = 12;
+ uint8_t buf[256];
+ EVP_PKEY *evp_key;
+ /* pp gets modified by d2i() */
+ const unsigned char* pp = (unsigned char*)buf;
+ if(keylen != 57 || keylen + pre_len > sizeof(buf))
+ return NULL; /* wrong length */
+ memmove(buf, pre, pre_len);
+ memmove(buf+pre_len, key, keylen);
+ evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
+ return evp_key;
+}
+#endif /* USE_ED448 */
+
+int
+sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
+ const EVP_MD* md)
+{
+ EVP_MD_CTX* ctx;
+ ctx = EVP_MD_CTX_create();
+ if(!ctx)
+ return 0;
+ if(!EVP_DigestInit_ex(ctx, md, NULL) ||
+ !EVP_DigestUpdate(ctx, data, len) ||
+ !EVP_DigestFinal_ex(ctx, dest, NULL)) {
+ EVP_MD_CTX_destroy(ctx);
+ return 0;
+ }
+ EVP_MD_CTX_destroy(ctx);
+ return 1;
+}
+#endif /* HAVE_SSL */