iPXE
validator.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 (at your option) 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#include <string.h>
28#include <stdio.h>
29#include <errno.h>
30#include <ipxe/refcnt.h>
31#include <ipxe/malloc.h>
32#include <ipxe/interface.h>
33#include <ipxe/xfer.h>
34#include <ipxe/open.h>
35#include <ipxe/iobuf.h>
36#include <ipxe/xferbuf.h>
37#include <ipxe/process.h>
38#include <ipxe/x509.h>
39#include <ipxe/settings.h>
40#include <ipxe/dhcp.h>
41#include <ipxe/base64.h>
42#include <ipxe/crc32.h>
43#include <ipxe/ocsp.h>
44#include <ipxe/job.h>
45#include <ipxe/validator.h>
46#include <config/crypto.h>
47
48/** @file
49 *
50 * Certificate validator
51 *
52 */
53
54struct validator;
55
56/** A certificate validator action */
58 /** Name */
59 const char *name;
60 /** Action to take upon completed transfer */
61 void ( * done ) ( struct validator *validator, int rc );
62};
63
64/** A certificate validator */
65struct validator {
66 /** Reference count */
67 struct refcnt refcnt;
68 /** Job control interface */
69 struct interface job;
70 /** Data transfer interface */
72
73 /** Process */
75 /** Most relevant status code
76 *
77 * The cross-signed certificate mechanism may attempt several
78 * downloads as it works its way up the provided partial chain
79 * to locate a suitable cross-signed certificate with which to
80 * complete the chain.
81 *
82 * Some of these download or validation attempts may fail for
83 * uninteresting reasons (i.e. because a cross-signed
84 * certificate has never existed for that link in the chain).
85 *
86 * We must therefore keep track of the most relevant error
87 * that has occurred, in order to be able to report a
88 * meaningful overall status to the user.
89 *
90 * As a concrete example: consider the case of an expired OCSP
91 * signer for an intermediate certificate. This will cause
92 * OCSP validation to fail for that intermediate certificate,
93 * and this is the error that should eventually be reported to
94 * the user. We do not want to instead report the
95 * uninteresting fact that no cross-signed certificate was
96 * found for the remaining links in the chain, nor do we want
97 * to report just a generic "OCSP required" error.
98 *
99 * We record the most relevant status code whenever a
100 * definitely relevant error occurs, and clear it whenever we
101 * successfully make forward progress (e.g. by completing
102 * OCSP, or by adding new cross-signed certificates).
103 *
104 * When we subsequently attempt to validate the chain, we
105 * report the most relevant error status code (if recorded),
106 * otherwise we report the validation error itself.
107 */
108 int rc;
109
110 /** Root of trust (or NULL to use default) */
112 /** X.509 certificate chain */
114 /** OCSP check */
116 /** Data buffer */
118
119 /** Current action */
121 /** Current certificate (for progress reporting)
122 *
123 * This will always be present within the certificate chain
124 * and so this pointer does not hold a reference to the
125 * certificate.
126 */
128 /** Current link within certificate chain */
130};
131
132/**
133 * Get validator name (for debug messages)
134 *
135 * @v validator Certificate validator
136 * @ret name Validator name
137 */
138static const char * validator_name ( struct validator *validator ) {
139 struct x509_certificate *cert;
140
141 /* Use name of first certificate in chain, if present */
142 cert = x509_first ( validator->chain );
143 return ( cert ? x509_name ( cert ) : "<empty>" );
144}
145
146/**
147 * Free certificate validator
148 *
149 * @v refcnt Reference count
150 */
151static void validator_free ( struct refcnt *refcnt ) {
152 struct validator *validator =
153 container_of ( refcnt, struct validator, refcnt );
154
155 DBGC2 ( validator, "VALIDATOR %p \"%s\" freed\n",
161 free ( validator );
162}
163
164/**
165 * Mark certificate validation as finished
166 *
167 * @v validator Certificate validator
168 * @v rc Reason for finishing
169 */
170static void validator_finished ( struct validator *validator, int rc ) {
171
172 /* Remove process */
174
175 /* Close all interfaces */
178}
179
180/****************************************************************************
181 *
182 * Job control interface
183 *
184 */
185
186/**
187 * Report job progress
188 *
189 * @v validator Certificate validator
190 * @v progress Progress report to fill in
191 * @ret ongoing_rc Ongoing job status code (if known)
192 */
194 struct job_progress *progress ) {
195
196 /* Report current action, if applicable */
197 if ( validator->action ) {
198 snprintf ( progress->message, sizeof ( progress->message ),
199 "%s %s", validator->action->name,
200 x509_name ( validator->cert ) );
201 }
202
203 return 0;
204}
205
206/** Certificate validator job control interface operations */
211
212/** Certificate validator job control interface descriptor */
215
216/****************************************************************************
217 *
218 * Cross-signing certificates
219 *
220 */
221
222/** Cross-signed certificate source setting */
223const struct setting crosscert_setting __setting ( SETTING_CRYPTO, crosscert )={
224 .name = "crosscert",
225 .description = "Cross-signed certificate source",
226 .tag = DHCP_EB_CROSS_CERT,
227 .type = &setting_type_string,
228};
229
230/** Default cross-signed certificate source */
231static const char crosscert_default[] = CROSSCERT;
232
233/**
234 * Append cross-signing certificates to certificate chain
235 *
236 * @v validator Certificate validator
237 * @v rc Completion status code
238 * @ret rc Return status code
239 */
240static void validator_append ( struct validator *validator, int rc ) {
241 struct asn1_cursor cursor;
242 struct x509_chain *certs;
243 struct x509_certificate *cert;
244 struct x509_link *link;
245 struct x509_link *prev;
246
247 /* Check for errors */
248 if ( rc != 0 ) {
249 DBGC ( validator, "VALIDATOR %p \"%s\" could not download ",
251 DBGC ( validator, "\"%s\" cross-signature: %s\n",
252 x509_name ( validator->cert ), strerror ( rc ) );
253 /* If the overall validation is going to fail, then we
254 * will end up attempting multiple downloads for
255 * non-existent cross-signed certificates as we work
256 * our way up the certificate chain. Do not record
257 * these as relevant errors, since we want to
258 * eventually report whichever much more relevant
259 * error occurred previously.
260 */
261 goto err_irrelevant;
262 }
263 DBGC ( validator, "VALIDATOR %p \"%s\" downloaded ",
265 DBGC ( validator, "\"%s\" cross-signature\n",
266 x509_name ( validator->cert ) );
267
268 /* Allocate certificate list */
269 certs = x509_alloc_chain();
270 if ( ! certs ) {
271 rc = -ENOMEM;
272 goto err_alloc_certs;
273 }
274
275 /* Initialise cursor */
276 cursor.data = validator->buffer.data;
277 cursor.len = validator->buffer.len;
278
279 /* Enter certificateSet */
280 if ( ( rc = asn1_enter ( &cursor, ASN1_SET ) ) != 0 ) {
281 DBGC ( validator, "VALIDATOR %p \"%s\" could not enter "
282 "certificateSet: %s\n", validator,
284 goto err_certificateset;
285 }
286
287 /* Add each certificate to list */
288 while ( cursor.len ) {
289
290 /* Add certificate to list */
291 if ( ( rc = x509_append_raw ( certs, cursor.data,
292 cursor.len ) ) != 0 ) {
293 DBGC ( validator, "VALIDATOR %p \"%s\" could not "
294 "append certificate: %s\n", validator,
296 DBGC_HDA ( validator, 0, cursor.data, cursor.len );
297 goto err_append_raw;
298 }
299 cert = x509_last ( certs );
300 DBGC ( validator, "VALIDATOR %p \"%s\" found certificate ",
302 DBGC ( validator, "%s\n", x509_name ( cert ) );
303
304 /* Move to next certificate */
305 asn1_skip_any ( &cursor );
306 }
307
308 /* Truncate existing certificate chain at current link */
310 assert ( link->flags & X509_LINK_FL_CROSSED );
312
313 /* Append certificates to chain */
314 if ( ( rc = x509_auto_append ( validator->chain, certs ) ) != 0 ) {
315 DBGC ( validator, "VALIDATOR %p \"%s\" could not append "
316 "certificates: %s\n", validator,
318 goto err_auto_append;
319 }
320
321 /* Record that a cross-signed certificate download has already
322 * been performed for all but the last of the appended
323 * certificates. (It may be necessary to perform a further
324 * download to complete the chain, if this download did not
325 * extend all the way to a root of trust.)
326 */
327 prev = NULL;
329 if ( prev )
331 prev = link;
332 }
333
334 /* Success */
335 rc = 0;
336
337 err_auto_append:
338 err_append_raw:
339 err_certificateset:
340 x509_chain_put ( certs );
341 err_alloc_certs:
342 validator->rc = rc;
343 err_irrelevant:
344 /* Do not record irrelevant errors */
345 return;
346}
347
348/** Cross-signing certificate download validator action */
350 .name = "XCRT",
351 .done = validator_append,
352};
353
354/**
355 * Start download of cross-signing certificate
356 *
357 * @v validator Certificate validator
358 * @v link Link in certificate chain
359 * @ret rc Return status code
360 */
362 struct x509_link *link ) {
363 struct x509_certificate *cert = link->cert;
364 const struct asn1_cursor *issuer = &cert->issuer.raw;
365 const char *crosscert;
366 char *crosscert_copy;
367 char *uri_string;
368 size_t uri_string_len;
369 uint32_t crc;
370 int len;
371 int rc;
372
373 /* Determine cross-signed certificate source */
374 fetch_string_setting_copy ( NULL, &crosscert_setting, &crosscert_copy );
375 crosscert = ( crosscert_copy ? crosscert_copy : crosscert_default );
376 if ( ! crosscert[0] ) {
377 rc = -EINVAL;
378 goto err_check_uri_string;
379 }
380
381 /* Allocate URI string */
382 uri_string_len = ( strlen ( crosscert ) + 22 /* "/%08x.der?subject=" */
383 + base64_encoded_len ( issuer->len ) + 1 /* NUL */ );
384 uri_string = zalloc ( uri_string_len );
385 if ( ! uri_string ) {
386 rc = -ENOMEM;
387 goto err_alloc_uri_string;
388 }
389
390 /* Generate CRC32 */
391 crc = crc32_le ( 0xffffffffUL, issuer->data, issuer->len );
392
393 /* Generate URI string */
394 len = snprintf ( uri_string, uri_string_len, "%s/%08x.der?subject=",
395 crosscert, crc );
396 base64_encode ( issuer->data, issuer->len, ( uri_string + len ),
397 ( uri_string_len - len ) );
398 DBGC ( validator, "VALIDATOR %p \"%s\" downloading ",
400 DBGC ( validator, "\"%s\" cross-signature from %s\n",
401 x509_name ( cert ), uri_string );
402
403 /* Set completion handler */
405 validator->cert = cert;
407
408 /* Open URI */
410 uri_string ) ) != 0 ) {
411 DBGC ( validator, "VALIDATOR %p \"%s\" could not open %s: "
413 uri_string, strerror ( rc ) );
414 goto err_open_uri_string;
415 }
416
417 /* Free temporary allocations */
418 free ( uri_string );
419 free ( crosscert_copy );
420
421 /* Success */
422 return 0;
423
425 err_open_uri_string:
426 free ( uri_string );
427 err_alloc_uri_string:
428 err_check_uri_string:
429 free ( crosscert_copy );
430 validator->rc = rc;
431 return rc;
432}
433
434/****************************************************************************
435 *
436 * OCSP checks
437 *
438 */
439
440/**
441 * Validate OCSP response
442 *
443 * @v validator Certificate validator
444 * @v rc Completion status code
445 */
446static void validator_ocsp_validate ( struct validator *validator, int rc ) {
447 const void *data = validator->buffer.data;
448 size_t len = validator->buffer.len;
449 time_t now;
450
451 /* Check for errors */
452 if ( rc != 0 ) {
453 DBGC ( validator, "VALIDATOR %p \"%s\" could not fetch OCSP "
454 "response: %s\n", validator,
456 goto err_status;
457 }
458
459 /* Record OCSP response */
460 if ( ( rc = ocsp_response ( validator->ocsp, data, len ) ) != 0 ) {
461 DBGC ( validator, "VALIDATOR %p \"%s\" could not record OCSP "
462 "response: %s\n", validator,
464 goto err_response;
465 }
466
467 /* Validate OCSP response */
468 now = time ( NULL );
469 if ( ( rc = ocsp_validate ( validator->ocsp, now ) ) != 0 ) {
470 DBGC ( validator, "VALIDATOR %p \"%s\" could not validate "
471 "OCSP response: %s\n", validator,
473 goto err_validate;
474 }
475
476 /* Success */
477 DBGC ( validator, "VALIDATOR %p \"%s\" checked ",
479 DBGC ( validator, "\"%s\" via OCSP\n", x509_name ( validator->cert ) );
480
481 err_validate:
482 err_response:
483 err_status:
486 validator->rc = rc;
487}
488
489/** OCSP validator action */
490static const struct validator_action validator_ocsp = {
491 .name = "OCSP",
493};
494
495/**
496 * Start OCSP check
497 *
498 * @v validator Certificate validator
499 * @v cert Certificate to check
500 * @v issuer Issuing certificate
501 * @ret rc Return status code
502 */
504 struct x509_certificate *cert,
505 struct x509_certificate *issuer ) {
506 const char *uri_string;
507 int rc;
508
509 /* Create OCSP check */
510 assert ( validator->ocsp == NULL );
511 if ( ( rc = ocsp_check ( cert, issuer, &validator->ocsp ) ) != 0 ) {
512 DBGC ( validator, "VALIDATOR %p \"%s\" could not create OCSP "
513 "check: %s\n", validator, validator_name ( validator ),
514 strerror ( rc ) );
515 goto err_check;
516 }
517
518 /* Set completion handler */
520 validator->cert = cert;
521
522 /* Open URI */
523 uri_string = validator->ocsp->uri_string;
524 DBGC ( validator, "VALIDATOR %p \"%s\" checking ",
526 DBGC ( validator, "\"%s\" via %s\n",
527 x509_name ( cert ), uri_string );
529 uri_string ) ) != 0 ) {
530 DBGC ( validator, "VALIDATOR %p \"%s\" could not open %s: "
532 uri_string, strerror ( rc ) );
533 goto err_open;
534 }
535
536 return 0;
537
539 err_open:
542 err_check:
543 validator->rc = rc;
544 return rc;
545}
546
547/****************************************************************************
548 *
549 * Data transfer interface
550 *
551 */
552
553/**
554 * Close data transfer interface
555 *
556 * @v validator Certificate validator
557 * @v rc Reason for close
558 */
559static void validator_xfer_close ( struct validator *validator, int rc ) {
560
561 /* Close data transfer interface */
563 DBGC2 ( validator, "VALIDATOR %p \"%s\" transfer complete\n",
565
566 /* Process completed download */
567 assert ( validator->action != NULL );
569
570 /* Free downloaded data */
572
573 /* Resume validation process */
575}
576
577/**
578 * Receive data
579 *
580 * @v validator Certificate validator
581 * @v iobuf I/O buffer
582 * @v meta Data transfer metadata
583 * @ret rc Return status code
584 */
586 struct io_buffer *iobuf,
587 struct xfer_metadata *meta ) {
588 int rc;
589
590 /* Add data to buffer */
591 if ( ( rc = xferbuf_deliver ( &validator->buffer, iob_disown ( iobuf ),
592 meta ) ) != 0 ) {
593 DBGC ( validator, "VALIDATOR %p \"%s\" could not receive "
594 "data: %s\n", validator, validator_name ( validator ),
595 strerror ( rc ) );
597 return rc;
598 }
599
600 return 0;
601}
602
603/** Certificate validator data transfer interface operations */
608
609/** Certificate validator data transfer interface descriptor */
612
613/****************************************************************************
614 *
615 * Validation process
616 *
617 */
618
619/**
620 * Certificate validation process
621 *
622 * @v validator Certificate validator
623 */
624static void validator_step ( struct validator *validator ) {
625 struct x509_chain *chain = validator->chain;
626 struct x509_link *link;
627 struct x509_link *prev;
628 struct x509_certificate *cert;
629 time_t now;
630 int rc;
631
632 /* Try validating chain. Try even if the chain is incomplete,
633 * since certificates may already have been validated
634 * previously.
635 */
636 now = time ( NULL );
637 if ( ( rc = x509_validate_chain ( chain, now, NULL,
638 validator->root ) ) == 0 ) {
639 DBGC ( validator, "VALIDATOR %p \"%s\" validated\n",
642 return;
643 }
644 DBGC ( validator, "VALIDATOR %p \"%s\" not yet valid: %s\n",
646
647 /* Record as the most relevant error, if no more relevant
648 * error has already been recorded.
649 */
650 if ( validator->rc == 0 )
651 validator->rc = rc;
652
653 /* Find the first valid link in the chain, if any
654 *
655 * There is no point in attempting OCSP or cross-signed
656 * certificate downloads for certificates after the first
657 * valid link in the chain, since they cannot make a
658 * difference to the overall validation of the chain.
659 */
660 prev = NULL;
661 list_for_each_entry ( link, &chain->links, list ) {
662
663 /* Dump link information (for debugging) */
664 DBGC ( validator, "VALIDATOR %p \"%s\" has link ",
666 DBGC ( validator, "\"%s\"%s%s%s%s%s\n",
667 x509_name ( link->cert ),
668 ( ocsp_required ( link->cert ) ? " [NEEDOCSP]" : "" ),
669 ( ( link->flags & X509_LINK_FL_OCSPED ) ?
670 " [OCSPED]" : "" ),
671 ( ( link->flags & X509_LINK_FL_CROSSED ) ?
672 " [CROSSED]" : "" ),
673 ( x509_is_self_signed ( link->cert ) ? " [SELF]" : "" ),
674 ( x509_is_valid ( link->cert, validator->root ) ?
675 " [VALID]" : "" ) );
676
677 /* Stop at first valid link */
678 if ( x509_is_valid ( link->cert, validator->root ) )
679 break;
680 prev = link;
681 }
682
683 /* If this link is the issuer for a certificate that is
684 * pending an OCSP check attempt, then start OCSP to validate
685 * that certificate.
686 *
687 * If OCSP is not required for the issued certificate, or has
688 * already been attempted, or if we were unable to start OCSP
689 * for any reason, then proceed to attempting a cross-signed
690 * certificate download (which may end up replacing this
691 * issuer anyway).
692 */
693 if ( ( ! list_is_head_entry ( link, &chain->links, list ) ) &&
694 ( ! ( link->flags & X509_LINK_FL_OCSPED ) ) &&
695 ( prev != NULL ) && ocsp_required ( prev->cert ) ) {
696
697 /* Mark OCSP as attempted with this issuer */
698 link->flags |= X509_LINK_FL_OCSPED;
699
700 /* Start OCSP */
701 if ( ( rc = validator_start_ocsp ( validator, prev->cert,
702 link->cert ) ) == 0 ) {
703 /* Sleep until OCSP is complete */
704 return;
705 }
706 }
707
708 /* Work back up the chain (starting from the already
709 * identified first valid link, if any) to find a not-yet
710 * valid certificate for which we could attempt to download a
711 * cross-signed certificate chain.
712 */
714 cert = link->cert;
715
716 /* Sanity check */
717 assert ( ! x509_is_valid ( cert, validator->root ) );
718
719 /* Skip self-signed certificates (cannot be cross-signed) */
720 if ( x509_is_self_signed ( cert ) )
721 continue;
722
723 /* Skip previously attempted cross-signed downloads */
724 if ( link->flags & X509_LINK_FL_CROSSED )
725 continue;
726
727 /* Mark cross-signed certificate download as attempted */
728 link->flags |= X509_LINK_FL_CROSSED;
729
730 /* Start cross-signed certificate download */
732 link ) ) == 0 ) {
733 /* Sleep until download is complete */
734 return;
735 }
736 }
737
738 /* Nothing more to try: fail the validation */
740}
741
742/** Certificate validator process descriptor */
745
746/****************************************************************************
747 *
748 * Instantiator
749 *
750 */
751
752/**
753 * Instantiate a certificate validator
754 *
755 * @v job Job control interface
756 * @v chain X.509 certificate chain
757 * @v root Root of trust, or NULL to use default
758 * @ret rc Return status code
759 */
760int create_validator ( struct interface *job, struct x509_chain *chain,
761 struct x509_root *root ) {
762 struct validator *validator;
763 int rc;
764
765 /* Sanity check */
766 if ( ! chain ) {
767 rc = -EINVAL;
768 goto err_sanity;
769 }
770
771 /* Allocate and initialise structure */
772 validator = zalloc ( sizeof ( *validator ) );
773 if ( ! validator ) {
774 rc = -ENOMEM;
775 goto err_alloc;
776 }
779 &validator->refcnt );
781 &validator->refcnt );
783 &validator->refcnt );
787
788 /* Attach parent interface, mortalise self, and return */
791 DBGC2 ( validator, "VALIDATOR %p \"%s\" validating X509 chain %p\n",
793 return 0;
794
797 err_alloc:
798 err_sanity:
799 return rc;
800}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
u32 link
Link to next descriptor.
Definition ar9003_mac.h:1
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned int uint32_t
Definition stdint.h:12
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition asn1.c:290
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition asn1.c:169
#define ASN1_SET
ASN.1 set.
Definition asn1.h:93
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
size_t base64_encode(const void *raw, size_t raw_len, char *data, size_t len)
Base64-encode data.
Definition base64.c:52
Base64 encoding.
static size_t base64_encoded_len(size_t raw_len)
Calculate length of base64-encoded data.
Definition base64.h:22
Cryptographic configuration.
#define CROSSCERT
Default cross-signed certificate source.
Definition crypto.h:87
u32 crc32_le(u32 seed, const void *data, size_t len)
Calculate 32-bit little-endian CRC checksum.
Definition crc32.c:40
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint8_t meta
Metadata flags.
Definition ena.h:3
Error codes.
#define DBGC2(...)
Definition compiler.h:522
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
#define DHCP_EB_CROSS_CERT
Cross-signed certificate source.
Definition dhcp.h:426
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOMEM
Not enough space.
Definition errno.h:535
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define SETTING_CRYPTO
Cryptography settings.
Definition settings.h:80
Dynamic Host Configuration Protocol.
Configuration settings.
#define __setting(setting_order, name)
Declare a configuration setting.
Definition settings.h:57
String functions.
int64_t time_t
Seconds since the Epoch.
Definition time.h:19
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition interface.c:108
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
Object interfaces.
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
I/O buffers.
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition iobuf.h:217
Job control interfaces.
#define list_for_each_entry_continue_reverse(pos, head, member)
Iterate over entries in a list in reverse, starting after current position.
Definition list.h:487
#define list_is_head_entry(entry, head, member)
Test if entry is the list head.
Definition list.h:410
#define list_for_each_entry_continue(pos, head, member)
Iterate over entries in a list, starting after current position.
Definition list.h:474
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
Dynamic memory allocation.
int ocsp_validate(struct ocsp_check *ocsp, time_t time)
Validate OCSP response.
Definition ocsp.c:880
Online Certificate Status Protocol.
static int ocsp_required(struct x509_certificate *cert)
Check if X.509 certificate requires an OCSP check.
Definition ocsp.h:129
static void ocsp_put(struct ocsp_check *ocsp)
Drop reference to OCSP check.
Definition ocsp.h:119
int xfer_open_uri_string(struct interface *intf, const char *uri_string)
Open URI string.
Definition open.c:116
Data transfer interface opening.
void process_del(struct process *process)
Remove process from process list.
Definition process.c:80
void process_add(struct process *process)
Add process to process list.
Definition process.c:60
Processes.
#define PROC_DESC_ONCE(object_type, process, _step)
Define a process descriptor for a process that runs only once.
Definition process.h:98
static void process_init(struct process *process, struct process_descriptor *desc, struct refcnt *refcnt)
Initialise process and add to process list.
Definition process.h:162
Reference counting.
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
int fetch_string_setting_copy(struct settings *settings, const struct setting *setting, char **data)
Fetch value of string setting.
Definition settings.c:874
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
struct stp_switch root
Root switch.
Definition stp.h:15
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
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
An object interface descriptor.
Definition interface.h:56
An object interface operation.
Definition interface.h:18
An object interface.
Definition interface.h:125
A persistent I/O buffer.
Definition iobuf.h:38
Job progress.
Definition job.h:16
char message[32]
Message (optional)
Definition job.h:33
An OCSP check.
Definition ocsp.h:86
char * uri_string
URI string.
Definition ocsp.h:94
An OCSP response.
Definition ocsp.h:66
A process descriptor.
Definition process.h:32
A process.
Definition process.h:18
A reference counter.
Definition refcnt.h:27
A setting.
Definition settings.h:24
A certificate validator action.
Definition validator.c:57
void(* done)(struct validator *validator, int rc)
Action to take upon completed transfer.
Definition validator.c:61
const char * name
Name.
Definition validator.c:59
A certificate validator.
Definition validator.c:65
struct refcnt refcnt
Reference count.
Definition validator.c:67
struct interface job
Job control interface.
Definition validator.c:69
struct ocsp_check * ocsp
OCSP check.
Definition validator.c:115
struct x509_link * link
Current link within certificate chain.
Definition validator.c:129
int rc
Most relevant status code.
Definition validator.c:108
struct x509_certificate * cert
Current certificate (for progress reporting)
Definition validator.c:127
struct process process
Process.
Definition validator.c:74
const struct validator_action * action
Current action.
Definition validator.c:120
struct interface xfer
Data transfer interface.
Definition validator.c:71
struct x509_chain * chain
X.509 certificate chain.
Definition validator.c:113
struct xfer_buffer buffer
Data buffer.
Definition validator.c:117
struct x509_root * root
Root of trust (or NULL to use default)
Definition validator.c:111
An X.509 certificate.
Definition x509.h:216
struct x509_issuer issuer
Issuer.
Definition x509.h:241
An X.509 certificate chain.
Definition x509.h:201
struct list_head links
List of links.
Definition x509.h:205
struct asn1_cursor raw
Raw issuer.
Definition x509.h:32
An X.509 root certificate list.
Definition x509.h:375
A data transfer buffer.
Definition xferbuf.h:19
size_t len
Size of data.
Definition xferbuf.h:23
void * data
Data.
Definition xferbuf.h:21
Data transfer metadata.
Definition xfer.h:23
static struct interface_operation validator_job_operations[]
Certificate validator job control interface operations.
Definition validator.c:207
static void validator_free(struct refcnt *refcnt)
Free certificate validator.
Definition validator.c:151
static void validator_ocsp_validate(struct validator *validator, int rc)
Validate OCSP response.
Definition validator.c:446
static int validator_start_download(struct validator *validator, struct x509_link *link)
Start download of cross-signing certificate.
Definition validator.c:361
static void validator_xfer_close(struct validator *validator, int rc)
Close data transfer interface.
Definition validator.c:559
static void validator_finished(struct validator *validator, int rc)
Mark certificate validation as finished.
Definition validator.c:170
int create_validator(struct interface *job, struct x509_chain *chain, struct x509_root *root)
Instantiate a certificate validator.
Definition validator.c:760
static const struct validator_action validator_crosscert
Cross-signing certificate download validator action.
Definition validator.c:349
static int validator_progress(struct validator *validator, struct job_progress *progress)
Report job progress.
Definition validator.c:193
static int validator_xfer_deliver(struct validator *validator, struct io_buffer *iobuf, struct xfer_metadata *meta)
Receive data.
Definition validator.c:585
static struct process_descriptor validator_process_desc
Certificate validator process descriptor.
Definition validator.c:743
static const char * validator_name(struct validator *validator)
Get validator name (for debug messages)
Definition validator.c:138
static void validator_step(struct validator *validator)
Certificate validation process.
Definition validator.c:624
static const struct validator_action validator_ocsp
OCSP validator action.
Definition validator.c:490
static struct interface_descriptor validator_xfer_desc
Certificate validator data transfer interface descriptor.
Definition validator.c:610
static struct interface_operation validator_xfer_operations[]
Certificate validator data transfer interface operations.
Definition validator.c:604
static struct interface_descriptor validator_job_desc
Certificate validator job control interface descriptor.
Definition validator.c:213
static const char crosscert_default[]
Default cross-signed certificate source.
Definition validator.c:231
static void validator_append(struct validator *validator, int rc)
Append cross-signing certificates to certificate chain.
Definition validator.c:240
static int validator_start_ocsp(struct validator *validator, struct x509_certificate *cert, struct x509_certificate *issuer)
Start OCSP check.
Definition validator.c:503
Certificate validator.
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383
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_is_valid(struct x509_certificate *cert, struct x509_root *root)
Check if X.509 certificate is valid.
Definition x509.c:1313
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
void x509_truncate(struct x509_chain *chain, struct x509_link *link)
Truncate X.509 certificate chain.
Definition x509.c:1704
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
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
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
static struct x509_chain * x509_chain_get(struct x509_chain *chain)
Get reference to X.509 certificate chain.
Definition x509.h:289
static struct x509_root * x509_root_get(struct x509_root *root)
Get reference to X.509 root certificate list.
Definition x509.h:393
static int x509_is_self_signed(struct x509_certificate *cert)
Check if X.509 certificate is self-signed.
Definition x509.h:414
@ X509_LINK_FL_OCSPED
OCSP has been attempted.
Definition x509.h:197
@ X509_LINK_FL_CROSSED
Cross-signed certificate download has been attempted.
Definition x509.h:188
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_root_put(struct x509_root *root)
Drop reference to X.509 root certificate list.
Definition x509.h:404
static void x509_chain_put(struct x509_chain *chain)
Drop reference to X.509 certificate chain.
Definition x509.h:300
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195
Data transfer interfaces.
void xferbuf_free(struct xfer_buffer *xferbuf)
Free data transfer buffer.
Definition xferbuf.c:74
int xferbuf_deliver(struct xfer_buffer *xferbuf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Add received data to data transfer buffer.
Definition xferbuf.c:175
Data transfer buffer.
static void xferbuf_malloc_init(struct xfer_buffer *xferbuf)
Initialise malloc()-based data transfer buffer.
Definition xferbuf.h:54