summaryrefslogtreecommitdiff
path: root/firmware/lib20
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/lib20')
-rw-r--r--firmware/lib20/include/vb2_common.h16
-rw-r--r--firmware/lib20/include/vb2_struct.h88
-rw-r--r--firmware/lib20/kernel.c112
3 files changed, 213 insertions, 3 deletions
diff --git a/firmware/lib20/include/vb2_common.h b/firmware/lib20/include/vb2_common.h
index 4067d694..a71cfe6c 100644
--- a/firmware/lib20/include/vb2_common.h
+++ b/firmware/lib20/include/vb2_common.h
@@ -156,4 +156,20 @@ int vb2_verify_fw_preamble(struct vb2_fw_preamble *preamble,
const struct vb2_public_key *key,
const struct vb2_workbuf *wb);
+/**
+ * Check the sanity of a kernel preamble using a public key.
+ *
+ * The signature in the preamble is destroyed during the check.
+ *
+ * @param preamble Preamble to verify
+ * @param size Size of preamble buffer
+ * @param key Key to use to verify preamble
+ * @param wb Work buffer
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble,
+ uint32_t size,
+ const struct vb2_public_key *key,
+ const struct vb2_workbuf *wb);
+
#endif /* VBOOT_REFERENCE_VB2_COMMON_H_ */
diff --git a/firmware/lib20/include/vb2_struct.h b/firmware/lib20/include/vb2_struct.h
index ec28e719..d3e2f400 100644
--- a/firmware/lib20/include/vb2_struct.h
+++ b/firmware/lib20/include/vb2_struct.h
@@ -81,8 +81,6 @@ struct vb2_keyblock {
/* Version of this header format */
uint32_t header_version_major;
-
- /* Version of this header format */
uint32_t header_version_minor;
/*
@@ -121,7 +119,7 @@ struct vb2_keyblock {
#define FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR 2
#define FIRMWARE_PREAMBLE_HEADER_VERSION_MINOR 1
-/* Flags for VbFirmwarePreambleHeader.flags */
+/* Flags for vb2_fw_preamble.flags */
/* Reserved; do not use */
#define VB2_FIRMWARE_PREAMBLE_RESERVED0 0x00000001
/* Do not allow use of any hardware crypto accelerators. */
@@ -178,4 +176,88 @@ struct vb2_fw_preamble {
#define EXPECTED_VB2_FW_PREAMBLE_SIZE 108
+/* Kernel preamble header */
+#define KERNEL_PREAMBLE_HEADER_VERSION_MAJOR 2
+#define KERNEL_PREAMBLE_HEADER_VERSION_MINOR 2
+
+/* Flags for vb2_kernel_preamble.flags */
+/* Kernel image type = bits 1:0 */
+#define VB2_KERNEL_PREAMBLE_KERNEL_TYPE_MASK 0x00000003
+#define VB2_KERNEL_PREAMBLE_KERNEL_TYPE_CROS 0
+#define VB2_KERNEL_PREAMBLE_KERNEL_TYPE_BOOTIMG 1
+/* Kernel types 2,3 are reserved for future use */
+
+/*
+ * Preamble block for kernel, version 2.2
+ *
+ * This should be followed by:
+ * 1) The signature data for the kernel body, pointed to by
+ * body_signature.sig_offset.
+ * 2) The signature data for (vb2_kernel_preamble + body signature data),
+ * pointed to by preamble_signature.sig_offset.
+ * 3) The 16-bit vmlinuz header, which is used for reconstruction of
+ * vmlinuz image.
+ */
+struct vb2_kernel_preamble {
+ /*
+ * Size of this preamble, including keys, signatures, vmlinuz header,
+ * and padding, in bytes
+ */
+ uint32_t preamble_size;
+ uint32_t reserved0;
+
+ /* Signature for this preamble (header + body signature) */
+ struct vb2_signature preamble_signature;
+
+ /* Version of this header format */
+ uint32_t header_version_major;
+ uint32_t header_version_minor;
+
+ /* Kernel version */
+ uint32_t kernel_version;
+ uint32_t reserved1;
+
+ /* Load address for kernel body */
+ uint64_t body_load_address;
+
+ /* Address of bootloader, after body is loaded at body_load_address */
+ uint64_t bootloader_address;
+
+ /* Size of bootloader in bytes */
+ uint32_t bootloader_size;
+ uint32_t reserved2;
+
+ /* Signature for the kernel body */
+ struct vb2_signature body_signature;
+
+ /*
+ * Fields added in header version 2.1. You must verify the header
+ * version before reading these fields!
+ */
+
+ /*
+ * Address of 16-bit header for vmlinuz reassembly. Readers should
+ * return 0 for header version < 2.1.
+ */
+ uint64_t vmlinuz_header_address;
+
+ /* Size of 16-bit header for vmlinuz in bytes. Readers should return 0
+ for header version < 2.1 */
+ uint32_t vmlinuz_header_size;
+ uint32_t reserved3;
+
+ /*
+ * Fields added in header version 2.2. You must verify the header
+ * version before reading these fields!
+ */
+
+ /*
+ * Flags; see VB2_KERNEL_PREAMBLE_*. Readers should return 0 for
+ * header version < 2.2.
+ */
+ uint32_t flags;
+} __attribute__((packed));
+
+#define EXPECTED_VB2_KERNEL_PREAMBLE_SIZE 116
+
#endif /* VBOOT_REFERENCE_VB2_STRUCT_H_ */
diff --git a/firmware/lib20/kernel.c b/firmware/lib20/kernel.c
new file mode 100644
index 00000000..ec47ce77
--- /dev/null
+++ b/firmware/lib20/kernel.c
@@ -0,0 +1,112 @@
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Kernel verified boot functions
+ */
+
+#include "2sysincludes.h"
+#include "2rsa.h"
+#include "2sha.h"
+#include "vb2_common.h"
+
+int vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble,
+ uint32_t size,
+ const struct vb2_public_key *key,
+ const struct vb2_workbuf *wb)
+{
+ struct vb2_signature *sig = &preamble->preamble_signature;
+
+ VB2_DEBUG("Verifying kernel preamble.\n");
+
+ /* Sanity checks before attempting signature of data */
+ if(size < sizeof(*preamble)) {
+ VB2_DEBUG("Not enough data for preamble header.\n");
+ return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER;
+ }
+ if (preamble->header_version_major !=
+ KERNEL_PREAMBLE_HEADER_VERSION_MAJOR) {
+ VB2_DEBUG("Incompatible kernel preamble header version.\n");
+ return VB2_ERROR_PREAMBLE_HEADER_VERSION;
+ }
+ if (preamble->header_version_minor < 2) {
+ VB2_DEBUG("Old preamble header format not supported\n");
+ return VB2_ERROR_PREAMBLE_HEADER_OLD;
+ }
+ if (size < preamble->preamble_size) {
+ VB2_DEBUG("Not enough data for preamble.\n");
+ return VB2_ERROR_PREAMBLE_SIZE;
+ }
+
+ /* Check signature */
+ if (vb2_verify_signature_inside(preamble, preamble->preamble_size,
+ sig)) {
+ VB2_DEBUG("Preamble signature off end of preamble\n");
+ return VB2_ERROR_PREAMBLE_SIG_OUTSIDE;
+ }
+
+ /* Make sure advertised signature data sizes are sane. */
+ if (preamble->preamble_size < sig->data_size) {
+ VB2_DEBUG("Signature calculated past end of the block\n");
+ return VB2_ERROR_PREAMBLE_SIGNED_TOO_MUCH;
+ }
+
+ if (vb2_verify_data((const uint8_t *)preamble, size, sig, key, wb)) {
+ VB2_DEBUG("Preamble signature validation failed\n");
+ return VB2_ERROR_PREAMBLE_SIG_INVALID;
+ }
+
+ /* Verify we signed enough data */
+ if (sig->data_size < sizeof(struct vb2_fw_preamble)) {
+ VB2_DEBUG("Didn't sign enough data\n");
+ return VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE;
+ }
+
+ /* Verify body signature is inside the signed data */
+ if (vb2_verify_signature_inside(preamble, sig->data_size,
+ &preamble->body_signature)) {
+ VB2_DEBUG("Body signature off end of preamble\n");
+ return VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE;
+ }
+
+ /*
+ * If bootloader is present, verify it's covered by the body
+ * signature.
+ */
+ if (preamble->bootloader_size) {
+ const void *body_ptr =
+ (const void *)(uintptr_t)preamble->body_load_address;
+ const void *bootloader_ptr =
+ (const void *)(uintptr_t)preamble->bootloader_address;
+ if (vb2_verify_member_inside(body_ptr,
+ preamble->body_signature.data_size,
+ bootloader_ptr,
+ preamble->bootloader_size,
+ 0, 0)) {
+ VB2_DEBUG("Bootloader off end of signed data\n");
+ return VB2_ERROR_PREAMBLE_BOOTLOADER_OUTSIDE;
+ }
+ }
+
+ /*
+ * If vmlinuz header is present, verify it's covered by the body
+ * signature.
+ */
+ if (preamble->vmlinuz_header_size) {
+ const void *body_ptr =
+ (const void *)(uintptr_t)preamble->body_load_address;
+ const void *vmlinuz_header_ptr = (const void *)
+ (uintptr_t)preamble->vmlinuz_header_address;
+ if (vb2_verify_member_inside(body_ptr,
+ preamble->body_signature.data_size,
+ vmlinuz_header_ptr,
+ preamble->vmlinuz_header_size,
+ 0, 0)) {
+ VB2_DEBUG("Vmlinuz header off end of signed data\n");
+ return VB2_ERROR_PREAMBLE_VMLINUZ_HEADER_OUTSIDE;
+ }
+ }
+
+ /* Success */
+ return VB2_SUCCESS;
+}