Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[crypto] Parse OCSP responder URI from X.509 certificate
Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed May 4, 2012
1 parent f91995f commit 601cb36
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 11 deletions.
148 changes: 142 additions & 6 deletions src/crypto/x509.c
Expand Up @@ -487,7 +487,7 @@ static int x509_parse_validity ( struct x509_certificate *cert,
* @ret rc Return status code
*/
static int x509_parse_common_name ( struct x509_certificate *cert,
struct x509_name *name,
struct x509_string *name,
const struct asn1_cursor *raw ) {
struct asn1_cursor cursor;
struct asn1_cursor oid_cursor;
Expand Down Expand Up @@ -533,7 +533,7 @@ static int x509_parse_common_name ( struct x509_certificate *cert,
static int x509_parse_subject ( struct x509_certificate *cert,
const struct asn1_cursor *raw ) {
struct x509_subject *subject = &cert->subject;
struct x509_name *name = &subject->name;
struct x509_string *name = &subject->name;
int rc;

/* Record raw subject */
Expand Down Expand Up @@ -750,7 +750,7 @@ static int x509_parse_extended_key_usage ( struct x509_certificate *cert,
memcpy ( &cursor, raw, sizeof ( cursor ) );
asn1_enter ( &cursor, ASN1_SEQUENCE );

/* Parse each extension in turn */
/* Parse each extended key usage in turn */
while ( cursor.len ) {
if ( ( rc = x509_parse_key_purpose ( cert, &cursor ) ) != 0 )
return rc;
Expand All @@ -760,14 +760,145 @@ static int x509_parse_extended_key_usage ( struct x509_certificate *cert,
return 0;
}

/**
* Parse X.509 certificate OCSP access method
*
* @v cert X.509 certificate
* @v raw ASN.1 cursor
* @ret rc Return status code
*/
static int x509_parse_ocsp ( struct x509_certificate *cert,
const struct asn1_cursor *raw ) {
struct x509_ocsp_responder *ocsp = &cert->extensions.auth_info.ocsp;
struct asn1_cursor cursor;
int rc;

/* Enter accessLocation */
memcpy ( &cursor, raw, sizeof ( cursor ) );
if ( ( rc = asn1_enter ( &cursor, ASN1_IMPLICIT_TAG ( 6 ) ) ) != 0 ) {
DBGC ( cert, "X509 %p OCSP does not contain "
"uniformResourceIdentifier:\n", cert );
DBGC_HDA ( cert, 0, raw->data, raw->len );
return rc;
}

/* Record URI */
ocsp->uri.data = cursor.data;
ocsp->uri.len = cursor.len;
DBGC ( cert, "X509 %p OCSP URI is:\n", cert );
DBGC_HDA ( cert, 0, ocsp->uri.data, ocsp->uri.len );

return 0;
}

/** "id-ad-ocsp" object identifier */
static uint8_t oid_ad_ocsp[] = { ASN1_OID_OCSP };

/** Supported access methods */
static struct x509_access_method x509_access_methods[] = {
{
.name = "OCSP",
.oid = ASN1_OID_CURSOR ( oid_ad_ocsp ),
.parse = x509_parse_ocsp,
},
};

/**
* Identify X.509 access method by OID
*
* @v oid OID
* @ret method Access method, or NULL
*/
static struct x509_access_method *
x509_find_access_method ( const struct asn1_cursor *oid ) {
struct x509_access_method *method;
unsigned int i;

for ( i = 0 ; i < ( sizeof ( x509_access_methods ) /
sizeof ( x509_access_methods[0] ) ) ; i++ ) {
method = &x509_access_methods[i];
if ( asn1_compare ( &method->oid, oid ) == 0 )
return method;
}

return NULL;
}

/**
* Parse X.509 certificate access description
*
* @v cert X.509 certificate
* @v raw ASN.1 cursor
* @ret rc Return status code
*/
static int x509_parse_access_description ( struct x509_certificate *cert,
const struct asn1_cursor *raw ) {
struct asn1_cursor cursor;
struct asn1_cursor subcursor;
struct x509_access_method *method;
int rc;

/* Enter keyPurposeId */
memcpy ( &cursor, raw, sizeof ( cursor ) );
asn1_enter ( &cursor, ASN1_SEQUENCE );

/* Try to identify access method */
memcpy ( &subcursor, &cursor, sizeof ( subcursor ) );
asn1_enter ( &subcursor, ASN1_OID );
method = x509_find_access_method ( &subcursor );
asn1_skip_any ( &cursor );
DBGC ( cert, "X509 %p found access method %s\n",
cert, ( method ? method->name : "<unknown>" ) );

/* Parse access location, if applicable */
if ( method && ( ( rc = method->parse ( cert, &cursor ) ) != 0 ) )
return rc;

return 0;
}

/**
* Parse X.509 certificate authority information access
*
* @v cert X.509 certificate
* @v raw ASN.1 cursor
* @ret rc Return status code
*/
static int x509_parse_authority_info_access ( struct x509_certificate *cert,
const struct asn1_cursor *raw ) {
struct asn1_cursor cursor;
int rc;

/* Enter authorityInfoAccess */
memcpy ( &cursor, raw, sizeof ( cursor ) );
asn1_enter ( &cursor, ASN1_SEQUENCE );

/* Parse each access description in turn */
while ( cursor.len ) {
if ( ( rc = x509_parse_access_description ( 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 };
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 };
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 };
static uint8_t oid_ce_ext_key_usage[] =
{ ASN1_OID_EXTKEYUSAGE };

/** "id-pe-authorityInfoAccess" object identifier */
static uint8_t oid_pe_authority_info_access[] =
{ ASN1_OID_AUTHORITYINFOACCESS };

/** Supported certificate extensions */
static struct x509_extension x509_extensions[] = {
Expand All @@ -786,6 +917,11 @@ static struct x509_extension x509_extensions[] = {
.oid = ASN1_OID_CURSOR ( oid_ce_ext_key_usage ),
.parse = x509_parse_extended_key_usage,
},
{
.name = "authorityInfoAccess",
.oid = ASN1_OID_CURSOR ( oid_pe_authority_info_access ),
.parse = x509_parse_authority_info_access,
},
};

/**
Expand Down
17 changes: 17 additions & 0 deletions src/include/ipxe/asn1.h
Expand Up @@ -53,6 +53,9 @@ struct asn1_cursor {
/** ASN.1 set */
#define ASN1_SET 0x31

/** ASN.1 implicit tag */
#define ASN1_IMPLICIT_TAG( number) ( 0x80 | (number) )

/** ASN.1 explicit tag */
#define ASN1_EXPLICIT_TAG( number) ( 0xa0 | (number) )

Expand Down Expand Up @@ -158,6 +161,20 @@ struct asn1_cursor {
ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \
ASN1_OID_SINGLE ( 7 ), ASN1_OID_SINGLE ( 2 )

/** ASN.1 OID for id-pe-authorityInfoAccess (1.3.6.1.5.5.7.1.1) */
#define ASN1_OID_AUTHORITYINFOACCESS \
ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ), \
ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 ), \
ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \
ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 1 )

/** ASN.1 OID for id-ad-ocsp (1.3.6.1.5.5.7.48.1) */
#define ASN1_OID_OCSP \
ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ), \
ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 ), \
ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \
ASN1_OID_SINGLE ( 48 ), ASN1_OID_SINGLE ( 1 )

/** Define an ASN.1 cursor containing an OID */
#define ASN1_OID_CURSOR( oid_value ) { \
.data = oid_value, \
Expand Down
38 changes: 34 additions & 4 deletions src/include/ipxe/x509.h
Expand Up @@ -50,9 +50,9 @@ struct x509_validity {
struct x509_time not_after;
};

/** An X.509 name */
struct x509_name {
/** Name (not NUL-terminated) */
/** An X.509 string */
struct x509_string {
/** String (not NUL-terminated) */
const void *data;
/** Length of name */
size_t len;
Expand All @@ -71,7 +71,7 @@ struct x509_subject {
/** Raw subject */
struct asn1_cursor raw;
/** Common name */
struct x509_name name;
struct x509_string name;
/** Public key information */
struct x509_public_key public_key;
};
Expand Down Expand Up @@ -128,6 +128,18 @@ enum x509_extended_key_usage_bits {
X509_CODE_SIGNING = 0x0001,
};

/** X.509 certificate OCSP responder */
struct x509_ocsp_responder {
/** URI */
struct x509_string uri;
};

/** X.509 certificate authority information access */
struct x509_authority_info_access {
/** OCSP responder */
struct x509_ocsp_responder ocsp;
};

/** An X.509 certificate extensions set */
struct x509_extensions {
/** Basic constraints */
Expand All @@ -136,6 +148,8 @@ struct x509_extensions {
struct x509_key_usage usage;
/** Extended key usage */
struct x509_extended_key_usage ext_usage;
/** Authority information access */
struct x509_authority_info_access auth_info;
};

/** An X.509 certificate */
Expand Down Expand Up @@ -188,6 +202,22 @@ struct x509_key_purpose {
unsigned int bits;
};

/** An X.509 access method */
struct x509_access_method {
/** Name */
const char *name;
/** Object identifier */
struct asn1_cursor oid;
/** Parse access method
*
* @v cert X.509 certificate
* @v raw ASN.1 cursor
* @ret rc Return status code
*/
int ( * parse ) ( struct x509_certificate *cert,
const struct asn1_cursor *raw );
};

/** An X.509 root certificate store */
struct x509_root {
/** Fingerprint digest algorithm */
Expand Down
2 changes: 1 addition & 1 deletion src/net/tls.c
Expand Up @@ -1347,7 +1347,7 @@ static int tls_new_certificate ( struct tls_session *tls,
struct pubkey_algorithm *pubkey = cipherspec->suite->pubkey;
struct tls_certificate_context context;
struct x509_certificate cert;
struct x509_name *name = &cert.subject.name;
struct x509_string *name = &cert.subject.name;
struct x509_public_key *key = &cert.subject.public_key;
time_t now;
int rc;
Expand Down

0 comments on commit 601cb36

Please sign in to comment.