diff --git a/src/crypto/cms.c b/src/crypto/cms.c index 9198d03e..18e59bfb 100644 --- a/src/crypto/cms.c +++ b/src/crypto/cms.c @@ -175,31 +175,6 @@ cms_find_issuer_serial ( struct cms_signature *sig, return NULL; } -/** - * Identify CMS signature certificate by subject - * - * @v sig CMS signature - * @v subject Subject - * @ret cert X.509 certificate, or NULL if not found - */ -static struct x509_certificate * -cms_find_subject ( struct cms_signature *sig, - const struct asn1_cursor *subject ) { - struct x509_link *link; - struct x509_certificate *cert; - - /* Scan through certificate list */ - list_for_each_entry ( link, &sig->certificates->links, list ) { - - /* Check subject */ - cert = link->cert; - if ( asn1_compare ( subject, &cert->subject.raw ) == 0 ) - return cert; - } - - return NULL; -} - /** * Parse CMS signature signer identifier * @@ -215,7 +190,6 @@ static int cms_parse_signer_identifier ( struct cms_signature *sig, struct asn1_cursor serial; struct asn1_cursor issuer; struct x509_certificate *cert; - struct x509_certificate *previous; int rc; /* Enter issuerAndSerialNumber */ @@ -253,22 +227,20 @@ static int cms_parse_signer_identifier ( struct cms_signature *sig, return -ENOENT; } - /* Create certificate chain */ - do { - /* Add certificate to chain */ - if ( ( rc = x509_append ( info->chain, cert ) ) != 0 ) { - DBGC ( sig, "CMS %p/%p could not append certificate: " - "%s\n", sig, info, strerror ( rc ) ); - return rc; - } - DBGC ( sig, "CMS %p/%p added certificate %s\n", - sig, info, cert->subject.name ); + /* Append certificate to chain */ + if ( ( rc = x509_append ( info->chain, cert ) ) != 0 ) { + DBGC ( sig, "CMS %p/%p could not append certificate: %s\n", + sig, info, strerror ( rc ) ); + return rc; + } - /* Locate next certificate in chain, if any */ - previous = cert; - cert = cms_find_subject ( sig, &cert->issuer.raw ); - - } while ( ( cert != NULL ) && ( cert != previous ) ); + /* Append remaining certificates to chain */ + if ( ( rc = x509_auto_append ( info->chain, + sig->certificates ) ) != 0 ) { + DBGC ( sig, "CMS %p/%p could not append certificates: %s\n", + sig, info, strerror ( rc ) ); + return rc; + } return 0; } diff --git a/src/crypto/x509.c b/src/crypto/x509.c index c83cd277..191ed412 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -1678,6 +1678,72 @@ int x509_append_raw ( struct x509_chain *chain, const void *data, return rc; } +/** + * Identify X.509 certificate by subject + * + * @v certs X.509 certificate list + * @v subject Subject + * @ret cert X.509 certificate, or NULL if not found + */ +static struct x509_certificate * +x509_find_subject ( struct x509_chain *certs, + const struct asn1_cursor *subject ) { + struct x509_link *link; + struct x509_certificate *cert; + + /* Scan through certificate list */ + list_for_each_entry ( link, &certs->links, list ) { + + /* Check subject */ + cert = link->cert; + if ( asn1_compare ( subject, &cert->subject.raw ) == 0 ) + return cert; + } + + return NULL; +} + +/** + * Append X.509 certificates to X.509 certificate chain + * + * @v chain X.509 certificate chain + * @v certs X.509 certificate list + * @ret rc Return status code + * + * Certificates will be automatically appended to the chain based upon + * the subject and issuer names. + */ +int x509_auto_append ( struct x509_chain *chain, struct x509_chain *certs ) { + struct x509_certificate *cert; + struct x509_certificate *previous; + int rc; + + /* Get current certificate */ + cert = x509_last ( chain ); + if ( ! cert ) { + DBGC ( chain, "X509 chain %p has no certificates\n", chain ); + return -EINVAL; + } + + /* Append certificates, in order */ + while ( 1 ) { + + /* Find issuing certificate */ + previous = cert; + cert = x509_find_subject ( certs, &cert->issuer.raw ); + if ( ! cert ) + break; + if ( cert == previous ) + break; + + /* Append certificate to chain */ + if ( ( rc = x509_append ( chain, cert ) ) != 0 ) + return rc; + } + + return 0; +} + /** * Validate X.509 certificate chain * diff --git a/src/include/ipxe/x509.h b/src/include/ipxe/x509.h index 78b180c9..8753bb05 100644 --- a/src/include/ipxe/x509.h +++ b/src/include/ipxe/x509.h @@ -335,6 +335,8 @@ extern int x509_append ( struct x509_chain *chain, struct x509_certificate *cert ); extern int x509_append_raw ( struct x509_chain *chain, const void *data, size_t len ); +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, struct x509_root *root );