mirror of
https://git.ipxe.org/ipxe.git
synced 2024-11-23 18:14:37 +08:00
[crypto] Centralise mechanisms for identifying X.509 certificates
Centralise all current mechanisms for identifying an X.509 certificate (by raw content, by subject, by issuer and serial number, and by matching public key), and remove the certstore-specific and CMS-specific variants of these functions. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
parent
59e2b03e6a
commit
d85590b658
@ -69,67 +69,29 @@ static struct asn1_cursor certstore_raw[] = {
|
||||
static struct x509_certificate certstore_certs[ sizeof ( certstore_raw ) /
|
||||
sizeof ( certstore_raw[0] ) ];
|
||||
|
||||
/**
|
||||
* Mark stored certificate as most recently used
|
||||
*
|
||||
* @v certs X.509 certificate list
|
||||
* @v cert X.509 certificate
|
||||
*/
|
||||
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, &certs->links );
|
||||
DBGC2 ( certs, "CERTSTORE found certificate %s\n",
|
||||
x509_name ( cert ) );
|
||||
}
|
||||
|
||||
/** Certificate store */
|
||||
struct x509_chain certstore = {
|
||||
.refcnt = REF_INIT ( ref_no_free ),
|
||||
.links = LIST_HEAD_INIT ( certstore.links ),
|
||||
.found = certstore_found,
|
||||
};
|
||||
|
||||
/**
|
||||
* Mark stored certificate as most recently used
|
||||
*
|
||||
* @v cert X.509 certificate
|
||||
* @ret cert X.509 certificate
|
||||
*/
|
||||
static struct x509_certificate *
|
||||
certstore_found ( 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",
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
@ -143,34 +143,6 @@ static int cms_parse_certificates ( struct cms_signature *sig,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
@ -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 );
|
||||
|
@ -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 );
|
||||
@ -1710,6 +1711,47 @@ 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
|
||||
*
|
||||
@ -1717,7 +1759,7 @@ void x509_truncate ( struct x509_chain *chain, struct x509_link *link ) {
|
||||
* @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;
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 );
|
||||
|
Loading…
Reference in New Issue
Block a user