[crypto] Generalise cms_signature to cms_message

There is some exploitable similarity between the data structures used
for representing CMS signatures and CMS encryption keys.  In both
cases, the CMS message fundamentally encodes a list of participants
(either message signers or message recipients), where each participant
has an associated certificate and an opaque octet string representing
the signature or encrypted cipher key.  The ASN.1 structures are not
identical, but are sufficiently similar to be worth exploiting: for
example, the SignerIdentifier and RecipientIdentifier data structures
are defined identically.

Rename data structures and functions, and add the concept of a CMS
message type.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2024-08-12 12:36:41 +01:00
parent 998edc6ec5
commit 97635eb71b
5 changed files with 366 additions and 286 deletions

View File

@@ -303,7 +303,7 @@ struct asn1_builder_header {
ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \
ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 3 )
/** ASN.1 OID for pkcs-signedData (1.2.840.113549.1.7.2) */
/** ASN.1 OID for id-signedData (1.2.840.113549.1.7.2) */
#define ASN1_OID_SIGNEDDATA \
ASN1_OID_INITIAL ( 1, 2 ), ASN1_OID_DOUBLE ( 840 ), \
ASN1_OID_TRIPLE ( 113549 ), ASN1_OID_SINGLE ( 1 ), \

View File

@@ -17,61 +17,92 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/uaccess.h>
struct image;
struct cms_message;
/** CMS signer information */
struct cms_signer_info {
/** List of signer information blocks */
/** A CMS message type */
struct cms_type {
/** Name */
const char *name;
/** Object identifier */
struct asn1_cursor oid;
/** Parse content
*
* @v cms CMS message
* @v raw ASN.1 cursor
* @ret rc Return status code
*/
int ( * parse ) ( struct cms_message *cms,
const struct asn1_cursor *raw );
};
/** CMS participant information */
struct cms_participant {
/** List of participant information blocks */
struct list_head list;
/** Certificate chain */
struct x509_chain *chain;
/** Digest algorithm */
/** Digest algorithm (for signature messages) */
struct digest_algorithm *digest;
/** Public-key algorithm */
struct pubkey_algorithm *pubkey;
/** Signature */
void *signature;
/** Length of signature */
size_t signature_len;
/** Signature or key value */
void *value;
/** Length of signature or key value */
size_t len;
};
/** A CMS signature */
struct cms_signature {
/** A CMS message */
struct cms_message {
/** Reference count */
struct refcnt refcnt;
/** List of all certificates */
/** Message type */
struct cms_type *type;
/** List of all certificates (for signature messages) */
struct x509_chain *certificates;
/** List of signer information blocks */
struct list_head info;
/** List of participant information blocks */
struct list_head participants;
};
/**
* Get reference to CMS signature
* Get reference to CMS message
*
* @v sig CMS signature
* @ret sig CMS signature
* @v cms CMS message
* @ret cms CMS message
*/
static inline __attribute__ (( always_inline )) struct cms_signature *
cms_get ( struct cms_signature *sig ) {
ref_get ( &sig->refcnt );
return sig;
static inline __attribute__ (( always_inline )) struct cms_message *
cms_get ( struct cms_message *cms ) {
ref_get ( &cms->refcnt );
return cms;
}
/**
* Drop reference to CMS signature
* Drop reference to CMS message
*
* @v sig CMS signature
* @v cms CMS message
*/
static inline __attribute__ (( always_inline )) void
cms_put ( struct cms_signature *sig ) {
ref_put ( &sig->refcnt );
cms_put ( struct cms_message *cms ) {
ref_put ( &cms->refcnt );
}
extern int cms_signature ( struct image *image,
struct cms_signature **sig );
extern int cms_verify ( struct cms_signature *sig, struct image *image,
/**
* Check if CMS message is a signature message
*
* @v cms CMS message
* @ret is_signature Message is a signature message
*/
static inline __attribute__ (( always_inline )) int
cms_is_signature ( struct cms_message *cms ) {
/* CMS signatures include an optional CertificateSet */
return ( cms->certificates != NULL );
}
extern int cms_message ( struct image *image, struct cms_message **cms );
extern int cms_verify ( struct cms_message *cms, struct image *image,
const char *name, time_t time, struct x509_chain *store,
struct x509_root *root );