aboutsummaryrefslogtreecommitdiff
path: root/lib/dns/opensslecdsa_link.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dns/opensslecdsa_link.c')
-rw-r--r--lib/dns/opensslecdsa_link.c57
1 files changed, 42 insertions, 15 deletions
diff --git a/lib/dns/opensslecdsa_link.c b/lib/dns/opensslecdsa_link.c
index c3f5061b75467..40081c2df856e 100644
--- a/lib/dns/opensslecdsa_link.c
+++ b/lib/dns/opensslecdsa_link.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -371,7 +371,7 @@ opensslecdsa_todns(const dst_key_t *key, isc_buffer_t *data) {
cp = buf;
if (!i2o_ECPublicKey(eckey, &cp))
DST_RET (dst__openssl_toresult(ISC_R_FAILURE));
- memcpy(r.base, buf + 1, len);
+ memmove(r.base, buf + 1, len);
isc_buffer_add(data, len);
ret = ISC_R_SUCCESS;
@@ -414,7 +414,7 @@ opensslecdsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
buf[0] = POINT_CONVERSION_UNCOMPRESSED;
- memcpy(buf + 1, r.base, len);
+ memmove(buf + 1, r.base, len);
cp = buf;
if (o2i_ECPublicKey(&eckey,
(const unsigned char **) &cp,
@@ -453,6 +453,11 @@ opensslecdsa_tofile(const dst_key_t *key, const char *directory) {
if (key->keydata.pkey == NULL)
return (DST_R_NULLKEY);
+ if (key->external) {
+ priv.nelements = 0;
+ return (dst__privstruct_writefile(key, &priv, directory));
+ }
+
pkey = key->keydata.pkey;
eckey = EVP_PKEY_get1_EC_KEY(pkey);
if (eckey == NULL)
@@ -514,8 +519,9 @@ static isc_result_t
opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
dst_private_t priv;
isc_result_t ret;
- EVP_PKEY *pkey;
- EC_KEY *eckey = NULL;
+ EVP_PKEY *pkey, *pubpkey;
+ EC_KEY *eckey = NULL, *pubeckey = NULL;
+ const EC_POINT *pubkey;
BIGNUM *privkey;
int group_nid;
isc_mem_t *mctx = key->mctx;
@@ -537,16 +543,35 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
if (ret != ISC_R_SUCCESS)
goto err;
- privkey = BN_bin2bn(priv.elements[0].data,
- priv.elements[0].length, NULL);
- if (privkey == NULL)
- DST_RET(ISC_R_NOMEMORY);
- if (!EC_KEY_set_private_key(eckey, privkey))
- DST_RET(ISC_R_NOMEMORY);
- if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS)
- DST_RET(DST_R_INVALIDPRIVATEKEY);
- dst__privstruct_free(&priv, mctx);
- memset(&priv, 0, sizeof(priv));
+ if (key->external) {
+ /*
+ * Copy the public key to this new key.
+ */
+ if (pub == NULL)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ pubpkey = pub->keydata.pkey;
+ pubeckey = EVP_PKEY_get1_EC_KEY(pubpkey);
+ if (pubeckey == NULL)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ pubkey = EC_KEY_get0_public_key(pubeckey);
+ if (pubkey == NULL)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ if (EC_KEY_set_public_key(eckey, pubkey) != 1)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ if (EC_KEY_check_key(eckey) != 1)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ } else {
+ privkey = BN_bin2bn(priv.elements[0].data,
+ priv.elements[0].length, NULL);
+ if (privkey == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ if (!EC_KEY_set_private_key(eckey, privkey))
+ DST_RET(ISC_R_NOMEMORY);
+ if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ }
pkey = EVP_PKEY_new();
if (pkey == NULL)
@@ -561,6 +586,8 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
err:
if (eckey != NULL)
EC_KEY_free(eckey);
+ if (pubeckey != NULL)
+ EC_KEY_free(pubeckey);
dst__privstruct_free(&priv, mctx);
memset(&priv, 0, sizeof(priv));
return (ret);