[crypto] Allow certificate chains to be long-lived data structures

At present, certificate chain validation is treated as an
instantaneous process that can be carried out using only data that is
already in memory.  This model does not allow for validation to
include non-instantaneous steps, such as downloading a cross-signing
certificate, or determining certificate revocation status via OCSP.

Redesign the internal representation of certificate chains to allow
chains to outlive the scope of the original source of certificates
(such as a TLS Certificate record).

Allow for certificates to be cached, so that each certificate needs to
be validated only once.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2012-05-04 17:12:32 +01:00
parent 6ed905aba2
commit 557f467bab
9 changed files with 1088 additions and 476 deletions

View File

@@ -52,6 +52,9 @@ struct cms_test_signature {
const void *data;
/** Length of data */
size_t len;
/** Parsed signature */
struct cms_signature *sig;
};
/** Define inline data */
@@ -1331,42 +1334,40 @@ static time_t test_expired = 1375573111ULL; /* Sat Aug 3 23:38:31 2013 */
/**
* Report signature parsing test result
*
* @v sig Test signature
* @v sgn Test signature
*/
#define cms_parse_ok( sig ) do { \
struct cms_signature temp; \
ok ( cms_parse ( &temp, (sig)->data, (sig)->len ) == 0 ); \
#define cms_signature_ok( sgn ) do { \
ok ( cms_signature ( (sgn)->data, (sgn)->len, \
&(sgn)->sig ) == 0 ); \
} while ( 0 )
/**
* Report signature verification test result
*
* @v sig Test signature
* @v sgn Test signature
* @v code Test signed code
* @v name Test verification name
* @v time Test verification time
* @v root Test root certificate store
*/
#define cms_verify_ok( sig, code, name, time, root ) do { \
struct cms_signature temp; \
ok ( cms_parse ( &temp, (sig)->data, (sig)->len ) == 0 ); \
ok ( cms_verify ( &temp, virt_to_user ( (code)->data ), \
#define cms_verify_ok( sgn, code, name, time, root ) do { \
x509_invalidate_chain ( (sgn)->sig->certificates ); \
ok ( cms_verify ( (sgn)->sig, virt_to_user ( (code)->data ), \
(code)->len, name, time, root ) == 0 ); \
} while ( 0 )
/**
* Report signature verification failure test result
*
* @v sig Test signature
* @v sgn Test signature
* @v code Test signed code
* @v name Test verification name
* @v time Test verification time
* @v root Test root certificate store
*/
#define cms_verify_fail_ok( sig, code, name, time, root ) do { \
struct cms_signature temp; \
ok ( cms_parse ( &temp, (sig)->data, (sig)->len ) == 0 ); \
ok ( cms_verify ( &temp, virt_to_user ( (code)->data ), \
#define cms_verify_fail_ok( sgn, code, name, time, root ) do { \
x509_invalidate_chain ( (sgn)->sig->certificates ); \
ok ( cms_verify ( (sgn)->sig, virt_to_user ( (code)->data ), \
(code)->len, name, time, root ) != 0 ); \
} while ( 0 )
@@ -1377,10 +1378,10 @@ static time_t test_expired = 1375573111ULL; /* Sat Aug 3 23:38:31 2013 */
static void cms_test_exec ( void ) {
/* Check that all signatures can be parsed */
cms_parse_ok ( &codesigned_sig );
cms_parse_ok ( &brokenchain_sig );
cms_parse_ok ( &genericsigned_sig );
cms_parse_ok ( &nonsigned_sig );
cms_signature_ok ( &codesigned_sig );
cms_signature_ok ( &brokenchain_sig );
cms_signature_ok ( &genericsigned_sig );
cms_signature_ok ( &nonsigned_sig );
/* Check good signature */
cms_verify_ok ( &codesigned_sig, &test_code,
@@ -1415,6 +1416,12 @@ static void cms_test_exec ( void ) {
/* Check expired signature */
cms_verify_fail_ok ( &codesigned_sig, &test_code,
NULL, test_expired, &test_root );
/* Drop signature references */
cms_put ( nonsigned_sig.sig );
cms_put ( genericsigned_sig.sig );
cms_put ( brokenchain_sig.sig );
cms_put ( codesigned_sig.sig );
}
/** CMS self-test */