summaryrefslogtreecommitdiffstats
path: root/src/crypto
diff options
context:
space:
mode:
authorMichael Brown2012-03-21 17:16:37 +0100
committerMichael Brown2012-03-22 12:41:22 +0100
commitfe6e741c62e11655018996b5d281eaeb1af796c1 (patch)
treef21086bd055a22a27c0710e1edee1735799d678e /src/crypto
parent[crypto] Differentiate "untrusted root" and "incomplete chain" error cases (diff)
downloadipxe-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.c85
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,
+ },
};
/**