Browse Source

[crypto] Add x509_auto_append()

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>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
1a5f025ad8
3 changed files with 81 additions and 41 deletions
  1. 13
    41
      src/crypto/cms.c
  2. 66
    0
      src/crypto/x509.c
  3. 2
    0
      src/include/ipxe/x509.h

+ 13
- 41
src/crypto/cms.c View File

175
 	return NULL;
175
 	return NULL;
176
 }
176
 }
177
 
177
 
178
-/**
179
- * Identify CMS signature certificate by subject
180
- *
181
- * @v sig		CMS signature
182
- * @v subject		Subject
183
- * @ret cert		X.509 certificate, or NULL if not found
184
- */
185
-static struct x509_certificate *
186
-cms_find_subject ( struct cms_signature *sig,
187
-		   const struct asn1_cursor *subject ) {
188
-	struct x509_link *link;
189
-	struct x509_certificate *cert;
190
-
191
-	/* Scan through certificate list */
192
-	list_for_each_entry ( link, &sig->certificates->links, list ) {
193
-
194
-		/* Check subject */
195
-		cert = link->cert;
196
-		if ( asn1_compare ( subject, &cert->subject.raw ) == 0 )
197
-			return cert;
198
-	}
199
-
200
-	return NULL;
201
-}
202
-
203
 /**
178
 /**
204
  * Parse CMS signature signer identifier
179
  * Parse CMS signature signer identifier
205
  *
180
  *
215
 	struct asn1_cursor serial;
190
 	struct asn1_cursor serial;
216
 	struct asn1_cursor issuer;
191
 	struct asn1_cursor issuer;
217
 	struct x509_certificate *cert;
192
 	struct x509_certificate *cert;
218
-	struct x509_certificate *previous;
219
 	int rc;
193
 	int rc;
220
 
194
 
221
 	/* Enter issuerAndSerialNumber */
195
 	/* Enter issuerAndSerialNumber */
253
 		return -ENOENT;
227
 		return -ENOENT;
254
 	}
228
 	}
255
 
229
 
256
-	/* Create certificate chain */
257
-	do {
258
-		/* Add certificate to chain */
259
-		if ( ( rc = x509_append ( info->chain, cert ) ) != 0 ) {
260
-			DBGC ( sig, "CMS %p/%p could not append certificate: "
261
-			       "%s\n", sig, info, strerror ( rc ) );
262
-			return rc;
263
-		}
264
-		DBGC ( sig, "CMS %p/%p added certificate %s\n",
265
-		       sig, info, cert->subject.name );
266
-
267
-		/* Locate next certificate in chain, if any */
268
-		previous = cert;
269
-		cert = cms_find_subject ( sig, &cert->issuer.raw );
230
+	/* Append certificate to chain */
231
+	if ( ( rc = x509_append ( info->chain, cert ) ) != 0 ) {
232
+		DBGC ( sig, "CMS %p/%p could not append certificate: %s\n",
233
+		       sig, info, strerror ( rc ) );
234
+		return rc;
235
+	}
270
 
236
 
271
-	} while ( ( cert != NULL ) && ( cert != previous ) );
237
+	/* Append remaining certificates to chain */
238
+	if ( ( rc = x509_auto_append ( info->chain,
239
+				       sig->certificates ) ) != 0 ) {
240
+		DBGC ( sig, "CMS %p/%p could not append certificates: %s\n",
241
+		       sig, info, strerror ( rc ) );
242
+		return rc;
243
+	}
272
 
244
 
273
 	return 0;
245
 	return 0;
274
 }
246
 }

+ 66
- 0
src/crypto/x509.c View File

1678
 	return rc;
1678
 	return rc;
1679
 }
1679
 }
1680
 
1680
 
1681
+/**
1682
+ * Identify X.509 certificate by subject
1683
+ *
1684
+ * @v certs		X.509 certificate list
1685
+ * @v subject		Subject
1686
+ * @ret cert		X.509 certificate, or NULL if not found
1687
+ */
1688
+static struct x509_certificate *
1689
+x509_find_subject ( struct x509_chain *certs,
1690
+		    const struct asn1_cursor *subject ) {
1691
+	struct x509_link *link;
1692
+	struct x509_certificate *cert;
1693
+
1694
+	/* Scan through certificate list */
1695
+	list_for_each_entry ( link, &certs->links, list ) {
1696
+
1697
+		/* Check subject */
1698
+		cert = link->cert;
1699
+		if ( asn1_compare ( subject, &cert->subject.raw ) == 0 )
1700
+			return cert;
1701
+	}
1702
+
1703
+	return NULL;
1704
+}
1705
+
1706
+/**
1707
+ * Append X.509 certificates to X.509 certificate chain
1708
+ *
1709
+ * @v chain		X.509 certificate chain
1710
+ * @v certs		X.509 certificate list
1711
+ * @ret rc		Return status code
1712
+ *
1713
+ * Certificates will be automatically appended to the chain based upon
1714
+ * the subject and issuer names.
1715
+ */
1716
+int x509_auto_append ( struct x509_chain *chain, struct x509_chain *certs ) {
1717
+	struct x509_certificate *cert;
1718
+	struct x509_certificate *previous;
1719
+	int rc;
1720
+
1721
+	/* Get current certificate */
1722
+	cert = x509_last ( chain );
1723
+	if ( ! cert ) {
1724
+		DBGC ( chain, "X509 chain %p has no certificates\n", chain );
1725
+		return -EINVAL;
1726
+	}
1727
+
1728
+	/* Append certificates, in order */
1729
+	while ( 1 ) {
1730
+
1731
+		/* Find issuing certificate */
1732
+		previous = cert;
1733
+		cert = x509_find_subject ( certs, &cert->issuer.raw );
1734
+		if ( ! cert )
1735
+			break;
1736
+		if ( cert == previous )
1737
+			break;
1738
+
1739
+		/* Append certificate to chain */
1740
+		if ( ( rc = x509_append ( chain, cert ) ) != 0 )
1741
+			return rc;
1742
+	}
1743
+
1744
+	return 0;
1745
+}
1746
+
1681
 /**
1747
 /**
1682
  * Validate X.509 certificate chain
1748
  * Validate X.509 certificate chain
1683
  *
1749
  *

+ 2
- 0
src/include/ipxe/x509.h View File

335
 			 struct x509_certificate *cert );
335
 			 struct x509_certificate *cert );
336
 extern int x509_append_raw ( struct x509_chain *chain, const void *data,
336
 extern int x509_append_raw ( struct x509_chain *chain, const void *data,
337
 			     size_t len );
337
 			     size_t len );
338
+extern int x509_auto_append ( struct x509_chain *chain,
339
+			      struct x509_chain *certs );
338
 extern int x509_validate_chain ( struct x509_chain *chain, time_t time,
340
 extern int x509_validate_chain ( struct x509_chain *chain, time_t time,
339
 				 struct x509_root *root );
341
 				 struct x509_root *root );
340
 
342
 

Loading…
Cancel
Save