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)
 
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 46 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 48 of file cms.c.

◆ EACCES_NON_CODE_SIGNING

#define EACCES_NON_CODE_SIGNING   __einfo_error ( EINFO_EACCES_NON_CODE_SIGNING )

Definition at line 50 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 52 of file cms.c.

◆ EACCES_WRONG_NAME

#define EACCES_WRONG_NAME   __einfo_error ( EINFO_EACCES_WRONG_NAME )

Definition at line 54 of file cms.c.

◆ EINFO_EACCES_WRONG_NAME

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

Definition at line 56 of file cms.c.

◆ EACCES_NO_SIGNATURES

#define EACCES_NO_SIGNATURES   __einfo_error ( EINFO_EACCES_NO_SIGNATURES )

Definition at line 58 of file cms.c.

◆ EINFO_EACCES_NO_SIGNATURES

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

Definition at line 60 of file cms.c.

◆ EACCES_NO_RECIPIENTS

#define EACCES_NO_RECIPIENTS   __einfo_error ( EINFO_EACCES_NO_RECIPIENTS )

Definition at line 62 of file cms.c.

◆ EINFO_EACCES_NO_RECIPIENTS

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

Definition at line 64 of file cms.c.

◆ EACCES_LEN

#define EACCES_LEN   __einfo_error ( EINFO_EACCES_LEN )

Definition at line 66 of file cms.c.

◆ EINFO_EACCES_LEN

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

Definition at line 68 of file cms.c.

◆ EACCES_PAD

#define EACCES_PAD   __einfo_error ( EINFO_EACCES_PAD )

Definition at line 70 of file cms.c.

◆ EINFO_EACCES_PAD

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

Definition at line 72 of file cms.c.

◆ EACCES_MAC

#define EACCES_MAC   __einfo_error ( EINFO_EACCES_MAC )

Definition at line 74 of file cms.c.

◆ EINFO_EACCES_MAC

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

Definition at line 76 of file cms.c.

◆ ENOTSUP_TYPE

#define ENOTSUP_TYPE   __einfo_error ( EINFO_ENOTSUP_TYPE )

Definition at line 78 of file cms.c.

◆ EINFO_ENOTSUP_TYPE

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

Definition at line 80 of file cms.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

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

530  {
531  struct asn1_cursor cursor;
532  int rc;
533 
534  /* Allocate certificate list */
536  if ( ! cms->certificates )
537  return -ENOMEM;
538 
539  /* Enter signedData */
540  memcpy ( &cursor, raw, sizeof ( cursor ) );
541  asn1_enter ( &cursor, ASN1_SEQUENCE );
542 
543  /* Skip version */
544  asn1_skip ( &cursor, ASN1_INTEGER );
545 
546  /* Skip digestAlgorithms */
547  asn1_skip ( &cursor, ASN1_SET );
548 
549  /* Skip encapContentInfo */
550  asn1_skip ( &cursor, ASN1_SEQUENCE );
551 
552  /* Parse certificates */
553  if ( ( rc = cms_parse_certificates ( cms, &cursor ) ) != 0 )
554  return rc;
555  asn1_skip_any ( &cursor );
556 
557  /* Skip crls, if present */
558  asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 1 ) );
559 
560  /* Parse signerInfos */
561  if ( ( rc = cms_parse_participants ( cms, &cursor ) ) != 0 )
562  return rc;
563 
564  return 0;
565 }
struct x509_chain * certificates
List of all certificates (for signature messages)
Definition: cms.h:63
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:432
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:181
struct x509_chain * x509_alloc_chain(void)
Allocate X.509 certificate chain.
Definition: x509.c:1614
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:302
#define ASN1_SET
ASN.1 set.
Definition: asn1.h:92
#define ENOMEM
Not enough space.
Definition: errno.h:534
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:157
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition: asn1.h:89
#define ASN1_INTEGER
ASN.1 integer.
Definition: asn1.h:62
int asn1_skip_if_exists(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object if present.
Definition: asn1.c:214
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition: asn1.c:243
__be32 raw[7]
Definition: CIB_PRM.h:28
#define ASN1_EXPLICIT_TAG(number)
ASN.1 explicit tag.
Definition: asn1.h:98
An ASN.1 object cursor.
Definition: asn1.h:20

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

575  {
576  struct asn1_cursor cursor;
577  int rc;
578 
579  /* Enter envelopedData or authEnvelopedData */
580  memcpy ( &cursor, raw, sizeof ( cursor ) );
581  asn1_enter ( &cursor, ASN1_SEQUENCE );
582 
583  /* Skip version */
584  asn1_skip ( &cursor, ASN1_INTEGER );
585 
586  /* Skip originatorInfo, if present */
587  asn1_skip_if_exists ( &cursor, ASN1_IMPLICIT_TAG ( 0 ) );
588 
589  /* Parse recipientInfos */
590  if ( ( rc = cms_parse_participants ( cms, &cursor ) ) != 0 )
591  return rc;
592  asn1_skip_any ( &cursor );
593 
594  /* Parse encryptedContentInfo or authEncryptedContentInfo */
595  if ( ( rc = cms_parse_encrypted ( cms, &cursor ) ) != 0 )
596  return rc;
597  asn1_skip_any ( &cursor );
598  assert ( cms->cipher != NULL );
599 
600  /* Skip unprotectedAttrs or authAttrs, if present */
601  asn1_skip_if_exists ( &cursor, ASN1_IMPLICIT_TAG ( 1 ) );
602 
603  /* Parse mac, if present */
604  if ( ( cms->cipher->authsize != 0 ) &&
605  ( ( rc = cms_parse_mac ( cms, &cursor ) ) != 0 ) )
606  return rc;
607 
608  return 0;
609 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define ASN1_IMPLICIT_TAG(number)
ASN.1 implicit tag.
Definition: asn1.h:95
static int cms_parse_participants(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message participants information.
Definition: cms.c:432
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:181
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:302
size_t authsize
Authentication tag size.
Definition: crypto.h:74
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:68
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition: asn1.h:89
#define ASN1_INTEGER
ASN.1 integer.
Definition: asn1.h:62
static int cms_parse_encrypted(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message encrypted content information.
Definition: cms.c:478
int asn1_skip_if_exists(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object if present.
Definition: asn1.c:214
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition: asn1.c:243
__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:504
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
An ASN.1 object cursor.
Definition: asn1.h:20

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

124  {
125  struct asn1_cursor cursor;
126  struct cms_type *type;
127  unsigned int i;
128 
129  /* Enter contentType */
130  memcpy ( &cursor, raw, sizeof ( cursor ) );
131  asn1_enter ( &cursor, ASN1_OID );
132 
133  /* Check for a recognised OID */
134  for ( i = 0 ; i < ( sizeof ( cms_types ) /
135  sizeof ( cms_types[0] ) ) ; i++ ) {
136  type = &cms_types[i];
137  if ( asn1_compare ( &cursor, &type->oid ) == 0 ) {
138  cms->type = type;
139  DBGC ( cms, "CMS %p contains %sData\n",
140  cms, type->name );
141  return 0;
142  }
143  }
144 
145  DBGC ( cms, "CMS %p is not a recognised message type:\n", cms );
146  DBGC_HDA ( cms, 0, raw->data, raw->len );
147  return -ENOTSUP_TYPE;
148 }
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition: asn1.c:447
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:181
A CMS message type.
Definition: cms.h:22
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:60
#define DBGC_HDA(...)
Definition: compiler.h:506
#define ENOTSUP_TYPE
Definition: cms.c:78
static struct cms_type cms_types[]
CMS message types.
Definition: cms.c:98
#define ASN1_OID
ASN.1 object identifier.
Definition: asn1.h:74
__be32 raw[7]
Definition: CIB_PRM.h:28
An ASN.1 object cursor.
Definition: asn1.h:20

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

158  {
159  struct asn1_cursor cursor;
160  struct x509_certificate *cert;
161  int rc;
162 
163  /* Enter certificates */
164  memcpy ( &cursor, raw, sizeof ( cursor ) );
165  asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
166 
167  /* Add each certificate */
168  while ( cursor.len ) {
169 
170  /* Add certificate to chain */
171  if ( ( rc = x509_append_raw ( cms->certificates, cursor.data,
172  cursor.len ) ) != 0 ) {
173  DBGC ( cms, "CMS %p could not append certificate: %s\n",
174  cms, strerror ( rc) );
175  DBGC_HDA ( cms, 0, cursor.data, cursor.len );
176  return rc;
177  }
178  cert = x509_last ( cms->certificates );
179  DBGC ( cms, "CMS %p found certificate %s\n",
180  cms, x509_name ( cert ) );
181 
182  /* Move to next certificate */
183  asn1_skip_any ( &cursor );
184  }
185 
186  return 0;
187 }
struct x509_chain * certificates
List of all certificates (for signature messages)
Definition: cms.h:63
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:181
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:1673
#define DBGC(...)
Definition: compiler.h:505
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:302
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:324
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
An X.509 certificate.
Definition: x509.h:215
const char * x509_name(struct x509_certificate *cert)
Get X.509 certificate display name.
Definition: x509.c:146
__be32 raw[7]
Definition: CIB_PRM.h:28
#define ASN1_EXPLICIT_TAG(number)
ASN.1 explicit tag.
Definition: asn1.h:98
An ASN.1 object cursor.
Definition: asn1.h:20

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

199  {
200  struct asn1_cursor cursor;
201  struct asn1_cursor serial;
202  struct asn1_cursor issuer;
203  struct x509_certificate *cert;
204  int rc;
205 
206  /* Enter issuerAndSerialNumber */
207  memcpy ( &cursor, raw, sizeof ( cursor ) );
208  asn1_enter ( &cursor, ASN1_SEQUENCE );
209 
210  /* Identify issuer */
211  memcpy ( &issuer, &cursor, sizeof ( issuer ) );
212  if ( ( rc = asn1_shrink ( &issuer, ASN1_SEQUENCE ) ) != 0 ) {
213  DBGC ( cms, "CMS %p/%p could not locate issuer: %s\n",
214  cms, part, strerror ( rc ) );
215  DBGC_HDA ( cms, 0, raw->data, raw->len );
216  return rc;
217  }
218  DBGC ( cms, "CMS %p/%p issuer is:\n", cms, part );
219  DBGC_HDA ( cms, 0, issuer.data, issuer.len );
220  asn1_skip_any ( &cursor );
221 
222  /* Identify serialNumber */
223  memcpy ( &serial, &cursor, sizeof ( serial ) );
224  if ( ( rc = asn1_shrink ( &serial, ASN1_INTEGER ) ) != 0 ) {
225  DBGC ( cms, "CMS %p/%p could not locate serialNumber: %s\n",
226  cms, part, strerror ( rc ) );
227  DBGC_HDA ( cms, 0, raw->data, raw->len );
228  return rc;
229  }
230  DBGC ( cms, "CMS %p/%p serial number is:\n", cms, part );
231  DBGC_HDA ( cms, 0, serial.data, serial.len );
232 
233  /* Identify certificate */
235  if ( ! cert ) {
236  DBGC ( cms, "CMS %p/%p could not identify certificate\n",
237  cms, part );
238  return ( cms_is_signature ( cms ) ? -ENOENT : 0 );
239  }
240 
241  /* Append certificate to chain */
242  if ( ( rc = x509_append ( part->chain, cert ) ) != 0 ) {
243  DBGC ( cms, "CMS %p/%p could not append certificate: %s\n",
244  cms, part, strerror ( rc ) );
245  return rc;
246  }
247 
248  /* Append remaining certificates to chain */
249  if ( ( rc = x509_auto_append ( part->chain,
250  cms->certificates ) ) != 0 ) {
251  DBGC ( cms, "CMS %p/%p could not append certificates: %s\n",
252  cms, part, strerror ( rc ) );
253  return rc;
254  }
255 
256  return 0;
257 }
struct x509_chain * certificates
List of all certificates (for signature messages)
Definition: cms.h:63
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:181
struct x509_issuer issuer
Issuer.
Definition: x509.h:240
#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:1637
#define ENOENT
No such file or directory.
Definition: errno.h:514
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:302
int asn1_shrink(struct asn1_cursor *cursor, unsigned int type)
Shrink ASN.1 cursor to fit object.
Definition: asn1.c:266
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:1867
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
An X.509 certificate.
Definition: x509.h:215
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:1804
uint64_t serial
Serial number.
Definition: edd.h:30
static int cms_is_signature(struct cms_message *cms)
Check if CMS message is a signature message.
Definition: cms.h:104
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition: asn1.h:89
#define ASN1_INTEGER
ASN.1 integer.
Definition: asn1.h:62
struct x509_chain * chain
Certificate chain.
Definition: cms.h:42
__be32 raw[7]
Definition: CIB_PRM.h:28
An ASN.1 object cursor.
Definition: asn1.h:20

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

269  {
270  struct asn1_algorithm *algorithm;
271  int rc;
272 
273  /* Identify algorithm */
274  if ( ( rc = asn1_digest_algorithm ( raw, &algorithm ) ) != 0 ) {
275  DBGC ( cms, "CMS %p/%p could not identify digest algorithm: "
276  "%s\n", cms, part, strerror ( rc ) );
277  DBGC_HDA ( cms, 0, raw->data, raw->len );
278  return rc;
279  }
280 
281  /* Record digest algorithm */
282  part->digest = algorithm->digest;
283  DBGC ( cms, "CMS %p/%p digest algorithm is %s\n",
284  cms, part, algorithm->name );
285 
286  return 0;
287 }
An ASN.1 OID-identified algorithm.
Definition: asn1.h:383
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:559
struct digest_algorithm * digest
Digest algorithm (for signature messages)
Definition: cms.h:45
#define DBGC_HDA(...)
Definition: compiler.h:506
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
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 297 of file cms.c.

299  {
300  struct asn1_algorithm *algorithm;
301  int rc;
302 
303  /* Identify algorithm */
304  if ( ( rc = asn1_pubkey_algorithm ( raw, &algorithm ) ) != 0 ) {
305  DBGC ( cms, "CMS %p/%p could not identify public-key "
306  "algorithm: %s\n", cms, part, strerror ( rc ) );
307  DBGC_HDA ( cms, 0, raw->data, raw->len );
308  return rc;
309  }
310 
311  /* Record public-key algorithm */
312  part->pubkey = algorithm->pubkey;
313  DBGC ( cms, "CMS %p/%p public-key algorithm is %s\n",
314  cms, part, algorithm->name );
315 
316  return 0;
317 }
An ASN.1 OID-identified algorithm.
Definition: asn1.h:383
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:47
#define DBGC_HDA(...)
Definition: compiler.h:506
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
int asn1_pubkey_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified public-key algorithm.
Definition: asn1.c:533
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 326 of file cms.c.

327  {
328  struct asn1_algorithm *algorithm;
329  int rc;
330 
331  /* Identify algorithm */
332  if ( ( rc = asn1_cipher_algorithm ( raw, &algorithm,
333  &cms->iv ) ) != 0 ) {
334  DBGC ( cms, "CMS %p could not identify cipher algorithm: %s\n",
335  cms, strerror ( rc ) );
336  DBGC_HDA ( cms, 0, raw->data, raw->len );
337  return rc;
338  }
339 
340  /* Record cipher */
341  cms->cipher = algorithm->cipher;
342  DBGC ( cms, "CMS %p cipher algorithm is %s\n", cms, algorithm->name );
343 
344  return 0;
345 }
An ASN.1 OID-identified algorithm.
Definition: asn1.h:383
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:78
struct cipher_algorithm * cipher
Cipher algorithm.
Definition: cms.h:68
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:586
struct asn1_cursor iv
Cipher initialization vector.
Definition: cms.h:70
__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 355 of file cms.c.

357  {
358  int rc;
359 
360  /* Enter signature or encryptedKey */
361  memcpy ( &part->value, raw, sizeof ( part->value ) );
362  if ( ( rc = asn1_enter ( &part->value, ASN1_OCTET_STRING ) ) != 0 ) {
363  DBGC ( cms, "CMS %p/%p could not locate value:\n",
364  cms, part );
365  DBGC_HDA ( cms, 0, raw->data, raw->len );
366  return rc;
367  }
368  DBGC ( cms, "CMS %p/%p value is:\n", cms, part );
369  DBGC_HDA ( cms, 0, part->value.data, part->value.len );
370 
371  return 0;
372 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct asn1_cursor value
Signature or key value.
Definition: cms.h:50
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:181
const void * data
Start of data.
Definition: asn1.h:22
#define DBGC(...)
Definition: compiler.h:505
size_t len
Length of data.
Definition: asn1.h:24
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:68

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

384  {
385  struct asn1_cursor cursor;
386  int rc;
387 
388  /* Enter signerInfo or ktri */
389  memcpy ( &cursor, raw, sizeof ( cursor ) );
390  asn1_enter ( &cursor, ASN1_SEQUENCE );
391 
392  /* Skip version */
393  asn1_skip ( &cursor, ASN1_INTEGER );
394 
395  /* Parse sid or rid */
396  if ( ( rc = cms_parse_identifier ( cms, part, &cursor ) ) != 0 )
397  return rc;
398  asn1_skip_any ( &cursor );
399 
400  /* Parse signature-only objects */
401  if ( cms_is_signature ( cms ) ) {
402 
403  /* Parse digestAlgorithm */
404  if ( ( rc = cms_parse_digest_algorithm ( cms, part,
405  &cursor ) ) != 0 )
406  return rc;
407  asn1_skip_any ( &cursor );
408 
409  /* Skip signedAttrs, if present */
410  asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
411  }
412 
413  /* Parse signatureAlgorithm or contentEncryptionAlgorithm */
414  if ( ( rc = cms_parse_pubkey_algorithm ( cms, part, &cursor ) ) != 0 )
415  return rc;
416  asn1_skip_any ( &cursor );
417 
418  /* Parse signature or encryptedKey */
419  if ( ( rc = cms_parse_value ( cms, part, &cursor ) ) != 0 )
420  return rc;
421 
422  return 0;
423 }
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:181
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:267
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:355
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:302
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:104
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition: asn1.h:89
#define ASN1_INTEGER
ASN.1 integer.
Definition: asn1.h:62
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:197
int asn1_skip_if_exists(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object if present.
Definition: asn1.c:214
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition: asn1.c:243
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:297
__be32 raw[7]
Definition: CIB_PRM.h:28
#define ASN1_EXPLICIT_TAG(number)
ASN.1 explicit tag.
Definition: asn1.h:98
An ASN.1 object cursor.
Definition: asn1.h:20

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

433  {
434  struct asn1_cursor cursor;
435  struct cms_participant *part;
436  int rc;
437 
438  /* Enter signerInfos or recipientInfos */
439  memcpy ( &cursor, raw, sizeof ( cursor ) );
440  asn1_enter ( &cursor, ASN1_SET );
441 
442  /* Add each signerInfo or recipientInfo. Errors are handled
443  * by ensuring that cms_put() will always be able to free any
444  * allocated memory.
445  */
446  while ( cursor.len ) {
447 
448  /* Allocate participant information block */
449  part = zalloc ( sizeof ( *part ) );
450  if ( ! part )
451  return -ENOMEM;
452  list_add ( &part->list, &cms->participants );
453  part->digest = &digest_null;
454  part->pubkey = &pubkey_null;
455 
456  /* Allocate certificate chain */
457  part->chain = x509_alloc_chain();
458  if ( ! part->chain )
459  return -ENOMEM;
460 
461  /* Parse signerInfo or recipientInfo */
462  if ( ( rc = cms_parse_participant ( cms, part,
463  &cursor ) ) != 0 )
464  return rc;
465  asn1_skip_any ( &cursor );
466  }
467 
468  return 0;
469 }
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:181
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:69
struct x509_chain * x509_alloc_chain(void)
Allocate X.509 certificate chain.
Definition: x509.c:1614
struct digest_algorithm * digest
Digest algorithm (for signature messages)
Definition: cms.h:45
struct pubkey_algorithm pubkey_null
Definition: crypto_null.c:122
struct pubkey_algorithm * pubkey
Public-key algorithm.
Definition: cms.h:47
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:302
#define ASN1_SET
ASN.1 set.
Definition: asn1.h:92
#define ENOMEM
Not enough space.
Definition: errno.h:534
void * memcpy(void *dest, const void *src, size_t len) __nonnull
CMS participant information.
Definition: cms.h:38
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:661
struct digest_algorithm digest_null
Definition: crypto_null.c:48
struct list_head participants
List of participant information blocks.
Definition: cms.h:65
struct list_head list
List of participant information blocks.
Definition: cms.h:40
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:382
struct x509_chain * chain
Certificate chain.
Definition: cms.h:42
__be32 raw[7]
Definition: CIB_PRM.h:28
An ASN.1 object cursor.
Definition: asn1.h:20

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

479  {
480  struct asn1_cursor cursor;
481  int rc;
482 
483  /* Enter encryptedContentInfo */
484  memcpy ( &cursor, raw, sizeof ( cursor ) );
485  asn1_enter ( &cursor, ASN1_SEQUENCE );
486 
487  /* Skip contentType */
488  asn1_skip ( &cursor, ASN1_OID );
489 
490  /* Parse contentEncryptionAlgorithm */
491  if ( ( rc = cms_parse_cipher_algorithm ( cms, &cursor ) ) != 0 )
492  return rc;
493 
494  return 0;
495 }
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:181
static int cms_parse_cipher_algorithm(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message cipher algorithm.
Definition: cms.c:326
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition: asn1.h:89
#define ASN1_OID
ASN.1 object identifier.
Definition: asn1.h:74
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition: asn1.c:243
__be32 raw[7]
Definition: CIB_PRM.h:28
An ASN.1 object cursor.
Definition: asn1.h:20

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

505  {
506  int rc;
507 
508  /* Enter mac */
509  memcpy ( &cms->mac, raw, sizeof ( cms->mac ) );
510  if ( ( rc = asn1_enter ( &cms->mac, ASN1_OCTET_STRING ) ) != 0 ) {
511  DBGC ( cms, "CMS %p could not locate mac: %s\n",
512  cms, strerror ( rc ) );
513  DBGC_HDA ( cms, 0, raw->data, raw->len );
514  return rc;
515  }
516  DBGC ( cms, "CMS %p mac is:\n", cms );
517  DBGC_HDA ( cms, 0, cms->mac.data, cms->mac.len );
518 
519  return 0;
520 }
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:181
const void * data
Start of data.
Definition: asn1.h:22
#define DBGC(...)
Definition: compiler.h:505
size_t len
Length of data.
Definition: asn1.h:24
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:78
__be32 raw[7]
Definition: CIB_PRM.h:28
struct asn1_cursor mac
Cipher authentication tag.
Definition: cms.h:72
#define ASN1_OCTET_STRING
ASN.1 octet string.
Definition: asn1.h:68

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

617  {
618  struct asn1_cursor cursor;
619  int rc;
620 
621  /* Enter contentInfo */
622  memcpy ( &cursor, cms->raw, sizeof ( cursor ) );
623  asn1_enter ( &cursor, ASN1_SEQUENCE );
624 
625  /* Parse contentType */
626  if ( ( rc = cms_parse_content_type ( cms, &cursor ) ) != 0 )
627  return rc;
628  asn1_skip_any ( &cursor );
629 
630  /* Enter content */
631  asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
632 
633  /* Parse type-specific content */
634  if ( ( rc = cms->type->parse ( cms, &cursor ) ) != 0 )
635  return rc;
636 
637  return 0;
638 }
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:181
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:302
void * memcpy(void *dest, const void *src, size_t len) __nonnull
struct cms_type * type
Message type.
Definition: cms.h:60
int(* parse)(struct cms_message *cms, const struct asn1_cursor *raw)
Parse content.
Definition: cms.h:33
struct asn1_cursor * raw
Raw ASN.1 data.
Definition: cms.h:58
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition: asn1.h:89
#define ASN1_EXPLICIT_TAG(number)
ASN.1 explicit tag.
Definition: asn1.h:98
An ASN.1 object cursor.
Definition: asn1.h:20
static int cms_parse_content_type(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message content type.
Definition: cms.c:123

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

645  {
646  struct cms_message *cms =
647  container_of ( refcnt, struct cms_message, refcnt );
648  struct cms_participant *part;
649  struct cms_participant *tmp;
650 
651  list_for_each_entry_safe ( part, tmp, &cms->participants, list ) {
652  list_del ( &part->list );
653  x509_chain_put ( part->chain );
654  free ( part );
655  }
656  x509_chain_put ( cms->certificates );
657  free ( cms->raw );
658  free ( cms );
659 }
static void x509_chain_put(struct x509_chain *chain)
Drop reference to X.509 certificate chain.
Definition: x509.h:299
struct x509_chain * certificates
List of all certificates (for signature messages)
Definition: cms.h:63
A CMS message.
Definition: cms.h:54
A reference counter.
Definition: refcnt.h:26
unsigned long tmp
Definition: linux_pci.h:64
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
CMS participant information.
Definition: cms.h:38
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
#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:458
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
struct asn1_cursor * raw
Raw ASN.1 data.
Definition: cms.h:58
struct list_head participants
List of participant information blocks.
Definition: cms.h:65
struct list_head list
List of participant information blocks.
Definition: cms.h:40
struct x509_chain * chain
Certificate chain.
Definition: cms.h:42

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

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

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

◆ cms_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 719 of file cms.c.

721  {
722  struct digest_algorithm *digest = part->digest;
723  uint8_t ctx[ digest->ctxsize ];
724 
725  /* Calculate digest */
726  digest_init ( digest, ctx );
727  digest_update ( digest, ctx, data, len );
728  digest_final ( digest, ctx, out );
729 
730  DBGC ( cms, "CMS %p/%p digest value:\n", cms, part );
731  DBGC_HDA ( cms, 0, out, digest->digestsize );
732 }
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition: crypto.h:201
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition: crypto.h:207
#define DBGC(...)
Definition: compiler.h:505
struct digest_algorithm * digest
Digest algorithm (for signature messages)
Definition: cms.h:45
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:196
unsigned char uint8_t
Definition: stdint.h:10
size_t ctxsize
Context size.
Definition: crypto.h:22
size_t digestsize
Digest size.
Definition: crypto.h:26
A message digest algorithm.
Definition: crypto.h:18
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 744 of file cms.c.

747  {
748  struct digest_algorithm *digest = part->digest;
749  struct pubkey_algorithm *pubkey = part->pubkey;
750  const struct asn1_cursor *key = &cert->subject.public_key.raw;
751  const struct asn1_cursor *value = &part->value;
752  uint8_t digest_out[ digest->digestsize ];
753  int rc;
754 
755  /* Generate digest */
756  cms_digest ( cms, part, data, len, digest_out );
757 
758  /* Verify digest */
759  if ( ( rc = pubkey_verify ( pubkey, key, digest, digest_out,
760  value ) ) != 0 ) {
761  DBGC ( cms, "CMS %p/%p signature verification failed: %s\n",
762  cms, part, strerror ( rc ) );
763  return rc;
764  }
765 
766  return 0;
767 }
struct asn1_cursor raw
Raw public key information.
Definition: x509.h:51
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct asn1_cursor value
Signature or key value.
Definition: cms.h:50
#define DBGC(...)
Definition: compiler.h:505
struct digest_algorithm * digest
Digest algorithm (for signature messages)
Definition: cms.h:45
struct pubkey_algorithm * pubkey
Public-key algorithm.
Definition: cms.h:47
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:719
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:65
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
struct x509_subject subject
Subject.
Definition: x509.h:244
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:285
size_t digestsize
Digest size.
Definition: crypto.h:26
A message digest algorithm.
Definition: crypto.h:18
uint8_t data[48]
Additional event data.
Definition: ena.h:22
An ASN.1 object cursor.
Definition: asn1.h:20
A public key algorithm.
Definition: crypto.h:121
union @391 key
Sense key.
Definition: scsi.h:17

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

785  {
786  struct x509_certificate *cert;
787  int rc;
788 
789  /* Validate certificate chain */
790  if ( ( rc = x509_validate_chain ( part->chain, time, store,
791  root ) ) != 0 ) {
792  DBGC ( cms, "CMS %p/%p could not validate chain: %s\n",
793  cms, part, strerror ( rc ) );
794  return rc;
795  }
796 
797  /* Extract code-signing certificate */
798  cert = x509_first ( part->chain );
799  assert ( cert != NULL );
800 
801  /* Check that certificate can create digital signatures */
802  if ( ! ( cert->extensions.usage.bits & X509_DIGITAL_SIGNATURE ) ) {
803  DBGC ( cms, "CMS %p/%p certificate cannot create signatures\n",
804  cms, part );
805  return -EACCES_NON_SIGNING;
806  }
807 
808  /* Check that certificate can sign code */
809  if ( ! ( cert->extensions.ext_usage.bits & X509_CODE_SIGNING ) ) {
810  DBGC ( cms, "CMS %p/%p certificate is not code-signing\n",
811  cms, part );
812  return -EACCES_NON_CODE_SIGNING;
813  }
814 
815  /* Verify digest */
816  if ( ( rc = cms_verify_digest ( cms, part, cert, data, len ) ) != 0 )
817  return rc;
818 
819  return 0;
820 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct x509_extended_key_usage ext_usage
Extended key usage.
Definition: x509.h:162
struct stp_switch root
Root switch.
Definition: stp.h:26
unsigned int bits
Usage bits.
Definition: x509.h:115
#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:46
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:1907
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
An X.509 certificate.
Definition: x509.h:215
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:744
#define EACCES_NON_CODE_SIGNING
Definition: cms.c:50
unsigned int bits
Usage bits.
Definition: x509.h:96
static struct x509_certificate * x509_first(struct x509_chain *chain)
Get first certificate in X.509 certificate chain.
Definition: x509.h:310
struct x509_chain * chain
Certificate chain.
Definition: cms.h:42
struct x509_link store
Link in certificate store.
Definition: x509.h:220
uint8_t data[48]
Additional event data.
Definition: ena.h:22
struct x509_key_usage usage
Key usage.
Definition: x509.h:160
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
struct x509_extensions extensions
Extensions.
Definition: x509.h:248

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

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

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

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

◆ cms_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 886 of file cms.c.

886  {
887  struct cms_participant *part;
888  struct x509_certificate *cert;
889 
890  /* Identify certificate (if any) for which we have a private key */
891  cert = x509_find_key ( NULL, private_key );
892  if ( ! cert )
893  return NULL;
894 
895  /* Identify corresponding recipient, if any */
896  list_for_each_entry ( part, &cms->participants, list ) {
897  if ( cert == x509_first ( part->chain ) )
898  return part;
899  }
900 
901  return NULL;
902 }
CMS participant information.
Definition: cms.h:38
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
An X.509 certificate.
Definition: x509.h:215
struct list_head participants
List of participant information blocks.
Definition: cms.h:65
static struct x509_certificate * x509_first(struct x509_chain *chain)
Get first certificate in X.509 certificate chain.
Definition: x509.h:310
struct x509_chain * chain
Certificate chain.
Definition: cms.h:42
A private key.
Definition: privkey.h:16
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:1834
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321

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

915  {
916  struct cipher_algorithm *cipher = cms->cipher;
917  struct pubkey_algorithm *pubkey = part->pubkey;
918  const struct asn1_cursor *key = privkey_cursor ( private_key );
919  const struct asn1_cursor *value = &part->value;
920  struct asn1_builder cipher_key = { NULL, 0 };
921  int rc;
922 
923  /* Decrypt cipher key */
924  if ( ( rc = pubkey_decrypt ( pubkey, key, value,
925  &cipher_key ) ) != 0 ) {
926  DBGC ( cms, "CMS %p/%p could not decrypt cipher key: %s\n",
927  cms, part, strerror ( rc ) );
928  DBGC_HDA ( cms, 0, value->data, value->len );
929  goto err_decrypt;
930  }
931  DBGC ( cms, "CMS %p/%p cipher key:\n", cms, part );
932  DBGC_HDA ( cms, 0, cipher_key.data, cipher_key.len );
933 
934  /* Set cipher key */
935  if ( ( rc = cipher_setkey ( cipher, ctx, cipher_key.data,
936  cipher_key.len ) ) != 0 ) {
937  DBGC ( cms, "CMS %p could not set cipher key: %s\n",
938  cms, strerror ( rc ) );
939  goto err_setkey;
940  }
941 
942  /* Set cipher initialization vector */
943  cipher_setiv ( cipher, ctx, cms->iv.data, cms->iv.len );
944  if ( cms->iv.len ) {
945  DBGC ( cms, "CMS %p cipher IV:\n", cms );
946  DBGC_HDA ( cms, 0, cms->iv.data, cms->iv.len );
947  }
948 
949  err_setkey:
950  err_decrypt:
951  free ( cipher_key.data );
952  return rc;
953 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void * data
Data.
Definition: asn1.h:35
struct asn1_cursor value
Signature or key value.
Definition: cms.h:50
const void * data
Start of data.
Definition: asn1.h:22
#define DBGC(...)
Definition: compiler.h:505
struct pubkey_algorithm * pubkey
Public-key algorithm.
Definition: cms.h:47
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
size_t len
Length of data.
Definition: asn1.h:24
static struct asn1_cursor * privkey_cursor(struct private_key *key)
Get private key ASN.1 cursor.
Definition: privkey.h:52
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:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
struct cipher_algorithm * cipher
Cipher algorithm.
Definition: cms.h:68
static void cipher_setiv(struct cipher_algorithm *cipher, void *ctx, const void *iv, size_t ivlen)
Definition: crypto.h:218
An ASN.1 object builder.
Definition: asn1.h:28
struct asn1_cursor iv
Cipher initialization vector.
Definition: cms.h:70
A cipher algorithm.
Definition: crypto.h:50
A private key.
Definition: privkey.h:16
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
size_t len
Length of data.
Definition: asn1.h:37
An ASN.1 object cursor.
Definition: asn1.h:20
A public key algorithm.
Definition: crypto.h:121
union @391 key
Sense key.
Definition: scsi.h:17
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:271
static int cipher_setkey(struct cipher_algorithm *cipher, void *ctx, const void *key, size_t keylen)
Definition: crypto.h:212

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

964  {
965  struct cms_participant *part;
966  int rc;
967 
968  /* Identify a usable recipient */
969  part = cms_recipient ( cms, private_key );
970  if ( ! part ) {
971  DBGC ( cms, "CMS %p had no usable recipients\n", cms );
972  return -EACCES_NO_RECIPIENTS;
973  }
974 
975  /* Decrypt and set cipher key */
976  if ( ( rc = cms_cipher_key ( cms, part, private_key, ctx ) ) != 0 )
977  return rc;
978 
979  return 0;
980 }
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:913
#define DBGC(...)
Definition: compiler.h:505
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
CMS participant information.
Definition: cms.h:38
#define EACCES_NO_RECIPIENTS
Definition: cms.c:62
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:886
A private key.
Definition: privkey.h:16

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

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

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

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

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

Referenced by cms_decrypt_okx(), and imgdecrypt().

Variable Documentation

◆ oid_signeddata

uint8_t oid_signeddata[] = { ASN1_OID_SIGNEDDATA }
static

"id-signedData" object identifier

Definition at line 89 of file cms.c.

◆ oid_envelopeddata

uint8_t oid_envelopeddata[] = { ASN1_OID_ENVELOPEDDATA }
static

"id-envelopedData" object identifier

Definition at line 92 of file cms.c.

◆ oid_authenvelopeddata

uint8_t oid_authenvelopeddata[] = { ASN1_OID_AUTHENVELOPEDDATA }
static

"id-authEnvelopedData" object identifier

Definition at line 95 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:529
#define ASN1_CURSOR(value)
Define an ASN.1 cursor for a static value.
Definition: asn1.h:377
static int cms_parse_enveloped(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS enveloped data.
Definition: cms.c:574
static uint8_t oid_authenvelopeddata[]
"id-authEnvelopedData" object identifier
Definition: cms.c:95
static uint8_t oid_signeddata[]
"id-signedData" object identifier
Definition: cms.c:89
static uint8_t oid_envelopeddata[]
"id-envelopedData" object identifier
Definition: cms.c:92

CMS message types.

Definition at line 98 of file cms.c.

Referenced by cms_parse_content_type().