xref: /aosp_15_r20/external/vboot_reference/firmware/2lib/2secdata_firmware.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2014 The ChromiumOS Authors
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  *
5  * Secure storage APIs
6  */
7 
8 #include "2common.h"
9 #include "2crc8.h"
10 #include "2misc.h"
11 #include "2secdata.h"
12 #include "2secdata_struct.h"
13 #include "2sysincludes.h"
14 
vb2api_secdata_firmware_check(struct vb2_context * ctx)15 vb2_error_t vb2api_secdata_firmware_check(struct vb2_context *ctx)
16 {
17 	struct vb2_secdata_firmware *sec =
18 		(struct vb2_secdata_firmware *)ctx->secdata_firmware;
19 
20 	/* Verify CRC */
21 	if (sec->crc8 != vb2_crc8(sec, offsetof(struct vb2_secdata_firmware,
22 						crc8))) {
23 		VB2_DEBUG("secdata_firmware: bad CRC\n");
24 		return VB2_ERROR_SECDATA_FIRMWARE_CRC;
25 	}
26 
27 	/* Verify version */
28 	if (sec->struct_version < VB2_SECDATA_FIRMWARE_VERSION) {
29 		VB2_DEBUG("secdata_firmware: version incompatible\n");
30 		return VB2_ERROR_SECDATA_FIRMWARE_VERSION;
31 	}
32 
33 	return VB2_SUCCESS;
34 }
35 
vb2api_secdata_firmware_create(struct vb2_context * ctx)36 uint32_t vb2api_secdata_firmware_create(struct vb2_context *ctx)
37 {
38 	struct vb2_secdata_firmware *sec =
39 		(struct vb2_secdata_firmware *)ctx->secdata_firmware;
40 
41 	/* Clear the entire struct */
42 	memset(sec, 0, sizeof(*sec));
43 
44 	/* Set to current version */
45 	sec->struct_version = VB2_SECDATA_FIRMWARE_VERSION;
46 
47 	/* Calculate initial CRC */
48 	sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdata_firmware, crc8));
49 
50 	/* Mark as changed */
51 	ctx->flags |= VB2_CONTEXT_SECDATA_FIRMWARE_CHANGED;
52 
53 	return sizeof(*sec);
54 }
55 
vb2_secdata_firmware_init(struct vb2_context * ctx)56 vb2_error_t vb2_secdata_firmware_init(struct vb2_context *ctx)
57 {
58 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
59 
60 	VB2_TRY(vb2api_secdata_firmware_check(ctx));
61 
62 	/* Set status flag */
63 	sd->status |= VB2_SD_STATUS_SECDATA_FIRMWARE_INIT;
64 
65 	/* Read this now to make sure crossystem has it even in rec mode */
66 	sd->fw_version_secdata =
67 		vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_VERSIONS);
68 
69 	return VB2_SUCCESS;
70 }
71 
vb2_secdata_firmware_get(struct vb2_context * ctx,enum vb2_secdata_firmware_param param)72 uint32_t vb2_secdata_firmware_get(struct vb2_context *ctx,
73 				  enum vb2_secdata_firmware_param param)
74 {
75 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
76 	struct vb2_secdata_firmware *sec =
77 		(struct vb2_secdata_firmware *)ctx->secdata_firmware;
78 	const char *msg;
79 
80 	if (!(sd->status & VB2_SD_STATUS_SECDATA_FIRMWARE_INIT)) {
81 		msg = "get before init";
82 		goto fail;
83 	}
84 
85 	switch (param) {
86 	case VB2_SECDATA_FIRMWARE_FLAGS:
87 		return sec->flags;
88 
89 	case VB2_SECDATA_FIRMWARE_VERSIONS:
90 		return sec->fw_versions;
91 
92 	default:
93 		msg = "invalid param";
94 	}
95 
96  fail:
97 	VB2_REC_OR_DIE(ctx, "%s\n", msg);
98 	return 0;
99 }
100 
vb2_secdata_firmware_set(struct vb2_context * ctx,enum vb2_secdata_firmware_param param,uint32_t value)101 void vb2_secdata_firmware_set(struct vb2_context *ctx,
102 			      enum vb2_secdata_firmware_param param,
103 			      uint32_t value)
104 {
105 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
106 	struct vb2_secdata_firmware *sec =
107 		(struct vb2_secdata_firmware *)ctx->secdata_firmware;
108 	const char *msg;
109 
110 	if (!(sd->status & VB2_SD_STATUS_SECDATA_FIRMWARE_INIT)) {
111 		msg = "set before init";
112 		goto fail;
113 	}
114 
115 	/* If not changing the value, just return early */
116 	if (value == vb2_secdata_firmware_get(ctx, param))
117 		return;
118 
119 	switch (param) {
120 	case VB2_SECDATA_FIRMWARE_FLAGS:
121 		/* Make sure flags is in valid range */
122 		if (value > 0xff) {
123 			msg = "flags out of range";
124 			goto fail;
125 		}
126 
127 		VB2_DEBUG("secdata_firmware flags updated from %#x to %#x\n",
128 			  sec->flags, value);
129 		sec->flags = value;
130 		break;
131 
132 	case VB2_SECDATA_FIRMWARE_VERSIONS:
133 		VB2_DEBUG("secdata_firmware versions updated from "
134 			  "%#x to %#x\n",
135 			  sec->fw_versions, value);
136 		sec->fw_versions = value;
137 		break;
138 
139 	default:
140 		msg = "invalid param";
141 		goto fail;
142 	}
143 
144 	/* Regenerate CRC */
145 	sec->crc8 = vb2_crc8(sec, offsetof(struct vb2_secdata_firmware, crc8));
146 	ctx->flags |= VB2_CONTEXT_SECDATA_FIRMWARE_CHANGED;
147 	return;
148 
149  fail:
150 	VB2_REC_OR_DIE(ctx, "%s\n", msg);
151 }
152