aboutsummaryrefslogtreecommitdiffstats
path: root/keys.c
diff options
context:
space:
mode:
Diffstat (limited to 'keys.c')
-rw-r--r--keys.c647
1 files changed, 575 insertions, 72 deletions
diff --git a/keys.c b/keys.c
index 46f6a3d0cb68..31208cb3a43f 100644
--- a/keys.c
+++ b/keys.c
@@ -35,11 +35,22 @@ ldns_lookup_table ldns_signing_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" },
+#endif
{ LDNS_SIGN_HMACMD5, "hmac-md5.sig-alg.reg.int" },
{ LDNS_SIGN_HMACSHA1, "hmac-sha1" },
{ LDNS_SIGN_HMACSHA256, "hmac-sha256" },
+ { LDNS_SIGN_HMACSHA224, "hmac-sha224" },
+ { LDNS_SIGN_HMACSHA384, "hmac-sha384" },
+ { LDNS_SIGN_HMACSHA512, "hmac-sha512" },
{ 0, NULL }
};
@@ -244,7 +255,7 @@ ldns_key_new_frm_fp_ecdsa_l(FILE* fp, ldns_algorithm alg, int* line_nr)
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)
@@ -286,7 +297,159 @@ ldns_key_new_frm_fp_ecdsa_l(FILE* fp, ldns_algorithm alg, int* line_nr)
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)
{
@@ -296,7 +459,9 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
ldns_rr *key_rr;
#ifdef HAVE_SSL
RSA *rsa;
+#ifdef USE_DSA
DSA *dsa;
+#endif
unsigned char *hmac;
size_t hmac_size;
#endif /* HAVE_SSL */
@@ -349,7 +514,14 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
alg = (ldns_signing_algorithm)LDNS_DH;
}
if (strncmp(d, "3 DSA", 2) == 0) {
+#ifdef USE_DSA
alg = LDNS_SIGN_DSA;
+#else
+# ifdef STDERR_MSGS
+ fprintf(stderr, "Warning: DSA not compiled into this ");
+ fprintf(stderr, "version of ldns\n");
+# endif
+#endif
}
if (strncmp(d, "4 ECC", 2) == 0) {
alg = (ldns_signing_algorithm)LDNS_ECC;
@@ -358,7 +530,14 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
alg = LDNS_SIGN_RSASHA1;
}
if (strncmp(d, "6 DSA", 2) == 0) {
+#ifdef USE_DSA
alg = LDNS_SIGN_DSA_NSEC3;
+#else
+# ifdef STDERR_MSGS
+ fprintf(stderr, "Warning: DSA not compiled into this ");
+ fprintf(stderr, "version of ldns\n");
+# endif
+#endif
}
if (strncmp(d, "7 RSASHA1", 2) == 0) {
alg = LDNS_SIGN_RSASHA1_NSEC3;
@@ -414,6 +593,26 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
# 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) {
alg = LDNS_SIGN_HMACMD5;
}
@@ -423,7 +622,23 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
if (strncmp(d, "159 HMAC-SHA256", 4) == 0) {
alg = LDNS_SIGN_HMACSHA256;
}
-
+ /* For compatibility with dnssec-keygen */
+ if (strncmp(d, "161 ", 4) == 0) {
+ alg = LDNS_SIGN_HMACSHA1;
+ }
+ if (strncmp(d, "162 HMAC-SHA224", 4) == 0) {
+ alg = LDNS_SIGN_HMACSHA224;
+ }
+ /* For compatibility with dnssec-keygen */
+ if (strncmp(d, "163 ", 4) == 0) {
+ alg = LDNS_SIGN_HMACSHA256;
+ }
+ if (strncmp(d, "164 HMAC-SHA384", 4) == 0) {
+ alg = LDNS_SIGN_HMACSHA384;
+ }
+ if (strncmp(d, "165 HMAC-SHA512", 4) == 0) {
+ alg = LDNS_SIGN_HMACSHA512;
+ }
LDNS_FREE(d);
switch(alg) {
@@ -444,6 +659,7 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
ldns_key_assign_rsa_key(k, rsa);
#endif /* HAVE_SSL */
break;
+#ifdef USE_DSA
case LDNS_SIGN_DSA:
case LDNS_SIGN_DSA_NSEC3:
ldns_key_set_algorithm(k, alg);
@@ -456,9 +672,13 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
ldns_key_assign_dsa_key(k, dsa);
#endif /* HAVE_SSL */
break;
+#endif /* USE_DSA */
case LDNS_SIGN_HMACMD5:
case LDNS_SIGN_HMACSHA1:
+ case LDNS_SIGN_HMACSHA224:
case LDNS_SIGN_HMACSHA256:
+ case LDNS_SIGN_HMACSHA384:
+ case LDNS_SIGN_HMACSHA512:
ldns_key_set_algorithm(k, alg);
#ifdef HAVE_SSL
hmac = ldns_key_new_frm_fp_hmac_l(fp, line_nr, &hmac_size);
@@ -501,6 +721,32 @@ ldns_key_new_frm_fp_l(ldns_key **key, FILE *fp, int *line_nr)
#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 LDNS_STATUS_SYNTAX_ALG_ERR;
@@ -552,15 +798,17 @@ ldns_key_new_frm_fp_rsa_l(FILE *f, int *line_nr)
* // ...
*
*/
- char *d;
+ char *b;
RSA *rsa;
uint8_t *buf;
int i;
+ BIGNUM *n=NULL, *e=NULL, *d=NULL, *p=NULL, *q=NULL,
+ *dmp1=NULL, *dmq1=NULL, *iqmp=NULL;
- d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
+ b = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN);
rsa = RSA_new();
- if (!d || !rsa || !buf) {
+ if (!b || !rsa || !buf) {
goto error;
}
@@ -569,95 +817,128 @@ ldns_key_new_frm_fp_rsa_l(FILE *f, int *line_nr)
*/
/* Modules, rsa->n */
- if (ldns_fget_keyword_data_l(f, "Modulus", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+ if (ldns_fget_keyword_data_l(f, "Modulus", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
goto error;
}
- i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
+ i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b)));
#ifndef S_SPLINT_S
- rsa->n = BN_bin2bn((const char unsigned*)buf, i, NULL);
- if (!rsa->n) {
+ n = BN_bin2bn((const char unsigned*)buf, i, NULL);
+ if (!n) {
goto error;
}
/* PublicExponent, rsa->e */
- if (ldns_fget_keyword_data_l(f, "PublicExponent", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+ if (ldns_fget_keyword_data_l(f, "PublicExponent", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
goto error;
}
- i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
- rsa->e = BN_bin2bn((const char unsigned*)buf, i, NULL);
- if (!rsa->e) {
+ i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b)));
+ e = BN_bin2bn((const char unsigned*)buf, i, NULL);
+ if (!e) {
goto error;
}
/* PrivateExponent, rsa->d */
- if (ldns_fget_keyword_data_l(f, "PrivateExponent", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+ if (ldns_fget_keyword_data_l(f, "PrivateExponent", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
goto error;
}
- i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
- rsa->d = BN_bin2bn((const char unsigned*)buf, i, NULL);
- if (!rsa->d) {
+ i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b)));
+ d = BN_bin2bn((const char unsigned*)buf, i, NULL);
+ if (!d) {
goto error;
}
/* Prime1, rsa->p */
- if (ldns_fget_keyword_data_l(f, "Prime1", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+ if (ldns_fget_keyword_data_l(f, "Prime1", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
goto error;
}
- i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
- rsa->p = BN_bin2bn((const char unsigned*)buf, i, NULL);
- if (!rsa->p) {
+ i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b)));
+ p = BN_bin2bn((const char unsigned*)buf, i, NULL);
+ if (!p) {
goto error;
}
/* Prime2, rsa->q */
- if (ldns_fget_keyword_data_l(f, "Prime2", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+ if (ldns_fget_keyword_data_l(f, "Prime2", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
goto error;
}
- i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
- rsa->q = BN_bin2bn((const char unsigned*)buf, i, NULL);
- if (!rsa->q) {
+ i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b)));
+ q = BN_bin2bn((const char unsigned*)buf, i, NULL);
+ if (!q) {
goto error;
}
/* Exponent1, rsa->dmp1 */
- if (ldns_fget_keyword_data_l(f, "Exponent1", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+ if (ldns_fget_keyword_data_l(f, "Exponent1", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
goto error;
}
- i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
- rsa->dmp1 = BN_bin2bn((const char unsigned*)buf, i, NULL);
- if (!rsa->dmp1) {
+ i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b)));
+ dmp1 = BN_bin2bn((const char unsigned*)buf, i, NULL);
+ if (!dmp1) {
goto error;
}
/* Exponent2, rsa->dmq1 */
- if (ldns_fget_keyword_data_l(f, "Exponent2", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+ if (ldns_fget_keyword_data_l(f, "Exponent2", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
goto error;
}
- i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
- rsa->dmq1 = BN_bin2bn((const char unsigned*)buf, i, NULL);
- if (!rsa->dmq1) {
+ i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b)));
+ dmq1 = BN_bin2bn((const char unsigned*)buf, i, NULL);
+ if (!dmq1) {
goto error;
}
/* Coefficient, rsa->iqmp */
- if (ldns_fget_keyword_data_l(f, "Coefficient", ": ", d, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
+ if (ldns_fget_keyword_data_l(f, "Coefficient", ": ", b, "\n", LDNS_MAX_LINELEN, line_nr) == -1) {
goto error;
}
- i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
- rsa->iqmp = BN_bin2bn((const char unsigned*)buf, i, NULL);
- if (!rsa->iqmp) {
+ i = ldns_b64_pton((const char*)b, buf, ldns_b64_ntop_calculate_size(strlen(b)));
+ iqmp = BN_bin2bn((const char unsigned*)buf, i, NULL);
+ if (!iqmp) {
goto error;
}
#endif /* splint */
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
+# ifndef S_SPLINT_S
+ rsa->n = n;
+ rsa->e = e;
+ rsa->d = d;
+ rsa->p = p;
+ rsa->q = q;
+ rsa->dmp1 = dmp1;
+ rsa->dmq1 = dmq1;
+ rsa->iqmp = iqmp;
+# endif
+#else
+ if(!RSA_set0_key(rsa, n, e, d))
+ goto error;
+ n = NULL;
+ e = NULL;
+ d = NULL;
+ if(!RSA_set0_factors(rsa, p, q))
+ goto error;
+ p = NULL;
+ q = NULL;
+ if(!RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp))
+ goto error;
+#endif
+
LDNS_FREE(buf);
- LDNS_FREE(d);
+ LDNS_FREE(b);
return rsa;
error:
RSA_free(rsa);
- LDNS_FREE(d);
+ LDNS_FREE(b);
LDNS_FREE(buf);
+ BN_free(n);
+ BN_free(e);
+ BN_free(d);
+ BN_free(p);
+ BN_free(q);
+ BN_free(dmp1);
+ BN_free(dmq1);
+ BN_free(iqmp);
return NULL;
}
@@ -674,6 +955,7 @@ ldns_key_new_frm_fp_dsa_l(FILE *f, ATTR_UNUSED(int *line_nr))
char *d;
DSA *dsa;
uint8_t *buf;
+ BIGNUM *p=NULL, *q=NULL, *g=NULL, *priv_key=NULL, *pub_key=NULL;
d = LDNS_XMALLOC(char, LDNS_MAX_LINELEN);
buf = LDNS_XMALLOC(uint8_t, LDNS_MAX_LINELEN);
@@ -690,8 +972,8 @@ ldns_key_new_frm_fp_dsa_l(FILE *f, ATTR_UNUSED(int *line_nr))
}
i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
#ifndef S_SPLINT_S
- dsa->p = BN_bin2bn((const char unsigned*)buf, i, NULL);
- if (!dsa->p) {
+ p = BN_bin2bn((const char unsigned*)buf, i, NULL);
+ if (!p) {
goto error;
}
@@ -700,8 +982,8 @@ ldns_key_new_frm_fp_dsa_l(FILE *f, ATTR_UNUSED(int *line_nr))
goto error;
}
i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
- dsa->q = BN_bin2bn((const char unsigned*)buf, i, NULL);
- if (!dsa->q) {
+ q = BN_bin2bn((const char unsigned*)buf, i, NULL);
+ if (!q) {
goto error;
}
@@ -710,8 +992,8 @@ ldns_key_new_frm_fp_dsa_l(FILE *f, ATTR_UNUSED(int *line_nr))
goto error;
}
i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
- dsa->g = BN_bin2bn((const char unsigned*)buf, i, NULL);
- if (!dsa->g) {
+ g = BN_bin2bn((const char unsigned*)buf, i, NULL);
+ if (!g) {
goto error;
}
@@ -720,8 +1002,8 @@ ldns_key_new_frm_fp_dsa_l(FILE *f, ATTR_UNUSED(int *line_nr))
goto error;
}
i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
- dsa->priv_key = BN_bin2bn((const char unsigned*)buf, i, NULL);
- if (!dsa->priv_key) {
+ priv_key = BN_bin2bn((const char unsigned*)buf, i, NULL);
+ if (!priv_key) {
goto error;
}
@@ -730,12 +1012,30 @@ ldns_key_new_frm_fp_dsa_l(FILE *f, ATTR_UNUSED(int *line_nr))
goto error;
}
i = ldns_b64_pton((const char*)d, buf, ldns_b64_ntop_calculate_size(strlen(d)));
- dsa->pub_key = BN_bin2bn((const char unsigned*)buf, i, NULL);
- if (!dsa->pub_key) {
+ pub_key = BN_bin2bn((const char unsigned*)buf, i, NULL);
+ if (!pub_key) {
goto error;
}
#endif /* splint */
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
+# ifndef S_SPLINT_S
+ dsa->p = p;
+ dsa->q = q;
+ dsa->g = g;
+ dsa->priv_key = priv_key;
+ dsa->pub_key = pub_key;
+# endif
+#else
+ if(!DSA_set0_pqg(dsa, p, q, g))
+ goto error;
+ p = NULL;
+ q = NULL;
+ g = NULL;
+ if(!DSA_set0_key(dsa, pub_key, priv_key))
+ goto error;
+#endif
+
LDNS_FREE(buf);
LDNS_FREE(d);
@@ -745,6 +1045,11 @@ error:
LDNS_FREE(d);
LDNS_FREE(buf);
DSA_free(dsa);
+ BN_free(p);
+ BN_free(q);
+ BN_free(g);
+ BN_free(priv_key);
+ BN_free(pub_key);
return NULL;
}
@@ -820,11 +1125,17 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
{
ldns_key *k;
#ifdef HAVE_SSL
+#ifdef USE_DSA
DSA *d;
- RSA *r;
+#endif /* USE_DSA */
# ifdef USE_ECDSA
EC_KEY *ec = NULL;
# endif
+# ifdef HAVE_EVP_PKEY_KEYGEN
+ EVP_PKEY_CTX *ctx;
+# else
+ RSA *r;
+# endif
#else
int i;
uint16_t offset = 0;
@@ -842,6 +1153,31 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
case LDNS_SIGN_RSASHA256:
case LDNS_SIGN_RSASHA512:
#ifdef HAVE_SSL
+#ifdef HAVE_EVP_PKEY_KEYGEN
+ ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, 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_rsa_keygen_bits(ctx, size) <= 0) {
+ ldns_key_free(k);
+ EVP_PKEY_CTX_free(ctx);
+ return NULL;
+ }
+#ifndef S_SPLINT_S
+ if (EVP_PKEY_keygen(ctx, &k->_key.key) <= 0) {
+ ldns_key_free(k);
+ EVP_PKEY_CTX_free(ctx);
+ return NULL;
+ }
+#endif
+ EVP_PKEY_CTX_free(ctx);
+#else /* HAVE_EVP_PKEY_KEYGEN */
r = RSA_generate_key((int)size, RSA_F4, NULL, NULL);
if(!r) {
ldns_key_free(k);
@@ -853,16 +1189,31 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
}
ldns_key_set_rsa_key(k, r);
RSA_free(r);
+#endif /* HAVE_EVP_PKEY_KEYGEN */
#endif /* HAVE_SSL */
break;
case LDNS_SIGN_DSA:
case LDNS_SIGN_DSA_NSEC3:
+#ifdef USE_DSA
#ifdef HAVE_SSL
+# if OPENSSL_VERSION_NUMBER < 0x00908000L
d = DSA_generate_parameters((int)size, NULL, 0, NULL, NULL, NULL, NULL);
if (!d) {
ldns_key_free(k);
return NULL;
}
+
+# else
+ if (! (d = DSA_new())) {
+ ldns_key_free(k);
+ return NULL;
+ }
+ if (! DSA_generate_parameters_ex(d, (int)size, NULL, 0, NULL, NULL, NULL)) {
+ DSA_free(d);
+ ldns_key_free(k);
+ return NULL;
+ }
+# endif
if (DSA_generate_key(d) != 1) {
ldns_key_free(k);
return NULL;
@@ -870,10 +1221,14 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
ldns_key_set_dsa_key(k, d);
DSA_free(d);
#endif /* HAVE_SSL */
+#endif /* USE_DSA */
break;
case LDNS_SIGN_HMACMD5:
case LDNS_SIGN_HMACSHA1:
+ case LDNS_SIGN_HMACSHA224:
case LDNS_SIGN_HMACSHA256:
+ case LDNS_SIGN_HMACSHA384:
+ case LDNS_SIGN_HMACSHA512:
#ifdef HAVE_SSL
#ifndef S_SPLINT_S
k->_key.key = NULL;
@@ -956,6 +1311,62 @@ ldns_key_new_frm_algorithm(ldns_signing_algorithm alg, uint16_t size)
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;
@@ -1005,9 +1416,13 @@ ldns_key_set_rsa_key(ldns_key *k, RSA *r)
void
ldns_key_set_dsa_key(ldns_key *k, DSA *d)
{
+#ifdef USE_DSA
EVP_PKEY *key = EVP_PKEY_new();
EVP_PKEY_set1_DSA(key, d);
k->_key.key = key;
+#else
+ (void)k; (void)d;
+#endif
}
void
@@ -1021,9 +1436,13 @@ ldns_key_assign_rsa_key(ldns_key *k, RSA *r)
void
ldns_key_assign_dsa_key(ldns_key *k, DSA *d)
{
+#ifdef USE_DSA
EVP_PKEY *key = EVP_PKEY_new();
EVP_PKEY_assign_DSA(key, d);
k->_key.key = key;
+#else
+ (void)k; (void)d;
+#endif
}
#endif /* splint */
#endif /* HAVE_SSL */
@@ -1137,11 +1556,16 @@ ldns_key_rsa_key(const ldns_key *k)
DSA *
ldns_key_dsa_key(const ldns_key *k)
{
+#ifdef USE_DSA
if (k->_key.key) {
return EVP_PKEY_get1_DSA(k->_key.key);
} else {
return NULL;
}
+#else
+ (void)k;
+ return NULL;
+#endif
}
#endif /* splint */
#endif /* HAVE_SSL */
@@ -1284,47 +1708,67 @@ static bool
ldns_key_rsa2bin(unsigned char *data, RSA *k, uint16_t *size)
{
int i,j;
+ const BIGNUM *n=NULL, *e=NULL;
if (!k) {
return false;
}
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
+ n = k->n;
+ e = k->e;
+#else
+ RSA_get0_key(k, &n, &e, NULL);
+#endif
- if (BN_num_bytes(k->e) <= 256) {
+ if (BN_num_bytes(e) <= 256) {
/* normally only this path is executed (small factors are
* more common
*/
- data[0] = (unsigned char) BN_num_bytes(k->e);
- i = BN_bn2bin(k->e, data + 1);
- j = BN_bn2bin(k->n, data + i + 1);
+ data[0] = (unsigned char) BN_num_bytes(e);
+ i = BN_bn2bin(e, data + 1);
+ j = BN_bn2bin(n, data + i + 1);
*size = (uint16_t) i + j;
- } else if (BN_num_bytes(k->e) <= 65536) {
+ } else if (BN_num_bytes(e) <= 65536) {
data[0] = 0;
/* BN_bn2bin does bigendian, _uint16 also */
- ldns_write_uint16(data + 1, (uint16_t) BN_num_bytes(k->e));
+ ldns_write_uint16(data + 1, (uint16_t) BN_num_bytes(e));
- BN_bn2bin(k->e, data + 3);
- BN_bn2bin(k->n, data + 4 + BN_num_bytes(k->e));
- *size = (uint16_t) BN_num_bytes(k->n) + 6;
+ BN_bn2bin(e, data + 3);
+ BN_bn2bin(n, data + 4 + BN_num_bytes(e));
+ *size = (uint16_t) BN_num_bytes(n) + 6;
} else {
return false;
}
return true;
}
+#ifdef USE_DSA
/* data pointer must be large enough (LDNS_MAX_KEYLEN) */
static bool
ldns_key_dsa2bin(unsigned char *data, DSA *k, uint16_t *size)
{
uint8_t T;
+ const BIGNUM *p, *q, *g;
+ const BIGNUM *pub_key, *priv_key;
if (!k) {
return false;
}
/* See RFC2536 */
- *size = (uint16_t)BN_num_bytes(k->p);
+# ifdef HAVE_DSA_GET0_PQG
+ DSA_get0_pqg(k, &p, &q, &g);
+# else
+ p = k->p; q = k->q; g = k->g;
+# endif
+# ifdef HAVE_DSA_GET0_KEY
+ DSA_get0_key(k, &pub_key, &priv_key);
+# else
+ pub_key = k->pub_key; priv_key = k->priv_key;
+# endif
+ (void)priv_key;
+ *size = (uint16_t)BN_num_bytes(p);
T = (*size - 64) / 8;
- memcpy(data, &T, 1);
if (T > 8) {
#ifdef STDERR_MSGS
@@ -1335,14 +1779,16 @@ ldns_key_dsa2bin(unsigned char *data, DSA *k, uint16_t *size)
}
/* size = 64 + (T * 8); */
+ memset(data, 0, 21 + *size * 3);
data[0] = (unsigned char)T;
- BN_bn2bin(k->q, data + 1 ); /* 20 octects */
- BN_bn2bin(k->p, data + 21 ); /* offset octects */
- BN_bn2bin(k->g, data + 21 + *size); /* offset octets */
- BN_bn2bin(k->pub_key, data + 21 + *size + *size); /* offset octets */
- *size = 21 + (*size * 3);
+ BN_bn2bin(q, data + 1 ); /* 20 octects */
+ BN_bn2bin(p, data + 21 ); /* offset octects */
+ BN_bn2bin(g, data + 21 + *size * 2 - BN_num_bytes(g));
+ BN_bn2bin(pub_key,data + 21 + *size * 3 - BN_num_bytes(pub_key));
+ *size = 21 + *size * 3;
return true;
}
+#endif /* USE_DSA */
#ifdef USE_GOST
static bool
@@ -1352,13 +1798,13 @@ ldns_key_gost2bin(unsigned char* data, EVP_PKEY* k, uint16_t* size)
unsigned char* pp = NULL;
if(i2d_PUBKEY(k, &pp) != 37 + 64) {
/* expect 37 byte(ASN header) and 64 byte(X and Y) */
- CRYPTO_free(pp);
+ free(pp);
return false;
}
/* omit ASN header */
for(i=0; i<64; i++)
data[i] = pp[i+37];
- CRYPTO_free(pp);
+ free(pp);
*size = 64;
return true;
}
@@ -1380,7 +1826,9 @@ ldns_key2rr(const ldns_key *k)
uint16_t size = 0;
#ifdef HAVE_SSL
RSA *rsa = NULL;
+#ifdef USE_DSA
DSA *dsa = NULL;
+#endif /* USE_DSA */
#endif /* HAVE_SSL */
#ifdef USE_ECDSA
EC_KEY* ec;
@@ -1395,7 +1843,10 @@ ldns_key2rr(const ldns_key *k)
switch (ldns_key_algorithm(k)) {
case LDNS_SIGN_HMACMD5:
case LDNS_SIGN_HMACSHA1:
+ case LDNS_SIGN_HMACSHA224:
case LDNS_SIGN_HMACSHA256:
+ case LDNS_SIGN_HMACSHA384:
+ case LDNS_SIGN_HMACSHA512:
ldns_rr_set_type(pubkey, LDNS_RR_TYPE_KEY);
break;
default:
@@ -1445,6 +1896,7 @@ ldns_key2rr(const ldns_key *k)
case LDNS_SIGN_DSA:
ldns_rr_push_rdf(pubkey,
ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA));
+#ifdef USE_DSA
#ifdef HAVE_SSL
dsa = ldns_key_dsa_key(k);
if (dsa) {
@@ -1462,10 +1914,12 @@ ldns_key2rr(const ldns_key *k)
internal_data = 1;
}
#endif /* HAVE_SSL */
+#endif /* USE_DSA */
break;
case LDNS_SIGN_DSA_NSEC3:
ldns_rr_push_rdf(pubkey,
ldns_native2rdf_int8(LDNS_RDF_TYPE_ALG, LDNS_DSA_NSEC3));
+#ifdef USE_DSA
#ifdef HAVE_SSL
dsa = ldns_key_dsa_key(k);
if (dsa) {
@@ -1483,6 +1937,7 @@ ldns_key2rr(const ldns_key *k)
internal_data = 1;
}
#endif /* HAVE_SSL */
+#endif /* USE_DSA */
break;
case LDNS_SIGN_ECC_GOST:
ldns_rr_push_rdf(pubkey, ldns_native2rdf_int8(
@@ -1540,9 +1995,50 @@ ldns_key2rr(const ldns_key *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_HMACSHA224:
case LDNS_SIGN_HMACSHA256:
+ case LDNS_SIGN_HMACSHA384:
+ case LDNS_SIGN_HMACSHA512:
bin = LDNS_XMALLOC(unsigned char, ldns_key_hmac_size(k));
if (!bin) {
ldns_rr_free(pubkey);
@@ -1654,7 +2150,7 @@ ldns_read_anchor_file(const char *filename)
}
char *
-ldns_key_get_file_base_name(ldns_key *key)
+ldns_key_get_file_base_name(const ldns_key *key)
{
ldns_buffer *buffer;
char *file_base_name;
@@ -1691,7 +2187,9 @@ ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name)
{LDNS_SIGN_DSA_NSEC3, "NSEC3DSA"},
{LDNS_SIGN_RSASHA1_NSEC3, "NSEC3RSASHA1"},
/* old ldns usage, now RFC names */
+#ifdef USE_DSA
{LDNS_SIGN_DSA_NSEC3, "DSA_NSEC3" },
+#endif
{LDNS_SIGN_RSASHA1_NSEC3, "RSASHA1_NSEC3" },
#ifdef USE_GOST
{LDNS_SIGN_ECC_GOST, "GOST"},
@@ -1704,6 +2202,9 @@ ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name)
{LDNS_PRIVATEOID, "PRIVATEOID"},
{0, NULL}};
ldns_lookup_table* lt = ldns_signing_algorithms;
+ ldns_signing_algorithm a;
+ char *endptr;
+
while(lt->name) {
if(strcasecmp(lt->name, name) == 0)
return lt->id;
@@ -1715,7 +2216,9 @@ ldns_signing_algorithm ldns_get_signing_algorithm_by_name(const char* name)
return lt->id;
lt++;
}
- if(atoi(name) != 0)
- return atoi(name);
+ a = strtol(name, &endptr, 10);
+ if (*name && !*endptr)
+ return a;
+
return 0;
}