From 63d9cc28b9e0c6a58f0ff2f1e6b638a185c471c6 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 24 Apr 2012 13:17:29 +0100 Subject: [PATCH] [crypto] Allow client certificate to be changed without a rebuild Signed-off-by: Michael Brown --- src/crypto/clientcert.c | 101 ++++++++++++++++++++++++++++++++++++---- src/include/ipxe/dhcp.h | 6 +++ 2 files changed, 98 insertions(+), 9 deletions(-) diff --git a/src/crypto/clientcert.c b/src/crypto/clientcert.c index 03c75284..692aafb4 100644 --- a/src/crypto/clientcert.c +++ b/src/crypto/clientcert.c @@ -19,6 +19,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include +#include +#include +#include #include /** @file @@ -55,12 +59,6 @@ __asm__ ( ".section \".rodata\", \"a\", @progbits\n\t" ".equ client_certificate_len, ( . - client_certificate_data )\n\t" ".previous\n\t" ); -/** Client certificate */ -struct client_certificate client_certificate = { - .data = client_certificate_data, - .len = ( ( size_t ) client_certificate_len ), -}; - /* Raw client private key data */ extern char client_private_key_data[]; extern char client_private_key_len[]; @@ -73,8 +71,93 @@ __asm__ ( ".section \".rodata\", \"a\", @progbits\n\t" ".equ client_private_key_len, ( . - client_private_key_data )\n\t" ".previous\n\t" ); +/** Client certificate */ +struct client_certificate client_certificate; + /** Client private key */ -struct client_private_key client_private_key = { - .data = client_private_key_data, - .len = ( ( size_t ) client_private_key_len ), +struct client_private_key client_private_key; + +/** Client certificate setting */ +struct setting cert_setting __setting ( SETTING_CRYPTO ) = { + .name = "cert", + .description = "Client certificate", + .tag = DHCP_EB_CERT, + .type = &setting_type_hex, +}; + +/** Client private key setting */ +struct setting key_setting __setting ( SETTING_CRYPTO ) = { + .name = "key", + .description = "Client private key", + .tag = DHCP_EB_KEY, + .type = &setting_type_hex, +}; + +/** + * Apply client certificate store configuration settings + * + * @ret rc Return status code + */ +static int clientcert_apply_settings ( void ) { + static void *cert; + static void *key; + int len; + int rc; + + /* Restore default client certificate */ + client_certificate.data = client_certificate_data; + client_certificate.len = ( ( size_t ) client_certificate_len ); + + /* Fetch new client certificate, if any */ + free ( cert ); + len = fetch_setting_copy ( NULL, &cert_setting, &cert ); + if ( len < 0 ) { + rc = len; + DBGC ( &client_certificate, "CLIENTCERT cannot fetch client " + "certificate: %s\n", strerror ( rc ) ); + return rc; + } + if ( cert ) { + client_certificate.data = cert; + client_certificate.len = len; + } + + /* Restore default client private key */ + client_private_key.data = client_private_key_data; + client_private_key.len = ( ( size_t ) client_private_key_len ); + + /* Fetch new client private key, if any */ + free ( key ); + len = fetch_setting_copy ( NULL, &key_setting, &key ); + if ( len < 0 ) { + rc = len; + DBGC ( &client_certificate, "CLIENTCERT cannot fetch client " + "private key: %s\n", strerror ( rc ) ); + return rc; + } + if ( key ) { + client_private_key.data = key; + client_private_key.len = len; + } + + /* Debug */ + if ( have_client_certificate() ) { + DBGC ( &client_certificate, "CLIENTCERT using %s " + "certificate:\n", ( cert ? "external" : "built-in" ) ); + DBGC_HDA ( &client_certificate, 0, client_certificate.data, + client_certificate.len ); + DBGC ( &client_certificate, "CLIENTCERT using %s private " + "key:\n", ( key ? "external" : "built-in" ) ); + DBGC_HDA ( &client_certificate, 0, client_private_key.data, + client_private_key.len ); + } else { + DBGC ( &client_certificate, "CLIENTCERT has no certificate\n" ); + } + + return 0; +} + +/** Client certificate store settings applicator */ +struct settings_applicator clientcert_applicator __settings_applicator = { + .apply = clientcert_apply_settings, }; diff --git a/src/include/ipxe/dhcp.h b/src/include/ipxe/dhcp.h index cc594ab1..dc8a6fc7 100644 --- a/src/include/ipxe/dhcp.h +++ b/src/include/ipxe/dhcp.h @@ -358,6 +358,12 @@ struct dhcp_client_uuid { /** Trusted root certficate fingerprints */ #define DHCP_EB_TRUST DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x5a ) +/** Client certficate */ +#define DHCP_EB_CERT DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x5b ) + +/** Client private key */ +#define DHCP_EB_KEY DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x5c ) + /** Skip PXE DHCP protocol extensions such as ProxyDHCP * * If set to a non-zero value, iPXE will not wait for ProxyDHCP offers