From 7deb610881d36dd156edbf705f923cf43cc0fdf5 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 14 May 2012 00:13:00 +0100 Subject: [PATCH] [crypto] Generalise asn1_{digest,pubkey,signature}_algorithm() Signed-off-by: Michael Brown --- src/crypto/asn1.c | 115 +++++++++++++++++++++++++++++++++++++--- src/crypto/cms.c | 41 ++++---------- src/crypto/x509.c | 79 +++++---------------------- src/include/ipxe/asn1.h | 10 +++- 4 files changed, 137 insertions(+), 108 deletions(-) diff --git a/src/crypto/asn1.c b/src/crypto/asn1.c index 55860558..47c735c5 100644 --- a/src/crypto/asn1.c +++ b/src/crypto/asn1.c @@ -58,6 +58,18 @@ FILE_LICENCE ( GPL2_OR_LATER ); __einfo_error ( EINFO_EINVAL_ASN1_TIME ) #define EINFO_EINVAL_ASN1_TIME \ __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid time" ) +#define EINVAL_ASN1_ALGORITHM \ + __einfo_error ( EINFO_EINVAL_ASN1_ALGORITHM ) +#define EINFO_EINVAL_ASN1_ALGORITHM \ + __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid algorithm" ) +#define ENOTSUP_ALGORITHM \ + __einfo_error ( EINFO_ENOTSUP_ALGORITHM ) +#define EINFO_ENOTSUP_ALGORITHM \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" ) +#define ENOTTY_ALGORITHM \ + __einfo_error ( EINFO_ENOTTY_ALGORITHM ) +#define EINFO_ENOTTY_ALGORITHM \ + __einfo_uniqify ( EINFO_ENOTTY, 0x01, "Inappropriate algorithm" ) /** * Invalidate ASN.1 object cursor @@ -377,11 +389,12 @@ asn1_find_algorithm ( const struct asn1_cursor *cursor ) { * Parse ASN.1 OID-identified algorithm * * @v cursor ASN.1 object cursor - * @ret algorithm Algorithm, or NULL + * @ret algorithm Algorithm + * @ret rc Return status code */ -struct asn1_algorithm * asn1_algorithm ( const struct asn1_cursor *cursor ) { +int asn1_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ) { struct asn1_cursor contents; - struct asn1_algorithm *algorithm; int rc; /* Enter signatureAlgorithm */ @@ -393,18 +406,104 @@ struct asn1_algorithm * asn1_algorithm ( const struct asn1_cursor *cursor ) { DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n", cursor ); DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return NULL; + return -EINVAL_ASN1_ALGORITHM; } /* Identify algorithm */ - algorithm = asn1_find_algorithm ( &contents ); - if ( ! 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 -ENOTSUP_ALGORITHM; } - return algorithm; + return 0; +} + +/** + * Parse ASN.1 OID-identified public-key algorithm + * + * @v cursor ASN.1 object cursor + * @ret algorithm Algorithm + * @ret rc Return status code + */ +int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ) { + int rc; + + /* Parse algorithm */ + if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 ) + return rc; + + /* Check algorithm has a public key */ + if ( ! (*algorithm)->pubkey ) { + DBGC ( cursor, "ASN1 %p algorithm %s is not a public-key " + "algorithm:\n", cursor, (*algorithm)->name ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -ENOTTY_ALGORITHM; + } + + return 0; +} + +/** + * Parse ASN.1 OID-identified digest algorithm + * + * @v cursor ASN.1 object cursor + * @ret algorithm Algorithm + * @ret rc Return status code + */ +int asn1_digest_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ) { + int rc; + + /* Parse algorithm */ + if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 ) + return rc; + + /* Check algorithm has a digest */ + if ( ! (*algorithm)->digest ) { + DBGC ( cursor, "ASN1 %p algorithm %s is not a digest " + "algorithm:\n", cursor, (*algorithm)->name ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -ENOTTY_ALGORITHM; + } + + return 0; +} + +/** + * Parse ASN.1 OID-identified signature algorithm + * + * @v cursor ASN.1 object cursor + * @ret algorithm Algorithm + * @ret rc Return status code + */ +int asn1_signature_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ) { + int rc; + + /* Parse algorithm */ + if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 ) + return rc; + + /* Check algorithm has a public key */ + if ( ! (*algorithm)->pubkey ) { + DBGC ( cursor, "ASN1 %p algorithm %s is not a signature " + "algorithm:\n", cursor, (*algorithm)->name ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -ENOTTY_ALGORITHM; + } + + /* Check algorithm has a digest */ + if ( ! (*algorithm)->digest ) { + DBGC ( cursor, "ASN1 %p algorithm %s is not a signature " + "algorithm:\n", cursor, (*algorithm)->name ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -ENOTTY_ALGORITHM; + } + + return 0; } /** diff --git a/src/crypto/cms.c b/src/crypto/cms.c index 18e59bfb..2083433e 100644 --- a/src/crypto/cms.c +++ b/src/crypto/cms.c @@ -65,15 +65,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); __einfo_error ( EINFO_ENOTSUP_SIGNEDDATA ) #define EINFO_ENOTSUP_SIGNEDDATA \ __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Not a digital signature" ) -#define ENOTSUP_DIGEST \ - __einfo_error ( EINFO_ENOTSUP_DIGEST ) -#define EINFO_ENOTSUP_DIGEST \ - __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported digest algorithm" ) -#define ENOTSUP_PUBKEY \ - __einfo_error ( EINFO_ENOTSUP_PUBKEY ) -#define EINFO_ENOTSUP_PUBKEY \ - __einfo_uniqify ( EINFO_ENOTSUP, 0x03, \ - "Unsupported public-key algorithm" ) /** "pkcs7-signedData" object identifier */ static uint8_t oid_signeddata[] = { ASN1_OID_SIGNEDDATA }; @@ -257,21 +248,14 @@ static int cms_parse_digest_algorithm ( struct cms_signature *sig, struct cms_signer_info *info, const struct asn1_cursor *raw ) { struct asn1_algorithm *algorithm; + int rc; /* Identify algorithm */ - algorithm = asn1_algorithm ( raw ); - if ( ! algorithm ) { - DBGC ( sig, "CMS %p/%p could not identify digest algorithm:\n", - sig, info ); + if ( ( rc = asn1_digest_algorithm ( raw, &algorithm ) ) != 0 ) { + DBGC ( sig, "CMS %p/%p could not identify digest algorithm: " + "%s\n", sig, info, strerror ( rc ) ); DBGC_HDA ( sig, 0, raw->data, raw->len ); - return -ENOTSUP_DIGEST; - } - - /* Check algorithm is a digest algorithm */ - if ( ! algorithm->digest ) { - DBGC ( sig, "CMS %p/%p algorithm %s is not a digest " - "algorithm\n", sig, info, algorithm->name ); - return -EINVAL_DIGEST; + return rc; } /* Record digest algorithm */ @@ -294,21 +278,14 @@ static int cms_parse_signature_algorithm ( struct cms_signature *sig, struct cms_signer_info *info, const struct asn1_cursor *raw ) { struct asn1_algorithm *algorithm; + int rc; /* Identify algorithm */ - algorithm = asn1_algorithm ( raw ); - if ( ! algorithm ) { + if ( ( rc = asn1_pubkey_algorithm ( raw, &algorithm ) ) != 0 ) { DBGC ( sig, "CMS %p/%p could not identify public-key " - "algorithm:\n", sig, info ); + "algorithm: %s\n", sig, info, strerror ( rc ) ); DBGC_HDA ( sig, 0, raw->data, raw->len ); - return -ENOTSUP_PUBKEY; - } - - /* Check algorithm is a signature algorithm */ - if ( ! algorithm->pubkey ) { - DBGC ( sig, "CMS %p/%p algorithm %s is not a public-key " - "algorithm\n", sig, info, algorithm->name ); - return -EINVAL_PUBKEY; + return rc; } /* Record signature algorithm */ diff --git a/src/crypto/x509.c b/src/crypto/x509.c index 1cb46a1d..f25424a1 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -154,66 +154,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 ); -/** - * Parse X.509 certificate algorithm - * - * @v cert X.509 certificate - * @v algorithm Algorithm to fill in - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_pubkey_algorithm ( struct x509_certificate *cert, - struct asn1_algorithm **algorithm, - const struct asn1_cursor *raw ) { - - /* 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 -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; -} - -/** - * Parse X.509 certificate signature algorithm - * - * @v cert X.509 certificate - * @v algorithm Algorithm to fill in - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_signature_algorithm ( struct x509_certificate *cert, - struct asn1_algorithm **algorithm, - const struct asn1_cursor *raw ) { - int rc; - - /* Parse algorithm */ - if ( ( rc = x509_parse_pubkey_algorithm ( cert, algorithm, - raw ) ) != 0 ) - return rc; - - /* Check algorithm is a signature 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_ALGORITHM; - } - - return 0; -} - /** * Parse X.509 certificate bit string * @@ -541,9 +481,11 @@ static int x509_parse_public_key ( struct x509_certificate *cert, asn1_enter ( &cursor, ASN1_SEQUENCE ); /* Parse algorithm */ - if ( ( rc = x509_parse_pubkey_algorithm ( cert, algorithm, - &cursor ) ) != 0 ) + if ( ( rc = asn1_pubkey_algorithm ( &cursor, algorithm ) ) != 0 ) { + DBGC ( cert, "X509 %p could not parse public key algorithm: " + "%s\n", cert, strerror ( rc ) ); return rc; + } DBGC2 ( cert, "X509 %p public key algorithm is %s\n", cert, (*algorithm)->name ); asn1_skip_any ( &cursor ); @@ -1045,9 +987,11 @@ static int x509_parse_tbscertificate ( struct x509_certificate *cert, asn1_skip_any ( &cursor ); /* Parse signature */ - if ( ( rc = x509_parse_signature_algorithm ( cert, algorithm, - &cursor ) ) != 0 ) + if ( ( rc = asn1_signature_algorithm ( &cursor, algorithm ) ) != 0 ) { + DBGC ( cert, "X509 %p could not parse signature algorithm: " + "%s\n", cert, strerror ( rc ) ); return rc; + } DBGC2 ( cert, "X509 %p tbsCertificate signature algorithm is %s\n", cert, (*algorithm)->name ); asn1_skip_any ( &cursor ); @@ -1107,9 +1051,12 @@ static int x509_parse ( struct x509_certificate *cert, asn1_skip_any ( &cursor ); /* Parse signatureAlgorithm */ - if ( ( rc = x509_parse_signature_algorithm ( cert, signature_algorithm, - &cursor ) ) != 0 ) + if ( ( rc = asn1_signature_algorithm ( &cursor, + signature_algorithm ) ) != 0 ) { + DBGC ( cert, "X509 %p could not parse signature algorithm: " + "%s\n", cert, strerror ( rc ) ); return rc; + } DBGC2 ( cert, "X509 %p signatureAlgorithm is %s\n", cert, (*signature_algorithm)->name ); asn1_skip_any ( &cursor ); diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h index 38f0e5b0..cd0d5342 100644 --- a/src/include/ipxe/asn1.h +++ b/src/include/ipxe/asn1.h @@ -238,8 +238,14 @@ 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 ); +extern int asn1_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ); +extern int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ); +extern int asn1_digest_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ); +extern int asn1_signature_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ); extern int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time );