/* Copyright 2019 The ChromiumOS Authors * 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; } uint32_t vb2api_secdata_fwmp_create(struct vb2_context *ctx) { struct vb2_secdata_fwmp *sec = (void *)&ctx->secdata_fwmp; /* Clear the entire struct */ memset(sec, 0, sizeof(*sec)); /* Set to current version */ sec->struct_version = VB2_SECDATA_FWMP_VERSION; /* Set the structure size */ sec->struct_size = sizeof(*sec); /* Calculate initial CRC */ sec->crc8 = vb2_secdata_fwmp_crc(sec); return sizeof(*sec); } test_mockable 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; }