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

◆ 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 82 of file cms.h.

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

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 93 of file cms.h.

93  {
94  ref_put ( &cms->refcnt );
95 }
struct refcnt refcnt
Reference count.
Definition: cms.h:56
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106

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 104 of file cms.h.

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

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 117 of file cms.h.

117  {
118 
119  /* CMS encrypted messages have a cipher algorithm */
120  return ( cms->cipher != NULL );
121 }
struct cipher_algorithm * cipher
Cipher algorithm.
Definition: cms.h:68
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

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 671 of file cms.c.

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

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 833 of file cms.c.

835  {
836  struct cms_participant *part;
837  struct x509_certificate *cert;
838  int count = 0;
839  int rc;
840 
841  /* Mark image as untrusted */
842  image_untrust ( image );
843 
844  /* Sanity check */
845  if ( ! cms_is_signature ( cms ) )
846  return -ENOTTY;
847 
848  /* Verify using all signers */
849  list_for_each_entry ( part, &cms->participants, list ) {
850  cert = x509_first ( part->chain );
851  if ( name && ( x509_check_name ( cert, name ) != 0 ) )
852  continue;
853  if ( ( rc = cms_verify_signer ( cms, part, image->data,
854  image->len, time, store,
855  root ) ) != 0 )
856  return rc;
857  count++;
858  }
859 
860  /* Check that we have verified at least one signature */
861  if ( count == 0 ) {
862  if ( name ) {
863  DBGC ( cms, "CMS %p had no signatures matching name "
864  "%s\n", cms, name );
865  return -EACCES_WRONG_NAME;
866  } else {
867  DBGC ( cms, "CMS %p had no signatures\n", cms );
868  return -EACCES_NO_SIGNATURES;
869  }
870  }
871 
872  /* Mark image as trusted */
873  image_trust ( image );
874 
875  return 0;
876 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
const char * name
Definition: ath9k_hw.c:1984
#define EACCES_NO_SIGNATURES
Definition: cms.c:58
#define EACCES_WRONG_NAME
Definition: cms.c:54
struct stp_switch root
Root switch.
Definition: stp.h:26
const void * data
Read-only data.
Definition: image.h:50
int x509_check_name(struct x509_certificate *cert, const char *name)
Check X.509 certificate name.
Definition: x509.c:1563
#define DBGC(...)
Definition: compiler.h:505
An executable image.
Definition: image.h:23
CMS participant information.
Definition: cms.h:38
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
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:276
An X.509 certificate.
Definition: x509.h:215
size_t len
Length of raw file image.
Definition: image.h:55
static int cms_is_signature(struct cms_message *cms)
Check if CMS message is a signature message.
Definition: cms.h:104
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:781
struct list_head participants
List of participant information blocks.
Definition: cms.h:65
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
static struct x509_certificate * x509_first(struct x509_chain *chain)
Get first certificate in X.509 certificate chain.
Definition: x509.h:310
struct x509_chain * chain
Certificate chain.
Definition: cms.h:42
struct x509_link store
Link in certificate store.
Definition: x509.h:220
static void image_trust(struct image *image)
Set image as trusted.
Definition: image.h:267

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 1038 of file cms.c.

1039  {
1040  struct cipher_algorithm *cipher = cms->cipher;
1041  const unsigned int original_flags = image->flags;
1042  uint8_t ctx[ cipher->ctxsize ];
1043  uint8_t ctxdup[ cipher->ctxsize ];
1044  uint8_t auth[ cipher->authsize ];
1045  uint8_t final[ cipher->blocksize ];
1046  size_t final_len;
1047  size_t bulk_len;
1048  int pad_len;
1049  int rc;
1050 
1051  /* Check block size */
1052  if ( ( image->len & ( cipher->blocksize - 1 ) ) != 0 ) {
1053  DBGC ( cms, "CMS %p invalid length %zd\n", cms, image->len );
1054  rc = -EACCES_LEN;
1055  goto err_blocksize;
1056  }
1057 
1058  /* Initialise cipher */
1059  if ( ( rc = cms_cipher ( cms, private_key, ctx ) ) != 0 )
1060  goto err_cipher;
1061 
1062  /* Duplicate cipher context for potential reencryption on error */
1063  memcpy ( ctxdup, ctx, cipher->ctxsize );
1064 
1065  /* Clear trusted flag before modifying image */
1066  image_untrust ( image );
1067 
1068  /* Temporarily unregister image, if applicable */
1069  if ( original_flags & IMAGE_REGISTERED ) {
1070  image_get ( image );
1071  unregister_image ( image );
1072  }
1073 
1074  /* Decrypt all but the final block */
1075  final_len = ( ( image->len && is_block_cipher ( cipher ) ) ?
1076  cipher->blocksize : 0 );
1077  bulk_len = ( image->len - final_len );
1078  cipher_decrypt ( cipher, ctx, image->data, image->rwdata, bulk_len );
1079 
1080  /* Decrypt final block */
1081  cipher_decrypt ( cipher, ctx, ( image->data + bulk_len ), final,
1082  final_len );
1083 
1084  /* Check authentication tag, if applicable */
1085  cipher_auth ( cipher, ctx, auth );
1086  if ( ( cms->mac.len != cipher->authsize ) ||
1087  ( memcmp ( cms->mac.data, auth, cipher->authsize ) != 0 ) ) {
1088  DBGC ( cms, "CMS %p invalid authentication tag\n", cms );
1089  DBGC_HDA ( cms, 0, auth, cipher->authsize );
1090  rc = -EACCES_MAC;
1091  goto err_auth;
1092  }
1093 
1094  /* Check block padding, if applicable */
1095  if ( ( pad_len = cms_verify_padding ( cms, final, final_len ) ) < 0 ) {
1096  rc = pad_len;
1097  goto err_pad;
1098  }
1099 
1100  /* Update image name. Do this as the last possible failure, so
1101  * that we do not have to include any error-handling code path
1102  * to restore the original image name (which may itself fail).
1103  */
1104  if ( name ) {
1105  if ( ( rc = image_set_name ( image, name ) ) != 0 )
1106  goto err_set_name;
1107  } else {
1109  }
1110 
1111  /* Overwrite final fragment and strip block padding. Do this
1112  * only once no further failure paths exist, so that we do not
1113  * have to include include any error-handling code path to
1114  * reconstruct the block padding.
1115  */
1116  memcpy ( ( image->rwdata + bulk_len ), final, final_len );
1117  image->len -= pad_len;
1118 
1119  /* Clear image type and re-register image, if applicable */
1120  image->type = NULL;
1121  if ( original_flags & IMAGE_REGISTERED ) {
1122  register_image ( image );
1123  image_put ( image );
1124  }
1125 
1126  return 0;
1127 
1128  err_set_name:
1129  err_pad:
1130  err_auth:
1131  /* Reencrypt all overwritten portions. This can be done since
1132  * we have deliberately not overwritten the final block
1133  * containing the potentially invalid (and therefore
1134  * unreproducible) block padding.
1135  */
1136  cipher_encrypt ( cipher, ctxdup, image->data, image->rwdata, bulk_len );
1137  if ( original_flags & IMAGE_REGISTERED ) {
1138  register_image ( image ); /* Cannot fail on re-registration */
1139  image_put ( image );
1140  }
1141  image->flags = original_flags;
1142  err_cipher:
1143  err_blocksize:
1144  return rc;
1145 }
unsigned int flags
Flags.
Definition: image.h:39
size_t blocksize
Block size.
Definition: crypto.h:60
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
const char * name
Definition: ath9k_hw.c:1984
const void * data
Read-only data.
Definition: image.h:50
char * image_strip_suffix(struct image *image)
Strip dot suffix from image name, if present.
Definition: image.c:205
struct image_type * type
Image type, if known.
Definition: image.h:58
static struct image * image_get(struct image *image)
Increment reference count on an image.
Definition: image.h:239
const void * data
Start of data.
Definition: asn1.h:22
#define DBGC(...)
Definition: compiler.h:505
An executable image.
Definition: image.h:23
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
size_t len
Length of data.
Definition: asn1.h:24
#define cipher_encrypt(cipher, ctx, src, dst, len)
Definition: crypto.h:228
size_t authsize
Authentication tag size.
Definition: crypto.h:74
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:76
static void image_untrust(struct image *image)
Set image as untrusted.
Definition: image.h:276
int register_image(struct image *image)
Register executable image.
Definition: image.c:314
struct cipher_algorithm * cipher
Cipher algorithm.
Definition: cms.h:68
size_t len
Length of raw file image.
Definition: image.h:55
int image_set_name(struct image *image, const char *name)
Set image name.
Definition: image.c:180
void(* auth)(void *ctx, void *auth)
Generate authentication tag.
Definition: crypto.h:117
static void image_put(struct image *image)
Decrement reference count on an image.
Definition: image.h:249
unsigned char uint8_t
Definition: stdint.h:10
size_t ctxsize
Context size.
Definition: crypto.h:54
#define cipher_decrypt(cipher, ctx, src, dst, len)
Definition: crypto.h:238
long pad_len
Definition: bigint.h:30
void unregister_image(struct image *image)
Unregister executable image.
Definition: image.c:357
static int cms_cipher(struct cms_message *cms, struct private_key *private_key, void *ctx)
Initialise cipher for CMS decryption.
Definition: cms.c:963
void * rwdata
Writable data.
Definition: image.h:52
A cipher algorithm.
Definition: crypto.h:50
A private key.
Definition: privkey.h:16
static void cipher_auth(struct cipher_algorithm *cipher, void *ctx, void *auth)
Definition: crypto.h:244
struct asn1_cursor mac
Cipher authentication tag.
Definition: cms.h:72
static int cms_verify_padding(struct cms_message *cms, const void *data, size_t len)
Check CMS padding.
Definition: cms.c:990
#define EACCES_MAC
Definition: cms.c:74
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
#define EACCES_LEN
Definition: cms.c:66
static int is_block_cipher(struct cipher_algorithm *cipher)
Definition: crypto.h:254

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