diff options
author | Michael Brown | 2012-04-24 14:17:29 +0200 |
---|---|---|
committer | Michael Brown | 2012-04-24 14:17:29 +0200 |
commit | 63d9cc28b9e0c6a58f0ff2f1e6b638a185c471c6 (patch) | |
tree | 817b96454b9582cfc3cabb4563e7cbd9fbf2f772 /src/crypto | |
parent | [build] Use $(xxx_DEPS) for additional dependency information (diff) | |
download | ipxe-63d9cc28b9e0c6a58f0ff2f1e6b638a185c471c6.tar.gz ipxe-63d9cc28b9e0c6a58f0ff2f1e6b638a185c471c6.tar.xz ipxe-63d9cc28b9e0c6a58f0ff2f1e6b638a185c471c6.zip |
[crypto] Allow client certificate to be changed without a rebuild
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/crypto')
-rw-r--r-- | src/crypto/clientcert.c | 101 |
1 files changed, 92 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 <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <ipxe/dhcp.h> +#include <ipxe/settings.h> #include <ipxe/clientcert.h> /** @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, }; |