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 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 FILE_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 
54 struct 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 */
65 struct validator {
66  /** Reference count */
67  struct refcnt refcnt;
68  /** Job control interface */
69  struct interface job;
70  /** Data transfer interface */
71  struct interface xfer;
72 
73  /** Process */
74  struct process 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) */
111  struct x509_root *root;
112  /** X.509 certificate chain */
113  struct x509_chain *chain;
114  /** OCSP check */
115  struct ocsp_check *ocsp;
116  /** Data buffer */
118 
119  /** Current action */
120  const struct validator_action *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 */
129  struct x509_link *link;
130 };
131 
132 /**
133  * Get validator name (for debug messages)
134  *
135  * @v validator Certificate validator
136  * @ret name Validator name
137  */
138 static 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  */
151 static 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",
159  ocsp_put ( validator->ocsp );
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  */
170 static void validator_finished ( struct validator *validator, int rc ) {
171 
172  /* Remove process */
174 
175  /* Close all interfaces */
177  intf_shutdown ( &validator->job, rc );
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 */
210 };
211 
212 /** Certificate validator job control interface descriptor */
215 
216 /****************************************************************************
217  *
218  * Cross-signing certificates
219  *
220  */
221 
222 /** Cross-signed certificate source setting */
223 const 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 */
231 static 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  */
240 static 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,
283  validator_name ( validator ), strerror ( rc ) );
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 */
309  link = validator->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,
317  validator_name ( validator ), strerror ( rc ) );
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 )
330  prev->flags |= X509_LINK_FL_CROSSED;
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 */
349 static const struct validator_action validator_crosscert = {
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;
406  validator->link = link;
407 
408  /* Open URI */
409  if ( ( rc = xfer_open_uri_string ( &validator->xfer,
410  uri_string ) ) != 0 ) {
411  DBGC ( validator, "VALIDATOR %p \"%s\" could not open %s: "
412  "%s\n", validator, validator_name ( validator ),
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 
424  intf_restart ( &validator->xfer, rc );
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  */
446 static 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,
455  validator_name ( validator ), strerror ( rc ) );
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,
463  validator_name ( validator ), strerror ( rc ) );
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,
472  validator_name ( validator ), strerror ( rc ) );
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:
484  ocsp_put ( validator->ocsp );
485  validator->ocsp = NULL;
486  validator->rc = rc;
487 }
488 
489 /** OCSP validator action */
490 static const struct validator_action validator_ocsp = {
491  .name = "OCSP",
492  .done = validator_ocsp_validate,
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 );
528  if ( ( rc = xfer_open_uri_string ( &validator->xfer,
529  uri_string ) ) != 0 ) {
530  DBGC ( validator, "VALIDATOR %p \"%s\" could not open %s: "
531  "%s\n", validator, validator_name ( validator ),
532  uri_string, strerror ( rc ) );
533  goto err_open;
534  }
535 
536  return 0;
537 
538  intf_restart ( &validator->xfer, rc );
539  err_open:
540  ocsp_put ( validator->ocsp );
541  validator->ocsp = NULL;
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  */
559 static void validator_xfer_close ( struct validator *validator, int rc ) {
560 
561  /* Close data transfer interface */
562  intf_restart ( &validator->xfer, rc );
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 */
607 };
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  */
624 static 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  */
713  list_for_each_entry_continue_reverse ( link, &chain->links, list ) {
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  */
760 int 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 */
790  ref_put ( &validator->refcnt );
791  DBGC2 ( validator, "VALIDATOR %p \"%s\" validating X509 chain %p\n",
793  return 0;
794 
796  ref_put ( &validator->refcnt );
797  err_alloc:
798  err_sanity:
799  return rc;
800 }
void * data
Data.
Definition: xferbuf.h:21
static void x509_chain_put(struct x509_chain *chain)
Drop reference to X.509 certificate chain.
Definition: x509.h:300
A process.
Definition: process.h:18
static void validator_step(struct validator *validator)
Certificate validation process.
Definition: validator.c:624
#define EINVAL
Invalid argument.
Definition: errno.h:429
An object interface operation.
Definition: interface.h:18
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:250
struct asn1_cursor raw
Raw issuer.
Definition: x509.h:32
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition: interface.c:344
Dynamic Host Configuration Protocol.
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 metadata.
Definition: xfer.h:23
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:279
static struct x509_chain * x509_chain_get(struct x509_chain *chain)
Get reference to X.509 certificate chain.
Definition: x509.h:289
static void validator_ocsp_validate(struct validator *validator, int rc)
Validate OCSP response.
Definition: validator.c:446
struct process process
Process.
Definition: validator.c:74
static struct interface_operation validator_xfer_operations[]
Certificate validator data transfer interface operations.
Definition: validator.c:604
static struct interface_operation validator_job_operations[]
Certificate validator job control interface operations.
Definition: validator.c:207
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:169
struct stp_switch root
Root switch.
Definition: stp.h:27
A certificate validator action.
Definition: validator.c:57
struct refcnt refcnt
Reference count.
Definition: validator.c:67
struct list_head links
List of links.
Definition: x509.h:205
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:65
Error codes.
A data transfer buffer.
Definition: xferbuf.h:19
I/O buffers.
struct x509_issuer issuer
Issuer.
Definition: x509.h:241
int x509_append_raw(struct x509_chain *chain, const void *data, size_t len)
Append X.509 certificate to X.509 certificate chain.
Definition: x509.c:1674
#define list_for_each_entry_continue(pos, head, member)
Iterate over entries in a list, starting after current position.
Definition: list.h:474
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
const void * data
Start of data.
Definition: asn1.h:23
#define DBGC(...)
Definition: compiler.h:505
A process descriptor.
Definition: process.h:32
struct x509_chain * x509_alloc_chain(void)
Allocate X.509 certificate chain.
Definition: x509.c:1615
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:108
static void x509_root_put(struct x509_root *root)
Drop reference to X.509 root certificate list.
Definition: x509.h:404
struct x509_chain * chain
X.509 certificate chain.
Definition: validator.c:113
void(* done)(struct validator *validator, int rc)
Action to take upon completed transfer.
Definition: validator.c:61
int ocsp_validate(struct ocsp_check *ocsp, time_t time)
Validate OCSP response.
Definition: ocsp.c:880
void x509_truncate(struct x509_chain *chain, struct x509_link *link)
Truncate X.509 certificate chain.
Definition: x509.c:1704
#define PROC_DESC_ONCE(object_type, process, _step)
Define a process descriptor for a process that runs only once.
Definition: process.h:98
int x509_is_valid(struct x509_certificate *cert, struct x509_root *root)
Check if X.509 certificate is valid.
Definition: x509.c:1313
static int validator_start_download(struct validator *validator, struct x509_link *link)
Start download of cross-signing certificate.
Definition: validator.c:361
static int ocsp_required(struct x509_certificate *cert)
Check if X.509 certificate requires an OCSP check.
Definition: ocsp.h:129
void xferbuf_free(struct xfer_buffer *xferbuf)
Free data transfer buffer.
Definition: xferbuf.c:74
void process_del(struct process *process)
Remove process from process list.
Definition: process.c:80
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition: asn1.c:290
static const char crosscert_default[]
Default cross-signed certificate source.
Definition: validator.c:231
#define ASN1_SET
ASN.1 set.
Definition: asn1.h:93
Dynamic memory allocation.
Data transfer interfaces.
size_t len
Length of data.
Definition: asn1.h:25
A reference counter.
Definition: refcnt.h:27
A certificate validator.
Definition: validator.c:65
const char * name
Name.
Definition: settings.h:29
size_t len
Size of data.
Definition: xferbuf.h:23
u32 crc32_le(u32 seed, const void *data, size_t len)
Calculate 32-bit little-endian CRC checksum.
Definition: crc32.c:40
static int validator_progress(struct validator *validator, struct job_progress *progress)
Report job progress.
Definition: validator.c:193
#define DHCP_EB_CROSS_CERT
Cross-signed certificate source.
Definition: dhcp.h:426
struct interface xfer
Data transfer interface.
Definition: validator.c:71
static int x509_is_self_signed(struct x509_certificate *cert)
Check if X.509 certificate is self-signed.
Definition: x509.h:414
static size_t base64_encoded_len(size_t raw_len)
Calculate length of base64-encoded data.
Definition: base64.h:22
An X.509 certificate chain.
Definition: x509.h:201
#define ENOMEM
Not enough space.
Definition: errno.h:535
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:217
static int validator_start_ocsp(struct validator *validator, struct x509_certificate *cert, struct x509_certificate *issuer)
Start OCSP check.
Definition: validator.c:503
int create_validator(struct interface *job, struct x509_chain *chain, struct x509_root *root)
Instantiate a certificate validator.
Definition: validator.c:760
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:36
Certificate validator.
An object interface.
Definition: interface.h:125
struct ocsp_check * ocsp
OCSP check.
Definition: validator.c:115
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:432
static struct interface_descriptor validator_xfer_desc
Certificate validator data transfer interface descriptor.
Definition: validator.c:610
const struct validator_action * action
Current action.
Definition: validator.c:120
#define DBGC_HDA(...)
Definition: compiler.h:506
Object interfaces.
static struct process_descriptor validator_process_desc
Certificate validator process descriptor.
Definition: validator.c:743
ring len
Length.
Definition: dwmac.h:231
static void xferbuf_malloc_init(struct xfer_buffer *xferbuf)
Initialise malloc()-based data transfer buffer.
Definition: xferbuf.h:54
u32 link
Link to next descriptor.
Definition: ar9003_mac.h:25
static struct x509_root * x509_root_get(struct x509_root *root)
Get reference to X.509 root certificate list.
Definition: x509.h:393
int fetch_string_setting_copy(struct settings *settings, const struct setting *setting, char **data)
Fetch value of string setting.
Definition: settings.c:874
static void validator_free(struct refcnt *refcnt)
Free certificate validator.
Definition: validator.c:151
void process_add(struct process *process)
Add process to process list.
Definition: process.c:60
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
static int validator_xfer_deliver(struct validator *validator, struct io_buffer *iobuf, struct xfer_metadata *meta)
Receive data.
Definition: validator.c:585
Configuration settings.
struct xfer_buffer buffer
Data buffer.
Definition: validator.c:117
An object interface descriptor.
Definition: interface.h:56
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
static struct x509_certificate * x509_last(struct x509_chain *chain)
Get last certificate in X.509 certificate chain.
Definition: x509.h:325
FILE_SECBOOT(PERMITTED)
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
An X.509 certificate.
Definition: x509.h:216
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:662
OCSP has been attempted.
Definition: x509.h:197
Job progress.
Definition: job.h:16
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:33
static struct interface_descriptor validator_job_desc
Certificate validator job control interface descriptor.
Definition: validator.c:213
static void ocsp_put(struct ocsp_check *ocsp)
Drop reference to OCSP check.
Definition: ocsp.h:119
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:195
int rc
Most relevant status code.
Definition: validator.c:108
size_t strlen(const char *src)
Get length of string.
Definition: string.c:244
Processes.
Data transfer interface opening.
Online Certificate Status Protocol.
X.509 certificates.
unsigned int uint32_t
Definition: stdint.h:12
An OCSP response.
Definition: ocsp.h:66
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
Cryptographic configuration.
A setting.
Definition: settings.h:24
Job control interfaces.
#define CROSSCERT
Default cross-signed certificate source.
Definition: crypto.h:87
static void validator_xfer_close(struct validator *validator, int rc)
Close data transfer interface.
Definition: validator.c:559
char message[32]
Message (optional)
Definition: job.h:33
Base64 encoding.
An X.509 root certificate list.
Definition: x509.h:375
const char * name
Name.
Definition: validator.c:59
struct x509_certificate * cert
Current certificate (for progress reporting)
Definition: validator.c:127
#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
static const struct validator_action validator_ocsp
OCSP validator action.
Definition: validator.c:490
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:81
const char * x509_name(struct x509_certificate *cert)
Get X.509 certificate display name.
Definition: x509.c:147
#define DBGC2(...)
Definition: compiler.h:522
struct x509_root * root
Root of trust (or NULL to use default)
Definition: validator.c:111
const struct setting crosscert_setting __setting(SETTING_CRYPTO, crosscert)
Cross-signed certificate source setting.
static struct x509_certificate * x509_first(struct x509_chain *chain)
Get first certificate in X.509 certificate chain.
Definition: x509.h:311
static void validator_append(struct validator *validator, int rc)
Append cross-signing certificates to certificate chain.
Definition: validator.c:240
Reference counting.
uint8_t data[48]
Additional event data.
Definition: ena.h:22
struct interface job
Job control interface.
Definition: validator.c:69
static void validator_finished(struct validator *validator, int rc)
Mark certificate validation as finished.
Definition: validator.c:170
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:383
#define SETTING_CRYPTO
Cryptography settings.
Definition: settings.h:80
uint8_t meta
Metadata flags.
Definition: ena.h:14
struct x509_link * link
Current link within certificate chain.
Definition: validator.c:129
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:204
int xfer_open_uri_string(struct interface *intf, const char *uri_string)
Open URI string.
Definition: open.c:116
int64_t time_t
Seconds since the Epoch.
Definition: time.h:19
An OCSP check.
Definition: ocsp.h:86
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
String functions.
An ASN.1 object cursor.
Definition: asn1.h:21
#define list_is_head_entry(entry, head, member)
Test if entry is the list head.
Definition: list.h:410
size_t base64_encode(const void *raw, size_t raw_len, char *data, size_t len)
Base64-encode data.
Definition: base64.c:52
Cross-signed certificate download has been attempted.
Definition: x509.h:188
Data transfer buffer.
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:107
char * uri_string
URI string.
Definition: ocsp.h:94
static const struct validator_action validator_crosscert
Cross-signing certificate download validator action.
Definition: validator.c:349
A persistent I/O buffer.
Definition: iobuf.h:38
static const char * validator_name(struct validator *validator)
Get validator name (for debug messages)
Definition: validator.c:138