| /* 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 "2common.h" |
| #include "2crc8.h" |
| #include "2misc.h" |
| #include "2secdata.h" |
| #include "2secdata_struct.h" |
| |
| test_mockable |
| 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; |
| |
| /* Skip checking if NO_SECDATA_FWMP is set. */ |
| if (!(ctx->flags & VB2_CONTEXT_NO_SECDATA_FWMP)) |
| VB2_TRY(vb2api_secdata_fwmp_check(ctx, &sec->struct_size)); |
| |
| /* 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)) { |
| VB2_REC_OR_DIE(ctx, "Must init FWMP before retrieving flag\n"); |
| return 0; |
| } |
| |
| 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)) { |
| VB2_REC_OR_DIE(ctx, "Must init FWMP before get dev key hash\n"); |
| return NULL; |
| } |
| |
| if (ctx->flags & VB2_CONTEXT_NO_SECDATA_FWMP) |
| return NULL; |
| |
| return sec->dev_key_hash; |
| } |