| /* | |
| * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>. | |
| * | |
| * This program is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU General Public License as | |
| * published by the Free Software Foundation; either version 2 of the | |
| * License, or any later version. | |
| * | |
| * This program is distributed in the hope that it will be useful, but | |
| * WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU General Public License | |
| * along with this program; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| * 02110-1301, USA. | |
| * | |
| * You can also choose to distribute this program under the terms of | |
| * the Unmodified Binary Distribution Licence (as given in the file | |
| * COPYING.UBDL), provided that you have satisfied its requirements. | |
| */ | |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | |
| FILE_SECBOOT ( PERMITTED ); | |
| #include <stdlib.h> | |
| #include <ipxe/crypto.h> | |
| #include <ipxe/sha256.h> | |
| #include <ipxe/x509.h> | |
| #include <ipxe/settings.h> | |
| #include <ipxe/dhcp.h> | |
| #include <ipxe/init.h> | |
| #include <ipxe/rootcert.h> | |
| /** @file | |
| * | |
| * Root certificate store | |
| * | |
| */ | |
| /** Length of a root certificate fingerprint */ | |
| #define FINGERPRINT_LEN SHA256_DIGEST_SIZE | |
| /* Allow trusted certificates to be overridden if not explicitly specified */ | |
| #ifndef ALLOW_TRUST_OVERRIDE | |
| #ifdef TRUSTED | |
| #define ALLOW_TRUST_OVERRIDE 0 | |
| #else | |
| #define ALLOW_TRUST_OVERRIDE 1 | |
| #endif | |
| #endif | |
| /* Use iPXE root CA if no trusted certificates are explicitly specified */ | |
| #ifndef TRUSTED | |
| #define TRUSTED \ | |
| /* iPXE root CA */ \ | |
| 0x9f, 0xaf, 0x71, 0x7b, 0x7f, 0x8c, 0xa2, 0xf9, 0x3c, 0x25, \ | |
| 0x6c, 0x79, 0xf8, 0xac, 0x55, 0x91, 0x89, 0x5d, 0x66, 0xd1, \ | |
| 0xff, 0x3b, 0xee, 0x63, 0x97, 0xa7, 0x0d, 0x29, 0xc6, 0x5e, \ | |
| 0xed, 0x1a, | |
| #endif | |
| /** Flag indicating if root of trust may be overridden at runtime */ | |
| const int allow_trust_override = ALLOW_TRUST_OVERRIDE; | |
| /** Root certificate fingerprints */ | |
| static const uint8_t fingerprints[] = { TRUSTED }; | |
| /** Root certificate fingerprint setting */ | |
| static struct setting trust_setting __setting ( SETTING_CRYPTO, trust ) = { | |
| .name = "trust", | |
| .description = "Trusted root certificate fingerprints", | |
| .tag = DHCP_EB_TRUST, | |
| .type = &setting_type_hex, | |
| }; | |
| /** Root certificates */ | |
| struct x509_root root_certificates = { | |
| .refcnt = REF_INIT ( ref_no_free ), | |
| .digest = &sha256_algorithm, | |
| .count = ( sizeof ( fingerprints ) / FINGERPRINT_LEN ), | |
| .fingerprints = fingerprints, | |
| }; | |
| /** | |
| * Initialise root certificate | |
| * | |
| * The list of trusted root certificates can be specified at build | |
| * time using the TRUST= build parameter. If no certificates are | |
| * specified, then the default iPXE root CA certificate is trusted. | |
| * | |
| * 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. | |
| */ | |
| static void rootcert_init ( void ) { | |
| static int initialised; | |
| 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 ) ) { | |
| /* Fetch copy of "trust" setting, if it exists. This | |
| * memory will never be freed. | |
| */ | |
| if ( ( len = fetch_raw_setting_copy ( NULL, &trust_setting, | |
| &external ) ) >= 0 ) { | |
| 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" )); | |
| DBGC_HDA ( &root_certificates, 0, root_certificates.fingerprints, | |
| ( root_certificates.count * FINGERPRINT_LEN ) ); | |
| } | |
| /** Root certificate initialiser */ | |
| struct startup_fn rootcert_startup_fn __startup_fn ( STARTUP_LATE ) = { | |
| .name = "rootcert", | |
| .startup = rootcert_init, | |
| }; |