mirror of https://github.com/ipxe/ipxe.git
[x509] Make root of trust a reference-counted structure
Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/181/head
parent
e3eedb0be5
commit
3475f9162b
|
@ -71,6 +71,7 @@ static struct setting trust_setting __setting ( SETTING_CRYPTO, trust ) = {
|
|||
|
||||
/** Root certificates */
|
||||
struct x509_root root_certificates = {
|
||||
.refcnt = REF_INIT ( ref_no_free ),
|
||||
.digest = &sha256_algorithm,
|
||||
.count = ( sizeof ( fingerprints ) / FINGERPRINT_LEN ),
|
||||
.fingerprints = fingerprints,
|
||||
|
|
|
@ -122,6 +122,19 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
#define EINFO_EACCES_USELESS \
|
||||
__einfo_uniqify ( EINFO_EACCES, 0x0b, "No usable certificates" )
|
||||
|
||||
/**
|
||||
* Free X.509 certificate
|
||||
*
|
||||
* @v refcnt Reference count
|
||||
*/
|
||||
static void x509_free ( struct refcnt *refcnt ) {
|
||||
struct x509_certificate *cert =
|
||||
container_of ( refcnt, struct x509_certificate, refcnt );
|
||||
|
||||
x509_root_put ( cert->root );
|
||||
free ( cert );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get X.509 certificate display name
|
||||
*
|
||||
|
@ -1075,7 +1088,7 @@ int x509_certificate ( const void *data, size_t len,
|
|||
*cert = zalloc ( sizeof ( **cert ) + cursor.len );
|
||||
if ( ! *cert )
|
||||
return -ENOMEM;
|
||||
ref_init ( &(*cert)->refcnt, NULL );
|
||||
ref_init ( &(*cert)->refcnt, x509_free );
|
||||
raw = ( *cert + 1 );
|
||||
|
||||
/* Copy raw data */
|
||||
|
@ -1310,6 +1323,35 @@ int x509_is_valid ( struct x509_certificate *cert, struct x509_root *root ) {
|
|||
return ( cert->root == root );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set X.509 certificate as validated
|
||||
*
|
||||
* @v cert X.509 certificate
|
||||
* @v issuer Issuing X.509 certificate (or NULL)
|
||||
* @v root Root certificate list
|
||||
*/
|
||||
static void x509_set_valid ( struct x509_certificate *cert,
|
||||
struct x509_certificate *issuer,
|
||||
struct x509_root *root ) {
|
||||
unsigned int max_path_remaining;
|
||||
|
||||
/* Sanity checks */
|
||||
assert ( root != NULL );
|
||||
assert ( ( issuer == NULL ) || ( issuer->path_remaining >= 1 ) );
|
||||
|
||||
/* Record validation root */
|
||||
x509_root_put ( cert->root );
|
||||
cert->root = x509_root_get ( root );
|
||||
|
||||
/* Calculate effective path length */
|
||||
cert->path_remaining = ( cert->extensions.basic.path_len + 1 );
|
||||
if ( issuer ) {
|
||||
max_path_remaining = ( issuer->path_remaining - 1 );
|
||||
if ( cert->path_remaining > max_path_remaining )
|
||||
cert->path_remaining = max_path_remaining;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate X.509 certificate
|
||||
*
|
||||
|
@ -1328,7 +1370,6 @@ int x509_is_valid ( struct x509_certificate *cert, struct x509_root *root ) {
|
|||
int x509_validate ( struct x509_certificate *cert,
|
||||
struct x509_certificate *issuer,
|
||||
time_t time, struct x509_root *root ) {
|
||||
unsigned int max_path_remaining;
|
||||
int rc;
|
||||
|
||||
/* Use default root certificate store if none specified */
|
||||
|
@ -1345,8 +1386,7 @@ int x509_validate ( struct x509_certificate *cert,
|
|||
|
||||
/* Succeed if certificate is a trusted root certificate */
|
||||
if ( x509_check_root ( cert, root ) == 0 ) {
|
||||
cert->root = root;
|
||||
cert->path_remaining = ( cert->extensions.basic.path_len + 1 );
|
||||
x509_set_valid ( cert, NULL, root );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1384,14 +1424,8 @@ int x509_validate ( struct x509_certificate *cert,
|
|||
return -EACCES_OCSP_REQUIRED;
|
||||
}
|
||||
|
||||
/* Calculate effective path length */
|
||||
cert->path_remaining = ( issuer->path_remaining - 1 );
|
||||
max_path_remaining = ( cert->extensions.basic.path_len + 1 );
|
||||
if ( cert->path_remaining > max_path_remaining )
|
||||
cert->path_remaining = max_path_remaining;
|
||||
|
||||
/* Mark certificate as valid */
|
||||
cert->root = root;
|
||||
x509_set_valid ( cert, issuer, root );
|
||||
|
||||
DBGC ( cert, "X509 %p \"%s\" successfully validated using ",
|
||||
cert, x509_name ( cert ) );
|
||||
|
|
|
@ -340,8 +340,10 @@ struct x509_access_method {
|
|||
const struct asn1_cursor *raw );
|
||||
};
|
||||
|
||||
/** An X.509 root certificate store */
|
||||
/** An X.509 root certificate list */
|
||||
struct x509_root {
|
||||
/** Reference count */
|
||||
struct refcnt refcnt;
|
||||
/** Fingerprint digest algorithm */
|
||||
struct digest_algorithm *digest;
|
||||
/** Number of certificates */
|
||||
|
@ -350,6 +352,28 @@ struct x509_root {
|
|||
const void *fingerprints;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get reference to X.509 root certificate list
|
||||
*
|
||||
* @v root X.509 root certificate list
|
||||
* @ret root X.509 root certificate list
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) struct x509_root *
|
||||
x509_root_get ( struct x509_root *root ) {
|
||||
ref_get ( &root->refcnt );
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop reference to X.509 root certificate list
|
||||
*
|
||||
* @v root X.509 root certificate list
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
x509_root_put ( struct x509_root *root ) {
|
||||
ref_put ( &root->refcnt );
|
||||
}
|
||||
|
||||
extern const char * x509_name ( struct x509_certificate *cert );
|
||||
extern int x509_parse ( struct x509_certificate *cert,
|
||||
const struct asn1_cursor *raw );
|
||||
|
@ -391,6 +415,7 @@ extern int x509_check_time ( struct x509_certificate *cert, time_t time );
|
|||
* @v cert X.509 certificate
|
||||
*/
|
||||
static inline void x509_invalidate ( struct x509_certificate *cert ) {
|
||||
x509_root_put ( cert->root );
|
||||
cert->root = NULL;
|
||||
cert->path_remaining = 0;
|
||||
}
|
||||
|
|
|
@ -380,6 +380,7 @@ static void free_tls ( struct refcnt *refcnt ) {
|
|||
}
|
||||
x509_chain_put ( tls->certs );
|
||||
x509_chain_put ( tls->chain );
|
||||
x509_root_put ( tls->root );
|
||||
|
||||
/* Drop reference to session */
|
||||
assert ( list_empty ( &tls->list ) );
|
||||
|
@ -3163,7 +3164,7 @@ int add_tls ( struct interface *xfer, const char *name,
|
|||
intf_init ( &tls->validator, &tls_validator_desc, &tls->refcnt );
|
||||
process_init_stopped ( &tls->process, &tls_process_desc,
|
||||
&tls->refcnt );
|
||||
tls->root = root;
|
||||
tls->root = x509_root_get ( root );
|
||||
tls->version = TLS_VERSION_TLS_1_2;
|
||||
tls_clear_cipher ( tls, &tls->tx_cipherspec );
|
||||
tls_clear_cipher ( tls, &tls->tx_cipherspec_pending );
|
||||
|
|
|
@ -116,6 +116,7 @@ static void validator_free ( struct refcnt *refcnt ) {
|
|||
|
||||
DBGC2 ( validator, "VALIDATOR %p \"%s\" freed\n",
|
||||
validator, validator_name ( validator ) );
|
||||
x509_root_put ( validator->root );
|
||||
x509_chain_put ( validator->chain );
|
||||
ocsp_put ( validator->ocsp );
|
||||
xferbuf_free ( &validator->buffer );
|
||||
|
@ -650,7 +651,7 @@ int create_validator ( struct interface *job, struct x509_chain *chain,
|
|||
&validator->refcnt );
|
||||
process_init ( &validator->process, &validator_process_desc,
|
||||
&validator->refcnt );
|
||||
validator->root = root;
|
||||
validator->root = x509_root_get ( root );
|
||||
validator->chain = x509_chain_get ( chain );
|
||||
xferbuf_malloc_init ( &validator->buffer );
|
||||
|
||||
|
|
|
@ -1317,6 +1317,7 @@ static struct x509_chain empty_store = {
|
|||
|
||||
/** Root certificate list containing the iPXE self-test root CA */
|
||||
static struct x509_root test_root = {
|
||||
.refcnt = REF_INIT ( ref_no_free ),
|
||||
.digest = &cms_test_algorithm,
|
||||
.count = 1,
|
||||
.fingerprints = root_crt_fingerprint,
|
||||
|
@ -1331,6 +1332,7 @@ static uint8_t dummy_fingerprint[] =
|
|||
|
||||
/** Certificate store containing a dummy fingerprint */
|
||||
static struct x509_root dummy_root = {
|
||||
.refcnt = REF_INIT ( ref_no_free ),
|
||||
.digest = &cms_test_algorithm,
|
||||
.count = 1,
|
||||
.fingerprints = dummy_fingerprint,
|
||||
|
|
|
@ -674,6 +674,7 @@ static struct x509_chain empty_store = {
|
|||
|
||||
/** Root certificate list containing the iPXE self-test root CA */
|
||||
static struct x509_root test_root = {
|
||||
.refcnt = REF_INIT ( ref_no_free ),
|
||||
.digest = &x509_test_algorithm,
|
||||
.count = 1,
|
||||
.fingerprints = root_crt_fingerprint,
|
||||
|
@ -681,6 +682,7 @@ static struct x509_root test_root = {
|
|||
|
||||
/** Root certificate list containing the iPXE self-test intermediate CA */
|
||||
static struct x509_root intermediate_root = {
|
||||
.refcnt = REF_INIT ( ref_no_free ),
|
||||
.digest = &x509_test_algorithm,
|
||||
.count = 1,
|
||||
.fingerprints = intermediate_crt_fingerprint,
|
||||
|
@ -695,6 +697,7 @@ static uint8_t dummy_fingerprint[] =
|
|||
|
||||
/** Certificate store containing a dummy fingerprint */
|
||||
static struct x509_root dummy_root = {
|
||||
.refcnt = REF_INIT ( ref_no_free ),
|
||||
.digest = &x509_test_algorithm,
|
||||
.count = 1,
|
||||
.fingerprints = dummy_fingerprint,
|
||||
|
|
Loading…
Reference in New Issue