ソースを参照

[crypto] Allow trusted root certificate to be changed without a rebuild

Changing the trusted root certificate currently requires a rebuild of
the iPXE binary, which may be inconvenient or impractical.

Allow the list of trusted root certificate fingerprints to be
overridden using the "trust" setting, but only at the point of iPXE
initialisation.  This prevents untrusted sources of settings
(e.g. DHCP) from subverting the chain of trust, while allowing
trustworthy sources to change the trusted root certificate without
requiring a rebuild.

The basic idea is that if you are able to manipulate a trustworthy
source of settings (e.g. VMware GuestInfo or non-volatile stored
options), then you would be able to replace the iPXE binary anyway,
and so no security is lost by allowing such sources to override the
list of trusted root certificates.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12年前
コミット
02f1f3066d
3個のファイルの変更69行の追加2行の削除
  1. 64
    1
      src/crypto/rootcert.c
  2. 3
    0
      src/include/ipxe/dhcp.h
  3. 2
    1
      src/include/ipxe/settings.h

+ 64
- 1
src/crypto/rootcert.c ファイルの表示

@@ -18,9 +18,13 @@
18 18
 
19 19
 FILE_LICENCE ( GPL2_OR_LATER );
20 20
 
21
+#include <stdlib.h>
21 22
 #include <ipxe/crypto.h>
22 23
 #include <ipxe/sha256.h>
23 24
 #include <ipxe/x509.h>
25
+#include <ipxe/settings.h>
26
+#include <ipxe/dhcp.h>
27
+#include <ipxe/init.h>
24 28
 #include <ipxe/rootcert.h>
25 29
 
26 30
 /** @file
@@ -29,6 +33,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
29 33
  *
30 34
  */
31 35
 
36
+/** Length of a root certificate fingerprint */
37
+#define FINGERPRINT_LEN SHA256_DIGEST_SIZE
38
+
32 39
 /* Use iPXE root CA if no trusted certificates are explicitly specified */
33 40
 #ifndef TRUSTED
34 41
 #define TRUSTED								\
@@ -42,9 +49,65 @@ FILE_LICENCE ( GPL2_OR_LATER );
42 49
 /** Root certificate fingerprints */
43 50
 static const uint8_t fingerprints[] = { TRUSTED };
44 51
 
52
+/** Root certificate fingerprint setting */
53
+struct setting trust_setting __setting ( SETTING_CRYPTO ) = {
54
+	.name = "trust",
55
+	.description = "Trusted root certificate fingerprint",
56
+	.tag = DHCP_EB_TRUST,
57
+	.type = &setting_type_hex,
58
+};
59
+
45 60
 /** Root certificates */
46 61
 struct x509_root root_certificates = {
47 62
 	.digest = &sha256_algorithm,
48
-	.count = ( sizeof ( fingerprints ) / SHA256_DIGEST_SIZE ),
63
+	.count = ( sizeof ( fingerprints ) / FINGERPRINT_LEN ),
49 64
 	.fingerprints = fingerprints,
50 65
 };
66
+
67
+/**
68
+ * Initialise root certificate
69
+ *
70
+ * We allow the list of trusted root certificate fingerprints to be
71
+ * overridden using the "trust" setting, but only at the point of iPXE
72
+ * initialisation.  This prevents untrusted sources of settings
73
+ * (e.g. DHCP) from subverting the chain of trust, while allowing
74
+ * trustworthy sources (e.g. VMware GuestInfo or non-volatile stored
75
+ * options) to change the trusted root certificate without requiring a
76
+ * rebuild.
77
+ */
78
+static void rootcert_init ( void ) {
79
+	void *external;
80
+	int len;
81
+	int rc;
82
+
83
+	/* Fetch copy of "trust" setting, if it exists.  This memory
84
+	 * will never be freed.
85
+	 */
86
+	len = fetch_setting_copy ( NULL, &trust_setting, &external );
87
+	if ( len < 0 ) {
88
+		rc = len;
89
+		DBGC ( &root_certificates, "ROOTCERT cannot fetch trusted "
90
+		       "root certificate fingerprints: %s\n", strerror ( rc ) );
91
+		/* No way to prevent startup; fail safe by trusting no
92
+		 * certificates.
93
+		 */
94
+		root_certificates.count = 0;
95
+		return;
96
+	}
97
+
98
+	/* Use certificates from "trust" setting, if present */
99
+	if ( external ) {
100
+		root_certificates.fingerprints = external;
101
+		root_certificates.count = ( len / FINGERPRINT_LEN );
102
+	}
103
+
104
+	DBGC ( &root_certificates, "ROOTCERT using %d %s certificate(s):\n",
105
+	       root_certificates.count, ( external ? "external" : "built-in" ));
106
+	DBGC_HDA ( &root_certificates, 0, root_certificates.fingerprints,
107
+		   ( root_certificates.count * FINGERPRINT_LEN ) );
108
+}
109
+
110
+/** Root certificate initialiser */
111
+struct init_fn rootcert_init_fn __init_fn ( INIT_LATE ) = {
112
+	.initialise = rootcert_init,
113
+};

+ 3
- 0
src/include/ipxe/dhcp.h ファイルの表示

@@ -355,6 +355,9 @@ struct dhcp_client_uuid {
355 355
 /** Encrypted syslog server */
356 356
 #define DHCP_EB_SYSLOGS_SERVER DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x55 )
357 357
 
358
+/** Trusted root certficate fingerprints */
359
+#define DHCP_EB_TRUST DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0x5a )
360
+
358 361
 /** Skip PXE DHCP protocol extensions such as ProxyDHCP
359 362
  *
360 363
  * If set to a non-zero value, iPXE will not wait for ProxyDHCP offers

+ 2
- 1
src/include/ipxe/settings.h ファイルの表示

@@ -83,7 +83,8 @@ struct setting {
83 83
 #define SETTING_HOST_EXTRA	10 /**< Host identity additional settings */
84 84
 #define SETTING_AUTH		11 /**< Authentication settings */
85 85
 #define SETTING_AUTH_EXTRA	12 /**< Authentication additional settings */
86
-#define SETTING_MISC		13 /**< Miscellaneous settings */
86
+#define SETTING_CRYPTO		13 /**< Cryptography settings */
87
+#define SETTING_MISC		14 /**< Miscellaneous settings */
87 88
 
88 89
 /** @} */
89 90
 

読み込み中…
キャンセル
保存