iPXE
Data Structures | Functions
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. More...
 
static void cms_put (struct cms_message *cms)
 Drop reference to CMS message. More...
 
static int cms_is_signature (struct cms_message *cms)
 Check if CMS message is a signature message. More...
 
static int cms_is_encrypted (struct cms_message *cms)
 Check if CMS message is an encrypted message. More...
 
int cms_message (struct image *image, struct cms_message **cms)
 Create CMS message. More...
 
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. More...
 
int cms_decrypt (struct cms_message *cms, struct image *image, const char *name, struct private_key *private_key)
 Decrypt CMS message. More...
 

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()

static 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()

static 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 }
struct refcnt refcnt
Reference count.
Definition: cms.h:57
#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()

static 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 }
struct x509_chain * certificates
List of all certificates (for signature messages)
Definition: cms.h:64
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322

References cms_message::certificates, and NULL.

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

◆ cms_is_encrypted()

static 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
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322

References cms_message::cipher, and NULL.

◆ cms_message()

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

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:14
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:65
#define DBGC(...)
Definition: compiler.h:505
int image_asn1(struct image *image, size_t offset, struct asn1_cursor **cursor)
Extract ASN.1 object from image.
Definition: asn1.c:1028
An executable image.
Definition: image.h:24
#define ENOMEM
Not enough space.
Definition: errno.h:535
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
static int cms_parse(struct cms_message *cms)
Parse CMS message from ASN.1 data.
Definition: cms.c:618
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:662
int asn1_shrink_any(struct asn1_cursor *cursor)
Shrink ASN.1 object of any type.
Definition: asn1.c:300
uint32_t next
Next descriptor address.
Definition: dwmac.h:22
struct cipher_algorithm cipher_null
Definition: crypto_null.c:84
static void cms_free(struct refcnt *refcnt)
Free CMS message.
Definition: cms.c:646
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition: list.h:46
static void cms_put(struct cms_message *cms)
Drop reference to CMS message.
Definition: cms.h:94

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 
)

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 */
843  image_untrust ( image );
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
const char * name
Definition: ath9k_hw.c:1986
#define EACCES_NO_SIGNATURES
Definition: cms.c:59
#define EACCES_WRONG_NAME
Definition: cms.c:55
struct stp_switch root
Root switch.
Definition: stp.h:27
const void * data
Read-only data.
Definition: image.h:51
int x509_check_name(struct x509_certificate *cert, const char *name)
Check X.509 certificate name.
Definition: x509.c:1564
#define DBGC(...)
Definition: compiler.h:505
An executable image.
Definition: image.h:24
CMS participant information.
Definition: cms.h:39
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:432
static unsigned int count
Number of entries.
Definition: dwmac.h:225
static void image_untrust(struct image *image)
Set image as untrusted.
Definition: image.h:277
An X.509 certificate.
Definition: x509.h:216
size_t len
Length of raw file image.
Definition: image.h:56
static int cms_is_signature(struct cms_message *cms)
Check if CMS message is a signature message.
Definition: cms.h:105
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
struct list_head participants
List of participant information blocks.
Definition: cms.h:66
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:595
static struct x509_certificate * x509_first(struct x509_chain *chain)
Get first certificate in X.509 certificate chain.
Definition: x509.h:311
struct x509_chain * chain
Certificate chain.
Definition: cms.h:43
struct x509_link store
Link in certificate store.
Definition: x509.h:221
static void image_trust(struct image *image)
Set image as trusted.
Definition: image.h:268

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 
)

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 );
1072  unregister_image ( 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 ) {
1123  register_image ( image );
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 }
unsigned int flags
Flags.
Definition: image.h:40
size_t blocksize
Block size.
Definition: crypto.h:61
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
const char * name
Definition: ath9k_hw.c:1986
const void * data
Read-only data.
Definition: image.h:51
char * image_strip_suffix(struct image *image)
Strip dot suffix from image name, if present.
Definition: image.c:206
struct image_type * type
Image type, if known.
Definition: image.h:59
static struct image * image_get(struct image *image)
Increment reference count on an image.
Definition: image.h:240
const void * data
Start of data.
Definition: asn1.h:23
#define DBGC(...)
Definition: compiler.h:505
An executable image.
Definition: image.h:24
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
size_t len
Length of data.
Definition: asn1.h:25
#define cipher_encrypt(cipher, ctx, src, dst, len)
Definition: crypto.h:251
size_t authsize
Authentication tag size.
Definition: crypto.h:75
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define DBGC_HDA(...)
Definition: compiler.h:506
#define IMAGE_REGISTERED
Image is registered.
Definition: image.h:77
static void image_untrust(struct image *image)
Set image as untrusted.
Definition: image.h:277
int register_image(struct image *image)
Register executable image.
Definition: image.c:315
struct cipher_algorithm * cipher
Cipher algorithm.
Definition: cms.h:69
size_t len
Length of raw file image.
Definition: image.h:56
int image_set_name(struct image *image, const char *name)
Set image name.
Definition: image.c:181
void(* auth)(void *ctx, void *auth)
Generate authentication tag.
Definition: crypto.h:118
static void image_put(struct image *image)
Decrement reference count on an image.
Definition: image.h:250
unsigned char uint8_t
Definition: stdint.h:10
size_t ctxsize
Context size.
Definition: crypto.h:55
#define cipher_decrypt(cipher, ctx, src, dst, len)
Definition: crypto.h:261
long pad_len
Definition: bigint.h:31
void unregister_image(struct image *image)
Unregister executable image.
Definition: image.c:358
static int cms_cipher(struct cms_message *cms, struct private_key *private_key, void *ctx)
Initialise cipher for CMS decryption.
Definition: cms.c:964
void * rwdata
Writable data.
Definition: image.h:53
A cipher algorithm.
Definition: crypto.h:51
A private key.
Definition: privkey.h:17
static void cipher_auth(struct cipher_algorithm *cipher, void *ctx, void *auth)
Definition: crypto.h:267
struct asn1_cursor mac
Cipher authentication tag.
Definition: cms.h:73
static int cms_verify_padding(struct cms_message *cms, const void *data, size_t len)
Check CMS padding.
Definition: cms.c:991
#define EACCES_MAC
Definition: cms.c:75
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:115
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
#define EACCES_LEN
Definition: cms.c:67
static int is_block_cipher(struct cipher_algorithm *cipher)
Definition: crypto.h:277

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().