summaryrefslogtreecommitdiffstats
path: root/src/crypto
diff options
context:
space:
mode:
authorMichael Brown2012-04-24 14:17:29 +0200
committerMichael Brown2012-04-24 14:17:29 +0200
commit63d9cc28b9e0c6a58f0ff2f1e6b638a185c471c6 (patch)
tree817b96454b9582cfc3cabb4563e7cbd9fbf2f772 /src/crypto
parent[build] Use $(xxx_DEPS) for additional dependency information (diff)
downloadipxe-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.c101
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,
};