Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F131472462
D18797.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
17 KB
Referenced Files
None
Subscribers
None
D18797.diff
View Options
Index: lib/libsecureboot/Makefile
===================================================================
--- /dev/null
+++ lib/libsecureboot/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+PACKAGE=lib${LIB}
+
+.include <src.opts.mk>
+
+LIB= secureboot
+
+.include "${SRCTOP}/lib/libbearssl/Makefile.inc"
+
+INCS= secureboot.h
+SRCS= gen_sha256.c get_tbs.c util.c verify_cert.c
+
+.include <bsd.lib.mk>
Index: lib/libsecureboot/Makefile.inc
===================================================================
--- /dev/null
+++ lib/libsecureboot/Makefile.inc
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SECUREBOOT_SRC= ${SRCTOP}/lib/libsecureboot
+
+.PATH: ${SECUREBOOT_SRC}
+
+CFLAGS+= -I${SECUREBOOT_SRC}
Index: lib/libsecureboot/Makefile.libsa.inc
===================================================================
--- /dev/null
+++ lib/libsecureboot/Makefile.libsa.inc
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+.include "Makefile.inc"
+
+SRCS+= gen_sha256.c get_tbs.c util.c verify_cert.c
Index: lib/libsecureboot/gen_sha256.c
===================================================================
--- /dev/null
+++ lib/libsecureboot/gen_sha256.c
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2019 Stormshield.
+ * Copyright (c) 2019 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <secureboot.h>
+
+#define CHUNK_SIZE 4096
+
+/*
+ * Hash length bytes from fd using SHA256
+ * and store the result in output.
+ */
+int
+gen_digest(int fd, size_t length, unsigned char *output)
+{
+ br_hash_compat_context hash_ctx;
+ const br_hash_class *md;
+ char chunk[CHUNK_SIZE];
+ int bytes;
+
+ md = &br_sha256_vtable;
+
+ if (fd < 0 || length == 0 || output == NULL)
+ return (EINVAL);
+
+ md->init(&hash_ctx.vtable);
+
+ while (length > 0) {
+ if (length > CHUNK_SIZE)
+ bytes = CHUNK_SIZE;
+ else
+ bytes = length;
+
+ bytes = checked_read(fd, chunk, bytes);
+ if (bytes <= 0) {
+ return (-bytes);
+ }
+ md->update(&hash_ctx.vtable, chunk, bytes);
+ length -= bytes;
+ }
+
+ md->out(&hash_ctx.vtable, output);
+
+ return (0);
+}
Index: lib/libsecureboot/get_tbs.c
===================================================================
--- /dev/null
+++ lib/libsecureboot/get_tbs.c
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 2019 Stormshield.
+ * Copyright (c) 2019 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <secureboot.h>
+
+/* ASN parsing related defines */
+#define ASN1_CONSTRUCTED BIT(5)
+#define ASN1_PRIMITIVE_TAG 0x1F
+#define ASN1_INF_LENGTH 0x80
+#define ASN1_LENGTH_MASK 0x7F
+
+/*
+ * Get TBS part of certificate.
+ * Since BearSSL doesn't provide any API to do this,
+ * it has to be implemented here.
+ */
+void*
+X509_to_tbs(unsigned char* cert, size_t* output_size)
+{
+ unsigned char *result;
+ size_t tbs_size;
+ int size;
+ int i;
+
+ if (cert == NULL)
+ return NULL;
+
+ /* Strip two sequences to get to the TBS section */
+ for (i = 0; i < 2; i++) {
+ /*
+ * XXX: We don't need to support extended tags since
+ * they should not be present in certificates.
+ */
+ if ((*cert & ASN1_PRIMITIVE_TAG) == ASN1_PRIMITIVE_TAG)
+ return (NULL);
+
+ cert++;
+
+ if (*cert == ASN1_INF_LENGTH)
+ return (NULL);
+
+ size = *cert & ASN1_LENGTH_MASK;
+ tbs_size = 0;
+
+ /* Size can either be stored on a single or multiple bytes */
+ if (*cert & (ASN1_LENGTH_MASK + 1)) {
+ cert++;
+ while (*cert == 0 && size > 0) {
+ cert++;
+ size--;
+ }
+ while(size-- > 0) {
+ tbs_size <<= 8;
+ tbs_size |= *(cert++);
+ }
+ }
+ if (i == 0)
+ result = cert;
+ }
+ tbs_size += (cert - result);
+
+ if (output_size != NULL)
+ *output_size = tbs_size;
+
+ return (result);
+}
Index: lib/libsecureboot/secureboot.h
===================================================================
--- /dev/null
+++ lib/libsecureboot/secureboot.h
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 2019 Stormshield.
+ * Copyright (c) 2019 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SECUREBOOT_H
+#define SECUREBOOT_H
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef _STANDALONE
+#include <stand.h>
+#else
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#endif /* _STANDALONE */
+
+#include <bearssl.h>
+
+#define MAGIC 0x05ECB00705ECB007
+
+#pragma pack(1)
+
+struct signature_info {
+ uint64_t magic;
+ uint64_t kernel_size;
+ uint64_t signature_size;
+ uint64_t cert_size;
+};
+
+#pragma pack()
+
+struct vector {
+ char *data;
+ size_t capacity;
+ size_t length;
+};
+
+int gen_digest(int, size_t, unsigned char*);
+void* X509_to_tbs(unsigned char*, size_t*);
+br_x509_pkey * verify_cert(br_x509_certificate*, br_x509_certificate*, size_t);
+
+/* Small helper functions */
+ssize_t checked_read(int, char*, size_t);
+void vector_append(void*, const void*, size_t);
+int copy_pkey(br_x509_pkey*, const br_x509_pkey*);
+void free_anchors(br_x509_trust_anchor*, size_t);
+void free_certs(br_x509_certificate*, size_t);
+void free_pkey(br_x509_pkey*);
+
+#endif /* SECUREBOOT_H */
+
Index: lib/libsecureboot/util.c
===================================================================
--- /dev/null
+++ lib/libsecureboot/util.c
@@ -0,0 +1,147 @@
+/*-
+ * Copyright (c) 2019 Stormshield.
+ * Copyright (c) 2019 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <secureboot.h>
+
+/*
+ * Read leangth bytes from file fd.
+ * If we can't read everything in a single read,
+ * repeat until we get all we need,
+ * or hit EOF.
+ */
+ssize_t
+checked_read(int fd, char *buf, size_t length)
+{
+ ssize_t result;
+ size_t bytes_read = 0;
+
+ while(length != 0) {
+ result = read(fd, buf, length);
+
+ if (result < 0) {
+ printf("Read error %d\n", errno);
+ return (-errno);
+ }
+ if (result == 0)
+ break;
+
+ length -= result;
+ bytes_read += result;
+ buf += result;
+ }
+ return (bytes_read);
+}
+
+/*
+ * Helper function used as callback in BearSSL.
+ * It simply appends data to existing vector structure.
+ */
+void
+vector_append(void *ctx, const void *src, size_t len)
+{
+ struct vector *vec = (struct vector*) ctx;
+
+ if (vec->data == NULL)
+ return;
+
+ if (vec->capacity - vec->length < len) {
+ vec->data = realloc(vec->data, 2*vec->capacity);
+ if (vec->data == NULL)
+ return;
+
+ vec->capacity *= 2;
+ }
+
+ memcpy((vec->data + vec->length), src, len);
+ vec->length += len;
+}
+
+/*
+ * Helper function that allocates memory and duplicates a public key.
+ */
+int
+copy_pkey(br_x509_pkey *dest, const br_x509_pkey *src)
+{
+ if (src->key_type != BR_KEYTYPE_RSA)
+ return (EINVAL);
+
+ dest->key_type = src->key_type;
+ dest->key.rsa.nlen = src->key.rsa.nlen;
+ dest->key.rsa.elen = src->key.rsa.elen;
+
+ dest->key.rsa.n = malloc(dest->key.rsa.nlen);
+ if (dest->key.rsa.n == NULL)
+ return (ENOMEM);
+
+ dest->key.rsa.e = malloc(dest->key.rsa.elen);
+ if (dest->key.rsa.e == NULL)
+ return (ENOMEM);
+
+ memcpy(dest->key.rsa.n, src->key.rsa.n, dest->key.rsa.nlen);
+ memcpy(dest->key.rsa.e, src->key.rsa.e, dest->key.rsa.elen);
+
+ return (0);
+}
+
+/*
+ * Routines used for memory management.
+ */
+void
+free_certs(br_x509_certificate *certs, size_t count)
+{
+ if (certs == NULL)
+ return;
+
+ while(count-- > 0)
+ free(certs[count].data);
+
+ free(certs);
+}
+
+void
+free_anchors(br_x509_trust_anchor *anchors, size_t count)
+{
+ if (anchors == NULL)
+ return;
+
+ while(count-- > 0) {
+ free(anchors[count].dn.data);
+ free_pkey(&anchors[count].pkey);
+ }
+
+ free(anchors);
+}
+
+void
+free_pkey(br_x509_pkey *pkey)
+{
+ free(pkey->key.rsa.n);
+ free(pkey->key.rsa.e);
+}
Index: lib/libsecureboot/verify_cert.c
===================================================================
--- /dev/null
+++ lib/libsecureboot/verify_cert.c
@@ -0,0 +1,164 @@
+/*-
+ * Copyright (c) 2019 Stormshield.
+ * Copyright (c) 2019 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <secureboot.h>
+
+#define DEFAULT_DN_SIZE 128
+
+/*
+ * Convert X509 certificate to a br_x509_trust_anchor format
+ * that can be used for verification in the "minimal" engine.
+ */
+static int
+get_anchor(const br_x509_certificate *cert, br_x509_trust_anchor *result)
+{
+ br_x509_decoder_context decoder_ctx;
+ br_x509_trust_anchor anchor;
+ br_x509_pkey *pkey;
+ struct vector vec;
+ int error;
+
+ anchor.dn.data = NULL;
+ anchor.pkey.key.rsa.n = NULL;
+ anchor.pkey.key.rsa.e = NULL;
+
+ /*
+ * Allocate memory for dn, that will be populated in callback.
+ */
+ vec.data = malloc(DEFAULT_DN_SIZE);
+ if (vec.data == NULL) {
+ printf("Failed to allocate memory\n");
+ error = ENOMEM;
+ goto fail;
+ }
+ vec.capacity = DEFAULT_DN_SIZE;
+ vec.length = 0;
+
+ br_x509_decoder_init(&decoder_ctx, vector_append, &vec);
+ br_x509_decoder_push(&decoder_ctx, cert->data, cert->data_len);
+ pkey = br_x509_decoder_get_pkey(&decoder_ctx);
+
+ error = copy_pkey(&anchor.pkey, pkey);
+ if (error != 0)
+ goto fail;
+
+ anchor.dn.data = vec.data;
+ anchor.dn.len = vec.length;
+
+ if (anchor.dn.data == NULL)
+ goto fail;
+
+ /*
+ * Check if parsed certificate has the CA bit.
+ * If that is not the case the verification engine
+ * will only look for a direct match against
+ * the verified certificate.
+ */
+ if (br_x509_decoder_isCA(&decoder_ctx))
+ anchor.flags = BR_X509_TA_CA;
+ else
+ anchor.flags = 0;
+
+ memcpy(result, &anchor, sizeof(br_x509_trust_anchor));
+ return (0);
+
+fail:
+ if (anchor.dn.data != NULL)
+ free(anchor.dn.data);
+
+ if (anchor.pkey.key.rsa.n != NULL)
+ free(anchor.pkey.key.rsa.n);
+
+ if (anchor.pkey.key.rsa.e != NULL)
+ free(anchor.pkey.key.rsa.e);
+
+ return (error);
+}
+
+/*
+ * Verify the cert using the BearSSL "minimal" engine.
+ * Return public key of verified certificate on success and NULL otherwise.
+ */
+br_x509_pkey *
+verify_cert(br_x509_certificate *cert, br_x509_certificate *trusted_certs, size_t num)
+{
+ br_x509_minimal_context ctx;
+ br_x509_trust_anchor *anchors;
+ const br_x509_pkey *result_pkey;
+ br_x509_pkey *pkey;
+ unsigned usages;
+ int error;
+ unsigned int i;
+
+ if (cert == NULL || trusted_certs == NULL || num == 0)
+ return (NULL);
+
+ anchors = malloc(sizeof(br_x509_trust_anchor) * num);
+ if (anchors == NULL)
+ return (NULL);
+
+ for (i = 0; i < num; i++) {
+ error = get_anchor(&trusted_certs[i], &anchors[i]);
+ if (error != 0)
+ return (NULL);
+ }
+
+ br_x509_minimal_init(&ctx, &br_sha256_vtable, anchors, num);
+ br_x509_minimal_set_hash(&ctx, br_sha256_ID, &br_sha256_vtable);
+ br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default());
+
+ /*
+ * We currently don't support chain certificates.
+ */
+ ctx.vtable->start_chain(&ctx.vtable, NULL);
+ ctx.vtable->start_cert(&ctx.vtable, cert->data_len);
+ ctx.vtable->append(&ctx.vtable, cert->data, cert->data_len);
+ ctx.vtable->end_cert(&ctx.vtable);
+ error = ctx.vtable->end_chain(&ctx.vtable);
+
+ result_pkey = ctx.vtable->get_pkey(&ctx.vtable, &usages);
+ free_anchors(anchors, num);
+
+ if (error != 0)
+ return (NULL);
+
+ if (ctx.err != BR_ERR_X509_OK && ctx.err != 0)
+ return (NULL);
+
+ pkey = malloc(sizeof(br_x509_pkey));
+ if (pkey == NULL || copy_pkey(pkey, result_pkey) != 0) {
+ if (pkey != NULL)
+ free(pkey);
+
+ return (NULL);
+ }
+
+ return (pkey);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Oct 9, 9:50 AM (18 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23489829
Default Alt Text
D18797.diff (17 KB)
Attached To
Mode
D18797: Introduce new Secure Boot library
Attached
Detach File
Event Timeline
Log In to Comment