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
".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[];
".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,
};