[ipxe-devel] [RESEND PATCH 4/5] [crypto] Allow trusted certificates to be set by trusted scripts

Ladi Prosek lprosek at redhat.com
Fri Mar 3 12:37:06 UTC 2017


The list of trusted root certificates can be currently overriden only
by rebuilding iPXE with the TRUST=... build parameter or by settings
coming from trusted sources, namely VMWare GuestInfo and non-volatile
options.

There are scenarios when one would want to set trusted root certificates
from an iPXE script that is considered trusted. For example, one may
want to pass such script to ipxe.lkrn as initrd. Since both initrd and
the iPXE binary are at the same level of trust, i.e. considered trusted
because they come from the same source, there's no reason why initrd
shouldn't be allowed to execute the 'set trust ...' command.

This commit adds a settings applicator which updates the root_certificates
global variable only in response to an explicit update of the 'trust'
setting and only when executing a trusted image.

Signed-off-by: Ladi Prosek <lprosek at redhat.com>
---
 src/crypto/rootcert.c | 66 +++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 48 insertions(+), 18 deletions(-)

diff --git a/src/crypto/rootcert.c b/src/crypto/rootcert.c
index f7b9dcf..40a5271 100644
--- a/src/crypto/rootcert.c
+++ b/src/crypto/rootcert.c
@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <ipxe/dhcp.h>
 #include <ipxe/init.h>
 #include <ipxe/rootcert.h>
+#include <ipxe/image.h>
 
 /** @file
  *
@@ -86,42 +87,71 @@ struct x509_root root_certificates = {
  * If no certificates were explicitly specified, then we 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 (e.g. VMware GuestInfo or non-volatile stored
- * options) to specify the trusted root certificate without requiring
- * a rebuild.
+ * initialisation and from trusted scripts.  This prevents untrusted
+ * sources of settings (e.g. DHCP) from subverting the chain of trust,
+ * while allowing trustworthy sources (e.g. VMware GuestInfo,
+ * non-volatile stored options, or initrd) to specify the trusted
+ * root certificate without requiring a rebuild.
  */
-static void rootcert_init ( void ) {
-	static int initialised;
+static void rootcert_init ( int allow_external ) {
 	void *external = NULL;
 	int len;
 
-	/* Allow trusted root certificates to be overridden only if
-	 * not explicitly specified at build time.
-	 */
-	if ( ALLOW_TRUST_OVERRIDE && ( ! initialised ) ) {
+	if ( allow_external ) {
 
-		/* Fetch copy of "trust" setting, if it exists.  This
-		 * memory will never be freed.
+		/* Fetch copy of "trust" setting, if it exists.  The
+		 * memory of the last fetched setting will never be freed.
 		 */
 		if ( ( len = fetch_raw_setting_copy ( NULL, &trust_setting,
 						      &external ) ) >= 0 ) {
+			if ( root_certificates.fingerprints != fingerprints ) {
+				free ( ( void * ) root_certificates.fingerprints );
+			}
 			root_certificates.fingerprints = external;
 			root_certificates.count = ( len / FINGERPRINT_LEN );
 		}
-
-		/* Prevent subsequent modifications */
-		initialised = 1;
 	}
 
 	DBGC ( &root_certificates, "ROOTCERT using %d %s certificate(s):\n",
-	       root_certificates.count, ( external ? "external" : "built-in" ));
+	       root_certificates.count,
+	       ( root_certificates.fingerprints != fingerprints ?
+	       "external" : "built-in" ));
 	DBGC_HDA ( &root_certificates, 0, root_certificates.fingerprints,
 		   ( root_certificates.count * FINGERPRINT_LEN ) );
 }
 
+static void rootcert_startup ( void ) {
+	static int initialised;
+
+	if ( ! initialised ) {
+		/* Allow trusted root certificates to be overridden only if
+		 * not explicitly specified at build time.
+		 */
+		rootcert_init ( ALLOW_TRUST_OVERRIDE );
+
+		/* Prevent subsequent modifications */
+		initialised = 1;
+	}
+}
+
+static int rootcert_apply_settings ( const struct setting *setting ) {
+	if ( setting && setting->tag == DHCP_EB_TRUST ) {
+		/* Allow trusted root certificates to be overridden from
+		 * trusted images only if not explicitly specified at build
+		 * time.
+		 */
+		rootcert_init ( ALLOW_TRUST_OVERRIDE &&
+				( current_image->flags & IMAGE_TRUSTED ) );
+	}
+	return 0;
+}
+
 /** Root certificate initialiser */
 struct startup_fn rootcert_startup_fn __startup_fn ( STARTUP_LATE ) = {
-	.startup = rootcert_init,
+	.startup = rootcert_startup,
+};
+
+/** Root certificate settings applicator */
+struct settings_applicator rootcert_applicator __settings_applicator = {
+	.apply = rootcert_apply_settings,
 };
-- 
2.7.4




More information about the ipxe-devel mailing list