]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Add x509_auto_append()
authorMichael Brown <mcb30@ipxe.org>
Tue, 8 May 2012 10:12:09 +0000 (11:12 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 8 May 2012 11:49:01 +0000 (12:49 +0100)
CMS includes an unordered certificate set, from which certificates
must be extracted in order by matching up issuers with subjects.  We
will use the same functionality as part of the automatic download of
cross-signing certificates.  Generalise cms_find_subject() to
x509_find_subject(), and create x509_auto_append().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/crypto/cms.c
src/crypto/x509.c
src/include/ipxe/x509.h

index 9198d03e4240e9c096a70c24de2383d776416f2e..18e59bfba9d0e9773d0064402c83293e2b40500d 100644 (file)
@@ -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 );
-
-               /* Locate next certificate in chain, if any */
-               previous = cert;
-               cert = cms_find_subject ( sig, &cert->issuer.raw );
+       /* 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;
+       }
 
-       } 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;
 }
index c83cd277778d91904852baeb30abe010a0b25bcf..191ed4125787991b0fcbefc0889f152cbe1a3274 100644 (file)
@@ -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
  *
index 78b180c995152593e14758059867da2c4fa34c86..8753bb050248aa4fb9a047cbf2988c47a14decf8 100644 (file)
@@ -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 );