iPXE
Macros | Functions | Variables
cms.c File Reference

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

#include <stdint.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <ipxe/asn1.h>
#include <ipxe/x509.h>
#include <ipxe/image.h>
#include <ipxe/malloc.h>
#include <ipxe/privkey.h>
#include <ipxe/cms.h>

Go to the source code of this file.

Macros

#define EACCES_NON_SIGNING   __einfo_error ( EINFO_EACCES_NON_SIGNING )
 
#define EINFO_EACCES_NON_SIGNING   __einfo_uniqify ( EINFO_EACCES, 0x01, "Not a signing certificate" )
 
#define EACCES_NON_CODE_SIGNING   __einfo_error ( EINFO_EACCES_NON_CODE_SIGNING )
 
#define EINFO_EACCES_NON_CODE_SIGNING   __einfo_uniqify ( EINFO_EACCES, 0x02, "Not a code-signing certificate" )
 
#define EACCES_WRONG_NAME   __einfo_error ( EINFO_EACCES_WRONG_NAME )
 
#define EINFO_EACCES_WRONG_NAME   __einfo_uniqify ( EINFO_EACCES, 0x04, "Incorrect certificate name" )
 
#define EACCES_NO_SIGNATURES   __einfo_error ( EINFO_EACCES_NO_SIGNATURES )
 
#define EINFO_EACCES_NO_SIGNATURES   __einfo_uniqify ( EINFO_EACCES, 0x05, "No signatures present" )
 
#define EACCES_NO_RECIPIENTS   __einfo_error ( EINFO_EACCES_NO_RECIPIENTS )
 
#define EINFO_EACCES_NO_RECIPIENTS   __einfo_uniqify ( EINFO_EACCES, 0x06, "No usable recipients" )
 
#define EACCES_LEN   __einfo_error ( EINFO_EACCES_LEN )
 
#define EINFO_EACCES_LEN   __einfo_uniqify ( EINFO_EACCES, 0x07, "Bad file length" )
 
#define EACCES_PAD   __einfo_error ( EINFO_EACCES_PAD )
 
#define EINFO_EACCES_PAD   __einfo_uniqify ( EINFO_EACCES, 0x08, "Bad block padding" )
 
#define EACCES_MAC   __einfo_error ( EINFO_EACCES_MAC )
 
#define EINFO_EACCES_MAC   __einfo_uniqify ( EINFO_EACCES, 0x09, "Invalid MAC" )
 
#define ENOTSUP_TYPE   __einfo_error ( EINFO_ENOTSUP_TYPE )
 
#define EINFO_ENOTSUP_TYPE   __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unrecognised message type" )
 

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
 FILE_SECBOOT (PERMITTED)
 
static int cms_parse_signed (struct cms_message *cms, const struct asn1_cursor *raw)
 Parse CMS signed data. More...
 
static int cms_parse_enveloped (struct cms_message *cms, const struct asn1_cursor *raw)
 Parse CMS enveloped data. More...
 
static int cms_parse_content_type (struct cms_message *cms, const struct asn1_cursor *raw)
 Parse CMS message content type. More...
 
static int cms_parse_certificates (struct cms_message *cms, const struct asn1_cursor *raw)
 Parse CMS message certificate list. More...
 
static int cms_parse_identifier (struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
 Parse CMS message participant identifier. More...
 
static int cms_parse_digest_algorithm (struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
 Parse CMS message digest algorithm. More...
 
static int cms_parse_pubkey_algorithm (struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
 Parse CMS message public-key algorithm. More...
 
static int cms_parse_cipher_algorithm (struct cms_message *cms, const struct asn1_cursor *raw)
 Parse CMS message cipher algorithm. More...
 
static int cms_parse_value (struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
 Parse CMS message signature or key value. More...
 
static int cms_parse_participant (struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
 Parse CMS message participant information. More...
 
static int cms_parse_participants (struct cms_message *cms, const struct asn1_cursor *raw)
 Parse CMS message participants information. More...
 
static int cms_parse_encrypted (struct cms_message *cms, const struct asn1_cursor *raw)
 Parse CMS message encrypted content information. More...
 
static int cms_parse_mac (struct cms_message *cms, const struct asn1_cursor *raw)
 Parse CMS message MAC. More...
 
static int cms_parse (struct cms_message *cms)
 Parse CMS message from ASN.1 data. More...
 
static void cms_free (struct refcnt *refcnt)
 Free CMS message. More...
 
int cms_message (struct image *image, struct cms_message **cms)
 Create CMS message. More...
 
static void cms_digest (struct cms_message *cms, struct cms_participant *part, const void *data, size_t len, void *out)
 Calculate digest of CMS-signed data. More...
 
static int cms_verify_digest (struct cms_message *cms, struct cms_participant *part, struct x509_certificate *cert, const void *data, size_t len)
 Verify digest of CMS-signed data. More...
 
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. 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...
 
static struct cms_participantcms_recipient (struct cms_message *cms, struct private_key *private_key)
 Identify CMS recipient corresponding to private key. More...
 
static int cms_cipher_key (struct cms_message *cms, struct cms_participant *part, struct private_key *private_key, void *ctx)
 Set CMS cipher key. More...
 
static int cms_cipher (struct cms_message *cms, struct private_key *private_key, void *ctx)
 Initialise cipher for CMS decryption. More...
 
static int cms_verify_padding (struct cms_message *cms, const void *data, size_t len)
 Check CMS padding. More...
 
int cms_decrypt (struct cms_message *cms, struct image *image, const char *name, struct private_key *private_key)
 Decrypt CMS message. More...
 

Variables

static uint8_t oid_signeddata [] = { ASN1_OID_SIGNEDDATA }
 "id-signedData" object identifier More...
 
static uint8_t oid_envelopeddata [] = { ASN1_OID_ENVELOPEDDATA }
 "id-envelopedData" object identifier More...
 
static uint8_t oid_authenvelopeddata [] = { ASN1_OID_AUTHENVELOPEDDATA }
 "id-authEnvelopedData" object identifier More...
 
static struct cms_type cms_types []
 CMS message types. More...
 

Detailed Description

Cryptographic Message Syntax (PKCS #7)

The format of CMS messages is defined in RFC 5652.

Definition in file cms.c.

Macro Definition Documentation

◆ EACCES_NON_SIGNING

#define EACCES_NON_SIGNING   __einfo_error ( EINFO_EACCES_NON_SIGNING )

Definition at line 47 of file cms.c.

◆ EINFO_EACCES_NON_SIGNING

#define EINFO_EACCES_NON_SIGNING   __einfo_uniqify ( EINFO_EACCES, 0x01, "Not a signing certificate" )

Definition at line 49 of file cms.c.

◆ EACCES_NON_CODE_SIGNING

#define EACCES_NON_CODE_SIGNING   __einfo_error ( EINFO_EACCES_NON_CODE_SIGNING )

Definition at line 51 of file cms.c.

◆ EINFO_EACCES_NON_CODE_SIGNING

#define EINFO_EACCES_NON_CODE_SIGNING   __einfo_uniqify ( EINFO_EACCES, 0x02, "Not a code-signing certificate" )

Definition at line 53 of file cms.c.

◆ EACCES_WRONG_NAME

#define EACCES_WRONG_NAME   __einfo_error ( EINFO_EACCES_WRONG_NAME )

Definition at line 55 of file cms.c.

◆ EINFO_EACCES_WRONG_NAME

#define EINFO_EACCES_WRONG_NAME   __einfo_uniqify ( EINFO_EACCES, 0x04, "Incorrect certificate name" )

Definition at line 57 of file cms.c.

◆ EACCES_NO_SIGNATURES

#define EACCES_NO_SIGNATURES   __einfo_error ( EINFO_EACCES_NO_SIGNATURES )

Definition at line 59 of file cms.c.

◆ EINFO_EACCES_NO_SIGNATURES

#define EINFO_EACCES_NO_SIGNATURES   __einfo_uniqify ( EINFO_EACCES, 0x05, "No signatures present" )

Definition at line 61 of file cms.c.

◆ EACCES_NO_RECIPIENTS

#define EACCES_NO_RECIPIENTS   __einfo_error ( EINFO_EACCES_NO_RECIPIENTS )

Definition at line 63 of file cms.c.

◆ EINFO_EACCES_NO_RECIPIENTS

#define EINFO_EACCES_NO_RECIPIENTS   __einfo_uniqify ( EINFO_EACCES, 0x06, "No usable recipients" )

Definition at line 65 of file cms.c.

◆ EACCES_LEN

#define EACCES_LEN   __einfo_error ( EINFO_EACCES_LEN )

Definition at line 67 of file cms.c.

◆ EINFO_EACCES_LEN

#define EINFO_EACCES_LEN   __einfo_uniqify ( EINFO_EACCES, 0x07, "Bad file length" )

Definition at line 69 of file cms.c.

◆ EACCES_PAD

#define EACCES_PAD   __einfo_error ( EINFO_EACCES_PAD )

Definition at line 71 of file cms.c.

◆ EINFO_EACCES_PAD

#define EINFO_EACCES_PAD   __einfo_uniqify ( EINFO_EACCES, 0x08, "Bad block padding" )

Definition at line 73 of file cms.c.

◆ EACCES_MAC

#define EACCES_MAC   __einfo_error ( EINFO_EACCES_MAC )

Definition at line 75 of file cms.c.

◆ EINFO_EACCES_MAC

#define EINFO_EACCES_MAC   __einfo_uniqify ( EINFO_EACCES, 0x09, "Invalid MAC" )

Definition at line 77 of file cms.c.

◆ ENOTSUP_TYPE

#define ENOTSUP_TYPE   __einfo_error ( EINFO_ENOTSUP_TYPE )

Definition at line 79 of file cms.c.

◆ EINFO_ENOTSUP_TYPE

#define EINFO_ENOTSUP_TYPE   __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unrecognised message type" )

Definition at line 81 of file cms.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED  )

◆ cms_parse_signed()

static int cms_parse_signed ( struct cms_message cms,
const struct asn1_cursor raw 
)
static

Parse CMS signed data.

Parameters
cmsCMS message
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 530 of file cms.c.

531  {
532  struct asn1_cursor cursor;
533  int rc;
534 
535  /* Allocate certificate list */
537  if ( ! cms->certificates )
538  return -ENOMEM;
539 
540  /* Enter signedData */
541  memcpy ( &cursor, raw, sizeof ( cursor ) );
542  asn1_enter ( &cursor, ASN1_SEQUENCE );
543 
544  /* Skip version */
545  asn1_skip ( &cursor, ASN1_INTEGER );
546 
547  /* Skip digestAlgorithms */
548  asn1_skip ( &cursor, ASN1_SET );
549 
550  /* Skip encapContentInfo */
551  asn1_skip ( &cursor, ASN1_SEQUENCE );
552 
553  /* Parse certificates */
554  if ( ( rc = cms_parse_certificates ( cms, &cursor ) ) != 0 )
555  return rc;
556  asn1_skip_any ( &cursor );
557 
558  /* Skip crls, if present */
559  asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 1 ) );
560 
561  /* Parse signerInfos */
562  if ( ( rc = cms_parse_participants ( cms, &cursor ) ) != 0 )
563  return rc;
564 
565  return 0;
566 }
struct x509_chain * certificates
List of all certificates (for signature messages)
Definition: cms.h:64
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
static int cms_parse_participants(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message participants information.
Definition: cms.c:433
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:169
struct x509_chain * x509_alloc_chain(void)
Allocate X.509 certificate chain.
Definition: x509.c:1615
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:290
#define ASN1_SET
ASN.1 set.
Definition: asn1.h:93
#define ENOMEM
Not enough space.
Definition: errno.h:535
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static int cms_parse_certificates(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message certificate list.
Definition: cms.c:158
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition: asn1.h:90
#define ASN1_INTEGER
ASN.1 integer.
Definition: asn1.h:63
int asn1_skip_if_exists(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object if present.
Definition: asn1.c:202
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition: asn1.c:231
__be32 raw[7]
Definition: CIB_PRM.h:28
#define ASN1_EXPLICIT_TAG(number)
ASN.1 explicit tag.
Definition: asn1.h:99
An ASN.1 object cursor.
Definition: asn1.h:21

References asn1_enter(), ASN1_EXPLICIT_TAG, ASN1_INTEGER, ASN1_SEQUENCE, ASN1_SET, asn1_skip(), asn1_skip_any(), asn1_skip_if_exists(), cms_message::certificates, cms_parse_certificates(), cms_parse_participants(), ENOMEM, memcpy(), raw, rc, and x509_alloc_chain().

◆ cms_parse_enveloped()

static int cms_parse_enveloped ( struct cms_message cms,
const struct asn1_cursor raw 
)
static

Parse CMS enveloped data.

Parameters
cmsCMS message
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 575 of file cms.c.

576  {
577  struct asn1_cursor cursor;
578  int rc;
579 
580  /* Enter envelopedData or authEnvelopedData */
581  memcpy ( &cursor, raw, sizeof ( cursor ) );
582  asn1_enter ( &cursor, ASN1_SEQUENCE );
583 
584  /* Skip version */
585  asn1_skip ( &cursor, ASN1_INTEGER );
586 
587  /* Skip originatorInfo, if present */
588  asn1_skip_if_exists ( &cursor, ASN1_IMPLICIT_TAG ( 0 ) );
589 
590  /* Parse recipientInfos */
591  if ( ( rc = cms_parse_participants ( cms, &cursor ) ) != 0 )
592  return rc;
593  asn1_skip_any ( &cursor );
594 
595  /* Parse encryptedContentInfo or authEncryptedContentInfo */
596  if ( ( rc = cms_parse_encrypted ( cms, &cursor ) ) != 0 )
597  return rc;
598  asn1_skip_any ( &cursor );
599  assert ( cms->cipher != NULL );
600 
601  /* Skip unprotectedAttrs or authAttrs, if present */
602  asn1_skip_if_exists ( &cursor, ASN1_IMPLICIT_TAG ( 1 ) );
603 
604  /* Parse mac, if present */
605  if ( ( cms->cipher->authsize != 0 ) &&
606  ( ( rc = cms_parse_mac ( cms, &cursor ) ) != 0 ) )
607  return rc;
608 
609  return 0;
610 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define ASN1_IMPLICIT_TAG(number)
ASN.1 implicit tag.
Definition: asn1.h:96
static int cms_parse_participants(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message participants information.
Definition: cms.c:433
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:169
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:290
size_t authsize
Authentication tag size.
Definition: crypto.h:75
void * memcpy(void *dest, const void *src, size_t len) __nonnull
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
struct cipher_algorithm * cipher
Cipher algorithm.
Definition: cms.h:69
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition: asn1.h:90
#define ASN1_INTEGER
ASN.1 integer.
Definition: asn1.h:63
static int cms_parse_encrypted(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message encrypted content information.
Definition: cms.c:479
int asn1_skip_if_exists(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object if present.
Definition: asn1.c:202
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition: asn1.c:231
__be32 raw[7]
Definition: CIB_PRM.h:28
static int cms_parse_mac(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message MAC.
Definition: cms.c:505
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
An ASN.1 object cursor.
Definition: asn1.h:21

References asn1_enter(), ASN1_IMPLICIT_TAG, ASN1_INTEGER, ASN1_SEQUENCE, asn1_skip(), asn1_skip_any(), asn1_skip_if_exists(), assert(), cipher_algorithm::authsize, cms_message::cipher, cms_parse_encrypted(), cms_parse_mac(), cms_parse_participants(), memcpy(), NULL, raw, and rc.

◆ cms_parse_content_type()

static int cms_parse_content_type ( struct cms_message cms,
const struct asn1_cursor raw 
)
static

Parse CMS message content type.

Parameters
cmsCMS message
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 124 of file cms.c.

125  {
126  struct asn1_cursor cursor;
127  struct cms_type *type;
128  unsigned int i;
129 
130  /* Enter contentType */
131  memcpy ( &cursor, raw, sizeof ( cursor ) );
132  asn1_enter ( &cursor, ASN1_OID );
133 
134  /* Check for a recognised OID */
135  for ( i = 0 ; i < ( sizeof ( cms_types ) /
136  sizeof ( cms_types[0] ) ) ; i++ ) {
137  type = &cms_types[i];
138  if ( asn1_compare ( &cursor, &type->oid ) == 0 ) {
139  cms->type = type;
140  DBGC ( cms, "CMS %p contains %sData\n",
141  cms, type->name );
142  return 0;
143  }
144  }
145 
146  DBGC ( cms, "CMS %p is not a recognised message type:\n", cms );
147  DBGC_HDA ( cms, 0, raw->data, raw->len );
148  return -ENOTSUP_TYPE;
149 }
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition: asn1.c:458
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:169
A CMS message type.
Definition: cms.h:23
uint32_t type
Operating system type.
Definition: ena.h:12
#define DBGC(...)
Definition: compiler.h:505
void * memcpy(void *dest, const void *src, size_t len) __nonnull
struct cms_type * type
Message type.
Definition: cms.h:61
#define DBGC_HDA(...)
Definition: compiler.h:506
#define ENOTSUP_TYPE
Definition: cms.c:79
static struct cms_type cms_types[]
CMS message types.
Definition: cms.c:99
#define ASN1_OID
ASN.1 object identifier.
Definition: asn1.h:75
__be32 raw[7]
Definition: CIB_PRM.h:28
An ASN.1 object cursor.
Definition: asn1.h:21

References asn1_compare(), asn1_enter(), ASN1_OID, cms_types, DBGC, DBGC_HDA, ENOTSUP_TYPE, memcpy(), raw, type, and cms_message::type.

Referenced by cms_parse().

◆ cms_parse_certificates()

static int cms_parse_certificates ( struct cms_message cms,
const struct asn1_cursor raw 
)
static

Parse CMS message certificate list.

Parameters
cmsCMS message
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 158 of file cms.c.

159  {
160  struct asn1_cursor cursor;
161  struct x509_certificate *cert;
162  int rc;
163 
164  /* Enter certificates */
165  memcpy ( &cursor, raw, sizeof ( cursor ) );
166  asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
167 
168  /* Add each certificate */
169  while ( cursor.len ) {
170 
171  /* Add certificate to chain */
172  if ( ( rc = x509_append_raw ( cms->certificates, cursor.data,
173  cursor.len ) ) != 0 ) {
174  DBGC ( cms, "CMS %p could not append certificate: %s\n",
175  cms, strerror ( rc) );
176  DBGC_HDA ( cms, 0, cursor.data, cursor.len );
177  return rc;
178  }
179  cert = x509_last ( cms->certificates );
180  DBGC ( cms, "CMS %p found certificate %s\n",
181  cms, x509_name ( cert ) );
182 
183  /* Move to next certificate */
184  asn1_skip_any ( &cursor );
185  }
186 
187  return 0;
188 }
struct x509_chain * certificates
List of all certificates (for signature messages)
Definition: cms.h:64
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:169
int x509_append_raw(struct x509_chain *chain, const void *data, size_t len)
Append X.509 certificate to X.509 certificate chain.
Definition: x509.c:1674
#define DBGC(...)
Definition: compiler.h:505
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:290
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define DBGC_HDA(...)
Definition: compiler.h:506
static struct x509_certificate * x509_last(struct x509_chain *chain)
Get last certificate in X.509 certificate chain.
Definition: x509.h:325
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
An X.509 certificate.
Definition: x509.h:216
const char * x509_name(struct x509_certificate *cert)
Get X.509 certificate display name.
Definition: x509.c:147
__be32 raw[7]
Definition: CIB_PRM.h:28
#define ASN1_EXPLICIT_TAG(number)
ASN.1 explicit tag.
Definition: asn1.h:99
An ASN.1 object cursor.
Definition: asn1.h:21

References asn1_enter(), ASN1_EXPLICIT_TAG, asn1_skip_any(), cms_message::certificates, asn1_cursor::data, DBGC, DBGC_HDA, asn1_cursor::len, memcpy(), raw, rc, strerror(), x509_append_raw(), x509_last(), and x509_name().

Referenced by cms_parse_signed().

◆ cms_parse_identifier()

static int cms_parse_identifier ( struct cms_message cms,
struct cms_participant part,
const struct asn1_cursor raw 
)
static

Parse CMS message participant identifier.

Parameters
cmsCMS message
partParticipant information to fill in
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 198 of file cms.c.

200  {
201  struct asn1_cursor cursor;
202  struct asn1_cursor serial;
203  struct asn1_cursor issuer;
204  struct x509_certificate *cert;
205  int rc;
206 
207  /* Enter issuerAndSerialNumber */
208  memcpy ( &cursor, raw, sizeof ( cursor ) );
209  asn1_enter ( &cursor, ASN1_SEQUENCE );
210 
211  /* Identify issuer */
212  memcpy ( &issuer, &cursor, sizeof ( issuer ) );
213  if ( ( rc = asn1_shrink ( &issuer, ASN1_SEQUENCE ) ) != 0 ) {
214  DBGC ( cms, "CMS %p/%p could not locate issuer: %s\n",
215  cms, part, strerror ( rc ) );
216  DBGC_HDA ( cms, 0, raw->data, raw->len );
217  return rc;
218  }
219  DBGC ( cms, "CMS %p/%p issuer is:\n", cms, part );
220  DBGC_HDA ( cms, 0, issuer.data, issuer.len );
221  asn1_skip_any ( &cursor );
222 
223  /* Identify serialNumber */
224  memcpy ( &serial, &cursor, sizeof ( serial ) );
225  if ( ( rc = asn1_shrink ( &serial, ASN1_INTEGER ) ) != 0 ) {
226  DBGC ( cms, "CMS %p/%p could not locate serialNumber: %s\n",
227  cms, part, strerror ( rc ) );
228  DBGC_HDA ( cms, 0, raw->data, raw->len );
229  return rc;
230  }
231  DBGC ( cms, "CMS %p/%p serial number is:\n", cms, part );
232  DBGC_HDA ( cms, 0, serial.data, serial.len );
233 
234  /* Identify certificate */
236  if ( ! cert ) {
237  DBGC ( cms, "CMS %p/%p could not identify certificate\n",
238  cms, part );
239  return ( cms_is_signature ( cms ) ? -ENOENT : 0 );
240  }
241 
242  /* Append certificate to chain */
243  if ( ( rc = x509_append ( part->chain, cert ) ) != 0 ) {
244  DBGC ( cms, "CMS %p/%p could not append certificate: %s\n",
245  cms, part, strerror ( rc ) );
246  return rc;
247  }
248 
249  /* Append remaining certificates to chain */
250  if ( ( rc = x509_auto_append ( part->chain,
251  cms->certificates ) ) != 0 ) {
252  DBGC ( cms, "CMS %p/%p could not append certificates: %s\n",
253  cms, part, strerror ( rc ) );
254  return rc;
255  }
256 
257  return 0;
258 }
struct x509_chain * certificates
List of all certificates (for signature messages)
Definition: cms.h:64
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:169
struct x509_issuer issuer
Issuer.
Definition: x509.h:241
#define DBGC(...)
Definition: compiler.h:505
int x509_append(struct x509_chain *chain, struct x509_certificate *cert)
Append X.509 certificate to X.509 certificate chain.
Definition: x509.c:1638
#define ENOENT
No such file or directory.
Definition: errno.h:515
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:290
int asn1_shrink(struct asn1_cursor *cursor, unsigned int type)
Shrink ASN.1 cursor to fit object.
Definition: asn1.c:254
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define DBGC_HDA(...)
Definition: compiler.h:506
int x509_auto_append(struct x509_chain *chain, struct x509_chain *store)
Append X.509 certificates to X.509 certificate chain.
Definition: x509.c:1868
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
An X.509 certificate.
Definition: x509.h:216
struct x509_certificate * x509_find_issuer_serial(struct x509_chain *store, const struct asn1_cursor *issuer, const struct asn1_cursor *serial)
Identify X.509 certificate by issuer and serial number.
Definition: x509.c:1805
uint64_t serial
Serial number.
Definition: edd.h:31
static int cms_is_signature(struct cms_message *cms)
Check if CMS message is a signature message.
Definition: cms.h:105
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition: asn1.h:90
#define ASN1_INTEGER
ASN.1 integer.
Definition: asn1.h:63
struct x509_chain * chain
Certificate chain.
Definition: cms.h:43
__be32 raw[7]
Definition: CIB_PRM.h:28
An ASN.1 object cursor.
Definition: asn1.h:21

References asn1_enter(), ASN1_INTEGER, ASN1_SEQUENCE, asn1_shrink(), asn1_skip_any(), cms_message::certificates, cms_participant::chain, cms_is_signature(), DBGC, DBGC_HDA, ENOENT, x509_certificate::issuer, memcpy(), raw, rc, serial, strerror(), x509_append(), x509_auto_append(), and x509_find_issuer_serial().

Referenced by cms_parse_participant().

◆ cms_parse_digest_algorithm()

static int cms_parse_digest_algorithm ( struct cms_message cms,
struct cms_participant part,
const struct asn1_cursor raw 
)
static

Parse CMS message digest algorithm.

Parameters
cmsCMS message
partParticipant information to fill in
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 268 of file cms.c.

270  {
271  struct asn1_algorithm *algorithm;
272  int rc;
273 
274  /* Identify algorithm */
275  if ( ( rc = asn1_digest_algorithm ( raw, &algorithm ) ) != 0 ) {
276  DBGC ( cms, "CMS %p/%p could not identify digest algorithm: "
277  "%s\n", cms, part, strerror ( rc ) );
278  DBGC_HDA ( cms, 0, raw->data, raw->len );
279  return rc;
280  }
281 
282  /* Record digest algorithm */
283  part->digest = algorithm->digest;
284  DBGC ( cms, "CMS %p/%p digest algorithm is %s\n",
285  cms, part, algorithm->name );
286 
287  return 0;
288 }
An ASN.1 OID-identified algorithm.
Definition: asn1.h:408
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define DBGC(...)
Definition: compiler.h:505
int asn1_digest_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified digest algorithm.
Definition: asn1.c:570
struct digest_algorithm * digest
Digest algorithm (for signature messages)
Definition: cms.h:46
#define DBGC_HDA(...)
Definition: compiler.h:506
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
u16 algorithm
Authentication algorithm (Open System or Shared Key)
Definition: ieee80211.h:1030
__be32 raw[7]
Definition: CIB_PRM.h:28

References algorithm, asn1_digest_algorithm(), DBGC, DBGC_HDA, cms_participant::digest, raw, rc, and strerror().

Referenced by cms_parse_participant().

◆ cms_parse_pubkey_algorithm()

static int cms_parse_pubkey_algorithm ( struct cms_message cms,
struct cms_participant part,
const struct asn1_cursor raw 
)
static

Parse CMS message public-key algorithm.

Parameters
cmsCMS message
partParticipant information to fill in
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 298 of file cms.c.

300  {
301  struct asn1_algorithm *algorithm;
302  int rc;
303 
304  /* Identify algorithm */
305  if ( ( rc = asn1_pubkey_algorithm ( raw, &algorithm ) ) != 0 ) {
306  DBGC ( cms, "CMS %p/%p could not identify public-key "
307  "algorithm: %s\n", cms, part, strerror ( rc ) );
308  DBGC_HDA ( cms, 0, raw->data, raw->len );
309  return rc;
310  }
311 
312  /* Record public-key algorithm */
313  part->pubkey = algorithm->pubkey;
314  DBGC ( cms, "CMS %p/%p public-key algorithm is %s\n",
315  cms, part, algorithm->name );
316 
317  return 0;
318 }
An ASN.1 OID-identified algorithm.
Definition: asn1.h:408
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define DBGC(...)
Definition: compiler.h:505
struct pubkey_algorithm * pubkey
Public-key algorithm.
Definition: cms.h:48
#define DBGC_HDA(...)
Definition: compiler.h:506
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
int asn1_pubkey_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified public-key algorithm.
Definition: asn1.c:544
u16 algorithm
Authentication algorithm (Open System or Shared Key)
Definition: ieee80211.h:1030
__be32 raw[7]
Definition: CIB_PRM.h:28

References algorithm, asn1_pubkey_algorithm(), DBGC, DBGC_HDA, cms_participant::pubkey, raw, rc, and strerror().

Referenced by cms_parse_participant().

◆ cms_parse_cipher_algorithm()

static int cms_parse_cipher_algorithm ( struct cms_message cms,
const struct asn1_cursor raw 
)
static

Parse CMS message cipher algorithm.

Parameters
cmsCMS message
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 327 of file cms.c.

328  {
329  struct asn1_algorithm *algorithm;
330  int rc;
331 
332  /* Identify algorithm */
333  if ( ( rc = asn1_cipher_algorithm ( raw, &algorithm,
334  &cms->iv ) ) != 0 ) {
335  DBGC ( cms, "CMS %p could not identify cipher algorithm: %s\n",
336  cms, strerror ( rc ) );
337  DBGC_HDA ( cms, 0, raw->data, raw->len );
338  return rc;
339  }
340 
341  /* Record cipher */
342  cms->cipher = algorithm->cipher;
343  DBGC ( cms, "CMS %p cipher algorithm is %s\n", cms, algorithm->name );
344 
345  return 0;
346 }
An ASN.1 OID-identified algorithm.
Definition: asn1.h:408
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define DBGC(...)
Definition: compiler.h:505
#define DBGC_HDA(...)
Definition: compiler.h:506
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
struct cipher_algorithm * cipher
Cipher algorithm.
Definition: cms.h:69
u16 algorithm
Authentication algorithm (Open System or Shared Key)
Definition: ieee80211.h:1030
int asn1_cipher_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm, struct asn1_cursor *params)
Parse ASN.1 OID-identified cipher algorithm.
Definition: asn1.c:597
struct asn1_cursor iv
Cipher initialization vector.
Definition: cms.h:71
__be32 raw[7]
Definition: CIB_PRM.h:28

References algorithm, asn1_cipher_algorithm(), cms_message::cipher, DBGC, DBGC_HDA, cms_message::iv, raw, rc, and strerror().

Referenced by cms_parse_encrypted().

◆ cms_parse_value()

static int cms_parse_value ( struct cms_message cms,
struct cms_participant part,
const struct asn1_cursor raw 
)
static

Parse CMS message signature or key value.

Parameters
cmsCMS message
partParticipant information to fill in
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 356 of file cms.c.

358  {
359  int rc;
360 
361  /* Enter signature or encryptedKey */
362  memcpy ( &part->value, raw, sizeof ( part->value ) );
363  if ( ( rc = asn1_enter ( &part->value, ASN1_OCTET_STRING ) ) != 0 ) {
364  DBGC ( cms, "CMS %p/%p could not locate value:\n",
365  cms, part );
366  DBGC_HDA ( cms, 0, raw->data, raw->len );
367  return rc;
368  }
369  DBGC ( cms, "CMS %p/%p value is:\n", cms, part );
370  DBGC_HDA ( cms, 0, part->value.data, part->value.len );
371 
372  return 0;
373 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct asn1_cursor value
Signature or key value.
Definition: cms.h:51
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:169
const void * data
Start of data.
Definition: asn1.h:23
#define DBGC(...)
Definition: compiler.h:505
size_t len
Length of data.
Definition: asn1.h:25
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define DBGC_HDA(...)
Definition: compiler.h:506
__be32 raw[7]
Definition: CIB_PRM.h:28
#define ASN1_OCTET_STRING
ASN.1 octet string.
Definition: asn1.h:69

References asn1_enter(), ASN1_OCTET_STRING, asn1_cursor::data, DBGC, DBGC_HDA, asn1_cursor::len, memcpy(), raw, rc, and cms_participant::value.

Referenced by cms_parse_participant().

◆ cms_parse_participant()

static int cms_parse_participant ( struct cms_message cms,
struct cms_participant part,
const struct asn1_cursor raw 
)
static

Parse CMS message participant information.

Parameters
cmsCMS message
partParticipant information to fill in
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 383 of file cms.c.

385  {
386  struct asn1_cursor cursor;
387  int rc;
388 
389  /* Enter signerInfo or ktri */
390  memcpy ( &cursor, raw, sizeof ( cursor ) );
391  asn1_enter ( &cursor, ASN1_SEQUENCE );
392 
393  /* Skip version */
394  asn1_skip ( &cursor, ASN1_INTEGER );
395 
396  /* Parse sid or rid */
397  if ( ( rc = cms_parse_identifier ( cms, part, &cursor ) ) != 0 )
398  return rc;
399  asn1_skip_any ( &cursor );
400 
401  /* Parse signature-only objects */
402  if ( cms_is_signature ( cms ) ) {
403 
404  /* Parse digestAlgorithm */
405  if ( ( rc = cms_parse_digest_algorithm ( cms, part,
406  &cursor ) ) != 0 )
407  return rc;
408  asn1_skip_any ( &cursor );
409 
410  /* Skip signedAttrs, if present */
411  asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
412  }
413 
414  /* Parse signatureAlgorithm or contentEncryptionAlgorithm */
415  if ( ( rc = cms_parse_pubkey_algorithm ( cms, part, &cursor ) ) != 0 )
416  return rc;
417  asn1_skip_any ( &cursor );
418 
419  /* Parse signature or encryptedKey */
420  if ( ( rc = cms_parse_value ( cms, part, &cursor ) ) != 0 )
421  return rc;
422 
423  return 0;
424 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:169
static int cms_parse_digest_algorithm(struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
Parse CMS message digest algorithm.
Definition: cms.c:268
static int cms_parse_value(struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
Parse CMS message signature or key value.
Definition: cms.c:356
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:290
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static int cms_is_signature(struct cms_message *cms)
Check if CMS message is a signature message.
Definition: cms.h:105
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition: asn1.h:90
#define ASN1_INTEGER
ASN.1 integer.
Definition: asn1.h:63
static int cms_parse_identifier(struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
Parse CMS message participant identifier.
Definition: cms.c:198
int asn1_skip_if_exists(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object if present.
Definition: asn1.c:202
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition: asn1.c:231
static int cms_parse_pubkey_algorithm(struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
Parse CMS message public-key algorithm.
Definition: cms.c:298
__be32 raw[7]
Definition: CIB_PRM.h:28
#define ASN1_EXPLICIT_TAG(number)
ASN.1 explicit tag.
Definition: asn1.h:99
An ASN.1 object cursor.
Definition: asn1.h:21

References asn1_enter(), ASN1_EXPLICIT_TAG, ASN1_INTEGER, ASN1_SEQUENCE, asn1_skip(), asn1_skip_any(), asn1_skip_if_exists(), cms_is_signature(), cms_parse_digest_algorithm(), cms_parse_identifier(), cms_parse_pubkey_algorithm(), cms_parse_value(), memcpy(), raw, and rc.

Referenced by cms_parse_participants().

◆ cms_parse_participants()

static int cms_parse_participants ( struct cms_message cms,
const struct asn1_cursor raw 
)
static

Parse CMS message participants information.

Parameters
cmsCMS message
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 433 of file cms.c.

434  {
435  struct asn1_cursor cursor;
436  struct cms_participant *part;
437  int rc;
438 
439  /* Enter signerInfos or recipientInfos */
440  memcpy ( &cursor, raw, sizeof ( cursor ) );
441  asn1_enter ( &cursor, ASN1_SET );
442 
443  /* Add each signerInfo or recipientInfo. Errors are handled
444  * by ensuring that cms_put() will always be able to free any
445  * allocated memory.
446  */
447  while ( cursor.len ) {
448 
449  /* Allocate participant information block */
450  part = zalloc ( sizeof ( *part ) );
451  if ( ! part )
452  return -ENOMEM;
453  list_add ( &part->list, &cms->participants );
454  part->digest = &digest_null;
455  part->pubkey = &pubkey_null;
456 
457  /* Allocate certificate chain */
458  part->chain = x509_alloc_chain();
459  if ( ! part->chain )
460  return -ENOMEM;
461 
462  /* Parse signerInfo or recipientInfo */
463  if ( ( rc = cms_parse_participant ( cms, part,
464  &cursor ) ) != 0 )
465  return rc;
466  asn1_skip_any ( &cursor );
467  }
468 
469  return 0;
470 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:169
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:70
struct x509_chain * x509_alloc_chain(void)
Allocate X.509 certificate chain.
Definition: x509.c:1615
struct digest_algorithm * digest
Digest algorithm (for signature messages)
Definition: cms.h:46
struct pubkey_algorithm pubkey_null
Definition: crypto_null.c:123
struct pubkey_algorithm * pubkey
Public-key algorithm.
Definition: cms.h:48
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:290
#define ASN1_SET
ASN.1 set.
Definition: asn1.h:93
#define ENOMEM
Not enough space.
Definition: errno.h:535
void * memcpy(void *dest, const void *src, size_t len) __nonnull
CMS participant information.
Definition: cms.h:39
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:662
struct digest_algorithm digest_null
Definition: crypto_null.c:49
struct list_head participants
List of participant information blocks.
Definition: cms.h:66
struct list_head list
List of participant information blocks.
Definition: cms.h:41
static int cms_parse_participant(struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
Parse CMS message participant information.
Definition: cms.c:383
struct x509_chain * chain
Certificate chain.
Definition: cms.h:43
__be32 raw[7]
Definition: CIB_PRM.h:28
An ASN.1 object cursor.
Definition: asn1.h:21

References asn1_enter(), ASN1_SET, asn1_skip_any(), cms_participant::chain, cms_parse_participant(), cms_participant::digest, digest_null, ENOMEM, asn1_cursor::len, cms_participant::list, list_add, memcpy(), cms_message::participants, cms_participant::pubkey, pubkey_null, raw, rc, x509_alloc_chain(), and zalloc().

Referenced by cms_parse_enveloped(), and cms_parse_signed().

◆ cms_parse_encrypted()

static int cms_parse_encrypted ( struct cms_message cms,
const struct asn1_cursor raw 
)
static

Parse CMS message encrypted content information.

Parameters
cmsCMS message
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 479 of file cms.c.

480  {
481  struct asn1_cursor cursor;
482  int rc;
483 
484  /* Enter encryptedContentInfo */
485  memcpy ( &cursor, raw, sizeof ( cursor ) );
486  asn1_enter ( &cursor, ASN1_SEQUENCE );
487 
488  /* Skip contentType */
489  asn1_skip ( &cursor, ASN1_OID );
490 
491  /* Parse contentEncryptionAlgorithm */
492  if ( ( rc = cms_parse_cipher_algorithm ( cms, &cursor ) ) != 0 )
493  return rc;
494 
495  return 0;
496 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:169
static int cms_parse_cipher_algorithm(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message cipher algorithm.
Definition: cms.c:327
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition: asn1.h:90
#define ASN1_OID
ASN.1 object identifier.
Definition: asn1.h:75
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition: asn1.c:231
__be32 raw[7]
Definition: CIB_PRM.h:28
An ASN.1 object cursor.
Definition: asn1.h:21

References asn1_enter(), ASN1_OID, ASN1_SEQUENCE, asn1_skip(), cms_parse_cipher_algorithm(), memcpy(), raw, and rc.

Referenced by cms_parse_enveloped().

◆ cms_parse_mac()

static int cms_parse_mac ( struct cms_message cms,
const struct asn1_cursor raw 
)
static

Parse CMS message MAC.

Parameters
cmsCMS message
rawASN.1 cursor
Return values
rcReturn status code

Definition at line 505 of file cms.c.

506  {
507  int rc;
508 
509  /* Enter mac */
510  memcpy ( &cms->mac, raw, sizeof ( cms->mac ) );
511  if ( ( rc = asn1_enter ( &cms->mac, ASN1_OCTET_STRING ) ) != 0 ) {
512  DBGC ( cms, "CMS %p could not locate mac: %s\n",
513  cms, strerror ( rc ) );
514  DBGC_HDA ( cms, 0, raw->data, raw->len );
515  return rc;
516  }
517  DBGC ( cms, "CMS %p mac is:\n", cms );
518  DBGC_HDA ( cms, 0, cms->mac.data, cms->mac.len );
519 
520  return 0;
521 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:169
const void * data
Start of data.
Definition: asn1.h:23
#define DBGC(...)
Definition: compiler.h:505
size_t len
Length of data.
Definition: asn1.h:25
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define DBGC_HDA(...)
Definition: compiler.h:506
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
__be32 raw[7]
Definition: CIB_PRM.h:28
struct asn1_cursor mac
Cipher authentication tag.
Definition: cms.h:73
#define ASN1_OCTET_STRING
ASN.1 octet string.
Definition: asn1.h:69

References asn1_enter(), ASN1_OCTET_STRING, asn1_cursor::data, DBGC, DBGC_HDA, asn1_cursor::len, cms_message::mac, memcpy(), raw, rc, and strerror().

Referenced by cms_parse_enveloped().

◆ cms_parse()

static int cms_parse ( struct cms_message cms)
static

Parse CMS message from ASN.1 data.

Parameters
cmsCMS message
Return values
rcReturn status code

Definition at line 618 of file cms.c.

618  {
619  struct asn1_cursor cursor;
620  int rc;
621 
622  /* Enter contentInfo */
623  memcpy ( &cursor, cms->raw, sizeof ( cursor ) );
624  asn1_enter ( &cursor, ASN1_SEQUENCE );
625 
626  /* Parse contentType */
627  if ( ( rc = cms_parse_content_type ( cms, &cursor ) ) != 0 )
628  return rc;
629  asn1_skip_any ( &cursor );
630 
631  /* Enter content */
632  asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
633 
634  /* Parse type-specific content */
635  if ( ( rc = cms->type->parse ( cms, &cursor ) ) != 0 )
636  return rc;
637 
638  return 0;
639 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:169
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:290
void * memcpy(void *dest, const void *src, size_t len) __nonnull
struct cms_type * type
Message type.
Definition: cms.h:61
int(* parse)(struct cms_message *cms, const struct asn1_cursor *raw)
Parse content.
Definition: cms.h:34
struct asn1_cursor * raw
Raw ASN.1 data.
Definition: cms.h:59
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition: asn1.h:90
#define ASN1_EXPLICIT_TAG(number)
ASN.1 explicit tag.
Definition: asn1.h:99
An ASN.1 object cursor.
Definition: asn1.h:21
static int cms_parse_content_type(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message content type.
Definition: cms.c:124

References asn1_enter(), ASN1_EXPLICIT_TAG, ASN1_SEQUENCE, asn1_skip_any(), cms_parse_content_type(), memcpy(), cms_type::parse, cms_message::raw, rc, and cms_message::type.

Referenced by cms_message().

◆ cms_free()

static void cms_free ( struct refcnt refcnt)
static

Free CMS message.

Parameters
refcntReference count

Definition at line 646 of file cms.c.

646  {
647  struct cms_message *cms =
648  container_of ( refcnt, struct cms_message, refcnt );
649  struct cms_participant *part;
650  struct cms_participant *tmp;
651 
652  list_for_each_entry_safe ( part, tmp, &cms->participants, list ) {
653  list_del ( &part->list );
654  x509_chain_put ( part->chain );
655  free ( part );
656  }
657  x509_chain_put ( cms->certificates );
658  free ( cms->raw );
659  free ( cms );
660 }
static void x509_chain_put(struct x509_chain *chain)
Drop reference to X.509 certificate chain.
Definition: x509.h:300
struct x509_chain * certificates
List of all certificates (for signature messages)
Definition: cms.h:64
A CMS message.
Definition: cms.h:55
A reference counter.
Definition: refcnt.h:27
unsigned long tmp
Definition: linux_pci.h:65
#define list_del(list)
Delete an entry from a list.
Definition: list.h:120
CMS participant information.
Definition: cms.h:39
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:36
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition: list.h:459
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
struct asn1_cursor * raw
Raw ASN.1 data.
Definition: cms.h:59
struct list_head participants
List of participant information blocks.
Definition: cms.h:66
struct list_head list
List of participant information blocks.
Definition: cms.h:41
struct x509_chain * chain
Certificate chain.
Definition: cms.h:43

References cms_message::certificates, cms_participant::chain, container_of, free, cms_participant::list, list_del, list_for_each_entry_safe, cms_message::participants, cms_message::raw, tmp, and x509_chain_put().

Referenced by cms_message().

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

static void cms_digest ( struct cms_message cms,
struct cms_participant part,
const void *  data,
size_t  len,
void *  out 
)
static

Calculate digest of CMS-signed data.

Parameters
cmsCMS message
partParticipant information
dataSigned data
lenLength of signed data
outDigest output

Definition at line 720 of file cms.c.

722  {
723  struct digest_algorithm *digest = part->digest;
724  uint8_t ctx[ digest->ctxsize ];
725 
726  /* Calculate digest */
727  digest_init ( digest, ctx );
728  digest_update ( digest, ctx, data, len );
729  digest_final ( digest, ctx, out );
730 
731  DBGC ( cms, "CMS %p/%p digest value:\n", cms, part );
732  DBGC_HDA ( cms, 0, out, digest->digestsize );
733 }
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition: crypto.h:224
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition: crypto.h:230
#define DBGC(...)
Definition: compiler.h:505
struct digest_algorithm * digest
Digest algorithm (for signature messages)
Definition: cms.h:46
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
__be32 out[4]
Definition: CIB_PRM.h:36
#define DBGC_HDA(...)
Definition: compiler.h:506
ring len
Length.
Definition: dwmac.h:231
static void digest_init(struct digest_algorithm *digest, void *ctx)
Definition: crypto.h:219
unsigned char uint8_t
Definition: stdint.h:10
size_t ctxsize
Context size.
Definition: crypto.h:23
size_t digestsize
Digest size.
Definition: crypto.h:27
A message digest algorithm.
Definition: crypto.h:19
uint8_t data[48]
Additional event data.
Definition: ena.h:22

References ctx, digest_algorithm::ctxsize, data, DBGC, DBGC_HDA, cms_participant::digest, digest_final(), digest_init(), digest_update(), digest_algorithm::digestsize, len, and out.

Referenced by cms_verify_digest().

◆ cms_verify_digest()

static int cms_verify_digest ( struct cms_message cms,
struct cms_participant part,
struct x509_certificate cert,
const void *  data,
size_t  len 
)
static

Verify digest of CMS-signed data.

Parameters
cmsCMS message
partParticipant information
certCorresponding certificate
dataSigned data
lenLength of signed data
Return values
rcReturn status code

Definition at line 745 of file cms.c.

748  {
749  struct digest_algorithm *digest = part->digest;
750  struct pubkey_algorithm *pubkey = part->pubkey;
751  const struct asn1_cursor *key = &cert->subject.public_key.raw;
752  const struct asn1_cursor *value = &part->value;
753  uint8_t digest_out[ digest->digestsize ];
754  int rc;
755 
756  /* Generate digest */
757  cms_digest ( cms, part, data, len, digest_out );
758 
759  /* Verify digest */
760  if ( ( rc = pubkey_verify ( pubkey, key, digest, digest_out,
761  value ) ) != 0 ) {
762  DBGC ( cms, "CMS %p/%p signature verification failed: %s\n",
763  cms, part, strerror ( rc ) );
764  return rc;
765  }
766 
767  return 0;
768 }
struct asn1_cursor raw
Raw public key information.
Definition: x509.h:52
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct asn1_cursor value
Signature or key value.
Definition: cms.h:51
#define DBGC(...)
Definition: compiler.h:505
struct digest_algorithm * digest
Digest algorithm (for signature messages)
Definition: cms.h:46
struct pubkey_algorithm * pubkey
Public-key algorithm.
Definition: cms.h:48
static void cms_digest(struct cms_message *cms, struct cms_participant *part, const void *data, size_t len, void *out)
Calculate digest of CMS-signed data.
Definition: cms.c:720
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
ring len
Length.
Definition: dwmac.h:231
struct x509_public_key public_key
Public key information.
Definition: x509.h:66
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
struct x509_subject subject
Subject.
Definition: x509.h:245
unsigned char uint8_t
Definition: stdint.h:10
static int pubkey_verify(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, const struct asn1_cursor *signature)
Definition: crypto.h:308
size_t digestsize
Digest size.
Definition: crypto.h:27
A message digest algorithm.
Definition: crypto.h:19
uint8_t data[48]
Additional event data.
Definition: ena.h:22
An ASN.1 object cursor.
Definition: asn1.h:21
A public key algorithm.
Definition: crypto.h:122
union @391 key
Sense key.
Definition: scsi.h:18

References cms_digest(), data, DBGC, cms_participant::digest, digest_algorithm::digestsize, key, len, cms_participant::pubkey, pubkey_verify(), x509_subject::public_key, x509_public_key::raw, rc, strerror(), x509_certificate::subject, value, and cms_participant::value.

Referenced by cms_verify_signer().

◆ cms_verify_signer()

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

Verify CMS message signer.

Parameters
cmsCMS message
partParticipant information
dataSigned data
lenLength of signed data
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 782 of file cms.c.

786  {
787  struct x509_certificate *cert;
788  int rc;
789 
790  /* Validate certificate chain */
791  if ( ( rc = x509_validate_chain ( part->chain, time, store,
792  root ) ) != 0 ) {
793  DBGC ( cms, "CMS %p/%p could not validate chain: %s\n",
794  cms, part, strerror ( rc ) );
795  return rc;
796  }
797 
798  /* Extract code-signing certificate */
799  cert = x509_first ( part->chain );
800  assert ( cert != NULL );
801 
802  /* Check that certificate can create digital signatures */
803  if ( ! ( cert->extensions.usage.bits & X509_DIGITAL_SIGNATURE ) ) {
804  DBGC ( cms, "CMS %p/%p certificate cannot create signatures\n",
805  cms, part );
806  return -EACCES_NON_SIGNING;
807  }
808 
809  /* Check that certificate can sign code */
810  if ( ! ( cert->extensions.ext_usage.bits & X509_CODE_SIGNING ) ) {
811  DBGC ( cms, "CMS %p/%p certificate is not code-signing\n",
812  cms, part );
813  return -EACCES_NON_CODE_SIGNING;
814  }
815 
816  /* Verify digest */
817  if ( ( rc = cms_verify_digest ( cms, part, cert, data, len ) ) != 0 )
818  return rc;
819 
820  return 0;
821 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct x509_extended_key_usage ext_usage
Extended key usage.
Definition: x509.h:163
struct stp_switch root
Root switch.
Definition: stp.h:27
unsigned int bits
Usage bits.
Definition: x509.h:116
#define DBGC(...)
Definition: compiler.h:505
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
ring len
Length.
Definition: dwmac.h:231
#define EACCES_NON_SIGNING
Definition: cms.c:47
int x509_validate_chain(struct x509_chain *chain, time_t time, struct x509_chain *store, struct x509_root *root)
Validate X.509 certificate chain.
Definition: x509.c:1908
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
An X.509 certificate.
Definition: x509.h:216
static int cms_verify_digest(struct cms_message *cms, struct cms_participant *part, struct x509_certificate *cert, const void *data, size_t len)
Verify digest of CMS-signed data.
Definition: cms.c:745
#define EACCES_NON_CODE_SIGNING
Definition: cms.c:51
unsigned int bits
Usage bits.
Definition: x509.h:97
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
uint8_t data[48]
Additional event data.
Definition: ena.h:22
struct x509_key_usage usage
Key usage.
Definition: x509.h:161
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
struct x509_extensions extensions
Extensions.
Definition: x509.h:249

References assert(), x509_key_usage::bits, x509_extended_key_usage::bits, cms_participant::chain, cms_verify_digest(), data, DBGC, EACCES_NON_CODE_SIGNING, EACCES_NON_SIGNING, x509_extensions::ext_usage, x509_certificate::extensions, len, NULL, rc, root, x509_certificate::store, strerror(), x509_extensions::usage, X509_CODE_SIGNING, X509_DIGITAL_SIGNATURE, x509_first(), and x509_validate_chain().

Referenced by cms_verify().

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

static struct cms_participant* cms_recipient ( struct cms_message cms,
struct private_key private_key 
)
static

Identify CMS recipient corresponding to private key.

Parameters
cmsCMS message
private_keyPrivate key
Return values
partParticipant information, or NULL if not found

Definition at line 887 of file cms.c.

887  {
888  struct cms_participant *part;
889  struct x509_certificate *cert;
890 
891  /* Identify certificate (if any) for which we have a private key */
892  cert = x509_find_key ( NULL, private_key );
893  if ( ! cert )
894  return NULL;
895 
896  /* Identify corresponding recipient, if any */
897  list_for_each_entry ( part, &cms->participants, list ) {
898  if ( cert == x509_first ( part->chain ) )
899  return part;
900  }
901 
902  return NULL;
903 }
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
An X.509 certificate.
Definition: x509.h:216
struct list_head participants
List of participant information blocks.
Definition: cms.h:66
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
A private key.
Definition: privkey.h:17
struct x509_certificate * x509_find_key(struct x509_chain *store, struct private_key *key)
Identify X.509 certificate by corresponding public key.
Definition: x509.c:1835
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322

References cms_participant::chain, list_for_each_entry, NULL, cms_message::participants, x509_find_key(), and x509_first().

Referenced by cms_cipher().

◆ cms_cipher_key()

static int cms_cipher_key ( struct cms_message cms,
struct cms_participant part,
struct private_key private_key,
void *  ctx 
)
static

Set CMS cipher key.

Parameters
cmsCMS message
partParticipant information
private_keyPrivate key
ctxCipher context
Return values
rcReturn status code

Definition at line 914 of file cms.c.

916  {
917  struct cipher_algorithm *cipher = cms->cipher;
918  struct pubkey_algorithm *pubkey = part->pubkey;
919  const struct asn1_cursor *key = privkey_cursor ( private_key );
920  const struct asn1_cursor *value = &part->value;
921  struct asn1_builder cipher_key = { NULL, 0 };
922  int rc;
923 
924  /* Decrypt cipher key */
925  if ( ( rc = pubkey_decrypt ( pubkey, key, value,
926  &cipher_key ) ) != 0 ) {
927  DBGC ( cms, "CMS %p/%p could not decrypt cipher key: %s\n",
928  cms, part, strerror ( rc ) );
929  DBGC_HDA ( cms, 0, value->data, value->len );
930  goto err_decrypt;
931  }
932  DBGC ( cms, "CMS %p/%p cipher key:\n", cms, part );
933  DBGC_HDA ( cms, 0, cipher_key.data, cipher_key.len );
934 
935  /* Set cipher key */
936  if ( ( rc = cipher_setkey ( cipher, ctx, cipher_key.data,
937  cipher_key.len ) ) != 0 ) {
938  DBGC ( cms, "CMS %p could not set cipher key: %s\n",
939  cms, strerror ( rc ) );
940  goto err_setkey;
941  }
942 
943  /* Set cipher initialization vector */
944  cipher_setiv ( cipher, ctx, cms->iv.data, cms->iv.len );
945  if ( cms->iv.len ) {
946  DBGC ( cms, "CMS %p cipher IV:\n", cms );
947  DBGC_HDA ( cms, 0, cms->iv.data, cms->iv.len );
948  }
949 
950  err_setkey:
951  err_decrypt:
952  free ( cipher_key.data );
953  return rc;
954 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void * data
Data.
Definition: asn1.h:36
struct asn1_cursor value
Signature or key value.
Definition: cms.h:51
const void * data
Start of data.
Definition: asn1.h:23
#define DBGC(...)
Definition: compiler.h:505
struct pubkey_algorithm * pubkey
Public-key algorithm.
Definition: cms.h:48
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
size_t len
Length of data.
Definition: asn1.h:25
static struct asn1_cursor * privkey_cursor(struct private_key *key)
Get private key ASN.1 cursor.
Definition: privkey.h:53
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
#define DBGC_HDA(...)
Definition: compiler.h:506
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
struct cipher_algorithm * cipher
Cipher algorithm.
Definition: cms.h:69
static void cipher_setiv(struct cipher_algorithm *cipher, void *ctx, const void *iv, size_t ivlen)
Definition: crypto.h:241
An ASN.1 object builder.
Definition: asn1.h:29
struct asn1_cursor iv
Cipher initialization vector.
Definition: cms.h:71
A cipher algorithm.
Definition: crypto.h:51
A private key.
Definition: privkey.h:17
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
size_t len
Length of data.
Definition: asn1.h:38
An ASN.1 object cursor.
Definition: asn1.h:21
A public key algorithm.
Definition: crypto.h:122
union @391 key
Sense key.
Definition: scsi.h:18
static int pubkey_decrypt(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, const struct asn1_cursor *ciphertext, struct asn1_builder *plaintext)
Definition: crypto.h:294
static int cipher_setkey(struct cipher_algorithm *cipher, void *ctx, const void *key, size_t keylen)
Definition: crypto.h:235

References cms_message::cipher, cipher_setiv(), cipher_setkey(), ctx, asn1_cursor::data, asn1_builder::data, DBGC, DBGC_HDA, free, cms_message::iv, key, asn1_cursor::len, asn1_builder::len, NULL, privkey_cursor(), cms_participant::pubkey, pubkey_decrypt(), rc, strerror(), value, and cms_participant::value.

Referenced by cms_cipher().

◆ cms_cipher()

static int cms_cipher ( struct cms_message cms,
struct private_key private_key,
void *  ctx 
)
static

Initialise cipher for CMS decryption.

Parameters
cmsCMS message
private_keyPrivate key
ctxCipher context
Return values
rcReturn status code

Definition at line 964 of file cms.c.

965  {
966  struct cms_participant *part;
967  int rc;
968 
969  /* Identify a usable recipient */
970  part = cms_recipient ( cms, private_key );
971  if ( ! part ) {
972  DBGC ( cms, "CMS %p had no usable recipients\n", cms );
973  return -EACCES_NO_RECIPIENTS;
974  }
975 
976  /* Decrypt and set cipher key */
977  if ( ( rc = cms_cipher_key ( cms, part, private_key, ctx ) ) != 0 )
978  return rc;
979 
980  return 0;
981 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
static int cms_cipher_key(struct cms_message *cms, struct cms_participant *part, struct private_key *private_key, void *ctx)
Set CMS cipher key.
Definition: cms.c:914
#define DBGC(...)
Definition: compiler.h:505
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
CMS participant information.
Definition: cms.h:39
#define EACCES_NO_RECIPIENTS
Definition: cms.c:63
static struct cms_participant * cms_recipient(struct cms_message *cms, struct private_key *private_key)
Identify CMS recipient corresponding to private key.
Definition: cms.c:887
A private key.
Definition: privkey.h:17

References cms_cipher_key(), cms_recipient(), ctx, DBGC, EACCES_NO_RECIPIENTS, and rc.

Referenced by cms_decrypt().

◆ cms_verify_padding()

static int cms_verify_padding ( struct cms_message cms,
const void *  data,
size_t  len 
)
static

Check CMS padding.

Parameters
cmsCMS message
dataFinal block
lenFinal block length
Return values
lenPadding length, or negative error

Definition at line 991 of file cms.c.

992  {
993  struct cipher_algorithm *cipher = cms->cipher;
994  const uint8_t *pad;
995  size_t pad_len;
996  unsigned int i;
997 
998  /* Non-block ciphers do not use padding */
999  if ( ! is_block_cipher ( cipher ) )
1000  return 0;
1001 
1002  /* Block padding can never produce an empty file */
1003  if ( len == 0 ) {
1004  DBGC ( cms, "CMS %p invalid empty padding\n", cms );
1005  return -EACCES_PAD;
1006  }
1007 
1008  /* Sanity check */
1009  assert ( len >= cipher->blocksize );
1010 
1011  /* Extract and verify padding */
1012  pad = ( data + len - 1 );
1013  pad_len = *pad;
1014  if ( ( pad_len == 0 ) || ( pad_len > len ) ) {
1015  DBGC ( cms, "CMS %p invalid padding length %zd\n",
1016  cms, pad_len );
1017  return -EACCES_PAD;
1018  }
1019  for ( i = 0 ; i < pad_len ; i++ ) {
1020  if ( *(pad--) != pad_len ) {
1021  DBGC ( cms, "CMS %p invalid padding\n", cms );
1022  DBGC_HDA ( cms, 0, ( data + len - pad_len ), pad_len );
1023  return -EACCES_PAD;
1024  }
1025  }
1026 
1027  return pad_len;
1028 }
size_t blocksize
Block size.
Definition: crypto.h:61
#define DBGC(...)
Definition: compiler.h:505
u32 pad[9]
Padding.
Definition: ar9003_mac.h:47
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define DBGC_HDA(...)
Definition: compiler.h:506
ring len
Length.
Definition: dwmac.h:231
#define EACCES_PAD
Definition: cms.c:71
struct cipher_algorithm * cipher
Cipher algorithm.
Definition: cms.h:69
unsigned char uint8_t
Definition: stdint.h:10
long pad_len
Definition: bigint.h:31
uint8_t data[48]
Additional event data.
Definition: ena.h:22
A cipher algorithm.
Definition: crypto.h:51
static int is_block_cipher(struct cipher_algorithm *cipher)
Definition: crypto.h:277

References assert(), cipher_algorithm::blocksize, cms_message::cipher, data, DBGC, DBGC_HDA, EACCES_PAD, is_block_cipher(), len, pad, and pad_len.

Referenced by cms_decrypt().

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

Variable Documentation

◆ oid_signeddata

uint8_t oid_signeddata[] = { ASN1_OID_SIGNEDDATA }
static

"id-signedData" object identifier

Definition at line 90 of file cms.c.

◆ oid_envelopeddata

uint8_t oid_envelopeddata[] = { ASN1_OID_ENVELOPEDDATA }
static

"id-envelopedData" object identifier

Definition at line 93 of file cms.c.

◆ oid_authenvelopeddata

uint8_t oid_authenvelopeddata[] = { ASN1_OID_AUTHENVELOPEDDATA }
static

"id-authEnvelopedData" object identifier

Definition at line 96 of file cms.c.

◆ cms_types

struct cms_type cms_types[]
static
Initial value:
= {
{
.name = "signed",
.parse = cms_parse_signed,
},
{
.name = "enveloped",
},
{
.name = "authEnveloped",
}
}
static int cms_parse_signed(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS signed data.
Definition: cms.c:530
#define ASN1_CURSOR(value)
Define an ASN.1 cursor for a static value.
Definition: asn1.h:402
static int cms_parse_enveloped(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS enveloped data.
Definition: cms.c:575
static uint8_t oid_authenvelopeddata[]
"id-authEnvelopedData" object identifier
Definition: cms.c:96
static uint8_t oid_signeddata[]
"id-signedData" object identifier
Definition: cms.c:90
static uint8_t oid_envelopeddata[]
"id-envelopedData" object identifier
Definition: cms.c:93

CMS message types.

Definition at line 99 of file cms.c.

Referenced by cms_parse_content_type().