Page MenuHomeFreeBSD

D18797.diff
No OneTemporary

D18797.diff

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

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)

Event Timeline