iPXE
cms.h File Reference

Cryptographic Message Syntax (PKCS #7) More...

#include <time.h>
#include <ipxe/asn1.h>
#include <ipxe/crypto.h>
#include <ipxe/x509.h>
#include <ipxe/refcnt.h>

Go to the source code of this file.

Data Structures

struct  cms_type
 A CMS message type. More...
struct  cms_participant
 CMS participant information. More...
struct  cms_message
 A CMS message. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static struct cms_messagecms_get (struct cms_message *cms)
 Get reference to CMS message.
static void cms_put (struct cms_message *cms)
 Drop reference to CMS message.
static int cms_is_signature (struct cms_message *cms)
 Check if CMS message is a signature message.
static int cms_is_encrypted (struct cms_message *cms)
 Check if CMS message is an encrypted message.
int cms_message (struct image *image, struct cms_message **cms)
 Create CMS message.
int cms_verify (struct cms_message *cms, struct image *image, const char *name, time_t time, struct x509_chain *store, struct x509_root *root)
 Verify CMS signature.
int cms_decrypt (struct cms_message *cms, struct image *image, const char *name, struct private_key *private_key)
 Decrypt CMS message.

Detailed Description

Cryptographic Message Syntax (PKCS #7)

Definition in file cms.h.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ cms_get()

struct cms_message * cms_get ( struct cms_message * cms)
inlinestatic

Get reference to CMS message.

Parameters
cmsCMS message
Return values
cmsCMS message

Definition at line 83 of file cms.h.

83 {
84 ref_get ( &cms->refcnt );
85 return cms;
86}
#define ref_get(refcnt)
Get additional reference to object.
Definition refcnt.h:93
struct refcnt refcnt
Reference count.
Definition cms.h:57

References ref_get, and cms_message::refcnt.

◆ cms_put()

void cms_put ( struct cms_message * cms)
inlinestatic

Drop reference to CMS message.

Parameters
cmsCMS message

Definition at line 94 of file cms.h.

94 {
95 ref_put ( &cms->refcnt );
96}
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107

References ref_put, and cms_message::refcnt.

Referenced by cms_message(), cms_test_exec(), imgdecrypt(), and imgverify().

◆ cms_is_signature()

int cms_is_signature ( struct cms_message * cms)
inlinestatic

Check if CMS message is a signature message.

Parameters
cmsCMS message
Return values
is_signatureMessage is a signature message

Definition at line 105 of file cms.h.

105 {
106
107 /* CMS signatures include an optional CertificateSet */
108 return ( cms->certificates != NULL );
109}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
struct x509_chain * certificates
List of all certificates (for signature messages)
Definition cms.h:64

References cms_message::certificates, and NULL.

Referenced by cms_parse_identifier(), cms_parse_participant(), and cms_verify().

◆ cms_is_encrypted()

int cms_is_encrypted ( struct cms_message * cms)
inlinestatic

Check if CMS message is an encrypted message.

Parameters
cmsCMS message
Return values
is_encryptedMessage is an encrypted message

Definition at line 118 of file cms.h.

118 {
119
120 /* CMS encrypted messages have a cipher algorithm */
121 return ( cms->cipher != NULL );
122}
struct cipher_algorithm * cipher
Cipher algorithm.
Definition cms.h:69

References cms_message::cipher, and NULL.

◆ cms_message()

int cms_message ( struct image * image,
struct cms_message ** cms )
extern

Create CMS message.

Parameters
imageImage
Return values
sigCMS message
rcReturn status code

On success, the caller holds a reference to the CMS message, and is responsible for ultimately calling cms_put().

Definition at line 672 of file cms.c.

672 {
673 int next;
674 int rc;
675
676 /* Allocate and initialise message */
677 *cms = zalloc ( sizeof ( **cms ) );
678 if ( ! *cms ) {
679 rc = -ENOMEM;
680 goto err_alloc;
681 }
682 ref_init ( &(*cms)->refcnt, cms_free );
683 INIT_LIST_HEAD ( &(*cms)->participants );
684 (*cms)->cipher = &cipher_null;
685
686 /* Get raw message data */
687 next = image_asn1 ( image, 0, &(*cms)->raw );
688 if ( next < 0 ) {
689 rc = next;
690 DBGC ( *cms, "CMS %p could not get raw ASN.1 data: %s\n",
691 *cms, strerror ( rc ) );
692 goto err_asn1;
693 }
694
695 /* Use only first message in image */
696 asn1_shrink_any ( (*cms)->raw );
697
698 /* Parse message */
699 if ( ( rc = cms_parse ( *cms ) ) != 0 )
700 goto err_parse;
701
702 return 0;
703
704 err_parse:
705 err_asn1:
706 cms_put ( *cms );
707 err_alloc:
708 return rc;
709}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
int image_asn1(struct image *image, size_t offset, struct asn1_cursor **cursor)
Extract ASN.1 object from image.
Definition asn1.c:1028
int asn1_shrink_any(struct asn1_cursor *cursor)
Shrink ASN.1 object of any type.
Definition asn1.c:300
static int cms_parse(struct cms_message *cms)
Parse CMS message from ASN.1 data.
Definition cms.c:618
static void cms_free(struct refcnt *refcnt)
Free CMS message.
Definition cms.c:646
static void cms_put(struct cms_message *cms)
Drop reference to CMS message.
Definition cms.h:94
struct cipher_algorithm cipher_null
Definition crypto_null.c:84
uint32_t next
Next descriptor address.
Definition dwmac.h:11
#define DBGC(...)
Definition compiler.h:505
#define ENOMEM
Not enough space.
Definition errno.h:535
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
An executable image.
Definition image.h:24

References asn1_shrink_any(), cipher_null, cms_free(), cms_parse(), cms_put(), DBGC, ENOMEM, image_asn1(), INIT_LIST_HEAD, next, rc, ref_init, strerror(), and zalloc().

◆ cms_verify()

int cms_verify ( struct cms_message * cms,
struct image * image,
const char * name,
time_t time,
struct x509_chain * store,
struct x509_root * root )
extern

Verify CMS signature.

Parameters
cmsCMS message
imageSigned image
nameRequired common name, or NULL to check all signatures
timeTime at which to validate certificates
storeCertificate store, or NULL to use default
rootRoot certificate list, or NULL to use default
Return values
rcReturn status code

Definition at line 834 of file cms.c.

836 {
837 struct cms_participant *part;
838 struct x509_certificate *cert;
839 int count = 0;
840 int rc;
841
842 /* Mark image as untrusted */
844
845 /* Sanity check */
846 if ( ! cms_is_signature ( cms ) )
847 return -ENOTTY;
848
849 /* Verify using all signers */
850 list_for_each_entry ( part, &cms->participants, list ) {
851 cert = x509_first ( part->chain );
852 if ( name && ( x509_check_name ( cert, name ) != 0 ) )
853 continue;
854 if ( ( rc = cms_verify_signer ( cms, part, image->data,
855 image->len, time, store,
856 root ) ) != 0 )
857 return rc;
858 count++;
859 }
860
861 /* Check that we have verified at least one signature */
862 if ( count == 0 ) {
863 if ( name ) {
864 DBGC ( cms, "CMS %p had no signatures matching name "
865 "%s\n", cms, name );
866 return -EACCES_WRONG_NAME;
867 } else {
868 DBGC ( cms, "CMS %p had no signatures\n", cms );
869 return -EACCES_NO_SIGNATURES;
870 }
871 }
872
873 /* Mark image as trusted */
874 image_trust ( image );
875
876 return 0;
877}
const char * name
Definition ath9k_hw.c:1986
static int cms_verify_signer(struct cms_message *cms, struct cms_participant *part, const void *data, size_t len, time_t time, struct x509_chain *store, struct x509_root *root)
Verify CMS message signer.
Definition cms.c:782
#define EACCES_WRONG_NAME
Definition cms.c:55
#define EACCES_NO_SIGNATURES
Definition cms.c:59
static int cms_is_signature(struct cms_message *cms)
Check if CMS message is a signature message.
Definition cms.h:105
static unsigned int count
Number of entries.
Definition dwmac.h:220
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
static void image_trust(struct image *image)
Set image as trusted.
Definition image.h:268
static void image_untrust(struct image *image)
Set image as untrusted.
Definition image.h:277
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
struct stp_switch root
Root switch.
Definition stp.h:15
struct list_head participants
List of participant information blocks.
Definition cms.h:66
CMS participant information.
Definition cms.h:39
struct x509_chain * chain
Certificate chain.
Definition cms.h:43
const void * data
Read-only data.
Definition image.h:51
size_t len
Length of raw file image.
Definition image.h:56
An X.509 certificate.
Definition x509.h:216
struct x509_link store
Link in certificate store.
Definition x509.h:221
int x509_check_name(struct x509_certificate *cert, const char *name)
Check X.509 certificate name.
Definition x509.c:1564
static struct x509_certificate * x509_first(struct x509_chain *chain)
Get first certificate in X.509 certificate chain.
Definition x509.h:311

References cms_participant::chain, cms_is_signature(), cms_verify_signer(), count, image::data, DBGC, EACCES_NO_SIGNATURES, EACCES_WRONG_NAME, ENOTTY, image_trust(), image_untrust(), image::len, list_for_each_entry, name, cms_message::participants, rc, root, x509_certificate::store, x509_check_name(), and x509_first().

Referenced by cms_verify_fail_okx(), cms_verify_okx(), and imgverify().

◆ cms_decrypt()

int cms_decrypt ( struct cms_message * cms,
struct image * image,
const char * name,
struct private_key * private_key )
extern

Decrypt CMS message.

Parameters
cmsCMS message
imageImage to decrypt
nameDecrypted image name, or NULL to use default
private_keyPrivate key
Return values
rcReturn status code

Definition at line 1039 of file cms.c.

1040 {
1041 struct cipher_algorithm *cipher = cms->cipher;
1042 const unsigned int original_flags = image->flags;
1043 uint8_t ctx[ cipher->ctxsize ];
1044 uint8_t ctxdup[ cipher->ctxsize ];
1045 uint8_t auth[ cipher->authsize ];
1046 uint8_t final[ cipher->blocksize ];
1047 size_t final_len;
1048 size_t bulk_len;
1049 int pad_len;
1050 int rc;
1051
1052 /* Check block size */
1053 if ( ( image->len & ( cipher->blocksize - 1 ) ) != 0 ) {
1054 DBGC ( cms, "CMS %p invalid length %zd\n", cms, image->len );
1055 rc = -EACCES_LEN;
1056 goto err_blocksize;
1057 }
1058
1059 /* Initialise cipher */
1060 if ( ( rc = cms_cipher ( cms, private_key, ctx ) ) != 0 )
1061 goto err_cipher;
1062
1063 /* Duplicate cipher context for potential reencryption on error */
1064 memcpy ( ctxdup, ctx, cipher->ctxsize );
1065
1066 /* Clear trusted flag before modifying image */
1067 image_untrust ( image );
1068
1069 /* Temporarily unregister image, if applicable */
1070 if ( original_flags & IMAGE_REGISTERED ) {
1071 image_get ( image );
1073 }
1074
1075 /* Decrypt all but the final block */
1076 final_len = ( ( image->len && is_block_cipher ( cipher ) ) ?
1077 cipher->blocksize : 0 );
1078 bulk_len = ( image->len - final_len );
1079 cipher_decrypt ( cipher, ctx, image->data, image->rwdata, bulk_len );
1080
1081 /* Decrypt final block */
1082 cipher_decrypt ( cipher, ctx, ( image->data + bulk_len ), final,
1083 final_len );
1084
1085 /* Check authentication tag, if applicable */
1086 cipher_auth ( cipher, ctx, auth );
1087 if ( ( cms->mac.len != cipher->authsize ) ||
1088 ( memcmp ( cms->mac.data, auth, cipher->authsize ) != 0 ) ) {
1089 DBGC ( cms, "CMS %p invalid authentication tag\n", cms );
1090 DBGC_HDA ( cms, 0, auth, cipher->authsize );
1091 rc = -EACCES_MAC;
1092 goto err_auth;
1093 }
1094
1095 /* Check block padding, if applicable */
1096 if ( ( pad_len = cms_verify_padding ( cms, final, final_len ) ) < 0 ) {
1097 rc = pad_len;
1098 goto err_pad;
1099 }
1100
1101 /* Update image name. Do this as the last possible failure, so
1102 * that we do not have to include any error-handling code path
1103 * to restore the original image name (which may itself fail).
1104 */
1105 if ( name ) {
1106 if ( ( rc = image_set_name ( image, name ) ) != 0 )
1107 goto err_set_name;
1108 } else {
1110 }
1111
1112 /* Overwrite final fragment and strip block padding. Do this
1113 * only once no further failure paths exist, so that we do not
1114 * have to include include any error-handling code path to
1115 * reconstruct the block padding.
1116 */
1117 memcpy ( ( image->rwdata + bulk_len ), final, final_len );
1118 image->len -= pad_len;
1119
1120 /* Clear image type and re-register image, if applicable */
1121 image->type = NULL;
1122 if ( original_flags & IMAGE_REGISTERED ) {
1124 image_put ( image );
1125 }
1126
1127 return 0;
1128
1129 err_set_name:
1130 err_pad:
1131 err_auth:
1132 /* Reencrypt all overwritten portions. This can be done since
1133 * we have deliberately not overwritten the final block
1134 * containing the potentially invalid (and therefore
1135 * unreproducible) block padding.
1136 */
1137 cipher_encrypt ( cipher, ctxdup, image->data, image->rwdata, bulk_len );
1138 if ( original_flags & IMAGE_REGISTERED ) {
1139 register_image ( image ); /* Cannot fail on re-registration */
1140 image_put ( image );
1141 }
1142 image->flags = original_flags;
1143 err_cipher:
1144 err_blocksize:
1145 return rc;
1146}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
unsigned char uint8_t
Definition stdint.h:10
long pad_len
Definition bigint.h:31
static int cms_cipher(struct cms_message *cms, struct private_key *private_key, void *ctx)
Initialise cipher for CMS decryption.
Definition cms.c:964
static int cms_verify_padding(struct cms_message *cms, const void *data, size_t len)
Check CMS padding.
Definition cms.c:991
#define EACCES_LEN
Definition cms.c:67
#define EACCES_MAC
Definition cms.c:75
#define DBGC_HDA(...)
Definition compiler.h:506
char * image_strip_suffix(struct image *image)
Strip dot suffix from image name, if present.
Definition image.c:206
void unregister_image(struct image *image)
Unregister executable image.
Definition image.c:358
int register_image(struct image *image)
Register executable image.
Definition image.c:315
int image_set_name(struct image *image, const char *name)
Set image name.
Definition image.c:181
static struct image * image_get(struct image *image)
Increment reference count on an image.
Definition image.h:240
#define IMAGE_REGISTERED
Image is registered.
Definition image.h:77
static void image_put(struct image *image)
Decrement reference count on an image.
Definition image.h:250
static int is_block_cipher(struct cipher_algorithm *cipher)
Definition crypto.h:277
#define cipher_decrypt(cipher, ctx, src, dst, len)
Definition crypto.h:261
#define cipher_encrypt(cipher, ctx, src, dst, len)
Definition crypto.h:251
static void cipher_auth(struct cipher_algorithm *cipher, void *ctx, void *auth)
Definition crypto.h:267
void * memcpy(void *dest, const void *src, size_t len) __nonnull
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
const void * data
Start of data.
Definition asn1.h:23
size_t len
Length of data.
Definition asn1.h:25
A cipher algorithm.
Definition crypto.h:51
void(* auth)(void *ctx, void *auth)
Generate authentication tag.
Definition crypto.h:118
size_t blocksize
Block size.
Definition crypto.h:61
size_t ctxsize
Context size.
Definition crypto.h:55
size_t authsize
Authentication tag size.
Definition crypto.h:75
struct asn1_cursor mac
Cipher authentication tag.
Definition cms.h:73
unsigned int flags
Flags.
Definition image.h:40
struct image_type * type
Image type, if known.
Definition image.h:59
void * rwdata
Writable data.
Definition image.h:53
A private key.
Definition privkey.h:17

References cipher_algorithm::auth, cipher_algorithm::authsize, cipher_algorithm::blocksize, cms_message::cipher, cipher_auth(), cipher_decrypt, cipher_encrypt, cms_cipher(), cms_verify_padding(), ctx, cipher_algorithm::ctxsize, asn1_cursor::data, image::data, DBGC, DBGC_HDA, EACCES_LEN, EACCES_MAC, image::flags, image_get(), image_put(), IMAGE_REGISTERED, image_set_name(), image_strip_suffix(), image_untrust(), is_block_cipher(), asn1_cursor::len, image::len, cms_message::mac, memcmp(), memcpy(), name, NULL, pad_len, rc, register_image(), image::rwdata, image::type, and unregister_image().

Referenced by cms_decrypt_okx(), and imgdecrypt().