summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/crypto/asn1.c54
-rw-r--r--src/crypto/rsa.c47
-rw-r--r--src/crypto/x509.c123
-rw-r--r--src/include/ipxe/asn1.h23
-rw-r--r--src/include/ipxe/x509.h29
5 files changed, 155 insertions, 121 deletions
diff --git a/src/crypto/asn1.c b/src/crypto/asn1.c
index f075b66dd..cd502502d 100644
--- a/src/crypto/asn1.c
+++ b/src/crypto/asn1.c
@@ -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;
+}
diff --git a/src/crypto/rsa.c b/src/crypto/rsa.c
index 9b98b1790..62f52c954 100644
--- a/src/crypto/rsa.c
+++ b/src/crypto/rsa.c
@@ -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 ) };
diff --git a/src/crypto/x509.c b/src/crypto/x509.c
index 449d07e2e..5ce42f88b 100644
--- a/src/crypto/x509.c
+++ b/src/crypto/x509.c
@@ -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 ];
diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h
index f912f5f57..553a8f3c3 100644
--- a/src/include/ipxe/asn1.h
+++ b/src/include/ipxe/asn1.h
@@ -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 */
diff --git a/src/include/ipxe/x509.h b/src/include/ipxe/x509.h
index 89f90b844..45f738cd7 100644
--- a/src/include/ipxe/x509.h
+++ b/src/include/ipxe/x509.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 */