mirror of
https://github.com/xcat2/xNBA.git
synced 2025-04-15 09:39:26 +00:00
[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>
This commit is contained in:
parent
9a03a8e3d2
commit
38b7e43f7d
@ -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
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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 ) };
|
||||
|
@ -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 \
|
||||
@ -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
|
||||
*
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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;
|
||||
|
||||
@ -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 );
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
@ -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 ];
|
||||
|
@ -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 */
|
||||
@ -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 */
|
||||
@ -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 */
|
||||
|
@ -14,29 +14,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <time.h>
|
||||
#include <ipxe/asn1.h>
|
||||
|
||||
/** An X.509 algorithm */
|
||||
struct x509_algorithm {
|
||||
/** Name */
|
||||
const char *name;
|
||||
/** Object identifier */
|
||||
struct asn1_cursor oid;
|
||||
/** Public-key algorithm */
|
||||
struct pubkey_algorithm *pubkey;
|
||||
/** Digest algorithm (if applicable) */
|
||||
struct digest_algorithm *digest;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test if X.509 algorithm is a signature algorithm
|
||||
*
|
||||
* @v algorithm Algorithm
|
||||
* @ret is_signature Algorithm is a signature algorithm
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
x509_is_signature_algorithm ( struct x509_algorithm *algorithm ) {
|
||||
return ( algorithm->digest != NULL );
|
||||
}
|
||||
|
||||
/** An X.509 bit string */
|
||||
struct x509_bit_string {
|
||||
/** Data */
|
||||
@ -80,7 +57,7 @@ struct x509_public_key {
|
||||
/** Raw public key */
|
||||
struct asn1_cursor raw;
|
||||
/** Public key algorithm */
|
||||
struct x509_algorithm *algorithm;
|
||||
struct asn1_algorithm *algorithm;
|
||||
};
|
||||
|
||||
/** An X.509 certificate subject */
|
||||
@ -96,7 +73,7 @@ struct x509_subject {
|
||||
/** An X.509 certificate signature */
|
||||
struct x509_signature {
|
||||
/** Signature algorithm */
|
||||
struct x509_algorithm *algorithm;
|
||||
struct asn1_algorithm *algorithm;
|
||||
/** Signature value */
|
||||
struct x509_bit_string value;
|
||||
};
|
||||
@ -147,7 +124,7 @@ struct x509_certificate {
|
||||
/** Raw tbsCertificate */
|
||||
struct asn1_cursor tbs;
|
||||
/** Signature algorithm */
|
||||
struct x509_algorithm *signature_algorithm;
|
||||
struct asn1_algorithm *signature_algorithm;
|
||||
/** Issuer */
|
||||
struct x509_issuer issuer;
|
||||
/** Validity */
|
||||
|
Loading…
x
Reference in New Issue
Block a user