diff options
Diffstat (limited to 'client/dhc6.c')
-rw-r--r-- | client/dhc6.c | 182 |
1 files changed, 147 insertions, 35 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 */ |