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