|
@@ -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
|
+};
|