dnssec.h, once openssl has support for signing with these algorithms.
The dns algorithm number is not yet allocated. These features are
not fully implemented yet.
* bugfix #726: 2 typos in drill manpage.
Thanks Hugo Lombard
* Add type CSYNC support, RFC 7477.
+ * Prepare for ED25519, ED448 support: todo convert* routines in
+ dnssec.h, once openssl has support for signing with these algorithms.
+ The dns algorithm number is not yet allocated. These features are
+ not fully implemented yet.
1.6.17 2014-01-10
* Fix ldns_dnssec_zone_new_frm_fp_l to allow the last parsed line of a
ACX_WITH_SSL_OPTIONAL
-AC_CHECK_FUNCS([EVP_sha256 ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new])
+AC_CHECK_FUNCS([EVP_sha256 ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id])
# for macosx, see if glibtool exists and use that
# BSD's need to know the version...
;;
esac
-AC_ARG_ENABLE(ed25519, AC_HELP_STRING([--enable-ed25519], [Enable ed25519 support (experimental)]))
+AC_ARG_ENABLE(ed25519, AC_HELP_STRING([--enable-ed25519], [Enable ED25519 support (experimental)]))
case "$enable_ed25519" in
yes)
if test "x$HAVE_SSL" != "xyes"; then
- AC_MSG_ERROR([DSA enabled, but no SSL support])
+ AC_MSG_ERROR([ED25519 enabled, but no SSL support])
fi
AC_CHECK_DECLS([NID_X25519], [], [AC_MSG_ERROR([OpenSSL does not support the EDDSA curve: please upgrade OpenSSL or rerun with --disable-ed25519])], [AC_INCLUDES_DEFAULT
#include <openssl/evp.h>
;;
esac
+AC_ARG_ENABLE(ed448, AC_HELP_STRING([--enable-ed448], [Enable ED448 support (experimental)]))
+case "$enable_ed448" in
+ yes)
+ if test "x$HAVE_SSL" != "xyes"; then
+ AC_MSG_ERROR([ED448 enabled, but no SSL support])
+ fi
+ AC_CHECK_DECLS([NID_X448], [], [AC_MSG_ERROR([OpenSSL does not support the EDDSA curve: please upgrade OpenSSL or rerun with --disable-ed448])], [AC_INCLUDES_DEFAULT
+#include <openssl/evp.h>
+ ])
+ AC_DEFINE_UNQUOTED([USE_ED448], [1], [Define this to enable ED448 support.])
+ ;;
+ *|no) dnl default
+ ;;
+esac
+
AC_ARG_ENABLE(dane, AC_HELP_STRING([--disable-dane], [Disable DANE support]))
case "$enable_dane" in
no)
r_high = ((d[0+r_rem]&0x80)?1:0);
s_high = ((d[bnsize+s_rem]&0x80)?1:0);
- raw_sig_len = pre_len + r_high + bnsize - r_rem + mid_len + s_high + bnsize - s_rem;
+ raw_sig_len = pre_len + r_high + bnsize - r_rem + mid_len +
+ s_high + bnsize - s_rem;
if(ldns_buffer_reserve(target_buffer, (size_t) raw_sig_len)) {
ldns_buffer_write_u8(target_buffer, pre[0]);
ldns_buffer_write_u8(target_buffer, raw_sig_len-2);
#endif /* S_SPLINT_S */
#endif /* USE_ECDSA */
+
+#if defined(USE_ED25519) || defined(USE_ED448)
+/* debug printout routine */
+static void print_hex(const char* str, uint8_t* d, int len)
+{
+ const char hex[] = "0123456789abcdef";
+ int i;
+ printf("%s [len=%d]: ", str, len);
+ for(i=0; i<len; i++) {
+ int x = (d[i]&0xf0)>>4;
+ int y = (d[i]&0x0f);
+ printf("%c%c", hex[x], hex[y]);
+ }
+ printf("\n");
+}
+#endif
+
+#ifdef USE_ED25519
+ldns_rdf *
+ldns_convert_ed25519_rrsig_asn12rdf(const ldns_buffer *sig, long sig_len)
+{
+ unsigned char *data = (unsigned char*)ldns_buffer_begin(sig);
+ ldns_rdf* rdf = NULL;
+
+ /* TODO when Openssl supports signing and you can test this */
+ print_hex("sig in ASN", data, sig_len);
+
+ return rdf;
+}
+
+ldns_status
+ldns_convert_ed25519_rrsig_rdf2asn1(ldns_buffer *target_buffer,
+ const ldns_rdf *sig_rdf)
+{
+ /* TODO when Openssl supports signing and you can test this. */
+ /* convert sig_buf into ASN1 into the target_buffer */
+ print_hex("sig raw", ldns_rdf_data(sig_rdf), ldns_rdf_size(sig_rdf));
+ return ldns_buffer_status(target_buffer);
+}
+#endif /* USE_ED25519 */
+
+#ifdef USE_ED448
+ldns_rdf *
+ldns_convert_ed448_rrsig_asn12rdf(const ldns_buffer *sig, long sig_len)
+{
+ unsigned char *data = (unsigned char*)ldns_buffer_begin(sig);
+ ldns_rdf* rdf = NULL;
+
+ /* TODO when Openssl supports signing and you can test this */
+ print_hex("sig in ASN", data, sig_len);
+
+ return rdf;
+}
+
+ldns_status
+ldns_convert_ed448_rrsig_rdf2asn1(ldns_buffer *target_buffer,
+ const ldns_rdf *sig_rdf)
+{
+ /* TODO when Openssl supports signing and you can test this. */
+ /* convert sig_buf into ASN1 into the target_buffer */
+ print_hex("sig raw", ldns_rdf_data(sig_rdf), ldns_rdf_size(sig_rdf));
+ return ldns_buffer_status(target_buffer);
+}
+#endif /* USE_ED448 */
+
#endif /* HAVE_SSL */
ldns_key_evp_key(current_key),
EVP_sha384());
break;
+#endif
+#ifdef USE_ED25519
+ case LDNS_SIGN_ED25519:
+ b64rdf = ldns_sign_public_evp(
+ sign_buf,
+ ldns_key_evp_key(current_key),
+ EVP_sha512());
+ break;
+#endif
+#ifdef USE_ED448
+ case LDNS_SIGN_ED448:
+ b64rdf = ldns_sign_public_evp(
+ sign_buf,
+ ldns_key_evp_key(current_key),
+ EVP_sha512());
+ break;
#endif
case LDNS_SIGN_RSAMD5:
b64rdf = ldns_sign_public_evp(
const EVP_MD *digest_type)
{
unsigned int siglen;
- ldns_rdf *sigdata_rdf;
+ ldns_rdf *sigdata_rdf = NULL;
ldns_buffer *b64sig;
EVP_MD_CTX *ctx;
const EVP_MD *md_type;
return NULL;
}
- /* unfortunately, OpenSSL output is differenct from DNS DSA format */
-#ifndef S_SPLINT_S
+ /* OpenSSL output is different, convert it */
+ r = 0;
#ifdef USE_DSA
+ /* unfortunately, OpenSSL output is different from DNS DSA format */
if (EVP_PKEY_type(key->type) == EVP_PKEY_DSA) {
+ r = 1;
sigdata_rdf = ldns_convert_dsa_rrsig_asn12rdf(b64sig, siglen);
}
#endif
-#if defined(USE_DSA) && defined(USE_ECDSA)
- else
-#endif
-#ifdef USE_ECDSA
- if(EVP_PKEY_base_id(key) == EVP_PKEY_EC &&
- ldns_pkey_is_ecdsa(key)) {
- sigdata_rdf = ldns_convert_ecdsa_rrsig_asn1len2rdf(
- b64sig, siglen, ldns_pkey_is_ecdsa(key));
+#if defined(USE_ECDSA) || defined(USE_ED25519) || defined(USE_ED448)
+ if(
+# ifdef HAVE_EVP_PKEY_BASE_ID
+ EVP_PKEY_base_id(key)
+# else
+ EVP_PKEY_type(key->type)
+# endif
+ == EVP_PKEY_EC) {
+# ifdef USE_ECDSA
+ if(ldns_pkey_is_ecdsa(key)) {
+ r = 1;
+ sigdata_rdf = ldns_convert_ecdsa_rrsig_asn1len2rdf(
+ b64sig, siglen, ldns_pkey_is_ecdsa(key));
+ }
+# endif /* USE_ECDSA */
+# ifdef USE_ED25519
+ if(EVP_PKEY_id(key) == NID_X25519) {
+ r = 1;
+ sigdata_rdf = ldns_convert_ed25519_rrsig_asn12rdf(
+ b64sig, siglen);
+ }
+# endif /* USE_ED25519 */
+# ifdef USE_ED448
+ if(EVP_PKEY_id(key) == NID_X448) {
+ r = 1;
+ sigdata_rdf = ldns_convert_ed448_rrsig_asn12rdf(
+ b64sig, siglen);
+ }
+# endif /* USE_ED448 */
}
-#endif
- else {
+#endif /* PKEY_EC */
+ if(r == 0) {
/* ok output for other types is the same */
sigdata_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, siglen,
ldns_buffer_begin(b64sig));
}
-#endif /* splint */
ldns_buffer_free(b64sig);
EVP_MD_CTX_destroy(ctx);
return sigdata_rdf;
}
#endif
+#ifdef USE_ED25519
+EVP_PKEY*
+ldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
+{
+ const unsigned char* pp = key; /* pp gets modified by o2i() */
+ EVP_PKEY *evp_key;
+ EC_KEY *ec;
+ if(keylen != 32)
+ return NULL; /* wrong length */
+ ec = EC_KEY_new_by_curve_name(NID_X25519);
+ if(!ec) return NULL;
+ if(!o2i_ECPublicKey(&ec, &pp, (int)keylen)) {
+ 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;
+}
+
+static ldns_status
+ldns_verify_rrsig_ed25519_raw(unsigned char* sig, size_t siglen,
+ ldns_buffer* rrset, unsigned char* key, size_t keylen)
+{
+ EVP_PKEY *evp_key;
+ ldns_status result;
+
+ evp_key = ldns_ed255192pkey_raw(key, keylen);
+ if(!evp_key) {
+ /* could not convert key */
+ return LDNS_STATUS_CRYPTO_BOGUS;
+ }
+ result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key,
+ EVP_sha512());
+ EVP_PKEY_free(evp_key);
+ return result;
+}
+#endif /* USE_ED25519 */
+
+#ifdef USE_ED448
+EVP_PKEY*
+ldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
+{
+ const unsigned char* pp = key; /* pp gets modified by o2i() */
+ EVP_PKEY *evp_key;
+ EC_KEY *ec;
+ if(keylen != 57)
+ return NULL; /* wrong length */
+ ec = EC_KEY_new_by_curve_name(NID_X448);
+ if(!ec) return NULL;
+ if(!o2i_ECPublicKey(&ec, &pp, (int)keylen)) {
+ 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;
+}
+
+static ldns_status
+ldns_verify_rrsig_ed448_raw(unsigned char* sig, size_t siglen,
+ ldns_buffer* rrset, unsigned char* key, size_t keylen)
+{
+ EVP_PKEY *evp_key;
+ ldns_status result;
+
+ evp_key = ldns_ed4482pkey_raw(key, keylen);
+ if(!evp_key) {
+ /* could not convert key */
+ return LDNS_STATUS_CRYPTO_BOGUS;
+ }
+ result = ldns_verify_rrsig_evp_raw(sig, siglen, rrset, evp_key,
+ EVP_sha512());
+ EVP_PKEY_free(evp_key);
+ return result;
+}
+#endif /* USE_ED448 */
+
#ifdef USE_ECDSA
EVP_PKEY*
ldns_ecdsa2pkey_raw(const unsigned char* key, size_t keylen, uint8_t algo)
return ldns_verify_rrsig_ecdsa_raw(sig, siglen, verify_buf,
key, keylen, algo);
break;
+#endif
+#ifdef USE_ED25519
+ case LDNS_ED25519:
+ return ldns_verify_rrsig_ed25519_raw(sig, siglen, verify_buf,
+ key, keylen);
+ break;
+#endif
+#ifdef USE_ED448
+ case LDNS_ED448:
+ return ldns_verify_rrsig_ed448_raw(sig, siglen, verify_buf,
+ key, keylen);
+ break;
#endif
case LDNS_RSAMD5:
return ldns_verify_rrsig_rsamd5_raw(sig,
return LDNS_STATUS_MEM_ERR;
}
break;
+#endif
+#ifdef USE_ED25519
+ case LDNS_ED25519:
+ /* EVP produces an ASN prefix on the signature, which is
+ * not used in the DNS */
+ if (ldns_rr_rdf(rrsig, 8) == NULL) {
+ return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
+ }
+ if (ldns_convert_ed25519_rrsig_rdf2asn1(
+ rawsig_buf, ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) {
+ return LDNS_STATUS_MEM_ERR;
+ }
+ break;
+#endif
+#ifdef USE_ED448
+ case LDNS_ED448:
+ /* EVP produces an ASN prefix on the signature, which is
+ * not used in the DNS */
+ if (ldns_rr_rdf(rrsig, 8) == NULL) {
+ return LDNS_STATUS_MISSING_RDATA_FIELDS_RRSIG;
+ }
+ if (ldns_convert_ed448_rrsig_rdf2asn1(
+ rawsig_buf, ldns_rr_rdf(rrsig, 8)) != LDNS_STATUS_OK) {
+ return LDNS_STATUS_MEM_ERR;
+ }
+ break;
#endif
case LDNS_DH:
case LDNS_ECC:
return LDNS_SHA256;
case LDNS_SIGN_ECDSAP384SHA384:
return LDNS_SHA384;
+#endif
+#ifdef USE_ED25519
+ case LDNS_SIGN_ED25519:
+ return LDNS_SHA256;
+#endif
+#ifdef USE_ED448
+ case LDNS_SIGN_ED448:
+ return LDNS_SHA256;
#endif
default: break;
}
ds = ldns_key_rr2ds(pubkey, LDNS_SHA384);
break;
case LDNS_SIGN_ECDSAP256SHA256:
+#endif
+#ifdef USE_ED25519
+ case LDNS_SIGN_ED25519:
+#endif
+#ifdef USE_ED448
+ case LDNS_SIGN_ED448:
#endif
case LDNS_SIGN_RSASHA256:
case LDNS_SIGN_RSASHA512:
#ifdef USE_ECDSA
{ LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
{ LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
+#endif
+#ifdef USE_ED25519
+ { LDNS_ED25519, "ED25519"},
+#endif
+#ifdef USE_ED448
+ { LDNS_ED448, "ED448"},
#endif
{ LDNS_INDIRECT, "INDIRECT" },
{ LDNS_PRIVATEDNS, "PRIVATEDNS" },
goto error;
#endif /* ECDSA */
break;
+#ifdef USE_ED25519
+ case LDNS_SIGN_ED25519:
+ ldns_buffer_printf(output, "Private-key-format: v1.2\n");
+ ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
+ status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
+ ldns_buffer_printf(output, ")\n");
+ ldns_buffer_printf(output, "PrivateKey: ");
+ if(k->_key.key) {
+ EC_KEY* ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
+ const BIGNUM* b = EC_KEY_get0_private_key(ec);
+ i = (uint16_t)BN_bn2bin(b, bignum);
+ if (i > LDNS_MAX_KEYLEN) {
+ goto error;
+ }
+ b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+ if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+ ldns_rdf_deep_free(b64_bignum);
+ goto error;
+ }
+ ldns_rdf_deep_free(b64_bignum);
+ /* down reference count in EC_KEY
+ * its still assigned to the PKEY */
+ EC_KEY_free(ec);
+ }
+ ldns_buffer_printf(output, "\n");
+ break;
+#endif /* USE_ED25519 */
+#ifdef USE_ED448
+ case LDNS_SIGN_ED448:
+ ldns_buffer_printf(output, "Private-key-format: v1.2\n");
+ ldns_buffer_printf(output, "Algorithm: %d (", ldns_key_algorithm(k));
+ status=ldns_algorithm2buffer_str(output, (ldns_algorithm)ldns_key_algorithm(k));
+ ldns_buffer_printf(output, ")\n");
+ ldns_buffer_printf(output, "PrivateKey: ");
+ if(k->_key.key) {
+ EC_KEY* ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
+ const BIGNUM* b = EC_KEY_get0_private_key(ec);
+ i = (uint16_t)BN_bn2bin(b, bignum);
+ if (i > LDNS_MAX_KEYLEN) {
+ goto error;
+ }
+ b64_bignum = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, i, bignum);
+ if (ldns_rdf2buffer_str(output, b64_bignum) != LDNS_STATUS_OK) {
+ ldns_rdf_deep_free(b64_bignum);
+ goto error;
+ }
+ ldns_rdf_deep_free(b64_bignum);
+ /* down reference count in EC_KEY
+ * its still assigned to the PKEY */
+ EC_KEY_free(ec);
+ }
+ ldns_buffer_printf(output, "\n");
+ break;
+#endif /* USE_ED448 */
case LDNS_SIGN_HMACMD5:
/* there's not much of a format defined for TSIG */
/* It's just a binary blob, Same for all algorithms */
{ LDNS_SIGN_ECDSAP256SHA256, "ECDSAP256SHA256" },
{ LDNS_SIGN_ECDSAP384SHA384, "ECDSAP384SHA384" },
#endif
+#ifdef USE_ED25519
+ { LDNS_SIGN_ED25519, "ED25519" },
+#endif
+#ifdef USE_ED448
+ { LDNS_SIGN_ED448, "ED448" },
+#endif
#ifdef USE_DSA
{ LDNS_SIGN_DSA, "DSA" },
{ LDNS_SIGN_DSA_NSEC3, "DSA-NSEC3-SHA1" },
BIGNUM* bn;
EVP_PKEY* evp_key;
EC_KEY* ec;
- if (ldns_fget_keyword_data_l(fp, "PrivateKey", ": ", token, "\n",
+ if (ldns_fget_keyword_data_l(fp, "PrivateKey", ": ", token, "\n",
sizeof(token), line_nr) == -1)
return NULL;
if(ldns_str2rdf_b64(&b64rdf, token) != LDNS_STATUS_OK)
return evp_key;
}
#endif
-
+
+#ifdef USE_ED25519
+/** turn private key buffer into EC_KEY structure */
+static EC_KEY*
+ldns_ed25519_priv_raw(uint8_t* pkey, int plen)
+{
+ const unsigned char* pp;
+ uint8_t buf[256];
+ int buflen = 0;
+ uint8_t pre[] = {0x30, 0x32, 0x02, 0x01, 0x01, 0x04, 0x20};
+ int pre_len = 7;
+ uint8_t post[] = {0xa0, 0x0b, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04,
+ 0x01, 0xda, 0x47, 0x0f, 0x01};
+ int post_len = 13;
+ int i;
+ /* ASN looks like this for ED25519
+ * 30320201010420 <32byteskey>
+ * andparameters a00b06092b06010401da470f01
+ * (noparameters, preamble is 30250201010420).
+ * the key is reversed (little endian).
+ */
+ buflen = pre_len + plen + post_len;
+ if((size_t)buflen > sizeof(buf))
+ return NULL;
+ memmove(buf, pre, pre_len);
+ /* reverse the pkey into the buf */
+ for(i=0; i<plen; i++)
+ buf[pre_len+i] = pkey[plen-1-i];
+ memmove(buf+pre_len+plen, post, post_len);
+ pp = buf;
+ return d2i_ECPrivateKey(NULL, &pp, buflen);
+}
+
+/** read ED25519 private key */
+static EVP_PKEY*
+ldns_key_new_frm_fp_ed25519_l(FILE* fp, int* line_nr)
+{
+ char token[16384];
+ ldns_rdf* b64rdf = NULL;
+ EVP_PKEY* evp_key;
+ EC_KEY* ec;
+ if (ldns_fget_keyword_data_l(fp, "PrivateKey", ": ", token, "\n",
+ sizeof(token), line_nr) == -1)
+ return NULL;
+ if(ldns_str2rdf_b64(&b64rdf, token) != LDNS_STATUS_OK)
+ return NULL;
+
+ /* we use d2i_ECPrivateKey because it calculates the public key
+ * from the private part, which others, EC_KEY_set_private_key,
+ * and o2i methods, do not do */
+ /* for that the private key has to be encoded in ASN1 notation
+ * with a X25519 prefix on it */
+
+ ec = ldns_ed25519_priv_raw(ldns_rdf_data(b64rdf),
+ (int)ldns_rdf_size(b64rdf));
+ ldns_rdf_deep_free(b64rdf);
+ if(!ec) return NULL;
+ if(EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)) != NID_X25519) {
+ /* wrong group, bad asn conversion */
+ 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
+
+#ifdef USE_ED448
+/** turn private key buffer into EC_KEY structure */
+static EC_KEY*
+ldns_ed448_priv_raw(uint8_t* pkey, int plen)
+{
+ const unsigned char* pp;
+ uint8_t buf[256];
+ int buflen = 0;
+ uint8_t pre[] = {0x30, 0x4b, 0x02, 0x01, 0x01, 0x04, 0x39};
+ int pre_len = 7;
+ uint8_t post[] = {0xa0, 0x0b, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04,
+ 0x01, 0xda, 0x47, 0x0f, 0x02};
+ int post_len = 13;
+ int i;
+ /* ASN looks like this for ED25519
+ * And for ED448, the parameters are ...02 instead of ...01
+ * For ED25519 it was:
+ * 30320201010420 <32byteskey>
+ * andparameters a00b06092b06010401da470f01
+ * (noparameters, preamble is 30250201010420).
+ * the key is reversed (little endian).
+ *
+ * For ED448 the key is 57 bytes, and that changes lengths.
+ * 304b0201010439 <57bytekey> a00b06092b06010401da470f02
+ */
+ buflen = pre_len + plen + post_len;
+ if((size_t)buflen > sizeof(buf))
+ return NULL;
+ memmove(buf, pre, pre_len);
+ /* reverse the pkey into the buf */
+ for(i=0; i<plen; i++)
+ buf[pre_len+i] = pkey[plen-1-i];
+ memmove(buf+pre_len+plen, post, post_len);
+ pp = buf;
+ return d2i_ECPrivateKey(NULL, &pp, buflen);
+}
+
+/** read ED448 private key */
+static EVP_PKEY*
+ldns_key_new_frm_fp_ed448_l(FILE* fp, int* line_nr)
+{
+ char token[16384];
+ ldns_rdf* b64rdf = NULL;
+ EVP_PKEY* evp_key;
+ EC_KEY* ec;
+ if (ldns_fget_keyword_data_l(fp, "PrivateKey", ": ", token, "\n",
+ sizeof(token), line_nr) == -1)
+ return NULL;
+ if(ldns_str2rdf_b64(&b64rdf, token) != LDNS_STATUS_OK)
+ return NULL;
+
+ /* convert private key into ASN notation and then convert that */
+ ec = ldns_ed448_priv_raw(ldns_rdf_data(b64rdf),
+ (int)ldns_rdf_size(b64rdf));
+ ldns_rdf_deep_free(b64rdf);
+ if(!ec) return NULL;
+ if(EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)) != NID_X448) {
+ /* wrong group, bad asn conversion */
+ 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
+
ldns_status
ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
{
fprintf(stderr, "Warning: ECDSA not compiled into this ");
fprintf(stderr, "version of ldns, use --enable-ecdsa\n");
# endif
+#endif
+ }
+ if (strncmp(d, "15 ED25519", 3) == 0) {
+#ifdef USE_ED25519
+ alg = LDNS_SIGN_ED25519;
+#else
+# ifdef STDERR_MSGS
+ fprintf(stderr, "Warning: ED25519 not compiled into this ");
+ fprintf(stderr, "version of ldns, use --enable-ed25519\n");
+# endif
+#endif
+ }
+ if (strncmp(d, "16 ED448", 3) == 0) {
+#ifdef USE_ED448
+ alg = LDNS_SIGN_ED448;
+#else
+# ifdef STDERR_MSGS
+ fprintf(stderr, "Warning: ED448 not compiled into this ");
+ fprintf(stderr, "version of ldns, use --enable-ed448\n");
+# endif
#endif
}
if (strncmp(d, "157 HMAC-MD5", 4) == 0) {
}
#endif /* splint */
break;
+#endif
+#ifdef USE_ED25519
+ case LDNS_SIGN_ED25519:
+ ldns_key_set_algorithm(k, alg);
+ ldns_key_set_evp_key(k,
+ ldns_key_new_frm_fp_ed25519_l(fp, line_nr));
+#ifndef S_SPLINT_S
+ if(!k->_key.key) {
+ ldns_key_free(k);
+ return LDNS_STATUS_ERR;
+ }
+#endif /* splint */
+ break;
+#endif
+#ifdef USE_ED448
+ case LDNS_SIGN_ED448:
+ ldns_key_set_algorithm(k, alg);
+ ldns_key_set_evp_key(k,
+ ldns_key_new_frm_fp_ed448_l(fp, line_nr));
+#ifndef S_SPLINT_S
+ if(!k->_key.key) {
+ ldns_key_free(k);
+ return LDNS_STATUS_ERR;
+ }
+#endif /* splint */
+ break;
#endif
default:
ldns_key_free(k);
return NULL;
#endif /* ECDSA */
break;
+#ifdef USE_ED25519
+ case LDNS_SIGN_ED25519:
+#ifdef HAVE_EVP_PKEY_KEYGEN
+ ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
+ if(!ctx) {
+ ldns_key_free(k);
+ return NULL;
+ }
+ if(EVP_PKEY_keygen_init(ctx) <= 0) {
+ ldns_key_free(k);
+ EVP_PKEY_CTX_free(ctx);
+ return NULL;
+ }
+ if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx,
+ NID_X25519) <= 0) {
+ ldns_key_free(k);
+ EVP_PKEY_CTX_free(ctx);
+ return NULL;
+ }
+ if (EVP_PKEY_keygen(ctx, &k->_key.key) <= 0) {
+ ldns_key_free(k);
+ EVP_PKEY_CTX_free(ctx);
+ return NULL;
+ }
+ EVP_PKEY_CTX_free(ctx);
+#endif
+ break;
+#endif /* ED25519 */
+#ifdef USE_ED448
+ case LDNS_SIGN_ED448:
+#ifdef HAVE_EVP_PKEY_KEYGEN
+ ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
+ if(!ctx) {
+ ldns_key_free(k);
+ return NULL;
+ }
+ if(EVP_PKEY_keygen_init(ctx) <= 0) {
+ ldns_key_free(k);
+ EVP_PKEY_CTX_free(ctx);
+ return NULL;
+ }
+ if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx,
+ NID_X448) <= 0) {
+ ldns_key_free(k);
+ EVP_PKEY_CTX_free(ctx);
+ return NULL;
+ }
+ if (EVP_PKEY_keygen(ctx, &k->_key.key) <= 0) {
+ ldns_key_free(k);
+ EVP_PKEY_CTX_free(ctx);
+ return NULL;
+ }
+ EVP_PKEY_CTX_free(ctx);
+#endif
+ break;
+#endif /* ED448 */
}
ldns_key_set_algorithm(k, alg);
return k;
return NULL;
#endif /* ECDSA */
break;
+#ifdef USE_ED25519
+ case LDNS_SIGN_ED25519:
+ ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(
+ LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k)));
+ bin = NULL;
+ ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
+ EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
+ size = (uint16_t)i2o_ECPublicKey(ec, NULL);
+ if(!i2o_ECPublicKey(ec, &bin)) {
+ EC_KEY_free(ec);
+ ldns_rr_free(pubkey);
+ return NULL;
+ }
+ /* down the reference count for ec, its still assigned
+ * to the pkey */
+ EC_KEY_free(ec);
+ internal_data = 1;
+ break;
+#endif
+#ifdef USE_ED448
+ case LDNS_SIGN_ED448:
+ ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(
+ LDNS_RDF_TYPE_ALG, ldns_key_algorithm(k)));
+ bin = NULL;
+ ec = EVP_PKEY_get1_EC_KEY(k->_key.key);
+ EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
+ size = (uint16_t)i2o_ECPublicKey(ec, NULL);
+ if(!i2o_ECPublicKey(ec, &bin)) {
+ EC_KEY_free(ec);
+ ldns_rr_free(pubkey);
+ return NULL;
+ }
+ /* down the reference count for ec, its still assigned
+ * to the pkey */
+ EC_KEY_free(ec);
+ internal_data = 1;
+ break;
+#endif
case LDNS_SIGN_HMACMD5:
case LDNS_SIGN_HMACSHA1:
case LDNS_SIGN_HMACSHA256:
*/
EVP_PKEY* ldns_ecdsa2pkey_raw(const unsigned char* key, size_t keylen, uint8_t algo);
+/**
+ * Converts a holding buffer with key material to EVP PKEY in openssl.
+ * Only available if ldns was compiled with ED25519.
+ * \param[in] key data to convert
+ * \param[in] keylen length of the key data
+ * \return the key or NULL on error.
+ */
+EVP_PKEY* ldns_ed255192pkey_raw(const unsigned char* key, size_t keylen);
+
+/**
+ * Converts a holding buffer with key material to EVP PKEY in openssl.
+ * Only available if ldns was compiled with ED448.
+ * \param[in] key data to convert
+ * \param[in] keylen length of the key data
+ * \return the key or NULL on error.
+ */
+EVP_PKEY* ldns_ed4482pkey_raw(const unsigned char* key, size_t keylen);
+
#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
#if LDNS_BUILD_CONFIG_HAVE_SSL
ldns_convert_ecdsa_rrsig_rdf2asn1(ldns_buffer *target_buffer,
const ldns_rdf *sig_rdf);
+/**
+ * Converts the ECDSA signature from ASN1 representation (as
+ * used by OpenSSL) to raw signature data as used in DNS
+ * This routine is only present if ldns is compiled with ED25519 support.
+ *
+ * \param[in] sig The signature in ASN1 format
+ * \param[in] sig_len The length of the signature
+ * \return a new rdf with the signature
+ */
+ldns_rdf *
+ldns_convert_ed25519_rrsig_asn12rdf(const ldns_buffer *sig, long sig_len);
+
+/**
+ * Converts the RRSIG signature RDF (from DNS) to a buffer with the
+ * signature in ASN1 format as openssl uses it.
+ * This routine is only present if ldns is compiled with ED25519 support.
+ *
+ * \param[out] target_buffer buffer to place the signature data in ASN1.
+ * \param[in] sig_rdf The signature rdf to convert
+ * \return LDNS_STATUS_OK on success, error code otherwise
+ */
+ldns_status
+ldns_convert_ed25519_rrsig_rdf2asn1(ldns_buffer *target_buffer,
+ const ldns_rdf *sig_rdf);
+
+/**
+ * Converts the ECDSA signature from ASN1 representation (as
+ * used by OpenSSL) to raw signature data as used in DNS
+ * This routine is only present if ldns is compiled with ED448 support.
+ *
+ * \param[in] sig The signature in ASN1 format
+ * \param[in] sig_len The length of the signature
+ * \return a new rdf with the signature
+ */
+ldns_rdf *
+ldns_convert_ed448_rrsig_asn12rdf(const ldns_buffer *sig, long sig_len);
+
+/**
+ * Converts the RRSIG signature RDF (from DNS) to a buffer with the
+ * signature in ASN1 format as openssl uses it.
+ * This routine is only present if ldns is compiled with ED448 support.
+ *
+ * \param[out] target_buffer buffer to place the signature data in ASN1.
+ * \param[in] sig_rdf The signature rdf to convert
+ * \return LDNS_STATUS_OK on success, error code otherwise
+ */
+ldns_status
+ldns_convert_ed448_rrsig_rdf2asn1(ldns_buffer *target_buffer,
+ const ldns_rdf *sig_rdf);
+
#endif /* LDNS_BUILD_CONFIG_HAVE_SSL */
#ifdef __cplusplus
LDNS_ECC_GOST = 12, /* RFC 5933 */
LDNS_ECDSAP256SHA256 = 13, /* RFC 6605 */
LDNS_ECDSAP384SHA384 = 14, /* RFC 6605 */
+#ifdef USE_ED25519
+ /* this ifdef is internal to ldns, because we do not want to export
+ * the symbol. Users can define it if they want access,
+ * the feature is not fully implemented at this time and openssl
+ * does not support it fully either (also for ED448). */
+ LDNS_ED25519 = 15, /* draft-ietf-curdle-dnskey-ed25519 */
+#endif
+#ifdef USE_ED448
+ LDNS_ED448 = 16, /* draft-ietf-curdle-dnskey-ed448 */
+#endif
LDNS_INDIRECT = 252,
LDNS_PRIVATEDNS = 253,
LDNS_PRIVATEOID = 254
LDNS_SIGN_ECC_GOST = LDNS_ECC_GOST,
LDNS_SIGN_ECDSAP256SHA256 = LDNS_ECDSAP256SHA256,
LDNS_SIGN_ECDSAP384SHA384 = LDNS_ECDSAP384SHA384,
+#ifdef USE_ED25519
+ LDNS_SIGN_ED25519 = LDNS_ED25519,
+#endif
+#ifdef USE_ED448
+ LDNS_SIGN_ED448 = LDNS_ED448,
+#endif
LDNS_SIGN_HMACMD5 = 157, /* not official! This type is for TSIG, not DNSSEC */
LDNS_SIGN_HMACSHA1 = 158, /* not official! This type is for TSIG, not DNSSEC */
LDNS_SIGN_HMACSHA256 = 159 /* ditto */
return 256;
case LDNS_SIGN_ECDSAP384SHA384:
return 384;
+#endif
+#ifdef USE_ED25519
+ case LDNS_SIGN_ED25519:
+ return 256;
+#endif
+#ifdef USE_ED448
+ case LDNS_SIGN_ED448:
+ return 456;
#endif
case LDNS_SIGN_HMACMD5:
return len;