crypto: initial import of the chromeos vboot libraries
authorRonald G. Minnich <rminnich@gmail.com>
Thu, 13 Oct 2016 20:39:02 +0000 (13:39 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 14 Oct 2016 14:52:45 +0000 (10:52 -0400)
This code is needed to support the capability device, imported
in a separate commit. This is recommended as a 'best' version
of these algorithms by a security expert at Google.

This is from  https://chromium.googlesource.com/chromiumos/platform/vboot_reference
ref 3b55afa94e84c91874fcdad352b4053036886aa7

Change-Id: Ie3d90f183df990fd5bde6dfd83efbbd1e9b6009b
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
34 files changed:
kern/lib/crypto/2api.c [new file with mode: 0644]
kern/lib/crypto/2common.c [new file with mode: 0644]
kern/lib/crypto/2crc8.c [new file with mode: 0644]
kern/lib/crypto/2hmac.c [new file with mode: 0644]
kern/lib/crypto/2misc.c [new file with mode: 0644]
kern/lib/crypto/2nvstorage.c [new file with mode: 0644]
kern/lib/crypto/2rsa.c [new file with mode: 0644]
kern/lib/crypto/2secdata.c [new file with mode: 0644]
kern/lib/crypto/2secdatak.c [new file with mode: 0644]
kern/lib/crypto/2sha1.c [new file with mode: 0644]
kern/lib/crypto/2sha256.c [new file with mode: 0644]
kern/lib/crypto/2sha512.c [new file with mode: 0644]
kern/lib/crypto/2sha_utility.c [new file with mode: 0644]
kern/lib/crypto/2stub.c [new file with mode: 0644]
kern/lib/crypto/2tpm_bootmode.c [new file with mode: 0644]
kern/lib/crypto/Kbuild [new file with mode: 0644]
kern/lib/crypto/include/2api.h [new file with mode: 0644]
kern/lib/crypto/include/2common.h [new file with mode: 0644]
kern/lib/crypto/include/2crc8.h [new file with mode: 0644]
kern/lib/crypto/include/2crypto.h [new file with mode: 0644]
kern/lib/crypto/include/2fw_hash_tags.h [new file with mode: 0644]
kern/lib/crypto/include/2hmac.h [new file with mode: 0644]
kern/lib/crypto/include/2id.h [new file with mode: 0644]
kern/lib/crypto/include/2misc.h [new file with mode: 0644]
kern/lib/crypto/include/2nvstorage.h [new file with mode: 0644]
kern/lib/crypto/include/2nvstorage_fields.h [new file with mode: 0644]
kern/lib/crypto/include/2recovery_reasons.h [new file with mode: 0644]
kern/lib/crypto/include/2return_codes.h [new file with mode: 0644]
kern/lib/crypto/include/2rsa.h [new file with mode: 0644]
kern/lib/crypto/include/2secdata.h [new file with mode: 0644]
kern/lib/crypto/include/2sha.h [new file with mode: 0644]
kern/lib/crypto/include/2struct.h [new file with mode: 0644]
kern/lib/crypto/include/2sysincludes.h [new file with mode: 0644]
kern/lib/crypto/include/2tpm_bootmode.h [new file with mode: 0644]

diff --git a/kern/lib/crypto/2api.c b/kern/lib/crypto/2api.c
new file mode 100644 (file)
index 0000000..c12a805
--- /dev/null
@@ -0,0 +1,208 @@
+/* Copyright (c) 2014 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.
+ *
+ * Externally-callable APIs
+ * (Firmware portion)
+ */
+
+#include "2sysincludes.h"
+#include "2api.h"
+#include "2common.h"
+#include "2misc.h"
+#include "2nvstorage.h"
+#include "2secdata.h"
+#include "2sha.h"
+#include "2rsa.h"
+#include "2tpm_bootmode.h"
+
+int vb2api_secdata_check(const struct vb2_context *ctx)
+{
+       return vb2_secdata_check_crc(ctx);
+}
+
+int vb2api_secdata_create(struct vb2_context *ctx)
+{
+       return vb2_secdata_create(ctx);
+}
+
+void vb2api_fail(struct vb2_context *ctx, uint8_t reason, uint8_t subcode)
+{
+       /* Initialize the vboot context if it hasn't been yet */
+       vb2_init_context(ctx);
+
+       vb2_fail(ctx, reason, subcode);
+}
+
+int vb2api_fw_phase1(struct vb2_context *ctx)
+{
+       int rv;
+
+       /* Initialize the vboot context if it hasn't been yet */
+       vb2_init_context(ctx);
+
+       /* Initialize NV context */
+       vb2_nv_init(ctx);
+
+       /*
+        * Handle caller-requested reboot due to secdata.  Do this before we
+        * even look at secdata.  If we fail because of a reboot loop we'll be
+        * the first failure so will get to set the recovery reason.
+        */
+       if (!(ctx->flags & VB2_CONTEXT_SECDATA_WANTS_REBOOT)) {
+               /* No reboot requested */
+               vb2_nv_set(ctx, VB2_NV_TPM_REQUESTED_REBOOT, 0);
+       } else if (vb2_nv_get(ctx, VB2_NV_TPM_REQUESTED_REBOOT)) {
+               /*
+                * Reboot requested... again.  Fool me once, shame on you.
+                * Fool me twice, shame on me.  Fail into recovery to avoid
+                * a reboot loop.
+                */
+               vb2_fail(ctx, VB2_RECOVERY_RO_TPM_REBOOT, 0);
+       } else {
+               /* Reboot requested for the first time */
+               vb2_nv_set(ctx, VB2_NV_TPM_REQUESTED_REBOOT, 1);
+               return VB2_ERROR_API_PHASE1_SECDATA_REBOOT;
+       }
+
+       /* Initialize secure data */
+       rv = vb2_secdata_init(ctx);
+       if (rv)
+               vb2_fail(ctx, VB2_RECOVERY_SECDATA_INIT, rv);
+
+       /* Load and parse the GBB header */
+       rv = vb2_fw_parse_gbb(ctx);
+       if (rv)
+               vb2_fail(ctx, VB2_RECOVERY_GBB_HEADER, rv);
+
+       /*
+        * Check for recovery.  Note that this function returns void, since any
+        * errors result in requesting recovery.  That's also why we don't
+        * return error from failures in the preceding two steps; those
+        * failures simply cause us to detect recovery mode here.
+        */
+       vb2_check_recovery(ctx);
+
+       /* Check for dev switch */
+       rv = vb2_check_dev_switch(ctx);
+       if (rv && !(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
+               /*
+                * Error in dev switch processing, and we weren't already
+                * headed for recovery mode.  Reboot into recovery mode, since
+                * it's too late to handle those errors this boot, and we need
+                * to take a different path through the dev switch checking
+                * code in that case.
+                */
+               vb2_fail(ctx, VB2_RECOVERY_DEV_SWITCH, rv);
+               return rv;
+       }
+
+       /* Return error if recovery is needed */
+       if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) {
+               /* Always clear RAM when entering recovery mode */
+               ctx->flags |= VB2_CONTEXT_CLEAR_RAM;
+               return VB2_ERROR_API_PHASE1_RECOVERY;
+       }
+
+       return VB2_SUCCESS;
+}
+
+int vb2api_fw_phase2(struct vb2_context *ctx)
+{
+       int rv;
+
+       /*
+        * Use the slot from the last boot if this is a resume.  Do not set
+        * VB2_SD_STATUS_CHOSE_SLOT so the try counter is not decremented on
+        * failure as we are explicitly not attempting to boot from a new slot.
+        */
+       if (ctx->flags & VB2_CONTEXT_S3_RESUME) {
+               struct vb2_shared_data *sd = vb2_get_sd(ctx);
+
+               /* Set the current slot to the last booted slot */
+               sd->fw_slot = vb2_nv_get(ctx, VB2_NV_FW_TRIED);
+
+               /* Set context flag if we're using slot B */
+               if (sd->fw_slot)
+                       ctx->flags |= VB2_CONTEXT_FW_SLOT_B;
+
+               return VB2_SUCCESS;
+       }
+
+       /* Always clear RAM when entering developer mode */
+       if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE)
+               ctx->flags |= VB2_CONTEXT_CLEAR_RAM;
+
+       /* Check for explicit request to clear TPM */
+       rv = vb2_check_tpm_clear(ctx);
+       if (rv) {
+               vb2_fail(ctx, VB2_RECOVERY_TPM_CLEAR_OWNER, rv);
+               return rv;
+       }
+
+       /* Decide which firmware slot to try this boot */
+       rv = vb2_select_fw_slot(ctx);
+       if (rv) {
+               vb2_fail(ctx, VB2_RECOVERY_FW_SLOT, rv);
+               return rv;
+       }
+
+       return VB2_SUCCESS;
+}
+
+int vb2api_extend_hash(struct vb2_context *ctx,
+                      const void *buf,
+                      uint32_t size)
+{
+       struct vb2_shared_data *sd = vb2_get_sd(ctx);
+       struct vb2_digest_context *dc = (struct vb2_digest_context *)
+               (ctx->workbuf + sd->workbuf_hash_offset);
+
+       /* Must have initialized hash digest work area */
+       if (!sd->workbuf_hash_size)
+               return VB2_ERROR_API_EXTEND_HASH_WORKBUF;
+
+       /* Don't extend past the data we expect to hash */
+       if (!size || size > sd->hash_remaining_size)
+               return VB2_ERROR_API_EXTEND_HASH_SIZE;
+
+       sd->hash_remaining_size -= size;
+
+       if (dc->using_hwcrypto)
+               return vb2ex_hwcrypto_digest_extend(buf, size);
+       else
+               return vb2_digest_extend(dc, buf, size);
+}
+
+int vb2api_get_pcr_digest(struct vb2_context *ctx,
+                         enum vb2_pcr_digest which_digest,
+                         uint8_t *dest,
+                         uint32_t *dest_size)
+{
+       const uint8_t *digest;
+       uint32_t digest_size;
+
+       switch (which_digest) {
+       case BOOT_MODE_PCR:
+               digest = vb2_get_boot_state_digest(ctx);
+               digest_size = VB2_SHA1_DIGEST_SIZE;
+               break;
+       case HWID_DIGEST_PCR:
+               digest = vb2_get_sd(ctx)->gbb_hwid_digest;
+               digest_size = VB2_GBB_HWID_DIGEST_SIZE;
+               break;
+       default:
+               return VB2_ERROR_API_PCR_DIGEST;
+       }
+
+       if (digest == NULL || *dest_size < digest_size)
+               return VB2_ERROR_API_PCR_DIGEST_BUF;
+
+       memcpy(dest, digest, digest_size);
+       if (digest_size < *dest_size)
+               memset(dest + digest_size, 0, *dest_size - digest_size);
+
+       *dest_size = digest_size;
+
+       return VB2_SUCCESS;
+}
diff --git a/kern/lib/crypto/2common.c b/kern/lib/crypto/2common.c
new file mode 100644 (file)
index 0000000..9e75d0c
--- /dev/null
@@ -0,0 +1,116 @@
+/* Copyright (c) 2014 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.
+ *
+ * Common functions between firmware and kernel verified boot.
+ * (Firmware portion)
+ */
+
+#include "2sysincludes.h"
+#include "2common.h"
+#include "2rsa.h"
+#include "2sha.h"
+
+int vb2_safe_memcmp(const void *s1, const void *s2, size_t size)
+{
+       const unsigned char *us1 = s1;
+       const unsigned char *us2 = s2;
+       int result = 0;
+
+       if (0 == size)
+               return 0;
+
+       /*
+        * Code snippet without data-dependent branch due to Nate Lawson
+        * (nate@root.org) of Root Labs.
+        */
+       while (size--)
+               result |= *us1++ ^ *us2++;
+
+       return result != 0;
+}
+
+int vb2_align(uint8_t **ptr, uint32_t *size, uint32_t align, uint32_t want_size)
+{
+       uintptr_t p = (uintptr_t)*ptr;
+       uintptr_t offs = p & (align - 1);
+
+       if (offs) {
+               offs = align - offs;
+
+               if (*size < offs)
+                       return VB2_ERROR_ALIGN_BIGGER_THAN_SIZE;
+
+               *ptr += offs;
+               *size -= offs;
+       }
+
+       if (*size < want_size)
+               return VB2_ERROR_ALIGN_SIZE;
+
+       return VB2_SUCCESS;
+}
+
+void vb2_workbuf_init(struct vb2_workbuf *wb, uint8_t *buf, uint32_t size)
+{
+       wb->buf = buf;
+       wb->size = size;
+
+       /* Align the buffer so allocations will be aligned */
+       if (vb2_align(&wb->buf, &wb->size, VB2_WORKBUF_ALIGN, 0))
+               wb->size = 0;
+}
+
+/**
+ * Round up a number to a multiple of VB2_WORKBUF_ALIGN
+ *
+ * @param v            Number to round up
+ * @return The number, rounded up.
+ */
+static __inline uint32_t wb_round_up(uint32_t v)
+{
+       return (v + VB2_WORKBUF_ALIGN - 1) & ~(VB2_WORKBUF_ALIGN - 1);
+}
+
+void *vb2_workbuf_alloc(struct vb2_workbuf *wb, uint32_t size)
+{
+       uint8_t *ptr = wb->buf;
+
+       /* Round up size to work buffer alignment */
+       size = wb_round_up(size);
+
+       if (size > wb->size)
+               return NULL;
+
+       wb->buf += size;
+       wb->size -= size;
+
+       return ptr;
+}
+
+void *vb2_workbuf_realloc(struct vb2_workbuf *wb,
+                         uint32_t oldsize,
+                         uint32_t newsize)
+{
+       /*
+        * Just free and allocate to update the size.  No need to move/copy
+        * memory, since the new pointer is guaranteed to be the same as the
+        * old one.  The new allocation can fail, if the new size is too big.
+        */
+       vb2_workbuf_free(wb, oldsize);
+       return vb2_workbuf_alloc(wb, newsize);
+}
+
+void vb2_workbuf_free(struct vb2_workbuf *wb, uint32_t size)
+{
+       /* Round up size to work buffer alignment */
+       size = wb_round_up(size);
+
+       wb->buf -= size;
+       wb->size += size;
+}
+
+ptrdiff_t vb2_offset_of(const void *base, const void *ptr)
+{
+       return (uintptr_t)ptr - (uintptr_t)base;
+}
diff --git a/kern/lib/crypto/2crc8.c b/kern/lib/crypto/2crc8.c
new file mode 100644 (file)
index 0000000..9df0a00
--- /dev/null
@@ -0,0 +1,29 @@
+/* Copyright (c) 2014 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.
+ */
+
+#include "2sysincludes.h"
+#include "2crc8.h"
+
+uint8_t vb2_crc8(const void *vptr, uint32_t size)
+{
+       const uint8_t *data = vptr;
+       unsigned crc = 0;
+       uint32_t i, j;
+
+       /*
+        * Calculate CRC-8 directly.  A table-based algorithm would be faster,
+        * but for only a few bytes it isn't worth the code size.
+        */
+       for (j = size; j; j--, data++) {
+               crc ^= (*data << 8);
+               for(i = 8; i; i--) {
+                       if (crc & 0x8000)
+                               crc ^= (0x1070 << 3);
+                       crc <<= 1;
+               }
+       }
+
+       return (uint8_t)(crc >> 8);
+}
diff --git a/kern/lib/crypto/2hmac.c b/kern/lib/crypto/2hmac.c
new file mode 100644 (file)
index 0000000..651ae57
--- /dev/null
@@ -0,0 +1,60 @@
+/* Copyright 2016 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.
+ */
+
+#include "2sysincludes.h"
+#include "2sha.h"
+#include "2hmac.h"
+
+int hmac(enum vb2_hash_algorithm alg,
+        const void *key, uint32_t key_size,
+        const void *msg, uint32_t msg_size,
+        uint8_t *mac, uint32_t mac_size)
+{
+       uint32_t block_size;
+       uint32_t digest_size;
+       uint8_t k[VB2_MAX_BLOCK_SIZE];
+       uint8_t o_pad[VB2_MAX_BLOCK_SIZE];
+       uint8_t i_pad[VB2_MAX_BLOCK_SIZE];
+       uint8_t b[VB2_MAX_DIGEST_SIZE];
+       struct vb2_digest_context dc;
+       int i;
+
+       if (!key | !msg | !mac)
+               return -1;
+
+       digest_size = vb2_digest_size(alg);
+       block_size = vb2_hash_block_size(alg);
+       if (!digest_size || !block_size)
+               return -1;
+
+       if (mac_size < digest_size)
+               return -1;
+
+       if (key_size > block_size) {
+               vb2_digest_buffer((uint8_t *)key, key_size, alg, k, block_size);
+               key_size = digest_size;
+       } else {
+               memcpy(k, key, key_size);
+       }
+       if (key_size < block_size)
+               memset(k + key_size, 0, block_size - key_size);
+
+       for (i = 0; i < block_size; i++) {
+               o_pad[i] = 0x5c ^ k[i];
+               i_pad[i] = 0x36 ^ k[i];
+       }
+
+       vb2_digest_init(&dc, alg);
+       vb2_digest_extend(&dc, i_pad, block_size);
+       vb2_digest_extend(&dc, msg, msg_size);
+       vb2_digest_finalize(&dc, b, digest_size);
+
+       vb2_digest_init(&dc, alg);
+       vb2_digest_extend(&dc, o_pad, block_size);
+       vb2_digest_extend(&dc, b, digest_size);
+       vb2_digest_finalize(&dc, mac, mac_size);
+
+       return 0;
+}
diff --git a/kern/lib/crypto/2misc.c b/kern/lib/crypto/2misc.c
new file mode 100644 (file)
index 0000000..a955f53
--- /dev/null
@@ -0,0 +1,408 @@
+/* Copyright (c) 2014 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.
+ *
+ * Misc functions which need access to vb2_context but are not public APIs
+ */
+
+#include "2sysincludes.h"
+#include "2api.h"
+#include "2common.h"
+#include "2misc.h"
+#include "2nvstorage.h"
+#include "2secdata.h"
+#include "2sha.h"
+#include "2rsa.h"
+
+int vb2_validate_gbb_signature(uint8_t *sig) {
+       const static uint8_t sig_xor[VB2_GBB_SIGNATURE_SIZE] =
+                       VB2_GBB_XOR_SIGNATURE;
+       int i;
+       for (i = 0; i < VB2_GBB_SIGNATURE_SIZE; i++) {
+               if (sig[i] != (sig_xor[i] ^ VB2_GBB_XOR_CHARS[i]))
+                       return VB2_ERROR_GBB_MAGIC;
+       }
+       return VB2_SUCCESS;
+}
+
+void vb2_workbuf_from_ctx(struct vb2_context *ctx, struct vb2_workbuf *wb)
+{
+       vb2_workbuf_init(wb, ctx->workbuf + ctx->workbuf_used,
+                        ctx->workbuf_size - ctx->workbuf_used);
+}
+
+int vb2_read_gbb_header(struct vb2_context *ctx, struct vb2_gbb_header *gbb)
+{
+       int rv;
+
+       /* Read the entire header */
+       rv = vb2ex_read_resource(ctx, VB2_RES_GBB, 0, gbb, sizeof(*gbb));
+       if (rv)
+               return rv;
+
+       /* Make sure it's really a GBB */
+       rv = vb2_validate_gbb_signature(gbb->signature);
+       if (rv)
+               return rv;
+
+       /* Check for compatible version */
+       if (gbb->major_version != VB2_GBB_MAJOR_VER)
+               return VB2_ERROR_GBB_VERSION;
+
+       /* Current code is not backwards-compatible to 1.1 headers or older */
+       if (gbb->minor_version < VB2_GBB_MINOR_VER)
+               return VB2_ERROR_GBB_TOO_OLD;
+
+       /*
+        * Header size should be at least as big as we expect.  It could be
+        * bigger, if the header has grown.
+        */
+       if (gbb->header_size < sizeof(*gbb))
+               return VB2_ERROR_GBB_HEADER_SIZE;
+
+       return VB2_SUCCESS;
+}
+
+void vb2_fail(struct vb2_context *ctx, uint8_t reason, uint8_t subcode)
+{
+       struct vb2_shared_data *sd = vb2_get_sd(ctx);
+
+       /* If NV data hasn't been initialized, initialize it now */
+       if (!(sd->status & VB2_SD_STATUS_NV_INIT))
+               vb2_nv_init(ctx);
+
+       /* See if we were far enough in the boot process to choose a slot */
+       if (sd->status & VB2_SD_STATUS_CHOSE_SLOT) {
+
+               /* Boot failed */
+               vb2_nv_set(ctx, VB2_NV_FW_RESULT, VB2_FW_RESULT_FAILURE);
+
+               /* Use up remaining tries */
+               vb2_nv_set(ctx, VB2_NV_TRY_COUNT, 0);
+
+               /*
+                * Try the other slot next time.  We'll alternate
+                * between slots, which may help if one or both slots is
+                * flaky.
+                */
+               vb2_nv_set(ctx, VB2_NV_TRY_NEXT, 1 - sd->fw_slot);
+
+               /*
+                * If we didn't try the other slot last boot, or we tried it
+                * and it didn't fail, try it next boot.
+                */
+               if (sd->last_fw_slot != 1 - sd->fw_slot ||
+                   sd->last_fw_result != VB2_FW_RESULT_FAILURE)
+                       return;
+       }
+
+       /*
+        * If we're still here, we failed before choosing a slot, or both
+        * this slot and the other slot failed in successive boots.  So we
+        * need to go to recovery.
+        *
+        * Set a recovery reason and subcode only if they're not already set.
+        * If recovery is already requested, it's a more specific error code
+        * than later code is providing and we shouldn't overwrite it.
+        */
+       VB2_DEBUG("Need recovery, reason: %#x / %#x\n", reason, subcode);
+       if (!vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST)) {
+               vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, reason);
+               vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, subcode);
+       }
+}
+
+int vb2_init_context(struct vb2_context *ctx)
+{
+       struct vb2_shared_data *sd = vb2_get_sd(ctx);
+
+       /* Don't do anything if the context has already been initialized */
+       if (ctx->workbuf_used)
+               return VB2_SUCCESS;
+
+       /*
+        * Workbuf had better be big enough for our shared data struct and
+        * aligned.  Not much we can do if it isn't; we'll die before we can
+        * store a recovery reason.
+        */
+       if (ctx->workbuf_size < sizeof(*sd))
+               return VB2_ERROR_INITCTX_WORKBUF_SMALL;
+       if (!vb2_aligned(ctx->workbuf, VB2_WORKBUF_ALIGN))
+               return VB2_ERROR_INITCTX_WORKBUF_ALIGN;
+
+       /* Initialize the shared data at the start of the work buffer */
+       memset(sd, 0, sizeof(*sd));
+       ctx->workbuf_used = sizeof(*sd);
+       return VB2_SUCCESS;
+}
+
+void vb2_check_recovery(struct vb2_context *ctx)
+{
+       struct vb2_shared_data *sd = vb2_get_sd(ctx);
+       uint32_t reason = vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST);
+       uint32_t subcode = vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE);
+
+       VB2_DEBUG("Recovery reason from previous boot: %#x / %#x\n",
+                 reason, subcode);
+
+       /*
+        * Sets the current recovery request, unless there's already been a
+        * failure earlier in the boot process.
+        */
+       if (!sd->recovery_reason)
+               sd->recovery_reason = reason;
+
+       /* Clear request and subcode so we don't get stuck in recovery mode */
+       vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, VB2_RECOVERY_NOT_REQUESTED);
+       vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, VB2_RECOVERY_NOT_REQUESTED);
+
+       if (ctx->flags & VB2_CONTEXT_FORCE_RECOVERY_MODE) {
+               VB2_DEBUG("Recovery was requested manually\n");
+               if (subcode && !sd->recovery_reason)
+                       /*
+                        * Recovery was requested at 'broken' screen.
+                        * Promote subcode to reason.
+                        */
+                       sd->recovery_reason = subcode;
+               else
+                       /* Recovery was forced. Override recovery reason */
+                       sd->recovery_reason = VB2_RECOVERY_RO_MANUAL;
+               sd->flags |= VB2_SD_FLAG_MANUAL_RECOVERY;
+       }
+
+       /* If recovery reason is non-zero, tell caller we need recovery mode */
+       if (sd->recovery_reason) {
+               ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
+               VB2_DEBUG("We have a recovery request: %#x / %#x\n",
+                         sd->recovery_reason,
+                         vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE));
+       }
+}
+
+int vb2_fw_parse_gbb(struct vb2_context *ctx)
+{
+       struct vb2_shared_data *sd = vb2_get_sd(ctx);
+       struct vb2_gbb_header *gbb;
+       struct vb2_workbuf wb;
+       int rv;
+
+       vb2_workbuf_from_ctx(ctx, &wb);
+
+       /* Read GBB into next chunk of work buffer */
+       gbb = vb2_workbuf_alloc(&wb, sizeof(*gbb));
+       if (!gbb)
+               return VB2_ERROR_GBB_WORKBUF;
+
+       rv = vb2_read_gbb_header(ctx, gbb);
+       if (rv)
+               return rv;
+
+       /* Extract the only things we care about at firmware time */
+       sd->gbb_flags = gbb->flags;
+       sd->gbb_rootkey_offset = gbb->rootkey_offset;
+       sd->gbb_rootkey_size = gbb->rootkey_size;
+       memcpy(sd->gbb_hwid_digest, gbb->hwid_digest, VB2_GBB_HWID_DIGEST_SIZE);
+
+       return VB2_SUCCESS;
+}
+
+int vb2_check_dev_switch(struct vb2_context *ctx)
+{
+       struct vb2_shared_data *sd = vb2_get_sd(ctx);
+       uint32_t flags = 0;
+       uint32_t old_flags;
+       int is_dev = 0;
+       int use_secdata = 1;
+       int rv;
+
+       /* Read secure flags */
+       rv = vb2_secdata_get(ctx, VB2_SECDATA_FLAGS, &flags);
+       if (rv) {
+               if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) {
+                       /*
+                        * Recovery mode needs to check other ways developer
+                        * mode can be enabled, so don't give up yet.  But
+                        * since we can't read secdata, assume dev mode was
+                        * disabled.
+                        */
+                       use_secdata = 0;
+                       flags = 0;
+               } else {
+                       /* Normal mode simply fails */
+                       return rv;
+               }
+       }
+       old_flags = flags;
+
+       /* Handle dev disable request */
+       if (use_secdata && vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST)) {
+               flags &= ~VB2_SECDATA_FLAG_DEV_MODE;
+
+               /* Clear the request */
+               vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 0);
+       }
+
+       /*
+        * Check if we've been asked by the caller to disable dev mode.  Note
+        * that hardware switch and GBB flag will take precedence over this.
+        */
+       if (ctx->flags & VB2_DISABLE_DEVELOPER_MODE)
+               flags &= ~VB2_SECDATA_FLAG_DEV_MODE;
+
+       /* Check virtual dev switch */
+       if (flags & VB2_SECDATA_FLAG_DEV_MODE)
+               is_dev = 1;
+
+       /* Handle forcing dev mode via physical switch */
+       if (ctx->flags & VB2_CONTEXT_FORCE_DEVELOPER_MODE)
+               is_dev = 1;
+
+       /* Check if GBB is forcing dev mode */
+       if (sd->gbb_flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON)
+               is_dev = 1;
+
+       /* Handle whichever mode we end up in */
+       if (is_dev) {
+               /* Developer mode */
+               sd->flags |= VB2_SD_DEV_MODE_ENABLED;
+               ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
+
+               flags |= VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER;
+       } else {
+               /* Normal mode */
+               flags &= ~VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER;
+
+               /*
+                * Disable dev_boot_* flags.  This ensures they will be
+                * initially disabled if the user later transitions back into
+                * developer mode.
+                */
+               vb2_nv_set(ctx, VB2_NV_DEV_BOOT_USB, 0);
+               vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 0);
+               vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 0);
+               vb2_nv_set(ctx, VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP, 0);
+               vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, 0);
+               vb2_nv_set(ctx, VB2_NV_FASTBOOT_UNLOCK_IN_FW, 0);
+       }
+
+       if (ctx->flags & VB2_CONTEXT_FORCE_WIPEOUT_MODE)
+               vb2_nv_set(ctx, VB2_NV_REQ_WIPEOUT, 1);
+
+       if (flags != old_flags) {
+               /*
+                * Just changed dev mode state.  Clear TPM owner.  This must be
+                * done here instead of simply passing a flag to
+                * vb2_check_tpm_clear(), because we don't want to update
+                * last_boot_developer and then fail to clear the TPM owner.
+                *
+                * Note that we do this even if we couldn't read secdata, since
+                * the TPM owner and secdata may be independent, and we want
+                * the owner to be cleared if *this boot* is different than the
+                * last one (perhaps due to GBB or hardware override).
+                */
+               rv = vb2ex_tpm_clear_owner(ctx);
+               if (use_secdata) {
+                       /* Check for failure to clear owner */
+                       if (rv) {
+                               /*
+                                * Note that this truncates rv to 8 bit.  Which
+                                * is not as useful as the full error code, but
+                                * we don't have NVRAM space to store the full
+                                * 32-bit code.
+                                */
+                               vb2_fail(ctx, VB2_RECOVERY_TPM_CLEAR_OWNER, rv);
+                               return rv;
+                       }
+
+                       /* Save new flags */
+                       rv = vb2_secdata_set(ctx, VB2_SECDATA_FLAGS, flags);
+                       if (rv)
+                               return rv;
+               }
+       }
+
+       return VB2_SUCCESS;
+}
+
+int vb2_check_tpm_clear(struct vb2_context *ctx)
+{
+       int rv;
+
+       /* Check if we've been asked to clear the owner */
+       if (!vb2_nv_get(ctx, VB2_NV_CLEAR_TPM_OWNER_REQUEST))
+               return VB2_SUCCESS;  /* No need to clear */
+
+       /* Request applies one time only */
+       vb2_nv_set(ctx, VB2_NV_CLEAR_TPM_OWNER_REQUEST, 0);
+
+       /* Try clearing */
+       rv = vb2ex_tpm_clear_owner(ctx);
+       if (rv) {
+               /*
+                * Note that this truncates rv to 8 bit.  Which is not as
+                * useful as the full error code, but we don't have NVRAM space
+                * to store the full 32-bit code.
+                */
+               vb2_fail(ctx, VB2_RECOVERY_TPM_CLEAR_OWNER, rv);
+               return rv;
+       }
+
+       /* Clear successful */
+       vb2_nv_set(ctx, VB2_NV_CLEAR_TPM_OWNER_DONE, 1);
+       return VB2_SUCCESS;
+}
+
+int vb2_select_fw_slot(struct vb2_context *ctx)
+{
+       struct vb2_shared_data *sd = vb2_get_sd(ctx);
+       uint32_t tries;
+
+       /* Get result of last boot */
+       sd->last_fw_slot = vb2_nv_get(ctx, VB2_NV_FW_TRIED);
+       sd->last_fw_result = vb2_nv_get(ctx, VB2_NV_FW_RESULT);
+
+       /* Save to the previous result fields in NV storage */
+       vb2_nv_set(ctx, VB2_NV_FW_PREV_TRIED, sd->last_fw_slot);
+       vb2_nv_set(ctx, VB2_NV_FW_PREV_RESULT, sd->last_fw_result);
+
+       /* Clear result, since we don't know what will happen this boot */
+       vb2_nv_set(ctx, VB2_NV_FW_RESULT, VB2_FW_RESULT_UNKNOWN);
+
+       /* Get slot to try */
+       sd->fw_slot = vb2_nv_get(ctx, VB2_NV_TRY_NEXT);
+
+       /* Check try count */
+       tries = vb2_nv_get(ctx, VB2_NV_TRY_COUNT);
+
+       if (sd->last_fw_result == VB2_FW_RESULT_TRYING &&
+           sd->last_fw_slot == sd->fw_slot &&
+           tries == 0) {
+               /*
+                * We used up our last try on the previous boot, so fall back
+                * to the other slot this boot.
+                */
+               sd->fw_slot = 1 - sd->fw_slot;
+               vb2_nv_set(ctx, VB2_NV_TRY_NEXT, sd->fw_slot);
+       }
+
+       if (tries > 0) {
+               /* Still trying this firmware */
+               vb2_nv_set(ctx, VB2_NV_FW_RESULT, VB2_FW_RESULT_TRYING);
+
+               /* Decrement non-zero try count, unless told not to */
+               if (!(ctx->flags & VB2_CONTEXT_NOFAIL_BOOT))
+                       vb2_nv_set(ctx, VB2_NV_TRY_COUNT, tries - 1);
+       }
+
+       /* Store the slot we're trying */
+       vb2_nv_set(ctx, VB2_NV_FW_TRIED, sd->fw_slot);
+
+       /* Set context flag if we're using slot B */
+       if (sd->fw_slot)
+               ctx->flags |= VB2_CONTEXT_FW_SLOT_B;
+
+       /* Set status flag */
+       sd->status |= VB2_SD_STATUS_CHOSE_SLOT;
+
+       return VB2_SUCCESS;
+}
diff --git a/kern/lib/crypto/2nvstorage.c b/kern/lib/crypto/2nvstorage.c
new file mode 100644 (file)
index 0000000..b40bbe7
--- /dev/null
@@ -0,0 +1,370 @@
+/* Copyright (c) 2014 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.
+ */
+
+/* Non-volatile storage routines */
+
+#include "2sysincludes.h"
+#include "2common.h"
+#include "2crc8.h"
+#include "2misc.h"
+#include "2nvstorage.h"
+#include "2nvstorage_fields.h"
+
+static void vb2_nv_regen_crc(struct vb2_context *ctx)
+{
+       ctx->nvdata[VB2_NV_OFFS_CRC] = vb2_crc8(ctx->nvdata, VB2_NV_OFFS_CRC);
+       ctx->flags |= VB2_CONTEXT_NVDATA_CHANGED;
+}
+
+/**
+ * Check the CRC of the non-volatile storage context.
+ *
+ * Use this if reading from non-volatile storage may be flaky, and you want to
+ * retry reading it several times.
+ *
+ * This may be called before vb2_context_init().
+ *
+ * @param ctx          Context pointer
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2_nv_check_crc(const struct vb2_context *ctx)
+{
+       const uint8_t *p = ctx->nvdata;
+
+       /* Check header */
+       if (VB2_NV_HEADER_SIGNATURE !=
+           (p[VB2_NV_OFFS_HEADER] & VB2_NV_HEADER_MASK))
+               return VB2_ERROR_NV_HEADER;
+
+       /* Check CRC */
+       if (vb2_crc8(p, VB2_NV_OFFS_CRC) != p[VB2_NV_OFFS_CRC])
+               return VB2_ERROR_NV_CRC;
+
+       return VB2_SUCCESS;
+}
+
+void vb2_nv_init(struct vb2_context *ctx)
+{
+       struct vb2_shared_data *sd = vb2_get_sd(ctx);
+       uint8_t *p = ctx->nvdata;
+
+       /* Check data for consistency */
+       if (vb2_nv_check_crc(ctx) != VB2_SUCCESS) {
+               /* Data is inconsistent (bad CRC or header); reset defaults */
+               memset(p, 0, VB2_NVDATA_SIZE);
+               p[VB2_NV_OFFS_HEADER] = (VB2_NV_HEADER_SIGNATURE |
+                                        VB2_NV_HEADER_FW_SETTINGS_RESET |
+                                        VB2_NV_HEADER_KERNEL_SETTINGS_RESET);
+
+               /* Regenerate CRC */
+               vb2_nv_regen_crc(ctx);
+
+               /* Set status flag */
+               sd->status |= VB2_SD_STATUS_NV_REINIT;
+               /* TODO: unit test for status flag being set */
+       }
+
+       sd->status |= VB2_SD_STATUS_NV_INIT;
+}
+
+/* Macro for vb2_nv_get() single-bit settings to reduce duplicate code. */
+#define GETBIT(offs, mask) (p[offs] & mask ? 1 : 0)
+
+uint32_t vb2_nv_get(struct vb2_context *ctx, enum vb2_nv_param param)
+{
+       const uint8_t *p = ctx->nvdata;
+
+       /*
+        * TODO: We could reduce the binary size for this code by #ifdef'ing
+        * out the params not used by firmware verification.
+        */
+       switch (param) {
+       case VB2_NV_FIRMWARE_SETTINGS_RESET:
+               return GETBIT(VB2_NV_OFFS_HEADER,
+                             VB2_NV_HEADER_FW_SETTINGS_RESET);
+
+       case VB2_NV_KERNEL_SETTINGS_RESET:
+               return GETBIT(VB2_NV_OFFS_HEADER,
+                             VB2_NV_HEADER_KERNEL_SETTINGS_RESET);
+
+       case VB2_NV_DEBUG_RESET_MODE:
+               return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DEBUG_RESET);
+
+       case VB2_NV_TRY_NEXT:
+               return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRY_NEXT);
+
+       case VB2_NV_TRY_COUNT:
+               return p[VB2_NV_OFFS_BOOT] & VB2_NV_BOOT_TRY_COUNT_MASK;
+
+       case VB2_NV_FW_TRIED:
+               return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRIED);
+
+       case VB2_NV_FW_RESULT:
+               return p[VB2_NV_OFFS_BOOT2] & VB2_NV_BOOT2_RESULT_MASK;
+
+       case VB2_NV_FW_PREV_TRIED:
+               return GETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_PREV_TRIED);
+
+       case VB2_NV_FW_PREV_RESULT:
+               return (p[VB2_NV_OFFS_BOOT2] & VB2_NV_BOOT2_PREV_RESULT_MASK)
+                       >> VB2_NV_BOOT2_PREV_RESULT_SHIFT;
+
+       case VB2_NV_RECOVERY_REQUEST:
+               return p[VB2_NV_OFFS_RECOVERY];
+
+       case VB2_NV_RECOVERY_SUBCODE:
+               return p[VB2_NV_OFFS_RECOVERY_SUBCODE];
+
+       case VB2_NV_LOCALIZATION_INDEX:
+               return p[VB2_NV_OFFS_LOCALIZATION];
+
+       case VB2_NV_KERNEL_FIELD:
+               return (p[VB2_NV_OFFS_KERNEL]
+                       | (p[VB2_NV_OFFS_KERNEL + 1] << 8)
+                       | (p[VB2_NV_OFFS_KERNEL + 2] << 16)
+                       | (p[VB2_NV_OFFS_KERNEL + 3] << 24));
+
+       case VB2_NV_DEV_BOOT_USB:
+               return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_USB);
+
+       case VB2_NV_DEV_BOOT_LEGACY:
+               return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_LEGACY);
+
+       case VB2_NV_DEV_BOOT_SIGNED_ONLY:
+               return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_SIGNED_ONLY);
+
+       case VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP:
+               return GETBIT(VB2_NV_OFFS_DEV,
+                             VB2_NV_DEV_FLAG_FASTBOOT_FULL_CAP);
+
+       case VB2_NV_DEV_DEFAULT_BOOT:
+               return (p[VB2_NV_OFFS_DEV] & VB2_NV_DEV_FLAG_DEFAULT_BOOT)
+                       >> VB2_NV_DEV_DEFAULT_BOOT_SHIFT;
+
+       case VB2_NV_DISABLE_DEV_REQUEST:
+               return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DISABLE_DEV);
+
+       case VB2_NV_OPROM_NEEDED:
+               return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_OPROM_NEEDED);
+
+       case VB2_NV_BACKUP_NVRAM_REQUEST:
+               return GETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_BACKUP_NVRAM);
+
+       case VB2_NV_CLEAR_TPM_OWNER_REQUEST:
+               return GETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_REQUEST);
+
+       case VB2_NV_CLEAR_TPM_OWNER_DONE:
+               return GETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_DONE);
+
+       case VB2_NV_TPM_REQUESTED_REBOOT:
+               return GETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_REBOOTED);
+
+       case VB2_NV_REQ_WIPEOUT:
+               return GETBIT(VB2_NV_OFFS_HEADER , VB2_NV_HEADER_WIPEOUT);
+
+       case VB2_NV_FASTBOOT_UNLOCK_IN_FW:
+               return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_UNLOCK_FASTBOOT);
+
+       case VB2_NV_BOOT_ON_AC_DETECT:
+               return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BOOT_ON_AC_DETECT);
+
+       case VB2_NV_TRY_RO_SYNC:
+               return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_TRY_RO_SYNC);
+
+       case VB2_NV_BATTERY_CUTOFF_REQUEST:
+               return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BATTERY_CUTOFF);
+       }
+
+       /*
+        * Put default return outside the switch() instead of in default:, so
+        * that adding a new param will cause a compiler warning.
+        */
+       return 0;
+}
+
+#undef GETBIT
+
+/* Macro for vb2_nv_set() single-bit settings to reduce duplicate code. */
+#define SETBIT(offs, mask)                                     \
+       { if (value) p[offs] |= mask; else p[offs] &= ~mask; }
+
+void vb2_nv_set(struct vb2_context *ctx,
+               enum vb2_nv_param param,
+               uint32_t value)
+{
+       uint8_t *p = ctx->nvdata;
+
+       /* If not changing the value, don't regenerate the CRC. */
+       if (vb2_nv_get(ctx, param) == value)
+               return;
+
+       /*
+        * TODO: We could reduce the binary size for this code by #ifdef'ing
+        * out the params not used by firmware verification.
+        */
+       switch (param) {
+       case VB2_NV_FIRMWARE_SETTINGS_RESET:
+               SETBIT(VB2_NV_OFFS_HEADER, VB2_NV_HEADER_FW_SETTINGS_RESET);
+               break;
+
+       case VB2_NV_KERNEL_SETTINGS_RESET:
+               SETBIT(VB2_NV_OFFS_HEADER, VB2_NV_HEADER_KERNEL_SETTINGS_RESET);
+               break;
+
+       case VB2_NV_DEBUG_RESET_MODE:
+               SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DEBUG_RESET);
+               break;
+
+       case VB2_NV_TRY_NEXT:
+               SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRY_NEXT);
+               break;
+
+       case VB2_NV_TRY_COUNT:
+               /* Clip to valid range. */
+               if (value > VB2_NV_BOOT_TRY_COUNT_MASK)
+                       value = VB2_NV_BOOT_TRY_COUNT_MASK;
+
+               p[VB2_NV_OFFS_BOOT] &= ~VB2_NV_BOOT_TRY_COUNT_MASK;
+               p[VB2_NV_OFFS_BOOT] |= (uint8_t)value;
+               break;
+
+       case VB2_NV_FW_TRIED:
+               SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_TRIED);
+               break;
+
+       case VB2_NV_FW_RESULT:
+               /* Map out of range values to unknown */
+               if (value > VB2_NV_BOOT2_RESULT_MASK)
+                       value = VB2_FW_RESULT_UNKNOWN;
+
+               p[VB2_NV_OFFS_BOOT2] &= ~VB2_NV_BOOT2_RESULT_MASK;
+               p[VB2_NV_OFFS_BOOT2] |= (uint8_t)value;
+               break;
+
+       case VB2_NV_FW_PREV_TRIED:
+               SETBIT(VB2_NV_OFFS_BOOT2, VB2_NV_BOOT2_PREV_TRIED);
+               break;
+
+       case VB2_NV_FW_PREV_RESULT:
+               /* Map out of range values to unknown */
+               if (value > VB2_NV_BOOT2_RESULT_MASK)
+                       value = VB2_FW_RESULT_UNKNOWN;
+
+               p[VB2_NV_OFFS_BOOT2] &= ~VB2_NV_BOOT2_PREV_RESULT_MASK;
+               p[VB2_NV_OFFS_BOOT2] |=
+                       (uint8_t)(value << VB2_NV_BOOT2_PREV_RESULT_SHIFT);
+               break;
+
+       case VB2_NV_RECOVERY_REQUEST:
+               /*
+                * Map values outside the valid range to the legacy reason,
+                * since we can't determine if we're called from kernel or user
+                * mode.
+                */
+               if (value > 0xff)
+                       value = VB2_RECOVERY_LEGACY;
+               p[VB2_NV_OFFS_RECOVERY] = (uint8_t)value;
+               break;
+
+       case VB2_NV_RECOVERY_SUBCODE:
+               p[VB2_NV_OFFS_RECOVERY_SUBCODE] = (uint8_t)value;
+               break;
+
+       case VB2_NV_LOCALIZATION_INDEX:
+               /* Map values outside the valid range to the default index. */
+               if (value > 0xFF)
+                       value = 0;
+               p[VB2_NV_OFFS_LOCALIZATION] = (uint8_t)value;
+               break;
+
+       case VB2_NV_KERNEL_FIELD:
+               p[VB2_NV_OFFS_KERNEL] = (uint8_t)(value);
+               p[VB2_NV_OFFS_KERNEL + 1] = (uint8_t)(value >> 8);
+               p[VB2_NV_OFFS_KERNEL + 2] = (uint8_t)(value >> 16);
+               p[VB2_NV_OFFS_KERNEL + 3] = (uint8_t)(value >> 24);
+               break;
+
+       case VB2_NV_DEV_BOOT_USB:
+               SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_USB);
+               break;
+
+       case VB2_NV_DEV_BOOT_LEGACY:
+               SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_LEGACY);
+               break;
+
+       case VB2_NV_DEV_BOOT_SIGNED_ONLY:
+               SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_SIGNED_ONLY);
+               break;
+
+       case VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP:
+               SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_FASTBOOT_FULL_CAP);
+               break;
+
+       case VB2_NV_DEV_DEFAULT_BOOT:
+               /* Map out of range values to disk */
+               if (value > (VB2_NV_DEV_FLAG_DEFAULT_BOOT >>
+                            VB2_NV_DEV_DEFAULT_BOOT_SHIFT))
+                       value = VB2_DEV_DEFAULT_BOOT_DISK;
+
+               p[VB2_NV_OFFS_DEV] &= ~VB2_NV_DEV_FLAG_DEFAULT_BOOT;
+               p[VB2_NV_OFFS_DEV] |=
+                       (uint8_t)(value << VB2_NV_DEV_DEFAULT_BOOT_SHIFT);
+               break;
+
+       case VB2_NV_DISABLE_DEV_REQUEST:
+               SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_DISABLE_DEV);
+               break;
+
+       case VB2_NV_OPROM_NEEDED:
+               SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_OPROM_NEEDED);
+               break;
+
+       case VB2_NV_BACKUP_NVRAM_REQUEST:
+               SETBIT(VB2_NV_OFFS_BOOT, VB2_NV_BOOT_BACKUP_NVRAM);
+               break;
+
+       case VB2_NV_CLEAR_TPM_OWNER_REQUEST:
+               SETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_REQUEST);
+               break;
+
+       case VB2_NV_CLEAR_TPM_OWNER_DONE:
+               SETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_CLEAR_OWNER_DONE);
+               break;
+
+       case VB2_NV_TPM_REQUESTED_REBOOT:
+               SETBIT(VB2_NV_OFFS_TPM, VB2_NV_TPM_REBOOTED);
+               break;
+
+       case VB2_NV_REQ_WIPEOUT:
+               SETBIT(VB2_NV_OFFS_HEADER , VB2_NV_HEADER_WIPEOUT);
+               break;
+
+       case VB2_NV_FASTBOOT_UNLOCK_IN_FW:
+               SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_UNLOCK_FASTBOOT);
+               break;
+
+       case VB2_NV_BOOT_ON_AC_DETECT:
+               SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BOOT_ON_AC_DETECT);
+               break;
+
+       case VB2_NV_TRY_RO_SYNC:
+               SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_TRY_RO_SYNC);
+               break;
+
+       case VB2_NV_BATTERY_CUTOFF_REQUEST:
+               SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BATTERY_CUTOFF);
+               break;
+       }
+
+       /*
+        * Note there is no default case.  This causes a compiler warning if
+        * a new param is added to the enum without adding support here.
+        */
+
+       /* Need to regenerate CRC, since the value changed. */
+       vb2_nv_regen_crc(ctx);
+}
+
+#undef SETBIT
diff --git a/kern/lib/crypto/2rsa.c b/kern/lib/crypto/2rsa.c
new file mode 100644 (file)
index 0000000..7862b13
--- /dev/null
@@ -0,0 +1,351 @@
+/* Copyright (c) 2014 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.
+ */
+
+/*
+ * Implementation of RSA signature verification which uses a pre-processed key
+ * for computation. The code extends Android's RSA verification code to support
+ * multiple RSA key lengths and hash digest algorithms.
+ */
+
+#include "2sysincludes.h"
+#include "2common.h"
+#include "2rsa.h"
+#include "2sha.h"
+
+/**
+ * a[] -= mod
+ */
+static void subM(const struct vb2_public_key *key, uint32_t *a)
+{
+       int64_t A = 0;
+       uint32_t i;
+       for (i = 0; i < key->arrsize; ++i) {
+               A += (uint64_t)a[i] - key->n[i];
+               a[i] = (uint32_t)A;
+               A >>= 32;
+       }
+}
+
+/**
+ * Return a[] >= mod
+ */
+int vb2_mont_ge(const struct vb2_public_key *key, uint32_t *a)
+{
+       uint32_t i;
+       for (i = key->arrsize; i;) {
+               --i;
+               if (a[i] < key->n[i])
+                       return 0;
+               if (a[i] > key->n[i])
+                       return 1;
+       }
+       return 1;  /* equal */
+}
+
+/**
+ * Montgomery c[] += a * b[] / R % mod
+ */
+static void montMulAdd(const struct vb2_public_key *key,
+                       uint32_t *c,
+                       const uint32_t a,
+                       const uint32_t *b)
+{
+       uint64_t A = (uint64_t)a * b[0] + c[0];
+       uint32_t d0 = (uint32_t)A * key->n0inv;
+       uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
+       uint32_t i;
+
+       for (i = 1; i < key->arrsize; ++i) {
+               A = (A >> 32) + (uint64_t)a * b[i] + c[i];
+               B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
+               c[i - 1] = (uint32_t)B;
+       }
+
+       A = (A >> 32) + (B >> 32);
+
+       c[i - 1] = (uint32_t)A;
+
+       if (A >> 32) {
+               subM(key, c);
+       }
+}
+
+/**
+ * Montgomery c[] = a[] * b[] / R % mod
+ */
+static void montMul(const struct vb2_public_key *key,
+                    uint32_t *c,
+                    const uint32_t *a,
+                    const uint32_t *b)
+{
+       uint32_t i;
+       for (i = 0; i < key->arrsize; ++i) {
+               c[i] = 0;
+       }
+       for (i = 0; i < key->arrsize; ++i) {
+               montMulAdd(key, c, a[i], b);
+       }
+}
+
+/**
+ * In-place public exponentiation. (65537}
+ *
+ * @param key          Key to use in signing
+ * @param inout                Input and output big-endian byte array
+ * @param workbuf32    Work buffer; caller must verify this is
+ *                     (3 * key->arrsize) elements long.
+ */
+static void modpowF4(const struct vb2_public_key *key, uint8_t *inout,
+                   uint32_t *workbuf32)
+{
+       uint32_t *a = workbuf32;
+       uint32_t *aR = a + key->arrsize;
+       uint32_t *aaR = aR + key->arrsize;
+       uint32_t *aaa = aaR;  /* Re-use location. */
+       int i;
+
+       /* Convert from big endian byte array to little endian word array. */
+       for (i = 0; i < (int)key->arrsize; ++i) {
+               uint32_t tmp =
+                       (inout[((key->arrsize - 1 - i) * 4) + 0] << 24) |
+                       (inout[((key->arrsize - 1 - i) * 4) + 1] << 16) |
+                       (inout[((key->arrsize - 1 - i) * 4) + 2] << 8) |
+                       (inout[((key->arrsize - 1 - i) * 4) + 3] << 0);
+               a[i] = tmp;
+       }
+
+       montMul(key, aR, a, key->rr);  /* aR = a * RR / R mod M   */
+       for (i = 0; i < 16; i+=2) {
+               montMul(key, aaR, aR, aR);  /* aaR = aR * aR / R mod M */
+               montMul(key, aR, aaR, aaR);  /* aR = aaR * aaR / R mod M */
+       }
+       montMul(key, aaa, aR, a);  /* aaa = aR * a / R mod M */
+
+
+       /* Make sure aaa < mod; aaa is at most 1x mod too large. */
+       if (vb2_mont_ge(key, aaa)) {
+               subM(key, aaa);
+       }
+
+       /* Convert to bigendian byte array */
+       for (i = (int)key->arrsize - 1; i >= 0; --i) {
+               uint32_t tmp = aaa[i];
+               *inout++ = (uint8_t)(tmp >> 24);
+               *inout++ = (uint8_t)(tmp >> 16);
+               *inout++ = (uint8_t)(tmp >>  8);
+               *inout++ = (uint8_t)(tmp >>  0);
+       }
+}
+
+
+static const uint8_t crypto_to_sig[] = {
+       VB2_SIG_RSA1024,
+       VB2_SIG_RSA1024,
+       VB2_SIG_RSA1024,
+       VB2_SIG_RSA2048,
+       VB2_SIG_RSA2048,
+       VB2_SIG_RSA2048,
+       VB2_SIG_RSA4096,
+       VB2_SIG_RSA4096,
+       VB2_SIG_RSA4096,
+       VB2_SIG_RSA8192,
+       VB2_SIG_RSA8192,
+       VB2_SIG_RSA8192,
+};
+
+/**
+ * Convert vb2_crypto_algorithm to vb2_signature_algorithm.
+ *
+ * @param algorithm    Crypto algorithm (vb2_crypto_algorithm)
+ *
+ * @return The signature algorithm for that crypto algorithm, or
+ * VB2_SIG_INVALID if the crypto algorithm or its corresponding signature
+ * algorithm is invalid or not supported.
+ */
+enum vb2_signature_algorithm vb2_crypto_to_signature(uint32_t algorithm)
+{
+       if (algorithm < ARRAY_SIZE(crypto_to_sig))
+               return crypto_to_sig[algorithm];
+       else
+               return VB2_SIG_INVALID;
+}
+
+uint32_t vb2_rsa_sig_size(enum vb2_signature_algorithm sig_alg)
+{
+       switch (sig_alg) {
+       case VB2_SIG_RSA1024:
+               return 1024 / 8;
+       case VB2_SIG_RSA2048:
+               return 2048 / 8;
+       case VB2_SIG_RSA4096:
+               return 4096 / 8;
+       case VB2_SIG_RSA8192:
+               return 8192 / 8;
+       default:
+               return 0;
+       }
+}
+
+uint32_t vb2_packed_key_size(enum vb2_signature_algorithm sig_alg)
+{
+       uint32_t sig_size = vb2_rsa_sig_size(sig_alg);
+
+       if (!sig_size)
+               return 0;
+
+       /*
+        * Total size needed by a RSAPublicKey buffer is =
+        *  2 * key_len bytes for the n and rr arrays
+        *  + sizeof len + sizeof n0inv.
+        */
+       return 2 * sig_size + 2 * sizeof(uint32_t);
+}
+
+/*
+ * PKCS 1.5 padding (from the RSA PKCS#1 v2.1 standard)
+ *
+ * Depending on the RSA key size and hash function, the padding is calculated
+ * as follows:
+ *
+ * 0x00 || 0x01 || PS || 0x00 || T
+ *
+ * T: DER Encoded DigestInfo value which depends on the hash function used.
+ *
+ * SHA-1:   (0x)30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14 || H.
+ * SHA-256: (0x)30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || H.
+ * SHA-512: (0x)30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40 || H.
+ *
+ * Length(T) = 35 octets for SHA-1
+ * Length(T) = 51 octets for SHA-256
+ * Length(T) = 83 octets for SHA-512
+ *
+ * PS: octet string consisting of {Length(RSA Key) - Length(T) - 3} 0xFF
+ */
+static const uint8_t sha1_tail[] = {
+       0x00,0x30,0x21,0x30,0x09,0x06,0x05,0x2b,
+       0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14
+};
+
+static const uint8_t sha256_tail[] = {
+       0x00,0x30,0x31,0x30,0x0d,0x06,0x09,0x60,
+       0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,
+       0x05,0x00,0x04,0x20
+};
+
+static const uint8_t sha512_tail[] = {
+       0x00,0x30,0x51,0x30,0x0d,0x06,0x09,0x60,
+       0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,
+       0x05,0x00,0x04,0x40
+};
+
+int vb2_check_padding(const uint8_t *sig, const struct vb2_public_key *key)
+{
+       /* Determine padding to use depending on the signature type */
+       uint32_t sig_size = vb2_rsa_sig_size(key->sig_alg);
+       uint32_t hash_size = vb2_digest_size(key->hash_alg);
+       uint32_t pad_size = sig_size - hash_size;
+       const uint8_t *tail;
+       uint32_t tail_size;
+       int result = 0;
+       int i;
+
+       if (!sig_size || !hash_size || hash_size > sig_size)
+               return VB2_ERROR_RSA_PADDING_SIZE;
+
+       switch (key->hash_alg) {
+       case VB2_HASH_SHA1:
+               tail = sha1_tail;
+               tail_size = sizeof(sha1_tail);
+               break;
+       case VB2_HASH_SHA256:
+               tail = sha256_tail;
+               tail_size = sizeof(sha256_tail);
+               break;
+       case VB2_HASH_SHA512:
+               tail = sha512_tail;
+               tail_size = sizeof(sha512_tail);
+               break;
+       default:
+               return VB2_ERROR_RSA_PADDING_ALGORITHM;
+       }
+
+       /* First 2 bytes are always 0x00 0x01 */
+       result |= *sig++ ^ 0x00;
+       result |= *sig++ ^ 0x01;
+
+       /* Then 0xff bytes until the tail */
+       for (i = 0; i < pad_size - tail_size - 2; i++)
+               result |= *sig++ ^ 0xff;
+
+       /*
+        * Then the tail.  Even though there are probably no timing issues
+        * here, we use vb2_safe_memcmp() just to be on the safe side.
+        */
+       result |= vb2_safe_memcmp(sig, tail, tail_size);
+
+       return result ? VB2_ERROR_RSA_PADDING : VB2_SUCCESS;
+}
+
+int vb2_rsa_verify_digest(const struct vb2_public_key *key,
+                         uint8_t *sig,
+                         const uint8_t *digest,
+                         const struct vb2_workbuf *wb)
+{
+       struct vb2_workbuf wblocal = *wb;
+       uint32_t *workbuf32;
+       uint32_t key_bytes;
+       int sig_size;
+       int pad_size;
+       int rv;
+
+       if (!key || !sig || !digest)
+               return VB2_ERROR_RSA_VERIFY_PARAM;
+
+       sig_size = vb2_rsa_sig_size(key->sig_alg);
+       if (!sig_size) {
+               VB2_DEBUG("Invalid signature type!\n");
+               return VB2_ERROR_RSA_VERIFY_ALGORITHM;
+       }
+
+       /* Signature length should be same as key length */
+       key_bytes = key->arrsize * sizeof(uint32_t);
+       if (key_bytes != sig_size) {
+               VB2_DEBUG("Signature is of incorrect length!\n");
+               return VB2_ERROR_RSA_VERIFY_SIG_LEN;
+       }
+
+       workbuf32 = vb2_workbuf_alloc(&wblocal, 3 * key_bytes);
+       if (!workbuf32) {
+               VB2_DEBUG("ERROR - vboot2 work buffer too small!\n");
+               return VB2_ERROR_RSA_VERIFY_WORKBUF;
+       }
+
+       modpowF4(key, sig, workbuf32);
+
+       vb2_workbuf_free(&wblocal, 3 * key_bytes);
+
+       /*
+        * Check padding.  Only fail immediately if the padding size is bad.
+        * Otherwise, continue on to check the digest to reduce the risk of
+        * timing based attacks.
+        */
+       rv = vb2_check_padding(sig, key);
+       if (rv == VB2_ERROR_RSA_PADDING_SIZE)
+               return rv;
+
+       /*
+        * Check digest.  Even though there are probably no timing issues here,
+        * use vb2_safe_memcmp() just to be on the safe side.  (That's also why
+        * we don't return before this check if the padding check failed.)
+        */
+       pad_size = sig_size - vb2_digest_size(key->hash_alg);
+       if (vb2_safe_memcmp(sig + pad_size, digest, key_bytes - pad_size)) {
+               VB2_DEBUG("Digest check failed!\n");
+               if (!rv)
+                       rv = VB2_ERROR_RSA_VERIFY_DIGEST;
+       }
+
+       return rv;
+}
diff --git a/kern/lib/crypto/2secdata.c b/kern/lib/crypto/2secdata.c
new file mode 100644 (file)
index 0000000..3281f7c
--- /dev/null
@@ -0,0 +1,126 @@
+/* Copyright (c) 2014 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.
+ *
+ * Secure storage APIs
+ */
+
+#include "2sysincludes.h"
+#include "2common.h"
+#include "2crc8.h"
+#include "2misc.h"
+#include "2secdata.h"
+
+int vb2_secdata_check_crc(const struct vb2_context *ctx)
+{
+       const struct vb2_secdata *sec =
+               (const struct vb2_secdata *)ctx->secdata;
+
+       /* Verify CRC */
+       if (sec->crc8 != vb2_crc8(sec, offsetof(struct vb2_secdata, crc8)))
+               return VB2_ERROR_SECDATA_CRC;
+
+       /* CRC(<000...00>) is 0, so check version as well (should never be 0) */
+       if (!sec->struct_version)
+               return VB2_ERROR_SECDATA_ZERO;
+
+       return VB2_SUCCESS;
+}
+
+int vb2_secdata_create(struct vb2_context *ctx)
+{
+       struct vb2_secdata *sec = (struct vb2_secdata *)ctx->secdata;
+
+       /* Clear the entire struct */
+       memset(sec, 0, sizeof(*sec));
+
+       /* Set to current version */
+       sec->struct_version = VB2_SECDATA_VERSION;
+
+       /* Calculate initial CRC */
+       sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdata, crc8));
+       ctx->flags |= VB2_CONTEXT_SECDATA_CHANGED;
+       return VB2_SUCCESS;
+}
+
+int vb2_secdata_init(struct vb2_context *ctx)
+{
+       struct vb2_shared_data *sd = vb2_get_sd(ctx);
+       int rv;
+
+       rv = vb2_secdata_check_crc(ctx);
+       if (rv)
+               return rv;
+
+       /* Set status flag */
+       sd->status |= VB2_SD_STATUS_SECDATA_INIT;
+       /* TODO: unit test for that */
+
+       /* Read this now to make sure crossystem has it even in rec mode. */
+       rv = vb2_secdata_get(ctx, VB2_SECDATA_VERSIONS,
+                            &sd->fw_version_secdata);
+       if (rv)
+               return rv;
+
+       return VB2_SUCCESS;
+}
+
+int vb2_secdata_get(struct vb2_context *ctx,
+                   enum vb2_secdata_param param,
+                   uint32_t *dest)
+{
+       struct vb2_secdata *sec = (struct vb2_secdata *)ctx->secdata;
+
+       if (!(vb2_get_sd(ctx)->status & VB2_SD_STATUS_SECDATA_INIT))
+               return VB2_ERROR_SECDATA_GET_UNINITIALIZED;
+
+       switch(param) {
+       case VB2_SECDATA_FLAGS:
+               *dest = sec->flags;
+               return VB2_SUCCESS;
+
+       case VB2_SECDATA_VERSIONS:
+               *dest = sec->fw_versions;
+               return VB2_SUCCESS;
+
+       default:
+               return VB2_ERROR_SECDATA_GET_PARAM;
+       }
+}
+
+int vb2_secdata_set(struct vb2_context *ctx,
+                   enum vb2_secdata_param param,
+                   uint32_t value)
+{
+       struct vb2_secdata *sec = (struct vb2_secdata *)ctx->secdata;
+       uint32_t now;
+
+       if (!(vb2_get_sd(ctx)->status & VB2_SD_STATUS_SECDATA_INIT))
+               return VB2_ERROR_SECDATA_SET_UNINITIALIZED;
+
+       /* If not changing the value, don't regenerate the CRC. */
+       if (vb2_secdata_get(ctx, param, &now) == VB2_SUCCESS && now == value)
+               return VB2_SUCCESS;
+
+       switch(param) {
+       case VB2_SECDATA_FLAGS:
+               /* Make sure flags is in valid range */
+               if (value > 0xff)
+                       return VB2_ERROR_SECDATA_SET_FLAGS;
+
+               sec->flags = value;
+               break;
+
+       case VB2_SECDATA_VERSIONS:
+               sec->fw_versions = value;
+               break;
+
+       default:
+               return VB2_ERROR_SECDATA_SET_PARAM;
+       }
+
+       /* Regenerate CRC */
+       sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdata, crc8));
+       ctx->flags |= VB2_CONTEXT_SECDATA_CHANGED;
+       return VB2_SUCCESS;
+}
diff --git a/kern/lib/crypto/2secdatak.c b/kern/lib/crypto/2secdatak.c
new file mode 100644 (file)
index 0000000..af11aef
--- /dev/null
@@ -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.
+ *
+ * Secure storage APIs - kernel version space
+ */
+
+#include "2sysincludes.h"
+#include "2common.h"
+#include "2crc8.h"
+#include "2misc.h"
+#include "2secdata.h"
+
+int vb2_secdatak_check_crc(const struct vb2_context *ctx)
+{
+       const struct vb2_secdatak *sec =
+               (const struct vb2_secdatak *)ctx->secdatak;
+
+       /* Verify CRC */
+       if (sec->crc8 != vb2_crc8(sec, offsetof(struct vb2_secdatak, crc8)))
+               return VB2_ERROR_SECDATAK_CRC;
+
+       return VB2_SUCCESS;
+}
+
+int vb2_secdatak_create(struct vb2_context *ctx)
+{
+       struct vb2_secdatak *sec = (struct vb2_secdatak *)ctx->secdatak;
+
+       /* Clear the entire struct */
+       memset(sec, 0, sizeof(*sec));
+
+       /* Set to current version */
+       sec->struct_version = VB2_SECDATAK_VERSION;
+
+       /* Set UID */
+       sec->uid = VB2_SECDATAK_UID;
+
+       /* Calculate initial CRC */
+       sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdatak, crc8));
+       ctx->flags |= VB2_CONTEXT_SECDATAK_CHANGED;
+       return VB2_SUCCESS;
+}
+
+int vb2_secdatak_init(struct vb2_context *ctx)
+{
+       struct vb2_secdatak *sec = (struct vb2_secdatak *)ctx->secdatak;
+       struct vb2_shared_data *sd = vb2_get_sd(ctx);
+       int rv;
+
+       rv = vb2_secdatak_check_crc(ctx);
+       if (rv)
+               return rv;
+
+       /* Make sure the UID is correct */
+       if (sec->uid != VB2_SECDATAK_UID)
+               return VB2_ERROR_SECDATAK_UID;
+
+       /* Set status flag */
+       sd->status |= VB2_SD_STATUS_SECDATAK_INIT;
+       /* TODO: unit test for that */
+
+       return VB2_SUCCESS;
+}
+
+int vb2_secdatak_get(struct vb2_context *ctx,
+                   enum vb2_secdatak_param param,
+                   uint32_t *dest)
+{
+       struct vb2_secdatak *sec = (struct vb2_secdatak *)ctx->secdatak;
+
+       if (!(vb2_get_sd(ctx)->status & VB2_SD_STATUS_SECDATAK_INIT))
+               return VB2_ERROR_SECDATAK_GET_UNINITIALIZED;
+
+       switch(param) {
+       case VB2_SECDATAK_VERSIONS:
+               *dest = sec->kernel_versions;
+               return VB2_SUCCESS;
+
+       default:
+               return VB2_ERROR_SECDATAK_GET_PARAM;
+       }
+}
+
+int vb2_secdatak_set(struct vb2_context *ctx,
+                   enum vb2_secdatak_param param,
+                   uint32_t value)
+{
+       struct vb2_secdatak *sec = (struct vb2_secdatak *)ctx->secdatak;
+       uint32_t now;
+
+       if (!(vb2_get_sd(ctx)->status & VB2_SD_STATUS_SECDATAK_INIT))
+               return VB2_ERROR_SECDATAK_SET_UNINITIALIZED;
+
+       /* If not changing the value, don't regenerate the CRC. */
+       if (vb2_secdatak_get(ctx, param, &now) == VB2_SUCCESS && now == value)
+               return VB2_SUCCESS;
+
+       switch(param) {
+       case VB2_SECDATAK_VERSIONS:
+               sec->kernel_versions = value;
+               break;
+
+       default:
+               return VB2_ERROR_SECDATAK_SET_PARAM;
+       }
+
+       /* Regenerate CRC */
+       sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdatak, crc8));
+       ctx->flags |= VB2_CONTEXT_SECDATAK_CHANGED;
+       return VB2_SUCCESS;
+}
diff --git a/kern/lib/crypto/2sha1.c b/kern/lib/crypto/2sha1.c
new file mode 100644 (file)
index 0000000..41c8317
--- /dev/null
@@ -0,0 +1,292 @@
+/* Copyright (c) 2014 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.
+ *
+ * SHA-1 implementation largely based on libmincrypt in the the Android
+ * Open Source Project (platorm/system/core.git/libmincrypt/sha.c
+ */
+
+#include "2sysincludes.h"
+#include "2common.h"
+#include "2sha.h"
+
+/*
+ * Some machines lack byteswap.h and endian.h. These have to use the
+ * slower code, even if they're little-endian.
+ */
+
+#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
+
+/*
+ * This version is about 28% faster than the generic version below,
+ * but assumes little-endianness.
+ */
+static uint32_t ror27(uint32_t val)
+{
+       return (val >> 27) | (val << 5);
+}
+
+static uint32_t ror2(uint32_t val)
+{
+       return (val >> 2) | (val << 30);
+}
+
+static uint32_t ror31(uint32_t val)
+{
+       return (val >> 31) | (val << 1);
+}
+
+static void sha1_transform(struct vb2_sha1_context *ctx)
+{
+       /* Note that this array uses 80*4=320 bytes of stack */
+       uint32_t W[80];
+       register uint32_t A, B, C, D, E;
+       int t;
+
+       A = ctx->state[0];
+       B = ctx->state[1];
+       C = ctx->state[2];
+       D = ctx->state[3];
+       E = ctx->state[4];
+
+#define SHA_F1(A,B,C,D,E,t)                            \
+       E += ror27(A) +                                 \
+               (W[t] = bswap_32(ctx->buf.w[t])) +      \
+               (D^(B&(C^D))) + 0x5A827999;             \
+       B = ror2(B);
+
+       for (t = 0; t < 15; t += 5) {
+               SHA_F1(A,B,C,D,E,t + 0);
+               SHA_F1(E,A,B,C,D,t + 1);
+               SHA_F1(D,E,A,B,C,t + 2);
+               SHA_F1(C,D,E,A,B,t + 3);
+               SHA_F1(B,C,D,E,A,t + 4);
+       }
+       SHA_F1(A,B,C,D,E,t + 0);  /* 16th one, t == 15 */
+
+#undef SHA_F1
+
+#define SHA_F1(A,B,C,D,E,t)                                            \
+       E += ror27(A) +                                                 \
+               (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) +   \
+               (D^(B&(C^D))) + 0x5A827999;                             \
+       B = ror2(B);
+
+       SHA_F1(E,A,B,C,D,t + 1);
+       SHA_F1(D,E,A,B,C,t + 2);
+       SHA_F1(C,D,E,A,B,t + 3);
+       SHA_F1(B,C,D,E,A,t + 4);
+
+#undef SHA_F1
+
+#define SHA_F2(A,B,C,D,E,t)                                            \
+       E += ror27(A) +                                                 \
+               (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) +   \
+               (B^C^D) + 0x6ED9EBA1;                                   \
+       B = ror2(B);
+
+       for (t = 20; t < 40; t += 5) {
+               SHA_F2(A,B,C,D,E,t + 0);
+               SHA_F2(E,A,B,C,D,t + 1);
+               SHA_F2(D,E,A,B,C,t + 2);
+               SHA_F2(C,D,E,A,B,t + 3);
+               SHA_F2(B,C,D,E,A,t + 4);
+       }
+
+#undef SHA_F2
+
+#define SHA_F3(A,B,C,D,E,t)                                            \
+       E += ror27(A) +                                                 \
+               (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) +   \
+               ((B&C)|(D&(B|C))) + 0x8F1BBCDC;                         \
+       B = ror2(B);
+
+       for (; t < 60; t += 5) {
+               SHA_F3(A,B,C,D,E,t + 0);
+               SHA_F3(E,A,B,C,D,t + 1);
+               SHA_F3(D,E,A,B,C,t + 2);
+               SHA_F3(C,D,E,A,B,t + 3);
+               SHA_F3(B,C,D,E,A,t + 4);
+       }
+
+#undef SHA_F3
+
+#define SHA_F4(A,B,C,D,E,t)                                            \
+       E += ror27(A) +                                                 \
+               (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) +   \
+               (B^C^D) + 0xCA62C1D6;                                   \
+       B = ror2(B);
+
+       for (; t < 80; t += 5) {
+               SHA_F4(A,B,C,D,E,t + 0);
+               SHA_F4(E,A,B,C,D,t + 1);
+               SHA_F4(D,E,A,B,C,t + 2);
+               SHA_F4(C,D,E,A,B,t + 3);
+               SHA_F4(B,C,D,E,A,t + 4);
+       }
+
+#undef SHA_F4
+
+       ctx->state[0] += A;
+       ctx->state[1] += B;
+       ctx->state[2] += C;
+       ctx->state[3] += D;
+       ctx->state[4] += E;
+}
+
+void vb2_sha1_update(struct vb2_sha1_context *ctx,
+                    const uint8_t *data,
+                    uint32_t size)
+{
+       int i = ctx->count % sizeof(ctx->buf);
+       const uint8_t *p = (const uint8_t*)data;
+
+       ctx->count += size;
+
+       while (size > sizeof(ctx->buf) - i) {
+               memcpy(&ctx->buf.b[i], p, sizeof(ctx->buf) - i);
+               size -= sizeof(ctx->buf) - i;
+               p += sizeof(ctx->buf) - i;
+               sha1_transform(ctx);
+               i = 0;
+       }
+
+       while (size--) {
+               ctx->buf.b[i++] = *p++;
+               if (i == sizeof(ctx->buf)) {
+                       sha1_transform(ctx);
+                       i = 0;
+               }
+       }
+}
+
+uint8_t *vb2_sha1_finalize(struct vb2_sha1_context *ctx)
+{
+       uint32_t cnt = ctx->count * 8;
+       int i;
+
+       vb2_sha1_update(ctx, (uint8_t*)"\x80", 1);
+       while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
+               vb2_sha1_update(ctx, (uint8_t*)"\0", 1);
+       }
+
+       for (i = 0; i < 8; ++i) {
+               uint8_t tmp = cnt >> ((7 - i) * 8);
+               vb2_sha1_update(ctx, &tmp, 1);
+       }
+
+       for (i = 0; i < 5; i++) {
+               ctx->buf.w[i] = bswap_32(ctx->state[i]);
+       }
+
+       return ctx->buf.b;
+}
+
+#else   /* #if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN) */
+
+#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+static void sha1_transform(struct vb2_sha1_context *ctx)
+{
+       /* Note that this array uses 80*4=320 bytes of stack */
+       uint32_t W[80];
+       uint32_t A, B, C, D, E;
+       uint8_t *p = ctx->buf;
+       int t;
+
+       for(t = 0; t < 16; ++t) {
+               uint32_t tmp = *p++ << 24;
+               tmp |= *p++ << 16;
+               tmp |= *p++ << 8;
+               tmp |= *p++;
+               W[t] = tmp;
+       }
+
+       for(; t < 80; t++) {
+               W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+       }
+
+       A = ctx->state[0];
+       B = ctx->state[1];
+       C = ctx->state[2];
+       D = ctx->state[3];
+       E = ctx->state[4];
+
+       for(t = 0; t < 80; t++) {
+               uint32_t tmp = rol(5,A) + E + W[t];
+
+               if (t < 20)
+                       tmp += (D^(B&(C^D))) + 0x5A827999;
+               else if ( t < 40)
+                       tmp += (B^C^D) + 0x6ED9EBA1;
+               else if ( t < 60)
+                       tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC;
+               else
+                       tmp += (B^C^D) + 0xCA62C1D6;
+
+               E = D;
+               D = C;
+               C = rol(30,B);
+               B = A;
+               A = tmp;
+       }
+
+       ctx->state[0] += A;
+       ctx->state[1] += B;
+       ctx->state[2] += C;
+       ctx->state[3] += D;
+       ctx->state[4] += E;
+}
+
+void vb2_sha1_update(struct vb2_sha1_context *ctx,
+                    const uint8_t *data,
+                    uint32_t size)
+{
+       int i = (int)(ctx->count % sizeof(ctx->buf));
+       const uint8_t* p = (const uint8_t*) data;
+
+       ctx->count += size;
+
+       while (size--) {
+               ctx->buf[i++] = *p++;
+               if (i == sizeof(ctx->buf)) {
+                       sha1_transform(ctx);
+                       i = 0;
+               }
+       }
+}
+
+void vb2_sha1_finalize(struct vb2_sha1_context *ctx, uint8_t *digest)
+{
+       uint32_t cnt = ctx->count << 3;
+       int i;
+
+       vb2_sha1_update(ctx, (uint8_t*)"\x80", 1);
+       while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
+               vb2_sha1_update(ctx, (uint8_t*)"\0", 1);
+       }
+       for (i = 0; i < 8; ++i) {
+               uint8_t tmp = (uint8_t)((uint64_t)cnt >> ((7 - i) * 8));
+               vb2_sha1_update(ctx, &tmp, 1);
+       }
+
+       for (i = 0; i < 5; i++) {
+               uint32_t tmp = ctx->state[i];
+               *digest++ = (uint8_t)(tmp >> 24);
+               *digest++ = (uint8_t)(tmp >> 16);
+               *digest++ = (uint8_t)(tmp >> 8);
+               *digest++ = (uint8_t)(tmp >> 0);
+       }
+}
+
+#endif /* endianness */
+
+void vb2_sha1_init(struct vb2_sha1_context *ctx)
+{
+       ctx->state[0] = 0x67452301;
+       ctx->state[1] = 0xefcdab89;
+       ctx->state[2] = 0x98badcfe;
+       ctx->state[3] = 0x10325476;
+       ctx->state[4] = 0xc3d2e1f0;
+       ctx->count = 0;
+}
diff --git a/kern/lib/crypto/2sha256.c b/kern/lib/crypto/2sha256.c
new file mode 100644 (file)
index 0000000..d2cf672
--- /dev/null
@@ -0,0 +1,334 @@
+/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
+ * <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
+ */
+
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date:  04/30/2005
+ *
+ * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``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 PROJECT OR CONTRIBUTORS 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 "2sysincludes.h"
+#include "2common.h"
+#include "2sha.h"
+
+#define SHFR(x, n)    (x >> n)
+#define ROTR(x, n)   ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define ROTL(x, n)   ((x << n) | (x >> ((sizeof(x) << 3) - n)))
+#define CH(x, y, z)  ((x & y) ^ (~x & z))
+#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SHA256_F1(x) (ROTR(x,  2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define SHA256_F2(x) (ROTR(x,  6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define SHA256_F3(x) (ROTR(x,  7) ^ ROTR(x, 18) ^ SHFR(x,  3))
+#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
+
+#define UNPACK32(x, str)                               \
+       {                                               \
+               *((str) + 3) = (uint8_t) ((x)      );   \
+               *((str) + 2) = (uint8_t) ((x) >>  8);   \
+               *((str) + 1) = (uint8_t) ((x) >> 16);   \
+               *((str) + 0) = (uint8_t) ((x) >> 24);   \
+       }
+
+#define PACK32(str, x)                                         \
+       {                                                       \
+               *(x) =   ((uint32_t) *((str) + 3)      )        \
+                       | ((uint32_t) *((str) + 2) <<  8)       \
+                       | ((uint32_t) *((str) + 1) << 16)       \
+                       | ((uint32_t) *((str) + 0) << 24);      \
+       }
+
+/* Macros used for loops unrolling */
+
+#define SHA256_SCR(i)                                          \
+       {                                                       \
+               w[i] =  SHA256_F4(w[i -  2]) + w[i -  7]        \
+                       + SHA256_F3(w[i - 15]) + w[i - 16];     \
+       }
+
+#define SHA256_EXP(a, b, c, d, e, f, g, h, j)                          \
+       {                                                               \
+               t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
+                       + sha256_k[j] + w[j];                           \
+               t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]);       \
+               wv[d] += t1;                                            \
+               wv[h] = t1 + t2;                                        \
+       }
+
+static const uint32_t sha256_h0[8] = {
+       0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+       0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
+};
+
+static const uint32_t sha256_k[64] = {
+       0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+       0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+       0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+       0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+       0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+       0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+       0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+       0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+       0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+       0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+       0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+       0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+       0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+       0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+       0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+       0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+/* SHA-256 implementation */
+void vb2_sha256_init(struct vb2_sha256_context *ctx)
+{
+#ifndef UNROLL_LOOPS
+       int i;
+       for (i = 0; i < 8; i++) {
+               ctx->h[i] = sha256_h0[i];
+       }
+#else
+       ctx->h[0] = sha256_h0[0]; ctx->h[1] = sha256_h0[1];
+       ctx->h[2] = sha256_h0[2]; ctx->h[3] = sha256_h0[3];
+       ctx->h[4] = sha256_h0[4]; ctx->h[5] = sha256_h0[5];
+       ctx->h[6] = sha256_h0[6]; ctx->h[7] = sha256_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+       ctx->size = 0;
+       ctx->total_size = 0;
+}
+
+static void vb2_sha256_transform(struct vb2_sha256_context *ctx,
+                                const uint8_t *message,
+                                unsigned int block_nb)
+{
+       /* Note that these arrays use 72*4=288 bytes of stack */
+       uint32_t w[64];
+       uint32_t wv[8];
+       uint32_t t1, t2;
+       const unsigned char *sub_block;
+       int i;
+
+#ifndef UNROLL_LOOPS
+       int j;
+#endif
+
+       for (i = 0; i < (int) block_nb; i++) {
+               sub_block = message + (i << 6);
+
+#ifndef UNROLL_LOOPS
+               for (j = 0; j < 16; j++) {
+                       PACK32(&sub_block[j << 2], &w[j]);
+               }
+
+               for (j = 16; j < 64; j++) {
+                       SHA256_SCR(j);
+               }
+
+               for (j = 0; j < 8; j++) {
+                       wv[j] = ctx->h[j];
+               }
+
+               for (j = 0; j < 64; j++) {
+                       t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
+                               + sha256_k[j] + w[j];
+                       t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+                       wv[7] = wv[6];
+                       wv[6] = wv[5];
+                       wv[5] = wv[4];
+                       wv[4] = wv[3] + t1;
+                       wv[3] = wv[2];
+                       wv[2] = wv[1];
+                       wv[1] = wv[0];
+                       wv[0] = t1 + t2;
+               }
+
+               for (j = 0; j < 8; j++) {
+                       ctx->h[j] += wv[j];
+               }
+#else
+               PACK32(&sub_block[ 0], &w[ 0]); PACK32(&sub_block[ 4], &w[ 1]);
+               PACK32(&sub_block[ 8], &w[ 2]); PACK32(&sub_block[12], &w[ 3]);
+               PACK32(&sub_block[16], &w[ 4]); PACK32(&sub_block[20], &w[ 5]);
+               PACK32(&sub_block[24], &w[ 6]); PACK32(&sub_block[28], &w[ 7]);
+               PACK32(&sub_block[32], &w[ 8]); PACK32(&sub_block[36], &w[ 9]);
+               PACK32(&sub_block[40], &w[10]); PACK32(&sub_block[44], &w[11]);
+               PACK32(&sub_block[48], &w[12]); PACK32(&sub_block[52], &w[13]);
+               PACK32(&sub_block[56], &w[14]); PACK32(&sub_block[60], &w[15]);
+
+               SHA256_SCR(16); SHA256_SCR(17); SHA256_SCR(18); SHA256_SCR(19);
+               SHA256_SCR(20); SHA256_SCR(21); SHA256_SCR(22); SHA256_SCR(23);
+               SHA256_SCR(24); SHA256_SCR(25); SHA256_SCR(26); SHA256_SCR(27);
+               SHA256_SCR(28); SHA256_SCR(29); SHA256_SCR(30); SHA256_SCR(31);
+               SHA256_SCR(32); SHA256_SCR(33); SHA256_SCR(34); SHA256_SCR(35);
+               SHA256_SCR(36); SHA256_SCR(37); SHA256_SCR(38); SHA256_SCR(39);
+               SHA256_SCR(40); SHA256_SCR(41); SHA256_SCR(42); SHA256_SCR(43);
+               SHA256_SCR(44); SHA256_SCR(45); SHA256_SCR(46); SHA256_SCR(47);
+               SHA256_SCR(48); SHA256_SCR(49); SHA256_SCR(50); SHA256_SCR(51);
+               SHA256_SCR(52); SHA256_SCR(53); SHA256_SCR(54); SHA256_SCR(55);
+               SHA256_SCR(56); SHA256_SCR(57); SHA256_SCR(58); SHA256_SCR(59);
+               SHA256_SCR(60); SHA256_SCR(61); SHA256_SCR(62); SHA256_SCR(63);
+
+               wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
+               wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
+               wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
+               wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
+
+               SHA256_EXP(0,1,2,3,4,5,6,7, 0); SHA256_EXP(7,0,1,2,3,4,5,6, 1);
+               SHA256_EXP(6,7,0,1,2,3,4,5, 2); SHA256_EXP(5,6,7,0,1,2,3,4, 3);
+               SHA256_EXP(4,5,6,7,0,1,2,3, 4); SHA256_EXP(3,4,5,6,7,0,1,2, 5);
+               SHA256_EXP(2,3,4,5,6,7,0,1, 6); SHA256_EXP(1,2,3,4,5,6,7,0, 7);
+               SHA256_EXP(0,1,2,3,4,5,6,7, 8); SHA256_EXP(7,0,1,2,3,4,5,6, 9);
+               SHA256_EXP(6,7,0,1,2,3,4,5,10); SHA256_EXP(5,6,7,0,1,2,3,4,11);
+               SHA256_EXP(4,5,6,7,0,1,2,3,12); SHA256_EXP(3,4,5,6,7,0,1,2,13);
+               SHA256_EXP(2,3,4,5,6,7,0,1,14); SHA256_EXP(1,2,3,4,5,6,7,0,15);
+               SHA256_EXP(0,1,2,3,4,5,6,7,16); SHA256_EXP(7,0,1,2,3,4,5,6,17);
+               SHA256_EXP(6,7,0,1,2,3,4,5,18); SHA256_EXP(5,6,7,0,1,2,3,4,19);
+               SHA256_EXP(4,5,6,7,0,1,2,3,20); SHA256_EXP(3,4,5,6,7,0,1,2,21);
+               SHA256_EXP(2,3,4,5,6,7,0,1,22); SHA256_EXP(1,2,3,4,5,6,7,0,23);
+               SHA256_EXP(0,1,2,3,4,5,6,7,24); SHA256_EXP(7,0,1,2,3,4,5,6,25);
+               SHA256_EXP(6,7,0,1,2,3,4,5,26); SHA256_EXP(5,6,7,0,1,2,3,4,27);
+               SHA256_EXP(4,5,6,7,0,1,2,3,28); SHA256_EXP(3,4,5,6,7,0,1,2,29);
+               SHA256_EXP(2,3,4,5,6,7,0,1,30); SHA256_EXP(1,2,3,4,5,6,7,0,31);
+               SHA256_EXP(0,1,2,3,4,5,6,7,32); SHA256_EXP(7,0,1,2,3,4,5,6,33);
+               SHA256_EXP(6,7,0,1,2,3,4,5,34); SHA256_EXP(5,6,7,0,1,2,3,4,35);
+               SHA256_EXP(4,5,6,7,0,1,2,3,36); SHA256_EXP(3,4,5,6,7,0,1,2,37);
+               SHA256_EXP(2,3,4,5,6,7,0,1,38); SHA256_EXP(1,2,3,4,5,6,7,0,39);
+               SHA256_EXP(0,1,2,3,4,5,6,7,40); SHA256_EXP(7,0,1,2,3,4,5,6,41);
+               SHA256_EXP(6,7,0,1,2,3,4,5,42); SHA256_EXP(5,6,7,0,1,2,3,4,43);
+               SHA256_EXP(4,5,6,7,0,1,2,3,44); SHA256_EXP(3,4,5,6,7,0,1,2,45);
+               SHA256_EXP(2,3,4,5,6,7,0,1,46); SHA256_EXP(1,2,3,4,5,6,7,0,47);
+               SHA256_EXP(0,1,2,3,4,5,6,7,48); SHA256_EXP(7,0,1,2,3,4,5,6,49);
+               SHA256_EXP(6,7,0,1,2,3,4,5,50); SHA256_EXP(5,6,7,0,1,2,3,4,51);
+               SHA256_EXP(4,5,6,7,0,1,2,3,52); SHA256_EXP(3,4,5,6,7,0,1,2,53);
+               SHA256_EXP(2,3,4,5,6,7,0,1,54); SHA256_EXP(1,2,3,4,5,6,7,0,55);
+               SHA256_EXP(0,1,2,3,4,5,6,7,56); SHA256_EXP(7,0,1,2,3,4,5,6,57);
+               SHA256_EXP(6,7,0,1,2,3,4,5,58); SHA256_EXP(5,6,7,0,1,2,3,4,59);
+               SHA256_EXP(4,5,6,7,0,1,2,3,60); SHA256_EXP(3,4,5,6,7,0,1,2,61);
+               SHA256_EXP(2,3,4,5,6,7,0,1,62); SHA256_EXP(1,2,3,4,5,6,7,0,63);
+
+               ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
+               ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
+               ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
+               ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
+#endif /* !UNROLL_LOOPS */
+       }
+}
+
+void vb2_sha256_update(struct vb2_sha256_context *ctx,
+                      const uint8_t *data,
+                      uint32_t size)
+{
+       unsigned int block_nb;
+       unsigned int new_size, rem_size, tmp_size;
+       const uint8_t *shifted_data;
+
+       tmp_size = VB2_SHA256_BLOCK_SIZE - ctx->size;
+       rem_size = size < tmp_size ? size : tmp_size;
+
+       memcpy(&ctx->block[ctx->size], data, rem_size);
+
+       if (ctx->size + size < VB2_SHA256_BLOCK_SIZE) {
+               ctx->size += size;
+               return;
+       }
+
+       new_size = size - rem_size;
+       block_nb = new_size / VB2_SHA256_BLOCK_SIZE;
+
+       shifted_data = data + rem_size;
+
+       vb2_sha256_transform(ctx, ctx->block, 1);
+       vb2_sha256_transform(ctx, shifted_data, block_nb);
+
+       rem_size = new_size % VB2_SHA256_BLOCK_SIZE;
+
+       memcpy(ctx->block, &shifted_data[block_nb << 6],
+              rem_size);
+
+       ctx->size = rem_size;
+       ctx->total_size += (block_nb + 1) << 6;
+}
+
+void vb2_sha256_finalize(struct vb2_sha256_context *ctx, uint8_t *digest)
+{
+       unsigned int block_nb;
+       unsigned int pm_size;
+       unsigned int size_b;
+#ifndef UNROLL_LOOPS
+       int i;
+#endif
+
+       block_nb = (1 + ((VB2_SHA256_BLOCK_SIZE - 9)
+                        < (ctx->size % VB2_SHA256_BLOCK_SIZE)));
+
+       size_b = (ctx->total_size + ctx->size) << 3;
+       pm_size = block_nb << 6;
+
+       memset(ctx->block + ctx->size, 0, pm_size - ctx->size);
+       ctx->block[ctx->size] = 0x80;
+       UNPACK32(size_b, ctx->block + pm_size - 4);
+
+       vb2_sha256_transform(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+       for (i = 0 ; i < 8; i++) {
+               UNPACK32(ctx->h[i], &digest[i << 2]);
+       }
+#else
+       UNPACK32(ctx->h[0], &digest[ 0]);
+       UNPACK32(ctx->h[1], &digest[ 4]);
+       UNPACK32(ctx->h[2], &digest[ 8]);
+       UNPACK32(ctx->h[3], &digest[12]);
+       UNPACK32(ctx->h[4], &digest[16]);
+       UNPACK32(ctx->h[5], &digest[20]);
+       UNPACK32(ctx->h[6], &digest[24]);
+       UNPACK32(ctx->h[7], &digest[28]);
+#endif /* !UNROLL_LOOPS */
+}
+
+void vb2_sha256_extend(const uint8_t *from, const uint8_t *by, uint8_t *to)
+{
+       struct vb2_sha256_context dc;
+       int i;
+
+       for (i = 0; i < 8; i++) {
+                PACK32(from, &dc.h[i]);
+                from += 4;
+       }
+
+       vb2_sha256_transform(&dc, by, 1);
+
+       for (i = 0; i < 8; i++) {
+                UNPACK32(dc.h[i], to);
+                to += 4;
+       }
+}
diff --git a/kern/lib/crypto/2sha512.c b/kern/lib/crypto/2sha512.c
new file mode 100644 (file)
index 0000000..fedc8b7
--- /dev/null
@@ -0,0 +1,346 @@
+/* SHA-256 and SHA-512 implementation based on code by Oliver Gay
+ * <olivier.gay@a3.epfl.ch> under a BSD-style license. See below.
+ */
+
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date:  04/30/2005
+ *
+ * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``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 PROJECT OR CONTRIBUTORS 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 "2sysincludes.h"
+#include "2common.h"
+#include "2sha.h"
+
+#define SHFR(x, n)    (x >> n)
+#define ROTR(x, n)   ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define ROTL(x, n)   ((x << n) | (x >> ((sizeof(x) << 3) - n)))
+#define CH(x, y, z)  ((x & y) ^ (~x & z))
+#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
+#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
+#define SHA512_F3(x) (ROTR(x,  1) ^ ROTR(x,  8) ^ SHFR(x,  7))
+#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x,  6))
+
+#define UNPACK32(x, str)                               \
+       {                                               \
+               *((str) + 3) = (uint8_t) ((x)      );   \
+               *((str) + 2) = (uint8_t) ((x) >>  8);   \
+               *((str) + 1) = (uint8_t) ((x) >> 16);   \
+               *((str) + 0) = (uint8_t) ((x) >> 24);   \
+       }
+
+#define UNPACK64(x, str)                                       \
+       {                                                       \
+               *((str) + 7) = (uint8_t) x;                     \
+               *((str) + 6) = (uint8_t) ((uint64_t)x >> 8);    \
+               *((str) + 5) = (uint8_t) ((uint64_t)x >> 16);   \
+               *((str) + 4) = (uint8_t) ((uint64_t)x >> 24);   \
+               *((str) + 3) = (uint8_t) ((uint64_t)x >> 32);   \
+               *((str) + 2) = (uint8_t) ((uint64_t)x >> 40);   \
+               *((str) + 1) = (uint8_t) ((uint64_t)x >> 48);   \
+               *((str) + 0) = (uint8_t) ((uint64_t)x >> 56);   \
+       }
+
+#define PACK64(str, x)                                         \
+       {                                                       \
+               *(x) =   ((uint64_t) *((str) + 7)      )        \
+                       | ((uint64_t) *((str) + 6) <<  8)       \
+                       | ((uint64_t) *((str) + 5) << 16)       \
+                       | ((uint64_t) *((str) + 4) << 24)       \
+                       | ((uint64_t) *((str) + 3) << 32)       \
+                       | ((uint64_t) *((str) + 2) << 40)       \
+                       | ((uint64_t) *((str) + 1) << 48)       \
+                       | ((uint64_t) *((str) + 0) << 56);      \
+       }
+
+/* Macros used for loops unrolling */
+
+#define SHA512_SCR(i)                                          \
+       {                                                       \
+               w[i] =  SHA512_F4(w[i -  2]) + w[i -  7]        \
+                       + SHA512_F3(w[i - 15]) + w[i - 16];     \
+       }
+
+#define SHA512_EXP(a, b, c, d, e, f, g ,h, j)                          \
+       {                                                               \
+               t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
+                       + sha512_k[j] + w[j];                           \
+               t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]);       \
+               wv[d] += t1;                                            \
+               wv[h] = t1 + t2;                                        \
+       }
+
+static const uint64_t sha512_h0[8] = {
+       0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
+       0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
+       0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+       0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+};
+
+static const uint64_t sha512_k[80] = {
+       0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+       0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+       0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+       0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+       0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+       0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+       0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+       0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+       0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+       0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+       0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+       0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+       0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+       0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+       0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+       0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+       0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+       0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+       0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+       0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+       0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+       0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+       0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+       0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+       0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+       0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+       0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+       0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+       0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+       0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+       0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+       0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+       0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+       0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+       0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+       0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+       0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+       0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+       0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+       0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+/* SHA-512 implementation */
+
+void vb2_sha512_init(struct vb2_sha512_context *ctx)
+{
+#ifdef UNROLL_LOOPS_SHA512
+       ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1];
+       ctx->h[2] = sha512_h0[2]; ctx->h[3] = sha512_h0[3];
+       ctx->h[4] = sha512_h0[4]; ctx->h[5] = sha512_h0[5];
+       ctx->h[6] = sha512_h0[6]; ctx->h[7] = sha512_h0[7];
+#else
+       int i;
+
+       for (i = 0; i < 8; i++)
+               ctx->h[i] = sha512_h0[i];
+#endif /* UNROLL_LOOPS_SHA512 */
+
+       ctx->size = 0;
+       ctx->total_size = 0;
+}
+
+static void vb2_sha512_transform(struct vb2_sha512_context *ctx,
+                            const uint8_t *message,
+                             unsigned int block_nb)
+{
+       /* Note that these arrays use 88*8=704 bytes of stack */
+       uint64_t w[80];
+       uint64_t wv[8];
+       uint64_t t1, t2;
+       const uint8_t *sub_block;
+       int i, j;
+
+       for (i = 0; i < (int) block_nb; i++) {
+               sub_block = message + (i << 7);
+
+#ifdef UNROLL_LOOPS_SHA512
+               PACK64(&sub_block[  0], &w[ 0]);
+               PACK64(&sub_block[  8], &w[ 1]);
+               PACK64(&sub_block[ 16], &w[ 2]);
+               PACK64(&sub_block[ 24], &w[ 3]);
+               PACK64(&sub_block[ 32], &w[ 4]);
+               PACK64(&sub_block[ 40], &w[ 5]);
+               PACK64(&sub_block[ 48], &w[ 6]);
+               PACK64(&sub_block[ 56], &w[ 7]);
+               PACK64(&sub_block[ 64], &w[ 8]);
+               PACK64(&sub_block[ 72], &w[ 9]);
+               PACK64(&sub_block[ 80], &w[10]);
+               PACK64(&sub_block[ 88], &w[11]);
+               PACK64(&sub_block[ 96], &w[12]);
+               PACK64(&sub_block[104], &w[13]);
+               PACK64(&sub_block[112], &w[14]);
+               PACK64(&sub_block[120], &w[15]);
+
+               SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19);
+               SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23);
+               SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27);
+               SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31);
+               SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35);
+               SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39);
+               SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43);
+               SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47);
+               SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51);
+               SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55);
+               SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59);
+               SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63);
+               SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67);
+               SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71);
+               SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75);
+               SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79);
+
+               wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
+               wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
+               wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
+               wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
+
+               j = 0;
+
+               do {
+                       SHA512_EXP(0,1,2,3,4,5,6,7,j); j++;
+                       SHA512_EXP(7,0,1,2,3,4,5,6,j); j++;
+                       SHA512_EXP(6,7,0,1,2,3,4,5,j); j++;
+                       SHA512_EXP(5,6,7,0,1,2,3,4,j); j++;
+                       SHA512_EXP(4,5,6,7,0,1,2,3,j); j++;
+                       SHA512_EXP(3,4,5,6,7,0,1,2,j); j++;
+                       SHA512_EXP(2,3,4,5,6,7,0,1,j); j++;
+                       SHA512_EXP(1,2,3,4,5,6,7,0,j); j++;
+               } while (j < 80);
+
+               ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
+               ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
+               ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
+               ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
+#else
+               for (j = 0; j < 16; j++) {
+                       PACK64(&sub_block[j << 3], &w[j]);
+               }
+
+               for (j = 16; j < 80; j++) {
+                       SHA512_SCR(j);
+               }
+
+               for (j = 0; j < 8; j++) {
+                       wv[j] = ctx->h[j];
+               }
+
+               for (j = 0; j < 80; j++) {
+                       t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
+                               + sha512_k[j] + w[j];
+                       t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+                       wv[7] = wv[6];
+                       wv[6] = wv[5];
+                       wv[5] = wv[4];
+                       wv[4] = wv[3] + t1;
+                       wv[3] = wv[2];
+                       wv[2] = wv[1];
+                       wv[1] = wv[0];
+                       wv[0] = t1 + t2;
+               }
+
+               for (j = 0; j < 8; j++)
+                       ctx->h[j] += wv[j];
+#endif /* UNROLL_LOOPS_SHA512 */
+       }
+}
+
+void vb2_sha512_update(struct vb2_sha512_context *ctx,
+                      const uint8_t *data,
+                      uint32_t size)
+{
+       unsigned int block_nb;
+       unsigned int new_size, rem_size, tmp_size;
+       const uint8_t *shifted_data;
+
+       tmp_size = VB2_SHA512_BLOCK_SIZE - ctx->size;
+       rem_size = size < tmp_size ? size : tmp_size;
+
+       memcpy(&ctx->block[ctx->size], data, rem_size);
+
+       if (ctx->size + size < VB2_SHA512_BLOCK_SIZE) {
+               ctx->size += size;
+               return;
+       }
+
+       new_size = size - rem_size;
+       block_nb = new_size / VB2_SHA512_BLOCK_SIZE;
+
+       shifted_data = data + rem_size;
+
+       vb2_sha512_transform(ctx, ctx->block, 1);
+       vb2_sha512_transform(ctx, shifted_data, block_nb);
+
+       rem_size = new_size % VB2_SHA512_BLOCK_SIZE;
+
+       memcpy(ctx->block, &shifted_data[block_nb << 7],
+              rem_size);
+
+       ctx->size = rem_size;
+       ctx->total_size += (block_nb + 1) << 7;
+}
+
+void vb2_sha512_finalize(struct vb2_sha512_context *ctx, uint8_t *digest)
+{
+       unsigned int block_nb;
+       unsigned int pm_size;
+       unsigned int size_b;
+
+#ifndef UNROLL_LOOPS_SHA512
+       int i;
+#endif
+
+       block_nb = 1 + ((VB2_SHA512_BLOCK_SIZE - 17)
+                       < (ctx->size % VB2_SHA512_BLOCK_SIZE));
+
+       size_b = (ctx->total_size + ctx->size) << 3;
+       pm_size = block_nb << 7;
+
+       memset(ctx->block + ctx->size, 0, pm_size - ctx->size);
+       ctx->block[ctx->size] = 0x80;
+       UNPACK32(size_b, ctx->block + pm_size - 4);
+
+       vb2_sha512_transform(ctx, ctx->block, block_nb);
+
+#ifdef UNROLL_LOOPS_SHA512
+       UNPACK64(ctx->h[0], &digest[ 0]);
+       UNPACK64(ctx->h[1], &digest[ 8]);
+       UNPACK64(ctx->h[2], &digest[16]);
+       UNPACK64(ctx->h[3], &digest[24]);
+       UNPACK64(ctx->h[4], &digest[32]);
+       UNPACK64(ctx->h[5], &digest[40]);
+       UNPACK64(ctx->h[6], &digest[48]);
+       UNPACK64(ctx->h[7], &digest[56]);
+#else
+       for (i = 0 ; i < 8; i++)
+               UNPACK64(ctx->h[i], &digest[i << 3]);
+#endif /* UNROLL_LOOPS_SHA512 */
+}
diff --git a/kern/lib/crypto/2sha_utility.c b/kern/lib/crypto/2sha_utility.c
new file mode 100644 (file)
index 0000000..dd74f29
--- /dev/null
@@ -0,0 +1,211 @@
+/* Copyright (c) 2014 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.
+ *
+ * Utility functions for message digest functions.
+ */
+
+#include "2sysincludes.h"
+#include "2common.h"
+#include "2sha.h"
+
+#if VB2_SUPPORT_SHA1
+#define CTH_SHA1 VB2_HASH_SHA1
+#else
+#define CTH_SHA1 VB2_HASH_INVALID
+#endif
+
+#if VB2_SUPPORT_SHA256
+#define CTH_SHA256 VB2_HASH_SHA256
+#else
+#define CTH_SHA256 VB2_HASH_INVALID
+#endif
+
+#if VB2_SUPPORT_SHA512
+#define CTH_SHA512 VB2_HASH_SHA512
+#else
+#define CTH_SHA512 VB2_HASH_INVALID
+#endif
+
+static const uint8_t crypto_to_hash[] = {
+       CTH_SHA1,
+       CTH_SHA256,
+       CTH_SHA512,
+       CTH_SHA1,
+       CTH_SHA256,
+       CTH_SHA512,
+       CTH_SHA1,
+       CTH_SHA256,
+       CTH_SHA512,
+       CTH_SHA1,
+       CTH_SHA256,
+       CTH_SHA512,
+};
+
+enum vb2_hash_algorithm vb2_crypto_to_hash(uint32_t algorithm)
+{
+       if (algorithm < ARRAY_SIZE(crypto_to_hash))
+               return crypto_to_hash[algorithm];
+       else
+               return VB2_HASH_INVALID;
+}
+
+int vb2_digest_size(enum vb2_hash_algorithm hash_alg)
+{
+       switch (hash_alg) {
+#if VB2_SUPPORT_SHA1
+       case VB2_HASH_SHA1:
+               return VB2_SHA1_DIGEST_SIZE;
+#endif
+#if VB2_SUPPORT_SHA256
+       case VB2_HASH_SHA256:
+               return VB2_SHA256_DIGEST_SIZE;
+#endif
+#if VB2_SUPPORT_SHA512
+       case VB2_HASH_SHA512:
+               return VB2_SHA512_DIGEST_SIZE;
+#endif
+       default:
+               return 0;
+       }
+}
+
+int vb2_hash_block_size(enum vb2_hash_algorithm alg)
+{
+       switch (alg) {
+#if VB2_SUPPORT_SHA1
+       case VB2_HASH_SHA1:
+               return VB2_SHA1_BLOCK_SIZE;
+#endif
+#if VB2_SUPPORT_SHA256
+       case VB2_HASH_SHA256:
+               return VB2_SHA256_BLOCK_SIZE;
+#endif
+#if VB2_SUPPORT_SHA512
+       case VB2_HASH_SHA512:
+               return VB2_SHA512_BLOCK_SIZE;
+#endif
+       default:
+               return 0;
+       }
+}
+
+const char *vb2_get_hash_algorithm_name(enum vb2_hash_algorithm alg)
+{
+       switch (alg) {
+#if VB2_SUPPORT_SHA1
+       case VB2_HASH_SHA1:
+               return VB2_SHA1_ALG_NAME;
+#endif
+#if VB2_SUPPORT_SHA256
+       case VB2_HASH_SHA256:
+               return VB2_SHA256_ALG_NAME;
+#endif
+#if VB2_SUPPORT_SHA512
+       case VB2_HASH_SHA512:
+               return VB2_SHA512_ALG_NAME;
+#endif
+       default:
+               return VB2_INVALID_ALG_NAME;
+       }
+}
+
+int vb2_digest_init(struct vb2_digest_context *dc,
+                   enum vb2_hash_algorithm hash_alg)
+{
+       dc->hash_alg = hash_alg;
+       dc->using_hwcrypto = 0;
+
+       switch (dc->hash_alg) {
+#if VB2_SUPPORT_SHA1
+       case VB2_HASH_SHA1:
+               vb2_sha1_init(&dc->sha1);
+               return VB2_SUCCESS;
+#endif
+#if VB2_SUPPORT_SHA256
+       case VB2_HASH_SHA256:
+               vb2_sha256_init(&dc->sha256);
+               return VB2_SUCCESS;
+#endif
+#if VB2_SUPPORT_SHA512
+       case VB2_HASH_SHA512:
+               vb2_sha512_init(&dc->sha512);
+               return VB2_SUCCESS;
+#endif
+       default:
+               return VB2_ERROR_SHA_INIT_ALGORITHM;
+       }
+}
+
+int vb2_digest_extend(struct vb2_digest_context *dc,
+                     const uint8_t *buf,
+                     uint32_t size)
+{
+       switch (dc->hash_alg) {
+#if VB2_SUPPORT_SHA1
+       case VB2_HASH_SHA1:
+               vb2_sha1_update(&dc->sha1, buf, size);
+               return VB2_SUCCESS;
+#endif
+#if VB2_SUPPORT_SHA256
+       case VB2_HASH_SHA256:
+               vb2_sha256_update(&dc->sha256, buf, size);
+               return VB2_SUCCESS;
+#endif
+#if VB2_SUPPORT_SHA512
+       case VB2_HASH_SHA512:
+               vb2_sha512_update(&dc->sha512, buf, size);
+               return VB2_SUCCESS;
+#endif
+       default:
+               return VB2_ERROR_SHA_EXTEND_ALGORITHM;
+       }
+}
+
+int vb2_digest_finalize(struct vb2_digest_context *dc,
+                       uint8_t *digest,
+                       uint32_t digest_size)
+{
+       if (digest_size < vb2_digest_size(dc->hash_alg))
+               return VB2_ERROR_SHA_FINALIZE_DIGEST_SIZE;
+
+       switch (dc->hash_alg) {
+#if VB2_SUPPORT_SHA1
+       case VB2_HASH_SHA1:
+               vb2_sha1_finalize(&dc->sha1, digest);
+               return VB2_SUCCESS;
+#endif
+#if VB2_SUPPORT_SHA256
+       case VB2_HASH_SHA256:
+               vb2_sha256_finalize(&dc->sha256, digest);
+               return VB2_SUCCESS;
+#endif
+#if VB2_SUPPORT_SHA512
+       case VB2_HASH_SHA512:
+               vb2_sha512_finalize(&dc->sha512, digest);
+               return VB2_SUCCESS;
+#endif
+       default:
+               return VB2_ERROR_SHA_FINALIZE_ALGORITHM;
+       }
+}
+
+int vb2_digest_buffer(const uint8_t *buf,
+                     uint32_t size,
+                     enum vb2_hash_algorithm hash_alg,
+                     uint8_t *digest,
+                     uint32_t digest_size)
+{
+       struct vb2_digest_context dc;
+       int rv;
+
+       rv = vb2_digest_init(&dc, hash_alg);
+       if (rv)
+               return rv;
+
+       rv = vb2_digest_extend(&dc, buf, size);
+       if (rv)
+               return rv;
+
+       return vb2_digest_finalize(&dc, digest, digest_size);
+}
diff --git a/kern/lib/crypto/2stub.c b/kern/lib/crypto/2stub.c
new file mode 100644 (file)
index 0000000..971286c
--- /dev/null
@@ -0,0 +1,59 @@
+/* Copyright (c) 2014 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.
+ *
+ * Stub API implementations which should be implemented by the caller.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "2sysincludes.h"
+#include "2api.h"
+
+__attribute__((weak))
+void vb2ex_printf(const char *func, const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       fprintf(stderr, "%s: ", func);
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
+}
+
+__attribute__((weak))
+int vb2ex_tpm_clear_owner(struct vb2_context *ctx)
+{
+       return VB2_ERROR_EX_TPM_CLEAR_OWNER_UNIMPLEMENTED;
+}
+
+__attribute__((weak))
+int vb2ex_read_resource(struct vb2_context *ctx,
+                       enum vb2_resource_index index,
+                       uint32_t offset,
+                       void *buf,
+                       uint32_t size)
+{
+       return VB2_ERROR_EX_READ_RESOURCE_UNIMPLEMENTED;
+}
+
+__attribute__((weak))
+int vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg,
+                              uint32_t data_size)
+{
+       return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED;
+}
+
+__attribute__((weak))
+int vb2ex_hwcrypto_digest_extend(const uint8_t *buf,
+                                uint32_t size)
+{
+       return VB2_ERROR_SHA_EXTEND_ALGORITHM;  /* Should not be called. */
+}
+
+__attribute__((weak))
+int vb2ex_hwcrypto_digest_finalize(uint8_t *digest,
+                                  uint32_t digest_size)
+{
+       return VB2_ERROR_SHA_FINALIZE_ALGORITHM; /* Should not be called. */
+}
diff --git a/kern/lib/crypto/2tpm_bootmode.c b/kern/lib/crypto/2tpm_bootmode.c
new file mode 100644 (file)
index 0000000..6903fe8
--- /dev/null
@@ -0,0 +1,54 @@
+/* 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.
+ *
+ * Functions for updating the TPM state with the status of boot path.
+ */
+
+#include "2sysincludes.h"
+#include "2common.h"
+#include "2sha.h"
+#include "2tpm_bootmode.h"
+
+/*
+ * Input digests for PCR extend.
+ * These are calculated as:
+ *    SHA1("|Developer_Mode||Recovery_Mode||Keyblock_Mode|").
+ * Developer_Mode can be 0 or 1.
+ * Recovery_Mode can be 0 or 1.
+ * Keyblock flags are defined in 2struct.h and assumed always 0 in recovery mode
+ * or 7 in non-recovery mode.
+ *
+ * We map them to Keyblock_Mode as follows:
+ *   -----------------------------------------
+ *   Keyblock Flags            | Keyblock Mode
+ *   -----------------------------------------
+ *   0 recovery mode           |     0
+ *   7 Normal-signed firmware  |     1
+ */
+
+const uint8_t kBootStateSHA1Digests[][VB2_SHA1_DIGEST_SIZE] = {
+       /* SHA1(0x00|0x00|0x01) */
+       {0x25, 0x47, 0xcc, 0x73, 0x6e, 0x95, 0x1f, 0xa4, 0x91, 0x98, 0x53, 0xc4,
+                       0x3a, 0xe8, 0x90, 0x86, 0x1a, 0x3b, 0x32, 0x64},
+
+       /* SHA1(0x01|0x00|0x01) */
+       {0xc4, 0x2a, 0xc1, 0xc4, 0x6f, 0x1d, 0x4e, 0x21, 0x1c, 0x73, 0x5c, 0xc7,
+                       0xdf, 0xad, 0x4f, 0xf8, 0x39, 0x11, 0x10, 0xe9},
+
+       /* SHA1(0x00|0x01|0x00) */
+       {0x62, 0x57, 0x18, 0x91, 0x21, 0x5b, 0x4e, 0xfc, 0x1c, 0xea, 0xb7, 0x44,
+                       0xce, 0x59, 0xdd, 0x0b, 0x66, 0xea, 0x6f, 0x73},
+
+       /* SHA1(0x01|0x01|0x00) */
+       {0x47, 0xec, 0x8d, 0x98, 0x36, 0x64, 0x33, 0xdc, 0x00, 0x2e, 0x77, 0x21,
+                       0xc9, 0xe3, 0x7d, 0x50, 0x67, 0x54, 0x79, 0x37},
+};
+
+const uint8_t *vb2_get_boot_state_digest(struct vb2_context *ctx)
+{
+       int index = (ctx->flags & VB2_CONTEXT_RECOVERY_MODE ? 2 : 0) +
+                       (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE ? 1 : 0);
+
+       return kBootStateSHA1Digests[index];
+}
diff --git a/kern/lib/crypto/Kbuild b/kern/lib/crypto/Kbuild
new file mode 100644 (file)
index 0000000..f82f470
--- /dev/null
@@ -0,0 +1,15 @@
+#obj-y                                           += 2api.o
+#obj-y                                           += 2common.o
+#obj-y                                           += 2crc8.o
+#obj-y                                           += 2hmac.o
+#obj-y                                           += 2misc.o
+#obj-y                                           += 2nvstorage.o
+#obj-y                                           += 2rsa.o
+#obj-y                                           += 2secdata.o
+#obj-y                                           += 2secdatak.o
+#obj-y                                           += 2sha1.o
+obj-y                                           += 2sha256.o
+#obj-y                                           += 2sha512.o
+#obj-y                                           += 2sha_utility.o
+#obj-y                                           += 2stub.o
+#obj-y                                           += 2tpm_bootmode.o
diff --git a/kern/lib/crypto/include/2api.h b/kern/lib/crypto/include/2api.h
new file mode 100644 (file)
index 0000000..e4c6ad0
--- /dev/null
@@ -0,0 +1,661 @@
+/* Copyright (c) 2013 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.
+ */
+
+/* APIs between calling firmware and vboot_reference
+ *
+ * General notes:
+ *
+ * TODO: split this file into a vboot_entry_points.h file which contains the
+ * entry points for the firmware to call vboot_reference, and a
+ * vboot_firmware_exports.h which contains the APIs to be implemented by the
+ * calling firmware and exported to vboot_reference.
+ *
+ * Notes:
+ *    * Assumes this code is never called in the S3 resume path.  TPM resume
+ *      must be done elsewhere, and VB2_NV_DEBUG_RESET_MODE is ignored.
+ */
+
+#ifndef VBOOT_2_API_H_
+#define VBOOT_2_API_H_
+#include <stdint.h>
+
+#include "2common.h"
+#include "2crypto.h"
+#include "2fw_hash_tags.h"
+#include "2id.h"
+#include "2recovery_reasons.h"
+#include "2return_codes.h"
+
+/* Size of non-volatile data used by vboot */
+#define VB2_NVDATA_SIZE 16
+
+/* Size of secure data spaces used by vboot */
+#define VB2_SECDATA_SIZE 10
+#define VB2_SECDATAK_SIZE 14
+
+/*
+ * Recommended size of work buffer for firmware verification stage
+ *
+ * TODO: The recommended size really depends on which key algorithms are
+ * used.  Should have a better / more accurate recommendation than this.
+ */
+#define VB2_WORKBUF_RECOMMENDED_SIZE (12 * 1024)
+
+/*
+ * Recommended size of work buffer for kernel verification stage
+ *
+ * This is bigger because vboot 2.0 kernel preambles are usually padded to
+ * 64 KB.
+ *
+ * TODO: The recommended size really depends on which key algorithms are
+ * used.  Should have a better / more accurate recommendation than this.
+ */
+#define VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE (80 * 1024)
+
+/* Recommended buffer size for vb2api_get_pcr_digest */
+#define VB2_PCR_DIGEST_RECOMMENDED_SIZE 32
+
+/* Flags for vb2_context.
+ *
+ * Unless otherwise noted, flags are set by verified boot and may be read (but
+ * not set or cleared) by the caller.
+ */
+enum vb2_context_flags {
+
+       /*
+        * Verified boot has changed nvdata[].  Caller must save nvdata[] back
+        * to its underlying storage, then may clear this flag.
+        */
+       VB2_CONTEXT_NVDATA_CHANGED = (1 << 0),
+
+       /*
+        * Verified boot has changed secdata[].  Caller must save secdata[]
+        * back to its underlying storage, then may clear this flag.
+        */
+       VB2_CONTEXT_SECDATA_CHANGED = (1 << 1),
+
+       /* Recovery mode is requested this boot */
+       VB2_CONTEXT_RECOVERY_MODE = (1 << 2),
+
+       /* Developer mode is requested this boot */
+       VB2_CONTEXT_DEVELOPER_MODE = (1 << 3),
+
+       /*
+        * Force recovery mode due to physical user request.  Caller may set
+        * this flag when initializing the context.
+        */
+       VB2_CONTEXT_FORCE_RECOVERY_MODE = (1 << 4),
+
+       /*
+        * Force developer mode enabled.  Caller may set this flag when
+        * initializing the context.
+        */
+       VB2_CONTEXT_FORCE_DEVELOPER_MODE = (1 << 5),
+
+       /* Using firmware slot B.  If this flag is clear, using slot A. */
+       VB2_CONTEXT_FW_SLOT_B = (1 << 6),
+
+       /* RAM should be cleared by caller this boot */
+       VB2_CONTEXT_CLEAR_RAM = (1 << 7),
+
+       /* Wipeout by the app should be requested. */
+       VB2_CONTEXT_FORCE_WIPEOUT_MODE = (1 << 8),
+
+       /* Erase TPM developer mode state if it is enabled. */
+       VB2_DISABLE_DEVELOPER_MODE = (1 << 9),
+
+       /*
+        * Verified boot has changed secdatak[].  Caller must save secdatak[]
+        * back to its underlying storage, then may clear this flag.
+        */
+       VB2_CONTEXT_SECDATAK_CHANGED = (1 << 10),
+
+       /*
+        * Allow kernel verification to roll forward the version in secdatak[].
+        * Caller may set this flag before calling vb2api_kernel_phase3().
+        */
+       VB2_CONTEXT_ALLOW_KERNEL_ROLL_FORWARD = (1 << 11),
+
+       /* Boot optimistically: don't touch failure counters */
+       VB2_CONTEXT_NOFAIL_BOOT = (1 << 12),
+
+       /*
+        * Secdata is not ready this boot, but should be ready next boot.  It
+        * would like to reboot.  The decision whether to reboot or not must be
+        * deferred until vboot, because rebooting all the time before then
+        * could cause a device with malfunctioning secdata to get stuck in an
+        * unrecoverable crash loop.
+        */
+       VB2_CONTEXT_SECDATA_WANTS_REBOOT = (1 << 13),
+
+       /* Boot is S3->S0 resume, not S5->S0 normal boot */
+       VB2_CONTEXT_S3_RESUME = (1 << 14),
+};
+
+/*
+ * Context for firmware verification.  Pass this to all vboot APIs.
+ *
+ * Caller may relocate this between calls to vboot APIs.
+ */
+struct vb2_context {
+       /**********************************************************************
+        * Fields which must be initialized by caller.
+        */
+
+       /*
+        * Flags; see vb2_context_flags.  Some flags may only be set by caller
+        * prior to calling vboot functions.
+        */
+       uint32_t flags;
+
+       /*
+        * Work buffer, and length in bytes.  Caller may relocate this between
+        * calls to vboot APIs; it contains no internal pointers.  Caller must
+        * not examine the contents of this work buffer directly.
+        */
+       uint8_t *workbuf;
+       uint32_t workbuf_size;
+
+       /*
+        * Non-volatile data.  Caller must fill this from some non-volatile
+        * location.  If the VB2_CONTEXT_NVDATA_CHANGED flag is set when a
+        * vb2api function returns, caller must save the data back to the
+        * non-volatile location and then clear the flag.
+        */
+       uint8_t nvdata[VB2_NVDATA_SIZE];
+
+       /*
+        * Secure data for firmware verification stage.  Caller must fill this
+        * from some secure non-volatile location.  If the
+        * VB2_CONTEXT_SECDATA_CHANGED flag is set when a function returns,
+        * caller must save the data back to the secure non-volatile location
+        * and then clear the flag.
+        */
+       uint8_t secdata[VB2_SECDATA_SIZE];
+
+       /*
+        * Context pointer for use by caller.  Verified boot never looks at
+        * this.  Put context here if you need it for APIs that verified boot
+        * may call (vb2ex_...() functions).
+        */
+       void *non_vboot_context;
+
+       /**********************************************************************
+        * Fields caller may examine after calling vb2api_fw_phase1().  Caller
+         * must set these fields to 0 before calling any vboot functions.
+        */
+
+       /*
+        * Amount of work buffer used so far.  Verified boot sub-calls use
+        * this to know where the unused work area starts.  Caller may use
+        * this between calls to vboot APIs to know how much data must be
+        * copied when relocating the work buffer.
+        */
+       uint32_t workbuf_used;
+
+       /**********************************************************************
+        * Fields caller must initialize before calling vb2api_kernel_phase1().
+        */
+
+       /*
+        * Secure data for kernel verification stage.  Caller must fill this
+        * from some secure non-volatile location.  If the
+        * VB2_CONTEXT_SECDATAK_CHANGED flag is set when a function returns,
+        * caller must save the data back to the secure non-volatile location
+        * and then clear the flag.
+        */
+       uint8_t secdatak[VB2_SECDATAK_SIZE];
+};
+
+/* Resource index for vb2ex_read_resource() */
+enum vb2_resource_index {
+
+       /* Google binary block */
+       VB2_RES_GBB,
+
+       /*
+        * Firmware verified boot block (keyblock+preamble).  Use
+        * VB2_CONTEXT_FW_SLOT_B to determine whether this refers to slot A or
+        * slot B; vboot will set that flag to the proper state before reading
+        * the vblock.
+        */
+       VB2_RES_FW_VBLOCK,
+
+       /*
+        * Kernel verified boot block (keyblock+preamble) for the current
+        * kernel partition.  Used only by vb2api_kernel_load_vblock().
+        * Contents are allowed to change between calls to that function (to
+        * allow multiple kernels to be examined).
+        */
+       VB2_RES_KERNEL_VBLOCK,
+};
+
+/* Digest ID for vbapi_get_pcr_digest() */
+enum vb2_pcr_digest {
+       /* Digest based on current developer and recovery mode flags */
+       BOOT_MODE_PCR,
+
+       /* SHA-256 hash digest of HWID, from GBB */
+       HWID_DIGEST_PCR,
+};
+
+/******************************************************************************
+ * APIs provided by verified boot.
+ *
+ * At a high level, call functions in the order described below.  After each
+ * call, examine vb2_context.flags to determine whether nvdata or secdata
+ * needs to be written.
+ *
+ * If you need to cause the boot process to fail at any point, call
+ * vb2api_fail().  Then check vb2_context.flags to see what data needs to be
+ * written.  Then reboot.
+ *
+ *     Load nvdata from wherever you keep it.
+ *
+ *     Load secdata from wherever you keep it.
+ *
+ *             If it wasn't there at all (for example, this is the first boot
+ *             of a new system in the factory), call vb2api_secdata_create()
+ *             to initialize the data.
+ *
+ *             If access to your storage is unreliable (reads/writes may
+ *             contain corrupt data), you may call vb2api_secdata_check() to
+ *             determine if the data was valid, and retry reading if it
+ *             wasn't.  (In that case, you should also read back and check the
+ *             data after any time you write it, to make sure it was written
+ *             correctly.)
+ *
+ *     Call vb2api_fw_phase1().  At present, this nominally decides whether
+ *     recovery mode is needed this boot.
+ *
+ *     Call vb2api_fw_phase2().  At present, this nominally decides which
+ *     firmware slot will be attempted (A or B).
+ *
+ *     Call vb2api_fw_phase3().  At present, this nominally verifies the
+ *     firmware keyblock and preamble.
+ *
+ *     Lock down wherever you keep secdata.  It should no longer be writable
+ *     this boot.
+ *
+ *     Verify the hash of each section of code/data you need to boot the RW
+ *     firmware.  For each section:
+ *
+ *             Call vb2_init_hash() to see if the hash exists.
+ *
+ *             Load the data for the section.  Call vb2_extend_hash() on the
+ *             data as you load it.  You can load it all at once and make one
+ *             call, or load and hash-extend a block at a time.
+ *
+ *             Call vb2_check_hash() to see if the hash is valid.
+ *
+ *                     If it is valid, you may use the data and/or execute
+ *                     code from that section.
+ *
+ *                     If the hash was invalid, you must reboot.
+ *
+ * At this point, firmware verification is done, and vb2_context contains the
+ * kernel key needed to verify the kernel.  That context should be preserved
+ * and passed on to kernel selection.  The kernel selection process may be
+ * done by the same firmware image, or may be done by the RW firmware.  The
+ * recommended order is:
+ *
+ *     Load secdatak from wherever you keep it.
+ *
+ *             If it wasn't there at all (for example, this is the first boot
+ *             of a new system in the factory), call vb2api_secdatak_create()
+ *             to initialize the data.
+ *
+ *             If access to your storage is unreliable (reads/writes may
+ *             contain corrupt data), you may call vb2api_secdatak_check() to
+ *             determine if the data was valid, and retry reading if it
+ *             wasn't.  (In that case, you should also read back and check the
+ *             data after any time you write it, to make sure it was written
+ *             correctly.)
+ *
+ *     Call vb2api_kernel_phase1().  At present, this decides which key to
+ *     use to verify kernel data - the recovery key from the GBB, or the
+ *     kernel subkey from the firmware verification stage.
+ *
+ *     Kernel phase 2 is finding loading, and verifying the kernel partition.
+ *
+ *     Find a boot device (you're on your own here).
+ *
+ *     Call vb2api_load_kernel_vblock() for each kernel partition on the
+ *     boot device, until one succeeds.
+ *
+ *     When that succeeds, call vb2api_get_kernel_size() to determine where
+ *     the kernel is located in the stream and how big it is.  Load or map
+ *     the kernel.  (Again, you're on your own.  This is the responsibility of
+ *     the caller so that the caller can choose whether to allocate a buffer,
+ *     load the kernel data into a predefined area of RAM, or directly map a
+ *     kernel file into the address space.  Note that technically it doesn't
+ *     matter whether the kernel data is even in the same file or stream as
+ *     the vblock, as long as the caller loads the right data.
+ *
+ *     Call vb2api_verify_kernel_data() on the kernel data.
+ *
+ *     If you ran out of kernels before finding a good one, call vb2api_fail()
+ *     with an appropriate recovery reason.
+ *
+ *     Set the VB2_CONTEXT_ALLOW_KERNEL_ROLL_FORWARD flag if the current
+ *     kernel partition has the successful flag (that is, it's already known
+ *     or assumed to be a functional kernel partition).
+ *
+ *     Call vb2api_kernel_phase3().  This cleans up from kernel verification
+ *     and updates the secure data if needed.
+ *
+ *     Lock down wherever you keep secdatak.  It should no longer be writable
+ *     this boot.
+ */
+
+/**
+ * Sanity-check the contents of the secure storage context.
+ *
+ * Use this if reading from secure storage may be flaky, and you want to retry
+ * reading it several times.
+ *
+ * This may be called before vb2api_phase1().
+ *
+ * @param ctx          Context pointer
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2api_secdata_check(const struct vb2_context *ctx);
+
+/**
+ * Create fresh data in the secure storage context.
+ *
+ * Use this only when initializing the secure storage context on a new machine
+ * the first time it boots.  Do NOT simply use this if vb2api_secdata_check()
+ * (or any other API in this library) fails; that could allow the secure data
+ * to be rolled back to an insecure state.
+ *
+ * This may be called before vb2api_phase1().
+ *
+ * @param ctx          Context pointer
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2api_secdata_create(struct vb2_context *ctx);
+
+/**
+ * Sanity-check the contents of the kernel version secure storage context.
+ *
+ * Use this if reading from secure storage may be flaky, and you want to retry
+ * reading it several times.
+ *
+ * This may be called before vb2api_phase1().
+ *
+ * @param ctx          Context pointer
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2api_secdatak_check(const struct vb2_context *ctx);
+
+/**
+ * Create fresh data in the kernel version secure storage context.
+ *
+ * Use this only when initializing the secure storage context on a new machine
+ * the first time it boots.  Do NOT simply use this if vb2api_secdatak_check()
+ * (or any other API in this library) fails; that could allow the secure data
+ * to be rolled back to an insecure state.
+ *
+ * This may be called before vb2api_phase1().
+ *
+ * @param ctx          Context pointer
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2api_secdatak_create(struct vb2_context *ctx);
+
+/**
+ * Report firmware failure to vboot.
+ *
+ * This may be called before vb2api_phase1() to indicate errors in the boot
+ * process prior to the start of vboot.
+ *
+ * If this is called after vb2api_phase1(), on return, the calling firmware
+ * should check for updates to secdata and/or nvdata, then reboot.
+ *
+ * @param reason       Recovery reason
+ * @param subcode      Recovery subcode
+ */
+void vb2api_fail(struct vb2_context *ctx, uint8_t reason, uint8_t subcode);
+
+/**
+ * Firmware selection, phase 1.
+ *
+ * If the returned error is VB2_ERROR_API_PHASE1_RECOVERY, the calling firmware
+ * should jump directly to recovery-mode firmware without rebooting.
+ *
+ * For other errors, the calling firmware should check for updates to secdata
+ * and/or nvdata, then reboot.
+ *
+ * @param ctx          Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2api_fw_phase1(struct vb2_context *ctx);
+
+/**
+ * Firmware selection, phase 2.
+ *
+ * On error, the calling firmware should check for updates to secdata and/or
+ * nvdata, then reboot.
+ *
+ * @param ctx          Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2api_fw_phase2(struct vb2_context *ctx);
+
+/**
+ * Firmware selection, phase 3.
+ *
+ * On error, the calling firmware should check for updates to secdata and/or
+ * nvdata, then reboot.
+ *
+ * On success, the calling firmware should lock down secdata before continuing
+ * with the boot process.
+ *
+ * @param ctx          Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2api_fw_phase3(struct vb2_context *ctx);
+
+/**
+ * Same, but for new-style structs.
+ */
+int vb21api_fw_phase3(struct vb2_context *ctx);
+
+/**
+ * Initialize hashing data for the specified tag.
+ *
+ * @param ctx          Vboot context
+ * @param tag          Tag to start hashing (enum vb2_hash_tag)
+ * @param size         If non-null, expected size of data for tag will be
+ *                     stored here on output.
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2api_init_hash(struct vb2_context *ctx, uint32_t tag, uint32_t *size);
+
+/**
+ * Same, but for new-style structs.
+ */
+int vb21api_init_hash(struct vb2_context *ctx,
+                     const struct vb2_id *id,
+                     uint32_t *size);
+
+/**
+ * Extend the hash started by vb2api_init_hash() with additional data.
+ *
+ * (This is the same for both old and new style structs.)
+ *
+ * @param ctx          Vboot context
+ * @param buf          Data to hash
+ * @param size         Size of data in bytes
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2api_extend_hash(struct vb2_context *ctx,
+                      const void *buf,
+                      uint32_t size);
+
+/**
+ * Check the hash value started by vb2api_init_hash().
+ *
+ * @param ctx          Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2api_check_hash(struct vb2_context *ctx);
+
+/**
+ * Same, but for new-style structs.
+ */
+int vb21api_check_hash(struct vb2_context *ctx);
+
+/**
+ * Check the hash value started by vb2api_init_hash() while retrieving
+ * calculated digest.
+ *
+ * @param ctx                  Vboot context
+ * @param digest_out           optional pointer to buffer to store digest
+ * @param digest_out_size      optional size of buffer to store digest
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2api_check_hash_get_digest(struct vb2_context *ctx, void *digest_out,
+                                uint32_t digest_out_size);
+
+/**
+ * Get a PCR digest
+ *
+ * @param ctx          Vboot context
+ * @param which_digest PCR index of the digest
+ * @param dest         Destination where the digest is copied.
+ *                     Recommended size is VB2_PCR_DIGEST_RECOMMENDED_SIZE.
+ * @param dest_size    IN: size of the buffer pointed by dest
+ *                     OUT: size of the copied digest
+ * @return VB2_SUCCESS, or error code on error
+ */
+int vb2api_get_pcr_digest(struct vb2_context *ctx,
+                         enum vb2_pcr_digest which_digest,
+                         uint8_t *dest,
+                         uint32_t *dest_size);
+
+/**
+ * Prepare for kernel verification stage.
+ *
+ * Must be called before other vb2api kernel functions.
+ *
+ * @param ctx          Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2api_kernel_phase1(struct vb2_context *ctx);
+
+/**
+ * Load the verified boot block (vblock) for a kernel.
+ *
+ * This function may be called multiple times, to load and verify the
+ * vblocks from multiple kernel partitions.
+ *
+ * @param ctx          Vboot context
+ * @param stream       Kernel stream
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2api_load_kernel_vblock(struct vb2_context *ctx);
+
+/**
+ * Get the size and offset of the kernel data for the most recent vblock.
+ *
+ * Valid after a successful call to vb2api_load_kernel_vblock().
+ *
+ * @param ctx          Vboot context
+ * @param offset_ptr   Destination for offset in bytes of kernel data as
+ *                     reported by vblock.
+ * @param size_ptr      Destination for size of kernel data in bytes.
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2api_get_kernel_size(struct vb2_context *ctx,
+                          uint32_t *offset_ptr,
+                          uint32_t *size_ptr);
+
+/**
+ * Verify kernel data using the previously loaded kernel vblock.
+ *
+ * Valid after a successful call to vb2api_load_kernel_vblock().  This allows
+ * the caller to load or map the kernel data, as appropriate, and pass the
+ * pointer to the kernel data into vboot.
+ *
+ * @param ctx          Vboot context
+ * @param buf          Pointer to kernel data
+ * @param size         Size of kernel data in bytes
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2api_verify_kernel_data(struct vb2_context *ctx,
+                             const void *buf,
+                             uint32_t size);
+
+/**
+ * Clean up after kernel verification.
+ *
+ * Call this after successfully loading a vblock and verifying kernel data,
+ * or if you've run out of boot devices and/or kernel partitions.
+ *
+ * This cleans up intermediate data structures in the vboot context, and
+ * updates the version in the secure data if necessary.
+ */
+int vb2api_kernel_phase3(struct vb2_context *ctx);
+
+/*****************************************************************************/
+/* APIs provided by the caller to verified boot */
+
+/**
+ * Clear the TPM owner.
+ *
+ * @param ctx          Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2ex_tpm_clear_owner(struct vb2_context *ctx);
+
+/**
+ * Read a verified boot resource.
+ *
+ * @param ctx          Vboot context
+ * @param index                Resource index to read
+ * @param offset       Byte offset within resource to start at
+ * @param buf          Destination for data
+ * @param size         Amount of data to read
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2ex_read_resource(struct vb2_context *ctx,
+                       enum vb2_resource_index index,
+                       uint32_t offset,
+                       void *buf,
+                       uint32_t size);
+
+void vb2ex_printf(const char *func, const char *fmt, ...);
+
+/**
+ * Initialize the hardware crypto engine to calculate a block-style digest.
+ *
+ * @param hash_alg     Hash algorithm to use
+ * @param data_size    Expected total size of data to hash
+ * @return VB2_SUCCESS, or non-zero error code (HWCRYPTO_UNSUPPORTED not fatal).
+ */
+int vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg,
+                              uint32_t data_size);
+
+/**
+ * Extend the hash in the hardware crypto engine with another block of data.
+ *
+ * @param buf          Next data block to hash
+ * @param size         Length of data block in bytes
+ * @return VB2_SUCCESS, or non-zero error code.
+ */
+int vb2ex_hwcrypto_digest_extend(const uint8_t *buf, uint32_t size);
+
+/**
+ * Finalize the digest in the hardware crypto engine and extract the result.
+ *
+ * @param digest       Destination buffer for resulting digest
+ * @param digest_size  Length of digest buffer in bytes
+ * @return VB2_SUCCESS, or non-zero error code.
+ */
+int vb2ex_hwcrypto_digest_finalize(uint8_t *digest, uint32_t digest_size);
+
+#endif  /* VBOOT_2_API_H_ */
diff --git a/kern/lib/crypto/include/2common.h b/kern/lib/crypto/include/2common.h
new file mode 100644 (file)
index 0000000..4622ab1
--- /dev/null
@@ -0,0 +1,197 @@
+/* Copyright (c) 2014 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.
+ *
+ * Common functions between firmware and kernel verified boot.
+ */
+
+#ifndef VBOOT_REFERENCE_VBOOT_2COMMON_H_
+#define VBOOT_REFERENCE_VBOOT_2COMMON_H_
+
+#include "2api.h"
+#include "2return_codes.h"
+#include "2sha.h"
+#include "2struct.h"
+
+struct vb2_public_key;
+
+/*
+ * Return the greater of A and B.  This is used in macros which calculate the
+ * required buffer size, so can't be turned into a static inline function.
+ */
+#ifndef VB2_MAX
+#define VB2_MAX(A, B) ((A) > (B) ? (A) : (B))
+#endif
+
+/* Return the number of elements in an array */
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
+#endif
+
+/* Debug output printf() for tests.  Otherwise, it's platform-dependent. */
+#if defined(VBOOT_DEBUG)
+#  if defined(FOR_TEST)
+#    define VB2_DEBUG(format, args...) printf(format, ## args)
+#  else
+#    define VB2_DEBUG(format, args...) vb2ex_printf(__func__, format, ## args)
+#  endif
+#else
+#  define VB2_DEBUG(format, args...)
+#endif
+
+/*
+ * Alignment for work buffer pointers/allocations should be useful for any
+ * data type. When declaring workbuf buffers on the stack, the caller should
+ * use explicit alignment to avoid run-time errors. For example:
+ *
+ *    int foo(void)
+ *    {
+ *        struct vb2_workbuf wb;
+ *        uint8_t buf[NUM] __attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
+ *        wb.buf = buf;
+ *        wb.size = sizeof(buf);
+ */
+
+/* We might get away with using __alignof__(void *), but since GCC defines a
+ * macro for us we'll be safe and use that. */
+#define VB2_WORKBUF_ALIGN __BIGGEST_ALIGNMENT__
+
+/* Work buffer */
+struct vb2_workbuf {
+       uint8_t *buf;
+       uint32_t size;
+};
+
+/**
+ * Initialize a work buffer.
+ *
+ * @param wb           Work buffer to init
+ * @param buf          Pointer to work buffer data
+ * @param size         Size of work buffer data in bytes
+ */
+void vb2_workbuf_init(struct vb2_workbuf *wb, uint8_t *buf, uint32_t size);
+
+/**
+ * Allocate space in a work buffer.
+ *
+ * Note that the returned buffer will always be aligned to VB2_WORKBUF_ALIGN.
+ *
+ * The work buffer acts like a stack, and detailed tracking of allocs and frees
+ * is not done.  The caller must track the size of each allocation and free via
+ * vb2_workbuf_free() in the reverse order they were allocated.
+ *
+ * An acceptable alternate workflow inside a function is to pass in a const
+ * work buffer, then make a local copy.  Allocations done to the local copy
+ * then don't change the passed-in work buffer, and will effectively be freed
+ * when the local copy goes out of scope.
+ *
+ * @param wb           Work buffer
+ * @param size         Requested size in bytes
+ * @return A pointer to the allocated space, or NULL if error.
+ */
+void *vb2_workbuf_alloc(struct vb2_workbuf *wb, uint32_t size);
+
+/**
+ * Reallocate space in a work buffer.
+ *
+ * Note that the returned buffer will always be aligned to VB2_WORKBUF_ALIGN.
+ * The work buffer acts like a stack, so this must only be done to the most
+ * recently allocated buffer.
+ *
+ * @param wb           Work buffer
+ * @param oldsize      Old allocation size in bytes
+ * @param newsize      Requested size in bytes
+ * @return A pointer to the allocated space, or NULL if error.
+ */
+void *vb2_workbuf_realloc(struct vb2_workbuf *wb,
+                         uint32_t oldsize,
+                         uint32_t newsize);
+
+/**
+ * Free the preceding allocation.
+ *
+ * Note that the work buffer acts like a stack, and detailed tracking of
+ * allocs and frees is not done.  The caller must track the size of each
+ * allocation and free them in reverse order.
+ *
+ * @param wb           Work buffer
+ * @param size         Size of data to free
+ */
+void vb2_workbuf_free(struct vb2_workbuf *wb, uint32_t size);
+
+/* Check if a pointer is aligned on an align-byte boundary */
+#define vb2_aligned(ptr, align) (!(((uintptr_t)(ptr)) & ((align) - 1)))
+
+/**
+ * Safer memcmp() for use in crypto.
+ *
+ * Compares the buffers to see if they are equal.  Time taken to perform
+ * the comparison is dependent only on the size, not the relationship of
+ * the match between the buffers.  Note that unlike memcmp(), this only
+ * indicates inequality, not which buffer is lesser.
+ *
+ * @param s1           First buffer
+ * @param s2           Second buffer
+ * @param size         Number of bytes to compare
+ * @return 0 if match or size=0, non-zero if at least one byte mismatched.
+ */
+int vb2_safe_memcmp(const void *s1, const void *s2, size_t size);
+
+/**
+ * Align a buffer and check its size.
+ *
+ * @param **ptr                Pointer to pointer to align
+ * @param *size                Points to size of buffer pointed to by *ptr
+ * @param align                Required alignment (must be power of 2)
+ * @param want_size    Required size
+ * @return VB2_SUCCESS, or non-zero if error.
+ */
+int vb2_align(uint8_t **ptr,
+             uint32_t *size,
+             uint32_t align,
+             uint32_t want_size);
+
+/**
+ * Return offset of ptr from base.
+ *
+ * @param base         Base pointer
+ * @param ptr          Pointer at some offset from base
+ * @return The offset of ptr from base.
+ */
+ptrdiff_t vb2_offset_of(const void *base, const void *ptr);
+
+/**
+ * Return expected signature size for a signature/hash algorithm pair
+ *
+ * @param sig_alg      Signature algorithm
+ * @param hash_alg     Hash algorithm
+ * @return The signature size, or zero if error / unsupported algorithm.
+ */
+uint32_t vb2_sig_size(enum vb2_signature_algorithm sig_alg,
+                     enum vb2_hash_algorithm hash_alg);
+
+/**
+ * Return a key ID for an unsigned hash algorithm.
+ *
+ * @param hash_alg     Hash algorithm to return key for
+ * @return A pointer to the key ID for that hash algorithm with
+ *        sig_alg=VB2_SIG_NONE, or NULL if error.
+ */
+const struct vb2_id *vb2_hash_id(enum vb2_hash_algorithm hash_alg);
+
+/* Size of work buffer sufficient for vb2_verify_digest() worst case. */
+#define VB2_VERIFY_DIGEST_WORKBUF_BYTES VB2_VERIFY_RSA_DIGEST_WORKBUF_BYTES
+
+/* Size of work buffer sufficient for vb2_verify_data() worst case. */
+#define VB2_VERIFY_DATA_WORKBUF_BYTES                                  \
+       (VB2_SHA512_DIGEST_SIZE +                                       \
+        VB2_MAX(VB2_VERIFY_DIGEST_WORKBUF_BYTES,                       \
+                sizeof(struct vb2_digest_context)))
+
+/* Size of work buffer sufficient for vb2_verify_keyblock() worst case. */
+#define VB2_KEY_BLOCK_VERIFY_WORKBUF_BYTES VB2_VERIFY_DATA_WORKBUF_BYTES
+
+/* Size of work buffer sufficient for vb2_verify_fw_preamble() worst case. */
+#define VB2_VERIFY_FIRMWARE_PREAMBLE_WORKBUF_BYTES VB2_VERIFY_DATA_WORKBUF_BYTES
+
+#endif  /* VBOOT_REFERENCE_VBOOT_2COMMON_H_ */
diff --git a/kern/lib/crypto/include/2crc8.h b/kern/lib/crypto/include/2crc8.h
new file mode 100644 (file)
index 0000000..f01eabd
--- /dev/null
@@ -0,0 +1,20 @@
+/* Copyright (c) 2014 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.
+ *
+ * Very simple 8-bit CRC function.
+ */
+
+#ifndef VBOOT_REFERENCE_2_CRC8_H_
+#define VBOOT_REFERENCE_2_CRC8_H_
+
+/**
+ * Calculate CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial.
+ *
+ * @param data         Data to CRC
+ * @param size         Size of data in bytes
+ * @return CRC-8 of the data.
+ */
+uint8_t vb2_crc8(const void *data, uint32_t size);
+
+#endif /* VBOOT_REFERENCE_2_CRC8_H_ */
diff --git a/kern/lib/crypto/include/2crypto.h b/kern/lib/crypto/include/2crypto.h
new file mode 100644 (file)
index 0000000..c1f225d
--- /dev/null
@@ -0,0 +1,65 @@
+/* Copyright (c) 2014 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.
+ *
+ * Crypto constants for verified boot
+ */
+
+#ifndef VBOOT_REFERENCE_VBOOT_2CRYPTO_H_
+#define VBOOT_REFERENCE_VBOOT_2CRYPTO_H_
+#include <stdint.h>
+
+/* Verified boot crypto algorithms */
+enum vb2_crypto_algorithm {
+       VB2_ALG_RSA1024_SHA1   = 0,
+       VB2_ALG_RSA1024_SHA256 = 1,
+       VB2_ALG_RSA1024_SHA512 = 2,
+       VB2_ALG_RSA2048_SHA1   = 3,
+       VB2_ALG_RSA2048_SHA256 = 4,
+       VB2_ALG_RSA2048_SHA512 = 5,
+       VB2_ALG_RSA4096_SHA1   = 6,
+       VB2_ALG_RSA4096_SHA256 = 7,
+       VB2_ALG_RSA4096_SHA512 = 8,
+       VB2_ALG_RSA8192_SHA1   = 9,
+       VB2_ALG_RSA8192_SHA256 = 10,
+       VB2_ALG_RSA8192_SHA512 = 11,
+
+       /* Number of algorithms */
+       VB2_ALG_COUNT
+};
+
+/* Algorithm types for signatures */
+enum vb2_signature_algorithm {
+       /* Invalid or unsupported signature type */
+       VB2_SIG_INVALID = 0,
+
+       /*
+        * No signature algorithm.  The digest is unsigned.  See
+        * VB2_ID_NONE_* for key IDs to use with this algorithm.
+        */
+       VB2_SIG_NONE = 1,
+
+       /* RSA algorithms of the given length in bits (1024-8192) */
+       VB2_SIG_RSA1024 = 2,  /* Warning!  This is likely to be deprecated! */
+       VB2_SIG_RSA2048 = 3,
+       VB2_SIG_RSA4096 = 4,
+       VB2_SIG_RSA8192 = 5,
+};
+
+/* Algorithm types for hash digests */
+enum vb2_hash_algorithm {
+       /* Invalid or unsupported digest type */
+       VB2_HASH_INVALID = 0,
+
+       /* SHA-1.  Warning: This is likely to be deprecated soon! */
+       VB2_HASH_SHA1 = 1,
+
+       /* SHA-256 and SHA-512 */
+       VB2_HASH_SHA256 = 2,
+       VB2_HASH_SHA512 = 3,
+
+       /* Last index. Don't add anything below. */
+       VB2_HASH_ALG_COUNT,
+};
+
+#endif /* VBOOT_REFERENCE_VBOOT_2CRYPTO_H_ */
diff --git a/kern/lib/crypto/include/2fw_hash_tags.h b/kern/lib/crypto/include/2fw_hash_tags.h
new file mode 100644 (file)
index 0000000..0c061f5
--- /dev/null
@@ -0,0 +1,40 @@
+/* Copyright (c) 2014 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.
+ *
+ * Firmware hash tags for verified boot
+ */
+
+#ifndef VBOOT_REFERENCE_VBOOT_2FW_HASH_TAGS_H_
+#define VBOOT_REFERENCE_VBOOT_2FW_HASH_TAGS_H_
+#include <stdint.h>
+
+/*
+ * Tags for types of hashable data.
+ *
+ * Note that not every firmware image will contain every tag.
+ *
+ * TODO: These are the ones that vboot specifically knows about given the
+ * current data structures.  In the future, I'd really like the vboot preamble
+ * to contain an arbitrary list of tags and their hashes, so that we can hash
+ * ram init, main RW body, EC-RW for software sync, etc. all separately.
+ */
+enum vb2_hash_tag {
+       /* Invalid hash tag; never present in table */
+       VB2_HASH_TAG_INVALID = 0,
+
+       /* Firmware body */
+       VB2_HASH_TAG_FW_BODY = 1,
+
+       /* Kernel data key */
+       VB2_HASH_TAG_KERNEL_DATA_KEY = 2,
+
+       /*
+        * Tags over 0x40000000 are reserved for use by the calling firmware,
+        * which may associate them with arbitrary types of RW firmware data
+        * that it wants to track.
+        */
+       VB2_HASH_TAG_CALLER_BASE = 0x40000000
+};
+
+#endif /* VBOOT_REFERENCE_VBOOT_2FW_HASH_TAGS_H_ */
diff --git a/kern/lib/crypto/include/2hmac.h b/kern/lib/crypto/include/2hmac.h
new file mode 100644 (file)
index 0000000..1df1939
--- /dev/null
@@ -0,0 +1,29 @@
+/* Copyright 2016 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.
+ */
+
+#ifndef VBOOT_REFERENCE_VBOOT_2HMAC_H_
+#define VBOOT_REFERENCE_VBOOT_2HMAC_H_
+
+#include <stdint.h>
+#include "2crypto.h"
+
+/**
+ * Compute HMAC
+ *
+ * @param alg          Hash algorithm ID
+ * @param key          HMAC key
+ * @param key_size     HMAC key size
+ * @param msg          Message to compute HMAC for
+ * @param msg_size     Message size
+ * @param mac          Computed message authentication code
+ * @param mac_size     Size of the buffer pointed by <mac>
+ * @return
+ */
+int hmac(enum vb2_hash_algorithm alg,
+        const void *key, uint32_t key_size,
+        const void *msg, uint32_t msg_size,
+        uint8_t *mac, uint32_t mac_size);
+
+#endif
diff --git a/kern/lib/crypto/include/2id.h b/kern/lib/crypto/include/2id.h
new file mode 100644 (file)
index 0000000..03f6d96
--- /dev/null
@@ -0,0 +1,28 @@
+/* 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.
+ *
+ * Key ID, used to quickly match keys with signatures. There's not a standard
+ * fingerprint for private keys, so we're using the sha1sum of the public key
+ * in our keyb format. Pretty much anything would work as long as it's
+ * resistant to collisions and easy to compare.
+ */
+
+#ifndef VBOOT_REFERENCE_VBOOT_2ID_H_
+#define VBOOT_REFERENCE_VBOOT_2ID_H_
+#include <stdint.h>
+
+#define VB2_ID_NUM_BYTES 20
+
+struct vb2_id {
+       uint8_t raw[VB2_ID_NUM_BYTES];
+} __attribute__((packed));
+
+#define EXPECTED_ID_SIZE VB2_ID_NUM_BYTES
+
+/* IDs to use for "keys" with sig_alg==VB2_SIG_NONE */
+#define VB2_ID_NONE_SHA1   {{0x00, 0x01,}}
+#define VB2_ID_NONE_SHA256 {{0x02, 0x56,}}
+#define VB2_ID_NONE_SHA512 {{0x05, 0x12,}}
+
+#endif  /* VBOOT_REFERENCE_VBOOT_2ID_H_ */
diff --git a/kern/lib/crypto/include/2misc.h b/kern/lib/crypto/include/2misc.h
new file mode 100644 (file)
index 0000000..f562fad
--- /dev/null
@@ -0,0 +1,166 @@
+/* Copyright (c) 2014 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.
+ *
+ * Misc functions which need access to vb2_context but are not public APIs
+ */
+
+#ifndef VBOOT_REFERENCE_VBOOT_2MISC_H_
+#define VBOOT_REFERENCE_VBOOT_2MISC_H_
+
+#include "2api.h"
+
+struct vb2_gbb_header;
+struct vb2_workbuf;
+
+/**
+ * Get the shared data pointer from the vboot context
+ *
+ * @param ctx          Vboot context
+ * @return The shared data pointer.
+ */
+static __inline struct vb2_shared_data *vb2_get_sd(struct vb2_context *ctx) {
+       return (struct vb2_shared_data *)ctx->workbuf;
+}
+
+/**
+ * Validate gbb signature (the magic number)
+ *
+ * @param sig          Pointer to the signature bytes to validate
+ * @return VB2_SUCCESS if valid or non-zero if error.
+ */
+int vb2_validate_gbb_signature(uint8_t *sig);
+
+/**
+ * Initialize a work buffer from the vboot context.
+ *
+ * This sets the work buffer to the unused portion of the context work buffer.
+ *
+ * @param ctx          Vboot context
+ * @param wb           Work buffer to initialize
+ */
+void vb2_workbuf_from_ctx(struct vb2_context *ctx, struct vb2_workbuf *wb);
+
+/**
+ * Read the GBB header.
+ *
+ * @param ctx          Vboot context
+ * @param gbb          Destination for header
+ * @return VB2_SUCCESS, or non-zero if error.
+ */
+int vb2_read_gbb_header(struct vb2_context *ctx, struct vb2_gbb_header *gbb);
+
+/**
+ * Handle vboot failure.
+ *
+ * If the failure occurred after choosing a firmware slot, and the other
+ * firmware slot is not known-bad, try the other firmware slot after reboot.
+ *
+ * If the failure occurred before choosing a firmware slot, or both slots have
+ * failed in successive boots, request recovery.
+ *
+ * @param reason       Recovery reason
+ * @param subcode      Recovery subcode
+ */
+void vb2_fail(struct vb2_context *ctx, uint8_t reason, uint8_t subcode);
+
+/**
+ * Set up the verified boot context data, if not already set up.
+ *
+ * This uses ctx->workbuf_used=0 as a flag to indicate that the data has not
+ * yet been set up.  Caller must set that before calling any voot functions;
+ * see 2api.h.
+ *
+ * @param ctx          Vboot context to initialize
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2_init_context(struct vb2_context *ctx);
+
+/**
+ * Check for recovery reasons we can determine early in the boot process.
+ *
+ * On exit, check ctx->flags for VB2_CONTEXT_RECOVERY_MODE; if present, jump to
+ * the recovery path instead of continuing with normal boot.  This is the only
+ * direct path to recovery mode.  All other errors later in the boot process
+ * should induce a reboot instead of jumping to recovery, so that recovery mode
+ * starts from a consistent firmware state.
+ *
+ * @param ctx          Vboot context
+ */
+void vb2_check_recovery(struct vb2_context *ctx);
+
+/**
+ * Parse the GBB header.
+ *
+ * @param ctx          Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2_fw_parse_gbb(struct vb2_context *ctx);
+
+/**
+ * Check developer switch position.
+ *
+ * @param ctx          Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2_check_dev_switch(struct vb2_context *ctx);
+
+/**
+ * Check if we need to clear the TPM owner.
+ *
+ * @param ctx          Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2_check_tpm_clear(struct vb2_context *ctx);
+
+/**
+ * Decide which firmware slot to try this boot.
+ *
+ * @param ctx          Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2_select_fw_slot(struct vb2_context *ctx);
+
+/**
+ * Verify the firmware keyblock using the root key.
+ *
+ * After this call, the data key is stored in the work buffer.
+ *
+ * @param ctx          Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2_load_fw_keyblock(struct vb2_context *ctx);
+int vb21_load_fw_keyblock(struct vb2_context *ctx);
+
+/**
+ * Verify the firmware preamble using the data subkey from the keyblock.
+ *
+ * After this call, the preamble is stored in the work buffer.
+ *
+ * @param ctx          Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2_load_fw_preamble(struct vb2_context *ctx);
+int vb21_load_fw_preamble(struct vb2_context *ctx);
+
+/**
+ * Verify the kernel keyblock using the previously-loaded kernel key.
+ *
+ * After this call, the data key is stored in the work buffer.
+ *
+ * @param ctx          Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2_load_kernel_keyblock(struct vb2_context *ctx);
+
+/**
+ * Verify the kernel preamble using the data subkey from the keyblock.
+ *
+ * After this call, the preamble is stored in the work buffer.
+ *
+ * @param ctx          Vboot context
+ * @return VB2_SUCCESS, or error code on error.
+ */
+int vb2_load_kernel_preamble(struct vb2_context *ctx);
+
+#endif  /* VBOOT_REFERENCE_VBOOT_2MISC_H_ */
diff --git a/kern/lib/crypto/include/2nvstorage.h b/kern/lib/crypto/include/2nvstorage.h
new file mode 100644 (file)
index 0000000..66a5fdf
--- /dev/null
@@ -0,0 +1,174 @@
+/* Copyright (c) 2014 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.
+ *
+ * Non-volatile storage routines
+ */
+
+#ifndef VBOOT_REFERENCE_VBOOT_2NVSTORAGE_H_
+#define VBOOT_REFERENCE_VBOOT_2NVSTORAGE_H_
+
+enum vb2_nv_param {
+       /*
+        * Parameter values have been reset to defaults (flag for firmware).
+        * 0=clear; 1=set.
+        */
+       VB2_NV_FIRMWARE_SETTINGS_RESET = 0,
+       /*
+        * Parameter values have been reset to defaults (flag for kernel).
+        * 0=clear; 1=set.
+        */
+       VB2_NV_KERNEL_SETTINGS_RESET,
+       /* Request debug reset on next S3->S0 transition.  0=clear; 1=set. */
+       VB2_NV_DEBUG_RESET_MODE,
+       /* Firmware slot to try next.  0=A, 1=B */
+       VB2_NV_TRY_NEXT,
+       /*
+        * Number of times to try booting RW firmware slot B before slot A.
+        * Valid range: 0-15.
+        *
+        * For VB2, number of times to try booting the slot indicated by
+        * VB2_NV_TRY_NEXT.  On a 1->0 transition of try count, VB2_NV_TRY_NEXT
+        * will be set to the other slot.
+        */
+       VB2_NV_TRY_COUNT,
+       /*
+        * Request recovery mode on next boot; see 2recovery_reason.h for
+        * currently defined reason codes.  8-bit value.
+        */
+       VB2_NV_RECOVERY_REQUEST,
+       /*
+        * Localization index for screen bitmaps displayed by firmware.
+        * 8-bit value.
+        */
+       VB2_NV_LOCALIZATION_INDEX,
+       /* Field reserved for kernel/user-mode use; 32-bit value. */
+       VB2_NV_KERNEL_FIELD,
+       /* Allow booting from USB in developer mode.  0=no, 1=yes. */
+       VB2_NV_DEV_BOOT_USB,
+       /* Allow booting of legacy OSes in developer mode.  0=no, 1=yes. */
+       VB2_NV_DEV_BOOT_LEGACY,
+       /* Only boot Google-signed images in developer mode.  0=no, 1=yes. */
+       VB2_NV_DEV_BOOT_SIGNED_ONLY,
+       /*
+        * Allow full fastboot capability in firmware in developer mode.
+        * 0=no, 1=yes.
+        */
+       VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP,
+       /* Set default boot mode (see vb2_dev_default_boot) */
+       VB2_NV_DEV_DEFAULT_BOOT,
+       /*
+        * Set by userspace to request that RO firmware disable dev-mode on the
+        * next boot. This is likely only possible if the dev-switch is
+        * virtual.
+        */
+       VB2_NV_DISABLE_DEV_REQUEST,
+       /*
+        * Set and cleared by vboot to request that the video Option ROM be
+        * loaded at boot time, so that BIOS screens can be displayed. 0=no,
+        * 1=yes.
+        */
+       VB2_NV_OPROM_NEEDED,
+       /* Request that the firmware clear the TPM owner on the next boot. */
+       VB2_NV_CLEAR_TPM_OWNER_REQUEST,
+       /* Flag that TPM owner was cleared on request. */
+       VB2_NV_CLEAR_TPM_OWNER_DONE,
+       /* TPM requested a reboot already. */
+       VB2_NV_TPM_REQUESTED_REBOOT,
+       /* More details on recovery reason */
+       VB2_NV_RECOVERY_SUBCODE,
+       /* Request that NVRAM be backed up at next boot if possible. */
+       VB2_NV_BACKUP_NVRAM_REQUEST,
+       /* Firmware slot tried this boot (0=A, 1=B) */
+       VB2_NV_FW_TRIED,
+       /* Result of trying that firmware (see vb2_fw_result) */
+       VB2_NV_FW_RESULT,
+       /* Firmware slot tried previous boot (0=A, 1=B) */
+       VB2_NV_FW_PREV_TRIED,
+       /* Result of trying that firmware (see vb2_fw_result) */
+       VB2_NV_FW_PREV_RESULT,
+       /* Request wipeout of the device by the app. */
+       VB2_NV_REQ_WIPEOUT,
+
+       /* Fastboot: Unlock in firmware, 0=disabled, 1=enabled. */
+       VB2_NV_FASTBOOT_UNLOCK_IN_FW,
+       /* Boot system when AC detected (0=no, 1=yes). */
+       VB2_NV_BOOT_ON_AC_DETECT,
+       /* Try to update the EC-RO image after updating the EC-RW image(0=no, 1=yes). */
+       VB2_NV_TRY_RO_SYNC,
+        /* Cut off battery and shutdown on next boot. */
+        VB2_NV_BATTERY_CUTOFF_REQUEST,
+};
+
+/* Set default boot in developer mode */
+enum vb2_dev_default_boot {
+       /* Default to boot from disk*/
+       VB2_DEV_DEFAULT_BOOT_DISK = 0,
+
+       /* Default to boot from USB */
+       VB2_DEV_DEFAULT_BOOT_USB= 1,
+
+       /* Default to boot legacy OS */
+       VB2_DEV_DEFAULT_BOOT_LEGACY = 2,
+
+};
+
+/* Firmware result codes for VB2_NV_FW_RESULT and VB2_NV_FW_PREV_RESULT */
+enum vb2_fw_result {
+       /* Unknown */
+       VB2_FW_RESULT_UNKNOWN = 0,
+
+       /* Trying a new slot, but haven't reached success/failure */
+       VB2_FW_RESULT_TRYING = 1,
+
+       /* Successfully booted to the OS */
+       VB2_FW_RESULT_SUCCESS = 2,
+
+       /* Known failure */
+       VB2_FW_RESULT_FAILURE = 3,
+};
+
+/**
+ * Check the CRC of the non-volatile storage context.
+ *
+ * Use this if reading from non-volatile storage may be flaky, and you want to
+ * retry reading it several times.
+ *
+ * This may be called before vb2_context_init().
+ *
+ * @param ctx          Context pointer
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2_nv_check_crc(const struct vb2_context *ctx);
+
+/**
+ * Initialize the non-volatile storage context and verify its CRC.
+ *
+ * @param ctx          Context pointer
+ */
+void vb2_nv_init(struct vb2_context *ctx);
+
+/**
+ * Read a non-volatile value.
+ *
+ * @param ctx          Context pointer
+ * @param param                Parameter to read
+ * @return The value of the parameter.  If you somehow force an invalid
+ *         parameter number, returns 0.
+ */
+uint32_t vb2_nv_get(struct vb2_context *ctx, enum vb2_nv_param param);
+
+/**
+ * Write a non-volatile value.
+ *
+ * Ignores writes to unknown params.
+ *
+ * @param ctx          Context pointer
+ * @param param                Parameter to write
+ * @param value                New value
+ */
+void vb2_nv_set(struct vb2_context *ctx,
+               enum vb2_nv_param param,
+               uint32_t value);
+
+#endif  /* VBOOT_REFERENCE_VBOOT_2NVSTORAGE_H_ */
diff --git a/kern/lib/crypto/include/2nvstorage_fields.h b/kern/lib/crypto/include/2nvstorage_fields.h
new file mode 100644 (file)
index 0000000..018bdeb
--- /dev/null
@@ -0,0 +1,79 @@
+/* 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.
+ *
+ * Non-volatile storage bitfields
+ */
+
+#ifndef VBOOT_REFERENCE_VBOOT_2NVSTORAGE_FIELDS_H_
+#define VBOOT_REFERENCE_VBOOT_2NVSTORAGE_FIELDS_H_
+
+/*
+ * Constants for NV storage.  We use this rather than structs and bitfields so
+ * the data format is consistent across platforms and compilers.  Total NV
+ * storage size is VB2_NVDATA_SIZE = 16 bytes.
+ *
+ * These constants must match the equivalent constants in
+ * lib/vboot_nvstorage.c.  (We currently don't share a common header file
+ * because we're tring to keep the two libs independent, and we hope to
+ * deprecate that one.)
+ */
+
+enum vb2_nv_offset {
+       VB2_NV_OFFS_HEADER = 0,
+       VB2_NV_OFFS_BOOT = 1,
+       VB2_NV_OFFS_RECOVERY = 2,
+       VB2_NV_OFFS_LOCALIZATION = 3,
+       VB2_NV_OFFS_DEV = 4,
+       VB2_NV_OFFS_TPM = 5,
+       VB2_NV_OFFS_RECOVERY_SUBCODE = 6,
+       VB2_NV_OFFS_BOOT2 = 7,
+       VB2_NV_OFFS_MISC = 8,
+       /* Offsets 9-10 are currently unused */
+       VB2_NV_OFFS_KERNEL = 11, /* 11-14; field is 32 bits */
+       /* CRC must be last field */
+       VB2_NV_OFFS_CRC = 15
+ };
+
+/* Fields in VB2_NV_OFFS_HEADER (unused = 0x07) */
+#define VB2_NV_HEADER_WIPEOUT                 0x08
+#define VB2_NV_HEADER_KERNEL_SETTINGS_RESET    0x10
+#define VB2_NV_HEADER_FW_SETTINGS_RESET        0x20
+#define VB2_NV_HEADER_SIGNATURE                0x40
+#define VB2_NV_HEADER_MASK                     0xc0
+
+/* Fields in VB2_NV_OFFS_BOOT */
+#define VB2_NV_BOOT_TRY_COUNT_MASK             0x0f
+#define VB2_NV_BOOT_BACKUP_NVRAM               0x10
+#define VB2_NV_BOOT_OPROM_NEEDED               0x20
+#define VB2_NV_BOOT_DISABLE_DEV                0x40
+#define VB2_NV_BOOT_DEBUG_RESET                0x80
+
+/* Fields in VB2_NV_OFFS_BOOT2 (unused = 0x80) */
+#define VB2_NV_BOOT2_RESULT_MASK               0x03
+#define VB2_NV_BOOT2_TRIED                     0x04
+#define VB2_NV_BOOT2_TRY_NEXT                  0x08
+#define VB2_NV_BOOT2_PREV_RESULT_MASK          0x30
+#define VB2_NV_BOOT2_PREV_RESULT_SHIFT 4  /* Number of bits to shift result */
+#define VB2_NV_BOOT2_PREV_TRIED                0x40
+
+/* Fields in VB2_NV_OFFS_DEV (unused = 0xc0) */
+#define VB2_NV_DEV_FLAG_USB                    0x01
+#define VB2_NV_DEV_FLAG_SIGNED_ONLY            0x02
+#define VB2_NV_DEV_FLAG_LEGACY                 0x04
+#define VB2_NV_DEV_FLAG_FASTBOOT_FULL_CAP      0x08
+#define VB2_NV_DEV_FLAG_DEFAULT_BOOT           0x30
+#define VB2_NV_DEV_DEFAULT_BOOT_SHIFT 4  /* Number of bits to shift */
+
+/* Fields in VB2_NV_OFFS_TPM (unused = 0xf8) */
+#define VB2_NV_TPM_CLEAR_OWNER_REQUEST         0x01
+#define VB2_NV_TPM_CLEAR_OWNER_DONE            0x02
+#define VB2_NV_TPM_REBOOTED                    0x04
+
+/* Fields in VB2_NV_OFFS_MISC (unused = 0xf0) */
+#define VB2_NV_MISC_UNLOCK_FASTBOOT            0x01
+#define VB2_NV_MISC_BOOT_ON_AC_DETECT          0x02
+#define VB2_NV_MISC_TRY_RO_SYNC                       0x04
+#define VB2_NV_MISC_BATTERY_CUTOFF             0x08
+
+#endif  /* VBOOT_REFERENCE_VBOOT_2NVSTORAGE_FIELDS_H_ */
diff --git a/kern/lib/crypto/include/2recovery_reasons.h b/kern/lib/crypto/include/2recovery_reasons.h
new file mode 100644 (file)
index 0000000..13685e6
--- /dev/null
@@ -0,0 +1,227 @@
+/* Copyright (c) 2014 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.
+ *
+ * Recovery reasons
+ */
+
+#ifndef VBOOT_REFERENCE_VBOOT_2RECOVERY_REASONS_H_
+#define VBOOT_REFERENCE_VBOOT_2RECOVERY_REASONS_H_
+
+/* Recovery reason codes */
+enum vb2_nv_recovery {
+       /* Recovery not requested. */
+       VB2_RECOVERY_NOT_REQUESTED = 0x00,
+
+       /*
+        * Recovery requested from legacy utility.  (Prior to the NV storage
+        * spec, recovery mode was a single bitfield; this value is reserved so
+        * that scripts which wrote 1 to the recovery field are distinguishable
+        * from scripts whch use the recovery reasons listed here.
+        */
+       VB2_RECOVERY_LEGACY = 0x01,
+
+       /* User manually requested recovery via recovery button */
+       VB2_RECOVERY_RO_MANUAL = 0x02,
+
+       /*
+        * RW firmware failed signature check (neither RW firmware slot was
+        * valid)
+        */
+       VB2_RECOVERY_RO_INVALID_RW = 0x03,
+
+       /* S3 resume failed */
+       VB2_RECOVERY_RO_S3_RESUME = 0x04,
+
+       /* TPM error in read-only firmware (deprecated) */
+       VB2_RECOVERY_DEP_RO_TPM_ERROR = 0x05,
+
+       /* Shared data error in read-only firmware */
+       VB2_RECOVERY_RO_SHARED_DATA = 0x06,
+
+       /* Test error from S3Resume() */
+       VB2_RECOVERY_RO_TEST_S3 = 0x07,
+
+       /* Test error from LoadFirmwareSetup() (deprecated) */
+       VB2_RECOVERY_RO_TEST_LFS = 0x08,
+
+       /* Test error from LoadFirmware() (deprecated) */
+       VB2_RECOVERY_RO_TEST_LF = 0x09,
+
+       /* Latest tried RW firmware keyblock verification failed */
+       VB2_RECOVERY_FW_KEYBLOCK = 0x13,
+
+       /* Latest tried RW firmware key version too old */
+       VB2_RECOVERY_FW_KEY_ROLLBACK = 0x14,
+
+       /* Latest tried RW firmware preamble verification failed */
+       VB2_RECOVERY_FW_PREAMBLE = 0x16,
+
+       /* Latest tried RW firmware version too old */
+       VB2_RECOVERY_FW_ROLLBACK = 0x17,
+
+       /* Latest tried RW firmware body verification failed */
+       VB2_RECOVERY_FW_BODY = 0x1b,
+
+       /*
+        * Firmware boot failure outside of verified boot (RAM init, missing
+        * SSD, etc.).
+        */
+       VB2_RECOVERY_RO_FIRMWARE = 0x20,
+
+       /*
+        * Recovery mode TPM initialization requires a system reboot.  The
+        * system was already in recovery mode for some other reason when this
+        * happened.
+        */
+       VB2_RECOVERY_RO_TPM_REBOOT = 0x21,
+
+       /* EC software sync - other error */
+       VB2_RECOVERY_EC_SOFTWARE_SYNC = 0x22,
+
+       /* EC software sync - unable to determine active EC image */
+       VB2_RECOVERY_EC_UNKNOWN_IMAGE = 0x23,
+
+       /* EC software sync - error obtaining EC image hash (deprecated) */
+       VB2_RECOVERY_DEP_EC_HASH = 0x24,
+
+       /* EC software sync - error obtaining expected EC image */
+       VB2_RECOVERY_EC_EXPECTED_IMAGE = 0x25,
+
+       /* EC software sync - error updating EC */
+       VB2_RECOVERY_EC_UPDATE = 0x26,
+
+       /* EC software sync - unable to jump to EC-RW */
+       VB2_RECOVERY_EC_JUMP_RW = 0x27,
+
+       /* EC software sync - unable to protect / unprotect EC-RW */
+       VB2_RECOVERY_EC_PROTECT = 0x28,
+
+       /* EC software sync - error obtaining expected EC hash */
+       VB2_RECOVERY_EC_EXPECTED_HASH = 0x29,
+
+       /* EC software sync - expected EC image doesn't match hash */
+       VB2_RECOVERY_EC_HASH_MISMATCH = 0x2a,
+
+       /* New error codes from VB2 */
+       /* TODO: may need to add strings for these in the original fwlib */
+
+       /* Secure data inititalization error */
+       VB2_RECOVERY_SECDATA_INIT = 0x2b,
+
+       /* GBB header is bad */
+       VB2_RECOVERY_GBB_HEADER = 0x2c,
+
+       /* Unable to clear TPM owner */
+       VB2_RECOVERY_TPM_CLEAR_OWNER = 0x2d,
+
+       /* Error determining/updating virtual dev switch */
+       VB2_RECOVERY_DEV_SWITCH = 0x2e,
+
+       /* Error determining firmware slot */
+       VB2_RECOVERY_FW_SLOT = 0x2f,
+
+       /* Unspecified/unknown error in read-only firmware */
+       VB2_RECOVERY_RO_UNSPECIFIED = 0x3f,
+
+       /*
+        * User manually requested recovery by pressing a key at developer
+        * warning screen
+        */
+       VB2_RECOVERY_RW_DEV_SCREEN = 0x41,
+
+       /* No OS kernel detected */
+       VB2_RECOVERY_RW_NO_OS = 0x42,
+
+       /* OS kernel failed signature check */
+       VB2_RECOVERY_RW_INVALID_OS = 0x43,
+
+       /* TPM error in rewritable firmware (deprecated) */
+       VB2_RECOVERY_DEP_RW_TPM_ERROR = 0x44,
+
+       /* RW firmware in dev mode, but dev switch is off */
+       VB2_RECOVERY_RW_DEV_MISMATCH = 0x45,
+
+       /* Shared data error in rewritable firmware */
+       VB2_RECOVERY_RW_SHARED_DATA = 0x46,
+
+       /* Test error from LoadKernel() */
+       VB2_RECOVERY_RW_TEST_LK = 0x47,
+
+       /* No bootable disk found (deprecated)*/
+       VB2_RECOVERY_DEP_RW_NO_DISK = 0x48,
+
+       /* Rebooting did not correct TPM_E_FAIL or TPM_E_FAILEDSELFTEST  */
+       VB2_RECOVERY_TPM_E_FAIL = 0x49,
+
+       /* TPM setup error in read-only firmware */
+       VB2_RECOVERY_RO_TPM_S_ERROR = 0x50,
+
+       /* TPM write error in read-only firmware */
+       VB2_RECOVERY_RO_TPM_W_ERROR = 0x51,
+
+       /* TPM lock error in read-only firmware */
+       VB2_RECOVERY_RO_TPM_L_ERROR = 0x52,
+
+       /* TPM update error in read-only firmware */
+       VB2_RECOVERY_RO_TPM_U_ERROR = 0x53,
+
+       /* TPM read error in rewritable firmware */
+       VB2_RECOVERY_RW_TPM_R_ERROR = 0x54,
+
+       /* TPM write error in rewritable firmware */
+       VB2_RECOVERY_RW_TPM_W_ERROR = 0x55,
+
+       /* TPM lock error in rewritable firmware */
+       VB2_RECOVERY_RW_TPM_L_ERROR = 0x56,
+
+       /* EC software sync unable to get EC image hash */
+       VB2_RECOVERY_EC_HASH_FAILED = 0x57,
+
+       /* EC software sync invalid image hash size */
+       VB2_RECOVERY_EC_HASH_SIZE    = 0x58,
+
+       /* Unspecified error while trying to load kernel */
+       VB2_RECOVERY_LK_UNSPECIFIED  = 0x59,
+
+       /* No bootable storage device in system */
+       VB2_RECOVERY_RW_NO_DISK      = 0x5a,
+
+       /* No bootable kernel found on disk */
+       VB2_RECOVERY_RW_NO_KERNEL    = 0x5b,
+
+       /* BCB related error in RW firmware */
+       VB2_RECOVERY_RW_BCB_ERROR    = 0x5c,
+
+       /* New error codes from VB2 */
+       /* TODO: may need to add strings for these in the original fwlib */
+
+       /* Secure data inititalization error */
+       VB2_RECOVERY_SECDATAK_INIT = 0x5d,
+
+       /* Fastboot mode requested in firmware */
+       VB2_RECOVERY_FW_FASTBOOT     = 0x5e,
+
+       /* Unspecified/unknown error in rewritable firmware */
+       VB2_RECOVERY_RW_UNSPECIFIED  = 0x7f,
+
+       /* DM-verity error */
+       VB2_RECOVERY_KE_DM_VERITY    = 0x81,
+
+       /* Unspecified/unknown error in kernel */
+       VB2_RECOVERY_KE_UNSPECIFIED  = 0xbf,
+
+       /* Recovery mode test from user-mode */
+       VB2_RECOVERY_US_TEST         = 0xc1,
+
+       /* Recovery requested by user-mode via BCB */
+       VB2_RECOVERY_BCB_USER_MODE   = 0xc2,
+
+       /* Fastboot mode requested by user-mode */
+       VB2_RECOVERY_US_FASTBOOT     = 0xc3,
+
+       /* Unspecified/unknown error in user-mode */
+       VB2_RECOVERY_US_UNSPECIFIED  = 0xff,
+};
+
+#endif  /* VBOOT_REFERENCE_VBOOT_2RECOVERY_REASONS_H_ */
diff --git a/kern/lib/crypto/include/2return_codes.h b/kern/lib/crypto/include/2return_codes.h
new file mode 100644 (file)
index 0000000..27b80d1
--- /dev/null
@@ -0,0 +1,773 @@
+/* Copyright (c) 2014 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.
+ */
+
+#ifndef VBOOT_2_RETURN_CODES_H_
+#define VBOOT_2_RETURN_CODES_H_
+
+/*
+ * Return codes from verified boot functions.
+ *
+ * Note that other values may be passed through from vb2ex_*() calls; see
+ * the comment for VB2_ERROR_EX below.
+ */
+enum vb2_return_code {
+       /* Success - no error */
+       VB2_SUCCESS = 0,
+
+       /*
+        * All vboot2 error codes start at a large offset from zero, to reduce
+        * the risk of overlap with other error codes (TPM, etc.).
+        */
+       VB2_ERROR_BASE = 0x10000000,
+
+       /* Unknown / unspecified error */
+       VB2_ERROR_UNKNOWN = VB2_ERROR_BASE + 1,
+
+       /* Mock error for testing */
+       VB2_ERROR_MOCK,
+
+        /**********************************************************************
+        * SHA errors
+        */
+       VB2_ERROR_SHA = VB2_ERROR_BASE + 0x010000,
+
+       /* Bad algorithm in vb2_digest_init() */
+       VB2_ERROR_SHA_INIT_ALGORITHM,
+
+       /* Bad algorithm in vb2_digest_extend() */
+       VB2_ERROR_SHA_EXTEND_ALGORITHM,
+
+       /* Bad algorithm in vb2_digest_finalize() */
+       VB2_ERROR_SHA_FINALIZE_ALGORITHM,
+
+       /* Digest size buffer too small in vb2_digest_finalize() */
+       VB2_ERROR_SHA_FINALIZE_DIGEST_SIZE,
+
+        /**********************************************************************
+        * RSA errors
+        */
+       VB2_ERROR_RSA = VB2_ERROR_BASE + 0x020000,
+
+       /* Padding mismatch in vb2_check_padding() */
+       VB2_ERROR_RSA_PADDING,
+
+       /* Bad algorithm in vb2_check_padding() */
+       VB2_ERROR_RSA_PADDING_ALGORITHM,
+
+       /* Null param passed to vb2_verify_digest() */
+       VB2_ERROR_RSA_VERIFY_PARAM,
+
+       /* Bad algorithm in vb2_verify_digest() */
+       VB2_ERROR_RSA_VERIFY_ALGORITHM,
+
+       /* Bad signature length in vb2_verify_digest() */
+       VB2_ERROR_RSA_VERIFY_SIG_LEN,
+
+       /* Work buffer too small in vb2_verify_digest() */
+       VB2_ERROR_RSA_VERIFY_WORKBUF,
+
+       /* Digest mismatch in vb2_verify_digest() */
+       VB2_ERROR_RSA_VERIFY_DIGEST,
+
+       /* Bad size calculation in vb2_check_padding() */
+       VB2_ERROR_RSA_PADDING_SIZE,
+
+        /**********************************************************************
+        * NV storage errors
+        */
+       VB2_ERROR_NV = VB2_ERROR_BASE + 0x030000,
+
+       /* Bad header in vb2_nv_check_crc() */
+       VB2_ERROR_NV_HEADER,
+
+       /* Bad CRC in vb2_nv_check_crc() */
+       VB2_ERROR_NV_CRC,
+
+        /**********************************************************************
+        * Secure data storage errors
+        */
+       VB2_ERROR_SECDATA = VB2_ERROR_BASE + 0x040000,
+
+       /* Bad CRC in vb2_secdata_check_crc() */
+       VB2_ERROR_SECDATA_CRC,
+
+       /* Secdata is all zeroes (uninitialized) in vb2_secdata_check_crc() */
+       VB2_ERROR_SECDATA_ZERO,
+
+       /* Invalid param in vb2_secdata_get() */
+       VB2_ERROR_SECDATA_GET_PARAM,
+
+       /* Invalid param in vb2_secdata_set() */
+       VB2_ERROR_SECDATA_SET_PARAM,
+
+       /* Invalid flags passed to vb2_secdata_set() */
+       VB2_ERROR_SECDATA_SET_FLAGS,
+
+       /* Called vb2_secdata_get() with uninitialized secdata */
+       VB2_ERROR_SECDATA_GET_UNINITIALIZED,
+
+       /* Called vb2_secdata_set() with uninitialized secdata */
+       VB2_ERROR_SECDATA_SET_UNINITIALIZED,
+
+       /* Bad CRC in vb2_secdatak_check_crc() */
+       VB2_ERROR_SECDATAK_CRC,
+
+       /* Bad struct version in vb2_secdatak_init() */
+       VB2_ERROR_SECDATAK_VERSION,
+
+       /* Bad uid in vb2_secdatak_init() */
+       VB2_ERROR_SECDATAK_UID,
+
+       /* Invalid param in vb2_secdatak_get() */
+       VB2_ERROR_SECDATAK_GET_PARAM,
+
+       /* Invalid param in vb2_secdatak_set() */
+       VB2_ERROR_SECDATAK_SET_PARAM,
+
+       /* Invalid flags passed to vb2_secdatak_set() */
+       VB2_ERROR_SECDATAK_SET_FLAGS,
+
+       /* Called vb2_secdatak_get() with uninitialized secdatak */
+       VB2_ERROR_SECDATAK_GET_UNINITIALIZED,
+
+       /* Called vb2_secdatak_set() with uninitialized secdatak */
+       VB2_ERROR_SECDATAK_SET_UNINITIALIZED,
+
+        /**********************************************************************
+        * Common code errors
+        */
+       VB2_ERROR_COMMON = VB2_ERROR_BASE + 0x050000,
+
+       /* Buffer is smaller than alignment offset in vb2_align() */
+       VB2_ERROR_ALIGN_BIGGER_THAN_SIZE,
+
+       /* Buffer is smaller than request in vb2_align() */
+       VB2_ERROR_ALIGN_SIZE,
+
+       /* Parent wraps around in vb2_verify_member_inside() */
+       VB2_ERROR_INSIDE_PARENT_WRAPS,
+
+       /* Member wraps around in vb2_verify_member_inside() */
+       VB2_ERROR_INSIDE_MEMBER_WRAPS,
+
+       /* Member outside parent in vb2_verify_member_inside() */
+       VB2_ERROR_INSIDE_MEMBER_OUTSIDE,
+
+       /* Member data wraps around in vb2_verify_member_inside() */
+       VB2_ERROR_INSIDE_DATA_WRAPS,
+
+       /* Member data outside parent in vb2_verify_member_inside() */
+       VB2_ERROR_INSIDE_DATA_OUTSIDE,
+
+       /* Unsupported signature algorithm in vb2_unpack_key() */
+       VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM,                      /* 0x150008 */
+
+       /* Bad key size in vb2_unpack_key() */
+       VB2_ERROR_UNPACK_KEY_SIZE,
+
+       /* Bad key alignment in vb2_unpack_key() */
+       VB2_ERROR_UNPACK_KEY_ALIGN,
+
+       /* Bad key array size in vb2_unpack_key() */
+       VB2_ERROR_UNPACK_KEY_ARRAY_SIZE,
+
+       /* Bad algorithm in vb2_verify_data() */
+       VB2_ERROR_VDATA_ALGORITHM,
+
+       /* Incorrect signature size for algorithm in vb2_verify_data() */
+       VB2_ERROR_VDATA_SIG_SIZE,
+
+       /* Data smaller than length of signed data in vb2_verify_data() */
+       VB2_ERROR_VDATA_NOT_ENOUGH_DATA,
+
+       /* Not enough work buffer for digest in vb2_verify_data() */
+       VB2_ERROR_VDATA_WORKBUF_DIGEST,
+
+       /* Not enough work buffer for hash temp data in vb2_verify_data() */
+       VB2_ERROR_VDATA_WORKBUF_HASHING,                         /* 0x150010 */
+
+       /*
+        * Bad digest size in vb2_verify_data() - probably because algorithm
+        * is bad.
+        */
+       VB2_ERROR_VDATA_DIGEST_SIZE,
+
+       /* Unsupported hash algorithm in vb2_unpack_key() */
+       VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM,
+
+       /* Member data overlaps member header */
+       VB2_ERROR_INSIDE_DATA_OVERLAP,
+
+       /* Unsupported packed key struct version */
+       VB2_ERROR_UNPACK_KEY_STRUCT_VERSION,
+
+       /*
+        * Buffer too small for total, fixed size, or description reported in
+        * common header, or member data checked via
+        * vb21_verify_common_member().
+        */
+       VB2_ERROR_COMMON_TOTAL_SIZE,
+       VB2_ERROR_COMMON_FIXED_SIZE,
+       VB2_ERROR_COMMON_DESC_SIZE,
+       VB2_ERROR_COMMON_MEMBER_SIZE,                            /* 0x150018 */
+
+       /*
+        * Total, fixed, description, or member offset/size not a multiple of
+        * 32 bits.
+        */
+       VB2_ERROR_COMMON_TOTAL_UNALIGNED,
+       VB2_ERROR_COMMON_FIXED_UNALIGNED,
+       VB2_ERROR_COMMON_DESC_UNALIGNED,
+       VB2_ERROR_COMMON_MEMBER_UNALIGNED,
+
+       /* Common struct description or member data wraps address space */
+       VB2_ERROR_COMMON_DESC_WRAPS,
+       VB2_ERROR_COMMON_MEMBER_WRAPS,
+
+       /* Common struct description is not null-terminated */
+       VB2_ERROR_COMMON_DESC_TERMINATOR,
+
+       /* Member data overlaps previous data */
+       VB2_ERROR_COMMON_MEMBER_OVERLAP,                         /* 0x150020 */
+
+       /* Signature bad magic number */
+       VB2_ERROR_SIG_MAGIC,
+
+       /* Signature incompatible version */
+       VB2_ERROR_SIG_VERSION,
+
+       /* Signature header doesn't fit */
+       VB2_ERROR_SIG_HEADER_SIZE,
+
+       /* Signature unsupported algorithm */
+       VB2_ERROR_SIG_ALGORITHM,
+
+       /* Signature bad size for algorithm */
+       VB2_ERROR_SIG_SIZE,
+
+       /* Wrong amount of data signed */
+       VB2_ERROR_VDATA_SIZE,
+
+       /* Digest mismatch */
+       VB2_ERROR_VDATA_VERIFY_DIGEST,
+
+       /* Key algorithm doesn't match signature algorithm */
+       VB2_ERROR_VDATA_ALGORITHM_MISMATCH,
+
+       /* Bad magic number in vb2_unpack_key() */
+       VB2_ERROR_UNPACK_KEY_MAGIC,
+
+        /**********************************************************************
+        * Keyblock verification errors (all in vb2_verify_keyblock())
+        */
+       VB2_ERROR_KEYBLOCK = VB2_ERROR_BASE + 0x060000,
+
+       /* Data buffer too small for header */
+       VB2_ERROR_KEYBLOCK_TOO_SMALL_FOR_HEADER,
+
+       /* Magic number not present */
+       VB2_ERROR_KEYBLOCK_MAGIC,
+
+       /* Header version incompatible */
+       VB2_ERROR_KEYBLOCK_HEADER_VERSION,
+
+       /* Data buffer too small for keyblock */
+       VB2_ERROR_KEYBLOCK_SIZE,
+
+       /* Signature data offset outside keyblock */
+       VB2_ERROR_KEYBLOCK_SIG_OUTSIDE,
+
+       /* Signature signed more data than size of keyblock */
+       VB2_ERROR_KEYBLOCK_SIGNED_TOO_MUCH,
+
+       /* Signature signed less data than size of keyblock header */
+       VB2_ERROR_KEYBLOCK_SIGNED_TOO_LITTLE,
+
+       /* Signature invalid */
+       VB2_ERROR_KEYBLOCK_SIG_INVALID,
+
+       /* Data key outside keyblock */
+       VB2_ERROR_KEYBLOCK_DATA_KEY_OUTSIDE,
+
+       /* Data key outside signed part of keyblock */
+       VB2_ERROR_KEYBLOCK_DATA_KEY_UNSIGNED,
+
+       /* Signature signed wrong amount of data */
+       VB2_ERROR_KEYBLOCK_SIGNED_SIZE,
+
+       /* No signature matching key ID */
+       VB2_ERROR_KEYBLOCK_SIG_ID,
+
+        /**********************************************************************
+        * Preamble verification errors (all in vb2_verify_preamble())
+        */
+       VB2_ERROR_PREAMBLE = VB2_ERROR_BASE + 0x070000,
+
+       /* Preamble data too small to contain header */
+       VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER,
+
+       /* Header version incompatible */
+       VB2_ERROR_PREAMBLE_HEADER_VERSION,
+
+       /* Header version too old */
+       VB2_ERROR_PREAMBLE_HEADER_OLD,
+
+       /* Data buffer too small for preamble */
+       VB2_ERROR_PREAMBLE_SIZE,
+
+       /* Signature data offset outside preamble */
+       VB2_ERROR_PREAMBLE_SIG_OUTSIDE,
+
+       /* Signature signed more data than size of preamble */
+       VB2_ERROR_PREAMBLE_SIGNED_TOO_MUCH,
+
+       /* Signature signed less data than size of preamble header */
+       VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE,
+
+       /* Signature invalid */
+       VB2_ERROR_PREAMBLE_SIG_INVALID,
+
+       /* Body signature outside preamble */
+       VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE,
+
+       /* Kernel subkey outside preamble */
+       VB2_ERROR_PREAMBLE_KERNEL_SUBKEY_OUTSIDE,
+
+       /* Bad magic number */
+       VB2_ERROR_PREAMBLE_MAGIC,
+
+       /* Hash is signed */
+       VB2_ERROR_PREAMBLE_HASH_SIGNED,
+
+       /* Bootloader outside signed portion of body */
+       VB2_ERROR_PREAMBLE_BOOTLOADER_OUTSIDE,
+
+       /* Vmlinuz header outside signed portion of body */
+       VB2_ERROR_PREAMBLE_VMLINUZ_HEADER_OUTSIDE,
+
+        /**********************************************************************
+        * Misc higher-level code errors
+        */
+       VB2_ERROR_MISC = VB2_ERROR_BASE + 0x080000,
+
+       /* Work buffer too small in vb2_init_context() */
+       VB2_ERROR_INITCTX_WORKBUF_SMALL,
+
+       /* Work buffer unaligned in vb2_init_context() */
+       VB2_ERROR_INITCTX_WORKBUF_ALIGN,
+
+       /* Work buffer too small in vb2_fw_parse_gbb() */
+       VB2_ERROR_GBB_WORKBUF,
+
+       /* Bad magic number in vb2_read_gbb_header() */
+       VB2_ERROR_GBB_MAGIC,
+
+       /* Incompatible version in vb2_read_gbb_header() */
+       VB2_ERROR_GBB_VERSION,
+
+       /* Old version in vb2_read_gbb_header() */
+       VB2_ERROR_GBB_TOO_OLD,
+
+       /* Header size too small in vb2_read_gbb_header() */
+       VB2_ERROR_GBB_HEADER_SIZE,
+
+       /* Work buffer too small for root key in vb2_load_fw_keyblock() */
+       VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY,
+
+       /* Work buffer too small for header in vb2_load_fw_keyblock() */
+       VB2_ERROR_FW_KEYBLOCK_WORKBUF_HEADER,
+
+       /* Work buffer too small for keyblock in vb2_load_fw_keyblock() */
+       VB2_ERROR_FW_KEYBLOCK_WORKBUF,
+
+       /* Keyblock version out of range in vb2_load_fw_keyblock() */
+       VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE,
+
+       /* Keyblock version rollback in vb2_load_fw_keyblock() */
+       VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK,
+
+       /* Missing firmware data key in vb2_load_fw_preamble() */
+       VB2_ERROR_FW_PREAMBLE2_DATA_KEY,
+
+       /* Work buffer too small for header in vb2_load_fw_preamble() */
+       VB2_ERROR_FW_PREAMBLE2_WORKBUF_HEADER,
+
+       /* Work buffer too small for preamble in vb2_load_fw_preamble() */
+       VB2_ERROR_FW_PREAMBLE2_WORKBUF,
+
+       /* Firmware version out of range in vb2_load_fw_preamble() */
+       VB2_ERROR_FW_PREAMBLE_VERSION_RANGE,
+
+       /* Firmware version rollback in vb2_load_fw_preamble() */
+       VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK,
+
+       /* Not enough space in work buffer for resource object */
+       VB2_ERROR_READ_RESOURCE_OBJECT_BUF,
+
+       /* Work buffer too small for header in vb2_load_kernel_keyblock() */
+       VB2_ERROR_KERNEL_KEYBLOCK_WORKBUF_HEADER,
+
+       /* Work buffer too small for keyblock in vb2_load_kernel_keyblock() */
+       VB2_ERROR_KERNEL_KEYBLOCK_WORKBUF,
+
+       /* Keyblock version out of range in vb2_load_kernel_keyblock() */
+       VB2_ERROR_KERNEL_KEYBLOCK_VERSION_RANGE,
+
+       /* Keyblock version rollback in vb2_load_kernel_keyblock() */
+       VB2_ERROR_KERNEL_KEYBLOCK_VERSION_ROLLBACK,
+
+       /*
+        * Keyblock flags don't match current mode in
+        * vb2_load_kernel_keyblock().
+        */
+       VB2_ERROR_KERNEL_KEYBLOCK_DEV_FLAG,
+       VB2_ERROR_KERNEL_KEYBLOCK_REC_FLAG,
+
+       /* Missing firmware data key in vb2_load_kernel_preamble() */
+       VB2_ERROR_KERNEL_PREAMBLE2_DATA_KEY,
+
+       /* Work buffer too small for header in vb2_load_kernel_preamble() */
+       VB2_ERROR_KERNEL_PREAMBLE2_WORKBUF_HEADER,
+
+       /* Work buffer too small for preamble in vb2_load_kernel_preamble() */
+       VB2_ERROR_KERNEL_PREAMBLE2_WORKBUF,
+
+       /* Kernel version out of range in vb2_load_kernel_preamble() */
+       VB2_ERROR_KERNEL_PREAMBLE_VERSION_RANGE,
+
+       /* Kernel version rollback in vb2_load_kernel_preamble() */
+       VB2_ERROR_KERNEL_PREAMBLE_VERSION_ROLLBACK,
+
+       /* Kernel preamble not loaded before calling vb2api_get_kernel_size() */
+       VB2_ERROR_API_GET_KERNEL_SIZE_PREAMBLE,
+
+        /**********************************************************************
+        * API-level errors
+        */
+       VB2_ERROR_API = VB2_ERROR_BASE + 0x090000,
+
+       /* Bad tag in vb2api_init_hash() */
+       VB2_ERROR_API_INIT_HASH_TAG,
+
+       /* Preamble not present in vb2api_init_hash() */
+       VB2_ERROR_API_INIT_HASH_PREAMBLE,
+
+       /* Work buffer too small in vb2api_init_hash() */
+       VB2_ERROR_API_INIT_HASH_WORKBUF,
+
+       /* Missing firmware data key in vb2api_init_hash() */
+       VB2_ERROR_API_INIT_HASH_DATA_KEY,
+
+       /* Uninitialized work area in vb2api_extend_hash() */
+       VB2_ERROR_API_EXTEND_HASH_WORKBUF,
+
+       /* Too much data hashed in vb2api_extend_hash() */
+       VB2_ERROR_API_EXTEND_HASH_SIZE,
+
+       /* Preamble not present in vb2api_check_hash() */
+       VB2_ERROR_API_CHECK_HASH_PREAMBLE,
+
+       /* Uninitialized work area in vb2api_check_hash() */
+       VB2_ERROR_API_CHECK_HASH_WORKBUF,
+
+       /* Wrong amount of data hashed in vb2api_check_hash() */
+       VB2_ERROR_API_CHECK_HASH_SIZE,
+
+       /* Work buffer too small in vb2api_check_hash() */
+       VB2_ERROR_API_CHECK_HASH_WORKBUF_DIGEST,
+
+       /* Bad tag in vb2api_check_hash() */
+       VB2_ERROR_API_CHECK_HASH_TAG,
+
+       /* Missing firmware data key in vb2api_check_hash() */
+       VB2_ERROR_API_CHECK_HASH_DATA_KEY,
+
+       /* Signature size mismatch in vb2api_check_hash() */
+       VB2_ERROR_API_CHECK_HASH_SIG_SIZE,
+
+       /* Phase one needs recovery mode */
+       VB2_ERROR_API_PHASE1_RECOVERY,
+
+       /* Bad tag in vb2api_check_hash() */
+       VB2_ERROR_API_INIT_HASH_ID,
+
+       /* Signature mismatch in vb2api_check_hash() */
+       VB2_ERROR_API_CHECK_HASH_SIG,
+
+       /* Invalid enum vb2_pcr_digest requested to vb2api_get_pcr_digest */
+       VB2_ERROR_API_PCR_DIGEST,
+
+       /* Buffer size for the digest is too small for vb2api_get_pcr_digest */
+       VB2_ERROR_API_PCR_DIGEST_BUF,
+
+       /* Work buffer too small for recovery key in vb2api_kernel_phase1() */
+       VB2_ERROR_API_KPHASE1_WORKBUF_REC_KEY,
+
+       /* Firmware preamble not present for vb2api_kernel_phase1() */
+       VB2_ERROR_API_KPHASE1_PREAMBLE,
+
+       /* Wrong amount of kernel data in vb2api_verify_kernel_data() */
+       VB2_ERROR_API_VERIFY_KDATA_SIZE,
+
+       /* Kernel preamble not present for vb2api_verify_kernel_data() */
+       VB2_ERROR_API_VERIFY_KDATA_PREAMBLE,
+
+       /* Insufficient workbuf for hashing in vb2api_verify_kernel_data() */
+       VB2_ERROR_API_VERIFY_KDATA_WORKBUF,
+
+       /* Bad data key in vb2api_verify_kernel_data() */
+       VB2_ERROR_API_VERIFY_KDATA_KEY,
+
+       /* Phase one passing through secdata's request to reboot */
+       VB2_ERROR_API_PHASE1_SECDATA_REBOOT,
+
+       /* Digest buffer passed into vb2api_check_hash incorrect. */
+       VB2_ERROR_API_CHECK_DIGEST_SIZE,
+
+        /**********************************************************************
+        * Errors which may be generated by implementations of vb2ex functions.
+        * Implementation may also return its own specific errors, which should
+        * NOT be in the range VB2_ERROR_BASE...VB2_ERROR_MAX to avoid
+        * conflicting with future vboot2 error codes.
+        */
+       VB2_ERROR_EX = VB2_ERROR_BASE + 0x0a0000,
+
+       /* Read resource not implemented */
+       VB2_ERROR_EX_READ_RESOURCE_UNIMPLEMENTED,
+
+       /* Resource index not found */
+       VB2_ERROR_EX_READ_RESOURCE_INDEX,
+
+       /* Size of resource not big enough for requested offset and/or size */
+       VB2_ERROR_EX_READ_RESOURCE_SIZE,
+
+       /* TPM clear owner failed */
+       VB2_ERROR_EX_TPM_CLEAR_OWNER,
+
+       /* TPM clear owner not implemented */
+       VB2_ERROR_EX_TPM_CLEAR_OWNER_UNIMPLEMENTED,
+
+       /* Hardware crypto engine doesn't support this algorithm (non-fatal) */
+       VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED,
+
+
+        /**********************************************************************
+        * Errors generated by host library (non-firmware) start here.
+        */
+       VB2_ERROR_HOST_BASE = 0x20000000,
+
+        /**********************************************************************
+        * Errors generated by host library misc functions
+        */
+       VB2_ERROR_HOST_MISC = VB2_ERROR_HOST_BASE + 0x010000,
+
+       /* Unable to open file in read_file() */
+       VB2_ERROR_READ_FILE_OPEN,
+
+       /* Bad size in read_file() */
+       VB2_ERROR_READ_FILE_SIZE,
+
+       /* Unable to allocate buffer in read_file() */
+       VB2_ERROR_READ_FILE_ALLOC,
+
+       /* Unable to read data in read_file() */
+       VB2_ERROR_READ_FILE_DATA,
+
+       /* Unable to open file in write_file() */
+       VB2_ERROR_WRITE_FILE_OPEN,
+
+       /* Unable to write data in write_file() */
+       VB2_ERROR_WRITE_FILE_DATA,
+
+       /* Unable to convert string to struct vb_id */
+       VB2_ERROR_STR_TO_ID,
+
+        /**********************************************************************
+        * Errors generated by host library key functions
+        */
+       VB2_ERROR_HOST_KEY = VB2_ERROR_HOST_BASE + 0x020000,
+
+       /* Unable to allocate key  in vb2_private_key_read_pem() */
+       VB2_ERROR_READ_PEM_ALLOC,
+
+       /* Unable to open .pem file in vb2_private_key_read_pem() */
+       VB2_ERROR_READ_PEM_FILE_OPEN,
+
+       /* Bad RSA data from .pem file in vb2_private_key_read_pem() */
+       VB2_ERROR_READ_PEM_RSA,
+
+       /* Unable to set private key description */
+       VB2_ERROR_PRIVATE_KEY_SET_DESC,
+
+       /* Bad magic number in vb2_private_key_unpack() */
+       VB2_ERROR_UNPACK_PRIVATE_KEY_MAGIC,
+
+       /* Bad common header in vb2_private_key_unpack() */
+       VB2_ERROR_UNPACK_PRIVATE_KEY_HEADER,
+
+       /* Bad key data in vb2_private_key_unpack() */
+       VB2_ERROR_UNPACK_PRIVATE_KEY_DATA,
+
+       /* Bad struct version in vb2_private_key_unpack() */
+       VB2_ERROR_UNPACK_PRIVATE_KEY_STRUCT_VERSION,
+
+       /* Unable to allocate buffer in vb2_private_key_unpack() */
+       VB2_ERROR_UNPACK_PRIVATE_KEY_ALLOC,
+
+       /* Unable to unpack RSA key in vb2_private_key_unpack() */
+       VB2_ERROR_UNPACK_PRIVATE_KEY_RSA,
+
+       /* Unable to set description in vb2_private_key_unpack() */
+       VB2_ERROR_UNPACK_PRIVATE_KEY_DESC,
+
+       /* Bad bare hash key in vb2_private_key_unpack() */
+       VB2_ERROR_UNPACK_PRIVATE_KEY_HASH,
+
+       /* Unable to create RSA data in vb2_private_key_write() */
+       VB2_ERROR_PRIVATE_KEY_WRITE_RSA,
+
+       /* Unable to allocate packed key buffer in vb2_private_key_write() */
+       VB2_ERROR_PRIVATE_KEY_WRITE_ALLOC,
+
+       /* Unable to write file in vb2_private_key_write() */
+       VB2_ERROR_PRIVATE_KEY_WRITE_FILE,
+
+       /* Bad algorithm in vb2_private_key_hash() */
+       VB2_ERROR_PRIVATE_KEY_HASH,
+
+       /* Unable to determine key size in vb2_public_key_alloc() */
+       VB2_ERROR_PUBLIC_KEY_ALLOC_SIZE,
+
+       /* Unable to allocate buffer in vb2_public_key_alloc() */
+       VB2_ERROR_PUBLIC_KEY_ALLOC,
+
+       /* Unable to set public key description */
+       VB2_ERROR_PUBLIC_KEY_SET_DESC,
+
+       /* Unable to read key data in vb2_public_key_read_keyb() */
+       VB2_ERROR_READ_KEYB_DATA,
+
+       /* Wrong amount of data read in vb2_public_key_read_keyb() */
+       VB2_ERROR_READ_KEYB_SIZE,
+
+       /* Unable to allocate key buffer in vb2_public_key_read_keyb() */
+       VB2_ERROR_READ_KEYB_ALLOC,
+
+       /* Error unpacking RSA arrays in vb2_public_key_read_keyb() */
+       VB2_ERROR_READ_KEYB_UNPACK,
+
+       /* Unable to read key data in vb2_packed_key_read() */
+       VB2_ERROR_READ_PACKED_KEY_DATA,
+
+       /* Bad key data in vb2_packed_key_read() */
+       VB2_ERROR_READ_PACKED_KEY,
+
+       /* Unable to determine key size in vb2_public_key_pack() */
+       VB2_ERROR_PUBLIC_KEY_PACK_SIZE,
+
+       /* Bad hash algorithm in vb2_public_key_hash() */
+       VB2_ERROR_PUBLIC_KEY_HASH,
+
+       /* Bad key size in vb2_copy_packed_key() */
+       VB2_ERROR_COPY_KEY_SIZE,
+
+       /* Unable to convert back to vb1 crypto algorithm */
+       VB2_ERROR_VB1_CRYPTO_ALGORITHM,
+
+       /* Unable to allocate packed key */
+       VB2_ERROR_PACKED_KEY_ALLOC,
+
+       /* Unable to copy packed key */
+       VB2_ERROR_PACKED_KEY_COPY,
+
+        /**********************************************************************
+        * Errors generated by host library signature functions
+        */
+       VB2_ERROR_HOST_SIG = VB2_ERROR_HOST_BASE + 0x030000,
+
+       /* Bad hash algorithm in vb2_digest_info() */
+       VB2_ERROR_DIGEST_INFO,
+
+       /*
+        * Unable to determine signature size for key algorithm in
+        * vb2_sig_size_for_key().
+        */
+       VB2_ERROR_SIG_SIZE_FOR_KEY,
+
+       /* Bad signature size in vb2_sign_data() */
+       VB2_SIGN_DATA_SIG_SIZE,
+
+       /* Unable to get digest info in vb2_sign_data() */
+       VB2_SIGN_DATA_DIGEST_INFO,
+
+       /* Unable to get digest size in vb2_sign_data() */
+       VB2_SIGN_DATA_DIGEST_SIZE,
+
+       /* Unable to allocate digest buffer in vb2_sign_data() */
+       VB2_SIGN_DATA_DIGEST_ALLOC,
+
+       /* Unable to initialize digest in vb2_sign_data() */
+       VB2_SIGN_DATA_DIGEST_INIT,
+
+       /* Unable to extend digest in vb2_sign_data() */
+       VB2_SIGN_DATA_DIGEST_EXTEND,
+
+       /* Unable to finalize digest in vb2_sign_data() */
+       VB2_SIGN_DATA_DIGEST_FINALIZE,
+
+       /* RSA encrypt failed in vb2_sign_data() */
+       VB2_SIGN_DATA_RSA_ENCRYPT,
+
+       /* Not enough buffer space to hold signature in vb2_sign_object() */
+       VB2_SIGN_OBJECT_OVERFLOW,
+
+        /**********************************************************************
+        * Errors generated by host library keyblock functions
+        */
+       VB2_ERROR_HOST_KEYBLOCK = VB2_ERROR_HOST_BASE + 0x040000,
+
+       /* Unable to determine signature sizes for vb2_create_keyblock() */
+       VB2_KEYBLOCK_CREATE_SIG_SIZE,
+
+       /* Unable to pack data key for vb2_create_keyblock() */
+       VB2_KEYBLOCK_CREATE_DATA_KEY,
+
+       /* Unable to allocate buffer in vb2_create_keyblock() */
+       VB2_KEYBLOCK_CREATE_ALLOC,
+
+       /* Unable to sign keyblock in vb2_create_keyblock() */
+       VB2_KEYBLOCK_CREATE_SIGN,
+
+        /**********************************************************************
+        * Errors generated by host library firmware preamble functions
+        */
+       VB2_ERROR_HOST_FW_PREAMBLE = VB2_ERROR_HOST_BASE + 0x050000,
+
+       /* Unable to determine signature sizes for vb2_create_fw_preamble() */
+       VB2_FW_PREAMBLE_CREATE_SIG_SIZE,
+
+       /* Unable to allocate buffer in vb2_create_fw_preamble() */
+       VB2_FW_PREAMBLE_CREATE_ALLOC,
+
+       /* Unable to sign preamble in vb2_create_fw_preamble() */
+       VB2_FW_PREAMBLE_CREATE_SIGN,
+
+        /**********************************************************************
+        * Errors generated by unit test functions
+        */
+       VB2_ERROR_UNIT_TEST = VB2_ERROR_HOST_BASE + 0x060000,
+
+       /* Unable to open an input file needed for a unit test */
+       VB2_ERROR_TEST_INPUT_FILE,
+
+        /**********************************************************************
+        * Highest non-zero error generated inside vboot library.  Note that
+        * error codes passed through vboot when it calls external APIs may
+        * still be outside this range.
+        */
+       VB2_ERROR_MAX = VB2_ERROR_BASE + 0x1fffffff,
+};
+
+#endif  /* VBOOT_2_RETURN_CODES_H_ */
diff --git a/kern/lib/crypto/include/2rsa.h b/kern/lib/crypto/include/2rsa.h
new file mode 100644 (file)
index 0000000..7e63a6a
--- /dev/null
@@ -0,0 +1,80 @@
+/* Copyright (c) 2014 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.
+ */
+
+#ifndef VBOOT_REFERENCE_2RSA_H_
+#define VBOOT_REFERENCE_2RSA_H_
+
+#include "2crypto.h"
+#include "2struct.h"
+
+struct vb2_workbuf;
+
+/* Public key structure in RAM */
+struct vb2_public_key {
+       uint32_t arrsize;    /* Length of n[] and rr[] in number of uint32_t */
+       uint32_t n0inv;      /* -1 / n[0] mod 2^32 */
+       const uint32_t *n;   /* Modulus as little endian array */
+       const uint32_t *rr;  /* R^2 as little endian array */
+       enum vb2_signature_algorithm sig_alg;   /* Signature algorithm */
+       enum vb2_hash_algorithm hash_alg;       /* Hash algorithm */
+       const char *desc;                       /* Description */
+       uint32_t version;                       /* Key version */
+       const struct vb2_id *id;                /* Key ID */
+};
+
+/**
+ * Convert vb2_crypto_algorithm to vb2_signature_algorithm.
+ *
+ * @param algorithm    Crypto algorithm (vb2_crypto_algorithm)
+ *
+ * @return The signature algorithm for that crypto algorithm, or
+ * VB2_SIG_INVALID if the crypto algorithm or its corresponding signature
+ * algorithm is invalid or not supported.
+ */
+enum vb2_signature_algorithm vb2_crypto_to_signature(uint32_t algorithm);
+
+/**
+ * Return the size of a RSA signature
+ *
+ * @param sig_alg      Signature algorithm
+ * @return The size of the signature in bytes, or 0 if error.
+ */
+uint32_t vb2_rsa_sig_size(enum vb2_signature_algorithm sig_alg);
+
+/**
+ * Return the size of a pre-processed RSA public key.
+ *
+ * @param sig_alg      Signature algorithm
+ * @return The size of the preprocessed key in bytes, or 0 if error.
+ */
+uint32_t vb2_packed_key_size(enum vb2_signature_algorithm sig_alg);
+
+/**
+ * Check pkcs 1.5 padding bytes
+ *
+ * @param sig          Signature to verify
+ * @param key          Key to take signature and hash algorithms from
+ * @return VB2_SUCCESS, or non-zero if error.
+ */
+int vb2_check_padding(const uint8_t *sig, const struct vb2_public_key *key);
+
+/* Size of work buffer sufficient for vb2_rsa_verify_digest() worst case */
+#define VB2_VERIFY_RSA_DIGEST_WORKBUF_BYTES (3 * 1024)
+
+/**
+ * Verify a RSA PKCS1.5 signature against an expected hash digest.
+ *
+ * @param key          Key to use in signature verification
+ * @param sig          Signature to verify (destroyed in process)
+ * @param digest       Digest of signed data
+ * @param wb           Work buffer
+ * @return VB2_SUCCESS, or non-zero if error.
+ */
+int vb2_rsa_verify_digest(const struct vb2_public_key *key,
+                         uint8_t *sig,
+                         const uint8_t *digest,
+                         const struct vb2_workbuf *wb);
+
+#endif  /* VBOOT_REFERENCE_2RSA_H_ */
diff --git a/kern/lib/crypto/include/2secdata.h b/kern/lib/crypto/include/2secdata.h
new file mode 100644 (file)
index 0000000..d27432e
--- /dev/null
@@ -0,0 +1,219 @@
+/* Copyright (c) 2014 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.
+ *
+ * Secure non-volatile storage routines
+ */
+
+#ifndef VBOOT_REFERENCE_VBOOT_SECDATA_H_
+#define VBOOT_REFERENCE_VBOOT_SECDATA_H_
+
+/*****************************************************************************/
+/* Firmware version space */
+
+/* Expected value of vb2_secdata.version */
+#define VB2_SECDATA_VERSION 2
+
+/* Flags for firmware space */
+enum vb2_secdata_flags {
+       /*
+        * Last boot was developer mode.  TPM ownership is cleared when
+        * transitioning to/from developer mode.  Set/cleared by
+        * vb2_check_dev_switch().
+        */
+       VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER = (1 << 0),
+
+       /*
+        * Virtual developer mode switch is on.  Set/cleared by the
+        * keyboard-controlled dev screens in recovery mode.  Cleared by
+        * vb2_check_dev_switch().
+        */
+       VB2_SECDATA_FLAG_DEV_MODE = (1 << 1),
+};
+
+/* Secure data area (firmware space) */
+struct vb2_secdata {
+       /* Struct version, for backwards compatibility */
+       uint8_t struct_version;
+
+       /* Flags; see vb2_secdata_flags */
+       uint8_t flags;
+
+       /* Firmware versions */
+       uint32_t fw_versions;
+
+       /* Reserved for future expansion */
+       uint8_t reserved[3];
+
+       /* CRC; must be last field in struct */
+       uint8_t crc8;
+} __attribute__((packed));
+
+/* Which param to get/set for vb2_secdata_get() / vb2_secdata_set() */
+enum vb2_secdata_param {
+       /* Flags; see vb2_secdata_flags */
+       VB2_SECDATA_FLAGS = 0,
+
+       /* Firmware versions */
+       VB2_SECDATA_VERSIONS,
+};
+
+/*****************************************************************************/
+/* Kernel version space */
+
+/* Kernel space - KERNEL_NV_INDEX, locked with physical presence. */
+#define VB2_SECDATAK_VERSION 2
+#define VB2_SECDATAK_UID 0x4752574c  /* 'GRWL' */
+
+struct vb2_secdatak {
+       /* Struct version, for backwards compatibility */
+       uint8_t struct_version;
+
+       /* Unique ID to detect space redefinition */
+       uint32_t uid;
+
+       /* Kernel versions */
+       uint32_t kernel_versions;
+
+       /* Reserved for future expansion */
+       uint8_t reserved[3];
+
+       /* CRC; must be last field in struct */
+       uint8_t crc8;
+} __attribute__((packed));
+
+/* Which param to get/set for vb2_secdatak_get() / vb2_secdatak_set() */
+enum vb2_secdatak_param {
+       /* Kernel versions */
+       VB2_SECDATAK_VERSIONS = 0,
+};
+
+/*****************************************************************************/
+/* Firmware version space functions */
+
+/**
+ * Check the CRC of the secure storage context.
+ *
+ * Use this if reading from secure storage may be flaky, and you want to retry
+ * reading it several times.
+ *
+ * This may be called before vb2_context_init().
+ *
+ * @param ctx          Context pointer
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2_secdata_check_crc(const struct vb2_context *ctx);
+
+/**
+ * Create fresh data in the secure storage context.
+ *
+ * Use this only when initializing the secure storage context on a new machine
+ * the first time it boots.  Do NOT simply use this if vb2_secdata_check_crc()
+ * (or any other API in this library) fails; that could allow the secure data
+ * to be rolled back to an insecure state.
+ *
+ * This may be called before vb2_context_init().
+ */
+int vb2_secdata_create(struct vb2_context *ctx);
+
+/**
+ * Initialize the secure storage context and verify its CRC.
+ *
+ * This must be called before vb2_secdata_get() or vb2_secdata_set().
+ *
+ * @param ctx          Context pointer
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2_secdata_init(struct vb2_context *ctx);
+
+/**
+ * Read a secure storage value.
+ *
+ * @param ctx          Context pointer
+ * @param param                Parameter to read
+ * @param dest         Destination for value
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2_secdata_get(struct vb2_context *ctx,
+                   enum vb2_secdata_param param,
+                   uint32_t *dest);
+
+/**
+ * Write a secure storage value.
+ *
+ * @param ctx          Context pointer
+ * @param param                Parameter to write
+ * @param value                New value
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2_secdata_set(struct vb2_context *ctx,
+                   enum vb2_secdata_param param,
+                   uint32_t value);
+
+/*****************************************************************************/
+/* Kernel version space functions.
+ *
+ * These are separate functions so that they don't bloat the size of the early
+ * boot code which uses the firmware version space functions.
+ */
+
+/**
+ * Check the CRC of the kernel version secure storage context.
+ *
+ * Use this if reading from secure storage may be flaky, and you want to retry
+ * reading it several times.
+ *
+ * This may be called before vb2_context_init().
+ *
+ * @param ctx          Context pointer
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2_secdatak_check_crc(const struct vb2_context *ctx);
+
+/**
+ * Create fresh data in the secure storage context.
+ *
+ * Use this only when initializing the secure storage context on a new machine
+ * the first time it boots.  Do NOT simply use this if vb2_secdatak_check_crc()
+ * (or any other API in this library) fails; that could allow the secure data
+ * to be rolled back to an insecure state.
+ *
+ * This may be called before vb2_context_init().
+ */
+int vb2_secdatak_create(struct vb2_context *ctx);
+
+/**
+ * Initialize the secure storage context and verify its CRC.
+ *
+ * This must be called before vb2_secdatak_get() or vb2_secdatak_set().
+ *
+ * @param ctx          Context pointer
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2_secdatak_init(struct vb2_context *ctx);
+
+/**
+ * Read a secure storage value.
+ *
+ * @param ctx          Context pointer
+ * @param param                Parameter to read
+ * @param dest         Destination for value
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2_secdatak_get(struct vb2_context *ctx,
+                    enum vb2_secdatak_param param,
+                    uint32_t *dest);
+
+/**
+ * Write a secure storage value.
+ *
+ * @param ctx          Context pointer
+ * @param param                Parameter to write
+ * @param value                New value
+ * @return VB2_SUCCESS, or non-zero error code if error.
+ */
+int vb2_secdatak_set(struct vb2_context *ctx,
+                    enum vb2_secdatak_param param,
+                    uint32_t value);
+
+#endif  /* VBOOT_REFERENCE_VBOOT_2SECDATA_H_ */
diff --git a/kern/lib/crypto/include/2sha.h b/kern/lib/crypto/include/2sha.h
new file mode 100644 (file)
index 0000000..38b8a81
--- /dev/null
@@ -0,0 +1,232 @@
+/* Copyright (c) 2014 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.
+ *
+ * These APIs may be called by external firmware as well as vboot.  External
+ * firmware must NOT include this header file directly; instead, define
+ * NEED_VB2_SHA_LIBRARY and include vb2api.h.  This is permissible because the
+ * SHA library routines below don't interact with the rest of vboot.
+ */
+
+#ifndef VBOOT_REFERENCE_2SHA_H_
+#define VBOOT_REFERENCE_2SHA_H_
+
+#include "2crypto.h"
+
+/* Hash algorithms may be disabled individually to save code space */
+
+#ifndef VB2_SUPPORT_SHA1
+#define VB2_SUPPORT_SHA1 1
+#endif
+
+#ifndef VB2_SUPPORT_SHA256
+#define VB2_SUPPORT_SHA256 1
+#endif
+
+#ifndef VB2_SUPPORT_SHA512
+#define VB2_SUPPORT_SHA512 1
+#endif
+
+/* These are set to the biggest values among the supported hash algorithms.
+ * They have to be updated as we add new hash algorithms */
+#define VB2_MAX_DIGEST_SIZE    VB2_SHA512_DIGEST_SIZE
+#define VB2_MAX_BLOCK_SIZE     VB2_SHA512_BLOCK_SIZE
+#define VB2_INVALID_ALG_NAME   "INVALID"
+
+#define VB2_SHA1_DIGEST_SIZE 20
+#define VB2_SHA1_BLOCK_SIZE 64
+#define VB2_SHA1_ALG_NAME      "SHA1"
+
+/* Context structs for hash algorithms */
+
+struct vb2_sha1_context {
+       uint32_t count;
+       uint32_t state[5];
+#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
+       union {
+               uint8_t b[VB2_SHA1_BLOCK_SIZE];
+               uint32_t w[VB2_SHA1_BLOCK_SIZE / sizeof(uint32_t)];
+       } buf;
+#else
+       uint8_t buf[VB2_SHA1_BLOCK_SIZE];
+#endif
+};
+
+#define VB2_SHA256_DIGEST_SIZE 32
+#define VB2_SHA256_BLOCK_SIZE 64
+#define VB2_SHA256_ALG_NAME    "SHA256"
+
+struct vb2_sha256_context {
+       uint32_t h[8];
+       uint32_t total_size;
+       uint32_t size;
+       uint8_t block[2 * VB2_SHA256_BLOCK_SIZE];
+};
+
+#define VB2_SHA512_DIGEST_SIZE 64
+#define VB2_SHA512_BLOCK_SIZE 128
+#define VB2_SHA512_ALG_NAME    "SHA512"
+
+struct vb2_sha512_context {
+       uint64_t h[8];
+       uint32_t total_size;
+       uint32_t size;
+       uint8_t block[2 * VB2_SHA512_BLOCK_SIZE];
+};
+
+/* Hash algorithm independent digest context; includes all of the above. */
+struct vb2_digest_context {
+       /* Context union for all algorithms */
+       union {
+#if VB2_SUPPORT_SHA1
+               struct vb2_sha1_context sha1;
+#endif
+#if VB2_SUPPORT_SHA256
+               struct vb2_sha256_context sha256;
+#endif
+#if VB2_SUPPORT_SHA512
+               struct vb2_sha512_context sha512;
+#endif
+       };
+
+       /* Current hash algorithm */
+       enum vb2_hash_algorithm hash_alg;
+
+       /* 1 if digest is computed with vb2ex_hwcrypto routines, else 0 */
+       int using_hwcrypto;
+};
+
+/**
+ * Initialize a hash context.
+ *
+ * @param ctx          Hash context
+ */
+void vb2_sha1_init(struct vb2_sha1_context *ctx);
+void vb2_sha256_init(struct vb2_sha256_context *ctx);
+void vb2_sha512_init(struct vb2_sha512_context *ctx);
+
+/**
+ * Update (extend) a hash.
+ *
+ * @param ctx          Hash context
+ * @param data         Data to hash
+ * @param size         Length of data in bytes
+ */
+void vb2_sha1_update(struct vb2_sha1_context *ctx,
+                    const uint8_t *data,
+                    uint32_t size);
+void vb2_sha256_update(struct vb2_sha256_context *ctx,
+                      const uint8_t *data,
+                      uint32_t size);
+void vb2_sha512_update(struct vb2_sha512_context *ctx,
+                      const uint8_t *data,
+                      uint32_t size);
+
+/**
+ * Finalize a hash digest.
+ *
+ * @param ctx          Hash context
+ * @param digest       Destination for hash; must be VB_SHA*_DIGEST_SIZE bytes
+ */
+void vb2_sha1_finalize(struct vb2_sha1_context *ctx, uint8_t *digest);
+void vb2_sha256_finalize(struct vb2_sha256_context *ctx, uint8_t *digest);
+void vb2_sha512_finalize(struct vb2_sha512_context *ctx, uint8_t *digest);
+
+/**
+ * Hash-extend data
+ *
+ * @param from Hash to be extended. It has to be the hash size.
+ * @param by   Block to be extended by. It has to be the hash block size.
+ * @param to   Destination for extended data
+ */
+void vb2_sha256_extend(const uint8_t *from, const uint8_t *by, uint8_t *to);
+
+/**
+ * Convert vb2_crypto_algorithm to vb2_hash_algorithm.
+ *
+ * @param algorithm    Crypto algorithm (vb2_crypto_algorithm)
+ *
+ * @return The hash algorithm for that crypto algorithm, or VB2_HASH_INVALID if
+ * the crypto algorithm or its corresponding hash algorithm is invalid or not
+ * supported.
+ */
+enum vb2_hash_algorithm vb2_crypto_to_hash(uint32_t algorithm);
+
+/**
+ * Return the size of the digest for a hash algorithm.
+ *
+ * @param hash_alg     Hash algorithm
+ * @return The size of the digest, or 0 if error.
+ */
+int vb2_digest_size(enum vb2_hash_algorithm hash_alg);
+
+/**
+ * Return the block size of a hash algorithm.
+ *
+ * @param hash_alg     Hash algorithm
+ * @return The block size of the algorithm, or 0 if error.
+ */
+int vb2_hash_block_size(enum vb2_hash_algorithm alg);
+
+/**
+ * Return the name of a hash algorithm
+ *
+ * @param alg  Hash algorithm ID
+ * @return     String containing a hash name or VB2_INVALID_ALG_NAME
+ *             if <alg> is invalid.
+ */
+const char *vb2_get_hash_algorithm_name(enum vb2_hash_algorithm alg);
+
+/**
+ * Initialize a digest context for doing block-style digesting.
+ *
+ * @param dc           Digest context
+ * @param hash_alg     Hash algorithm
+ * @return VB2_SUCCESS, or non-zero on error.
+ */
+int vb2_digest_init(struct vb2_digest_context *dc,
+                   enum vb2_hash_algorithm hash_alg);
+
+/**
+ * Extend a digest's hash with another block of data.
+ *
+ * @param dc           Digest context
+ * @param buf          Data to hash
+ * @param size         Length of data in bytes
+ * @return VB2_SUCCESS, or non-zero on error.
+ */
+int vb2_digest_extend(struct vb2_digest_context *dc,
+                     const uint8_t *buf,
+                     uint32_t size);
+
+/**
+ * Finalize a digest and store the result.
+ *
+ * The destination digest should be at least vb2_digest_size(algorithm).
+ *
+ * @param dc           Digest context
+ * @param digest       Destination for digest
+ * @param digest_size  Length of digest buffer in bytes.
+ * @return VB2_SUCCESS, or non-zero on error.
+ */
+int vb2_digest_finalize(struct vb2_digest_context *dc,
+                       uint8_t *digest,
+                       uint32_t digest_size);
+
+/**
+ * Calculate the digest of a buffer and store the result.
+ *
+ * @param buf          Data to hash
+ * @param size         Length of data in bytes
+ * @param hash_alg     Hash algorithm
+ * @param digest       Destination for digest
+ * @param digest_size  Length of digest buffer in bytes.
+ * @return VB2_SUCCESS, or non-zero on error.
+ */
+int vb2_digest_buffer(const uint8_t *buf,
+                     uint32_t size,
+                     enum vb2_hash_algorithm hash_alg,
+                     uint8_t *digest,
+                     uint32_t digest_size);
+
+#endif  /* VBOOT_REFERENCE_2SHA_H_ */
diff --git a/kern/lib/crypto/include/2struct.h b/kern/lib/crypto/include/2struct.h
new file mode 100644 (file)
index 0000000..da687b0
--- /dev/null
@@ -0,0 +1,347 @@
+/* Copyright (c) 2014 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.
+ *
+ * Data structure definitions for verified boot, for on-disk / in-eeprom
+ * data.
+ */
+
+#ifndef VBOOT_REFERENCE_VBOOT_2STRUCT_H_
+#define VBOOT_REFERENCE_VBOOT_2STRUCT_H_
+#include <stdint.h>
+#include "2crypto.h"
+
+/*
+ * Key block flags.
+ *
+ *The following flags set where the key is valid.  Not used by firmware
+ * verification; only kernel verification.
+ */
+#define VB2_KEY_BLOCK_FLAG_DEVELOPER_0  0x01 /* Developer switch off */
+#define VB2_KEY_BLOCK_FLAG_DEVELOPER_1  0x02 /* Developer switch on */
+#define VB2_KEY_BLOCK_FLAG_RECOVERY_0   0x04 /* Not recovery mode */
+#define VB2_KEY_BLOCK_FLAG_RECOVERY_1   0x08 /* Recovery mode */
+#define VB2_GBB_HWID_DIGEST_SIZE       32
+
+/****************************************************************************/
+
+/* Flags for vb2_shared_data.flags */
+enum vb2_shared_data_flags {
+       /* User has explicitly and physically requested recovery */
+       VB2_SD_FLAG_MANUAL_RECOVERY = (1 << 0),
+
+       /* Developer mode is enabled */
+       /* TODO: should have been VB2_SD_FLAG_DEV_MODE_ENABLED */
+       VB2_SD_DEV_MODE_ENABLED = (1 << 1),
+
+       /*
+        * TODO: might be nice to add flags for why dev mode is enabled - via
+        * gbb, virtual dev switch, or forced on for testing.
+        */
+
+       /* Kernel keyblock was verified by signature (not just hash) */
+       VB2_SD_FLAG_KERNEL_SIGNED = (1 << 2),
+};
+
+/* Flags for vb2_shared_data.status */
+enum vb2_shared_data_status {
+       /* Reinitialized NV data due to invalid checksum */
+       VB2_SD_STATUS_NV_REINIT = (1 << 0),
+
+       /* NV data has been initialized */
+       VB2_SD_STATUS_NV_INIT = (1 << 1),
+
+       /* Secure data initialized */
+       VB2_SD_STATUS_SECDATA_INIT = (1 << 2),
+
+       /* Chose a firmware slot */
+       VB2_SD_STATUS_CHOSE_SLOT = (1 << 3),
+
+       /* Secure data kernel version space initialized */
+       VB2_SD_STATUS_SECDATAK_INIT = (1 << 4),
+};
+
+/*
+ * Data shared between vboot API calls.  Stored at the start of the work
+ * buffer.
+ */
+struct vb2_shared_data {
+       /* Flags; see enum vb2_shared_data_flags */
+       uint32_t flags;
+
+       /* Flags from GBB header */
+       uint32_t gbb_flags;
+
+       /*
+        * Reason we are in recovery mode this boot (enum vb2_nv_recovery), or
+        * 0 if we aren't.
+        */
+       uint32_t recovery_reason;
+
+       /* Firmware slot used last boot (0=A, 1=B) */
+       uint32_t last_fw_slot;
+
+       /* Result of last boot (enum vb2_fw_result) */
+       uint32_t last_fw_result;
+
+       /* Firmware slot used this boot */
+       uint32_t fw_slot;
+
+       /*
+        * Version for this slot (top 16 bits = key, lower 16 bits = firmware).
+        *
+        * TODO: Make this a union to allow getting/setting those versions
+        * separately?
+        */
+       uint32_t fw_version;
+
+       /* Version stored in secdata (must be <= fw_version to boot). */
+       uint32_t fw_version_secdata;
+
+       /*
+        * Status flags for this boot; see enum vb2_shared_data_status.  Status
+        * is "what we've done"; flags above are "decisions we've made".
+        */
+       uint32_t status;
+
+       /**********************************************************************
+        * Data from kernel verification stage.
+        *
+        * TODO: shouldn't be part of the main struct, since that needlessly
+        * uses more memory during firmware verification.
+        */
+
+       /*
+        * Version for the current kernel (top 16 bits = key, lower 16 bits =
+        * kernel preamble).
+        *
+        * TODO: Make this a union to allow getting/setting those versions
+        * separately?
+        */
+       uint32_t kernel_version;
+
+       /* Kernel version from secdatak (must be <= kernel_version to boot) */
+       uint32_t kernel_version_secdatak;
+
+       /**********************************************************************
+        * Temporary variables used during firmware verification.  These don't
+        * really need to persist through to the OS, but there's nowhere else
+        * we can put them.
+        */
+
+       /* Root key offset and size from GBB header */
+       uint32_t gbb_rootkey_offset;
+       uint32_t gbb_rootkey_size;
+
+       /* HWID digest from GBB header */
+       uint8_t gbb_hwid_digest[VB2_GBB_HWID_DIGEST_SIZE];
+
+       /* Offset of preamble from start of vblock */
+       uint32_t vblock_preamble_offset;
+
+       /*
+        * Offset and size of packed data key in work buffer.  Size is 0 if
+        * data key is not stored in the work buffer.
+        */
+       uint32_t workbuf_data_key_offset;
+       uint32_t workbuf_data_key_size;
+
+       /*
+        * Offset and size of firmware preamble in work buffer.  Size is 0 if
+        * preamble is not stored in the work buffer.
+        */
+       uint32_t workbuf_preamble_offset;
+       uint32_t workbuf_preamble_size;
+
+       /*
+        * Offset and size of hash context in work buffer.  Size is 0 if
+        * hash context is not stored in the work buffer.
+        */
+       uint32_t workbuf_hash_offset;
+       uint32_t workbuf_hash_size;
+
+       /*
+        * Current tag we're hashing
+        *
+        * For new structs, this is the offset of the vb2_signature struct
+        * in the work buffer.
+        *
+        * TODO: rename to workbuf_hash_sig_offset when vboot1 structs are
+        * deprecated.
+        */
+       uint32_t hash_tag;
+
+       /* Amount of data we still expect to hash */
+       uint32_t hash_remaining_size;
+
+       /**********************************************************************
+        * Temporary variables used during kernel verification.  These don't
+        * really need to persist through to the OS, but there's nowhere else
+        * we can put them.
+        *
+        * TODO: make a union with the firmware verification temp variables,
+        * or make both of them workbuf-allocated sub-structs, so that we can
+        * overlap them so kernel variables don't bloat firmware verification
+        * stage memory requirements.
+        */
+
+       /*
+        * Offset and size of packed kernel key in work buffer.  Size is 0 if
+        * subkey is not stored in the work buffer.  Note that kernel key may
+        * be inside the firmware preamble.
+        */
+       uint32_t workbuf_kernel_key_offset;
+       uint32_t workbuf_kernel_key_size;
+
+} __attribute__((packed));
+
+/****************************************************************************/
+
+/* Signature at start of the GBB
+ * Note that if you compile in the signature as is, you are likely to break any
+ * tools that search for the signature. */
+#define VB2_GBB_SIGNATURE "$GBB"
+#define VB2_GBB_SIGNATURE_SIZE 4
+#define VB2_GBB_XOR_CHARS "****"
+/* TODO: can we write a macro to produce this at compile time? */
+#define VB2_GBB_XOR_SIGNATURE { 0x0e, 0x6d, 0x68, 0x68 }
+
+/* VB2 GBB struct version */
+#define VB2_GBB_MAJOR_VER      1
+#define VB2_GBB_MINOR_VER      2
+/* v1.2 - added fields for sha256 digest of the HWID */
+
+/* Flags for vb2_gbb_header.flags */
+enum vb2_gbb_flag {
+       /*
+        * Reduce the dev screen delay to 2 sec from 30 sec to speed up
+        * factory.
+        */
+       VB2_GBB_FLAG_DEV_SCREEN_SHORT_DELAY = (1 << 0),
+
+       /*
+        * BIOS should load option ROMs from arbitrary PCI devices. We'll never
+        * enable this ourselves because it executes non-verified code, but if
+        * a customer wants to void their warranty and set this flag in the
+        * read-only flash, they should be able to do so.
+        *
+        * (TODO: Currently not supported. Mark as deprecated/unused?)
+        */
+       VB2_GBB_FLAG_LOAD_OPTION_ROMS = (1 << 1),
+
+       /*
+        * The factory flow may need the BIOS to boot a non-ChromeOS kernel if
+        * the dev-switch is on. This flag allows that.
+        *
+        * (TODO: Currently not supported. Mark as deprecated/unused?)
+        */
+       VB2_GBB_FLAG_ENABLE_ALTERNATE_OS = (1 << 2),
+
+       /*
+        * Force dev switch on, regardless of physical/keyboard dev switch
+        * position.
+        */
+       VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON = (1 << 3),
+
+       /* Allow booting from USB in dev mode even if dev_boot_usb=0. */
+       VB2_GBB_FLAG_FORCE_DEV_BOOT_USB = (1 << 4),
+
+       /* Disable firmware rollback protection. */
+       VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK = (1 << 5),
+
+       /* Allow Enter key to trigger dev->tonorm screen transition */
+       VB2_GBB_FLAG_ENTER_TRIGGERS_TONORM = (1 << 6),
+
+       /* Allow booting Legacy OSes in dev mode even if dev_boot_legacy=0. */
+       VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY = (1 << 7),
+
+       /* Allow booting using alternate keys for FAFT servo testing */
+       VB2_GBB_FLAG_FAFT_KEY_OVERIDE = (1 << 8),
+
+       /* Disable EC software sync */
+       VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC = (1 << 9),
+
+       /* Default to booting legacy OS when dev screen times out */
+       VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY = (1 << 10),
+
+       /* Disable PD software sync */
+       VB2_GBB_FLAG_DISABLE_PD_SOFTWARE_SYNC = (1 << 11),
+
+       /* Disable shutdown on lid closed */
+       VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN = (1 << 12),
+
+       /*
+        * Allow full fastboot capability in firmware even if
+        * dev_boot_fastboot_full_cap=0.
+        */
+       VB2_GBB_FLAG_FORCE_DEV_BOOT_FASTBOOT_FULL_CAP = (1 << 13),
+
+       /* Enable serial */
+       VB2_GBB_FLAG_ENABLE_SERIAL = (1 << 14),
+};
+
+struct vb2_gbb_header {
+       /* Fields present in version 1.1 */
+       uint8_t  signature[VB2_GBB_SIGNATURE_SIZE]; /* VB2_GBB_SIGNATURE */
+       uint16_t major_version;   /* See VB2_GBB_MAJOR_VER */
+       uint16_t minor_version;   /* See VB2_GBB_MINOR_VER */
+       uint32_t header_size;     /* Size of GBB header in bytes */
+       uint32_t flags;           /* Flags (see enum vb2_gbb_flag) */
+
+       /* Offsets (from start of header) and sizes (in bytes) of components */
+       uint32_t hwid_offset;           /* HWID */
+       uint32_t hwid_size;
+       uint32_t rootkey_offset;        /* Root key */
+       uint32_t rootkey_size;
+       uint32_t bmpfv_offset;          /* BMP FV */
+       uint32_t bmpfv_size;
+       uint32_t recovery_key_offset;   /* Recovery key */
+       uint32_t recovery_key_size;
+
+       /* Added in version 1.2 */
+       uint8_t  hwid_digest[VB2_GBB_HWID_DIGEST_SIZE]; /* SHA-256 of HWID */
+
+       /* Pad to match EXPECETED_VB2_GBB_HEADER_SIZE.  Initialize to 0. */
+       uint8_t  pad[48];
+} __attribute__((packed));
+
+/* The GBB is used outside of vboot_reference, so this size is important. */
+#define EXPECTED_VB2_GBB_HEADER_SIZE 128
+
+/*
+ * Root key hash for Ryu devices only.  Contains the hash of the root key.
+ * This will be embedded somewhere inside the RO part of the firmware, so that
+ * it can verify the GBB contains only the official root key.
+ */
+
+#define RYU_ROOT_KEY_HASH_MAGIC "RtKyHash"
+#define RYU_ROOT_KEY_HASH_MAGIC_INVCASE "rTkYhASH"
+#define RYU_ROOT_KEY_HASH_MAGIC_SIZE 8
+
+#define RYU_ROOT_KEY_HASH_VERSION_MAJOR 1
+#define RYU_ROOT_KEY_HASH_VERSION_MINOR 0
+
+struct vb2_ryu_root_key_hash {
+       /* Magic number (RYU_ROOT_KEY_HASH_MAGIC) */
+       uint8_t magic[RYU_ROOT_KEY_HASH_MAGIC_SIZE];
+
+       /* Version of this struct */
+       uint16_t header_version_major;
+       uint16_t header_version_minor;
+
+       /*
+        * Length of this struct, in bytes, including any variable length data
+        * which follows (there is none, yet).
+        */
+       uint32_t struct_size;
+
+       /*
+        * SHA-256 hash digest of the entire root key section from the GBB.  If
+        * all 0 bytes, all root keys will be treated as if matching.
+        */
+       uint8_t root_key_hash_digest[32];
+};
+
+#define EXPECTED_VB2_RYU_ROOT_KEY_HASH_SIZE 48
+
+#endif  /* VBOOT_REFERENCE_VBOOT_2STRUCT_H_ */
diff --git a/kern/lib/crypto/include/2sysincludes.h b/kern/lib/crypto/include/2sysincludes.h
new file mode 100644 (file)
index 0000000..4c9e66c
--- /dev/null
@@ -0,0 +1,27 @@
+/* Copyright (c) 2014 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.
+ */
+
+/*
+ * System includes for vboot reference library.  With few exceptions, this is
+ * the ONLY place in firmware/ where system headers may be included via
+ * #include <...>, so that there's only one place that needs to be fixed up for
+ * platforms which don't have all the system includes.
+ */
+
+#ifndef VBOOT_REFERENCE_2_SYSINCLUDES_H_
+#define VBOOT_REFERENCE_2_SYSINCLUDES_H_
+
+#include <inttypes.h>  /* For PRIu64 */
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
+#include <byteswap.h>
+#include <memory.h>
+#endif
+
+#endif  /* VBOOT_REFERENCE_2_SYSINCLUDES_H_ */
diff --git a/kern/lib/crypto/include/2tpm_bootmode.h b/kern/lib/crypto/include/2tpm_bootmode.h
new file mode 100644 (file)
index 0000000..63f247d
--- /dev/null
@@ -0,0 +1,21 @@
+/* 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.
+ *
+ * Functions for updating the TPM state with the status of boot path.
+ */
+
+#ifndef VBOOT_REFERENCE_2TPM_BOOTMODE_H_
+#define VBOOT_REFERENCE_2TPM_BOOTMODE_H_
+
+#include "2api.h"
+
+/**
+ * Return digest indicating the boot state
+ *
+ * @param ctx          Vboot context
+ * @return             Pointer to sha1 digest of size VB2_SHA1_DIGEST_SIZE
+ */
+const uint8_t *vb2_get_boot_state_digest(struct vb2_context *ctx);
+
+#endif  /* VBOOT_REFERENCE_2TPM_BOOTMODE_H_ */