mirror of https://github.com/ipxe/ipxe.git
[crypto] Hold CMS message as a single ASN.1 object
Reduce the number of dynamic allocations required to parse a CMS message by retaining the ASN.1 cursor returned from image_asn1() for the lifetime of the CMS message. This allows embedded ASN.1 cursors to be used for parsed objects within the message, such as embedded signatures. Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/1171/head
parent
46937a9df6
commit
bdb5b4aef4
|
@ -293,26 +293,18 @@ static int cms_parse_pubkey_algorithm ( struct cms_message *cms,
|
||||||
static int cms_parse_value ( struct cms_message *cms,
|
static int cms_parse_value ( struct cms_message *cms,
|
||||||
struct cms_participant *part,
|
struct cms_participant *part,
|
||||||
const struct asn1_cursor *raw ) {
|
const struct asn1_cursor *raw ) {
|
||||||
struct asn1_cursor cursor;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Enter signature */
|
/* Enter signature */
|
||||||
memcpy ( &cursor, raw, sizeof ( cursor ) );
|
memcpy ( &part->value, raw, sizeof ( part->value ) );
|
||||||
if ( ( rc = asn1_enter ( &cursor, ASN1_OCTET_STRING ) ) != 0 ) {
|
if ( ( rc = asn1_enter ( &part->value, ASN1_OCTET_STRING ) ) != 0 ) {
|
||||||
DBGC ( cms, "CMS %p/%p could not locate value:\n",
|
DBGC ( cms, "CMS %p/%p could not locate value:\n",
|
||||||
cms, part );
|
cms, part );
|
||||||
DBGC_HDA ( cms, 0, raw->data, raw->len );
|
DBGC_HDA ( cms, 0, raw->data, raw->len );
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Record signature */
|
|
||||||
part->len = cursor.len;
|
|
||||||
part->value = malloc ( part->len );
|
|
||||||
if ( ! part->value )
|
|
||||||
return -ENOMEM;
|
|
||||||
memcpy ( part->value, cursor.data, part->len );
|
|
||||||
DBGC ( cms, "CMS %p/%p value is:\n", cms, part );
|
DBGC ( cms, "CMS %p/%p value is:\n", cms, part );
|
||||||
DBGC_HDA ( cms, 0, part->value, part->len );
|
DBGC_HDA ( cms, 0, part->value.data, part->value.len );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -456,16 +448,14 @@ static int cms_parse_signed ( struct cms_message *cms,
|
||||||
* Parse CMS message from ASN.1 data
|
* Parse CMS message from ASN.1 data
|
||||||
*
|
*
|
||||||
* @v cms CMS message
|
* @v cms CMS message
|
||||||
* @v raw ASN.1 cursor
|
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int cms_parse ( struct cms_message *cms,
|
static int cms_parse ( struct cms_message *cms ) {
|
||||||
const struct asn1_cursor *raw ) {
|
|
||||||
struct asn1_cursor cursor;
|
struct asn1_cursor cursor;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Enter contentInfo */
|
/* Enter contentInfo */
|
||||||
memcpy ( &cursor, raw, sizeof ( cursor ) );
|
memcpy ( &cursor, cms->raw, sizeof ( cursor ) );
|
||||||
asn1_enter ( &cursor, ASN1_SEQUENCE );
|
asn1_enter ( &cursor, ASN1_SEQUENCE );
|
||||||
|
|
||||||
/* Parse contentType */
|
/* Parse contentType */
|
||||||
|
@ -497,10 +487,10 @@ static void cms_free ( struct refcnt *refcnt ) {
|
||||||
list_for_each_entry_safe ( part, tmp, &cms->participants, list ) {
|
list_for_each_entry_safe ( part, tmp, &cms->participants, list ) {
|
||||||
list_del ( &part->list );
|
list_del ( &part->list );
|
||||||
x509_chain_put ( part->chain );
|
x509_chain_put ( part->chain );
|
||||||
free ( part->value );
|
|
||||||
free ( part );
|
free ( part );
|
||||||
}
|
}
|
||||||
x509_chain_put ( cms->certificates );
|
x509_chain_put ( cms->certificates );
|
||||||
|
free ( cms->raw );
|
||||||
free ( cms );
|
free ( cms );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,7 +505,6 @@ static void cms_free ( struct refcnt *refcnt ) {
|
||||||
* is responsible for ultimately calling cms_put().
|
* is responsible for ultimately calling cms_put().
|
||||||
*/
|
*/
|
||||||
int cms_message ( struct image *image, struct cms_message **cms ) {
|
int cms_message ( struct image *image, struct cms_message **cms ) {
|
||||||
struct asn1_cursor *raw;
|
|
||||||
int next;
|
int next;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -529,7 +518,7 @@ int cms_message ( struct image *image, struct cms_message **cms ) {
|
||||||
INIT_LIST_HEAD ( &(*cms)->participants );
|
INIT_LIST_HEAD ( &(*cms)->participants );
|
||||||
|
|
||||||
/* Get raw message data */
|
/* Get raw message data */
|
||||||
next = image_asn1 ( image, 0, &raw );
|
next = image_asn1 ( image, 0, &(*cms)->raw );
|
||||||
if ( next < 0 ) {
|
if ( next < 0 ) {
|
||||||
rc = next;
|
rc = next;
|
||||||
DBGC ( *cms, "CMS %p could not get raw ASN.1 data: %s\n",
|
DBGC ( *cms, "CMS %p could not get raw ASN.1 data: %s\n",
|
||||||
|
@ -538,19 +527,15 @@ int cms_message ( struct image *image, struct cms_message **cms ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use only first message in image */
|
/* Use only first message in image */
|
||||||
asn1_shrink_any ( raw );
|
asn1_shrink_any ( (*cms)->raw );
|
||||||
|
|
||||||
/* Parse message */
|
/* Parse message */
|
||||||
if ( ( rc = cms_parse ( *cms, raw ) ) != 0 )
|
if ( ( rc = cms_parse ( *cms ) ) != 0 )
|
||||||
goto err_parse;
|
goto err_parse;
|
||||||
|
|
||||||
/* Free raw message data */
|
|
||||||
free ( raw );
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_parse:
|
err_parse:
|
||||||
free ( raw );
|
|
||||||
err_asn1:
|
err_asn1:
|
||||||
cms_put ( *cms );
|
cms_put ( *cms );
|
||||||
err_alloc:
|
err_alloc:
|
||||||
|
@ -612,7 +597,8 @@ static int cms_verify_digest ( struct cms_message *cms,
|
||||||
userptr_t data, size_t len ) {
|
userptr_t data, size_t len ) {
|
||||||
struct digest_algorithm *digest = part->digest;
|
struct digest_algorithm *digest = part->digest;
|
||||||
struct pubkey_algorithm *pubkey = part->pubkey;
|
struct pubkey_algorithm *pubkey = part->pubkey;
|
||||||
struct asn1_cursor *key = &cert->subject.public_key.raw;
|
const struct asn1_cursor *key = &cert->subject.public_key.raw;
|
||||||
|
const struct asn1_cursor *value = &part->value;
|
||||||
uint8_t digest_out[ digest->digestsize ];
|
uint8_t digest_out[ digest->digestsize ];
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -621,7 +607,7 @@ static int cms_verify_digest ( struct cms_message *cms,
|
||||||
|
|
||||||
/* Verify digest */
|
/* Verify digest */
|
||||||
if ( ( rc = pubkey_verify ( pubkey, key, digest, digest_out,
|
if ( ( rc = pubkey_verify ( pubkey, key, digest, digest_out,
|
||||||
part->value, part->len ) ) != 0 ) {
|
value->data, value->len ) ) != 0 ) {
|
||||||
DBGC ( cms, "CMS %p/%p signature verification failed: %s\n",
|
DBGC ( cms, "CMS %p/%p signature verification failed: %s\n",
|
||||||
cms, part, strerror ( rc ) );
|
cms, part, strerror ( rc ) );
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -48,15 +48,15 @@ struct cms_participant {
|
||||||
struct pubkey_algorithm *pubkey;
|
struct pubkey_algorithm *pubkey;
|
||||||
|
|
||||||
/** Signature or key value */
|
/** Signature or key value */
|
||||||
void *value;
|
struct asn1_cursor value;
|
||||||
/** Length of signature or key value */
|
|
||||||
size_t len;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A CMS message */
|
/** A CMS message */
|
||||||
struct cms_message {
|
struct cms_message {
|
||||||
/** Reference count */
|
/** Reference count */
|
||||||
struct refcnt refcnt;
|
struct refcnt refcnt;
|
||||||
|
/** Raw ASN.1 data */
|
||||||
|
struct asn1_cursor *raw;
|
||||||
/** Message type */
|
/** Message type */
|
||||||
struct cms_type *type;
|
struct cms_type *type;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue