summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancis Dupont <fdupont@isc.org>2015-06-05 18:26:18 +0200
committerFrancis Dupont <fdupont@isc.org>2015-06-05 18:26:18 +0200
commit1e1561b5ef5089b7b8460383d9f8718de0f09c42 (patch)
treed6d1afaedd3c40708878551662c251ec07668beb
parent8c4734c44b993983eb627d4e32d5dfe751eed7d6 (diff)
downloadisc-dhcp-secure_client.tar.gz
moved to native OpenSSLsecure_client
-rw-r--r--client/dhc6.c182
-rw-r--r--client/dhclient.814
-rw-r--r--client/dhclient.c71
-rw-r--r--includes/dhcpd.h2
-rw-r--r--util/Makefile.bind.in3
5 files changed, 163 insertions, 109 deletions
diff --git a/client/dhc6.c b/client/dhc6.c
index 06a1a5ad..4a55f4fe 100644
--- a/client/dhc6.c
+++ b/client/dhc6.c
@@ -5239,14 +5239,12 @@ secure_dhc6_add(struct data_string *packet)
struct data_string tbs;
struct data_string tmstmp;
struct data_string sign;
+ EVP_MD_CTX ctx;
+ EVP_PKEY *pkey = (EVP_PKEY *) key;
isc_uint64_t sec;
isc_uint64_t fraction;
- dst_context_t *ctx = NULL;
- isc_region_t r;
- isc_buffer_t sigbuf;
- unsigned int siglen = 0;
- int savedlen = (int) packet->len;
- isc_result_t result;
+ int siglen, savedlen = (int) packet->len;
+ unsigned size;
/* Prepare a to be signed copy of the packet */
memset(&tbs, 0, sizeof(tbs));
@@ -5295,22 +5293,23 @@ secure_dhc6_add(struct data_string *packet)
}
/* Prepare the signature option */
- result = dst_key_sigsize(key, &siglen);
- if (result != ISC_R_SUCCESS) {
- log_error("dst_key_sigsize: %s.", isc_result_totext(result));
+ siglen = EVP_PKEY_size(pkey);
+ if (siglen <= 0) {
+ log_error("EVP_PKEY_size failed");
data_string_forget(&tbs, MDL);
data_string_forget(&tmstmp, MDL);
return;
}
- if (!buffer_allocate(&sign.buffer, siglen, MDL)) {
+ size = (unsigned) siglen;
+ if (!buffer_allocate(&sign.buffer, size, MDL)) {
log_error("Unable to allocate memory for signature.");
data_string_forget(&tbs, MDL);
data_string_forget(&tmstmp, MDL);
return;
}
- memset(sign.buffer->data, 0, siglen + 2);
+ memset(sign.buffer->data, 0, size + 2);
sign.data = sign.buffer->data;
- sign.len = siglen + 2;
+ sign.len = size + 2;
/* TODO: map algos */
sign.buffer->data[0] = SHA_256;
sign.buffer->data[1] = RSASSA_PKCS1v1_5;
@@ -5323,43 +5322,32 @@ secure_dhc6_add(struct data_string *packet)
return;
}
- /* Get a signing context */
- result = dst_context_create(key, dhcp_gbl_ctx.mctx, &ctx);
- if (result != ISC_R_SUCCESS) {
- log_error("dst_context_create: %s.",
- isc_result_totext(result));
+ /* Sign */
+ EVP_MD_CTX_init(&ctx);
+ if (!EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL)) {
+ log_error("EVP_DigestInit_ex failed");
data_string_forget(&tbs, MDL);
data_string_forget(&tmstmp, MDL);
data_string_forget(&sign, MDL);
return;
}
-
- /* Digest the to be signed copy */
- r.base = tbs.buffer->data;
- r.length = tbs.len;
- result = dst_context_adddata(ctx, &r);
- if (result != ISC_R_SUCCESS) {
- log_error("dst_context_adddata: %s.",
- isc_result_totext(result));
+ if (!EVP_DigestUpdate(&ctx, tbs.data, tbs.len)) {
+ log_error("EVP_DigestUpdate failed");
data_string_forget(&tbs, MDL);
data_string_forget(&tmstmp, MDL);
data_string_forget(&sign, MDL);
- dst_context_destroy(&ctx);
return;
}
-
- /* Sign */
- isc_buffer_init(&sigbuf, &sign.buffer->data[2], siglen);
- result = dst_context_sign(ctx, &sigbuf);
- data_string_forget(&tbs, MDL);
- dst_context_destroy(&ctx);
- if (result != ISC_R_SUCCESS) {
- log_error("dst_context_sign: %s.",
- isc_result_totext(result));
+ if (!EVP_SignFinal(&ctx, sign.buffer->data + 2, &size, pkey)) {
+ log_error("EVP_SignFinal failed");
+ data_string_forget(&tbs, MDL);
data_string_forget(&tmstmp, MDL);
data_string_forget(&sign, MDL);
+ EVP_MD_CTX_cleanup(&ctx);
return;
}
+ data_string_forget(&tbs, MDL);
+ EVP_MD_CTX_cleanup(&ctx);
/* Push the public key/certificate option on the packet */
if (!append_option(packet, &dhcpv6_universe,
@@ -5632,4 +5620,128 @@ valid_secure_dhc6(struct packet *packet)
log_info("signature is valid.");
return ISC_TRUE;
}
+
+#define DER_MAXSIZE 16*1024
+
+void
+get_keys(const char *rootname)
+{
+
+ char *tmp;
+ FILE *fp = NULL;
+ EVP_PKEY *pkey = (EVP_PKEY *) key;
+ EVP_PKEY *pubkey;
+ RSA *rsa;
+ X509 *x509;
+ size_t nlen = strlen(rootname);
+ isc_result_t ret;
+ int len, nid;
+ unsigned char *p;
+
+ nlen += 20;
+ tmp = dmalloc(nlen, MDL);
+ if (!tmp)
+ log_fatal("No memory for %s", rootname);
+
+ /* Get the private key - PKCS#1 or PKCS#8 format. */
+ (void) snprintf(tmp, nlen, "%s.pkcs8", rootname);
+ ret = isc_stdio_open(tmp, "r", &fp);
+ if (ret != ISC_R_SUCCESS) {
+ (void) snprintf(tmp, nlen, "%s.priv", rootname);
+ ret = isc_stdio_open(tmp, "r", &fp);
+ }
+ if (ret != ISC_R_SUCCESS)
+ log_fatal("can't open '%s': %s", tmp, isc_result_totext(ret));
+ pkey = PEM_read_PrivateKey(fp, NULL, 0, NULL);
+ fclose(fp);
+ if (!pkey)
+ log_fatal("PEM_read_PrivateKey() failed");
+ key = (void *) pkey;
+
+ /* Get the public key - PKCS#1 format. */
+ (void) snprintf(tmp, nlen, "%s.pub", rootname);
+ ret = isc_stdio_open(tmp, "r", &fp);
+ if (ret != ISC_R_SUCCESS)
+ goto spki;
+ rsa = PEM_read_RSAPublicKey(fp, NULL, 0, NULL);
+ fclose(fp);
+ if (!rsa)
+ log_fatal("PEM_read_RSAPublicKey failed");
+ goto der;
+
+ spki:
+ /* Get the public key - SPKI format. */
+ (void) snprintf(tmp, nlen, "%s.spki", rootname);
+ ret = isc_stdio_open(tmp, "r", &fp);
+ if (ret != ISC_R_SUCCESS)
+ goto cert;
+ pubkey = PEM_read_PUBKEY(fp, NULL, 0, NULL);
+ fclose(fp);
+ if (!pubkey)
+ log_fatal("PEM_read_PUBKEY failed");
+ rsa = EVP_PKEY_get1_RSA(pubkey);
+ if (!rsa)
+ log_fatal("EVP_PKEY_get1_RSA failed");
+ EVP_PKEY_free(pubkey);
+
+ der:
+ /* Put the public key in SPKI DER format in the der data string. */
+ len = i2d_RSA_PUBKEY(rsa, NULL);
+ if (len < 0)
+ log_fatal("i2d_RSA_PUBKEY failed0");
+ if (len > DER_MAXSIZE)
+ log_fatal("the public key is too large (size %d)", len);
+ if (!buffer_allocate(&der.buffer, (unsigned)len, MDL))
+ log_fatal("No memory for the public key in DER (size %u)",
+ (unsigned)len);
+ der.data = der.buffer->data;
+ der.len = (unsigned)len;
+ p = der.buffer->data;
+ len = i2d_RSA_PUBKEY(rsa, &p);
+ if (len != (int)der.len)
+ log_fatal("i2d_RSA_PUBKEY failed");
+ RSA_free(rsa);
+ dfree(tmp, MDL);
+ return;
+
+ cert:
+ /* Get the X.509 public key certificate. */
+ is_secure = 2;
+ (void) snprintf(tmp, nlen, "%s.x509", rootname);
+ ret = isc_stdio_open(tmp, "r", &fp);
+ if (ret != ISC_R_SUCCESS) {
+ (void) snprintf(tmp, nlen, "%s.cert", rootname);
+ ret = isc_stdio_open(tmp, "r", &fp);
+ }
+ if (ret != ISC_R_SUCCESS)
+ log_fatal("can't open '%s': %s", tmp, isc_result_totext(ret));
+ x509 = PEM_read_X509(fp, NULL, 0, NULL);
+ fclose(fp);
+ if (!x509)
+ log_fatal("PEM_read_X509 failed");
+ /* Verify it is RSASHA256. */
+ nid = OBJ_obj2nid(x509->sig_alg->algorithm);
+ /* SHA-512 is .13 */
+ if (nid != OBJ_txt2nid("1.2.840.113549.1.1.11"))
+ log_fatal("The certificate is not for RSASHA256");
+
+ /* Put the certificate in DER format in the der data string. */
+ len = i2d_X509(x509, NULL);
+ if (len < 0)
+ log_fatal("i2d_X509 failed0");
+ if (len > DER_MAXSIZE)
+ log_fatal("the certificate is too large (size %d)", len);
+ if (!buffer_allocate(&der.buffer, (unsigned)len, MDL))
+ log_fatal("No memory for the certificate in DER (size %u)",
+ (unsigned)len);
+ der.data = der.buffer->data;
+ der.len = (unsigned)len;
+ p = der.buffer->data;
+ len = i2d_X509(x509, &p);
+ if (len != (int)der.len)
+ log_fatal("i2d_X509 failed");
+ X509_free(x509);
+ dfree(tmp, MDL);
+ return;
+}
#endif /* DHCPv6 */
diff --git a/client/dhclient.8 b/client/dhclient.8
index 91fd790e..239b4398 100644
--- a/client/dhclient.8
+++ b/client/dhclient.8
@@ -349,13 +349,13 @@ Use the standard DDNS scheme from RFCs 4701 & 4702.
.TP
.TP
.BI \-k \ keys-rootname
-Specify the rootname of key files for secure DHCPv6 (so requires \fB-6\fR).
-The public key must be in \fIrootname.key\fR, the private key in
-\fIrootname.private\fR, both in DNSSEC format for RSASHA256 or
-RSASHA512. The third file is used for the public key or the certificate
-secure DHCPv6 option, must be in DER format and the name is
-\fIrootname.pubkeyder\fR for a public key (SubjectPublicKeyInfo) and
-\fIrootname.certder\fR for a certificate (X.509 public key certificate).
+Specify the rootname of PEM key files for secure DHCPv6 (so requires \fB-6\fR).
+Suffixes are \fI.pkcs8\fR or \fI.priv\fR for the mandatory private key
+in PKCS#8 or PKCS#1 format, \fI.spki\fR for the public key in
+SubjectPublicKeyInfo (SPKI) format or \fI.pub\fR inPKCS#1 format,
+or \fI.x509\fR or \fI.cert\fR for the X.509 public key certificate.
+The public key or certificate file is used to build the corresponding
+(and mandatory) secure DHCPv6 option.
.TP
.BI \--version
Print version number and exit.
diff --git a/client/dhclient.c b/client/dhclient.c
index 488bcfb2..a5e00947 100644
--- a/client/dhclient.c
+++ b/client/dhclient.c
@@ -91,9 +91,9 @@ int wanted_ia_pd = 0;
char *mockup_relay = NULL;
int is_secure = 0;
-dst_key_t *key = NULL;
+void *key = NULL;
struct data_string der;
-const char *path_keys = NULL;
+const char *keys_root_name = NULL;
char *progname = NULL;
@@ -109,7 +109,7 @@ static int check_domain_name_list(const char *ptr, size_t len, int dots);
static int check_option_values(struct universe *universe, unsigned int opt,
const char *ptr, size_t len);
#ifdef DHCPv6
-static void get_der(const char *filename);
+extern void get_keys(const char *rootname);
#endif
#ifndef UNIT_TEST
@@ -323,7 +323,7 @@ main(int argc, char **argv) {
local_family_set = 1;
local_family = AF_INET6;
is_secure = 1;
- path_keys = argv[i];
+ keys_root_name = argv[i];
#endif /* DHCPv6 */
} else if (!strcmp(argv[i], "-D")) {
duid_v4 = 1;
@@ -410,20 +410,8 @@ main(int argc, char **argv) {
#ifdef DHCPv6
else if (local_family == AF_INET6) {
dhcpv6_client_assignments();
- if (is_secure) {
- status = dst_key_fromnamedfile(path_keys,
- NULL,
- DST_TYPE_PRIVATE,
- dhcp_gbl_ctx.mctx,
- &key);
- if (status != ISC_R_SUCCESS)
- log_fatal("dst_key_fromnamedfile: "
- "'%s.private': %s",
- path_keys,
- isc_result_totext(status));
- /* TODO: check key_alg */
- get_der(path_keys);
- }
+ if (is_secure)
+ get_keys(keys_root_name);
}
#endif /* DHCPv6 */
else
@@ -793,7 +781,7 @@ static void usage()
log_fatal("Usage: %s "
#ifdef DHCPv6
"[-4|-6] [-SNTPI1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n"
- " [-k keys-rootname]\n"
+ " [-k <keys-rootname>]\n"
#else /* DHCPv6 */
"[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n"
#endif /* DHCPv6 */
@@ -4629,48 +4617,3 @@ add_reject(struct packet *packet) {
*/
log_info("Server added to list of rejected servers.");
}
-
-#ifdef DHCPv6
-
-#define DER_MAXSIZE 16*1024U
-
-static void
-get_der(const char *filename)
-{
- size_t len = strlen(filename);
- char *tmp;
- FILE *fp = NULL;
- isc_result_t ret;
- off_t size = 0;
-
- len += 20;
- tmp = dmalloc(len, MDL);
- if (!tmp)
- log_fatal("No memory for %s", filename);
- (void) snprintf(tmp, len, "%s.pubkeyder", filename);
- ret = isc_stdio_open(tmp, "r", &fp);
- if (ret != ISC_R_SUCCESS) {
- is_secure = 2;
- (void) snprintf(tmp, len, "%s.certder", filename);
- ret = isc_stdio_open(tmp, "r", &fp);
- }
- if (ret != ISC_R_SUCCESS)
- log_fatal("can't open '%s': %s", tmp, isc_result_totext(ret));
- /* isc_file_getsize() is not available in bind9.9 */
- ret = isc_file_getsizefd(fileno(fp), &size);
- if (ret != ISC_R_SUCCESS)
- log_fatal("can't get the size of '%s': %s",
- tmp, isc_result_totext(ret));
- if (size > DER_MAXSIZE)
- log_fatal("%s is too large (%u > %u)",
- tmp, (unsigned)size, DER_MAXSIZE);
- if (!buffer_allocate(&der.buffer, (unsigned)size, MDL))
- log_fatal("No memory for %s (size %u)", tmp, (unsigned)size);
- der.data = der.buffer->data;
- der.len = size;
- ret = isc_stdio_read(der.buffer->data, 1, size, fp, NULL);
- (void) isc_stdio_close(fp);
- if (ret != ISC_R_SUCCESS)
- log_fatal("can't read '%s': %s", tmp, isc_result_totext(ret));
-}
-#endif /* DHCPv6 */
diff --git a/includes/dhcpd.h b/includes/dhcpd.h
index 7183f32d..300353a6 100644
--- a/includes/dhcpd.h
+++ b/includes/dhcpd.h
@@ -2805,7 +2805,7 @@ extern struct client_config top_level_config;
extern int is_secure;
-extern dst_key_t *key;
+extern void *key;
extern struct data_string der;
void dhcpoffer (struct packet *);
diff --git a/util/Makefile.bind.in b/util/Makefile.bind.in
index 6fe780f8..bd784c60 100644
--- a/util/Makefile.bind.in
+++ b/util/Makefile.bind.in
@@ -27,8 +27,7 @@ include ./bindvar.tmp
bindsrcdir=bind-${version}
bindconfig = --disable-kqueue --disable-epoll --disable-devpoll \
- --with-openssl=/usr/local/opt/openssl \
- --without-libxml2 --enable-exportlib \
+ --without-openssl --without-libxml2 --enable-exportlib \
--with-gssapi=no --enable-threads=no @BINDCONFIG@ \
--with-export-includedir=${binddir}/include \
--with-export-libdir=${binddir}/lib