iPXE
cms.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27/** @file
28 *
29 * Cryptographic Message Syntax (PKCS #7)
30 *
31 * The format of CMS messages is defined in RFC 5652.
32 *
33 */
34
35#include <stdint.h>
36#include <string.h>
37#include <time.h>
38#include <errno.h>
39#include <ipxe/asn1.h>
40#include <ipxe/x509.h>
41#include <ipxe/image.h>
42#include <ipxe/malloc.h>
43#include <ipxe/privkey.h>
44#include <ipxe/cms.h>
45
46/* Disambiguate the various error causes */
47#define EACCES_NON_SIGNING \
48 __einfo_error ( EINFO_EACCES_NON_SIGNING )
49#define EINFO_EACCES_NON_SIGNING \
50 __einfo_uniqify ( EINFO_EACCES, 0x01, "Not a signing certificate" )
51#define EACCES_NON_CODE_SIGNING \
52 __einfo_error ( EINFO_EACCES_NON_CODE_SIGNING )
53#define EINFO_EACCES_NON_CODE_SIGNING \
54 __einfo_uniqify ( EINFO_EACCES, 0x02, "Not a code-signing certificate" )
55#define EACCES_WRONG_NAME \
56 __einfo_error ( EINFO_EACCES_WRONG_NAME )
57#define EINFO_EACCES_WRONG_NAME \
58 __einfo_uniqify ( EINFO_EACCES, 0x04, "Incorrect certificate name" )
59#define EACCES_NO_SIGNATURES \
60 __einfo_error ( EINFO_EACCES_NO_SIGNATURES )
61#define EINFO_EACCES_NO_SIGNATURES \
62 __einfo_uniqify ( EINFO_EACCES, 0x05, "No signatures present" )
63#define EACCES_NO_RECIPIENTS \
64 __einfo_error ( EINFO_EACCES_NO_RECIPIENTS )
65#define EINFO_EACCES_NO_RECIPIENTS \
66 __einfo_uniqify ( EINFO_EACCES, 0x06, "No usable recipients" )
67#define EACCES_LEN \
68 __einfo_error ( EINFO_EACCES_LEN )
69#define EINFO_EACCES_LEN \
70 __einfo_uniqify ( EINFO_EACCES, 0x07, "Bad file length" )
71#define EACCES_PAD \
72 __einfo_error ( EINFO_EACCES_PAD )
73#define EINFO_EACCES_PAD \
74 __einfo_uniqify ( EINFO_EACCES, 0x08, "Bad block padding" )
75#define EACCES_MAC \
76 __einfo_error ( EINFO_EACCES_MAC )
77#define EINFO_EACCES_MAC \
78 __einfo_uniqify ( EINFO_EACCES, 0x09, "Invalid MAC" )
79#define ENOTSUP_TYPE \
80 __einfo_error ( EINFO_ENOTSUP_TYPE )
81#define EINFO_ENOTSUP_TYPE \
82 __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unrecognised message type" )
83
84static int cms_parse_signed ( struct cms_message *cms,
85 const struct asn1_cursor *raw );
86static int cms_parse_enveloped ( struct cms_message *cms,
87 const struct asn1_cursor *raw );
88
89/** "id-signedData" object identifier */
91
92/** "id-envelopedData" object identifier */
94
95/** "id-authEnvelopedData" object identifier */
97
98/** CMS message types */
99static struct cms_type cms_types[] = {
100 {
101 .name = "signed",
102 .oid = ASN1_CURSOR ( oid_signeddata ),
103 .parse = cms_parse_signed,
104 },
105 {
106 .name = "enveloped",
108 .parse = cms_parse_enveloped,
109 },
110 {
111 .name = "authEnveloped",
113 .parse = cms_parse_enveloped,
114 }
115};
116
117/**
118 * Parse CMS message content type
119 *
120 * @v cms CMS message
121 * @v raw ASN.1 cursor
122 * @ret rc Return status code
123 */
124static int cms_parse_content_type ( struct cms_message *cms,
125 const struct asn1_cursor *raw ) {
126 struct asn1_cursor cursor;
127 struct cms_type *type;
128 unsigned int i;
129
130 /* Enter contentType */
131 memcpy ( &cursor, raw, sizeof ( cursor ) );
132 asn1_enter ( &cursor, ASN1_OID );
133
134 /* Check for a recognised OID */
135 for ( i = 0 ; i < ( sizeof ( cms_types ) /
136 sizeof ( cms_types[0] ) ) ; i++ ) {
137 type = &cms_types[i];
138 if ( asn1_compare ( &cursor, &type->oid ) == 0 ) {
139 cms->type = type;
140 DBGC ( cms, "CMS %p contains %sData\n",
141 cms, type->name );
142 return 0;
143 }
144 }
145
146 DBGC ( cms, "CMS %p is not a recognised message type:\n", cms );
147 DBGC_HDA ( cms, 0, raw->data, raw->len );
148 return -ENOTSUP_TYPE;
149}
150
151/**
152 * Parse CMS message certificate list
153 *
154 * @v cms CMS message
155 * @v raw ASN.1 cursor
156 * @ret rc Return status code
157 */
158static int cms_parse_certificates ( struct cms_message *cms,
159 const struct asn1_cursor *raw ) {
160 struct asn1_cursor cursor;
161 struct x509_certificate *cert;
162 int rc;
163
164 /* Enter certificates */
165 memcpy ( &cursor, raw, sizeof ( cursor ) );
166 asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
167
168 /* Add each certificate */
169 while ( cursor.len ) {
170
171 /* Add certificate to chain */
172 if ( ( rc = x509_append_raw ( cms->certificates, cursor.data,
173 cursor.len ) ) != 0 ) {
174 DBGC ( cms, "CMS %p could not append certificate: %s\n",
175 cms, strerror ( rc) );
176 DBGC_HDA ( cms, 0, cursor.data, cursor.len );
177 return rc;
178 }
179 cert = x509_last ( cms->certificates );
180 DBGC ( cms, "CMS %p found certificate %s\n",
181 cms, x509_name ( cert ) );
182
183 /* Move to next certificate */
184 asn1_skip_any ( &cursor );
185 }
186
187 return 0;
188}
189
190/**
191 * Parse CMS message participant identifier
192 *
193 * @v cms CMS message
194 * @v part Participant information to fill in
195 * @v raw ASN.1 cursor
196 * @ret rc Return status code
197 */
198static int cms_parse_identifier ( struct cms_message *cms,
199 struct cms_participant *part,
200 const struct asn1_cursor *raw ) {
201 struct asn1_cursor cursor;
202 struct asn1_cursor serial;
203 struct asn1_cursor issuer;
204 struct x509_certificate *cert;
205 int rc;
206
207 /* Enter issuerAndSerialNumber */
208 memcpy ( &cursor, raw, sizeof ( cursor ) );
209 asn1_enter ( &cursor, ASN1_SEQUENCE );
210
211 /* Identify issuer */
212 memcpy ( &issuer, &cursor, sizeof ( issuer ) );
213 if ( ( rc = asn1_shrink ( &issuer, ASN1_SEQUENCE ) ) != 0 ) {
214 DBGC ( cms, "CMS %p/%p could not locate issuer: %s\n",
215 cms, part, strerror ( rc ) );
216 DBGC_HDA ( cms, 0, raw->data, raw->len );
217 return rc;
218 }
219 DBGC ( cms, "CMS %p/%p issuer is:\n", cms, part );
220 DBGC_HDA ( cms, 0, issuer.data, issuer.len );
221 asn1_skip_any ( &cursor );
222
223 /* Identify serialNumber */
224 memcpy ( &serial, &cursor, sizeof ( serial ) );
225 if ( ( rc = asn1_shrink ( &serial, ASN1_INTEGER ) ) != 0 ) {
226 DBGC ( cms, "CMS %p/%p could not locate serialNumber: %s\n",
227 cms, part, strerror ( rc ) );
228 DBGC_HDA ( cms, 0, raw->data, raw->len );
229 return rc;
230 }
231 DBGC ( cms, "CMS %p/%p serial number is:\n", cms, part );
232 DBGC_HDA ( cms, 0, serial.data, serial.len );
233
234 /* Identify certificate */
236 if ( ! cert ) {
237 DBGC ( cms, "CMS %p/%p could not identify certificate\n",
238 cms, part );
239 return ( cms_is_signature ( cms ) ? -ENOENT : 0 );
240 }
241
242 /* Append certificate to chain */
243 if ( ( rc = x509_append ( part->chain, cert ) ) != 0 ) {
244 DBGC ( cms, "CMS %p/%p could not append certificate: %s\n",
245 cms, part, strerror ( rc ) );
246 return rc;
247 }
248
249 /* Append remaining certificates to chain */
250 if ( ( rc = x509_auto_append ( part->chain,
251 cms->certificates ) ) != 0 ) {
252 DBGC ( cms, "CMS %p/%p could not append certificates: %s\n",
253 cms, part, strerror ( rc ) );
254 return rc;
255 }
256
257 return 0;
258}
259
260/**
261 * Parse CMS message digest algorithm
262 *
263 * @v cms CMS message
264 * @v part Participant information to fill in
265 * @v raw ASN.1 cursor
266 * @ret rc Return status code
267 */
269 struct cms_participant *part,
270 const struct asn1_cursor *raw ) {
272 int rc;
273
274 /* Identify algorithm */
275 if ( ( rc = asn1_digest_algorithm ( raw, &algorithm ) ) != 0 ) {
276 DBGC ( cms, "CMS %p/%p could not identify digest algorithm: "
277 "%s\n", cms, part, strerror ( rc ) );
278 DBGC_HDA ( cms, 0, raw->data, raw->len );
279 return rc;
280 }
281
282 /* Record digest algorithm */
283 part->digest = algorithm->digest;
284 DBGC ( cms, "CMS %p/%p digest algorithm is %s\n",
285 cms, part, algorithm->name );
286
287 return 0;
288}
289
290/**
291 * Parse CMS message public-key algorithm
292 *
293 * @v cms CMS message
294 * @v part Participant information to fill in
295 * @v raw ASN.1 cursor
296 * @ret rc Return status code
297 */
299 struct cms_participant *part,
300 const struct asn1_cursor *raw ) {
302 int rc;
303
304 /* Identify algorithm */
305 if ( ( rc = asn1_pubkey_algorithm ( raw, &algorithm ) ) != 0 ) {
306 DBGC ( cms, "CMS %p/%p could not identify public-key "
307 "algorithm: %s\n", cms, part, strerror ( rc ) );
308 DBGC_HDA ( cms, 0, raw->data, raw->len );
309 return rc;
310 }
311
312 /* Record public-key algorithm */
313 part->pubkey = algorithm->pubkey;
314 DBGC ( cms, "CMS %p/%p public-key algorithm is %s\n",
315 cms, part, algorithm->name );
316
317 return 0;
318}
319
320/**
321 * Parse CMS message cipher algorithm
322 *
323 * @v cms CMS message
324 * @v raw ASN.1 cursor
325 * @ret rc Return status code
326 */
328 const struct asn1_cursor *raw ) {
330 int rc;
331
332 /* Identify algorithm */
334 &cms->iv ) ) != 0 ) {
335 DBGC ( cms, "CMS %p could not identify cipher algorithm: %s\n",
336 cms, strerror ( rc ) );
337 DBGC_HDA ( cms, 0, raw->data, raw->len );
338 return rc;
339 }
340
341 /* Record cipher */
342 cms->cipher = algorithm->cipher;
343 DBGC ( cms, "CMS %p cipher algorithm is %s\n", cms, algorithm->name );
344
345 return 0;
346}
347
348/**
349 * Parse CMS message signature or key value
350 *
351 * @v cms CMS message
352 * @v part Participant information to fill in
353 * @v raw ASN.1 cursor
354 * @ret rc Return status code
355 */
356static int cms_parse_value ( struct cms_message *cms,
357 struct cms_participant *part,
358 const struct asn1_cursor *raw ) {
359 int rc;
360
361 /* Enter signature or encryptedKey */
362 memcpy ( &part->value, raw, sizeof ( part->value ) );
363 if ( ( rc = asn1_enter ( &part->value, ASN1_OCTET_STRING ) ) != 0 ) {
364 DBGC ( cms, "CMS %p/%p could not locate value:\n",
365 cms, part );
366 DBGC_HDA ( cms, 0, raw->data, raw->len );
367 return rc;
368 }
369 DBGC ( cms, "CMS %p/%p value is:\n", cms, part );
370 DBGC_HDA ( cms, 0, part->value.data, part->value.len );
371
372 return 0;
373}
374
375/**
376 * Parse CMS message participant information
377 *
378 * @v cms CMS message
379 * @v part Participant information to fill in
380 * @v raw ASN.1 cursor
381 * @ret rc Return status code
382 */
383static int cms_parse_participant ( struct cms_message *cms,
384 struct cms_participant *part,
385 const struct asn1_cursor *raw ) {
386 struct asn1_cursor cursor;
387 int rc;
388
389 /* Enter signerInfo or ktri */
390 memcpy ( &cursor, raw, sizeof ( cursor ) );
391 asn1_enter ( &cursor, ASN1_SEQUENCE );
392
393 /* Skip version */
394 asn1_skip ( &cursor, ASN1_INTEGER );
395
396 /* Parse sid or rid */
397 if ( ( rc = cms_parse_identifier ( cms, part, &cursor ) ) != 0 )
398 return rc;
399 asn1_skip_any ( &cursor );
400
401 /* Parse signature-only objects */
402 if ( cms_is_signature ( cms ) ) {
403
404 /* Parse digestAlgorithm */
405 if ( ( rc = cms_parse_digest_algorithm ( cms, part,
406 &cursor ) ) != 0 )
407 return rc;
408 asn1_skip_any ( &cursor );
409
410 /* Skip signedAttrs, if present */
411 asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
412 }
413
414 /* Parse signatureAlgorithm or contentEncryptionAlgorithm */
415 if ( ( rc = cms_parse_pubkey_algorithm ( cms, part, &cursor ) ) != 0 )
416 return rc;
417 asn1_skip_any ( &cursor );
418
419 /* Parse signature or encryptedKey */
420 if ( ( rc = cms_parse_value ( cms, part, &cursor ) ) != 0 )
421 return rc;
422
423 return 0;
424}
425
426/**
427 * Parse CMS message participants information
428 *
429 * @v cms CMS message
430 * @v raw ASN.1 cursor
431 * @ret rc Return status code
432 */
433static int cms_parse_participants ( struct cms_message *cms,
434 const struct asn1_cursor *raw ) {
435 struct asn1_cursor cursor;
436 struct cms_participant *part;
437 int rc;
438
439 /* Enter signerInfos or recipientInfos */
440 memcpy ( &cursor, raw, sizeof ( cursor ) );
441 asn1_enter ( &cursor, ASN1_SET );
442
443 /* Add each signerInfo or recipientInfo. Errors are handled
444 * by ensuring that cms_put() will always be able to free any
445 * allocated memory.
446 */
447 while ( cursor.len ) {
448
449 /* Allocate participant information block */
450 part = zalloc ( sizeof ( *part ) );
451 if ( ! part )
452 return -ENOMEM;
453 list_add ( &part->list, &cms->participants );
454 part->digest = &digest_null;
455 part->pubkey = &pubkey_null;
456
457 /* Allocate certificate chain */
458 part->chain = x509_alloc_chain();
459 if ( ! part->chain )
460 return -ENOMEM;
461
462 /* Parse signerInfo or recipientInfo */
463 if ( ( rc = cms_parse_participant ( cms, part,
464 &cursor ) ) != 0 )
465 return rc;
466 asn1_skip_any ( &cursor );
467 }
468
469 return 0;
470}
471
472/**
473 * Parse CMS message encrypted content information
474 *
475 * @v cms CMS message
476 * @v raw ASN.1 cursor
477 * @ret rc Return status code
478 */
479static int cms_parse_encrypted ( struct cms_message *cms,
480 const struct asn1_cursor *raw ) {
481 struct asn1_cursor cursor;
482 int rc;
483
484 /* Enter encryptedContentInfo */
485 memcpy ( &cursor, raw, sizeof ( cursor ) );
486 asn1_enter ( &cursor, ASN1_SEQUENCE );
487
488 /* Skip contentType */
489 asn1_skip ( &cursor, ASN1_OID );
490
491 /* Parse contentEncryptionAlgorithm */
492 if ( ( rc = cms_parse_cipher_algorithm ( cms, &cursor ) ) != 0 )
493 return rc;
494
495 return 0;
496}
497
498/**
499 * Parse CMS message MAC
500 *
501 * @v cms CMS message
502 * @v raw ASN.1 cursor
503 * @ret rc Return status code
504 */
505static int cms_parse_mac ( struct cms_message *cms,
506 const struct asn1_cursor *raw ) {
507 int rc;
508
509 /* Enter mac */
510 memcpy ( &cms->mac, raw, sizeof ( cms->mac ) );
511 if ( ( rc = asn1_enter ( &cms->mac, ASN1_OCTET_STRING ) ) != 0 ) {
512 DBGC ( cms, "CMS %p could not locate mac: %s\n",
513 cms, strerror ( rc ) );
514 DBGC_HDA ( cms, 0, raw->data, raw->len );
515 return rc;
516 }
517 DBGC ( cms, "CMS %p mac is:\n", cms );
518 DBGC_HDA ( cms, 0, cms->mac.data, cms->mac.len );
519
520 return 0;
521}
522
523/**
524 * Parse CMS signed data
525 *
526 * @v cms CMS message
527 * @v raw ASN.1 cursor
528 * @ret rc Return status code
529 */
530static int cms_parse_signed ( struct cms_message *cms,
531 const struct asn1_cursor *raw ) {
532 struct asn1_cursor cursor;
533 int rc;
534
535 /* Allocate certificate list */
537 if ( ! cms->certificates )
538 return -ENOMEM;
539
540 /* Enter signedData */
541 memcpy ( &cursor, raw, sizeof ( cursor ) );
542 asn1_enter ( &cursor, ASN1_SEQUENCE );
543
544 /* Skip version */
545 asn1_skip ( &cursor, ASN1_INTEGER );
546
547 /* Skip digestAlgorithms */
548 asn1_skip ( &cursor, ASN1_SET );
549
550 /* Skip encapContentInfo */
551 asn1_skip ( &cursor, ASN1_SEQUENCE );
552
553 /* Parse certificates */
554 if ( ( rc = cms_parse_certificates ( cms, &cursor ) ) != 0 )
555 return rc;
556 asn1_skip_any ( &cursor );
557
558 /* Skip crls, if present */
559 asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 1 ) );
560
561 /* Parse signerInfos */
562 if ( ( rc = cms_parse_participants ( cms, &cursor ) ) != 0 )
563 return rc;
564
565 return 0;
566}
567
568/**
569 * Parse CMS enveloped data
570 *
571 * @v cms CMS message
572 * @v raw ASN.1 cursor
573 * @ret rc Return status code
574 */
575static int cms_parse_enveloped ( struct cms_message *cms,
576 const struct asn1_cursor *raw ) {
577 struct asn1_cursor cursor;
578 int rc;
579
580 /* Enter envelopedData or authEnvelopedData */
581 memcpy ( &cursor, raw, sizeof ( cursor ) );
582 asn1_enter ( &cursor, ASN1_SEQUENCE );
583
584 /* Skip version */
585 asn1_skip ( &cursor, ASN1_INTEGER );
586
587 /* Skip originatorInfo, if present */
588 asn1_skip_if_exists ( &cursor, ASN1_IMPLICIT_TAG ( 0 ) );
589
590 /* Parse recipientInfos */
591 if ( ( rc = cms_parse_participants ( cms, &cursor ) ) != 0 )
592 return rc;
593 asn1_skip_any ( &cursor );
594
595 /* Parse encryptedContentInfo or authEncryptedContentInfo */
596 if ( ( rc = cms_parse_encrypted ( cms, &cursor ) ) != 0 )
597 return rc;
598 asn1_skip_any ( &cursor );
599 assert ( cms->cipher != NULL );
600
601 /* Skip unprotectedAttrs or authAttrs, if present */
602 asn1_skip_if_exists ( &cursor, ASN1_IMPLICIT_TAG ( 1 ) );
603
604 /* Parse mac, if present */
605 if ( ( cms->cipher->authsize != 0 ) &&
606 ( ( rc = cms_parse_mac ( cms, &cursor ) ) != 0 ) )
607 return rc;
608
609 return 0;
610}
611
612/**
613 * Parse CMS message from ASN.1 data
614 *
615 * @v cms CMS message
616 * @ret rc Return status code
617 */
618static int cms_parse ( struct cms_message *cms ) {
619 struct asn1_cursor cursor;
620 int rc;
621
622 /* Enter contentInfo */
623 memcpy ( &cursor, cms->raw, sizeof ( cursor ) );
624 asn1_enter ( &cursor, ASN1_SEQUENCE );
625
626 /* Parse contentType */
627 if ( ( rc = cms_parse_content_type ( cms, &cursor ) ) != 0 )
628 return rc;
629 asn1_skip_any ( &cursor );
630
631 /* Enter content */
632 asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );
633
634 /* Parse type-specific content */
635 if ( ( rc = cms->type->parse ( cms, &cursor ) ) != 0 )
636 return rc;
637
638 return 0;
639}
640
641/**
642 * Free CMS message
643 *
644 * @v refcnt Reference count
645 */
646static void cms_free ( struct refcnt *refcnt ) {
647 struct cms_message *cms =
649 struct cms_participant *part;
650 struct cms_participant *tmp;
651
653 list_del ( &part->list );
654 x509_chain_put ( part->chain );
655 free ( part );
656 }
658 free ( cms->raw );
659 free ( cms );
660}
661
662/**
663 * Create CMS message
664 *
665 * @v image Image
666 * @ret sig CMS message
667 * @ret rc Return status code
668 *
669 * On success, the caller holds a reference to the CMS message, and
670 * is responsible for ultimately calling cms_put().
671 */
672int cms_message ( struct image *image, struct cms_message **cms ) {
673 int next;
674 int rc;
675
676 /* Allocate and initialise message */
677 *cms = zalloc ( sizeof ( **cms ) );
678 if ( ! *cms ) {
679 rc = -ENOMEM;
680 goto err_alloc;
681 }
682 ref_init ( &(*cms)->refcnt, cms_free );
683 INIT_LIST_HEAD ( &(*cms)->participants );
684 (*cms)->cipher = &cipher_null;
685
686 /* Get raw message data */
687 next = image_asn1 ( image, 0, &(*cms)->raw );
688 if ( next < 0 ) {
689 rc = next;
690 DBGC ( *cms, "CMS %p could not get raw ASN.1 data: %s\n",
691 *cms, strerror ( rc ) );
692 goto err_asn1;
693 }
694
695 /* Use only first message in image */
696 asn1_shrink_any ( (*cms)->raw );
697
698 /* Parse message */
699 if ( ( rc = cms_parse ( *cms ) ) != 0 )
700 goto err_parse;
701
702 return 0;
703
704 err_parse:
705 err_asn1:
706 cms_put ( *cms );
707 err_alloc:
708 return rc;
709}
710
711/**
712 * Calculate digest of CMS-signed data
713 *
714 * @v cms CMS message
715 * @v part Participant information
716 * @v data Signed data
717 * @v len Length of signed data
718 * @v out Digest output
719 */
720static void cms_digest ( struct cms_message *cms,
721 struct cms_participant *part,
722 const void *data, size_t len, void *out ) {
723 struct digest_algorithm *digest = part->digest;
724 uint8_t ctx[ digest->ctxsize ];
725
726 /* Calculate digest */
727 digest_init ( digest, ctx );
728 digest_update ( digest, ctx, data, len );
729 digest_final ( digest, ctx, out );
730
731 DBGC ( cms, "CMS %p/%p digest value:\n", cms, part );
732 DBGC_HDA ( cms, 0, out, digest->digestsize );
733}
734
735/**
736 * Verify digest of CMS-signed data
737 *
738 * @v cms CMS message
739 * @v part Participant information
740 * @v cert Corresponding certificate
741 * @v data Signed data
742 * @v len Length of signed data
743 * @ret rc Return status code
744 */
745static int cms_verify_digest ( struct cms_message *cms,
746 struct cms_participant *part,
747 struct x509_certificate *cert,
748 const void *data, size_t len ) {
749 struct digest_algorithm *digest = part->digest;
750 struct pubkey_algorithm *pubkey = part->pubkey;
751 const struct asn1_cursor *key = &cert->subject.public_key.raw;
752 const struct asn1_cursor *value = &part->value;
753 uint8_t digest_out[ digest->digestsize ];
754 int rc;
755
756 /* Generate digest */
757 cms_digest ( cms, part, data, len, digest_out );
758
759 /* Verify digest */
760 if ( ( rc = pubkey_verify ( pubkey, key, digest, digest_out,
761 value ) ) != 0 ) {
762 DBGC ( cms, "CMS %p/%p signature verification failed: %s\n",
763 cms, part, strerror ( rc ) );
764 return rc;
765 }
766
767 return 0;
768}
769
770/**
771 * Verify CMS message signer
772 *
773 * @v cms CMS message
774 * @v part Participant information
775 * @v data Signed data
776 * @v len Length of signed data
777 * @v time Time at which to validate certificates
778 * @v store Certificate store, or NULL to use default
779 * @v root Root certificate list, or NULL to use default
780 * @ret rc Return status code
781 */
782static int cms_verify_signer ( struct cms_message *cms,
783 struct cms_participant *part,
784 const void *data, size_t len,
785 time_t time, struct x509_chain *store,
786 struct x509_root *root ) {
787 struct x509_certificate *cert;
788 int rc;
789
790 /* Validate certificate chain */
791 if ( ( rc = x509_validate_chain ( part->chain, time, store,
792 root ) ) != 0 ) {
793 DBGC ( cms, "CMS %p/%p could not validate chain: %s\n",
794 cms, part, strerror ( rc ) );
795 return rc;
796 }
797
798 /* Extract code-signing certificate */
799 cert = x509_first ( part->chain );
800 assert ( cert != NULL );
801
802 /* Check that certificate can create digital signatures */
803 if ( ! ( cert->extensions.usage.bits & X509_DIGITAL_SIGNATURE ) ) {
804 DBGC ( cms, "CMS %p/%p certificate cannot create signatures\n",
805 cms, part );
806 return -EACCES_NON_SIGNING;
807 }
808
809 /* Check that certificate can sign code */
810 if ( ! ( cert->extensions.ext_usage.bits & X509_CODE_SIGNING ) ) {
811 DBGC ( cms, "CMS %p/%p certificate is not code-signing\n",
812 cms, part );
814 }
815
816 /* Verify digest */
817 if ( ( rc = cms_verify_digest ( cms, part, cert, data, len ) ) != 0 )
818 return rc;
819
820 return 0;
821}
822
823/**
824 * Verify CMS signature
825 *
826 * @v cms CMS message
827 * @v image Signed image
828 * @v name Required common name, or NULL to check all signatures
829 * @v time Time at which to validate certificates
830 * @v store Certificate store, or NULL to use default
831 * @v root Root certificate list, or NULL to use default
832 * @ret rc Return status code
833 */
834int cms_verify ( struct cms_message *cms, struct image *image,
835 const char *name, time_t time, struct x509_chain *store,
836 struct x509_root *root ) {
837 struct cms_participant *part;
838 struct x509_certificate *cert;
839 int count = 0;
840 int rc;
841
842 /* Mark image as untrusted */
844
845 /* Sanity check */
846 if ( ! cms_is_signature ( cms ) )
847 return -ENOTTY;
848
849 /* Verify using all signers */
850 list_for_each_entry ( part, &cms->participants, list ) {
851 cert = x509_first ( part->chain );
852 if ( name && ( x509_check_name ( cert, name ) != 0 ) )
853 continue;
854 if ( ( rc = cms_verify_signer ( cms, part, image->data,
855 image->len, time, store,
856 root ) ) != 0 )
857 return rc;
858 count++;
859 }
860
861 /* Check that we have verified at least one signature */
862 if ( count == 0 ) {
863 if ( name ) {
864 DBGC ( cms, "CMS %p had no signatures matching name "
865 "%s\n", cms, name );
866 return -EACCES_WRONG_NAME;
867 } else {
868 DBGC ( cms, "CMS %p had no signatures\n", cms );
869 return -EACCES_NO_SIGNATURES;
870 }
871 }
872
873 /* Mark image as trusted */
874 image_trust ( image );
875
876 return 0;
877}
878
879/**
880 * Identify CMS recipient corresponding to private key
881 *
882 * @v cms CMS message
883 * @v private_key Private key
884 * @ret part Participant information, or NULL if not found
885 */
886static struct cms_participant *
888 struct cms_participant *part;
889 struct x509_certificate *cert;
890
891 /* Identify certificate (if any) for which we have a private key */
892 cert = x509_find_key ( NULL, private_key );
893 if ( ! cert )
894 return NULL;
895
896 /* Identify corresponding recipient, if any */
897 list_for_each_entry ( part, &cms->participants, list ) {
898 if ( cert == x509_first ( part->chain ) )
899 return part;
900 }
901
902 return NULL;
903}
904
905/**
906 * Set CMS cipher key
907 *
908 * @v cms CMS message
909 * @v part Participant information
910 * @v private_key Private key
911 * @v ctx Cipher context
912 * @ret rc Return status code
913 */
914static int cms_cipher_key ( struct cms_message *cms,
915 struct cms_participant *part,
916 struct private_key *private_key, void *ctx ) {
917 struct cipher_algorithm *cipher = cms->cipher;
918 struct pubkey_algorithm *pubkey = part->pubkey;
919 const struct asn1_cursor *key = privkey_cursor ( private_key );
920 const struct asn1_cursor *value = &part->value;
921 struct asn1_builder cipher_key = { NULL, 0 };
922 int rc;
923
924 /* Decrypt cipher key */
925 if ( ( rc = pubkey_decrypt ( pubkey, key, value,
926 &cipher_key ) ) != 0 ) {
927 DBGC ( cms, "CMS %p/%p could not decrypt cipher key: %s\n",
928 cms, part, strerror ( rc ) );
929 DBGC_HDA ( cms, 0, value->data, value->len );
930 goto err_decrypt;
931 }
932 DBGC ( cms, "CMS %p/%p cipher key:\n", cms, part );
933 DBGC_HDA ( cms, 0, cipher_key.data, cipher_key.len );
934
935 /* Set cipher key */
936 if ( ( rc = cipher_setkey ( cipher, ctx, cipher_key.data,
937 cipher_key.len ) ) != 0 ) {
938 DBGC ( cms, "CMS %p could not set cipher key: %s\n",
939 cms, strerror ( rc ) );
940 goto err_setkey;
941 }
942
943 /* Set cipher initialization vector */
944 cipher_setiv ( cipher, ctx, cms->iv.data, cms->iv.len );
945 if ( cms->iv.len ) {
946 DBGC ( cms, "CMS %p cipher IV:\n", cms );
947 DBGC_HDA ( cms, 0, cms->iv.data, cms->iv.len );
948 }
949
950 err_setkey:
951 err_decrypt:
952 free ( cipher_key.data );
953 return rc;
954}
955
956/**
957 * Initialise cipher for CMS decryption
958 *
959 * @v cms CMS message
960 * @v private_key Private key
961 * @v ctx Cipher context
962 * @ret rc Return status code
963 */
964static int cms_cipher ( struct cms_message *cms,
965 struct private_key *private_key, void *ctx ) {
966 struct cms_participant *part;
967 int rc;
968
969 /* Identify a usable recipient */
970 part = cms_recipient ( cms, private_key );
971 if ( ! part ) {
972 DBGC ( cms, "CMS %p had no usable recipients\n", cms );
973 return -EACCES_NO_RECIPIENTS;
974 }
975
976 /* Decrypt and set cipher key */
977 if ( ( rc = cms_cipher_key ( cms, part, private_key, ctx ) ) != 0 )
978 return rc;
979
980 return 0;
981}
982
983/**
984 * Check CMS padding
985 *
986 * @v cms CMS message
987 * @v data Final block
988 * @v len Final block length
989 * @ret len Padding length, or negative error
990 */
991static int cms_verify_padding ( struct cms_message *cms, const void *data,
992 size_t len ) {
993 struct cipher_algorithm *cipher = cms->cipher;
994 const uint8_t *pad;
995 size_t pad_len;
996 unsigned int i;
997
998 /* Non-block ciphers do not use padding */
999 if ( ! is_block_cipher ( cipher ) )
1000 return 0;
1001
1002 /* Block padding can never produce an empty file */
1003 if ( len == 0 ) {
1004 DBGC ( cms, "CMS %p invalid empty padding\n", cms );
1005 return -EACCES_PAD;
1006 }
1007
1008 /* Sanity check */
1009 assert ( len >= cipher->blocksize );
1010
1011 /* Extract and verify padding */
1012 pad = ( data + len - 1 );
1013 pad_len = *pad;
1014 if ( ( pad_len == 0 ) || ( pad_len > len ) ) {
1015 DBGC ( cms, "CMS %p invalid padding length %zd\n",
1016 cms, pad_len );
1017 return -EACCES_PAD;
1018 }
1019 for ( i = 0 ; i < pad_len ; i++ ) {
1020 if ( *(pad--) != pad_len ) {
1021 DBGC ( cms, "CMS %p invalid padding\n", cms );
1022 DBGC_HDA ( cms, 0, ( data + len - pad_len ), pad_len );
1023 return -EACCES_PAD;
1024 }
1025 }
1026
1027 return pad_len;
1028}
1029
1030/**
1031 * Decrypt CMS message
1032 *
1033 * @v cms CMS message
1034 * @v image Image to decrypt
1035 * @v name Decrypted image name, or NULL to use default
1036 * @v private_key Private key
1037 * @ret rc Return status code
1038 */
1039int cms_decrypt ( struct cms_message *cms, struct image *image,
1040 const char *name, struct private_key *private_key ) {
1041 struct cipher_algorithm *cipher = cms->cipher;
1042 const unsigned int original_flags = image->flags;
1043 uint8_t ctx[ cipher->ctxsize ];
1044 uint8_t ctxdup[ cipher->ctxsize ];
1045 uint8_t auth[ cipher->authsize ];
1046 uint8_t final[ cipher->blocksize ];
1047 size_t final_len;
1048 size_t bulk_len;
1049 int pad_len;
1050 int rc;
1051
1052 /* Check block size */
1053 if ( ( image->len & ( cipher->blocksize - 1 ) ) != 0 ) {
1054 DBGC ( cms, "CMS %p invalid length %zd\n", cms, image->len );
1055 rc = -EACCES_LEN;
1056 goto err_blocksize;
1057 }
1058
1059 /* Initialise cipher */
1060 if ( ( rc = cms_cipher ( cms, private_key, ctx ) ) != 0 )
1061 goto err_cipher;
1062
1063 /* Duplicate cipher context for potential reencryption on error */
1064 memcpy ( ctxdup, ctx, cipher->ctxsize );
1065
1066 /* Clear trusted flag before modifying image */
1067 image_untrust ( image );
1068
1069 /* Temporarily unregister image, if applicable */
1070 if ( original_flags & IMAGE_REGISTERED ) {
1071 image_get ( image );
1073 }
1074
1075 /* Decrypt all but the final block */
1076 final_len = ( ( image->len && is_block_cipher ( cipher ) ) ?
1077 cipher->blocksize : 0 );
1078 bulk_len = ( image->len - final_len );
1079 cipher_decrypt ( cipher, ctx, image->data, image->rwdata, bulk_len );
1080
1081 /* Decrypt final block */
1082 cipher_decrypt ( cipher, ctx, ( image->data + bulk_len ), final,
1083 final_len );
1084
1085 /* Check authentication tag, if applicable */
1086 cipher_auth ( cipher, ctx, auth );
1087 if ( ( cms->mac.len != cipher->authsize ) ||
1088 ( memcmp ( cms->mac.data, auth, cipher->authsize ) != 0 ) ) {
1089 DBGC ( cms, "CMS %p invalid authentication tag\n", cms );
1090 DBGC_HDA ( cms, 0, auth, cipher->authsize );
1091 rc = -EACCES_MAC;
1092 goto err_auth;
1093 }
1094
1095 /* Check block padding, if applicable */
1096 if ( ( pad_len = cms_verify_padding ( cms, final, final_len ) ) < 0 ) {
1097 rc = pad_len;
1098 goto err_pad;
1099 }
1100
1101 /* Update image name. Do this as the last possible failure, so
1102 * that we do not have to include any error-handling code path
1103 * to restore the original image name (which may itself fail).
1104 */
1105 if ( name ) {
1106 if ( ( rc = image_set_name ( image, name ) ) != 0 )
1107 goto err_set_name;
1108 } else {
1110 }
1111
1112 /* Overwrite final fragment and strip block padding. Do this
1113 * only once no further failure paths exist, so that we do not
1114 * have to include include any error-handling code path to
1115 * reconstruct the block padding.
1116 */
1117 memcpy ( ( image->rwdata + bulk_len ), final, final_len );
1118 image->len -= pad_len;
1119
1120 /* Clear image type and re-register image, if applicable */
1121 image->type = NULL;
1122 if ( original_flags & IMAGE_REGISTERED ) {
1124 image_put ( image );
1125 }
1126
1127 return 0;
1128
1129 err_set_name:
1130 err_pad:
1131 err_auth:
1132 /* Reencrypt all overwritten portions. This can be done since
1133 * we have deliberately not overwritten the final block
1134 * containing the potentially invalid (and therefore
1135 * unreproducible) block padding.
1136 */
1137 cipher_encrypt ( cipher, ctxdup, image->data, image->rwdata, bulk_len );
1138 if ( original_flags & IMAGE_REGISTERED ) {
1139 register_image ( image ); /* Cannot fail on re-registration */
1140 image_put ( image );
1141 }
1142 image->flags = original_flags;
1143 err_cipher:
1144 err_blocksize:
1145 return rc;
1146}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
union @162305117151260234136356364136041353210355154177 key
Sense key.
Definition scsi.h:3
struct golan_eq_context ctx
Definition CIB_PRM.h:0
__be32 raw[7]
Definition CIB_PRM.h:0
__be32 out[4]
Definition CIB_PRM.h:8
u32 pad[9]
Padding.
Definition ar9003_mac.h:23
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
pseudo_bit_t value[0x00020]
Definition arbel.h:2
unsigned char uint8_t
Definition stdint.h:10
long pad_len
Definition bigint.h:31
int asn1_cipher_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm, struct asn1_cursor *params)
Parse ASN.1 OID-identified cipher algorithm.
Definition asn1.c:597
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition asn1.c:290
int asn1_digest_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified digest algorithm.
Definition asn1.c:570
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition asn1.c:169
int image_asn1(struct image *image, size_t offset, struct asn1_cursor **cursor)
Extract ASN.1 object from image.
Definition asn1.c:1028
int asn1_skip(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object.
Definition asn1.c:231
int asn1_pubkey_algorithm(const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm)
Parse ASN.1 OID-identified public-key algorithm.
Definition asn1.c:544
int asn1_shrink_any(struct asn1_cursor *cursor)
Shrink ASN.1 object of any type.
Definition asn1.c:300
int asn1_compare(const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2)
Compare two ASN.1 objects.
Definition asn1.c:458
int asn1_shrink(struct asn1_cursor *cursor, unsigned int type)
Shrink ASN.1 cursor to fit object.
Definition asn1.c:254
int asn1_skip_if_exists(struct asn1_cursor *cursor, unsigned int type)
Skip ASN.1 object if present.
Definition asn1.c:202
ASN.1 encoding.
#define ASN1_OID_ENVELOPEDDATA
ASN.1 OID for id-envelopedData (1.2.840.113549.1.7.3)
Definition asn1.h:355
#define ASN1_INTEGER
ASN.1 integer.
Definition asn1.h:63
#define ASN1_EXPLICIT_TAG(number)
ASN.1 explicit tag.
Definition asn1.h:99
#define ASN1_OID
ASN.1 object identifier.
Definition asn1.h:75
#define ASN1_OID_AUTHENVELOPEDDATA
ASN.1 OID for id-authEnvelopedData (1.2.840.113549.1.9.16.1.23)
Definition asn1.h:361
#define ASN1_CURSOR(value)
Define an ASN.1 cursor for a static value.
Definition asn1.h:402
#define ASN1_SEQUENCE
ASN.1 sequence.
Definition asn1.h:90
#define ASN1_SET
ASN.1 set.
Definition asn1.h:93
#define ASN1_OID_SIGNEDDATA
ASN.1 OID for id-signedData (1.2.840.113549.1.7.2)
Definition asn1.h:349
#define ASN1_IMPLICIT_TAG(number)
ASN.1 implicit tag.
Definition asn1.h:96
#define ASN1_OCTET_STRING
ASN.1 octet string.
Definition asn1.h:69
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
const char * name
Definition ath9k_hw.c:1986
static int cms_verify_digest(struct cms_message *cms, struct cms_participant *part, struct x509_certificate *cert, const void *data, size_t len)
Verify digest of CMS-signed data.
Definition cms.c:745
static int cms_parse_identifier(struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
Parse CMS message participant identifier.
Definition cms.c:198
#define EACCES_PAD
Definition cms.c:71
static int cms_parse_encrypted(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message encrypted content information.
Definition cms.c:479
#define EACCES_NON_SIGNING
Definition cms.c:47
static int cms_cipher(struct cms_message *cms, struct private_key *private_key, void *ctx)
Initialise cipher for CMS decryption.
Definition cms.c:964
static int cms_verify_padding(struct cms_message *cms, const void *data, size_t len)
Check CMS padding.
Definition cms.c:991
static void cms_digest(struct cms_message *cms, struct cms_participant *part, const void *data, size_t len, void *out)
Calculate digest of CMS-signed data.
Definition cms.c:720
static int cms_parse_content_type(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message content type.
Definition cms.c:124
static int cms_parse_participant(struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
Parse CMS message participant information.
Definition cms.c:383
static int cms_parse_digest_algorithm(struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
Parse CMS message digest algorithm.
Definition cms.c:268
static uint8_t oid_authenvelopeddata[]
"id-authEnvelopedData" object identifier
Definition cms.c:96
int cms_decrypt(struct cms_message *cms, struct image *image, const char *name, struct private_key *private_key)
Decrypt CMS message.
Definition cms.c:1039
static int cms_parse_enveloped(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS enveloped data.
Definition cms.c:575
static int cms_parse_signed(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS signed data.
Definition cms.c:530
static int cms_parse_cipher_algorithm(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message cipher algorithm.
Definition cms.c:327
int cms_message(struct image *image, struct cms_message **cms)
Create CMS message.
Definition cms.c:672
static int cms_parse_pubkey_algorithm(struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
Parse CMS message public-key algorithm.
Definition cms.c:298
static int cms_verify_signer(struct cms_message *cms, struct cms_participant *part, const void *data, size_t len, time_t time, struct x509_chain *store, struct x509_root *root)
Verify CMS message signer.
Definition cms.c:782
#define EACCES_LEN
Definition cms.c:67
#define EACCES_WRONG_NAME
Definition cms.c:55
static int cms_parse_mac(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message MAC.
Definition cms.c:505
static uint8_t oid_envelopeddata[]
"id-envelopedData" object identifier
Definition cms.c:93
static int cms_parse(struct cms_message *cms)
Parse CMS message from ASN.1 data.
Definition cms.c:618
static int cms_parse_participants(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message participants information.
Definition cms.c:433
#define EACCES_NO_RECIPIENTS
Definition cms.c:63
static struct cms_type cms_types[]
CMS message types.
Definition cms.c:99
#define EACCES_MAC
Definition cms.c:75
static uint8_t oid_signeddata[]
"id-signedData" object identifier
Definition cms.c:90
#define EACCES_NON_CODE_SIGNING
Definition cms.c:51
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.
Definition cms.c:834
static int cms_parse_value(struct cms_message *cms, struct cms_participant *part, const struct asn1_cursor *raw)
Parse CMS message signature or key value.
Definition cms.c:356
static int cms_parse_certificates(struct cms_message *cms, const struct asn1_cursor *raw)
Parse CMS message certificate list.
Definition cms.c:158
#define EACCES_NO_SIGNATURES
Definition cms.c:59
static struct cms_participant * cms_recipient(struct cms_message *cms, struct private_key *private_key)
Identify CMS recipient corresponding to private key.
Definition cms.c:887
static int cms_cipher_key(struct cms_message *cms, struct cms_participant *part, struct private_key *private_key, void *ctx)
Set CMS cipher key.
Definition cms.c:914
static void cms_free(struct refcnt *refcnt)
Free CMS message.
Definition cms.c:646
Cryptographic Message Syntax (PKCS #7)
static int cms_is_signature(struct cms_message *cms)
Check if CMS message is a signature message.
Definition cms.h:105
static void cms_put(struct cms_message *cms)
Drop reference to CMS message.
Definition cms.h:94
struct cipher_algorithm cipher_null
Definition crypto_null.c:84
struct pubkey_algorithm pubkey_null
struct digest_algorithm digest_null
Definition crypto_null.c:49
uint32_t next
Next descriptor address.
Definition dwmac.h:11
ring len
Length.
Definition dwmac.h:226
uint64_t serial
Serial number.
Definition edd.h:1
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
Error codes.
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
static unsigned int count
Number of entries.
Definition dwmac.h:220
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ENOENT
No such file or directory.
Definition errno.h:515
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
u16 algorithm
Authentication algorithm (Open System or Shared Key)
Definition ieee80211.h:1
char * image_strip_suffix(struct image *image)
Strip dot suffix from image name, if present.
Definition image.c:206
void unregister_image(struct image *image)
Unregister executable image.
Definition image.c:358
int register_image(struct image *image)
Register executable image.
Definition image.c:315
int image_set_name(struct image *image, const char *name)
Set image name.
Definition image.c:181
Executable images.
static struct image * image_get(struct image *image)
Increment reference count on an image.
Definition image.h:240
#define IMAGE_REGISTERED
Image is registered.
Definition image.h:77
static void image_trust(struct image *image)
Set image as trusted.
Definition image.h:268
static void image_put(struct image *image)
Decrement reference count on an image.
Definition image.h:250
static void image_untrust(struct image *image)
Set image as untrusted.
Definition image.h:277
static int is_block_cipher(struct cipher_algorithm *cipher)
Definition crypto.h:277
static void digest_init(struct digest_algorithm *digest, void *ctx)
Definition crypto.h:219
static int cipher_setkey(struct cipher_algorithm *cipher, void *ctx, const void *key, size_t keylen)
Definition crypto.h:235
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition crypto.h:230
static int pubkey_verify(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, struct digest_algorithm *digest, const void *value, const struct asn1_cursor *signature)
Definition crypto.h:308
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition crypto.h:224
static void cipher_setiv(struct cipher_algorithm *cipher, void *ctx, const void *iv, size_t ivlen)
Definition crypto.h:241
#define cipher_decrypt(cipher, ctx, src, dst, len)
Definition crypto.h:261
static int pubkey_decrypt(struct pubkey_algorithm *pubkey, const struct asn1_cursor *key, const struct asn1_cursor *ciphertext, struct asn1_builder *plaintext)
Definition crypto.h:294
#define cipher_encrypt(cipher, ctx, src, dst, len)
Definition crypto.h:251
static void cipher_auth(struct cipher_algorithm *cipher, void *ctx, void *auth)
Definition crypto.h:267
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
int64_t time_t
Seconds since the Epoch.
Definition time.h:19
Date and time.
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
Dynamic memory allocation.
Private key.
static struct asn1_cursor * privkey_cursor(struct private_key *key)
Get private key ASN.1 cursor.
Definition privkey.h:53
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
#define ENOTSUP_TYPE
Definition stp.c:50
struct stp_switch root
Root switch.
Definition stp.h:15
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
An ASN.1 OID-identified algorithm.
Definition asn1.h:408
An ASN.1 object builder.
Definition asn1.h:29
void * data
Data.
Definition asn1.h:36
size_t len
Length of data.
Definition asn1.h:38
An ASN.1 object cursor.
Definition asn1.h:21
const void * data
Start of data.
Definition asn1.h:23
size_t len
Length of data.
Definition asn1.h:25
A cipher algorithm.
Definition crypto.h:51
void(* auth)(void *ctx, void *auth)
Generate authentication tag.
Definition crypto.h:118
size_t blocksize
Block size.
Definition crypto.h:61
size_t ctxsize
Context size.
Definition crypto.h:55
size_t authsize
Authentication tag size.
Definition crypto.h:75
A CMS message.
Definition cms.h:55
struct asn1_cursor * raw
Raw ASN.1 data.
Definition cms.h:59
struct cms_type * type
Message type.
Definition cms.h:61
struct asn1_cursor mac
Cipher authentication tag.
Definition cms.h:73
struct x509_chain * certificates
List of all certificates (for signature messages)
Definition cms.h:64
struct cipher_algorithm * cipher
Cipher algorithm.
Definition cms.h:69
struct asn1_cursor iv
Cipher initialization vector.
Definition cms.h:71
struct list_head participants
List of participant information blocks.
Definition cms.h:66
CMS participant information.
Definition cms.h:39
struct digest_algorithm * digest
Digest algorithm (for signature messages)
Definition cms.h:46
struct asn1_cursor value
Signature or key value.
Definition cms.h:51
struct list_head list
List of participant information blocks.
Definition cms.h:41
struct x509_chain * chain
Certificate chain.
Definition cms.h:43
struct pubkey_algorithm * pubkey
Public-key algorithm.
Definition cms.h:48
A CMS message type.
Definition cms.h:23
int(* parse)(struct cms_message *cms, const struct asn1_cursor *raw)
Parse content.
Definition cms.h:34
A message digest algorithm.
Definition crypto.h:19
size_t digestsize
Digest size.
Definition crypto.h:27
size_t ctxsize
Context size.
Definition crypto.h:23
An executable image.
Definition image.h:24
unsigned int flags
Flags.
Definition image.h:40
struct image_type * type
Image type, if known.
Definition image.h:59
const void * data
Read-only data.
Definition image.h:51
size_t len
Length of raw file image.
Definition image.h:56
void * rwdata
Writable data.
Definition image.h:53
A private key.
Definition privkey.h:17
A public key algorithm.
Definition crypto.h:122
A reference counter.
Definition refcnt.h:27
An X.509 certificate.
Definition x509.h:216
struct x509_subject subject
Subject.
Definition x509.h:245
struct x509_extensions extensions
Extensions.
Definition x509.h:249
struct x509_link store
Link in certificate store.
Definition x509.h:221
struct x509_issuer issuer
Issuer.
Definition x509.h:241
An X.509 certificate chain.
Definition x509.h:201
unsigned int bits
Usage bits.
Definition x509.h:116
struct x509_key_usage usage
Key usage.
Definition x509.h:161
struct x509_extended_key_usage ext_usage
Extended key usage.
Definition x509.h:163
unsigned int bits
Usage bits.
Definition x509.h:97
struct asn1_cursor raw
Raw public key information.
Definition x509.h:52
An X.509 root certificate list.
Definition x509.h:375
struct x509_public_key public_key
Public key information.
Definition x509.h:66
int x509_auto_append(struct x509_chain *chain, struct x509_chain *store)
Append X.509 certificates to X.509 certificate chain.
Definition x509.c:1868
int x509_check_name(struct x509_certificate *cert, const char *name)
Check X.509 certificate name.
Definition x509.c:1564
int x509_validate_chain(struct x509_chain *chain, time_t time, struct x509_chain *store, struct x509_root *root)
Validate X.509 certificate chain.
Definition x509.c:1908
struct x509_chain * x509_alloc_chain(void)
Allocate X.509 certificate chain.
Definition x509.c:1615
const char * x509_name(struct x509_certificate *cert)
Get X.509 certificate display name.
Definition x509.c:147
struct x509_certificate * x509_find_key(struct x509_chain *store, struct private_key *key)
Identify X.509 certificate by corresponding public key.
Definition x509.c:1835
int x509_append_raw(struct x509_chain *chain, const void *data, size_t len)
Append X.509 certificate to X.509 certificate chain.
Definition x509.c:1674
struct x509_certificate * x509_find_issuer_serial(struct x509_chain *store, const struct asn1_cursor *issuer, const struct asn1_cursor *serial)
Identify X.509 certificate by issuer and serial number.
Definition x509.c:1805
int x509_append(struct x509_chain *chain, struct x509_certificate *cert)
Append X.509 certificate to X.509 certificate chain.
Definition x509.c:1638
X.509 certificates.
static struct x509_certificate * x509_first(struct x509_chain *chain)
Get first certificate in X.509 certificate chain.
Definition x509.h:311
@ X509_CODE_SIGNING
Definition x509.h:125
static struct x509_certificate * x509_last(struct x509_chain *chain)
Get last certificate in X.509 certificate chain.
Definition x509.h:325
static void x509_chain_put(struct x509_chain *chain)
Drop reference to X.509 certificate chain.
Definition x509.h:300
@ X509_DIGITAL_SIGNATURE
Definition x509.h:102