[crypto] Allow for extraction of ASN.1 algorithm parameters

Some ASN.1 OID-identified algorithms require additional parameters,
such as an initialisation vector for a block cipher.  The structure of
the parameters is defined by the individual algorithm.

Extend asn1_algorithm() to allow these additional parameters to be
returned via a separate ASN.1 cursor.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2024-08-26 23:36:06 +01:00
parent bdb5b4aef4
commit 4b4a362f07
4 changed files with 92 additions and 11 deletions

View File

@ -32,6 +32,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <time.h>
#include <ipxe/tables.h>
#include <ipxe/image.h>
#include <ipxe/crypto.h>
#include <ipxe/asn1.h>
/** @file
@ -509,18 +510,26 @@ asn1_find_algorithm ( const struct asn1_cursor *cursor ) {
*
* @v cursor ASN.1 object cursor
* @ret algorithm Algorithm
* @ret params Algorithm parameters, or NULL
* @ret rc Return status code
*/
int asn1_algorithm ( const struct asn1_cursor *cursor,
struct asn1_algorithm **algorithm ) {
struct asn1_algorithm **algorithm,
struct asn1_cursor *params ) {
struct asn1_cursor contents;
int rc;
/* Enter signatureAlgorithm */
/* Enter algorithm */
memcpy ( &contents, cursor, sizeof ( contents ) );
asn1_enter ( &contents, ASN1_SEQUENCE );
/* Enter algorithm */
/* Get raw parameters, if applicable */
if ( params ) {
memcpy ( params, &contents, sizeof ( *params ) );
asn1_skip_any ( params );
}
/* Enter algorithm identifier */
if ( ( rc = asn1_enter ( &contents, ASN1_OID ) ) != 0 ) {
DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n",
cursor );
@ -536,6 +545,14 @@ int asn1_algorithm ( const struct asn1_cursor *cursor,
return -ENOTSUP_ALGORITHM;
}
/* Parse parameters, if applicable */
if ( params && (*algorithm)->parse &&
( ( rc = (*algorithm)->parse ( *algorithm, params ) ) != 0 ) ) {
DBGC ( cursor, "ASN1 %p cannot parse %s parameters: %s\n",
cursor, (*algorithm)->name, strerror ( rc ) );
return rc;
}
return 0;
}
@ -551,7 +568,7 @@ int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor,
int rc;
/* Parse algorithm */
if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
return rc;
/* Check algorithm has a public key */
@ -577,7 +594,7 @@ int asn1_digest_algorithm ( const struct asn1_cursor *cursor,
int rc;
/* Parse algorithm */
if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
return rc;
/* Check algorithm has a digest */
@ -596,14 +613,16 @@ int asn1_digest_algorithm ( const struct asn1_cursor *cursor,
*
* @v cursor ASN.1 object cursor
* @ret algorithm Algorithm
* @ret params Algorithm parameters, or NULL
* @ret rc Return status code
*/
int asn1_cipher_algorithm ( const struct asn1_cursor *cursor,
struct asn1_algorithm **algorithm ) {
struct asn1_algorithm **algorithm,
struct asn1_cursor *params ) {
int rc;
/* Parse algorithm */
if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
if ( ( rc = asn1_algorithm ( cursor, algorithm, params ) ) != 0 )
return rc;
/* Check algorithm has a cipher */
@ -629,7 +648,7 @@ int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
int rc;
/* Parse algorithm */
if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 )
if ( ( rc = asn1_algorithm ( cursor, algorithm, NULL ) ) != 0 )
return rc;
/* Check algorithm has a public key */
@ -664,7 +683,7 @@ int asn1_check_algorithm ( const struct asn1_cursor *cursor,
int rc;
/* Parse algorithm */
if ( ( rc = asn1_algorithm ( cursor, &actual ) ) != 0 )
if ( ( rc = asn1_algorithm ( cursor, &actual, NULL ) ) != 0 )
return rc;
/* Check algorithm matches */
@ -677,6 +696,47 @@ int asn1_check_algorithm ( const struct asn1_cursor *cursor,
return 0;
}
/**
* Parse ASN.1 CBC cipher parameters
*
* @v algorithm Algorithm
* @v param Parameters to parse
* @ret rc Return status code
*/
int asn1_parse_cbc ( struct asn1_algorithm *algorithm,
struct asn1_cursor *params ) {
struct cipher_algorithm *cipher = algorithm->cipher;
/* Sanity check */
assert ( cipher != NULL );
/* Enter parameters */
asn1_enter ( params, ASN1_OCTET_STRING );
/* Check length */
if ( params->len != cipher->blocksize )
return -EINVAL;
return 0;
}
/**
* Parse ASN.1 GCM cipher parameters
*
* @v algorithm Algorithm
* @v param Parameters to parse
* @ret rc Return status code
*/
int asn1_parse_gcm ( struct asn1_algorithm *algorithm __unused,
struct asn1_cursor *params ) {
/* Enter parameters */
asn1_enter ( params, ASN1_SEQUENCE );
/* Enter nonce */
return asn1_enter ( params, ASN1_OCTET_STRING );
}
/**
* Parse ASN.1 GeneralizedTime
*

View File

@ -40,6 +40,7 @@ struct asn1_algorithm aes_128_cbc_algorithm __asn1_algorithm = {
.name = "aes128-cbc",
.cipher = &aes_cbc_algorithm,
.oid = ASN1_CURSOR ( oid_aes_128_cbc ),
.parse = asn1_parse_cbc,
};
/** "aes192-cbc" OID-identified algorithm */
@ -47,6 +48,7 @@ struct asn1_algorithm aes_192_cbc_algorithm __asn1_algorithm = {
.name = "aes192-cbc",
.cipher = &aes_cbc_algorithm,
.oid = ASN1_CURSOR ( oid_aes_192_cbc ),
.parse = asn1_parse_cbc,
};
/** "aes256-cbc" OID-identified algorithm */
@ -54,4 +56,5 @@ struct asn1_algorithm aes_256_cbc_algorithm __asn1_algorithm = {
.name = "aes256-cbc",
.cipher = &aes_cbc_algorithm,
.oid = ASN1_CURSOR ( oid_aes_256_cbc ),
.parse = asn1_parse_cbc,
};

View File

@ -40,6 +40,7 @@ struct asn1_algorithm aes_128_gcm_algorithm __asn1_algorithm = {
.name = "aes128-gcm",
.cipher = &aes_gcm_algorithm,
.oid = ASN1_CURSOR ( oid_aes_128_gcm ),
.parse = asn1_parse_gcm,
};
/** "aes192-gcm" OID-identified algorithm */
@ -47,6 +48,7 @@ struct asn1_algorithm aes_192_gcm_algorithm __asn1_algorithm = {
.name = "aes192-gcm",
.cipher = &aes_gcm_algorithm,
.oid = ASN1_CURSOR ( oid_aes_192_gcm ),
.parse = asn1_parse_gcm,
};
/** "aes256-gcm" OID-identified algorithm */
@ -54,4 +56,5 @@ struct asn1_algorithm aes_256_gcm_algorithm __asn1_algorithm = {
.name = "aes256-gcm",
.cipher = &aes_gcm_algorithm,
.oid = ASN1_CURSOR ( oid_aes_256_gcm ),
.parse = asn1_parse_gcm,
};

View File

@ -363,6 +363,15 @@ struct asn1_algorithm {
struct cipher_algorithm *cipher;
/** Elliptic curve (if applicable) */
struct elliptic_curve *curve;
/**
* Parse algorithm parameters (optional)
*
* @v algorithm Algorithm
* @v param Parameters to parse (and potentially modify)
* @ret rc Return status code
*/
int ( * parse ) ( struct asn1_algorithm *algorithm,
struct asn1_cursor *params );
};
/** ASN.1 OID-identified algorithms */
@ -467,17 +476,23 @@ extern int asn1_integral_bit_string ( const struct asn1_cursor *cursor,
extern int asn1_compare ( const struct asn1_cursor *cursor1,
const struct asn1_cursor *cursor2 );
extern int asn1_algorithm ( const struct asn1_cursor *cursor,
struct asn1_algorithm **algorithm );
struct asn1_algorithm **algorithm,
struct asn1_cursor *params );
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_cipher_algorithm ( const struct asn1_cursor *cursor,
struct asn1_algorithm **algorithm );
struct asn1_algorithm **algorithm,
struct asn1_cursor *params );
extern int asn1_signature_algorithm ( const struct asn1_cursor *cursor,
struct asn1_algorithm **algorithm );
extern int asn1_check_algorithm ( const struct asn1_cursor *cursor,
struct asn1_algorithm *expected );
extern int asn1_parse_cbc ( struct asn1_algorithm *algorithm,
struct asn1_cursor *params );
extern int asn1_parse_gcm ( struct asn1_algorithm *algorithm,
struct asn1_cursor *params );
extern int asn1_generalized_time ( const struct asn1_cursor *cursor,
time_t *time );
extern int asn1_grow ( struct asn1_builder *builder, size_t extra );