diff options
Diffstat (limited to 'firmware/2lib/2secdata_fwmp.c')
-rw-r--r-- | firmware/2lib/2secdata_fwmp.c | 130 |
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; +} |