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>
#include <ipxe/uaccess.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 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:92
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: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 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: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 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: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 677 of file cms.c.

677  {
678  int next;
679  int rc;
680 
681  /* Allocate and initialise message */
682  *cms = zalloc ( sizeof ( **cms ) );
683  if ( ! *cms ) {
684  rc = -ENOMEM;
685  goto err_alloc;
686  }
687  ref_init ( &(*cms)->refcnt, cms_free );
688  INIT_LIST_HEAD ( &(*cms)->participants );
689  (*cms)->cipher = &cipher_null;
690 
691  /* Get raw message data */
692  next = image_asn1 ( image, 0, &(*cms)->raw );
693  if ( next < 0 ) {
694  rc = next;
695  DBGC ( *cms, "CMS %p could not get raw ASN.1 data: %s\n",
696  *cms, strerror ( rc ) );
697  goto err_asn1;
698  }
699 
700  /* Use only first message in image */
701  asn1_shrink_any ( (*cms)->raw );
702 
703  /* Parse message */
704  if ( ( rc = cms_parse ( *cms ) ) != 0 )
705  goto err_parse;
706 
707  return 0;
708 
709  err_parse:
710  err_asn1:
711  cms_put ( *cms );
712  err_alloc:
713  return rc;
714 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
uint32_t next
Next descriptor address.
Definition: myson.h:18
#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:1002
An executable image.
Definition: image.h:24
#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:623
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
int asn1_shrink_any(struct asn1_cursor *cursor)
Shrink ASN.1 object of any type.
Definition: asn1.c:323
struct cipher_algorithm cipher_null
Definition: crypto_null.c:83
static void cms_free(struct refcnt *refcnt)
Free CMS message.
Definition: cms.c:651
#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: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 854 of file cms.c.

856  {
857  struct cms_participant *part;
858  struct x509_certificate *cert;
859  int count = 0;
860  int rc;
861 
862  /* Mark image as untrusted */
863  image_untrust ( image );
864 
865  /* Sanity check */
866  if ( ! cms_is_signature ( cms ) )
867  return -ENOTTY;
868 
869  /* Verify using all signers */
870  list_for_each_entry ( part, &cms->participants, list ) {
871  cert = x509_first ( part->chain );
872  if ( name && ( x509_check_name ( cert, name ) != 0 ) )
873  continue;
874  if ( ( rc = cms_verify_signer ( cms, part, image->data,
875  image->len, time, store,
876  root ) ) != 0 )
877  return rc;
878  count++;
879  }
880 
881  /* Check that we have verified at least one signature */
882  if ( count == 0 ) {
883  if ( name ) {
884  DBGC ( cms, "CMS %p had no signatures matching name "
885  "%s\n", cms, name );
886  return -EACCES_WRONG_NAME;
887  } else {
888  DBGC ( cms, "CMS %p had no signatures\n", cms );
889  return -EACCES_NO_SIGNATURES;
890  }
891  }
892 
893  /* Mark image as trusted */
894  image_trust ( image );
895 
896  return 0;
897 }
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:59
userptr_t data
Raw file image.
Definition: image.h:41
#define EACCES_WRONG_NAME
Definition: cms.c:55
struct stp_switch root
Root switch.
Definition: stp.h:26
int x509_check_name(struct x509_certificate *cert, const char *name)
Check X.509 certificate name.
Definition: x509.c:1561
#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:431
uint16_t count
Number of entries.
Definition: ena.h:22
static void image_untrust(struct image *image)
Set image as untrusted.
Definition: image.h:256
An X.509 certificate.
Definition: x509.h:215
size_t len
Length of raw file image.
Definition: image.h:43
static int cms_is_signature(struct cms_message *cms)
Check if CMS message is a signature message.
Definition: cms.h:105
struct list_head participants
List of participant information blocks.
Definition: cms.h:66
#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:43
struct x509_link store
Link in certificate store.
Definition: x509.h:220
static int cms_verify_signer(struct cms_message *cms, struct cms_participant *part, userptr_t data, size_t len, time_t time, struct x509_chain *store, struct x509_root *root)
Verify CMS message signer.
Definition: cms.c:802
static void image_trust(struct image *image)
Set image as trusted.
Definition: image.h:247

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

1060  {
1061  struct cipher_algorithm *cipher = cms->cipher;
1062  const unsigned int original_flags = image->flags;
1063  size_t offset;
1064  size_t remaining;
1065  size_t frag_len;
1066  int pad_len;
1067  void *tmp;
1068  void *ctx;
1069  void *ctxdup;
1070  void *auth;
1071  int rc;
1072 
1073  /* Sanity checks */
1074  if ( ! cipher ) {
1075  rc = -ENOTTY;
1076  goto err_no_cipher;
1077  }
1078 
1079  /* Check block size */
1080  if ( ( image->len & ( cipher->blocksize - 1 ) ) != 0 ) {
1081  DBGC ( cms, "CMS %p invalid length %zd\n", cms, image->len );
1082  rc = -EACCES_LEN;
1083  goto err_blocksize;
1084  }
1085 
1086  /* Allocate temporary working space */
1087  tmp = malloc ( CMS_DECRYPT_BLKSZ + ( 2 * cipher->ctxsize ) +
1088  cipher->authsize );
1089  if ( ! tmp ) {
1090  rc = -ENOMEM;
1091  goto err_alloc;
1092  }
1093  ctx = ( tmp + CMS_DECRYPT_BLKSZ );
1094  ctxdup = ( ctx + cipher->ctxsize );
1095  auth = ( ctxdup + cipher->ctxsize );
1096 
1097  /* Initialise cipher */
1098  if ( ( rc = cms_cipher ( cms, private_key, ctx ) ) != 0 )
1099  goto err_cipher;
1100 
1101  /* Duplicate cipher context for potential reencryption on error */
1102  memcpy ( ctxdup, ctx, cipher->ctxsize );
1103 
1104  /* Clear trusted flag before modifying image */
1105  image_untrust ( image );
1106 
1107  /* Temporarily unregister image, if applicable */
1108  if ( original_flags & IMAGE_REGISTERED ) {
1109  image_get ( image );
1110  unregister_image ( image );
1111  }
1112 
1113  /* Decrypt one block at a time */
1114  offset = 0;
1115  remaining = image->len;
1116  frag_len = 0;
1117  while ( remaining ) {
1118 
1119  /* Calculate fragment length */
1120  frag_len = remaining;
1121  if ( frag_len > CMS_DECRYPT_BLKSZ )
1122  frag_len = CMS_DECRYPT_BLKSZ;
1123 
1124  /* Decrypt fragment */
1125  copy_from_user ( tmp, image->data, offset, frag_len );
1126  cipher_decrypt ( cipher, ctx, tmp, tmp, frag_len );
1127 
1128  /* Overwrite all but the final fragment */
1129  if ( remaining > frag_len )
1130  copy_to_user ( image->data, offset, tmp, frag_len );
1131 
1132  /* Move to next block */
1133  remaining -= frag_len;
1134  offset += frag_len;
1135  }
1136 
1137  /* Check authentication tag, if applicable */
1138  cipher_auth ( cipher, ctx, auth );
1139  if ( ( cms->mac.len != cipher->authsize ) ||
1140  ( memcmp ( cms->mac.data, auth, cipher->authsize ) != 0 ) ) {
1141  DBGC ( cms, "CMS %p invalid authentication tag\n", cms );
1142  DBGC_HDA ( cms, 0, auth, cipher->authsize );
1143  rc = -EACCES_MAC;
1144  goto err_auth;
1145  }
1146 
1147  /* Check block padding, if applicable */
1148  if ( ( pad_len = cms_verify_padding ( cms, tmp, frag_len ) ) < 0 ) {
1149  rc = pad_len;
1150  goto err_pad;
1151  }
1152 
1153  /* Update image name. Do this as the last possible failure, so
1154  * that we do not have to include any error-handling code path
1155  * to restore the original image name (which may itself fail).
1156  */
1157  if ( name ) {
1158  if ( ( rc = image_set_name ( image, name ) ) != 0 )
1159  goto err_set_name;
1160  } else {
1162  }
1163 
1164  /* Overwrite final fragment and strip block padding. Do this
1165  * only once no further failure paths exist, so that we do not
1166  * have to include include any error-handling code path to
1167  * reconstruct the block padding.
1168  */
1169  copy_to_user ( image->data, ( offset - frag_len ), tmp, frag_len );
1170  image->len -= pad_len;
1171 
1172  /* Clear image type and re-register image, if applicable */
1173  image->type = NULL;
1174  if ( original_flags & IMAGE_REGISTERED ) {
1175  register_image ( image );
1176  image_put ( image );
1177  }
1178 
1179  /* Free temporary working space */
1180  free ( tmp );
1181 
1182  return 0;
1183 
1184  err_set_name:
1185  err_pad:
1186  err_auth:
1187  /* Reencrypt all overwritten fragments. This can be done
1188  * since we have deliberately not overwritten the final
1189  * fragment containing the potentially invalid (and therefore
1190  * unreproducible) block padding.
1191  */
1192  remaining = ( offset - frag_len );
1193  for ( offset = 0 ; offset < remaining ; offset += CMS_DECRYPT_BLKSZ ) {
1195  cipher_encrypt ( cipher, ctxdup, tmp, tmp, CMS_DECRYPT_BLKSZ );
1197  }
1198  if ( original_flags & IMAGE_REGISTERED ) {
1199  register_image ( image ); /* Cannot fail on re-registration */
1200  image_put ( image );
1201  }
1202  image->flags = original_flags;
1203  err_cipher:
1204  free ( tmp );
1205  err_alloc:
1206  err_blocksize:
1207  err_no_cipher:
1208  return rc;
1209 }
unsigned int flags
Flags.
Definition: image.h:36
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
userptr_t data
Raw file image.
Definition: image.h:41
char * image_strip_suffix(struct image *image)
Strip dot suffix from image name, if present.
Definition: image.c:181
struct image_type * type
Image type, if known.
Definition: image.h:46
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
static struct image * image_get(struct image *image)
Increment reference count on an image.
Definition: image.h:219
const void * data
Start of data.
Definition: asn1.h:22
#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:24
unsigned long tmp
Definition: linux_pci.h:63
#define cipher_encrypt(cipher, ctx, src, dst, len)
Definition: crypto.h:233
size_t authsize
Authentication tag size.
Definition: crypto.h:74
#define ENOMEM
Not enough space.
Definition: errno.h:534
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define DBGC_HDA(...)
Definition: compiler.h:506
#define CMS_DECRYPT_BLKSZ
Buffer size for decryption.
Definition: cms.c:89
#define IMAGE_REGISTERED
Image is registered.
Definition: image.h:64
static void image_untrust(struct image *image)
Set image as untrusted.
Definition: image.h:256
int register_image(struct image *image)
Register executable image.
Definition: image.c:286
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
struct cipher_algorithm * cipher
Cipher algorithm.
Definition: cms.h:69
size_t len
Length of raw file image.
Definition: image.h:43
int image_set_name(struct image *image, const char *name)
Set image name.
Definition: image.c:160
static __always_inline void copy_to_user(userptr_t dest, off_t dest_off, const void *src, size_t len)
Copy data to user buffer.
Definition: uaccess.h:324
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:229
size_t ctxsize
Context size.
Definition: crypto.h:54
#define cipher_decrypt(cipher, ctx, src, dst, len)
Definition: crypto.h:243
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
long pad_len
Definition: bigint.h:30
void unregister_image(struct image *image)
Unregister executable image.
Definition: image.c:322
static int cms_cipher(struct cms_message *cms, struct private_key *private_key, void *ctx)
Initialise cipher for CMS decryption.
Definition: cms.c:984
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
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:249
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
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:1011
#define EACCES_MAC
Definition: cms.c:75
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:67

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

Referenced by cms_decrypt_okx(), and imgdecrypt().