mirror of
https://github.com/ipxe/ipxe
synced 2025-12-12 23:15:10 +03:00
[crypto] Generalise X.509 cache to a full certificate store
Expand the concept of the X.509 cache to provide the functionality of a certificate store. Certificates in the store will be automatically used to complete certificate chains where applicable. The certificate store may be prepopulated at build time using the CERT=... build command line option. For example: make bin/ipxe.usb CERT=mycert1.crt,mycert2.crt Certificates within the certificate store are not implicitly trusted; the trust list is specified using TRUST=... as before. For example: make bin/ipxe.usb CERT=root.crt TRUST=root.crt This can be used to embed the full trusted root certificate within the iPXE binary, which is potentially useful in an HTTPS-only environment in which there is no HTTP server from which to automatically download cross-signed certificates or other certificate chain fragments. This usage of CERT= extends the existing use of CERT= to specify the client certificate. The client certificate is now identified automatically by checking for a match against the private key. For example: make bin/ipxe.usb CERT=root.crt,client.crt TRUST=root.crt KEY=client.key Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -1305,7 +1305,13 @@ static uint8_t root_crt_fingerprint[] =
|
||||
0x96, 0xe7, 0xa8, 0x6d, 0x63, 0x2d, 0x32, 0x38,
|
||||
0xaf, 0x00, 0xc4, 0x1a, 0xfc, 0xd8, 0xac, 0xc3 );
|
||||
|
||||
/** Certificate store containing the iPXE self-test root CA */
|
||||
/** Empty certificate store */
|
||||
static struct x509_chain empty_store = {
|
||||
.refcnt = REF_INIT ( ref_no_free ),
|
||||
.links = LIST_HEAD_INIT ( empty_store.links ),
|
||||
};
|
||||
|
||||
/** Root certificate list containing the iPXE self-test root CA */
|
||||
static struct x509_root test_root = {
|
||||
.digest = &cms_test_algorithm,
|
||||
.count = 1,
|
||||
@@ -1349,12 +1355,13 @@ static time_t test_expired = 1375573111ULL; /* Sat Aug 3 23:38:31 2013 */
|
||||
* @v code Test signed code
|
||||
* @v name Test verification name
|
||||
* @v time Test verification time
|
||||
* @v root Test root certificate store
|
||||
* @v store Test certificate store
|
||||
* @v root Test root certificate list
|
||||
*/
|
||||
#define cms_verify_ok( sgn, code, name, time, root ) do { \
|
||||
#define cms_verify_ok( sgn, code, name, time, store, root ) do { \
|
||||
x509_invalidate_chain ( (sgn)->sig->certificates ); \
|
||||
ok ( cms_verify ( (sgn)->sig, virt_to_user ( (code)->data ), \
|
||||
(code)->len, name, time, root ) == 0 ); \
|
||||
(code)->len, name, time, store, root ) == 0 );\
|
||||
} while ( 0 )
|
||||
|
||||
/**
|
||||
@@ -1364,12 +1371,13 @@ static time_t test_expired = 1375573111ULL; /* Sat Aug 3 23:38:31 2013 */
|
||||
* @v code Test signed code
|
||||
* @v name Test verification name
|
||||
* @v time Test verification time
|
||||
* @v root Test root certificate store
|
||||
* @v store Test certificate store
|
||||
* @v root Test root certificate list
|
||||
*/
|
||||
#define cms_verify_fail_ok( sgn, code, name, time, root ) do { \
|
||||
#define cms_verify_fail_ok( sgn, code, name, time, store, root ) do { \
|
||||
x509_invalidate_chain ( (sgn)->sig->certificates ); \
|
||||
ok ( cms_verify ( (sgn)->sig, virt_to_user ( (code)->data ), \
|
||||
(code)->len, name, time, root ) != 0 ); \
|
||||
(code)->len, name, time, store, root ) != 0 );\
|
||||
} while ( 0 )
|
||||
|
||||
/**
|
||||
@@ -1385,38 +1393,42 @@ static void cms_test_exec ( void ) {
|
||||
cms_signature_ok ( &nonsigned_sig );
|
||||
|
||||
/* Check good signature */
|
||||
cms_verify_ok ( &codesigned_sig, &test_code, "codesign.test.ipxe.org",
|
||||
test_time, &empty_store, &test_root );
|
||||
cms_verify_ok ( &codesigned_sig, &test_code,
|
||||
"codesign.test.ipxe.org", test_time, &test_root );
|
||||
cms_verify_ok ( &codesigned_sig, &test_code,
|
||||
NULL, test_time, &test_root );
|
||||
NULL, test_time, &empty_store, &test_root );
|
||||
|
||||
/* Check incorrect signer name */
|
||||
cms_verify_fail_ok ( &codesigned_sig, &test_code,
|
||||
"wrongname.test.ipxe.org", test_time, &test_root );
|
||||
"wrongname.test.ipxe.org", test_time,
|
||||
&empty_store, &test_root );
|
||||
|
||||
/* Check non-code-signing certificate */
|
||||
cms_verify_fail_ok ( &genericsigned_sig, &test_code,
|
||||
NULL, test_time, &test_root );
|
||||
NULL, test_time, &empty_store, &test_root );
|
||||
|
||||
/* Check non-signing certificate */
|
||||
cms_verify_fail_ok ( &nonsigned_sig, &test_code,
|
||||
NULL, test_time, &test_root );
|
||||
NULL, test_time, &empty_store, &test_root );
|
||||
|
||||
/* Check broken chain */
|
||||
cms_verify_fail_ok ( &brokenchain_sig, &test_code,
|
||||
NULL, test_time, &test_root );
|
||||
NULL, test_time, &empty_store, &test_root );
|
||||
|
||||
/* Check untrusted signature */
|
||||
cms_verify_fail_ok ( &codesigned_sig, &test_code,
|
||||
NULL, test_time, &dummy_root );
|
||||
NULL, test_time, &empty_store, &dummy_root );
|
||||
|
||||
/* Check incorrect signed content */
|
||||
cms_verify_fail_ok ( &codesigned_sig, &bad_code,
|
||||
NULL, test_time, &test_root );
|
||||
NULL, test_time, &empty_store, &test_root );
|
||||
|
||||
/* Check expired signature */
|
||||
cms_verify_fail_ok ( &codesigned_sig, &test_code,
|
||||
NULL, test_expired, &test_root );
|
||||
NULL, test_expired, &empty_store, &test_root );
|
||||
|
||||
/* Sanity check */
|
||||
assert ( list_empty ( &empty_store.links ) );
|
||||
|
||||
/* Drop signature references */
|
||||
cms_put ( nonsigned_sig.sig );
|
||||
|
||||
@@ -654,14 +654,20 @@ CHAIN ( useless_chain, &useless_crt, &leaf_crt, &intermediate_crt, &root_crt );
|
||||
CHAIN ( bad_path_len_chain, &bad_path_len_crt, &useless_crt, &leaf_crt,
|
||||
&intermediate_crt, &root_crt );
|
||||
|
||||
/** Certificate store containing the iPXE self-test root CA */
|
||||
/** Empty certificate store */
|
||||
static struct x509_chain empty_store = {
|
||||
.refcnt = REF_INIT ( ref_no_free ),
|
||||
.links = LIST_HEAD_INIT ( empty_store.links ),
|
||||
};
|
||||
|
||||
/** Root certificate list containing the iPXE self-test root CA */
|
||||
static struct x509_root test_root = {
|
||||
.digest = &x509_test_algorithm,
|
||||
.count = 1,
|
||||
.fingerprints = root_crt_fingerprint,
|
||||
};
|
||||
|
||||
/** Certificate store containing the iPXE self-test intermediate CA */
|
||||
/** Root certificate list containing the iPXE self-test intermediate CA */
|
||||
static struct x509_root intermediate_root = {
|
||||
.digest = &x509_test_algorithm,
|
||||
.count = 1,
|
||||
@@ -813,12 +819,13 @@ static time_t test_ca_expired = 2205014905ULL; /* Wed Nov 16 00:08:25 2039 */
|
||||
*
|
||||
* @v chn Test certificate chain
|
||||
* @v time Test certificate validation time
|
||||
* @v root Test root certificate store
|
||||
* @v store Test certificate store
|
||||
* @v root Test root certificate list
|
||||
*/
|
||||
#define x509_validate_chain_ok( chn, time, root ) do { \
|
||||
#define x509_validate_chain_ok( chn, time, store, root ) do { \
|
||||
x509_invalidate_chain ( (chn)->chain ); \
|
||||
ok ( x509_validate_chain ( (chn)->chain, (time), \
|
||||
(root) ) == 0 ); \
|
||||
(store), (root) ) == 0 ); \
|
||||
} while ( 0 )
|
||||
|
||||
/**
|
||||
@@ -826,12 +833,13 @@ static time_t test_ca_expired = 2205014905ULL; /* Wed Nov 16 00:08:25 2039 */
|
||||
*
|
||||
* @v chn Test certificate chain
|
||||
* @v time Test certificate validation time
|
||||
* @v root Test root certificate store
|
||||
* @v store Test certificate store
|
||||
* @v root Test root certificate list
|
||||
*/
|
||||
#define x509_validate_chain_fail_ok( chn, time, root ) do { \
|
||||
#define x509_validate_chain_fail_ok( chn, time, store, root ) do { \
|
||||
x509_invalidate_chain ( (chn)->chain ); \
|
||||
ok ( x509_validate_chain ( (chn)->chain, (time), \
|
||||
(root) ) != 0 ); \
|
||||
(store), (root) ) != 0 ); \
|
||||
} while ( 0 )
|
||||
|
||||
/**
|
||||
@@ -898,25 +906,35 @@ static void x509_test_exec ( void ) {
|
||||
x509_chain_ok ( &bad_path_len_chain );
|
||||
|
||||
/* Check certificate chains */
|
||||
x509_validate_chain_ok ( &server_chain, test_time, &test_root );
|
||||
x509_validate_chain_ok ( &server_chain, test_time, &intermediate_root );
|
||||
x509_validate_chain_fail_ok ( &server_chain, test_time, &dummy_root );
|
||||
x509_validate_chain_ok ( &server_chain, test_time,
|
||||
&empty_store, &test_root );
|
||||
x509_validate_chain_ok ( &server_chain, test_time,
|
||||
&empty_store, &intermediate_root );
|
||||
x509_validate_chain_fail_ok ( &server_chain, test_time,
|
||||
&empty_store, &dummy_root );
|
||||
x509_validate_chain_fail_ok ( &broken_server_chain, test_time,
|
||||
&test_root );
|
||||
&empty_store, &test_root );
|
||||
x509_validate_chain_fail_ok ( &incomplete_server_chain, test_time,
|
||||
&test_root );
|
||||
&empty_store, &test_root );
|
||||
x509_validate_chain_ok ( &incomplete_server_chain, test_time,
|
||||
&intermediate_root );
|
||||
x509_validate_chain_fail_ok ( ¬_ca_chain, test_time, &test_root );
|
||||
x509_validate_chain_ok ( &useless_chain, test_time, &test_root );
|
||||
&empty_store, &intermediate_root );
|
||||
x509_validate_chain_fail_ok ( ¬_ca_chain, test_time,
|
||||
&empty_store, &test_root );
|
||||
x509_validate_chain_ok ( &useless_chain, test_time,
|
||||
&empty_store, &test_root );
|
||||
x509_validate_chain_fail_ok ( &bad_path_len_chain, test_time,
|
||||
&test_root );
|
||||
&empty_store, &test_root );
|
||||
|
||||
/* Check certificate chain expiry times */
|
||||
x509_validate_chain_fail_ok ( &server_chain, test_expired, &test_root );
|
||||
x509_validate_chain_ok ( &useless_chain, test_expired, &test_root );
|
||||
x509_validate_chain_fail_ok ( &server_chain, test_expired,
|
||||
&empty_store, &test_root );
|
||||
x509_validate_chain_ok ( &useless_chain, test_expired,
|
||||
&empty_store, &test_root );
|
||||
x509_validate_chain_fail_ok ( &useless_chain, test_ca_expired,
|
||||
&test_root );
|
||||
&empty_store, &test_root );
|
||||
|
||||
/* Sanity check */
|
||||
assert ( list_empty ( &empty_store.links ) );
|
||||
|
||||
/* Drop chain references */
|
||||
x509_chain_put ( bad_path_len_chain.chain );
|
||||
|
||||
Reference in New Issue
Block a user