[crypto] Generalise X.509 cache to a full certificate store

Expand the concept of the X.509 cache to provide the functionality of
a certificate store.  Certificates in the store will be automatically
used to complete certificate chains where applicable.

The certificate store may be prepopulated at build time using the
CERT=... build command line option.  For example:

  make bin/ipxe.usb CERT=mycert1.crt,mycert2.crt

Certificates within the certificate store are not implicitly trusted;
the trust list is specified using TRUST=... as before.  For example:

  make bin/ipxe.usb CERT=root.crt TRUST=root.crt

This can be used to embed the full trusted root certificate within the
iPXE binary, which is potentially useful in an HTTPS-only environment
in which there is no HTTP server from which to automatically download
cross-signed certificates or other certificate chain fragments.

This usage of CERT= extends the existing use of CERT= to specify the
client certificate.  The client certificate is now identified
automatically by checking for a match against the private key.  For
example:

  make bin/ipxe.usb CERT=root.crt,client.crt TRUST=root.crt KEY=client.key

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2014-03-28 15:45:10 +00:00
parent 2dd3fffe18
commit bc8ca6b8ce
18 changed files with 640 additions and 398 deletions

View File

@@ -617,18 +617,21 @@ static int cms_verify_digest ( struct cms_signature *sig,
* @v data Signed data
* @v len Length of signed data
* @v time Time at which to validate certificates
* @v root Root certificate store, or NULL to use default
* @v store Certificate store, or NULL to use default
* @v root Root certificate list, or NULL to use default
* @ret rc Return status code
*/
static int cms_verify_signer_info ( struct cms_signature *sig,
struct cms_signer_info *info,
userptr_t data, size_t len,
time_t time, struct x509_root *root ) {
time_t time, struct x509_chain *store,
struct x509_root *root ) {
struct x509_certificate *cert;
int rc;
/* Validate certificate chain */
if ( ( rc = x509_validate_chain ( info->chain, time, root ) ) != 0 ) {
if ( ( rc = x509_validate_chain ( info->chain, time, store,
root ) ) != 0 ) {
DBGC ( sig, "CMS %p/%p could not validate chain: %s\n",
sig, info, strerror ( rc ) );
return rc;
@@ -667,11 +670,13 @@ static int cms_verify_signer_info ( struct cms_signature *sig,
* @v len Length of signed data
* @v name Required common name, or NULL to check all signatures
* @v time Time at which to validate certificates
* @v root Root certificate store, or NULL to use default
* @v store Certificate store, or NULL to use default
* @v root Root certificate list, or NULL to use default
* @ret rc Return status code
*/
int cms_verify ( struct cms_signature *sig, userptr_t data, size_t len,
const char *name, time_t time, struct x509_root *root ) {
const char *name, time_t time, struct x509_chain *store,
struct x509_root *root ) {
struct cms_signer_info *info;
struct x509_certificate *cert;
int count = 0;
@@ -682,8 +687,8 @@ int cms_verify ( struct cms_signature *sig, userptr_t data, size_t len,
cert = x509_first ( info->chain );
if ( name && ( x509_check_name ( cert, name ) != 0 ) )
continue;
if ( ( rc = cms_verify_signer_info ( sig, info, data, len,
time, root ) ) != 0 )
if ( ( rc = cms_verify_signer_info ( sig, info, data, len, time,
store, root ) ) != 0 )
return rc;
count++;
}