aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/crypto/certstore.c62
-rw-r--r--src/crypto/cms.c30
-rw-r--r--src/crypto/x509.c103
-rw-r--r--src/include/ipxe/certstore.h4
-rw-r--r--src/include/ipxe/x509.h19
-rw-r--r--src/net/tls.c2
6 files changed, 133 insertions, 87 deletions
diff --git a/src/crypto/certstore.c b/src/crypto/certstore.c
index 2676c7e1e..f8ddbd3d7 100644
--- a/src/crypto/certstore.c
+++ b/src/crypto/certstore.c
@@ -69,66 +69,28 @@ static struct asn1_cursor certstore_raw[] = {
static struct x509_certificate certstore_certs[ sizeof ( certstore_raw ) /
sizeof ( certstore_raw[0] ) ];
-/** Certificate store */
-struct x509_chain certstore = {
- .refcnt = REF_INIT ( ref_no_free ),
- .links = LIST_HEAD_INIT ( certstore.links ),
-};
-
/**
* Mark stored certificate as most recently used
*
+ * @v certs X.509 certificate list
* @v cert X.509 certificate
- * @ret cert X.509 certificate
*/
-static struct x509_certificate *
-certstore_found ( struct x509_certificate *cert ) {
+static void certstore_found ( struct x509_chain *certs,
+ struct x509_certificate *cert ) {
/* Mark as most recently used */
list_del ( &cert->store.list );
- list_add ( &cert->store.list, &certstore.links );
- DBGC2 ( &certstore, "CERTSTORE found certificate %s\n",
+ list_add ( &cert->store.list, &certs->links );
+ DBGC2 ( certs, "CERTSTORE found certificate %s\n",
x509_name ( cert ) );
-
- return cert;
-}
-
-/**
- * Find certificate in store
- *
- * @v raw Raw certificate data
- * @ret cert X.509 certificate, or NULL if not found
- */
-struct x509_certificate * certstore_find ( struct asn1_cursor *raw ) {
- struct x509_certificate *cert;
-
- /* Search for certificate within store */
- list_for_each_entry ( cert, &certstore.links, store.list ) {
- if ( asn1_compare ( raw, &cert->raw ) == 0 )
- return certstore_found ( cert );
- }
- return NULL;
}
-/**
- * Find certificate in store corresponding to a private key
- *
- * @v key Private key
- * @ret cert X.509 certificate, or NULL if not found
- */
-struct x509_certificate * certstore_find_key ( struct private_key *key ) {
- struct x509_certificate *cert;
-
- /* Search for certificate within store */
- list_for_each_entry ( cert, &certstore.links, store.list ) {
- if ( pubkey_match ( cert->signature_algorithm->pubkey,
- key->builder.data, key->builder.len,
- cert->subject.public_key.raw.data,
- cert->subject.public_key.raw.len ) == 0 )
- return certstore_found ( cert );
- }
- return NULL;
-}
+/** Certificate store */
+struct x509_chain certstore = {
+ .refcnt = REF_INIT ( ref_no_free ),
+ .links = LIST_HEAD_INIT ( certstore.links ),
+ .found = certstore_found,
+};
/**
* Add certificate to store
@@ -219,7 +181,7 @@ static void certstore_init ( void ) {
/* Skip if certificate already present in store */
raw = &certstore_raw[i];
- if ( ( cert = certstore_find ( raw ) ) != NULL ) {
+ if ( ( cert = x509_find ( &certstore, raw ) ) != NULL ) {
DBGC ( &certstore, "CERTSTORE permanent certificate %d "
"is a duplicate of %s\n", i, x509_name ( cert ));
continue;
diff --git a/src/crypto/cms.c b/src/crypto/cms.c
index 9511cec8a..19a0ce7ad 100644
--- a/src/crypto/cms.c
+++ b/src/crypto/cms.c
@@ -144,34 +144,6 @@ static int cms_parse_certificates ( struct cms_signature *sig,
}
/**
- * Identify CMS signature certificate by issuer and serial number
- *
- * @v sig CMS signature
- * @v issuer Issuer
- * @v serial Serial number
- * @ret cert X.509 certificate, or NULL if not found
- */
-static struct x509_certificate *
-cms_find_issuer_serial ( struct cms_signature *sig,
- const struct asn1_cursor *issuer,
- const struct asn1_cursor *serial ) {
- struct x509_link *link;
- struct x509_certificate *cert;
-
- /* Scan through certificate list */
- list_for_each_entry ( link, &sig->certificates->links, list ) {
-
- /* Check issuer and serial number */
- cert = link->cert;
- if ( ( asn1_compare ( issuer, &cert->issuer.raw ) == 0 ) &&
- ( asn1_compare ( serial, &cert->serial.raw ) == 0 ) )
- return cert;
- }
-
- return NULL;
-}
-
-/**
* Parse CMS signature signer identifier
*
* @v sig CMS signature
@@ -216,7 +188,7 @@ static int cms_parse_signer_identifier ( struct cms_signature *sig,
DBGC_HDA ( sig, 0, serial.data, serial.len );
/* Identify certificate */
- cert = cms_find_issuer_serial ( sig, &issuer, &serial );
+ cert = x509_find_issuer_serial ( sig->certificates, &issuer, &serial );
if ( ! cert ) {
DBGC ( sig, "CMS %p/%p could not identify signer's "
"certificate\n", sig, info );
diff --git a/src/crypto/x509.c b/src/crypto/x509.c
index 92318093e..341b91449 100644
--- a/src/crypto/x509.c
+++ b/src/crypto/x509.c
@@ -38,6 +38,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/rsa.h>
#include <ipxe/rootcert.h>
#include <ipxe/certstore.h>
+#include <ipxe/privkey.h>
#include <ipxe/socket.h>
#include <ipxe/in.h>
#include <ipxe/image.h>
@@ -1078,7 +1079,7 @@ int x509_certificate ( const void *data, size_t len,
asn1_shrink_any ( &cursor );
/* Return stored certificate, if present */
- if ( ( *cert = certstore_find ( &cursor ) ) != NULL ) {
+ if ( ( *cert = x509_find ( &certstore, &cursor ) ) != NULL ) {
/* Add caller's reference */
x509_get ( *cert );
@@ -1711,13 +1712,54 @@ void x509_truncate ( struct x509_chain *chain, struct x509_link *link ) {
}
/**
+ * Mark X.509 certificate as found
+ *
+ * @v certs X.509 certificate list
+ * @v cert X.509 certificate
+ * @ret cert X.509 certificate
+ */
+static struct x509_certificate * x509_found ( struct x509_chain *certs,
+ struct x509_certificate *cert ) {
+
+ /* Mark as found, if applicable */
+ if ( certs->found )
+ certs->found ( certs, cert );
+
+ return cert;
+}
+
+/**
+ * Identify X.509 certificate by raw certificate data
+ *
+ * @v certs X.509 certificate list
+ * @v raw Raw certificate data
+ * @ret cert X.509 certificate, or NULL if not found
+ */
+struct x509_certificate * x509_find ( struct x509_chain *certs,
+ const struct asn1_cursor *raw ) {
+ struct x509_link *link;
+ struct x509_certificate *cert;
+
+ /* Search for certificate within store */
+ list_for_each_entry ( link, &certs->links, list ) {
+
+ /* Check raw certificate data */
+ cert = link->cert;
+ if ( asn1_compare ( raw, &cert->raw ) == 0 )
+ return x509_found ( certs, cert );
+ }
+
+ return NULL;
+}
+
+/**
* 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 *
+struct x509_certificate *
x509_find_subject ( struct x509_chain *certs,
const struct asn1_cursor *subject ) {
struct x509_link *link;
@@ -1729,7 +1771,62 @@ x509_find_subject ( struct x509_chain *certs,
/* Check subject */
cert = link->cert;
if ( asn1_compare ( subject, &cert->subject.raw ) == 0 )
- return cert;
+ return x509_found ( certs, cert );
+ }
+
+ return NULL;
+}
+
+/**
+ * Identify X.509 certificate by issuer and serial number
+ *
+ * @v certs X.509 certificate list
+ * @v issuer Issuer
+ * @v serial Serial number
+ * @ret cert X.509 certificate, or NULL if not found
+ */
+struct x509_certificate *
+x509_find_issuer_serial ( struct x509_chain *certs,
+ const struct asn1_cursor *issuer,
+ const struct asn1_cursor *serial ) {
+ struct x509_link *link;
+ struct x509_certificate *cert;
+
+ /* Scan through certificate list */
+ list_for_each_entry ( link, &certs->links, list ) {
+
+ /* Check issuer and serial number */
+ cert = link->cert;
+ if ( ( asn1_compare ( issuer, &cert->issuer.raw ) == 0 ) &&
+ ( asn1_compare ( serial, &cert->serial.raw ) == 0 ) )
+ return x509_found ( certs, cert );
+ }
+
+ return NULL;
+}
+
+/**
+ * Identify X.509 certificate by corresponding public key
+ *
+ * @v certs X.509 certificate list
+ * @v key Private key
+ * @ret cert X.509 certificate, or NULL if not found
+ */
+struct x509_certificate * x509_find_key ( struct x509_chain *certs,
+ struct private_key *key ) {
+ struct x509_link *link;
+ struct x509_certificate *cert;
+
+ /* Scan through certificate list */
+ list_for_each_entry ( link, &certs->links, list ) {
+
+ /* Check public key */
+ cert = link->cert;
+ if ( pubkey_match ( cert->signature_algorithm->pubkey,
+ key->builder.data, key->builder.len,
+ cert->subject.public_key.raw.data,
+ cert->subject.public_key.raw.len ) == 0 )
+ return x509_found ( certs, cert );
}
return NULL;
diff --git a/src/include/ipxe/certstore.h b/src/include/ipxe/certstore.h
index ce96666cf..e276d6792 100644
--- a/src/include/ipxe/certstore.h
+++ b/src/include/ipxe/certstore.h
@@ -9,14 +9,10 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-#include <ipxe/asn1.h>
#include <ipxe/x509.h>
-#include <ipxe/privkey.h>
extern struct x509_chain certstore;
-extern struct x509_certificate * certstore_find ( struct asn1_cursor *raw );
-extern struct x509_certificate * certstore_find_key ( struct private_key *key );
extern void certstore_add ( struct x509_certificate *cert );
extern void certstore_del ( struct x509_certificate *cert );
diff --git a/src/include/ipxe/x509.h b/src/include/ipxe/x509.h
index 87323cec0..612743a77 100644
--- a/src/include/ipxe/x509.h
+++ b/src/include/ipxe/x509.h
@@ -17,6 +17,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/list.h>
struct image;
+struct private_key;
/** An X.509 serial number */
struct x509_serial {
@@ -201,6 +202,13 @@ struct x509_chain {
struct refcnt refcnt;
/** List of links */
struct list_head links;
+ /** Mark certificate as found
+ *
+ * @v certs X.509 certificate list
+ * @v cert X.509 certificate
+ */
+ void ( * found ) ( struct x509_chain *certs,
+ struct x509_certificate *cert );
};
/** An X.509 certificate */
@@ -424,6 +432,17 @@ extern int x509_append ( struct x509_chain *chain,
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 struct x509_certificate * x509_find ( struct x509_chain *certs,
+ const struct asn1_cursor *raw );
+extern struct x509_certificate *
+x509_find_subject ( struct x509_chain *certs,
+ const struct asn1_cursor *subject );
+extern struct x509_certificate *
+x509_find_issuer_serial ( struct x509_chain *certs,
+ const struct asn1_cursor *issuer,
+ const struct asn1_cursor *serial );
+extern struct x509_certificate * x509_find_key ( struct x509_chain *certs,
+ struct private_key *key );
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,
diff --git a/src/net/tls.c b/src/net/tls.c
index 5f89be452..98414e2b1 100644
--- a/src/net/tls.c
+++ b/src/net/tls.c
@@ -2467,7 +2467,7 @@ static int tls_new_certificate_request ( struct tls_connection *tls,
tls->certs = NULL;
/* Determine client certificate to be sent */
- cert = certstore_find_key ( tls->key );
+ cert = x509_find_key ( &certstore, tls->key );
if ( ! cert ) {
DBGC ( tls, "TLS %p could not find certificate corresponding "
"to private key\n", tls );