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 
139  /* Use name of first certificate in chain */
140  return x509_name ( x509_first ( validator->chain ) );
141 }
142 
143 /**
144  * Free certificate validator
145  *
146  * @v refcnt Reference count
147  */
148 static void validator_free ( struct refcnt *refcnt ) {
149  struct validator *validator =
150  container_of ( refcnt, struct validator, refcnt );
151 
152  DBGC2 ( validator, "VALIDATOR %p \"%s\" freed\n",
156  ocsp_put ( validator->ocsp );
158  free ( validator );
159 }
160 
161 /**
162  * Mark certificate validation as finished
163  *
164  * @v validator Certificate validator
165  * @v rc Reason for finishing
166  */
167 static void validator_finished ( struct validator *validator, int rc ) {
168 
169  /* Remove process */
171 
172  /* Close all interfaces */
174  intf_shutdown ( &validator->job, rc );
175 }
176 
177 /****************************************************************************
178  *
179  * Job control interface
180  *
181  */
182 
183 /**
184  * Report job progress
185  *
186  * @v validator Certificate validator
187  * @v progress Progress report to fill in
188  * @ret ongoing_rc Ongoing job status code (if known)
189  */
191  struct job_progress *progress ) {
192 
193  /* Report current action, if applicable */
194  if ( validator->action ) {
195  snprintf ( progress->message, sizeof ( progress->message ),
196  "%s %s", validator->action->name,
197  x509_name ( validator->cert ) );
198  }
199 
200  return 0;
201 }
202 
203 /** Certificate validator job control interface operations */
207 };
208 
209 /** Certificate validator job control interface descriptor */
212 
213 /****************************************************************************
214  *
215  * Cross-signing certificates
216  *
217  */
218 
219 /** Cross-signed certificate source setting */
220 const struct setting crosscert_setting __setting ( SETTING_CRYPTO, crosscert )={
221  .name = "crosscert",
222  .description = "Cross-signed certificate source",
223  .tag = DHCP_EB_CROSS_CERT,
224  .type = &setting_type_string,
225 };
226 
227 /** Default cross-signed certificate source */
228 static const char crosscert_default[] = CROSSCERT;
229 
230 /**
231  * Append cross-signing certificates to certificate chain
232  *
233  * @v validator Certificate validator
234  * @v rc Completion status code
235  * @ret rc Return status code
236  */
237 static void validator_append ( struct validator *validator, int rc ) {
238  struct asn1_cursor cursor;
239  struct x509_chain *certs;
240  struct x509_certificate *cert;
241  struct x509_link *link;
242  struct x509_link *prev;
243 
244  /* Check for errors */
245  if ( rc != 0 ) {
246  DBGC ( validator, "VALIDATOR %p \"%s\" could not download ",
248  DBGC ( validator, "\"%s\" cross-signature: %s\n",
249  x509_name ( validator->cert ), strerror ( rc ) );
250  /* If the overall validation is going to fail, then we
251  * will end up attempting multiple downloads for
252  * non-existent cross-signed certificates as we work
253  * our way up the certificate chain. Do not record
254  * these as relevant errors, since we want to
255  * eventually report whichever much more relevant
256  * error occurred previously.
257  */
258  goto err_irrelevant;
259  }
260  DBGC ( validator, "VALIDATOR %p \"%s\" downloaded ",
262  DBGC ( validator, "\"%s\" cross-signature\n",
263  x509_name ( validator->cert ) );
264 
265  /* Allocate certificate list */
266  certs = x509_alloc_chain();
267  if ( ! certs ) {
268  rc = -ENOMEM;
269  goto err_alloc_certs;
270  }
271 
272  /* Initialise cursor */
273  cursor.data = validator->buffer.data;
274  cursor.len = validator->buffer.len;
275 
276  /* Enter certificateSet */
277  if ( ( rc = asn1_enter ( &cursor, ASN1_SET ) ) != 0 ) {
278  DBGC ( validator, "VALIDATOR %p \"%s\" could not enter "
279  "certificateSet: %s\n", validator,
280  validator_name ( validator ), strerror ( rc ) );
281  goto err_certificateset;
282  }
283 
284  /* Add each certificate to list */
285  while ( cursor.len ) {
286 
287  /* Add certificate to list */
288  if ( ( rc = x509_append_raw ( certs, cursor.data,
289  cursor.len ) ) != 0 ) {
290  DBGC ( validator, "VALIDATOR %p \"%s\" could not "
291  "append certificate: %s\n", validator,
293  DBGC_HDA ( validator, 0, cursor.data, cursor.len );
294  goto err_append_raw;
295  }
296  cert = x509_last ( certs );
297  DBGC ( validator, "VALIDATOR %p \"%s\" found certificate ",
299  DBGC ( validator, "%s\n", x509_name ( cert ) );
300 
301  /* Move to next certificate */
302  asn1_skip_any ( &cursor );
303  }
304 
305  /* Truncate existing certificate chain at current link */
306  link = validator->link;
307  assert ( link->flags & X509_LINK_FL_CROSSED );
309 
310  /* Append certificates to chain */
311  if ( ( rc = x509_auto_append ( validator->chain, certs ) ) != 0 ) {
312  DBGC ( validator, "VALIDATOR %p \"%s\" could not append "
313  "certificates: %s\n", validator,
314  validator_name ( validator ), strerror ( rc ) );
315  goto err_auto_append;
316  }
317 
318  /* Record that a cross-signed certificate download has already
319  * been performed for all but the last of the appended
320  * certificates. (It may be necessary to perform a further
321  * download to complete the chain, if this download did not
322  * extend all the way to a root of trust.)
323  */
324  prev = NULL;
326  if ( prev )
327  prev->flags |= X509_LINK_FL_CROSSED;
328  prev = link;
329  }
330 
331  /* Success */
332  rc = 0;
333 
334  err_auto_append:
335  err_append_raw:
336  err_certificateset:
337  x509_chain_put ( certs );
338  err_alloc_certs:
339  validator->rc = rc;
340  err_irrelevant:
341  /* Do not record irrelevant errors */
342  return;
343 }
344 
345 /** Cross-signing certificate download validator action */
346 static const struct validator_action validator_crosscert = {
347  .name = "XCRT",
348  .done = validator_append,
349 };
350 
351 /**
352  * Start download of cross-signing certificate
353  *
354  * @v validator Certificate validator
355  * @v link Link in certificate chain
356  * @ret rc Return status code
357  */
359  struct x509_link *link ) {
360  struct x509_certificate *cert = link->cert;
361  const struct asn1_cursor *issuer = &cert->issuer.raw;
362  const char *crosscert;
363  char *crosscert_copy;
364  char *uri_string;
365  size_t uri_string_len;
366  uint32_t crc;
367  int len;
368  int rc;
369 
370  /* Determine cross-signed certificate source */
371  fetch_string_setting_copy ( NULL, &crosscert_setting, &crosscert_copy );
372  crosscert = ( crosscert_copy ? crosscert_copy : crosscert_default );
373  if ( ! crosscert[0] ) {
374  rc = -EINVAL;
375  goto err_check_uri_string;
376  }
377 
378  /* Allocate URI string */
379  uri_string_len = ( strlen ( crosscert ) + 22 /* "/%08x.der?subject=" */
380  + base64_encoded_len ( issuer->len ) + 1 /* NUL */ );
381  uri_string = zalloc ( uri_string_len );
382  if ( ! uri_string ) {
383  rc = -ENOMEM;
384  goto err_alloc_uri_string;
385  }
386 
387  /* Generate CRC32 */
388  crc = crc32_le ( 0xffffffffUL, issuer->data, issuer->len );
389 
390  /* Generate URI string */
391  len = snprintf ( uri_string, uri_string_len, "%s/%08x.der?subject=",
392  crosscert, crc );
393  base64_encode ( issuer->data, issuer->len, ( uri_string + len ),
394  ( uri_string_len - len ) );
395  DBGC ( validator, "VALIDATOR %p \"%s\" downloading ",
397  DBGC ( validator, "\"%s\" cross-signature from %s\n",
398  x509_name ( cert ), uri_string );
399 
400  /* Set completion handler */
402  validator->cert = cert;
403  validator->link = link;
404 
405  /* Open URI */
406  if ( ( rc = xfer_open_uri_string ( &validator->xfer,
407  uri_string ) ) != 0 ) {
408  DBGC ( validator, "VALIDATOR %p \"%s\" could not open %s: "
409  "%s\n", validator, validator_name ( validator ),
410  uri_string, strerror ( rc ) );
411  goto err_open_uri_string;
412  }
413 
414  /* Free temporary allocations */
415  free ( uri_string );
416  free ( crosscert_copy );
417 
418  /* Success */
419  return 0;
420 
421  intf_restart ( &validator->xfer, rc );
422  err_open_uri_string:
423  free ( uri_string );
424  err_alloc_uri_string:
425  err_check_uri_string:
426  free ( crosscert_copy );
427  validator->rc = rc;
428  return rc;
429 }
430 
431 /****************************************************************************
432  *
433  * OCSP checks
434  *
435  */
436 
437 /**
438  * Validate OCSP response
439  *
440  * @v validator Certificate validator
441  * @v rc Completion status code
442  */
443 static void validator_ocsp_validate ( struct validator *validator, int rc ) {
444  const void *data = validator->buffer.data;
445  size_t len = validator->buffer.len;
446  time_t now;
447 
448  /* Check for errors */
449  if ( rc != 0 ) {
450  DBGC ( validator, "VALIDATOR %p \"%s\" could not fetch OCSP "
451  "response: %s\n", validator,
452  validator_name ( validator ), strerror ( rc ) );
453  goto err_status;
454  }
455 
456  /* Record OCSP response */
457  if ( ( rc = ocsp_response ( validator->ocsp, data, len ) ) != 0 ) {
458  DBGC ( validator, "VALIDATOR %p \"%s\" could not record OCSP "
459  "response: %s\n", validator,
460  validator_name ( validator ), strerror ( rc ) );
461  goto err_response;
462  }
463 
464  /* Validate OCSP response */
465  now = time ( NULL );
466  if ( ( rc = ocsp_validate ( validator->ocsp, now ) ) != 0 ) {
467  DBGC ( validator, "VALIDATOR %p \"%s\" could not validate "
468  "OCSP response: %s\n", validator,
469  validator_name ( validator ), strerror ( rc ) );
470  goto err_validate;
471  }
472 
473  /* Success */
474  DBGC ( validator, "VALIDATOR %p \"%s\" checked ",
476  DBGC ( validator, "\"%s\" via OCSP\n", x509_name ( validator->cert ) );
477 
478  err_validate:
479  err_response:
480  err_status:
481  ocsp_put ( validator->ocsp );
482  validator->ocsp = NULL;
483  validator->rc = rc;
484 }
485 
486 /** OCSP validator action */
487 static const struct validator_action validator_ocsp = {
488  .name = "OCSP",
489  .done = validator_ocsp_validate,
490 };
491 
492 /**
493  * Start OCSP check
494  *
495  * @v validator Certificate validator
496  * @v cert Certificate to check
497  * @v issuer Issuing certificate
498  * @ret rc Return status code
499  */
501  struct x509_certificate *cert,
502  struct x509_certificate *issuer ) {
503  const char *uri_string;
504  int rc;
505 
506  /* Create OCSP check */
507  assert ( validator->ocsp == NULL );
508  if ( ( rc = ocsp_check ( cert, issuer, &validator->ocsp ) ) != 0 ) {
509  DBGC ( validator, "VALIDATOR %p \"%s\" could not create OCSP "
510  "check: %s\n", validator, validator_name ( validator ),
511  strerror ( rc ) );
512  goto err_check;
513  }
514 
515  /* Set completion handler */
517  validator->cert = cert;
518 
519  /* Open URI */
520  uri_string = validator->ocsp->uri_string;
521  DBGC ( validator, "VALIDATOR %p \"%s\" checking ",
523  DBGC ( validator, "\"%s\" via %s\n",
524  x509_name ( cert ), uri_string );
525  if ( ( rc = xfer_open_uri_string ( &validator->xfer,
526  uri_string ) ) != 0 ) {
527  DBGC ( validator, "VALIDATOR %p \"%s\" could not open %s: "
528  "%s\n", validator, validator_name ( validator ),
529  uri_string, strerror ( rc ) );
530  goto err_open;
531  }
532 
533  return 0;
534 
535  intf_restart ( &validator->xfer, rc );
536  err_open:
537  ocsp_put ( validator->ocsp );
538  validator->ocsp = NULL;
539  err_check:
540  validator->rc = rc;
541  return rc;
542 }
543 
544 /****************************************************************************
545  *
546  * Data transfer interface
547  *
548  */
549 
550 /**
551  * Close data transfer interface
552  *
553  * @v validator Certificate validator
554  * @v rc Reason for close
555  */
556 static void validator_xfer_close ( struct validator *validator, int rc ) {
557 
558  /* Close data transfer interface */
559  intf_restart ( &validator->xfer, rc );
560  DBGC2 ( validator, "VALIDATOR %p \"%s\" transfer complete\n",
562 
563  /* Process completed download */
564  assert ( validator->action != NULL );
566 
567  /* Free downloaded data */
569 
570  /* Resume validation process */
572 }
573 
574 /**
575  * Receive data
576  *
577  * @v validator Certificate validator
578  * @v iobuf I/O buffer
579  * @v meta Data transfer metadata
580  * @ret rc Return status code
581  */
583  struct io_buffer *iobuf,
584  struct xfer_metadata *meta ) {
585  int rc;
586 
587  /* Add data to buffer */
588  if ( ( rc = xferbuf_deliver ( &validator->buffer, iob_disown ( iobuf ),
589  meta ) ) != 0 ) {
590  DBGC ( validator, "VALIDATOR %p \"%s\" could not receive "
591  "data: %s\n", validator, validator_name ( validator ),
592  strerror ( rc ) );
594  return rc;
595  }
596 
597  return 0;
598 }
599 
600 /** Certificate validator data transfer interface operations */
604 };
605 
606 /** Certificate validator data transfer interface descriptor */
609 
610 /****************************************************************************
611  *
612  * Validation process
613  *
614  */
615 
616 /**
617  * Certificate validation process
618  *
619  * @v validator Certificate validator
620  */
621 static void validator_step ( struct validator *validator ) {
622  struct x509_chain *chain = validator->chain;
623  struct x509_link *link;
624  struct x509_link *prev;
625  struct x509_certificate *cert;
626  time_t now;
627  int rc;
628 
629  /* Try validating chain. Try even if the chain is incomplete,
630  * since certificates may already have been validated
631  * previously.
632  */
633  now = time ( NULL );
634  if ( ( rc = x509_validate_chain ( chain, now, NULL,
635  validator->root ) ) == 0 ) {
636  DBGC ( validator, "VALIDATOR %p \"%s\" validated\n",
639  return;
640  }
641  DBGC ( validator, "VALIDATOR %p \"%s\" not yet valid: %s\n",
643 
644  /* Record as the most relevant error, if no more relevant
645  * error has already been recorded.
646  */
647  if ( validator->rc == 0 )
648  validator->rc = rc;
649 
650  /* Find the first valid link in the chain, if any
651  *
652  * There is no point in attempting OCSP or cross-signed
653  * certificate downloads for certificates after the first
654  * valid link in the chain, since they cannot make a
655  * difference to the overall validation of the chain.
656  */
657  prev = NULL;
658  list_for_each_entry ( link, &chain->links, list ) {
659 
660  /* Dump link information (for debugging) */
661  DBGC ( validator, "VALIDATOR %p \"%s\" has link ",
663  DBGC ( validator, "\"%s\"%s%s%s%s%s\n",
664  x509_name ( link->cert ),
665  ( ocsp_required ( link->cert ) ? " [NEEDOCSP]" : "" ),
666  ( ( link->flags & X509_LINK_FL_OCSPED ) ?
667  " [OCSPED]" : "" ),
668  ( ( link->flags & X509_LINK_FL_CROSSED ) ?
669  " [CROSSED]" : "" ),
670  ( x509_is_self_signed ( link->cert ) ? " [SELF]" : "" ),
671  ( x509_is_valid ( link->cert, validator->root ) ?
672  " [VALID]" : "" ) );
673 
674  /* Stop at first valid link */
675  if ( x509_is_valid ( link->cert, validator->root ) )
676  break;
677  prev = link;
678  }
679 
680  /* If this link is the issuer for a certificate that is
681  * pending an OCSP check attempt, then start OCSP to validate
682  * that certificate.
683  *
684  * If OCSP is not required for the issued certificate, or has
685  * already been attempted, or if we were unable to start OCSP
686  * for any reason, then proceed to attempting a cross-signed
687  * certificate download (which may end up replacing this
688  * issuer anyway).
689  */
690  if ( ( ! list_is_head_entry ( link, &chain->links, list ) ) &&
691  ( ! ( link->flags & X509_LINK_FL_OCSPED ) ) &&
692  ( prev != NULL ) && ocsp_required ( prev->cert ) ) {
693 
694  /* Mark OCSP as attempted with this issuer */
695  link->flags |= X509_LINK_FL_OCSPED;
696 
697  /* Start OCSP */
698  if ( ( rc = validator_start_ocsp ( validator, prev->cert,
699  link->cert ) ) == 0 ) {
700  /* Sleep until OCSP is complete */
701  return;
702  }
703  }
704 
705  /* Work back up the chain (starting from the already
706  * identified first valid link, if any) to find a not-yet
707  * valid certificate for which we could attempt to download a
708  * cross-signed certificate chain.
709  */
710  list_for_each_entry_continue_reverse ( link, &chain->links, list ) {
711  cert = link->cert;
712 
713  /* Sanity check */
714  assert ( ! x509_is_valid ( cert, validator->root ) );
715 
716  /* Skip self-signed certificates (cannot be cross-signed) */
717  if ( x509_is_self_signed ( cert ) )
718  continue;
719 
720  /* Skip previously attempted cross-signed downloads */
721  if ( link->flags & X509_LINK_FL_CROSSED )
722  continue;
723 
724  /* Mark cross-signed certificate download as attempted */
725  link->flags |= X509_LINK_FL_CROSSED;
726 
727  /* Start cross-signed certificate download */
729  link ) ) == 0 ) {
730  /* Sleep until download is complete */
731  return;
732  }
733  }
734 
735  /* Nothing more to try: fail the validation */
737 }
738 
739 /** Certificate validator process descriptor */
742 
743 /****************************************************************************
744  *
745  * Instantiator
746  *
747  */
748 
749 /**
750  * Instantiate a certificate validator
751  *
752  * @v job Job control interface
753  * @v chain X.509 certificate chain
754  * @v root Root of trust, or NULL to use default
755  * @ret rc Return status code
756  */
757 int create_validator ( struct interface *job, struct x509_chain *chain,
758  struct x509_root *root ) {
759  struct validator *validator;
760  int rc;
761 
762  /* Sanity check */
763  if ( ! chain ) {
764  rc = -EINVAL;
765  goto err_sanity;
766  }
767 
768  /* Allocate and initialise structure */
769  validator = zalloc ( sizeof ( *validator ) );
770  if ( ! validator ) {
771  rc = -ENOMEM;
772  goto err_alloc;
773  }
776  &validator->refcnt );
778  &validator->refcnt );
780  &validator->refcnt );
784 
785  /* Attach parent interface, mortalise self, and return */
787  ref_put ( &validator->refcnt );
788  DBGC2 ( validator, "VALIDATOR %p \"%s\" validating X509 chain %p\n",
790  return 0;
791 
793  ref_put ( &validator->refcnt );
794  err_alloc:
795  err_sanity:
796  return rc;
797 }
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:291
A process.
Definition: process.h:17
static void validator_step(struct validator *validator)
Certificate validation process.
Definition: validator.c:621
#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:30
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:280
static void validator_ocsp_validate(struct validator *validator, int rc)
Validate OCSP response.
Definition: validator.c:443
struct process process
Process.
Definition: validator.c:73
static struct interface_operation validator_xfer_operations[]
Certificate validator data transfer interface operations.
Definition: validator.c:601
static struct interface_operation validator_job_operations[]
Certificate validator job control interface operations.
Definition: validator.c:204
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition: asn1.c:160
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:203
#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:232
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:1668
#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:1620
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:395
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:892
void x509_truncate(struct x509_chain *chain, struct x509_link *link)
Truncate X.509 certificate chain.
Definition: x509.c:1698
#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:1318
static int validator_start_download(struct validator *validator, struct x509_link *link)
Start download of cross-signing certificate.
Definition: validator.c:358
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:276
static const char crosscert_default[]
Default cross-signed certificate source.
Definition: validator.c:228
#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:190
#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:405
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:199
#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:500
int create_validator(struct interface *job, struct x509_chain *chain, struct x509_root *root)
Instantiate a certificate validator.
Definition: validator.c:757
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:607
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:740
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:384
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:148
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:1788
static int validator_xfer_deliver(struct validator *validator, struct io_buffer *iobuf, struct xfer_metadata *meta)
Receive data.
Definition: validator.c:582
Configuration settings.
struct xfer_buffer buffer
Data buffer.
Definition: validator.c:116
An object interface descriptor.
Definition: interface.h:55
static struct x509_certificate * x509_last(struct x509_chain *chain)
Get last certificate in X.509 certificate chain.
Definition: x509.h:316
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
An X.509 certificate.
Definition: x509.h:207
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:195
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:210
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:556
char message[32]
Message (optional)
Definition: job.h:32
Base64 encoding.
An X.509 root certificate list.
Definition: x509.h:366
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:487
#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:145
uint32_t len
Length.
Definition: ena.h:14
int x509_auto_append(struct x509_chain *chain, struct x509_chain *certs)
Append X.509 certificates to X.509 certificate chain.
Definition: x509.c:1748
#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:302
static void validator_append(struct validator *validator, int rc)
Append cross-signing certificates to certificate chain.
Definition: validator.c:237
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:167
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
uint64_t time
Current time.
Definition: ntlm.h:20
An OCSP check.
Definition: ocsp.h:85
#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:186
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:346
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