iPXE
validator.c File Reference

Certificate validator. More...

#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <ipxe/refcnt.h>
#include <ipxe/malloc.h>
#include <ipxe/interface.h>
#include <ipxe/xfer.h>
#include <ipxe/open.h>
#include <ipxe/iobuf.h>
#include <ipxe/xferbuf.h>
#include <ipxe/process.h>
#include <ipxe/x509.h>
#include <ipxe/settings.h>
#include <ipxe/dhcp.h>
#include <ipxe/base64.h>
#include <ipxe/crc32.h>
#include <ipxe/ocsp.h>
#include <ipxe/job.h>
#include <ipxe/validator.h>
#include <config/crypto.h>

Go to the source code of this file.

Data Structures

struct  validator_action
 A certificate validator action. More...
struct  validator
 A certificate validator. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static const char * validator_name (struct validator *validator)
 Get validator name (for debug messages).
static void validator_free (struct refcnt *refcnt)
 Free certificate validator.
static void validator_finished (struct validator *validator, int rc)
 Mark certificate validation as finished.
static int validator_progress (struct validator *validator, struct job_progress *progress)
 Report job progress.
const struct setting crosscert_setting __setting (SETTING_CRYPTO, crosscert)
 Cross-signed certificate source setting.
static void validator_append (struct validator *validator, struct x509_certificate *cert, int rc)
 Append cross-signing certificates to certificate chain.
static int validator_start_download (struct validator *validator, struct x509_link *link)
 Start download of cross-signing certificate.
static void validator_ocsp_validate (struct validator *validator, struct x509_certificate *cert, int rc)
 Validate OCSP response.
static int validator_start_ocsp (struct validator *validator, struct x509_certificate *cert, struct x509_certificate *issuer)
 Start OCSP check.
static void validator_xfer_close (struct validator *validator, int rc)
 Close data transfer interface.
static int validator_xfer_deliver (struct validator *validator, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Receive data.
static void validator_step (struct validator *validator)
 Certificate validation process.
int create_validator (struct interface *job, struct x509_chain *chain, struct x509_root *root)
 Instantiate a certificate validator.

Variables

static struct interface_operation validator_job_operations []
 Certificate validator job control interface operations.
static struct interface_descriptor validator_job_desc
 Certificate validator job control interface descriptor.
static const char crosscert_default [] = CROSSCERT
 Default cross-signed certificate source.
static const struct validator_action validator_crosscert
 Cross-signing certificate download validator action.
static const struct validator_action validator_ocsp
 OCSP validator action.
static struct interface_operation validator_xfer_operations []
 Certificate validator data transfer interface operations.
static struct interface_descriptor validator_xfer_desc
 Certificate validator data transfer interface descriptor.
static struct process_descriptor validator_process_desc
 Certificate validator process descriptor.

Detailed Description

Certificate validator.

Definition in file validator.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ validator_name()

const char * validator_name ( struct validator * validator)
static

Get validator name (for debug messages).

Parameters
validatorCertificate validator
Return values
nameValidator name

Definition at line 138 of file validator.c.

138 {
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}
A certificate validator.
Definition validator.c:72
struct x509_chain * chain
X.509 certificate chain.
Definition validator.c:120
An X.509 certificate.
Definition x509.h:216
const char * x509_name(struct x509_certificate *cert)
Get X.509 certificate display name.
Definition x509.c:147
static struct x509_certificate * x509_first(struct x509_chain *chain)
Get first certificate in X.509 certificate chain.
Definition x509.h:311

References validator::chain, x509_first(), and x509_name().

Referenced by create_validator(), validator_append(), validator_free(), validator_ocsp_validate(), validator_start_download(), validator_start_ocsp(), validator_step(), validator_xfer_close(), and validator_xfer_deliver().

◆ validator_free()

void validator_free ( struct refcnt * refcnt)
static

Free certificate validator.

Parameters
refcntReference count

Definition at line 151 of file validator.c.

151 {
152 struct validator *validator =
153 container_of ( refcnt, struct validator, refcnt );
154
155 DBGC2 ( validator, "VALIDATOR %p \"%s\" freed\n",
162 free ( validator );
163}
#define DBGC2(...)
Definition compiler.h:547
static void ocsp_put(struct ocsp_check *ocsp)
Drop reference to OCSP check.
Definition ocsp.h:119
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
A reference counter.
Definition refcnt.h:27
struct ocsp_check * ocsp
OCSP check.
Definition validator.c:122
struct x509_certificate * cert
Current certificate.
Definition validator.c:129
struct xfer_buffer buffer
Data buffer.
Definition validator.c:124
struct x509_root * root
Root of trust (or NULL to use default).
Definition validator.c:118
static const char * validator_name(struct validator *validator)
Get validator name (for debug messages).
Definition validator.c:138
static void x509_put(struct x509_certificate *cert)
Drop reference to X.509 certificate.
Definition x509.h:278
static void x509_root_put(struct x509_root *root)
Drop reference to X.509 root certificate list.
Definition x509.h:404
static void x509_chain_put(struct x509_chain *chain)
Drop reference to X.509 certificate chain.
Definition x509.h:300
void xferbuf_free(struct xfer_buffer *xferbuf)
Free data transfer buffer.
Definition xferbuf.c:88

References validator::buffer, validator::cert, validator::chain, container_of, DBGC2, free, validator::ocsp, ocsp_put(), validator::root, validator_name(), x509_chain_put(), x509_put(), x509_root_put(), and xferbuf_free().

Referenced by create_validator().

◆ validator_finished()

void validator_finished ( struct validator * validator,
int rc )
static

Mark certificate validation as finished.

Parameters
validatorCertificate validator
rcReason for finishing

Definition at line 171 of file validator.c.

171 {
172
173 /* Remove process */
175
176 /* Close all interfaces */
179}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
void process_del(struct process *process)
Remove process from process list.
Definition process.c:80
struct interface job
Job control interface.
Definition validator.c:76
struct process process
Process.
Definition validator.c:81
struct interface xfer
Data transfer interface.
Definition validator.c:78

References intf_shutdown(), validator::job, validator::process, process_del(), rc, and validator::xfer.

Referenced by create_validator(), and validator_step().

◆ validator_progress()

int validator_progress ( struct validator * validator,
struct job_progress * progress )
static

Report job progress.

Parameters
validatorCertificate validator
progressProgress report to fill in
Return values
ongoing_rcOngoing job status code (if known)

Definition at line 194 of file validator.c.

195 {
196
197 /* Report current action, if applicable */
198 if ( validator->action ) {
199 assert ( validator->cert != NULL );
200 snprintf ( progress->message, sizeof ( progress->message ),
201 "%s %s", validator->action->name,
202 x509_name ( validator->cert ) );
203 }
204
205 return 0;
206}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
char message[32]
Message (optional).
Definition job.h:33
const char * name
Name.
Definition validator.c:59
const struct validator_action * action
Current action.
Definition validator.c:127
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383

References validator::action, assert, validator::cert, job_progress::message, validator_action::name, NULL, snprintf(), and x509_name().

◆ __setting()

const struct setting crosscert_setting __setting ( SETTING_CRYPTO ,
crosscert  )

Cross-signed certificate source setting.

References __setting, DHCP_EB_CROSS_CERT, and SETTING_CRYPTO.

◆ validator_append()

void validator_append ( struct validator * validator,
struct x509_certificate * cert,
int rc )
static

Append cross-signing certificates to certificate chain.

Parameters
validatorCertificate validator
certCross-signed certificate
rcCompletion status code
Return values
rcReturn status code

Definition at line 243 of file validator.c.

244 {
245 struct asn1_cursor cursor;
246 struct x509_chain *certs;
247 struct x509_certificate *last;
248 struct x509_link *link;
249 struct x509_link *prev;
250
251 /* Check for errors */
252 if ( rc != 0 ) {
253 DBGC ( validator, "VALIDATOR %p \"%s\" could not download ",
255 DBGC ( validator, "\"%s\" cross-signature: %s\n",
256 x509_name ( cert ), strerror ( rc ) );
257 /* If the overall validation is going to fail, then we
258 * will end up attempting multiple downloads for
259 * non-existent cross-signed certificates as we work
260 * our way up the certificate chain. Do not record
261 * these as relevant errors, since we want to
262 * eventually report whichever much more relevant
263 * error occurred previously.
264 */
265 goto err_irrelevant;
266 }
267 DBGC ( validator, "VALIDATOR %p \"%s\" downloaded ",
269 DBGC ( validator, "\"%s\" cross-signature\n", x509_name ( cert ) );
270
271 /* Allocate certificate list */
272 certs = x509_alloc_chain();
273 if ( ! certs ) {
274 rc = -ENOMEM;
275 goto err_alloc_certs;
276 }
277
278 /* Initialise cursor */
279 cursor.data = validator->buffer.data;
280 cursor.len = validator->buffer.len;
281
282 /* Enter certificateSet */
283 if ( ( rc = asn1_enter ( &cursor, ASN1_SET ) ) != 0 ) {
284 DBGC ( validator, "VALIDATOR %p \"%s\" could not enter "
285 "certificateSet: %s\n", validator,
287 goto err_certificateset;
288 }
289
290 /* Add each certificate to list */
291 while ( cursor.len ) {
292
293 /* Add certificate to list */
294 if ( ( rc = x509_append_raw ( certs, cursor.data,
295 cursor.len ) ) != 0 ) {
296 DBGC ( validator, "VALIDATOR %p \"%s\" could not "
297 "append certificate: %s\n", validator,
299 DBGC_HDA ( validator, 0, cursor.data, cursor.len );
300 goto err_append_raw;
301 }
302 last = x509_last ( certs );
303 DBGC ( validator, "VALIDATOR %p \"%s\" found certificate ",
305 DBGC ( validator, "%s\n", x509_name ( last ) );
306
307 /* Move to next certificate */
308 asn1_skip_any ( &cursor );
309 }
310
311 /* Locate cross-signed certificate within chain */
313 if ( ! link ) {
314 DBGC ( validator, "VALIDATOR %p \"%s\" lost \"%s\"\n",
316 x509_name ( cert ) );
317 rc = -ENOENT;
318 goto err_link;
319 }
320
321 /* Truncate existing certificate chain at current link */
322 assert ( link->flags & X509_LINK_FL_CROSSED );
324
325 /* Append certificates to chain */
326 if ( ( rc = x509_auto_append ( validator->chain, certs ) ) != 0 ) {
327 DBGC ( validator, "VALIDATOR %p \"%s\" could not append "
328 "certificates: %s\n", validator,
330 goto err_auto_append;
331 }
332
333 /* Record that a cross-signed certificate download has already
334 * been performed for all but the last of the appended
335 * certificates. (It may be necessary to perform a further
336 * download to complete the chain, if this download did not
337 * extend all the way to a root of trust.)
338 */
339 prev = NULL;
341 if ( prev )
343 prev = link;
344 }
345
346 /* Success */
347 rc = 0;
348
349 err_auto_append:
350 err_link:
351 err_append_raw:
352 err_certificateset:
353 x509_chain_put ( certs );
354 err_alloc_certs:
355 validator->rc = rc;
356 err_irrelevant:
357 /* Do not record irrelevant errors */
358 return;
359}
u32 link
Link to next descriptor.
Definition ar9003_mac.h:1
int asn1_skip_any(struct asn1_cursor *cursor)
Skip ASN.1 object of any type.
Definition asn1.c:382
int asn1_enter(struct asn1_cursor *cursor, unsigned int type)
Enter ASN.1 object.
Definition asn1.c:261
#define ASN1_SET
ASN.1 set.
Definition asn1.h:96
#define DBGC(...)
Definition compiler.h:530
#define DBGC_HDA(...)
Definition compiler.h:531
#define ENOENT
No such file or directory.
Definition errno.h:558
#define ENOMEM
Not enough space.
Definition errno.h:578
#define list_for_each_entry_continue(pos, head, member)
Iterate over entries in a list, starting after current position.
Definition list.h:474
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
An ASN.1 object cursor.
Definition asn1.h:21
int rc
Most relevant status code.
Definition validator.c:115
An X.509 certificate chain.
Definition x509.h:201
struct list_head links
List of links.
Definition x509.h:205
size_t len
Size of data.
Definition xferbuf.h:25
void * data
Data.
Definition xferbuf.h:23
int x509_auto_append(struct x509_chain *chain, struct x509_chain *store)
Append X.509 certificates to X.509 certificate chain.
Definition x509.c:1888
void x509_truncate(struct x509_chain *chain, struct x509_link *link)
Truncate X.509 certificate chain.
Definition x509.c:1724
struct x509_link * x509_link(struct x509_chain *chain, struct x509_certificate *cert)
Find link containing X.509 certificate.
Definition x509.c:1705
struct x509_chain * x509_alloc_chain(void)
Allocate X.509 certificate chain.
Definition x509.c:1615
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
@ X509_LINK_FL_CROSSED
Cross-signed certificate download has been attempted.
Definition x509.h:188
static struct x509_certificate * x509_last(struct x509_chain *chain)
Get last certificate in X.509 certificate chain.
Definition x509.h:325

References asn1_enter(), ASN1_SET, asn1_skip_any(), assert, validator::buffer, x509_link::cert, validator::chain, asn1_cursor::data, xfer_buffer::data, DBGC, DBGC_HDA, ENOENT, ENOMEM, x509_link::flags, asn1_cursor::len, xfer_buffer::len, link, x509_chain::links, x509_link::list, list_for_each_entry_continue, NULL, rc, validator::rc, strerror(), validator_name(), x509_alloc_chain(), x509_append_raw(), x509_auto_append(), x509_chain_put(), x509_last(), x509_link(), X509_LINK_FL_CROSSED, x509_name(), and x509_truncate().

◆ validator_start_download()

int validator_start_download ( struct validator * validator,
struct x509_link * link )
static

Start download of cross-signing certificate.

Parameters
validatorCertificate validator
linkLink in certificate chain
Return values
rcReturn status code

Definition at line 374 of file validator.c.

375 {
376 struct x509_certificate *cert = link->cert;
377 const struct asn1_cursor *issuer = &cert->issuer.raw;
378 const char *crosscert;
379 char *crosscert_copy;
380 char *uri_string;
381 size_t uri_string_len;
382 uint32_t crc;
383 int len;
384 int rc;
385
386 /* Determine cross-signed certificate source */
387 fetch_string_setting_copy ( NULL, &crosscert_setting, &crosscert_copy );
388 crosscert = ( crosscert_copy ? crosscert_copy : crosscert_default );
389 if ( ! crosscert[0] ) {
390 rc = -EINVAL;
391 goto err_check_uri_string;
392 }
393
394 /* Allocate URI string */
395 uri_string_len = ( strlen ( crosscert ) + 22 /* "/%08x.der?subject=" */
396 + base64_encoded_len ( issuer->len ) + 1 /* NUL */ );
397 uri_string = zalloc ( uri_string_len );
398 if ( ! uri_string ) {
399 rc = -ENOMEM;
400 goto err_alloc_uri_string;
401 }
402
403 /* Generate CRC32 */
404 crc = crc32_le ( 0xffffffffUL, issuer->data, issuer->len );
405
406 /* Generate URI string */
407 len = snprintf ( uri_string, uri_string_len, "%s/%08x.der?subject=",
408 crosscert, crc );
409 base64_encode ( issuer->data, issuer->len, ( uri_string + len ),
410 ( uri_string_len - len ) );
411 DBGC ( validator, "VALIDATOR %p \"%s\" downloading ",
413 DBGC ( validator, "\"%s\" cross-signature from %s\n",
414 x509_name ( cert ), uri_string );
415
416 /* Set completion handler */
418 validator->cert = x509_get ( cert );
419
420 /* Open URI */
422 uri_string ) ) != 0 ) {
423 DBGC ( validator, "VALIDATOR %p \"%s\" could not open %s: "
425 uri_string, strerror ( rc ) );
426 goto err_open_uri_string;
427 }
428
429 /* Free temporary allocations */
430 free ( uri_string );
431 free ( crosscert_copy );
432
433 /* Success */
434 return 0;
435
437 err_open_uri_string:
441 free ( uri_string );
442 err_alloc_uri_string:
443 err_check_uri_string:
444 free ( crosscert_copy );
445 validator->rc = rc;
446 return rc;
447}
unsigned int uint32_t
Definition stdint.h:12
size_t base64_encode(const void *raw, size_t raw_len, char *data, size_t len)
Base64-encode data.
Definition base64.c:52
static size_t base64_encoded_len(size_t raw_len)
Calculate length of base64-encoded data.
Definition base64.h:22
u32 crc32_le(u32 seed, const void *data, size_t len)
Calculate 32-bit little-endian CRC checksum.
Definition crc32.c:40
ring len
Length.
Definition dwmac.h:226
#define EINVAL
Invalid argument.
Definition errno.h:472
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
int xfer_open_uri_string(struct interface *intf, const char *uri_string)
Open URI string.
Definition open.c:125
int fetch_string_setting_copy(struct settings *settings, const struct setting *setting, char **data)
Fetch value of string setting.
Definition settings.c:874
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
const void * data
Start of data.
Definition asn1.h:23
size_t len
Length of data.
Definition asn1.h:25
struct x509_issuer issuer
Issuer.
Definition x509.h:241
struct asn1_cursor raw
Raw issuer.
Definition x509.h:32
static const struct validator_action validator_crosscert
Cross-signing certificate download validator action.
Definition validator.c:362
static const char crosscert_default[]
Default cross-signed certificate source.
Definition validator.c:233
static struct x509_certificate * x509_get(struct x509_certificate *cert)
Get reference to X.509 certificate.
Definition x509.h:267

References validator::action, base64_encode(), base64_encoded_len(), validator::cert, crc32_le(), crosscert_default, asn1_cursor::data, DBGC, EINVAL, ENOMEM, fetch_string_setting_copy(), free, intf_restart(), x509_certificate::issuer, asn1_cursor::len, len, link, NULL, x509_issuer::raw, rc, validator::rc, snprintf(), strerror(), strlen(), validator_crosscert, validator_name(), x509_get(), x509_name(), x509_put(), validator::xfer, xfer_open_uri_string(), and zalloc().

Referenced by validator_step().

◆ validator_ocsp_validate()

void validator_ocsp_validate ( struct validator * validator,
struct x509_certificate * cert,
int rc )
static

Validate OCSP response.

Parameters
validatorCertificate validator
certChecked certificate
rcCompletion status code

Definition at line 462 of file validator.c.

464 {
465 const void *data = validator->buffer.data;
466 size_t len = validator->buffer.len;
467 time_t now;
468
469 /* Check for errors */
470 if ( rc != 0 ) {
471 DBGC ( validator, "VALIDATOR %p \"%s\" could not fetch OCSP "
472 "response: %s\n", validator,
474 goto err_status;
475 }
476
477 /* Record OCSP response */
478 if ( ( rc = ocsp_response ( validator->ocsp, data, len ) ) != 0 ) {
479 DBGC ( validator, "VALIDATOR %p \"%s\" could not record OCSP "
480 "response: %s\n", validator,
482 goto err_response;
483 }
484
485 /* Validate OCSP response */
486 now = time ( NULL );
487 if ( ( rc = ocsp_validate ( validator->ocsp, now ) ) != 0 ) {
488 DBGC ( validator, "VALIDATOR %p \"%s\" could not validate "
489 "OCSP response: %s\n", validator,
491 goto err_validate;
492 }
493
494 /* Success */
495 DBGC ( validator, "VALIDATOR %p \"%s\" checked ",
497 DBGC ( validator, "\"%s\" via OCSP\n", x509_name ( cert ) );
498
499 err_validate:
500 err_response:
501 err_status:
504 validator->rc = rc;
505}
uint8_t data[48]
Additional event data.
Definition ena.h:11
int64_t time_t
Seconds since the Epoch.
Definition time.h:19
int ocsp_validate(struct ocsp_check *ocsp, time_t time)
Validate OCSP response.
Definition ocsp.c:884
An OCSP response.
Definition ocsp.h:66

References validator::buffer, data, xfer_buffer::data, DBGC, len, xfer_buffer::len, NULL, validator::ocsp, ocsp_put(), ocsp_validate(), rc, validator::rc, strerror(), validator_name(), and x509_name().

◆ validator_start_ocsp()

int validator_start_ocsp ( struct validator * validator,
struct x509_certificate * cert,
struct x509_certificate * issuer )
static

Start OCSP check.

Parameters
validatorCertificate validator
certCertificate to check
issuerIssuing certificate
Return values
rcReturn status code

Definition at line 521 of file validator.c.

523 {
524 const char *uri_string;
525 int rc;
526
527 /* Create OCSP check */
528 assert ( validator->ocsp == NULL );
529 if ( ( rc = ocsp_check ( cert, issuer, &validator->ocsp ) ) != 0 ) {
530 DBGC ( validator, "VALIDATOR %p \"%s\" could not create OCSP "
531 "check: %s\n", validator, validator_name ( validator ),
532 strerror ( rc ) );
533 goto err_check;
534 }
535
536 /* Set completion handler */
538 validator->cert = x509_get ( cert );
539
540 /* Open URI */
541 uri_string = validator->ocsp->uri_string;
542 DBGC ( validator, "VALIDATOR %p \"%s\" checking ",
544 DBGC ( validator, "\"%s\" via %s\n",
545 x509_name ( cert ), uri_string );
547 uri_string ) ) != 0 ) {
548 DBGC ( validator, "VALIDATOR %p \"%s\" could not open %s: "
550 uri_string, strerror ( rc ) );
551 goto err_open;
552 }
553
554 return 0;
555
557 err_open:
563 err_check:
564 validator->rc = rc;
565 return rc;
566}
An OCSP check.
Definition ocsp.h:86
char * uri_string
URI string.
Definition ocsp.h:94
static const struct validator_action validator_ocsp
OCSP validator action.
Definition validator.c:508

References validator::action, assert, validator::cert, DBGC, intf_restart(), NULL, validator::ocsp, ocsp_put(), rc, validator::rc, strerror(), ocsp_check::uri_string, validator_name(), validator_ocsp, x509_get(), x509_name(), x509_put(), validator::xfer, and xfer_open_uri_string().

Referenced by validator_step().

◆ validator_xfer_close()

void validator_xfer_close ( struct validator * validator,
int rc )
static

Close data transfer interface.

Parameters
validatorCertificate validator
rcReason for close

Definition at line 580 of file validator.c.

580 {
581 const struct validator_action *action;
582 struct x509_certificate *cert;
583
584 /* Close data transfer interface */
586 DBGC2 ( validator, "VALIDATOR %p \"%s\" transfer complete\n",
588
589 /* Clear current action */
590 action = validator->action;
592 assert ( action != NULL );
593
594 /* Take temporary ownership of the current certificate */
595 cert = validator->cert;
597 assert ( cert != NULL );
598
599 /* Process completed download */
600 action->done ( validator, cert, rc );
601
602 /* Drop temporary reference to certificate */
603 x509_put ( cert );
604
605 /* Free downloaded data */
607
608 /* Resume validation process */
610}
void process_add(struct process *process)
Add process to process list.
Definition process.c:60
A certificate validator action.
Definition validator.c:57
void(* done)(struct validator *validator, struct x509_certificate *cert, int rc)
Action to take upon completed transfer.
Definition validator.c:67

References validator::action, assert, validator::buffer, validator::cert, DBGC2, validator_action::done, intf_restart(), NULL, validator::process, process_add(), rc, validator_name(), x509_put(), validator::xfer, and xferbuf_free().

Referenced by validator_xfer_deliver().

◆ validator_xfer_deliver()

int validator_xfer_deliver ( struct validator * validator,
struct io_buffer * iobuf,
struct xfer_metadata * meta )
static

Receive data.

Parameters
validatorCertificate validator
iobufI/O buffer
metaData transfer metadata
Return values
rcReturn status code

Definition at line 620 of file validator.c.

622 {
623 int rc;
624
625 /* Add data to buffer */
626 if ( ( rc = xferbuf_deliver ( &validator->buffer, iob_disown ( iobuf ),
627 meta ) ) != 0 ) {
628 DBGC ( validator, "VALIDATOR %p \"%s\" could not receive "
629 "data: %s\n", validator, validator_name ( validator ),
630 strerror ( rc ) );
632 return rc;
633 }
634
635 return 0;
636}
uint8_t meta
Metadata flags.
Definition ena.h:3
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition iobuf.h:277
static void validator_xfer_close(struct validator *validator, int rc)
Close data transfer interface.
Definition validator.c:580
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:198

References validator::buffer, DBGC, iob_disown, meta, rc, strerror(), validator_name(), validator_xfer_close(), and xferbuf_deliver().

◆ validator_step()

void validator_step ( struct validator * validator)
static

Certificate validation process.

Parameters
validatorCertificate validator

Definition at line 659 of file validator.c.

659 {
660 struct x509_chain *chain = validator->chain;
661 struct x509_link *link;
662 struct x509_link *prev;
663 struct x509_certificate *cert;
664 time_t now;
665 int rc;
666
667 /* Try validating chain. Try even if the chain is incomplete,
668 * since certificates may already have been validated
669 * previously.
670 */
671 now = time ( NULL );
672 if ( ( rc = x509_validate_chain ( chain, now, NULL,
673 validator->root ) ) == 0 ) {
674 DBGC ( validator, "VALIDATOR %p \"%s\" validated\n",
677 return;
678 }
679 DBGC ( validator, "VALIDATOR %p \"%s\" not yet valid: %s\n",
681
682 /* Record as the most relevant error, if no more relevant
683 * error has already been recorded.
684 */
685 if ( validator->rc == 0 )
686 validator->rc = rc;
687
688 /* Find the first valid link in the chain, if any
689 *
690 * There is no point in attempting OCSP or cross-signed
691 * certificate downloads for certificates after the first
692 * valid link in the chain, since they cannot make a
693 * difference to the overall validation of the chain.
694 */
695 prev = NULL;
696 list_for_each_entry ( link, &chain->links, list ) {
697
698 /* Dump link information (for debugging) */
699 DBGC ( validator, "VALIDATOR %p \"%s\" has link ",
701 DBGC ( validator, "\"%s\"%s%s%s%s%s\n",
702 x509_name ( link->cert ),
703 ( ocsp_required ( link->cert ) ? " [NEEDOCSP]" : "" ),
704 ( ( link->flags & X509_LINK_FL_OCSPED ) ?
705 " [OCSPED]" : "" ),
706 ( ( link->flags & X509_LINK_FL_CROSSED ) ?
707 " [CROSSED]" : "" ),
708 ( x509_is_self_signed ( link->cert ) ? " [SELF]" : "" ),
709 ( x509_is_valid ( link->cert, validator->root ) ?
710 " [VALID]" : "" ) );
711
712 /* Stop at first valid link */
713 if ( x509_is_valid ( link->cert, validator->root ) )
714 break;
715 prev = link;
716 }
717
718 /* If this link is the issuer for a certificate that is
719 * pending an OCSP check attempt, then start OCSP to validate
720 * that certificate.
721 *
722 * If OCSP is not required for the issued certificate, or has
723 * already been attempted, or if we were unable to start OCSP
724 * for any reason, then proceed to attempting a cross-signed
725 * certificate download (which may end up replacing this
726 * issuer anyway).
727 */
728 if ( ( ! list_is_head_entry ( link, &chain->links, list ) ) &&
729 ( ! ( link->flags & X509_LINK_FL_OCSPED ) ) &&
730 ( prev != NULL ) && ocsp_required ( prev->cert ) ) {
731
732 /* Mark OCSP as attempted with this issuer */
733 link->flags |= X509_LINK_FL_OCSPED;
734
735 /* Start OCSP */
736 if ( ( rc = validator_start_ocsp ( validator, prev->cert,
737 link->cert ) ) == 0 ) {
738 /* Sleep until OCSP is complete */
739 return;
740 }
741 }
742
743 /* Work back up the chain (starting from the already
744 * identified first valid link, if any) to find a not-yet
745 * valid certificate for which we could attempt to download a
746 * cross-signed certificate chain.
747 */
749 cert = link->cert;
750
751 /* Sanity check */
752 assert ( ! x509_is_valid ( cert, validator->root ) );
753
754 /* Skip self-signed certificates (cannot be cross-signed) */
755 if ( x509_is_self_signed ( cert ) )
756 continue;
757
758 /* Skip previously attempted cross-signed downloads */
759 if ( link->flags & X509_LINK_FL_CROSSED )
760 continue;
761
762 /* Mark cross-signed certificate download as attempted */
763 link->flags |= X509_LINK_FL_CROSSED;
764
765 /* Start cross-signed certificate download */
767 link ) ) == 0 ) {
768 /* Sleep until download is complete */
769 return;
770 }
771 }
772
773 /* Nothing more to try: fail the validation */
775}
#define list_for_each_entry_continue_reverse(pos, head, member)
Iterate over entries in a list in reverse, starting after current position.
Definition list.h:487
#define list_is_head_entry(entry, head, member)
Test if entry is the list head.
Definition list.h:410
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
static int ocsp_required(struct x509_certificate *cert)
Check if X.509 certificate requires an OCSP check.
Definition ocsp.h:129
static int validator_start_download(struct validator *validator, struct x509_link *link)
Start download of cross-signing certificate.
Definition validator.c:374
static void validator_finished(struct validator *validator, int rc)
Mark certificate validation as finished.
Definition validator.c:171
static int validator_start_ocsp(struct validator *validator, struct x509_certificate *cert, struct x509_certificate *issuer)
Start OCSP check.
Definition validator.c:521
int x509_is_valid(struct x509_certificate *cert, struct x509_root *root)
Check if X.509 certificate is valid.
Definition x509.c:1313
int x509_validate_chain(struct x509_chain *chain, time_t time, struct x509_chain *store, struct x509_root *root)
Validate X.509 certificate chain.
Definition x509.c:1928
static int x509_is_self_signed(struct x509_certificate *cert)
Check if X.509 certificate is self-signed.
Definition x509.h:414
@ X509_LINK_FL_OCSPED
OCSP has been attempted.
Definition x509.h:197

References assert, x509_link::cert, validator::chain, DBGC, link, x509_chain::links, list_for_each_entry, list_for_each_entry_continue_reverse, list_is_head_entry, NULL, ocsp_required(), rc, validator::rc, validator::root, strerror(), validator_finished(), validator_name(), validator_start_download(), validator_start_ocsp(), x509_is_self_signed(), x509_is_valid(), X509_LINK_FL_CROSSED, X509_LINK_FL_OCSPED, x509_name(), and x509_validate_chain().

◆ create_validator()

int create_validator ( struct interface * job,
struct x509_chain * chain,
struct x509_root * root )

Instantiate a certificate validator.

Parameters
jobJob control interface
chainX.509 certificate chain
rootRoot of trust, or NULL to use default
Return values
rcReturn status code

Definition at line 795 of file validator.c.

796 {
797 struct validator *validator;
798 int rc;
799
800 /* Sanity check */
801 if ( ! chain ) {
802 rc = -EINVAL;
803 goto err_sanity;
804 }
805
806 /* Allocate and initialise structure */
807 validator = zalloc ( sizeof ( *validator ) );
808 if ( ! validator ) {
809 rc = -ENOMEM;
810 goto err_alloc;
811 }
814 &validator->refcnt );
816 &validator->refcnt );
818 &validator->refcnt );
822
823 /* Attach parent interface, mortalise self, and return */
826 DBGC2 ( validator, "VALIDATOR %p \"%s\" validating X509 chain %p\n",
828 return 0;
829
832 err_alloc:
833 err_sanity:
834 return rc;
835}
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition interface.c:108
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
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
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
struct stp_switch root
Root switch.
Definition stp.h:15
struct refcnt refcnt
Reference count.
Definition validator.c:74
static void validator_free(struct refcnt *refcnt)
Free certificate validator.
Definition validator.c:151
static struct process_descriptor validator_process_desc
Certificate validator process descriptor.
Definition validator.c:778
static struct interface_descriptor validator_xfer_desc
Certificate validator data transfer interface descriptor.
Definition validator.c:645
static struct interface_descriptor validator_job_desc
Certificate validator job control interface descriptor.
Definition validator.c:215
static struct x509_chain * x509_chain_get(struct x509_chain *chain)
Get reference to X.509 certificate chain.
Definition x509.h:289
static struct x509_root * x509_root_get(struct x509_root *root)
Get reference to X.509 root certificate list.
Definition x509.h:393
static void xferbuf_malloc_init(struct xfer_buffer *xferbuf)
Initialise malloc()-based data transfer buffer.
Definition xferbuf.h:66

References validator::buffer, validator::chain, DBGC2, EINVAL, ENOMEM, intf_init(), intf_plug_plug(), validator::job, validator::process, process_init(), rc, ref_init, ref_put, validator::refcnt, root, validator::root, validator_finished(), validator_free(), validator_job_desc, validator_name(), validator_process_desc, validator_xfer_desc, x509_chain_get(), x509_root_get(), validator::xfer, xferbuf_malloc_init(), and zalloc().

Referenced by imgverify(), and tls_new_server_hello_done().

Variable Documentation

◆ validator_job_operations

struct interface_operation validator_job_operations[]
static
Initial value:
= {
}
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
Job progress.
Definition job.h:16
static int validator_progress(struct validator *validator, struct job_progress *progress)
Report job progress.
Definition validator.c:194

Certificate validator job control interface operations.

Definition at line 209 of file validator.c.

209 {
212};

◆ validator_job_desc

struct interface_descriptor validator_job_desc
static
Initial value:
=
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
static struct interface_operation validator_job_operations[]
Certificate validator job control interface operations.
Definition validator.c:209

Certificate validator job control interface descriptor.

Definition at line 215 of file validator.c.

Referenced by create_validator().

◆ crosscert_default

const char crosscert_default[] = CROSSCERT
static

Default cross-signed certificate source.

Definition at line 233 of file validator.c.

Referenced by validator_start_download().

◆ validator_crosscert

const struct validator_action validator_crosscert
static
Initial value:
= {
.name = "XCRT",
}
static void validator_append(struct validator *validator, struct x509_certificate *cert, int rc)
Append cross-signing certificates to certificate chain.
Definition validator.c:243

Cross-signing certificate download validator action.

Definition at line 362 of file validator.c.

362 {
363 .name = "XCRT",
364 .done = validator_append,
365};

Referenced by validator_start_download().

◆ validator_ocsp

const struct validator_action validator_ocsp
static
Initial value:
= {
.name = "OCSP",
}
static void validator_ocsp_validate(struct validator *validator, struct x509_certificate *cert, int rc)
Validate OCSP response.
Definition validator.c:462

OCSP validator action.

Definition at line 508 of file validator.c.

508 {
509 .name = "OCSP",
511};

Referenced by validator_start_ocsp().

◆ validator_xfer_operations

struct interface_operation validator_xfer_operations[]
static
Initial value:
= {
}
static int validator_xfer_deliver(struct validator *validator, struct io_buffer *iobuf, struct xfer_metadata *meta)
Receive data.
Definition validator.c:620
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195

Certificate validator data transfer interface operations.

Definition at line 639 of file validator.c.

◆ validator_xfer_desc

struct interface_descriptor validator_xfer_desc
static
Initial value:
=
static struct interface_operation validator_xfer_operations[]
Certificate validator data transfer interface operations.
Definition validator.c:639

Certificate validator data transfer interface descriptor.

Definition at line 645 of file validator.c.

Referenced by create_validator().

◆ validator_process_desc

struct process_descriptor validator_process_desc
static
Initial value:
=
#define PROC_DESC_ONCE(object_type, process, _step)
Define a process descriptor for a process that runs only once.
Definition process.h:98
A process.
Definition process.h:18
static void validator_step(struct validator *validator)
Certificate validation process.
Definition validator.c:659

Certificate validator process descriptor.

Definition at line 778 of file validator.c.

Referenced by create_validator().