Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[crypto] Generalise X.509 OID-identified algorithm to asn1.c
The concept of an OID-identified algorithm as defined in X.509 is used
in some other standards (e.g. PKCS#7).  Generalise this functionality
and provide it as part of the ASN.1 core.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Mar 22, 2012
1 parent 9a03a8e commit 38b7e43
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 121 deletions.
54 changes: 54 additions & 0 deletions src/crypto/asn1.c
Expand Up @@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <ipxe/tables.h>
#include <ipxe/asn1.h>

/** @file
Expand Down Expand Up @@ -341,3 +342,56 @@ int asn1_compare ( const struct asn1_cursor *cursor1,
return ( difference ? difference :
memcmp ( cursor1->data, cursor2->data, cursor1->len ) );
}

/**
* Identify ASN.1 algorithm by OID
*
* @v cursor ASN.1 object cursor
* @ret algorithm Algorithm, or NULL
*/
static struct asn1_algorithm *
asn1_find_algorithm ( const struct asn1_cursor *cursor ) {
struct asn1_algorithm *algorithm;

for_each_table_entry ( algorithm, ASN1_ALGORITHMS ) {
if ( asn1_compare ( &algorithm->oid, cursor ) == 0 )
return algorithm;
}

return NULL;
}

/**
* Parse ASN.1 OID-identified algorithm
*
* @v cursor ASN.1 object cursor
* @ret algorithm Algorithm, or NULL
*/
struct asn1_algorithm * asn1_algorithm ( const struct asn1_cursor *cursor ) {
struct asn1_cursor contents;
struct asn1_algorithm *algorithm;
int rc;

/* Enter signatureAlgorithm */
memcpy ( &contents, cursor, sizeof ( contents ) );
asn1_enter ( &contents, ASN1_SEQUENCE );

/* Enter algorithm */
if ( ( rc = asn1_enter ( &contents, ASN1_OID ) ) != 0 ) {
DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n",
cursor );
DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
return NULL;
}

/* Identify algorithm */
algorithm = asn1_find_algorithm ( &contents );
if ( ! algorithm ) {
DBGC ( cursor, "ASN1 %p unrecognised algorithm:\n", cursor );
DBGC_HDA ( cursor, 0, cursor->data, cursor->len );
return NULL;
}

return algorithm;
}
47 changes: 47 additions & 0 deletions src/crypto/rsa.c
Expand Up @@ -39,6 +39,53 @@ FILE_LICENCE ( GPL2_OR_LATER );
* RSA is documented in RFC 3447.
*/

/** "rsaEncryption" object identifier */
static uint8_t oid_rsa_encryption[] = { ASN1_OID_RSAENCRYPTION };

/** "md5WithRSAEncryption" object identifier */
static uint8_t oid_md5_with_rsa_encryption[] =
{ ASN1_OID_MD5WITHRSAENCRYPTION };

/** "sha1WithRSAEncryption" object identifier */
static uint8_t oid_sha1_with_rsa_encryption[] =
{ ASN1_OID_SHA1WITHRSAENCRYPTION };

/** "sha256WithRSAEncryption" object identifier */
static uint8_t oid_sha256_with_rsa_encryption[] =
{ ASN1_OID_SHA256WITHRSAENCRYPTION };

/** "rsaEncryption" OID-identified algorithm */
struct asn1_algorithm rsa_encryption_algorithm __asn1_algorithm = {
.name = "rsaEncryption",
.pubkey = &rsa_algorithm,
.digest = NULL,
.oid = ASN1_OID_CURSOR ( oid_rsa_encryption ),
};

/** "md5WithRSAEncryption" OID-identified algorithm */
struct asn1_algorithm md5_with_rsa_encryption_algorithm __asn1_algorithm = {
.name = "md5WithRSAEncryption",
.pubkey = &rsa_algorithm,
.digest = &md5_algorithm,
.oid = ASN1_OID_CURSOR ( oid_md5_with_rsa_encryption ),
};

/** "sha1WithRSAEncryption" OID-identified algorithm */
struct asn1_algorithm sha1_with_rsa_encryption_algorithm __asn1_algorithm = {
.name = "sha1WithRSAEncryption",
.pubkey = &rsa_algorithm,
.digest = &sha1_algorithm,
.oid = ASN1_OID_CURSOR ( oid_sha1_with_rsa_encryption ),
};

/** "sha256WithRSAEncryption" OID-identified algorithm */
struct asn1_algorithm sha256_with_rsa_encryption_algorithm __asn1_algorithm = {
.name = "sha256WithRSAEncryption",
.pubkey = &rsa_algorithm,
.digest = &sha256_algorithm,
.oid = ASN1_OID_CURSOR ( oid_sha256_with_rsa_encryption ),
};

/** MD5 digestInfo prefix */
static const uint8_t rsa_md5_prefix_data[] =
{ RSA_DIGESTINFO_PREFIX ( MD5_DIGEST_SIZE, ASN1_OID_MD5 ) };
Expand Down
123 changes: 28 additions & 95 deletions src/crypto/x509.c
Expand Up @@ -49,10 +49,10 @@ FILE_LICENCE ( GPL2_OR_LATER );
__einfo_error ( EINFO_ENOTSUP_EXTENSION )
#define EINFO_ENOTSUP_EXTENSION \
__einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported extension" )
#define EINVAL_NON_SIGNATURE \
__einfo_error ( EINFO_EINVAL_NON_SIGNATURE )
#define EINFO_EINVAL_NON_SIGNATURE \
__einfo_uniqify ( EINFO_EINVAL, 0x01, "Not a signature algorithm" )
#define EINVAL_ALGORITHM \
__einfo_error ( EINFO_EINVAL_ALGORITHM )
#define EINFO_EINVAL_ALGORITHM \
__einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid algorithm type" )
#define EINVAL_BIT_STRING \
__einfo_error ( EINFO_EINVAL_BIT_STRING )
#define EINFO_EINVAL_BIT_STRING \
Expand Down Expand Up @@ -101,70 +101,6 @@ static uint8_t oid_common_name[] = { ASN1_OID_COMMON_NAME };
static struct asn1_cursor oid_common_name_cursor =
ASN1_OID_CURSOR ( oid_common_name );

/** "rsaEncryption" object identifier */
static uint8_t oid_rsa_encryption[] = { ASN1_OID_RSAENCRYPTION };

/** "md5WithRSAEncryption" object identifier */
static uint8_t oid_md5_with_rsa_encryption[] =
{ ASN1_OID_MD5WITHRSAENCRYPTION };

/** "sha1WithRSAEncryption" object identifier */
static uint8_t oid_sha1_with_rsa_encryption[] =
{ ASN1_OID_SHA1WITHRSAENCRYPTION };

/** "sha256WithRSAEncryption" object identifier */
static uint8_t oid_sha256_with_rsa_encryption[] =
{ ASN1_OID_SHA256WITHRSAENCRYPTION };

/** Supported algorithms */
static struct x509_algorithm x509_algorithms[] = {
{
.name = "rsaEncryption",
.pubkey = &rsa_algorithm,
.digest = NULL,
.oid = ASN1_OID_CURSOR ( oid_rsa_encryption ),
},
{
.name = "md5WithRSAEncryption",
.pubkey = &rsa_algorithm,
.digest = &md5_algorithm,
.oid = ASN1_OID_CURSOR ( oid_md5_with_rsa_encryption ),
},
{
.name = "sha1WithRSAEncryption",
.pubkey = &rsa_algorithm,
.digest = &sha1_algorithm,
.oid = ASN1_OID_CURSOR ( oid_sha1_with_rsa_encryption ),
},
{
.name = "sha256WithRSAEncryption",
.pubkey = &rsa_algorithm,
.digest = &sha256_algorithm,
.oid = ASN1_OID_CURSOR ( oid_sha256_with_rsa_encryption ),
},
};

/**
* Identify X.509 algorithm by OID
*
* @v oid OID
* @ret algorithm Algorithm, or NULL
*/
static struct x509_algorithm *
x509_find_algorithm ( const struct asn1_cursor *oid ) {
struct x509_algorithm *algorithm;
unsigned int i;

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

return NULL;
}

/**
* Parse X.509 certificate algorithm
*
Expand All @@ -173,29 +109,24 @@ x509_find_algorithm ( const struct asn1_cursor *oid ) {
* @v raw ASN.1 cursor
* @ret rc Return status code
*/
static int x509_parse_algorithm ( struct x509_certificate *cert,
struct x509_algorithm **algorithm,
int x509_parse_pubkey_algorithm ( struct x509_certificate *cert,
struct asn1_algorithm **algorithm,
const struct asn1_cursor *raw ) {
struct asn1_cursor cursor;
int rc;

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

/* Enter algorithm */
if ( ( rc = asn1_enter ( &cursor, ASN1_OID ) ) != 0 ) {
DBGC ( cert, "X509 %p cannot locate algorithm:\n", cert );
/* Parse algorithm */
*algorithm = asn1_algorithm ( raw );
if ( ! (*algorithm) ) {
DBGC ( cert, "X509 %p unrecognised algorithm:\n", cert );
DBGC_HDA ( cert, 0, raw->data, raw->len );
return rc;
return -ENOTSUP_ALGORITHM;
}

/* Identify algorithm */
*algorithm = x509_find_algorithm ( &cursor );
if ( ! *algorithm ) {
DBGC ( cert, "X509 %p unsupported algorithm:\n", cert );
DBGC_HDA ( cert, 0, cursor.data, cursor.len );
return -ENOTSUP_ALGORITHM;
/* Check algorithm has a public key */
if ( ! (*algorithm)->pubkey ) {
DBGC ( cert, "X509 %p algorithm %s is not a public-key "
"algorithm:\n", cert, (*algorithm)->name );
DBGC_HDA ( cert, 0, raw->data, raw->len );
return -EINVAL_ALGORITHM;
}

return 0;
Expand All @@ -210,20 +141,21 @@ static int x509_parse_algorithm ( struct x509_certificate *cert,
* @ret rc Return status code
*/
static int x509_parse_signature_algorithm ( struct x509_certificate *cert,
struct x509_algorithm **algorithm,
struct asn1_algorithm **algorithm,
const struct asn1_cursor *raw ) {
int rc;

/* Parse algorithm */
if ( ( rc = x509_parse_algorithm ( cert, algorithm, raw ) ) != 0 )
if ( ( rc = x509_parse_pubkey_algorithm ( cert, algorithm,
raw ) ) != 0 )
return rc;

/* Check algorithm is a signature algorithm */
if ( ! x509_is_signature_algorithm ( *algorithm ) ) {
if ( ! (*algorithm)->digest ) {
DBGC ( cert, "X509 %p algorithm %s is not a signature "
"algorithm:\n", cert, (*algorithm)->name );
DBGC_HDA ( cert, 0, raw->data, raw->len );
return -EINVAL_NON_SIGNATURE;
return -EINVAL_ALGORITHM;
}

return 0;
Expand Down Expand Up @@ -600,7 +532,7 @@ static int x509_parse_subject ( struct x509_certificate *cert,
static int x509_parse_public_key ( struct x509_certificate *cert,
const struct asn1_cursor *raw ) {
struct x509_public_key *public_key = &cert->subject.public_key;
struct x509_algorithm **algorithm = &public_key->algorithm;
struct asn1_algorithm **algorithm = &public_key->algorithm;
struct asn1_cursor cursor;
int rc;

Expand All @@ -613,7 +545,8 @@ static int x509_parse_public_key ( struct x509_certificate *cert,
asn1_enter ( &cursor, ASN1_SEQUENCE );

/* Parse algorithm */
if ( ( rc = x509_parse_algorithm ( cert, algorithm, &cursor ) ) != 0 )
if ( ( rc = x509_parse_pubkey_algorithm ( cert, algorithm,
&cursor ) ) != 0 )
return rc;
DBGC ( cert, "X509 %p public key algorithm is %s\n",
cert, (*algorithm)->name );
Expand Down Expand Up @@ -866,7 +799,7 @@ static int x509_parse_extensions ( struct x509_certificate *cert,
*/
static int x509_parse_tbscertificate ( struct x509_certificate *cert,
const struct asn1_cursor *raw ) {
struct x509_algorithm **algorithm = &cert->signature_algorithm;
struct asn1_algorithm **algorithm = &cert->signature_algorithm;
struct asn1_cursor cursor;
int rc;

Expand Down Expand Up @@ -933,7 +866,7 @@ static int x509_parse_tbscertificate ( struct x509_certificate *cert,
*/
int x509_parse ( struct x509_certificate *cert, const void *data, size_t len ) {
struct x509_signature *signature = &cert->signature;
struct x509_algorithm **signature_algorithm = &signature->algorithm;
struct asn1_algorithm **signature_algorithm = &signature->algorithm;
struct x509_bit_string *signature_value = &signature->value;
struct asn1_cursor cursor;
int rc;
Expand Down Expand Up @@ -991,7 +924,7 @@ int x509_parse ( struct x509_certificate *cert, const void *data, size_t len ) {
static int x509_check_signature ( struct x509_certificate *cert,
struct x509_public_key *public_key ) {
struct x509_signature *signature = &cert->signature;
struct x509_algorithm *algorithm = signature->algorithm;
struct asn1_algorithm *algorithm = signature->algorithm;
struct digest_algorithm *digest = algorithm->digest;
struct pubkey_algorithm *pubkey = algorithm->pubkey;
uint8_t digest_ctx[ digest->ctxsize ];
Expand Down
23 changes: 23 additions & 0 deletions src/include/ipxe/asn1.h
Expand Up @@ -9,6 +9,9 @@

FILE_LICENCE ( GPL2_OR_LATER );

#include <stdint.h>
#include <ipxe/tables.h>

/** An ASN.1 object cursor */
struct asn1_cursor {
/** Start of data */
Expand Down Expand Up @@ -143,6 +146,24 @@ struct asn1_cursor {
.len = sizeof ( oid_value ), \
}

/** An ASN.1 OID-identified algorithm */
struct asn1_algorithm {
/** Name */
const char *name;
/** Object identifier */
struct asn1_cursor oid;
/** Public-key algorithm (if applicable) */
struct pubkey_algorithm *pubkey;
/** Digest algorithm (if applicable) */
struct digest_algorithm *digest;
};

/** ASN.1 OID-identified algorithms */
#define ASN1_ALGORITHMS __table ( struct asn1_algorithm, "asn1_algorithms" )

/** Declare an ASN.1 OID-identified algorithm */
#define __asn1_algorithm __table_entry ( ASN1_ALGORITHMS, 01 )

/** An ASN.1 boolean */
struct asn1_boolean {
/** Value */
Expand Down Expand Up @@ -181,5 +202,7 @@ extern int asn1_boolean ( const struct asn1_cursor *cursor );
extern int asn1_integer ( const struct asn1_cursor *cursor, int *value );
extern int asn1_compare ( const struct asn1_cursor *cursor1,
const struct asn1_cursor *cursor2 );
extern struct asn1_algorithm *
asn1_algorithm ( const struct asn1_cursor *cursor );

#endif /* _IPXE_ASN1_H */

0 comments on commit 38b7e43

Please sign in to comment.