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