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/uaccess.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" )
 
#define CMS_DECRYPT_BLKSZ   2048
 Buffer size for decryption. More...
 

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, userptr_t 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, userptr_t data, size_t len)
 Verify digest of CMS-signed data. More...
 
static int cms_verify_signer (struct cms_message *cms, struct cms_participant *part, userptr_t data, size_t len, time_t time, struct x509_chain *store, struct x509_root *root)
 Verify CMS message signer. 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.

◆ CMS_DECRYPT_BLKSZ

#define CMS_DECRYPT_BLKSZ   2048

Buffer size for decryption.

Must be at least 256 to allow block padding to be removed if needed.

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

536  {
537  struct asn1_cursor cursor;
538  int rc;
539 
540  /* Allocate certificate list */
542  if ( ! cms->certificates )
543  return -ENOMEM;
544 
545  /* Enter signedData */
546  memcpy ( &cursor, raw, sizeof ( cursor ) );
547  asn1_enter ( &cursor, ASN1_SEQUENCE );
548 
549  /* Skip version */
550  asn1_skip ( &cursor, ASN1_INTEGER );
551 
552  /* Skip digestAlgorithms */
553  asn1_skip ( &cursor, ASN1_SET );
554 
555  /* Skip encapContentInfo */
556  asn1_skip ( &cursor, ASN1_SEQUENCE );
557 
558  /* Parse certificates */
559  if ( ( rc = cms_parse_certificates ( cms, &cursor ) ) != 0 )
560  return rc;
561  asn1_skip_any ( &cursor );
562 
563  /* Skip crls, if present */
564  asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 1 ) );
565 
566  /* Parse signerInfos */
567  if ( ( rc = cms_parse_participants ( cms, &cursor ) ) != 0 )
568  return rc;
569 
570  return 0;
571 }
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:440
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:205
struct x509_chain * x509_alloc_chain(void)
Allocate X.509 certificate chain.
Definition: x509.c:1612
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:313
#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:165
#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:225
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition: asn1.c:254
__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 580 of file cms.c.

581  {
582  struct asn1_cursor cursor;
583  int rc;
584 
585  /* Enter envelopedData or authEnvelopedData */
586  memcpy ( &cursor, raw, sizeof ( cursor ) );
587  asn1_enter ( &cursor, ASN1_SEQUENCE );
588 
589  /* Skip version */
590  asn1_skip ( &cursor, ASN1_INTEGER );
591 
592  /* Skip originatorInfo, if present */
593  asn1_skip_if_exists ( &cursor, ASN1_IMPLICIT_TAG ( 0 ) );
594 
595  /* Parse recipientInfos */
596  if ( ( rc = cms_parse_participants ( cms, &cursor ) ) != 0 )
597  return rc;
598  asn1_skip_any ( &cursor );
599 
600  /* Parse encryptedContentInfo or authEncryptedContentInfo */
601  if ( ( rc = cms_parse_encrypted ( cms, &cursor ) ) != 0 )
602  return rc;
603  asn1_skip_any ( &cursor );
604  assert ( cms->cipher != NULL );
605 
606  /* Skip unprotectedAttrs or authAttrs, if present */
607  asn1_skip_if_exists ( &cursor, ASN1_IMPLICIT_TAG ( 1 ) );
608 
609  /* Parse mac, if present */
610  if ( ( cms->cipher->authsize != 0 ) &&
611  ( ( rc = cms_parse_mac ( cms, &cursor ) ) != 0 ) )
612  return rc;
613 
614  return 0;
615 }
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:440
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:205
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:313
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:69
#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:484
int asn1_skip_if_exists(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object if present.
Definition: asn1.c:225
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition: asn1.c:254
__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:510
#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 131 of file cms.c.

132  {
133  struct asn1_cursor cursor;
134  struct cms_type *type;
135  unsigned int i;
136 
137  /* Enter contentType */
138  memcpy ( &cursor, raw, sizeof ( cursor ) );
139  asn1_enter ( &cursor, ASN1_OID );
140 
141  /* Check for a recognised OID */
142  for ( i = 0 ; i < ( sizeof ( cms_types ) /
143  sizeof ( cms_types[0] ) ) ; i++ ) {
144  type = &cms_types[i];
145  if ( asn1_compare ( &cursor, &type->oid ) == 0 ) {
146  cms->type = type;
147  DBGC ( cms, "CMS %p contains %sData\n",
148  cms, type->name );
149  return 0;
150  }
151  }
152 
153  DBGC ( cms, "CMS %p is not a recognised message type:\n", cms );
154  DBGC_HDA ( cms, 0, raw->data, raw->len );
155  return -ENOTSUP_TYPE;
156 }
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition: asn1.c:480
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:205
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:106
#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 165 of file cms.c.

166  {
167  struct asn1_cursor cursor;
168  struct x509_certificate *cert;
169  int rc;
170 
171  /* Enter certificates */
172  memcpy ( &cursor, raw, sizeof ( cursor ) );
173  asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
174 
175  /* Add each certificate */
176  while ( cursor.len ) {
177 
178  /* Add certificate to chain */
179  if ( ( rc = x509_append_raw ( cms->certificates, cursor.data,
180  cursor.len ) ) != 0 ) {
181  DBGC ( cms, "CMS %p could not append certificate: %s\n",
182  cms, strerror ( rc) );
183  DBGC_HDA ( cms, 0, cursor.data, cursor.len );
184  return rc;
185  }
186  cert = x509_last ( cms->certificates );
187  DBGC ( cms, "CMS %p found certificate %s\n",
188  cms, x509_name ( cert ) );
189 
190  /* Move to next certificate */
191  asn1_skip_any ( &cursor );
192  }
193 
194  return 0;
195 }
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:205
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:1660
#define DBGC(...)
Definition: compiler.h:505
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:313
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 205 of file cms.c.

207  {
208  struct asn1_cursor cursor;
209  struct asn1_cursor serial;
210  struct asn1_cursor issuer;
211  struct x509_certificate *cert;
212  int rc;
213 
214  /* Enter issuerAndSerialNumber */
215  memcpy ( &cursor, raw, sizeof ( cursor ) );
216  asn1_enter ( &cursor, ASN1_SEQUENCE );
217 
218  /* Identify issuer */
219  memcpy ( &issuer, &cursor, sizeof ( issuer ) );
220  if ( ( rc = asn1_shrink ( &issuer, ASN1_SEQUENCE ) ) != 0 ) {
221  DBGC ( cms, "CMS %p/%p could not locate issuer: %s\n",
222  cms, part, strerror ( rc ) );
223  DBGC_HDA ( cms, 0, raw->data, raw->len );
224  return rc;
225  }
226  DBGC ( cms, "CMS %p/%p issuer is:\n", cms, part );
227  DBGC_HDA ( cms, 0, issuer.data, issuer.len );
228  asn1_skip_any ( &cursor );
229 
230  /* Identify serialNumber */
231  memcpy ( &serial, &cursor, sizeof ( serial ) );
232  if ( ( rc = asn1_shrink ( &serial, ASN1_INTEGER ) ) != 0 ) {
233  DBGC ( cms, "CMS %p/%p could not locate serialNumber: %s\n",
234  cms, part, strerror ( rc ) );
235  DBGC_HDA ( cms, 0, raw->data, raw->len );
236  return rc;
237  }
238  DBGC ( cms, "CMS %p/%p serial number is:\n", cms, part );
239  DBGC_HDA ( cms, 0, serial.data, serial.len );
240 
241  /* Identify certificate */
243  if ( ! cert ) {
244  DBGC ( cms, "CMS %p/%p could not identify certificate\n",
245  cms, part );
246  return ( cms_is_signature ( cms ) ? -ENOENT : 0 );
247  }
248 
249  /* Append certificate to chain */
250  if ( ( rc = x509_append ( part->chain, cert ) ) != 0 ) {
251  DBGC ( cms, "CMS %p/%p could not append certificate: %s\n",
252  cms, part, strerror ( rc ) );
253  return rc;
254  }
255 
256  /* Append remaining certificates to chain */
257  if ( ( rc = x509_auto_append ( part->chain,
258  cms->certificates ) ) != 0 ) {
259  DBGC ( cms, "CMS %p/%p could not append certificates: %s\n",
260  cms, part, strerror ( rc ) );
261  return rc;
262  }
263 
264  return 0;
265 }
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:205
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:1635
#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:313
int asn1_shrink(struct asn1_cursor *cursor, unsigned int type)
Shrink ASN.1 cursor to fit object.
Definition: asn1.c:277
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:1854
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:1791
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:105
#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:43
__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 275 of file cms.c.

277  {
278  struct asn1_algorithm *algorithm;
279  int rc;
280 
281  /* Identify algorithm */
282  if ( ( rc = asn1_digest_algorithm ( raw, &algorithm ) ) != 0 ) {
283  DBGC ( cms, "CMS %p/%p could not identify digest algorithm: "
284  "%s\n", cms, part, strerror ( rc ) );
285  DBGC_HDA ( cms, 0, raw->data, raw->len );
286  return rc;
287  }
288 
289  /* Record digest algorithm */
290  part->digest = algorithm->digest;
291  DBGC ( cms, "CMS %p/%p digest algorithm is %s\n",
292  cms, part, algorithm->name );
293 
294  return 0;
295 }
An ASN.1 OID-identified algorithm.
Definition: asn1.h:366
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:592
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: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 305 of file cms.c.

307  {
308  struct asn1_algorithm *algorithm;
309  int rc;
310 
311  /* Identify algorithm */
312  if ( ( rc = asn1_pubkey_algorithm ( raw, &algorithm ) ) != 0 ) {
313  DBGC ( cms, "CMS %p/%p could not identify public-key "
314  "algorithm: %s\n", cms, part, strerror ( rc ) );
315  DBGC_HDA ( cms, 0, raw->data, raw->len );
316  return rc;
317  }
318 
319  /* Record public-key algorithm */
320  part->pubkey = algorithm->pubkey;
321  DBGC ( cms, "CMS %p/%p public-key algorithm is %s\n",
322  cms, part, algorithm->name );
323 
324  return 0;
325 }
An ASN.1 OID-identified algorithm.
Definition: asn1.h:366
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: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:566
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 334 of file cms.c.

335  {
336  struct asn1_algorithm *algorithm;
337  int rc;
338 
339  /* Identify algorithm */
340  if ( ( rc = asn1_cipher_algorithm ( raw, &algorithm,
341  &cms->iv ) ) != 0 ) {
342  DBGC ( cms, "CMS %p could not identify cipher algorithm: %s\n",
343  cms, strerror ( rc ) );
344  DBGC_HDA ( cms, 0, raw->data, raw->len );
345  return rc;
346  }
347 
348  /* Record cipher */
349  cms->cipher = algorithm->cipher;
350  DBGC ( cms, "CMS %p cipher algorithm is %s\n", cms, algorithm->name );
351 
352  return 0;
353 }
An ASN.1 OID-identified algorithm.
Definition: asn1.h:366
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: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:619
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 363 of file cms.c.

365  {
366  int rc;
367 
368  /* Enter signature or encryptedKey */
369  memcpy ( &part->value, raw, sizeof ( part->value ) );
370  if ( ( rc = asn1_enter ( &part->value, ASN1_OCTET_STRING ) ) != 0 ) {
371  DBGC ( cms, "CMS %p/%p could not locate value:\n",
372  cms, part );
373  DBGC_HDA ( cms, 0, raw->data, raw->len );
374  return rc;
375  }
376  DBGC ( cms, "CMS %p/%p value is:\n", cms, part );
377  DBGC_HDA ( cms, 0, part->value.data, part->value.len );
378 
379  return 0;
380 }
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:205
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 390 of file cms.c.

392  {
393  struct asn1_cursor cursor;
394  int rc;
395 
396  /* Enter signerInfo or ktri */
397  memcpy ( &cursor, raw, sizeof ( cursor ) );
398  asn1_enter ( &cursor, ASN1_SEQUENCE );
399 
400  /* Skip version */
401  asn1_skip ( &cursor, ASN1_INTEGER );
402 
403  /* Parse sid or rid */
404  if ( ( rc = cms_parse_identifier ( cms, part, &cursor ) ) != 0 )
405  return rc;
406  asn1_skip_any ( &cursor );
407 
408  /* Parse signature-only objects */
409  if ( cms_is_signature ( cms ) ) {
410 
411  /* Parse digestAlgorithm */
412  if ( ( rc = cms_parse_digest_algorithm ( cms, part,
413  &cursor ) ) != 0 )
414  return rc;
415  asn1_skip_any ( &cursor );
416 
417  /* Skip signedAttrs, if present */
418  asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
419  }
420 
421  /* Parse signatureAlgorithm or contentEncryptionAlgorithm */
422  if ( ( rc = cms_parse_pubkey_algorithm ( cms, part, &cursor ) ) != 0 )
423  return rc;
424  asn1_skip_any ( &cursor );
425 
426  /* Parse signature or encryptedKey */
427  if ( ( rc = cms_parse_value ( cms, part, &cursor ) ) != 0 )
428  return rc;
429 
430  return 0;
431 }
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:205
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:275
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:363
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:313
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: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:205
int asn1_skip_if_exists(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object if present.
Definition: asn1.c:225
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition: asn1.c:254
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:305
__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 440 of file cms.c.

441  {
442  struct asn1_cursor cursor;
443  struct cms_participant *part;
444  int rc;
445 
446  /* Enter signerInfos or recipientInfos */
447  memcpy ( &cursor, raw, sizeof ( cursor ) );
448  asn1_enter ( &cursor, ASN1_SET );
449 
450  /* Add each signerInfo or recipientInfo. Errors are handled
451  * by ensuring that cms_put() will always be able to free any
452  * allocated memory.
453  */
454  while ( cursor.len ) {
455 
456  /* Allocate participant information block */
457  part = zalloc ( sizeof ( *part ) );
458  if ( ! part )
459  return -ENOMEM;
460  list_add ( &part->list, &cms->participants );
461 
462  /* Allocate certificate chain */
463  part->chain = x509_alloc_chain();
464  if ( ! part->chain )
465  return -ENOMEM;
466 
467  /* Parse signerInfo or recipientInfo */
468  if ( ( rc = cms_parse_participant ( cms, part,
469  &cursor ) ) != 0 )
470  return rc;
471  asn1_skip_any ( &cursor );
472  }
473 
474  return 0;
475 }
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:205
#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:1612
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:313
#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:39
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
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:390
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:20

References asn1_enter(), ASN1_SET, asn1_skip_any(), cms_participant::chain, cms_parse_participant(), ENOMEM, asn1_cursor::len, cms_participant::list, list_add, memcpy(), cms_message::participants, 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 484 of file cms.c.

485  {
486  struct asn1_cursor cursor;
487  int rc;
488 
489  /* Enter encryptedContentInfo */
490  memcpy ( &cursor, raw, sizeof ( cursor ) );
491  asn1_enter ( &cursor, ASN1_SEQUENCE );
492 
493  /* Skip contentType */
494  asn1_skip ( &cursor, ASN1_OID );
495 
496  /* Parse contentEncryptionAlgorithm */
497  if ( ( rc = cms_parse_cipher_algorithm ( cms, &cursor ) ) != 0 )
498  return rc;
499 
500  return 0;
501 }
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:205
static int cms_parse_cipher_algorithm(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message cipher algorithm.
Definition: cms.c:334
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:254
__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 510 of file cms.c.

511  {
512  int rc;
513 
514  /* Enter mac */
515  memcpy ( &cms->mac, raw, sizeof ( cms->mac ) );
516  if ( ( rc = asn1_enter ( &cms->mac, ASN1_OCTET_STRING ) ) != 0 ) {
517  DBGC ( cms, "CMS %p could not locate mac: %s\n",
518  cms, strerror ( rc ) );
519  DBGC_HDA ( cms, 0, raw->data, raw->len );
520  return rc;
521  }
522  DBGC ( cms, "CMS %p mac is:\n", cms );
523  DBGC_HDA ( cms, 0, cms->mac.data, cms->mac.len );
524 
525  return 0;
526 }
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:205
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:73
#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 623 of file cms.c.

623  {
624  struct asn1_cursor cursor;
625  int rc;
626 
627  /* Enter contentInfo */
628  memcpy ( &cursor, cms->raw, sizeof ( cursor ) );
629  asn1_enter ( &cursor, ASN1_SEQUENCE );
630 
631  /* Parse contentType */
632  if ( ( rc = cms_parse_content_type ( cms, &cursor ) ) != 0 )
633  return rc;
634  asn1_skip_any ( &cursor );
635 
636  /* Enter content */
637  asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
638 
639  /* Parse type-specific content */
640  if ( ( rc = cms->type->parse ( cms, &cursor ) ) != 0 )
641  return rc;
642 
643  return 0;
644 }
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:205
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:313
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: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:131

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

651  {
652  struct cms_message *cms =
653  container_of ( refcnt, struct cms_message, refcnt );
654  struct cms_participant *part;
655  struct cms_participant *tmp;
656 
657  list_for_each_entry_safe ( part, tmp, &cms->participants, list ) {
658  list_del ( &part->list );
659  x509_chain_put ( part->chain );
660  free ( part );
661  }
662  x509_chain_put ( cms->certificates );
663  free ( cms->raw );
664  free ( cms );
665 }
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:64
A CMS message.
Definition: cms.h:55
A reference counter.
Definition: refcnt.h:26
unsigned long tmp
Definition: linux_pci.h:63
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
CMS participant information.
Definition: cms.h:39
#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: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 677 of file cms.c.

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

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

◆ cms_digest()

static void cms_digest ( struct cms_message cms,
struct cms_participant part,
userptr_t  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 725 of file cms.c.

727  {
728  struct digest_algorithm *digest = part->digest;
729  uint8_t ctx[ digest->ctxsize ];
730  uint8_t block[ digest->blocksize ];
731  size_t offset = 0;
732  size_t frag_len;
733 
734  /* Initialise digest */
735  digest_init ( digest, ctx );
736 
737  /* Process data one block at a time */
738  while ( len ) {
739  frag_len = len;
740  if ( frag_len > sizeof ( block ) )
741  frag_len = sizeof ( block );
742  copy_from_user ( block, data, offset, frag_len );
743  digest_update ( digest, ctx, block, frag_len );
744  offset += frag_len;
745  len -= frag_len;
746  }
747 
748  /* Finalise digest */
749  digest_final ( digest, ctx, out );
750 
751  DBGC ( cms, "CMS %p/%p digest value:\n", cms, part );
752  DBGC_HDA ( cms, 0, out, digest->digestsize );
753 }
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition: crypto.h:206
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition: crypto.h:212
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:411
#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
size_t blocksize
Block size.
Definition: crypto.h:24
#define DBGC_HDA(...)
Definition: compiler.h:506
__be32 out[4]
Definition: CIB_PRM.h:36
static void digest_init(struct digest_algorithm *digest, void *ctx)
Definition: crypto.h:201
unsigned char uint8_t
Definition: stdint.h:10
size_t ctxsize
Context size.
Definition: crypto.h:22
uint8_t block[3][8]
DES-encrypted blocks.
Definition: mschapv2.h:12
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
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
uint32_t len
Length.
Definition: ena.h:14

References block, digest_algorithm::blocksize, copy_from_user(), ctx, digest_algorithm::ctxsize, data, DBGC, DBGC_HDA, cms_participant::digest, digest_final(), digest_init(), digest_update(), digest_algorithm::digestsize, len, offset, 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,
userptr_t  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 765 of file cms.c.

768  {
769  struct digest_algorithm *digest = part->digest;
770  struct pubkey_algorithm *pubkey = part->pubkey;
771  const struct asn1_cursor *key = &cert->subject.public_key.raw;
772  const struct asn1_cursor *value = &part->value;
773  uint8_t digest_out[ digest->digestsize ];
774  int rc;
775 
776  /* Generate digest */
777  cms_digest ( cms, part, data, len, digest_out );
778 
779  /* Verify digest */
780  if ( ( rc = pubkey_verify ( pubkey, key, digest, digest_out,
781  value->data, value->len ) ) != 0 ) {
782  DBGC ( cms, "CMS %p/%p signature verification failed: %s\n",
783  cms, part, strerror ( rc ) );
784  return rc;
785  }
786 
787  return 0;
788 }
struct asn1_cursor raw
Raw public key information.
Definition: x509.h:51
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
static int pubkey_verify(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, const void *signature, size_t signature_len)
Definition: crypto.h:294
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
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
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
size_t digestsize
Digest size.
Definition: crypto.h:26
static void cms_digest(struct cms_message *cms, struct cms_participant *part, userptr_t data, size_t len, void *out)
Calculate digest of CMS-signed data.
Definition: cms.c:725
A message digest algorithm.
Definition: crypto.h:18
uint8_t data[48]
Additional event data.
Definition: ena.h:22
uint32_t len
Length.
Definition: ena.h:14
An ASN.1 object cursor.
Definition: asn1.h:20
A public key algorithm.
Definition: crypto.h:121
union @383 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,
userptr_t  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 802 of file cms.c.

806  {
807  struct x509_certificate *cert;
808  int rc;
809 
810  /* Validate certificate chain */
811  if ( ( rc = x509_validate_chain ( part->chain, time, store,
812  root ) ) != 0 ) {
813  DBGC ( cms, "CMS %p/%p could not validate chain: %s\n",
814  cms, part, strerror ( rc ) );
815  return rc;
816  }
817 
818  /* Extract code-signing certificate */
819  cert = x509_first ( part->chain );
820  assert ( cert != NULL );
821 
822  /* Check that certificate can create digital signatures */
823  if ( ! ( cert->extensions.usage.bits & X509_DIGITAL_SIGNATURE ) ) {
824  DBGC ( cms, "CMS %p/%p certificate cannot create signatures\n",
825  cms, part );
826  return -EACCES_NON_SIGNING;
827  }
828 
829  /* Check that certificate can sign code */
830  if ( ! ( cert->extensions.ext_usage.bits & X509_CODE_SIGNING ) ) {
831  DBGC ( cms, "CMS %p/%p certificate is not code-signing\n",
832  cms, part );
833  return -EACCES_NON_CODE_SIGNING;
834  }
835 
836  /* Verify digest */
837  if ( ( rc = cms_verify_digest ( cms, part, cert, data, len ) ) != 0 )
838  return rc;
839 
840  return 0;
841 }
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)
#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:1894
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
An X.509 certificate.
Definition: x509.h:215
#define EACCES_NON_CODE_SIGNING
Definition: cms.c:51
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:43
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
uint32_t len
Length.
Definition: ena.h:14
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
static int cms_verify_digest(struct cms_message *cms, struct cms_participant *part, struct x509_certificate *cert, userptr_t data, size_t len)
Verify digest of CMS-signed data.
Definition: cms.c:765
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 854 of file cms.c.

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

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

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

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

907  {
908  struct cms_participant *part;
909  struct x509_certificate *cert;
910 
911  /* Identify certificate (if any) for which we have a private key */
912  cert = x509_find_key ( NULL, private_key );
913  if ( ! cert )
914  return NULL;
915 
916  /* Identify corresponding recipient, if any */
917  list_for_each_entry ( part, &cms->participants, list ) {
918  if ( cert == x509_first ( part->chain ) )
919  return part;
920  }
921 
922  return NULL;
923 }
CMS participant information.
Definition: cms.h:39
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:431
An X.509 certificate.
Definition: x509.h:215
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:310
struct x509_chain * chain
Certificate chain.
Definition: cms.h:43
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:1821
#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 934 of file cms.c.

936  {
937  struct cipher_algorithm *cipher = cms->cipher;
938  struct pubkey_algorithm *pubkey = part->pubkey;
939  const struct asn1_cursor *key = privkey_cursor ( private_key );
940  const struct asn1_cursor *value = &part->value;
941  size_t max_len = pubkey_max_len ( pubkey, key );
942  uint8_t cipher_key[max_len];
943  int len;
944  int rc;
945 
946  /* Decrypt cipher key */
947  len = pubkey_decrypt ( pubkey, key, value->data, value->len,
948  cipher_key );
949  if ( len < 0 ) {
950  rc = len;
951  DBGC ( cms, "CMS %p/%p could not decrypt cipher key: %s\n",
952  cms, part, strerror ( rc ) );
953  DBGC_HDA ( cms, 0, value->data, value->len );
954  return rc;
955  }
956  DBGC ( cms, "CMS %p/%p cipher key:\n", cms, part );
957  DBGC_HDA ( cms, 0, cipher_key, len );
958 
959  /* Set cipher key */
960  if ( ( rc = cipher_setkey ( cipher, ctx, cipher_key, len ) ) != 0 ) {
961  DBGC ( cms, "CMS %p could not set cipher key: %s\n",
962  cms, strerror ( rc ) );
963  return rc;
964  }
965 
966  /* Set cipher initialization vector */
967  cipher_setiv ( cipher, ctx, cms->iv.data, cms->iv.len );
968  if ( cms->iv.len ) {
969  DBGC ( cms, "CMS %p cipher IV:\n", cms );
970  DBGC_HDA ( cms, 0, cms->iv.data, cms->iv.len );
971  }
972 
973  return 0;
974 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct asn1_cursor value
Signature or key value.
Definition: cms.h:51
const void * data
Start of data.
Definition: asn1.h:22
#define DBGC(...)
Definition: compiler.h:505
static int pubkey_decrypt(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, const void *data, size_t len, void *out)
Definition: crypto.h:281
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: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
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:223
unsigned char uint8_t
Definition: stdint.h:10
struct asn1_cursor iv
Cipher initialization vector.
Definition: cms.h:71
A cipher algorithm.
Definition: crypto.h:50
A private key.
Definition: privkey.h:16
static size_t pubkey_max_len(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key)
Definition: crypto.h:269
uint32_t len
Length.
Definition: ena.h:14
An ASN.1 object cursor.
Definition: asn1.h:20
A public key algorithm.
Definition: crypto.h:121
union @383 key
Sense key.
Definition: scsi.h:18
static int cipher_setkey(struct cipher_algorithm *cipher, void *ctx, const void *key, size_t keylen)
Definition: crypto.h:217

References cms_message::cipher, cipher_setiv(), cipher_setkey(), ctx, asn1_cursor::data, DBGC, DBGC_HDA, cms_message::iv, key, len, asn1_cursor::len, privkey_cursor(), cms_participant::pubkey, pubkey_decrypt(), pubkey_max_len(), 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 984 of file cms.c.

985  {
986  struct cms_participant *part;
987  int rc;
988 
989  /* Identify a usable recipient */
990  part = cms_recipient ( cms, private_key );
991  if ( ! part ) {
992  DBGC ( cms, "CMS %p had no usable recipients\n", cms );
993  return -EACCES_NO_RECIPIENTS;
994  }
995 
996  /* Decrypt and set cipher key */
997  if ( ( rc = cms_cipher_key ( cms, part, private_key, ctx ) ) != 0 )
998  return rc;
999 
1000  return 0;
1001 }
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:934
#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:907
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 1011 of file cms.c.

1012  {
1013  struct cipher_algorithm *cipher = cms->cipher;
1014  const uint8_t *pad;
1015  size_t pad_len;
1016  unsigned int i;
1017 
1018  /* Non-block ciphers do not use padding */
1019  if ( ! is_block_cipher ( cipher ) )
1020  return 0;
1021 
1022  /* Block padding can never produce an empty file */
1023  if ( len == 0 ) {
1024  DBGC ( cms, "CMS %p invalid empty padding\n", cms );
1025  return -EACCES_PAD;
1026  }
1027 
1028  /* Sanity check */
1029  assert ( len >= cipher->blocksize );
1030 
1031  /* Extract and verify padding */
1032  pad = ( data + len - 1 );
1033  pad_len = *pad;
1034  if ( ( pad_len == 0 ) || ( pad_len > len ) ) {
1035  DBGC ( cms, "CMS %p invalid padding length %zd\n",
1036  cms, pad_len );
1037  return -EACCES_PAD;
1038  }
1039  for ( i = 0 ; i < pad_len ; i++ ) {
1040  if ( *(pad--) != pad_len ) {
1041  DBGC ( cms, "CMS %p invalid padding\n", cms );
1042  DBGC_HDA ( cms, 0, ( data + len - pad_len ), pad_len );
1043  return -EACCES_PAD;
1044  }
1045  }
1046 
1047  return pad_len;
1048 }
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
#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:30
uint8_t data[48]
Additional event data.
Definition: ena.h:22
A cipher algorithm.
Definition: crypto.h:50
uint32_t len
Length.
Definition: ena.h:14
static int is_block_cipher(struct cipher_algorithm *cipher)
Definition: crypto.h:259

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

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

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

Referenced by cms_decrypt_okx(), and imgdecrypt().

Variable Documentation

◆ oid_signeddata

uint8_t oid_signeddata[] = { ASN1_OID_SIGNEDDATA }
static

"id-signedData" object identifier

Definition at line 97 of file cms.c.

◆ oid_envelopeddata

uint8_t oid_envelopeddata[] = { ASN1_OID_ENVELOPEDDATA }
static

"id-envelopedData" object identifier

Definition at line 100 of file cms.c.

◆ oid_authenvelopeddata

uint8_t oid_authenvelopeddata[] = { ASN1_OID_AUTHENVELOPEDDATA }
static

"id-authEnvelopedData" object identifier

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

CMS message types.

Definition at line 106 of file cms.c.

Referenced by cms_parse_content_type().