diff options
author | Michael Brown | 2012-03-21 17:16:37 +0100 |
---|---|---|
committer | Michael Brown | 2012-03-22 12:41:22 +0100 |
commit | fe6e741c62e11655018996b5d281eaeb1af796c1 (patch) | |
tree | f21086bd055a22a27c0710e1edee1735799d678e /src/crypto | |
parent | [crypto] Differentiate "untrusted root" and "incomplete chain" error cases (diff) | |
download | ipxe-fe6e741c62e11655018996b5d281eaeb1af796c1.tar.gz ipxe-fe6e741c62e11655018996b5d281eaeb1af796c1.tar.xz ipxe-fe6e741c62e11655018996b5d281eaeb1af796c1.zip |
[crypto] Parse X.509 extended key usage extension
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/crypto')
-rw-r--r-- | src/crypto/x509.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/crypto/x509.c b/src/crypto/x509.c index cf82fc03..7c6aab5c 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -683,12 +683,92 @@ static int x509_parse_key_usage ( struct x509_certificate *cert, return 0; } +/** "id-kp-codeSigning" object identifier */ +static uint8_t oid_code_signing[] = { ASN1_OID_CODESIGNING }; + +/** Supported key purposes */ +static struct x509_key_purpose x509_key_purposes[] = { + { + .name = "codeSigning", + .bits = X509_CODE_SIGNING, + .oid = ASN1_OID_CURSOR ( oid_code_signing ), + }, +}; + +/** + * Parse X.509 certificate key purpose identifier + * + * @v cert X.509 certificate + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int x509_parse_key_purpose ( struct x509_certificate *cert, + const struct asn1_cursor *raw ) { + struct x509_extended_key_usage *ext_usage = &cert->extensions.ext_usage; + struct x509_key_purpose *purpose; + struct asn1_cursor cursor; + unsigned int i; + int rc; + + /* Enter keyPurposeId */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + if ( ( rc = asn1_enter ( &cursor, ASN1_OID ) ) != 0 ) { + DBGC ( cert, "X509 %p invalid keyPurposeId:\n", cert ); + DBGC_HDA ( cert, 0, raw->data, raw->len ); + return rc; + } + + /* Identify key purpose */ + for ( i = 0 ; i < ( sizeof ( x509_key_purposes ) / + sizeof ( x509_key_purposes[0] ) ) ; i++ ) { + purpose = &x509_key_purposes[i]; + if ( asn1_compare ( &cursor, &purpose->oid ) == 0 ) { + DBGC ( cert, "X509 %p has key purpose %s\n", + cert, purpose->name ); + ext_usage->bits |= purpose->bits; + return 0; + } + } + + /* Ignore unrecognised key purposes */ + return 0; +} + +/** + * Parse X.509 certificate extended key usage + * + * @v cert X.509 certificate + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int x509_parse_extended_key_usage ( struct x509_certificate *cert, + const struct asn1_cursor *raw ) { + struct asn1_cursor cursor; + int rc; + + /* Enter extKeyUsage */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Parse each extension in turn */ + while ( cursor.len ) { + if ( ( rc = x509_parse_key_purpose ( cert, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + } + + return 0; +} + /** "id-ce-basicConstraints" object identifier */ static uint8_t oid_ce_basic_constraints[] = { ASN1_OID_BASICCONSTRAINTS }; /** "id-ce-keyUsage" object identifier */ static uint8_t oid_ce_key_usage[] = { ASN1_OID_KEYUSAGE }; +/** "id-ce-extKeyUsage" object identifier */ +static uint8_t oid_ce_ext_key_usage[] = { ASN1_OID_EXTKEYUSAGE }; + /** Supported certificate extensions */ static struct x509_extension x509_extensions[] = { { @@ -701,6 +781,11 @@ static struct x509_extension x509_extensions[] = { .oid = ASN1_OID_CURSOR ( oid_ce_key_usage ), .parse = x509_parse_key_usage, }, + { + .name = "extKeyUsage", + .oid = ASN1_OID_CURSOR ( oid_ce_ext_key_usage ), + .parse = x509_parse_extended_key_usage, + }, }; /** |