mirror of https://github.com/ipxe/ipxe.git
[crypto] Add x509_truncate() to truncate a certificate chain
Downloading a cross-signed certificate chain to partially replace (rather than simply extend) an existing chain will require the ability to discard all certificates after a specified link in the chain. Extract the relevant logic from x509_free_chain() and expose it separately as x509_truncate(). Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/154/merge
parent
e10dfe5dc7
commit
3e721e0c08
|
@ -1603,19 +1603,12 @@ int x509_check_name ( struct x509_certificate *cert, const char *name ) {
|
||||||
static void x509_free_chain ( struct refcnt *refcnt ) {
|
static void x509_free_chain ( struct refcnt *refcnt ) {
|
||||||
struct x509_chain *chain =
|
struct x509_chain *chain =
|
||||||
container_of ( refcnt, struct x509_chain, refcnt );
|
container_of ( refcnt, struct x509_chain, refcnt );
|
||||||
struct x509_link *link;
|
|
||||||
struct x509_link *tmp;
|
|
||||||
|
|
||||||
DBGC2 ( chain, "X509 chain %p freed\n", chain );
|
DBGC2 ( chain, "X509 chain %p freed\n", chain );
|
||||||
|
|
||||||
/* Free each link in the chain */
|
|
||||||
list_for_each_entry_safe ( link, tmp, &chain->links, list ) {
|
|
||||||
x509_put ( link->cert );
|
|
||||||
list_del ( &link->list );
|
|
||||||
free ( link );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free chain */
|
/* Free chain */
|
||||||
|
x509_truncate ( chain, NULL );
|
||||||
|
assert ( list_empty ( &chain->links ) );
|
||||||
free ( chain );
|
free ( chain );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1696,6 +1689,27 @@ int x509_append_raw ( struct x509_chain *chain, const void *data,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Truncate X.509 certificate chain
|
||||||
|
*
|
||||||
|
* @v chain X.509 certificate chain
|
||||||
|
* @v link Link after which to truncate chain, or NULL
|
||||||
|
*/
|
||||||
|
void x509_truncate ( struct x509_chain *chain, struct x509_link *link ) {
|
||||||
|
struct x509_link *tmp;
|
||||||
|
|
||||||
|
/* Truncate entire chain if no link is specified */
|
||||||
|
if ( ! link )
|
||||||
|
link = list_entry ( &chain->links, struct x509_link, list );
|
||||||
|
|
||||||
|
/* Free each link in the chain */
|
||||||
|
list_for_each_entry_safe_continue ( link, tmp, &chain->links, list ) {
|
||||||
|
x509_put ( link->cert );
|
||||||
|
list_del ( &link->list );
|
||||||
|
free ( link );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identify X.509 certificate by subject
|
* Identify X.509 certificate by subject
|
||||||
*
|
*
|
||||||
|
|
|
@ -391,6 +391,7 @@ extern int x509_append ( struct x509_chain *chain,
|
||||||
struct x509_certificate *cert );
|
struct x509_certificate *cert );
|
||||||
extern int x509_append_raw ( struct x509_chain *chain, const void *data,
|
extern int x509_append_raw ( struct x509_chain *chain, const void *data,
|
||||||
size_t len );
|
size_t len );
|
||||||
|
extern void x509_truncate ( struct x509_chain *chain, struct x509_link *link );
|
||||||
extern int x509_auto_append ( struct x509_chain *chain,
|
extern int x509_auto_append ( struct x509_chain *chain,
|
||||||
struct x509_chain *certs );
|
struct x509_chain *certs );
|
||||||
extern int x509_validate_chain ( struct x509_chain *chain, time_t time,
|
extern int x509_validate_chain ( struct x509_chain *chain, time_t time,
|
||||||
|
|
|
@ -984,6 +984,7 @@ static void x509_validate_chain_fail_okx ( struct x509_test_chain *chn,
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void x509_test_exec ( void ) {
|
static void x509_test_exec ( void ) {
|
||||||
|
struct x509_link *link;
|
||||||
|
|
||||||
/* Parse all certificates */
|
/* Parse all certificates */
|
||||||
x509_certificate_ok ( &root_crt );
|
x509_certificate_ok ( &root_crt );
|
||||||
|
@ -1089,6 +1090,18 @@ static void x509_test_exec ( void ) {
|
||||||
x509_validate_chain_fail_ok ( &useless_chain, test_ca_expired,
|
x509_validate_chain_fail_ok ( &useless_chain, test_ca_expired,
|
||||||
&empty_store, &test_root );
|
&empty_store, &test_root );
|
||||||
|
|
||||||
|
/* Check chain truncation */
|
||||||
|
link = list_last_entry ( &server_chain.chain->links,
|
||||||
|
struct x509_link, list );
|
||||||
|
ok ( link->cert == root_crt.cert );
|
||||||
|
link = list_prev_entry ( link, &server_chain.chain->links, list );
|
||||||
|
ok ( link->cert == intermediate_crt.cert );
|
||||||
|
x509_validate_chain_ok ( &server_chain, test_time,
|
||||||
|
&empty_store, &test_root );
|
||||||
|
x509_truncate ( server_chain.chain, link );
|
||||||
|
x509_validate_chain_fail_ok ( &server_chain, test_time,
|
||||||
|
&empty_store, &test_root );
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
assert ( list_empty ( &empty_store.links ) );
|
assert ( list_empty ( &empty_store.links ) );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue