static void x509_free_chain ( struct refcnt *refcnt ) {
struct x509_chain *chain =
container_of ( refcnt, struct x509_chain, refcnt );
- struct x509_link *link;
- struct x509_link *tmp;
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 */
+ x509_truncate ( chain, NULL );
+ assert ( list_empty ( &chain->links ) );
free ( chain );
}
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
*
struct x509_certificate *cert );
extern int x509_append_raw ( struct x509_chain *chain, const void *data,
size_t len );
+extern void x509_truncate ( struct x509_chain *chain, struct x509_link *link );
extern int x509_auto_append ( struct x509_chain *chain,
struct x509_chain *certs );
extern int x509_validate_chain ( struct x509_chain *chain, time_t time,
*
*/
static void x509_test_exec ( void ) {
+ struct x509_link *link;
/* Parse all certificates */
x509_certificate_ok ( &root_crt );
x509_validate_chain_fail_ok ( &useless_chain, test_ca_expired,
&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 */
assert ( list_empty ( &empty_store.links ) );