]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[crypto] Add asynchronous certificate validator
authorMichael Brown <mcb30@ipxe.org>
Tue, 8 May 2012 11:10:01 +0000 (12:10 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 8 May 2012 11:49:01 +0000 (12:49 +0100)
To allow for automatic download of cross-signing certificates and for
OCSP, the validation of certificates must be an asynchronous process.
Create a stub validator which uses a job-control interface to report
the result of certificate validation.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/errfile.h
src/include/ipxe/validator.h [new file with mode: 0644]
src/net/validator.c [new file with mode: 0644]

index 7de833d08cc19a36482d0ba06b92704fee651102..fbdeb0a39e7516d16a5d9ed235ca626632d7827b 100644 (file)
@@ -258,6 +258,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #define ERRFILE_imgtrust             ( ERRFILE_OTHER | 0x002b0000 )
 #define ERRFILE_menu_ui                      ( ERRFILE_OTHER | 0x002c0000 )
 #define ERRFILE_menu_cmd             ( ERRFILE_OTHER | 0x002d0000 )
+#define ERRFILE_validator            ( ERRFILE_OTHER | 0x002e0000 )
 
 /** @} */
 
diff --git a/src/include/ipxe/validator.h b/src/include/ipxe/validator.h
new file mode 100644 (file)
index 0000000..23bdab4
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _IPXE_VALIDATOR_H
+#define _IPXE_VALIDATOR_H
+
+/** @file
+ *
+ * Certificate validator
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/interface.h>
+#include <ipxe/x509.h>
+
+extern int create_validator ( struct interface *job, struct x509_chain *chain );
+
+#endif /* _IPXE_VALIDATOR_H */
diff --git a/src/net/validator.c b/src/net/validator.c
new file mode 100644 (file)
index 0000000..b6b52a2
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <errno.h>
+#include <ipxe/refcnt.h>
+#include <ipxe/malloc.h>
+#include <ipxe/interface.h>
+#include <ipxe/process.h>
+#include <ipxe/x509.h>
+#include <ipxe/validator.h>
+
+/** @file
+ *
+ * Certificate validator
+ *
+ */
+
+/** A certificate validator */
+struct validator {
+       /** Reference count */
+       struct refcnt refcnt;
+       /** Job control interface */
+       struct interface job;
+       /** Process */
+       struct process process;
+       /** X.509 certificate chain */
+       struct x509_chain *chain;
+};
+
+/**
+ * Free certificate validator
+ *
+ * @v refcnt           Reference count
+ */
+static void validator_free ( struct refcnt *refcnt ) {
+       struct validator *validator =
+               container_of ( refcnt, struct validator, refcnt );
+
+       DBGC ( validator, "VALIDATOR %p freed\n", validator );
+       x509_chain_put ( validator->chain );
+       free ( validator );
+}
+
+/**
+ * Mark certificate validation as finished
+ *
+ * @v validator                Certificate validator
+ * @v rc               Reason for finishing
+ */
+static void validator_finished ( struct validator *validator, int rc ) {
+
+       /* Remove process */
+       process_del ( &validator->process );
+
+       /* Close all interfaces */
+       intf_shutdown ( &validator->job, rc );
+}
+
+/****************************************************************************
+ *
+ * Job control interface
+ *
+ */
+
+/** Certificate validator job control interface operations */
+static struct interface_operation validator_job_operations[] = {
+       INTF_OP ( intf_close, struct validator *, validator_finished ),
+};
+
+/** Certificate validator job control interface descriptor */
+static struct interface_descriptor validator_job_desc =
+       INTF_DESC ( struct validator, job, validator_job_operations );
+
+/****************************************************************************
+ *
+ * Validation process
+ *
+ */
+
+/**
+ * Certificate validation process
+ *
+ * @v validator                Certificate validator
+ */
+static void validator_step ( struct validator *validator ) {
+       time_t now;
+       int rc;
+
+       /* Attempt to validate certificate chain */
+       now = time ( NULL );
+       if ( ( rc = x509_validate_chain ( validator->chain, now,
+                                         NULL ) ) != 0 ) {
+               DBGC ( validator, "VALIDATOR %p could not validate chain: %s\n",
+                      validator, strerror ( rc ) );
+               goto err_validate;
+       }
+
+       /* Mark validation as complete */
+       validator_finished ( validator, 0 );
+
+       return;
+
+ err_validate:
+       validator_finished ( validator, rc );
+}
+
+/** Certificate validator process descriptor */
+static struct process_descriptor validator_process_desc =
+       PROC_DESC_ONCE ( struct validator, process, validator_step );
+
+/****************************************************************************
+ *
+ * Instantiator
+ *
+ */
+
+/**
+ * Instantiate a certificate validator
+ *
+ * @v job              Job control interface
+ * @v chain            X.509 certificate chain
+ * @ret rc             Return status code
+ */
+int create_validator ( struct interface *job, struct x509_chain *chain ) {
+       struct validator *validator;
+       int rc;
+
+       /* Sanity check */
+       if ( ! chain ) {
+               rc = -EINVAL;
+               goto err_sanity;
+       }
+
+       /* Allocate and initialise structure */
+       validator = zalloc ( sizeof ( *validator ) );
+       if ( ! validator ) {
+               rc = -ENOMEM;
+               goto err_alloc;
+       }
+       ref_init ( &validator->refcnt, validator_free );
+       intf_init ( &validator->job, &validator_job_desc,
+                   &validator->refcnt );
+       process_init ( &validator->process, &validator_process_desc,
+                      &validator->refcnt );
+       validator->chain = x509_chain_get ( chain );
+
+       /* Attach parent interface, mortalise self, and return */
+       intf_plug_plug ( &validator->job, job );
+       ref_put ( &validator->refcnt );
+       DBGC ( validator, "VALIDATOR %p validating X509 chain %p\n",
+              validator, validator->chain );
+       return 0;
+
+       validator_finished ( validator, rc );
+       ref_put ( &validator->refcnt );
+ err_alloc:
+ err_sanity:
+       return rc;
+}