summaryrefslogtreecommitdiff
path: root/firmware/2lib/2secdata_fwmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/2lib/2secdata_fwmp.c')
-rw-r--r--firmware/2lib/2secdata_fwmp.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/firmware/2lib/2secdata_fwmp.c b/firmware/2lib/2secdata_fwmp.c
new file mode 100644
index 00000000..774a7fa8
--- /dev/null
+++ b/firmware/2lib/2secdata_fwmp.c
@@ -0,0 +1,130 @@
+/* Copyright 2019 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 management parameters (FWMP) APIs
+ */
+
+#include "2crc8.h"
+#include "2common.h"
+#include "2misc.h"
+#include "2secdata.h"
+
+uint32_t vb2_secdata_fwmp_crc(struct vb2_secdata_fwmp *sec)
+{
+ int version_offset = offsetof(struct vb2_secdata_fwmp, struct_version);
+ return vb2_crc8((void *)sec + version_offset,
+ sec->struct_size - version_offset);
+}
+
+vb2_error_t vb2api_secdata_fwmp_check(struct vb2_context *ctx, uint8_t *size)
+{
+ struct vb2_secdata_fwmp *sec =
+ (struct vb2_secdata_fwmp *)&ctx->secdata_fwmp;
+
+ /* Verify that at least the minimum size has been read */
+ if (*size < VB2_SECDATA_FWMP_MIN_SIZE) {
+ VB2_DEBUG("FWMP: missing %d bytes for minimum size\n",
+ VB2_SECDATA_FWMP_MIN_SIZE - *size);
+ *size = VB2_SECDATA_FWMP_MIN_SIZE;
+ return VB2_ERROR_SECDATA_FWMP_INCOMPLETE;
+ }
+
+ /* Verify that struct_size is reasonable */
+ if (sec->struct_size < VB2_SECDATA_FWMP_MIN_SIZE ||
+ sec->struct_size > VB2_SECDATA_FWMP_MAX_SIZE) {
+ VB2_DEBUG("FWMP: invalid size: %d\n", sec->struct_size);
+ return VB2_ERROR_SECDATA_FWMP_SIZE;
+ }
+
+ /* Verify that we have read full structure */
+ if (*size < sec->struct_size) {
+ VB2_DEBUG("FWMP: missing %d bytes\n", sec->struct_size - *size);
+ *size = sec->struct_size;
+ return VB2_ERROR_SECDATA_FWMP_INCOMPLETE;
+ }
+ *size = sec->struct_size;
+
+ /* Verify CRC */
+ if (sec->crc8 != vb2_secdata_fwmp_crc(sec)) {
+ VB2_DEBUG("FWMP: bad CRC\n");
+ return VB2_ERROR_SECDATA_FWMP_CRC;
+ }
+
+ /* Verify major version is compatible */
+ if ((sec->struct_version >> 4) != (VB2_SECDATA_FWMP_VERSION >> 4)) {
+ VB2_DEBUG("FWMP: major version incompatible\n");
+ return VB2_ERROR_SECDATA_FWMP_VERSION;
+ }
+
+ /*
+ * If this were a 1.1+ reader and the source was a 1.0 struct,
+ * we would need to take care of initializing the extra fields
+ * added in 1.1+. But that's not an issue yet.
+ */
+ return VB2_SUCCESS;
+}
+
+vb2_error_t vb2_secdata_fwmp_init(struct vb2_context *ctx)
+{
+ struct vb2_shared_data *sd = vb2_get_sd(ctx);
+ struct vb2_secdata_fwmp *sec =
+ (struct vb2_secdata_fwmp *)&ctx->secdata_fwmp;
+ vb2_error_t rv;
+
+ /* Skip checking if NO_SECDATA_FWMP is set. */
+ if (!(ctx->flags & VB2_CONTEXT_NO_SECDATA_FWMP)) {
+ rv = vb2api_secdata_fwmp_check(ctx, &sec->struct_size);
+ if (rv)
+ return rv;
+ }
+
+ /* Mark as initialized */
+ sd->status |= VB2_SD_STATUS_SECDATA_FWMP_INIT;
+
+ return VB2_SUCCESS;
+}
+
+int vb2_secdata_fwmp_get_flag(struct vb2_context *ctx,
+ enum vb2_secdata_fwmp_flags flag)
+{
+ struct vb2_shared_data *sd = vb2_get_sd(ctx);
+ struct vb2_secdata_fwmp *sec =
+ (struct vb2_secdata_fwmp *)&ctx->secdata_fwmp;
+
+ if (!(sd->status & VB2_SD_STATUS_SECDATA_FWMP_INIT)) {
+ if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) {
+ VB2_DEBUG("Assuming broken FWMP flag %d as 0\n", flag);
+ return 0;
+ } else {
+ VB2_DIE("Must init FWMP before retrieving flag\n");
+ }
+ }
+
+ if (ctx->flags & VB2_CONTEXT_NO_SECDATA_FWMP)
+ return 0;
+
+ return !!(sec->flags & flag);
+}
+
+uint8_t *vb2_secdata_fwmp_get_dev_key_hash(struct vb2_context *ctx)
+{
+ struct vb2_shared_data *sd = vb2_get_sd(ctx);
+ struct vb2_secdata_fwmp *sec =
+ (struct vb2_secdata_fwmp *)&ctx->secdata_fwmp;
+
+ if (!(sd->status & VB2_SD_STATUS_SECDATA_FWMP_INIT)) {
+ if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) {
+ VB2_DEBUG("Assuming broken FWMP dev_key_hash "
+ "as empty\n");
+ return NULL;
+ } else {
+ VB2_DIE("Must init FWMP before getting dev key hash\n");
+ }
+ }
+
+ if (ctx->flags & VB2_CONTEXT_NO_SECDATA_FWMP)
+ return NULL;
+
+ return sec->dev_key_hash;
+}