1*bb154e3eSDorjoy Chowdhury /*
2*bb154e3eSDorjoy Chowdhury * AWS Nitro Secure Module (NSM) device
3*bb154e3eSDorjoy Chowdhury *
4*bb154e3eSDorjoy Chowdhury * Copyright (c) 2024 Dorjoy Chowdhury <dorjoychy111@gmail.com>
5*bb154e3eSDorjoy Chowdhury *
6*bb154e3eSDorjoy Chowdhury * This work is licensed under the terms of the GNU GPL, version 2 or
7*bb154e3eSDorjoy Chowdhury * (at your option) any later version. See the COPYING file in the
8*bb154e3eSDorjoy Chowdhury * top-level directory.
9*bb154e3eSDorjoy Chowdhury */
10*bb154e3eSDorjoy Chowdhury
11*bb154e3eSDorjoy Chowdhury #include "qemu/osdep.h"
12*bb154e3eSDorjoy Chowdhury #include "qemu/iov.h"
13*bb154e3eSDorjoy Chowdhury #include "qemu/guest-random.h"
14*bb154e3eSDorjoy Chowdhury #include "qapi/error.h"
15*bb154e3eSDorjoy Chowdhury
16*bb154e3eSDorjoy Chowdhury #include "crypto/hash.h"
17*bb154e3eSDorjoy Chowdhury #include "hw/virtio/virtio.h"
18*bb154e3eSDorjoy Chowdhury #include "hw/virtio/virtio-nsm.h"
19*bb154e3eSDorjoy Chowdhury #include "hw/virtio/cbor-helpers.h"
20*bb154e3eSDorjoy Chowdhury #include "standard-headers/linux/virtio_ids.h"
21*bb154e3eSDorjoy Chowdhury
22*bb154e3eSDorjoy Chowdhury #define NSM_REQUEST_MAX_SIZE 0x1000
23*bb154e3eSDorjoy Chowdhury #define NSM_RESPONSE_BUF_SIZE 0x3000
24*bb154e3eSDorjoy Chowdhury #define NSM_RND_BUF_SIZE 256
25*bb154e3eSDorjoy Chowdhury
26*bb154e3eSDorjoy Chowdhury enum NSMResponseTypes {
27*bb154e3eSDorjoy Chowdhury NSM_SUCCESS = 0,
28*bb154e3eSDorjoy Chowdhury NSM_INVALID_ARGUMENT = 1,
29*bb154e3eSDorjoy Chowdhury NSM_INVALID_INDEX = 2,
30*bb154e3eSDorjoy Chowdhury NSM_READONLY_INDEX = 3,
31*bb154e3eSDorjoy Chowdhury NSM_INVALID_OPERATION = 4,
32*bb154e3eSDorjoy Chowdhury NSM_BUFFER_TOO_SMALL = 5,
33*bb154e3eSDorjoy Chowdhury NSM_INPUT_TOO_LARGE = 6,
34*bb154e3eSDorjoy Chowdhury NSM_INTERNAL_ERROR = 7,
35*bb154e3eSDorjoy Chowdhury };
36*bb154e3eSDorjoy Chowdhury
error_string(enum NSMResponseTypes type)37*bb154e3eSDorjoy Chowdhury static const char *error_string(enum NSMResponseTypes type)
38*bb154e3eSDorjoy Chowdhury {
39*bb154e3eSDorjoy Chowdhury const char *str;
40*bb154e3eSDorjoy Chowdhury switch (type) {
41*bb154e3eSDorjoy Chowdhury case NSM_INVALID_ARGUMENT:
42*bb154e3eSDorjoy Chowdhury str = "InvalidArgument";
43*bb154e3eSDorjoy Chowdhury break;
44*bb154e3eSDorjoy Chowdhury case NSM_INVALID_INDEX:
45*bb154e3eSDorjoy Chowdhury str = "InvalidIndex";
46*bb154e3eSDorjoy Chowdhury break;
47*bb154e3eSDorjoy Chowdhury case NSM_READONLY_INDEX:
48*bb154e3eSDorjoy Chowdhury str = "ReadOnlyIndex";
49*bb154e3eSDorjoy Chowdhury break;
50*bb154e3eSDorjoy Chowdhury case NSM_INVALID_OPERATION:
51*bb154e3eSDorjoy Chowdhury str = "InvalidOperation";
52*bb154e3eSDorjoy Chowdhury break;
53*bb154e3eSDorjoy Chowdhury case NSM_BUFFER_TOO_SMALL:
54*bb154e3eSDorjoy Chowdhury str = "BufferTooSmall";
55*bb154e3eSDorjoy Chowdhury break;
56*bb154e3eSDorjoy Chowdhury case NSM_INPUT_TOO_LARGE:
57*bb154e3eSDorjoy Chowdhury str = "InputTooLarge";
58*bb154e3eSDorjoy Chowdhury break;
59*bb154e3eSDorjoy Chowdhury default:
60*bb154e3eSDorjoy Chowdhury str = "InternalError";
61*bb154e3eSDorjoy Chowdhury break;
62*bb154e3eSDorjoy Chowdhury }
63*bb154e3eSDorjoy Chowdhury
64*bb154e3eSDorjoy Chowdhury return str;
65*bb154e3eSDorjoy Chowdhury }
66*bb154e3eSDorjoy Chowdhury
67*bb154e3eSDorjoy Chowdhury /*
68*bb154e3eSDorjoy Chowdhury * Error response structure:
69*bb154e3eSDorjoy Chowdhury *
70*bb154e3eSDorjoy Chowdhury * {
71*bb154e3eSDorjoy Chowdhury * Map(1) {
72*bb154e3eSDorjoy Chowdhury * key = String("Error"),
73*bb154e3eSDorjoy Chowdhury * value = String(error_name)
74*bb154e3eSDorjoy Chowdhury * }
75*bb154e3eSDorjoy Chowdhury * }
76*bb154e3eSDorjoy Chowdhury *
77*bb154e3eSDorjoy Chowdhury * where error_name can be one of the following:
78*bb154e3eSDorjoy Chowdhury * InvalidArgument
79*bb154e3eSDorjoy Chowdhury * InvalidIndex
80*bb154e3eSDorjoy Chowdhury * InvalidResponse
81*bb154e3eSDorjoy Chowdhury * ReadOnlyIndex
82*bb154e3eSDorjoy Chowdhury * InvalidOperation
83*bb154e3eSDorjoy Chowdhury * BufferTooSmall
84*bb154e3eSDorjoy Chowdhury * InputTooLarge
85*bb154e3eSDorjoy Chowdhury * InternalError
86*bb154e3eSDorjoy Chowdhury */
87*bb154e3eSDorjoy Chowdhury
error_response(struct iovec * response,enum NSMResponseTypes error,Error ** errp)88*bb154e3eSDorjoy Chowdhury static bool error_response(struct iovec *response, enum NSMResponseTypes error,
89*bb154e3eSDorjoy Chowdhury Error **errp)
90*bb154e3eSDorjoy Chowdhury {
91*bb154e3eSDorjoy Chowdhury cbor_item_t *root;
92*bb154e3eSDorjoy Chowdhury size_t len;
93*bb154e3eSDorjoy Chowdhury bool r = false;
94*bb154e3eSDorjoy Chowdhury
95*bb154e3eSDorjoy Chowdhury root = cbor_new_definite_map(1);
96*bb154e3eSDorjoy Chowdhury if (!root) {
97*bb154e3eSDorjoy Chowdhury goto err;
98*bb154e3eSDorjoy Chowdhury }
99*bb154e3eSDorjoy Chowdhury
100*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_string_to_map(root, "Error", error_string(error))) {
101*bb154e3eSDorjoy Chowdhury goto err;
102*bb154e3eSDorjoy Chowdhury }
103*bb154e3eSDorjoy Chowdhury
104*bb154e3eSDorjoy Chowdhury len = cbor_serialize(root, response->iov_base, response->iov_len);
105*bb154e3eSDorjoy Chowdhury if (len == 0) {
106*bb154e3eSDorjoy Chowdhury error_setg(errp, "Response buffer is small for %s response",
107*bb154e3eSDorjoy Chowdhury error_string(error));
108*bb154e3eSDorjoy Chowdhury goto out;
109*bb154e3eSDorjoy Chowdhury }
110*bb154e3eSDorjoy Chowdhury response->iov_len = len;
111*bb154e3eSDorjoy Chowdhury r = true;
112*bb154e3eSDorjoy Chowdhury
113*bb154e3eSDorjoy Chowdhury out:
114*bb154e3eSDorjoy Chowdhury if (root) {
115*bb154e3eSDorjoy Chowdhury cbor_decref(&root);
116*bb154e3eSDorjoy Chowdhury }
117*bb154e3eSDorjoy Chowdhury return r;
118*bb154e3eSDorjoy Chowdhury
119*bb154e3eSDorjoy Chowdhury err:
120*bb154e3eSDorjoy Chowdhury error_setg(errp, "Failed to initialize %s response", error_string(error));
121*bb154e3eSDorjoy Chowdhury goto out;
122*bb154e3eSDorjoy Chowdhury }
123*bb154e3eSDorjoy Chowdhury
124*bb154e3eSDorjoy Chowdhury /*
125*bb154e3eSDorjoy Chowdhury * GetRandom response structure:
126*bb154e3eSDorjoy Chowdhury *
127*bb154e3eSDorjoy Chowdhury * {
128*bb154e3eSDorjoy Chowdhury * Map(1) {
129*bb154e3eSDorjoy Chowdhury * key = String("GetRandom"),
130*bb154e3eSDorjoy Chowdhury * value = Map(1) {
131*bb154e3eSDorjoy Chowdhury * key = String("random"),
132*bb154e3eSDorjoy Chowdhury * value = Byte_String()
133*bb154e3eSDorjoy Chowdhury * }
134*bb154e3eSDorjoy Chowdhury * }
135*bb154e3eSDorjoy Chowdhury * }
136*bb154e3eSDorjoy Chowdhury */
handle_get_random(VirtIONSM * vnsm,struct iovec * request,struct iovec * response,Error ** errp)137*bb154e3eSDorjoy Chowdhury static bool handle_get_random(VirtIONSM *vnsm, struct iovec *request,
138*bb154e3eSDorjoy Chowdhury struct iovec *response, Error **errp)
139*bb154e3eSDorjoy Chowdhury {
140*bb154e3eSDorjoy Chowdhury cbor_item_t *root, *nested_map;
141*bb154e3eSDorjoy Chowdhury size_t len;
142*bb154e3eSDorjoy Chowdhury uint8_t rnd[NSM_RND_BUF_SIZE];
143*bb154e3eSDorjoy Chowdhury bool r = false;
144*bb154e3eSDorjoy Chowdhury
145*bb154e3eSDorjoy Chowdhury root = cbor_new_definite_map(1);
146*bb154e3eSDorjoy Chowdhury if (!root) {
147*bb154e3eSDorjoy Chowdhury goto err;
148*bb154e3eSDorjoy Chowdhury }
149*bb154e3eSDorjoy Chowdhury
150*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_map_to_map(root, "GetRandom", 1, &nested_map)) {
151*bb154e3eSDorjoy Chowdhury goto err;
152*bb154e3eSDorjoy Chowdhury }
153*bb154e3eSDorjoy Chowdhury
154*bb154e3eSDorjoy Chowdhury qemu_guest_getrandom_nofail(rnd, NSM_RND_BUF_SIZE);
155*bb154e3eSDorjoy Chowdhury
156*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_bytestring_to_map(nested_map, "random", rnd,
157*bb154e3eSDorjoy Chowdhury NSM_RND_BUF_SIZE)) {
158*bb154e3eSDorjoy Chowdhury goto err;
159*bb154e3eSDorjoy Chowdhury }
160*bb154e3eSDorjoy Chowdhury
161*bb154e3eSDorjoy Chowdhury len = cbor_serialize(root, response->iov_base, response->iov_len);
162*bb154e3eSDorjoy Chowdhury if (len == 0) {
163*bb154e3eSDorjoy Chowdhury if (error_response(response, NSM_INPUT_TOO_LARGE, errp)) {
164*bb154e3eSDorjoy Chowdhury r = true;
165*bb154e3eSDorjoy Chowdhury }
166*bb154e3eSDorjoy Chowdhury goto out;
167*bb154e3eSDorjoy Chowdhury }
168*bb154e3eSDorjoy Chowdhury
169*bb154e3eSDorjoy Chowdhury response->iov_len = len;
170*bb154e3eSDorjoy Chowdhury r = true;
171*bb154e3eSDorjoy Chowdhury
172*bb154e3eSDorjoy Chowdhury out:
173*bb154e3eSDorjoy Chowdhury if (root) {
174*bb154e3eSDorjoy Chowdhury cbor_decref(&root);
175*bb154e3eSDorjoy Chowdhury }
176*bb154e3eSDorjoy Chowdhury return r;
177*bb154e3eSDorjoy Chowdhury
178*bb154e3eSDorjoy Chowdhury err:
179*bb154e3eSDorjoy Chowdhury error_setg(errp, "Failed to initialize GetRandom response");
180*bb154e3eSDorjoy Chowdhury goto out;
181*bb154e3eSDorjoy Chowdhury }
182*bb154e3eSDorjoy Chowdhury
183*bb154e3eSDorjoy Chowdhury /*
184*bb154e3eSDorjoy Chowdhury * DescribeNSM response structure:
185*bb154e3eSDorjoy Chowdhury *
186*bb154e3eSDorjoy Chowdhury * {
187*bb154e3eSDorjoy Chowdhury * Map(1) {
188*bb154e3eSDorjoy Chowdhury * key = String("DescribeNSM"),
189*bb154e3eSDorjoy Chowdhury * value = Map(7) {
190*bb154e3eSDorjoy Chowdhury * key = String("digest"),
191*bb154e3eSDorjoy Chowdhury * value = String("SHA384"),
192*bb154e3eSDorjoy Chowdhury * key = String("max_pcrs"),
193*bb154e3eSDorjoy Chowdhury * value = Uint8(32),
194*bb154e3eSDorjoy Chowdhury * key = String("module_id"),
195*bb154e3eSDorjoy Chowdhury * value = String("i-1234-enc5678"),
196*bb154e3eSDorjoy Chowdhury * key = String("locked_pcrs"),
197*bb154e3eSDorjoy Chowdhury * value = Array<Uint8>(),
198*bb154e3eSDorjoy Chowdhury * key = String("version_major"),
199*bb154e3eSDorjoy Chowdhury * value = Uint8(1),
200*bb154e3eSDorjoy Chowdhury * key = String("version_minor"),
201*bb154e3eSDorjoy Chowdhury * value = Uint8(0),
202*bb154e3eSDorjoy Chowdhury * key = String("version_patch"),
203*bb154e3eSDorjoy Chowdhury * value = Uint8(0)
204*bb154e3eSDorjoy Chowdhury * }
205*bb154e3eSDorjoy Chowdhury * }
206*bb154e3eSDorjoy Chowdhury * }
207*bb154e3eSDorjoy Chowdhury */
handle_describe_nsm(VirtIONSM * vnsm,struct iovec * request,struct iovec * response,Error ** errp)208*bb154e3eSDorjoy Chowdhury static bool handle_describe_nsm(VirtIONSM *vnsm, struct iovec *request,
209*bb154e3eSDorjoy Chowdhury struct iovec *response, Error **errp)
210*bb154e3eSDorjoy Chowdhury {
211*bb154e3eSDorjoy Chowdhury cbor_item_t *root, *nested_map;
212*bb154e3eSDorjoy Chowdhury uint16_t locked_pcrs_cnt = 0;
213*bb154e3eSDorjoy Chowdhury uint8_t locked_pcrs_ind[NSM_MAX_PCRS];
214*bb154e3eSDorjoy Chowdhury size_t len;
215*bb154e3eSDorjoy Chowdhury bool r = false;
216*bb154e3eSDorjoy Chowdhury
217*bb154e3eSDorjoy Chowdhury root = cbor_new_definite_map(1);
218*bb154e3eSDorjoy Chowdhury if (!root) {
219*bb154e3eSDorjoy Chowdhury goto err;
220*bb154e3eSDorjoy Chowdhury }
221*bb154e3eSDorjoy Chowdhury
222*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_map_to_map(root, "DescribeNSM", 7, &nested_map)) {
223*bb154e3eSDorjoy Chowdhury goto err;
224*bb154e3eSDorjoy Chowdhury }
225*bb154e3eSDorjoy Chowdhury
226*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_string_to_map(nested_map, "digest", vnsm->digest)) {
227*bb154e3eSDorjoy Chowdhury goto err;
228*bb154e3eSDorjoy Chowdhury }
229*bb154e3eSDorjoy Chowdhury
230*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_uint8_to_map(nested_map, "max_pcrs", vnsm->max_pcrs)) {
231*bb154e3eSDorjoy Chowdhury goto err;
232*bb154e3eSDorjoy Chowdhury }
233*bb154e3eSDorjoy Chowdhury
234*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_string_to_map(nested_map, "module_id",
235*bb154e3eSDorjoy Chowdhury vnsm->module_id)) {
236*bb154e3eSDorjoy Chowdhury goto err;
237*bb154e3eSDorjoy Chowdhury }
238*bb154e3eSDorjoy Chowdhury
239*bb154e3eSDorjoy Chowdhury for (uint8_t i = 0; i < NSM_MAX_PCRS; ++i) {
240*bb154e3eSDorjoy Chowdhury if (vnsm->pcrs[i].locked) {
241*bb154e3eSDorjoy Chowdhury locked_pcrs_ind[locked_pcrs_cnt++] = i;
242*bb154e3eSDorjoy Chowdhury }
243*bb154e3eSDorjoy Chowdhury }
244*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_uint8_array_to_map(nested_map, "locked_pcrs",
245*bb154e3eSDorjoy Chowdhury locked_pcrs_ind, locked_pcrs_cnt)) {
246*bb154e3eSDorjoy Chowdhury goto err;
247*bb154e3eSDorjoy Chowdhury }
248*bb154e3eSDorjoy Chowdhury
249*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_uint8_to_map(nested_map, "version_major",
250*bb154e3eSDorjoy Chowdhury vnsm->version_major)) {
251*bb154e3eSDorjoy Chowdhury goto err;
252*bb154e3eSDorjoy Chowdhury }
253*bb154e3eSDorjoy Chowdhury
254*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_uint8_to_map(nested_map, "version_minor",
255*bb154e3eSDorjoy Chowdhury vnsm->version_minor)) {
256*bb154e3eSDorjoy Chowdhury goto err;
257*bb154e3eSDorjoy Chowdhury }
258*bb154e3eSDorjoy Chowdhury
259*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_uint8_to_map(nested_map, "version_patch",
260*bb154e3eSDorjoy Chowdhury vnsm->version_patch)) {
261*bb154e3eSDorjoy Chowdhury goto err;
262*bb154e3eSDorjoy Chowdhury }
263*bb154e3eSDorjoy Chowdhury
264*bb154e3eSDorjoy Chowdhury len = cbor_serialize(root, response->iov_base, response->iov_len);
265*bb154e3eSDorjoy Chowdhury if (len == 0) {
266*bb154e3eSDorjoy Chowdhury if (error_response(response, NSM_INPUT_TOO_LARGE, errp)) {
267*bb154e3eSDorjoy Chowdhury r = true;
268*bb154e3eSDorjoy Chowdhury }
269*bb154e3eSDorjoy Chowdhury goto out;
270*bb154e3eSDorjoy Chowdhury }
271*bb154e3eSDorjoy Chowdhury
272*bb154e3eSDorjoy Chowdhury response->iov_len = len;
273*bb154e3eSDorjoy Chowdhury r = true;
274*bb154e3eSDorjoy Chowdhury
275*bb154e3eSDorjoy Chowdhury out:
276*bb154e3eSDorjoy Chowdhury if (root) {
277*bb154e3eSDorjoy Chowdhury cbor_decref(&root);
278*bb154e3eSDorjoy Chowdhury }
279*bb154e3eSDorjoy Chowdhury return r;
280*bb154e3eSDorjoy Chowdhury
281*bb154e3eSDorjoy Chowdhury err:
282*bb154e3eSDorjoy Chowdhury error_setg(errp, "Failed to initialize DescribeNSM response");
283*bb154e3eSDorjoy Chowdhury goto out;
284*bb154e3eSDorjoy Chowdhury }
285*bb154e3eSDorjoy Chowdhury
286*bb154e3eSDorjoy Chowdhury /*
287*bb154e3eSDorjoy Chowdhury * DescribePCR request structure:
288*bb154e3eSDorjoy Chowdhury *
289*bb154e3eSDorjoy Chowdhury * {
290*bb154e3eSDorjoy Chowdhury * Map(1) {
291*bb154e3eSDorjoy Chowdhury * key = String("DescribePCR"),
292*bb154e3eSDorjoy Chowdhury * value = Map(1) {
293*bb154e3eSDorjoy Chowdhury * key = String("index"),
294*bb154e3eSDorjoy Chowdhury * value = Uint8(pcr)
295*bb154e3eSDorjoy Chowdhury * }
296*bb154e3eSDorjoy Chowdhury * }
297*bb154e3eSDorjoy Chowdhury * }
298*bb154e3eSDorjoy Chowdhury */
299*bb154e3eSDorjoy Chowdhury typedef struct NSMDescribePCRReq {
300*bb154e3eSDorjoy Chowdhury uint8_t index;
301*bb154e3eSDorjoy Chowdhury } NSMDescribePCRReq;
302*bb154e3eSDorjoy Chowdhury
get_nsm_describe_pcr_req(uint8_t * req,size_t len,NSMDescribePCRReq * nsm_req)303*bb154e3eSDorjoy Chowdhury static enum NSMResponseTypes get_nsm_describe_pcr_req(
304*bb154e3eSDorjoy Chowdhury uint8_t *req, size_t len,
305*bb154e3eSDorjoy Chowdhury NSMDescribePCRReq *nsm_req)
306*bb154e3eSDorjoy Chowdhury {
307*bb154e3eSDorjoy Chowdhury size_t size;
308*bb154e3eSDorjoy Chowdhury uint8_t *str;
309*bb154e3eSDorjoy Chowdhury struct cbor_pair *pair;
310*bb154e3eSDorjoy Chowdhury cbor_item_t *item = NULL;
311*bb154e3eSDorjoy Chowdhury struct cbor_load_result result;
312*bb154e3eSDorjoy Chowdhury enum NSMResponseTypes r = NSM_INVALID_OPERATION;
313*bb154e3eSDorjoy Chowdhury
314*bb154e3eSDorjoy Chowdhury item = cbor_load(req, len, &result);
315*bb154e3eSDorjoy Chowdhury if (!item || result.error.code != CBOR_ERR_NONE) {
316*bb154e3eSDorjoy Chowdhury goto cleanup;
317*bb154e3eSDorjoy Chowdhury }
318*bb154e3eSDorjoy Chowdhury
319*bb154e3eSDorjoy Chowdhury pair = cbor_map_handle(item);
320*bb154e3eSDorjoy Chowdhury if (!cbor_isa_map(pair->value)) {
321*bb154e3eSDorjoy Chowdhury goto cleanup;
322*bb154e3eSDorjoy Chowdhury }
323*bb154e3eSDorjoy Chowdhury size = cbor_map_size(pair->value);
324*bb154e3eSDorjoy Chowdhury if (size < 1) {
325*bb154e3eSDorjoy Chowdhury goto cleanup;
326*bb154e3eSDorjoy Chowdhury }
327*bb154e3eSDorjoy Chowdhury
328*bb154e3eSDorjoy Chowdhury pair = cbor_map_handle(pair->value);
329*bb154e3eSDorjoy Chowdhury for (int i = 0; i < size; ++i) {
330*bb154e3eSDorjoy Chowdhury if (!cbor_isa_string(pair[i].key)) {
331*bb154e3eSDorjoy Chowdhury continue;
332*bb154e3eSDorjoy Chowdhury }
333*bb154e3eSDorjoy Chowdhury
334*bb154e3eSDorjoy Chowdhury str = cbor_string_handle(pair[i].key);
335*bb154e3eSDorjoy Chowdhury if (str && cbor_string_length(pair[i].key) == 5 &&
336*bb154e3eSDorjoy Chowdhury memcmp(str, "index", 5) == 0) {
337*bb154e3eSDorjoy Chowdhury if (!cbor_isa_uint(pair[i].value) ||
338*bb154e3eSDorjoy Chowdhury cbor_int_get_width(pair[i].value) != CBOR_INT_8) {
339*bb154e3eSDorjoy Chowdhury break;
340*bb154e3eSDorjoy Chowdhury }
341*bb154e3eSDorjoy Chowdhury
342*bb154e3eSDorjoy Chowdhury nsm_req->index = cbor_get_uint8(pair[i].value);
343*bb154e3eSDorjoy Chowdhury r = NSM_SUCCESS;
344*bb154e3eSDorjoy Chowdhury break;
345*bb154e3eSDorjoy Chowdhury }
346*bb154e3eSDorjoy Chowdhury }
347*bb154e3eSDorjoy Chowdhury
348*bb154e3eSDorjoy Chowdhury cleanup:
349*bb154e3eSDorjoy Chowdhury if (item) {
350*bb154e3eSDorjoy Chowdhury cbor_decref(&item);
351*bb154e3eSDorjoy Chowdhury }
352*bb154e3eSDorjoy Chowdhury return r;
353*bb154e3eSDorjoy Chowdhury }
354*bb154e3eSDorjoy Chowdhury
355*bb154e3eSDorjoy Chowdhury /*
356*bb154e3eSDorjoy Chowdhury * DescribePCR response structure:
357*bb154e3eSDorjoy Chowdhury *
358*bb154e3eSDorjoy Chowdhury * {
359*bb154e3eSDorjoy Chowdhury * Map(1) {
360*bb154e3eSDorjoy Chowdhury * key = String("DescribePCR"),
361*bb154e3eSDorjoy Chowdhury * value = Map(2) {
362*bb154e3eSDorjoy Chowdhury * key = String("data"),
363*bb154e3eSDorjoy Chowdhury * value = Byte_String(),
364*bb154e3eSDorjoy Chowdhury * key = String("lock"),
365*bb154e3eSDorjoy Chowdhury * value = Bool()
366*bb154e3eSDorjoy Chowdhury * }
367*bb154e3eSDorjoy Chowdhury * }
368*bb154e3eSDorjoy Chowdhury * }
369*bb154e3eSDorjoy Chowdhury */
handle_describe_pcr(VirtIONSM * vnsm,struct iovec * request,struct iovec * response,Error ** errp)370*bb154e3eSDorjoy Chowdhury static bool handle_describe_pcr(VirtIONSM *vnsm, struct iovec *request,
371*bb154e3eSDorjoy Chowdhury struct iovec *response, Error **errp)
372*bb154e3eSDorjoy Chowdhury {
373*bb154e3eSDorjoy Chowdhury cbor_item_t *root = NULL;
374*bb154e3eSDorjoy Chowdhury cbor_item_t *nested_map;
375*bb154e3eSDorjoy Chowdhury size_t len;
376*bb154e3eSDorjoy Chowdhury NSMDescribePCRReq nsm_req;
377*bb154e3eSDorjoy Chowdhury enum NSMResponseTypes type;
378*bb154e3eSDorjoy Chowdhury struct PCRInfo *pcr;
379*bb154e3eSDorjoy Chowdhury bool r = false;
380*bb154e3eSDorjoy Chowdhury
381*bb154e3eSDorjoy Chowdhury type = get_nsm_describe_pcr_req(request->iov_base, request->iov_len,
382*bb154e3eSDorjoy Chowdhury &nsm_req);
383*bb154e3eSDorjoy Chowdhury if (type != NSM_SUCCESS) {
384*bb154e3eSDorjoy Chowdhury if (error_response(response, type, errp)) {
385*bb154e3eSDorjoy Chowdhury r = true;
386*bb154e3eSDorjoy Chowdhury }
387*bb154e3eSDorjoy Chowdhury goto out;
388*bb154e3eSDorjoy Chowdhury }
389*bb154e3eSDorjoy Chowdhury if (nsm_req.index >= vnsm->max_pcrs) {
390*bb154e3eSDorjoy Chowdhury if (error_response(response, NSM_INVALID_INDEX, errp)) {
391*bb154e3eSDorjoy Chowdhury r = true;
392*bb154e3eSDorjoy Chowdhury }
393*bb154e3eSDorjoy Chowdhury goto out;
394*bb154e3eSDorjoy Chowdhury }
395*bb154e3eSDorjoy Chowdhury pcr = &(vnsm->pcrs[nsm_req.index]);
396*bb154e3eSDorjoy Chowdhury
397*bb154e3eSDorjoy Chowdhury root = cbor_new_definite_map(1);
398*bb154e3eSDorjoy Chowdhury if (!root) {
399*bb154e3eSDorjoy Chowdhury goto err;
400*bb154e3eSDorjoy Chowdhury }
401*bb154e3eSDorjoy Chowdhury
402*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_map_to_map(root, "DescribePCR", 2, &nested_map)) {
403*bb154e3eSDorjoy Chowdhury goto err;
404*bb154e3eSDorjoy Chowdhury }
405*bb154e3eSDorjoy Chowdhury
406*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_bytestring_to_map(nested_map, "data", pcr->data,
407*bb154e3eSDorjoy Chowdhury QCRYPTO_HASH_DIGEST_LEN_SHA384)) {
408*bb154e3eSDorjoy Chowdhury goto err;
409*bb154e3eSDorjoy Chowdhury }
410*bb154e3eSDorjoy Chowdhury
411*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_bool_to_map(nested_map, "lock", pcr->locked)) {
412*bb154e3eSDorjoy Chowdhury goto err;
413*bb154e3eSDorjoy Chowdhury }
414*bb154e3eSDorjoy Chowdhury
415*bb154e3eSDorjoy Chowdhury len = cbor_serialize(root, response->iov_base, response->iov_len);
416*bb154e3eSDorjoy Chowdhury if (len == 0) {
417*bb154e3eSDorjoy Chowdhury if (error_response(response, NSM_INPUT_TOO_LARGE, errp)) {
418*bb154e3eSDorjoy Chowdhury r = true;
419*bb154e3eSDorjoy Chowdhury }
420*bb154e3eSDorjoy Chowdhury goto out;
421*bb154e3eSDorjoy Chowdhury }
422*bb154e3eSDorjoy Chowdhury
423*bb154e3eSDorjoy Chowdhury response->iov_len = len;
424*bb154e3eSDorjoy Chowdhury r = true;
425*bb154e3eSDorjoy Chowdhury
426*bb154e3eSDorjoy Chowdhury out:
427*bb154e3eSDorjoy Chowdhury if (root) {
428*bb154e3eSDorjoy Chowdhury cbor_decref(&root);
429*bb154e3eSDorjoy Chowdhury }
430*bb154e3eSDorjoy Chowdhury return r;
431*bb154e3eSDorjoy Chowdhury
432*bb154e3eSDorjoy Chowdhury err:
433*bb154e3eSDorjoy Chowdhury error_setg(errp, "Failed to initialize DescribePCR response");
434*bb154e3eSDorjoy Chowdhury goto out;
435*bb154e3eSDorjoy Chowdhury }
436*bb154e3eSDorjoy Chowdhury
437*bb154e3eSDorjoy Chowdhury /*
438*bb154e3eSDorjoy Chowdhury * ExtendPCR request structure:
439*bb154e3eSDorjoy Chowdhury *
440*bb154e3eSDorjoy Chowdhury * {
441*bb154e3eSDorjoy Chowdhury * Map(1) {
442*bb154e3eSDorjoy Chowdhury * key = String("ExtendPCR"),
443*bb154e3eSDorjoy Chowdhury * value = Map(2) {
444*bb154e3eSDorjoy Chowdhury * key = String("index"),
445*bb154e3eSDorjoy Chowdhury * value = Uint8(pcr),
446*bb154e3eSDorjoy Chowdhury * key = String("data"),
447*bb154e3eSDorjoy Chowdhury * value = Byte_String(data),
448*bb154e3eSDorjoy Chowdhury * }
449*bb154e3eSDorjoy Chowdhury * }
450*bb154e3eSDorjoy Chowdhury * }
451*bb154e3eSDorjoy Chowdhury */
452*bb154e3eSDorjoy Chowdhury typedef struct NSMExtendPCRReq {
453*bb154e3eSDorjoy Chowdhury uint8_t index;
454*bb154e3eSDorjoy Chowdhury uint16_t data_len;
455*bb154e3eSDorjoy Chowdhury uint8_t data[NSM_REQUEST_MAX_SIZE];
456*bb154e3eSDorjoy Chowdhury } NSMExtendPCRReq;
457*bb154e3eSDorjoy Chowdhury
get_nsm_extend_pcr_req(uint8_t * req,size_t len,NSMExtendPCRReq * nsm_req)458*bb154e3eSDorjoy Chowdhury static enum NSMResponseTypes get_nsm_extend_pcr_req(uint8_t *req, size_t len,
459*bb154e3eSDorjoy Chowdhury NSMExtendPCRReq *nsm_req)
460*bb154e3eSDorjoy Chowdhury {
461*bb154e3eSDorjoy Chowdhury cbor_item_t *item = NULL;
462*bb154e3eSDorjoy Chowdhury size_t size ;
463*bb154e3eSDorjoy Chowdhury uint8_t *str;
464*bb154e3eSDorjoy Chowdhury bool index_found = false;
465*bb154e3eSDorjoy Chowdhury bool data_found = false;
466*bb154e3eSDorjoy Chowdhury struct cbor_pair *pair;
467*bb154e3eSDorjoy Chowdhury struct cbor_load_result result;
468*bb154e3eSDorjoy Chowdhury enum NSMResponseTypes r = NSM_INVALID_OPERATION;
469*bb154e3eSDorjoy Chowdhury
470*bb154e3eSDorjoy Chowdhury item = cbor_load(req, len, &result);
471*bb154e3eSDorjoy Chowdhury if (!item || result.error.code != CBOR_ERR_NONE) {
472*bb154e3eSDorjoy Chowdhury goto cleanup;
473*bb154e3eSDorjoy Chowdhury }
474*bb154e3eSDorjoy Chowdhury
475*bb154e3eSDorjoy Chowdhury pair = cbor_map_handle(item);
476*bb154e3eSDorjoy Chowdhury if (!cbor_isa_map(pair->value)) {
477*bb154e3eSDorjoy Chowdhury goto cleanup;
478*bb154e3eSDorjoy Chowdhury }
479*bb154e3eSDorjoy Chowdhury size = cbor_map_size(pair->value);
480*bb154e3eSDorjoy Chowdhury if (size < 2) {
481*bb154e3eSDorjoy Chowdhury goto cleanup;
482*bb154e3eSDorjoy Chowdhury }
483*bb154e3eSDorjoy Chowdhury
484*bb154e3eSDorjoy Chowdhury pair = cbor_map_handle(pair->value);
485*bb154e3eSDorjoy Chowdhury for (int i = 0; i < size; ++i) {
486*bb154e3eSDorjoy Chowdhury if (!cbor_isa_string(pair[i].key)) {
487*bb154e3eSDorjoy Chowdhury continue;
488*bb154e3eSDorjoy Chowdhury }
489*bb154e3eSDorjoy Chowdhury str = cbor_string_handle(pair[i].key);
490*bb154e3eSDorjoy Chowdhury if (!str) {
491*bb154e3eSDorjoy Chowdhury continue;
492*bb154e3eSDorjoy Chowdhury }
493*bb154e3eSDorjoy Chowdhury
494*bb154e3eSDorjoy Chowdhury if (cbor_string_length(pair[i].key) == 5 &&
495*bb154e3eSDorjoy Chowdhury memcmp(str, "index", 5) == 0) {
496*bb154e3eSDorjoy Chowdhury if (!cbor_isa_uint(pair[i].value) ||
497*bb154e3eSDorjoy Chowdhury cbor_int_get_width(pair[i].value) != CBOR_INT_8) {
498*bb154e3eSDorjoy Chowdhury goto cleanup;
499*bb154e3eSDorjoy Chowdhury }
500*bb154e3eSDorjoy Chowdhury nsm_req->index = cbor_get_uint8(pair[i].value);
501*bb154e3eSDorjoy Chowdhury index_found = true;
502*bb154e3eSDorjoy Chowdhury continue;
503*bb154e3eSDorjoy Chowdhury }
504*bb154e3eSDorjoy Chowdhury
505*bb154e3eSDorjoy Chowdhury if (cbor_string_length(pair[i].key) == 4 &&
506*bb154e3eSDorjoy Chowdhury memcmp(str, "data", 4) == 0) {
507*bb154e3eSDorjoy Chowdhury if (!cbor_isa_bytestring(pair[i].value)) {
508*bb154e3eSDorjoy Chowdhury goto cleanup;
509*bb154e3eSDorjoy Chowdhury }
510*bb154e3eSDorjoy Chowdhury str = cbor_bytestring_handle(pair[i].value);
511*bb154e3eSDorjoy Chowdhury if (!str) {
512*bb154e3eSDorjoy Chowdhury goto cleanup;
513*bb154e3eSDorjoy Chowdhury }
514*bb154e3eSDorjoy Chowdhury nsm_req->data_len = cbor_bytestring_length(pair[i].value);
515*bb154e3eSDorjoy Chowdhury /*
516*bb154e3eSDorjoy Chowdhury * nsm_req->data_len will be smaller than NSM_REQUEST_MAX_SIZE as
517*bb154e3eSDorjoy Chowdhury * we already check for the max request size before processing
518*bb154e3eSDorjoy Chowdhury * any request. So it's safe to copy.
519*bb154e3eSDorjoy Chowdhury */
520*bb154e3eSDorjoy Chowdhury memcpy(nsm_req->data, str, nsm_req->data_len);
521*bb154e3eSDorjoy Chowdhury data_found = true;
522*bb154e3eSDorjoy Chowdhury continue;
523*bb154e3eSDorjoy Chowdhury }
524*bb154e3eSDorjoy Chowdhury }
525*bb154e3eSDorjoy Chowdhury
526*bb154e3eSDorjoy Chowdhury if (index_found && data_found) {
527*bb154e3eSDorjoy Chowdhury r = NSM_SUCCESS;
528*bb154e3eSDorjoy Chowdhury }
529*bb154e3eSDorjoy Chowdhury
530*bb154e3eSDorjoy Chowdhury cleanup:
531*bb154e3eSDorjoy Chowdhury if (item) {
532*bb154e3eSDorjoy Chowdhury cbor_decref(&item);
533*bb154e3eSDorjoy Chowdhury }
534*bb154e3eSDorjoy Chowdhury return r;
535*bb154e3eSDorjoy Chowdhury }
536*bb154e3eSDorjoy Chowdhury
537*bb154e3eSDorjoy Chowdhury /*
538*bb154e3eSDorjoy Chowdhury * ExtendPCR response structure:
539*bb154e3eSDorjoy Chowdhury *
540*bb154e3eSDorjoy Chowdhury * {
541*bb154e3eSDorjoy Chowdhury * Map(1) {
542*bb154e3eSDorjoy Chowdhury * key = String("ExtendPCR"),
543*bb154e3eSDorjoy Chowdhury * value = Map(1) {
544*bb154e3eSDorjoy Chowdhury * key = String("data"),
545*bb154e3eSDorjoy Chowdhury * value = Byte_String()
546*bb154e3eSDorjoy Chowdhury * }
547*bb154e3eSDorjoy Chowdhury * }
548*bb154e3eSDorjoy Chowdhury * }
549*bb154e3eSDorjoy Chowdhury */
handle_extend_pcr(VirtIONSM * vnsm,struct iovec * request,struct iovec * response,Error ** errp)550*bb154e3eSDorjoy Chowdhury static bool handle_extend_pcr(VirtIONSM *vnsm, struct iovec *request,
551*bb154e3eSDorjoy Chowdhury struct iovec *response, Error **errp)
552*bb154e3eSDorjoy Chowdhury {
553*bb154e3eSDorjoy Chowdhury cbor_item_t *root = NULL;
554*bb154e3eSDorjoy Chowdhury cbor_item_t *nested_map;
555*bb154e3eSDorjoy Chowdhury size_t len;
556*bb154e3eSDorjoy Chowdhury struct PCRInfo *pcr;
557*bb154e3eSDorjoy Chowdhury enum NSMResponseTypes type;
558*bb154e3eSDorjoy Chowdhury bool r = false;
559*bb154e3eSDorjoy Chowdhury g_autofree NSMExtendPCRReq *nsm_req = g_malloc(sizeof(NSMExtendPCRReq));
560*bb154e3eSDorjoy Chowdhury
561*bb154e3eSDorjoy Chowdhury type = get_nsm_extend_pcr_req(request->iov_base, request->iov_len,
562*bb154e3eSDorjoy Chowdhury nsm_req);
563*bb154e3eSDorjoy Chowdhury if (type != NSM_SUCCESS) {
564*bb154e3eSDorjoy Chowdhury if (error_response(response, type, errp)) {
565*bb154e3eSDorjoy Chowdhury r = true;
566*bb154e3eSDorjoy Chowdhury }
567*bb154e3eSDorjoy Chowdhury goto out;
568*bb154e3eSDorjoy Chowdhury }
569*bb154e3eSDorjoy Chowdhury if (nsm_req->index >= vnsm->max_pcrs) {
570*bb154e3eSDorjoy Chowdhury if (error_response(response, NSM_INVALID_INDEX, errp)) {
571*bb154e3eSDorjoy Chowdhury r = true;
572*bb154e3eSDorjoy Chowdhury }
573*bb154e3eSDorjoy Chowdhury goto out;
574*bb154e3eSDorjoy Chowdhury }
575*bb154e3eSDorjoy Chowdhury
576*bb154e3eSDorjoy Chowdhury pcr = &(vnsm->pcrs[nsm_req->index]);
577*bb154e3eSDorjoy Chowdhury
578*bb154e3eSDorjoy Chowdhury if (pcr->locked) {
579*bb154e3eSDorjoy Chowdhury if (error_response(response, NSM_READONLY_INDEX, errp)) {
580*bb154e3eSDorjoy Chowdhury r = true;
581*bb154e3eSDorjoy Chowdhury }
582*bb154e3eSDorjoy Chowdhury goto out;
583*bb154e3eSDorjoy Chowdhury }
584*bb154e3eSDorjoy Chowdhury
585*bb154e3eSDorjoy Chowdhury if (!vnsm->extend_pcr(vnsm, nsm_req->index, nsm_req->data,
586*bb154e3eSDorjoy Chowdhury nsm_req->data_len)) {
587*bb154e3eSDorjoy Chowdhury if (error_response(response, NSM_INTERNAL_ERROR, errp)) {
588*bb154e3eSDorjoy Chowdhury r = true;
589*bb154e3eSDorjoy Chowdhury }
590*bb154e3eSDorjoy Chowdhury goto out;
591*bb154e3eSDorjoy Chowdhury }
592*bb154e3eSDorjoy Chowdhury
593*bb154e3eSDorjoy Chowdhury root = cbor_new_definite_map(1);
594*bb154e3eSDorjoy Chowdhury if (!root) {
595*bb154e3eSDorjoy Chowdhury goto err;
596*bb154e3eSDorjoy Chowdhury }
597*bb154e3eSDorjoy Chowdhury
598*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_map_to_map(root, "ExtendPCR", 1, &nested_map)) {
599*bb154e3eSDorjoy Chowdhury goto err;
600*bb154e3eSDorjoy Chowdhury }
601*bb154e3eSDorjoy Chowdhury
602*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_bytestring_to_map(nested_map, "data", pcr->data,
603*bb154e3eSDorjoy Chowdhury QCRYPTO_HASH_DIGEST_LEN_SHA384)) {
604*bb154e3eSDorjoy Chowdhury goto err;
605*bb154e3eSDorjoy Chowdhury }
606*bb154e3eSDorjoy Chowdhury
607*bb154e3eSDorjoy Chowdhury len = cbor_serialize(root, response->iov_base, response->iov_len);
608*bb154e3eSDorjoy Chowdhury if (len == 0) {
609*bb154e3eSDorjoy Chowdhury if (error_response(response, NSM_BUFFER_TOO_SMALL, errp)) {
610*bb154e3eSDorjoy Chowdhury r = true;
611*bb154e3eSDorjoy Chowdhury }
612*bb154e3eSDorjoy Chowdhury goto out;
613*bb154e3eSDorjoy Chowdhury }
614*bb154e3eSDorjoy Chowdhury
615*bb154e3eSDorjoy Chowdhury response->iov_len = len;
616*bb154e3eSDorjoy Chowdhury r = true;
617*bb154e3eSDorjoy Chowdhury
618*bb154e3eSDorjoy Chowdhury out:
619*bb154e3eSDorjoy Chowdhury if (root) {
620*bb154e3eSDorjoy Chowdhury cbor_decref(&root);
621*bb154e3eSDorjoy Chowdhury }
622*bb154e3eSDorjoy Chowdhury return r;
623*bb154e3eSDorjoy Chowdhury
624*bb154e3eSDorjoy Chowdhury err:
625*bb154e3eSDorjoy Chowdhury error_setg(errp, "Failed to initialize DescribePCR response");
626*bb154e3eSDorjoy Chowdhury goto out;
627*bb154e3eSDorjoy Chowdhury }
628*bb154e3eSDorjoy Chowdhury
629*bb154e3eSDorjoy Chowdhury /*
630*bb154e3eSDorjoy Chowdhury * LockPCR request structure:
631*bb154e3eSDorjoy Chowdhury *
632*bb154e3eSDorjoy Chowdhury * {
633*bb154e3eSDorjoy Chowdhury * Map(1) {
634*bb154e3eSDorjoy Chowdhury * key = String("LockPCR"),
635*bb154e3eSDorjoy Chowdhury * value = Map(1) {
636*bb154e3eSDorjoy Chowdhury * key = String("index"),
637*bb154e3eSDorjoy Chowdhury * value = Uint8(pcr)
638*bb154e3eSDorjoy Chowdhury * }
639*bb154e3eSDorjoy Chowdhury * }
640*bb154e3eSDorjoy Chowdhury * }
641*bb154e3eSDorjoy Chowdhury */
642*bb154e3eSDorjoy Chowdhury typedef struct NSMLockPCRReq {
643*bb154e3eSDorjoy Chowdhury uint8_t index;
644*bb154e3eSDorjoy Chowdhury } NSMLockPCRReq;
645*bb154e3eSDorjoy Chowdhury
get_nsm_lock_pcr_req(uint8_t * req,size_t len,NSMLockPCRReq * nsm_req)646*bb154e3eSDorjoy Chowdhury static enum NSMResponseTypes get_nsm_lock_pcr_req(uint8_t *req, size_t len,
647*bb154e3eSDorjoy Chowdhury NSMLockPCRReq *nsm_req)
648*bb154e3eSDorjoy Chowdhury {
649*bb154e3eSDorjoy Chowdhury cbor_item_t *item = NULL;
650*bb154e3eSDorjoy Chowdhury size_t size;
651*bb154e3eSDorjoy Chowdhury uint8_t *str;
652*bb154e3eSDorjoy Chowdhury struct cbor_pair *pair;
653*bb154e3eSDorjoy Chowdhury struct cbor_load_result result;
654*bb154e3eSDorjoy Chowdhury enum NSMResponseTypes r = NSM_INVALID_OPERATION;
655*bb154e3eSDorjoy Chowdhury
656*bb154e3eSDorjoy Chowdhury item = cbor_load(req, len, &result);
657*bb154e3eSDorjoy Chowdhury if (!item || result.error.code != CBOR_ERR_NONE) {
658*bb154e3eSDorjoy Chowdhury goto cleanup;
659*bb154e3eSDorjoy Chowdhury }
660*bb154e3eSDorjoy Chowdhury
661*bb154e3eSDorjoy Chowdhury pair = cbor_map_handle(item);
662*bb154e3eSDorjoy Chowdhury if (!cbor_isa_map(pair->value)) {
663*bb154e3eSDorjoy Chowdhury goto cleanup;
664*bb154e3eSDorjoy Chowdhury }
665*bb154e3eSDorjoy Chowdhury size = cbor_map_size(pair->value);
666*bb154e3eSDorjoy Chowdhury if (size < 1) {
667*bb154e3eSDorjoy Chowdhury goto cleanup;
668*bb154e3eSDorjoy Chowdhury }
669*bb154e3eSDorjoy Chowdhury
670*bb154e3eSDorjoy Chowdhury pair = cbor_map_handle(pair->value);
671*bb154e3eSDorjoy Chowdhury for (int i = 0; i < size; ++i) {
672*bb154e3eSDorjoy Chowdhury if (!cbor_isa_string(pair[i].key)) {
673*bb154e3eSDorjoy Chowdhury continue;
674*bb154e3eSDorjoy Chowdhury }
675*bb154e3eSDorjoy Chowdhury str = cbor_string_handle(pair[i].key);
676*bb154e3eSDorjoy Chowdhury if (str && cbor_string_length(pair[i].key) == 5 &&
677*bb154e3eSDorjoy Chowdhury memcmp(str, "index", 5) == 0) {
678*bb154e3eSDorjoy Chowdhury if (!cbor_isa_uint(pair[i].value) ||
679*bb154e3eSDorjoy Chowdhury cbor_int_get_width(pair[i].value) != CBOR_INT_8) {
680*bb154e3eSDorjoy Chowdhury break;
681*bb154e3eSDorjoy Chowdhury }
682*bb154e3eSDorjoy Chowdhury
683*bb154e3eSDorjoy Chowdhury nsm_req->index = cbor_get_uint8(pair[i].value);
684*bb154e3eSDorjoy Chowdhury r = NSM_SUCCESS;
685*bb154e3eSDorjoy Chowdhury break;
686*bb154e3eSDorjoy Chowdhury }
687*bb154e3eSDorjoy Chowdhury }
688*bb154e3eSDorjoy Chowdhury
689*bb154e3eSDorjoy Chowdhury cleanup:
690*bb154e3eSDorjoy Chowdhury if (item) {
691*bb154e3eSDorjoy Chowdhury cbor_decref(&item);
692*bb154e3eSDorjoy Chowdhury }
693*bb154e3eSDorjoy Chowdhury return r;
694*bb154e3eSDorjoy Chowdhury }
695*bb154e3eSDorjoy Chowdhury
696*bb154e3eSDorjoy Chowdhury /*
697*bb154e3eSDorjoy Chowdhury * LockPCR success response structure:
698*bb154e3eSDorjoy Chowdhury * {
699*bb154e3eSDorjoy Chowdhury * String("LockPCR")
700*bb154e3eSDorjoy Chowdhury * }
701*bb154e3eSDorjoy Chowdhury */
handle_lock_pcr(VirtIONSM * vnsm,struct iovec * request,struct iovec * response,Error ** errp)702*bb154e3eSDorjoy Chowdhury static bool handle_lock_pcr(VirtIONSM *vnsm, struct iovec *request,
703*bb154e3eSDorjoy Chowdhury struct iovec *response, Error **errp)
704*bb154e3eSDorjoy Chowdhury {
705*bb154e3eSDorjoy Chowdhury cbor_item_t *root = NULL;
706*bb154e3eSDorjoy Chowdhury size_t len;
707*bb154e3eSDorjoy Chowdhury NSMLockPCRReq nsm_req;
708*bb154e3eSDorjoy Chowdhury enum NSMResponseTypes type;
709*bb154e3eSDorjoy Chowdhury struct PCRInfo *pcr;
710*bb154e3eSDorjoy Chowdhury bool r = false;
711*bb154e3eSDorjoy Chowdhury
712*bb154e3eSDorjoy Chowdhury type = get_nsm_lock_pcr_req(request->iov_base, request->iov_len, &nsm_req);
713*bb154e3eSDorjoy Chowdhury if (type != NSM_SUCCESS) {
714*bb154e3eSDorjoy Chowdhury if (error_response(response, type, errp)) {
715*bb154e3eSDorjoy Chowdhury r = true;
716*bb154e3eSDorjoy Chowdhury }
717*bb154e3eSDorjoy Chowdhury goto cleanup;
718*bb154e3eSDorjoy Chowdhury }
719*bb154e3eSDorjoy Chowdhury if (nsm_req.index >= vnsm->max_pcrs) {
720*bb154e3eSDorjoy Chowdhury if (error_response(response, NSM_INVALID_INDEX, errp)) {
721*bb154e3eSDorjoy Chowdhury r = true;
722*bb154e3eSDorjoy Chowdhury }
723*bb154e3eSDorjoy Chowdhury goto cleanup;
724*bb154e3eSDorjoy Chowdhury }
725*bb154e3eSDorjoy Chowdhury
726*bb154e3eSDorjoy Chowdhury pcr = &(vnsm->pcrs[nsm_req.index]);
727*bb154e3eSDorjoy Chowdhury
728*bb154e3eSDorjoy Chowdhury if (pcr->locked) {
729*bb154e3eSDorjoy Chowdhury if (error_response(response, NSM_READONLY_INDEX, errp)) {
730*bb154e3eSDorjoy Chowdhury r = true;
731*bb154e3eSDorjoy Chowdhury }
732*bb154e3eSDorjoy Chowdhury goto cleanup;
733*bb154e3eSDorjoy Chowdhury }
734*bb154e3eSDorjoy Chowdhury
735*bb154e3eSDorjoy Chowdhury pcr->locked = true;
736*bb154e3eSDorjoy Chowdhury
737*bb154e3eSDorjoy Chowdhury root = cbor_build_string("LockPCR");
738*bb154e3eSDorjoy Chowdhury if (!root) {
739*bb154e3eSDorjoy Chowdhury goto err;
740*bb154e3eSDorjoy Chowdhury }
741*bb154e3eSDorjoy Chowdhury
742*bb154e3eSDorjoy Chowdhury len = cbor_serialize(root, response->iov_base, response->iov_len);
743*bb154e3eSDorjoy Chowdhury if (len == 0) {
744*bb154e3eSDorjoy Chowdhury if (error_response(response, NSM_BUFFER_TOO_SMALL, errp)) {
745*bb154e3eSDorjoy Chowdhury r = true;
746*bb154e3eSDorjoy Chowdhury }
747*bb154e3eSDorjoy Chowdhury goto cleanup;
748*bb154e3eSDorjoy Chowdhury }
749*bb154e3eSDorjoy Chowdhury
750*bb154e3eSDorjoy Chowdhury response->iov_len = len;
751*bb154e3eSDorjoy Chowdhury r = true;
752*bb154e3eSDorjoy Chowdhury goto cleanup;
753*bb154e3eSDorjoy Chowdhury
754*bb154e3eSDorjoy Chowdhury err:
755*bb154e3eSDorjoy Chowdhury error_setg(errp, "Failed to initialize LockPCR response");
756*bb154e3eSDorjoy Chowdhury
757*bb154e3eSDorjoy Chowdhury cleanup:
758*bb154e3eSDorjoy Chowdhury if (root) {
759*bb154e3eSDorjoy Chowdhury cbor_decref(&root);
760*bb154e3eSDorjoy Chowdhury }
761*bb154e3eSDorjoy Chowdhury return r;
762*bb154e3eSDorjoy Chowdhury }
763*bb154e3eSDorjoy Chowdhury
764*bb154e3eSDorjoy Chowdhury /*
765*bb154e3eSDorjoy Chowdhury * LockPCRs request structure:
766*bb154e3eSDorjoy Chowdhury *
767*bb154e3eSDorjoy Chowdhury * {
768*bb154e3eSDorjoy Chowdhury * Map(1) {
769*bb154e3eSDorjoy Chowdhury * key = String("LockPCRs"),
770*bb154e3eSDorjoy Chowdhury * value = Map(1) {
771*bb154e3eSDorjoy Chowdhury * key = String("range"),
772*bb154e3eSDorjoy Chowdhury * value = Uint8(pcr)
773*bb154e3eSDorjoy Chowdhury * }
774*bb154e3eSDorjoy Chowdhury * }
775*bb154e3eSDorjoy Chowdhury * }
776*bb154e3eSDorjoy Chowdhury */
777*bb154e3eSDorjoy Chowdhury typedef struct NSMLockPCRsReq {
778*bb154e3eSDorjoy Chowdhury uint16_t range;
779*bb154e3eSDorjoy Chowdhury } NSMLockPCRsReq;
780*bb154e3eSDorjoy Chowdhury
get_nsm_lock_pcrs_req(uint8_t * req,size_t len,NSMLockPCRsReq * nsm_req)781*bb154e3eSDorjoy Chowdhury static enum NSMResponseTypes get_nsm_lock_pcrs_req(uint8_t *req, size_t len,
782*bb154e3eSDorjoy Chowdhury NSMLockPCRsReq *nsm_req)
783*bb154e3eSDorjoy Chowdhury {
784*bb154e3eSDorjoy Chowdhury cbor_item_t *item = NULL;
785*bb154e3eSDorjoy Chowdhury size_t size;
786*bb154e3eSDorjoy Chowdhury uint8_t *str;
787*bb154e3eSDorjoy Chowdhury struct cbor_pair *pair;
788*bb154e3eSDorjoy Chowdhury struct cbor_load_result result;
789*bb154e3eSDorjoy Chowdhury enum NSMResponseTypes r = NSM_INVALID_OPERATION;
790*bb154e3eSDorjoy Chowdhury
791*bb154e3eSDorjoy Chowdhury item = cbor_load(req, len, &result);
792*bb154e3eSDorjoy Chowdhury if (!item || result.error.code != CBOR_ERR_NONE) {
793*bb154e3eSDorjoy Chowdhury goto cleanup;
794*bb154e3eSDorjoy Chowdhury }
795*bb154e3eSDorjoy Chowdhury
796*bb154e3eSDorjoy Chowdhury pair = cbor_map_handle(item);
797*bb154e3eSDorjoy Chowdhury if (!cbor_isa_map(pair->value)) {
798*bb154e3eSDorjoy Chowdhury goto cleanup;
799*bb154e3eSDorjoy Chowdhury }
800*bb154e3eSDorjoy Chowdhury size = cbor_map_size(pair->value);
801*bb154e3eSDorjoy Chowdhury if (size < 1) {
802*bb154e3eSDorjoy Chowdhury goto cleanup;
803*bb154e3eSDorjoy Chowdhury }
804*bb154e3eSDorjoy Chowdhury
805*bb154e3eSDorjoy Chowdhury pair = cbor_map_handle(pair->value);
806*bb154e3eSDorjoy Chowdhury for (int i = 0; i < size; ++i) {
807*bb154e3eSDorjoy Chowdhury if (!cbor_isa_string(pair[i].key)) {
808*bb154e3eSDorjoy Chowdhury continue;
809*bb154e3eSDorjoy Chowdhury }
810*bb154e3eSDorjoy Chowdhury str = cbor_string_handle(pair[i].key);
811*bb154e3eSDorjoy Chowdhury if (str && cbor_string_length(pair[i].key) == 5 &&
812*bb154e3eSDorjoy Chowdhury memcmp(str, "range", 5) == 0) {
813*bb154e3eSDorjoy Chowdhury if (!cbor_isa_uint(pair[i].value) ||
814*bb154e3eSDorjoy Chowdhury cbor_int_get_width(pair[i].value) != CBOR_INT_8) {
815*bb154e3eSDorjoy Chowdhury break;
816*bb154e3eSDorjoy Chowdhury }
817*bb154e3eSDorjoy Chowdhury
818*bb154e3eSDorjoy Chowdhury nsm_req->range = cbor_get_uint8(pair[i].value);
819*bb154e3eSDorjoy Chowdhury r = NSM_SUCCESS;
820*bb154e3eSDorjoy Chowdhury break;
821*bb154e3eSDorjoy Chowdhury }
822*bb154e3eSDorjoy Chowdhury }
823*bb154e3eSDorjoy Chowdhury
824*bb154e3eSDorjoy Chowdhury cleanup:
825*bb154e3eSDorjoy Chowdhury if (item) {
826*bb154e3eSDorjoy Chowdhury cbor_decref(&item);
827*bb154e3eSDorjoy Chowdhury }
828*bb154e3eSDorjoy Chowdhury return r;
829*bb154e3eSDorjoy Chowdhury }
830*bb154e3eSDorjoy Chowdhury
831*bb154e3eSDorjoy Chowdhury /*
832*bb154e3eSDorjoy Chowdhury * LockPCRs success response structure:
833*bb154e3eSDorjoy Chowdhury * {
834*bb154e3eSDorjoy Chowdhury * String("LockPCRs")
835*bb154e3eSDorjoy Chowdhury * }
836*bb154e3eSDorjoy Chowdhury */
handle_lock_pcrs(VirtIONSM * vnsm,struct iovec * request,struct iovec * response,Error ** errp)837*bb154e3eSDorjoy Chowdhury static bool handle_lock_pcrs(VirtIONSM *vnsm, struct iovec *request,
838*bb154e3eSDorjoy Chowdhury struct iovec *response, Error **errp)
839*bb154e3eSDorjoy Chowdhury {
840*bb154e3eSDorjoy Chowdhury cbor_item_t *root = NULL;
841*bb154e3eSDorjoy Chowdhury size_t len;
842*bb154e3eSDorjoy Chowdhury NSMLockPCRsReq nsm_req;
843*bb154e3eSDorjoy Chowdhury enum NSMResponseTypes type;
844*bb154e3eSDorjoy Chowdhury bool r = false;
845*bb154e3eSDorjoy Chowdhury
846*bb154e3eSDorjoy Chowdhury type = get_nsm_lock_pcrs_req(request->iov_base, request->iov_len, &nsm_req);
847*bb154e3eSDorjoy Chowdhury if (type != NSM_SUCCESS) {
848*bb154e3eSDorjoy Chowdhury if (error_response(response, type, errp)) {
849*bb154e3eSDorjoy Chowdhury r = true;
850*bb154e3eSDorjoy Chowdhury }
851*bb154e3eSDorjoy Chowdhury goto cleanup;
852*bb154e3eSDorjoy Chowdhury }
853*bb154e3eSDorjoy Chowdhury if (nsm_req.range > vnsm->max_pcrs) {
854*bb154e3eSDorjoy Chowdhury if (error_response(response, NSM_INVALID_INDEX, errp)) {
855*bb154e3eSDorjoy Chowdhury r = true;
856*bb154e3eSDorjoy Chowdhury }
857*bb154e3eSDorjoy Chowdhury goto cleanup;
858*bb154e3eSDorjoy Chowdhury }
859*bb154e3eSDorjoy Chowdhury
860*bb154e3eSDorjoy Chowdhury for (int i = 0; i < nsm_req.range; ++i) {
861*bb154e3eSDorjoy Chowdhury vnsm->pcrs[i].locked = true;
862*bb154e3eSDorjoy Chowdhury }
863*bb154e3eSDorjoy Chowdhury
864*bb154e3eSDorjoy Chowdhury root = cbor_build_string("LockPCRs");
865*bb154e3eSDorjoy Chowdhury if (!root) {
866*bb154e3eSDorjoy Chowdhury goto err;
867*bb154e3eSDorjoy Chowdhury }
868*bb154e3eSDorjoy Chowdhury
869*bb154e3eSDorjoy Chowdhury len = cbor_serialize(root, response->iov_base, response->iov_len);
870*bb154e3eSDorjoy Chowdhury if (len == 0) {
871*bb154e3eSDorjoy Chowdhury if (error_response(response, NSM_BUFFER_TOO_SMALL, errp)) {
872*bb154e3eSDorjoy Chowdhury r = true;
873*bb154e3eSDorjoy Chowdhury }
874*bb154e3eSDorjoy Chowdhury goto cleanup;
875*bb154e3eSDorjoy Chowdhury }
876*bb154e3eSDorjoy Chowdhury
877*bb154e3eSDorjoy Chowdhury response->iov_len = len;
878*bb154e3eSDorjoy Chowdhury r = true;
879*bb154e3eSDorjoy Chowdhury goto cleanup;
880*bb154e3eSDorjoy Chowdhury
881*bb154e3eSDorjoy Chowdhury err:
882*bb154e3eSDorjoy Chowdhury error_setg(errp, "Failed to initialize response");
883*bb154e3eSDorjoy Chowdhury
884*bb154e3eSDorjoy Chowdhury cleanup:
885*bb154e3eSDorjoy Chowdhury if (root) {
886*bb154e3eSDorjoy Chowdhury cbor_decref(&root);
887*bb154e3eSDorjoy Chowdhury }
888*bb154e3eSDorjoy Chowdhury return r;
889*bb154e3eSDorjoy Chowdhury }
890*bb154e3eSDorjoy Chowdhury
891*bb154e3eSDorjoy Chowdhury /*
892*bb154e3eSDorjoy Chowdhury * Attestation request structure:
893*bb154e3eSDorjoy Chowdhury *
894*bb154e3eSDorjoy Chowdhury * Map(1) {
895*bb154e3eSDorjoy Chowdhury * key = String("Attestation"),
896*bb154e3eSDorjoy Chowdhury * value = Map(3) {
897*bb154e3eSDorjoy Chowdhury * key = String("user_data"),
898*bb154e3eSDorjoy Chowdhury * value = Byte_String() || null, // Optional
899*bb154e3eSDorjoy Chowdhury * key = String("nonce"),
900*bb154e3eSDorjoy Chowdhury * value = Byte_String() || null, // Optional
901*bb154e3eSDorjoy Chowdhury * key = String("public_key"),
902*bb154e3eSDorjoy Chowdhury * value = Byte_String() || null, // Optional
903*bb154e3eSDorjoy Chowdhury * }
904*bb154e3eSDorjoy Chowdhury * }
905*bb154e3eSDorjoy Chowdhury * }
906*bb154e3eSDorjoy Chowdhury */
907*bb154e3eSDorjoy Chowdhury
908*bb154e3eSDorjoy Chowdhury struct AttestationProperty {
909*bb154e3eSDorjoy Chowdhury bool is_null; /* True if property is not present in map or is null */
910*bb154e3eSDorjoy Chowdhury uint16_t len;
911*bb154e3eSDorjoy Chowdhury uint8_t buf[NSM_REQUEST_MAX_SIZE];
912*bb154e3eSDorjoy Chowdhury };
913*bb154e3eSDorjoy Chowdhury
914*bb154e3eSDorjoy Chowdhury typedef struct NSMAttestationReq {
915*bb154e3eSDorjoy Chowdhury struct AttestationProperty public_key;
916*bb154e3eSDorjoy Chowdhury struct AttestationProperty user_data;
917*bb154e3eSDorjoy Chowdhury struct AttestationProperty nonce;
918*bb154e3eSDorjoy Chowdhury } NSMAttestationReq;
919*bb154e3eSDorjoy Chowdhury
fill_attestation_property(struct AttestationProperty * prop,cbor_item_t * value)920*bb154e3eSDorjoy Chowdhury static bool fill_attestation_property(struct AttestationProperty *prop,
921*bb154e3eSDorjoy Chowdhury cbor_item_t *value)
922*bb154e3eSDorjoy Chowdhury {
923*bb154e3eSDorjoy Chowdhury uint8_t *str;
924*bb154e3eSDorjoy Chowdhury bool ret = false;
925*bb154e3eSDorjoy Chowdhury
926*bb154e3eSDorjoy Chowdhury if (cbor_is_null(value)) {
927*bb154e3eSDorjoy Chowdhury prop->is_null = true;
928*bb154e3eSDorjoy Chowdhury ret = true;
929*bb154e3eSDorjoy Chowdhury goto out;
930*bb154e3eSDorjoy Chowdhury } else if (cbor_isa_bytestring(value)) {
931*bb154e3eSDorjoy Chowdhury str = cbor_bytestring_handle(value);
932*bb154e3eSDorjoy Chowdhury if (!str) {
933*bb154e3eSDorjoy Chowdhury goto out;
934*bb154e3eSDorjoy Chowdhury }
935*bb154e3eSDorjoy Chowdhury prop->len = cbor_bytestring_length(value);
936*bb154e3eSDorjoy Chowdhury } else if (cbor_isa_string(value)) {
937*bb154e3eSDorjoy Chowdhury str = cbor_string_handle(value);
938*bb154e3eSDorjoy Chowdhury if (!str) {
939*bb154e3eSDorjoy Chowdhury goto out;
940*bb154e3eSDorjoy Chowdhury }
941*bb154e3eSDorjoy Chowdhury prop->len = cbor_string_length(value);
942*bb154e3eSDorjoy Chowdhury } else {
943*bb154e3eSDorjoy Chowdhury goto out;
944*bb154e3eSDorjoy Chowdhury }
945*bb154e3eSDorjoy Chowdhury
946*bb154e3eSDorjoy Chowdhury /*
947*bb154e3eSDorjoy Chowdhury * prop->len will be smaller than NSM_REQUEST_MAX_SIZE as we
948*bb154e3eSDorjoy Chowdhury * already check for the max request size before processing
949*bb154e3eSDorjoy Chowdhury * any request. So it's safe to copy.
950*bb154e3eSDorjoy Chowdhury */
951*bb154e3eSDorjoy Chowdhury memcpy(prop->buf, str, prop->len);
952*bb154e3eSDorjoy Chowdhury prop->is_null = false;
953*bb154e3eSDorjoy Chowdhury ret = true;
954*bb154e3eSDorjoy Chowdhury
955*bb154e3eSDorjoy Chowdhury out:
956*bb154e3eSDorjoy Chowdhury return ret;
957*bb154e3eSDorjoy Chowdhury }
958*bb154e3eSDorjoy Chowdhury
get_nsm_attestation_req(uint8_t * req,size_t len,NSMAttestationReq * nsm_req)959*bb154e3eSDorjoy Chowdhury static enum NSMResponseTypes get_nsm_attestation_req(uint8_t *req, size_t len,
960*bb154e3eSDorjoy Chowdhury NSMAttestationReq *nsm_req)
961*bb154e3eSDorjoy Chowdhury {
962*bb154e3eSDorjoy Chowdhury cbor_item_t *item = NULL;
963*bb154e3eSDorjoy Chowdhury size_t size;
964*bb154e3eSDorjoy Chowdhury uint8_t *str;
965*bb154e3eSDorjoy Chowdhury struct cbor_pair *pair;
966*bb154e3eSDorjoy Chowdhury struct cbor_load_result result;
967*bb154e3eSDorjoy Chowdhury enum NSMResponseTypes r = NSM_INVALID_OPERATION;
968*bb154e3eSDorjoy Chowdhury
969*bb154e3eSDorjoy Chowdhury nsm_req->public_key.is_null = true;
970*bb154e3eSDorjoy Chowdhury nsm_req->user_data.is_null = true;
971*bb154e3eSDorjoy Chowdhury nsm_req->nonce.is_null = true;
972*bb154e3eSDorjoy Chowdhury
973*bb154e3eSDorjoy Chowdhury item = cbor_load(req, len, &result);
974*bb154e3eSDorjoy Chowdhury if (!item || result.error.code != CBOR_ERR_NONE) {
975*bb154e3eSDorjoy Chowdhury goto cleanup;
976*bb154e3eSDorjoy Chowdhury }
977*bb154e3eSDorjoy Chowdhury
978*bb154e3eSDorjoy Chowdhury pair = cbor_map_handle(item);
979*bb154e3eSDorjoy Chowdhury if (!cbor_isa_map(pair->value)) {
980*bb154e3eSDorjoy Chowdhury goto cleanup;
981*bb154e3eSDorjoy Chowdhury }
982*bb154e3eSDorjoy Chowdhury size = cbor_map_size(pair->value);
983*bb154e3eSDorjoy Chowdhury if (size == 0) {
984*bb154e3eSDorjoy Chowdhury r = NSM_SUCCESS;
985*bb154e3eSDorjoy Chowdhury goto cleanup;
986*bb154e3eSDorjoy Chowdhury }
987*bb154e3eSDorjoy Chowdhury
988*bb154e3eSDorjoy Chowdhury pair = cbor_map_handle(pair->value);
989*bb154e3eSDorjoy Chowdhury for (int i = 0; i < size; ++i) {
990*bb154e3eSDorjoy Chowdhury if (!cbor_isa_string(pair[i].key)) {
991*bb154e3eSDorjoy Chowdhury continue;
992*bb154e3eSDorjoy Chowdhury }
993*bb154e3eSDorjoy Chowdhury
994*bb154e3eSDorjoy Chowdhury str = cbor_string_handle(pair[i].key);
995*bb154e3eSDorjoy Chowdhury if (!str) {
996*bb154e3eSDorjoy Chowdhury continue;
997*bb154e3eSDorjoy Chowdhury }
998*bb154e3eSDorjoy Chowdhury
999*bb154e3eSDorjoy Chowdhury if (cbor_string_length(pair[i].key) == 10 &&
1000*bb154e3eSDorjoy Chowdhury memcmp(str, "public_key", 10) == 0) {
1001*bb154e3eSDorjoy Chowdhury if (!fill_attestation_property(&(nsm_req->public_key),
1002*bb154e3eSDorjoy Chowdhury pair[i].value)) {
1003*bb154e3eSDorjoy Chowdhury goto cleanup;
1004*bb154e3eSDorjoy Chowdhury }
1005*bb154e3eSDorjoy Chowdhury continue;
1006*bb154e3eSDorjoy Chowdhury }
1007*bb154e3eSDorjoy Chowdhury
1008*bb154e3eSDorjoy Chowdhury if (cbor_string_length(pair[i].key) == 9 &&
1009*bb154e3eSDorjoy Chowdhury memcmp(str, "user_data", 9) == 0) {
1010*bb154e3eSDorjoy Chowdhury if (!fill_attestation_property(&(nsm_req->user_data),
1011*bb154e3eSDorjoy Chowdhury pair[i].value)) {
1012*bb154e3eSDorjoy Chowdhury goto cleanup;
1013*bb154e3eSDorjoy Chowdhury }
1014*bb154e3eSDorjoy Chowdhury continue;
1015*bb154e3eSDorjoy Chowdhury }
1016*bb154e3eSDorjoy Chowdhury
1017*bb154e3eSDorjoy Chowdhury if (cbor_string_length(pair[i].key) == 5 &&
1018*bb154e3eSDorjoy Chowdhury memcmp(str, "nonce", 5) == 0) {
1019*bb154e3eSDorjoy Chowdhury if (!fill_attestation_property(&(nsm_req->nonce), pair[i].value)) {
1020*bb154e3eSDorjoy Chowdhury goto cleanup;
1021*bb154e3eSDorjoy Chowdhury }
1022*bb154e3eSDorjoy Chowdhury continue;
1023*bb154e3eSDorjoy Chowdhury }
1024*bb154e3eSDorjoy Chowdhury }
1025*bb154e3eSDorjoy Chowdhury
1026*bb154e3eSDorjoy Chowdhury r = NSM_SUCCESS;
1027*bb154e3eSDorjoy Chowdhury
1028*bb154e3eSDorjoy Chowdhury cleanup:
1029*bb154e3eSDorjoy Chowdhury if (item) {
1030*bb154e3eSDorjoy Chowdhury cbor_decref(&item);
1031*bb154e3eSDorjoy Chowdhury }
1032*bb154e3eSDorjoy Chowdhury return r;
1033*bb154e3eSDorjoy Chowdhury }
1034*bb154e3eSDorjoy Chowdhury
add_protected_header_to_cose(cbor_item_t * cose)1035*bb154e3eSDorjoy Chowdhury static bool add_protected_header_to_cose(cbor_item_t *cose)
1036*bb154e3eSDorjoy Chowdhury {
1037*bb154e3eSDorjoy Chowdhury cbor_item_t *map = NULL;
1038*bb154e3eSDorjoy Chowdhury cbor_item_t *key = NULL;
1039*bb154e3eSDorjoy Chowdhury cbor_item_t *value = NULL;
1040*bb154e3eSDorjoy Chowdhury cbor_item_t *bs = NULL;
1041*bb154e3eSDorjoy Chowdhury size_t len;
1042*bb154e3eSDorjoy Chowdhury bool r = false;
1043*bb154e3eSDorjoy Chowdhury size_t buf_len = 4096;
1044*bb154e3eSDorjoy Chowdhury g_autofree uint8_t *buf = g_malloc(buf_len);
1045*bb154e3eSDorjoy Chowdhury
1046*bb154e3eSDorjoy Chowdhury map = cbor_new_definite_map(1);
1047*bb154e3eSDorjoy Chowdhury if (!map) {
1048*bb154e3eSDorjoy Chowdhury goto cleanup;
1049*bb154e3eSDorjoy Chowdhury }
1050*bb154e3eSDorjoy Chowdhury key = cbor_build_uint8(1);
1051*bb154e3eSDorjoy Chowdhury if (!key) {
1052*bb154e3eSDorjoy Chowdhury goto cleanup;
1053*bb154e3eSDorjoy Chowdhury }
1054*bb154e3eSDorjoy Chowdhury value = cbor_new_int8();
1055*bb154e3eSDorjoy Chowdhury if (!value) {
1056*bb154e3eSDorjoy Chowdhury goto cleanup;
1057*bb154e3eSDorjoy Chowdhury }
1058*bb154e3eSDorjoy Chowdhury cbor_mark_negint(value);
1059*bb154e3eSDorjoy Chowdhury /* we don't actually sign the data, so we use -1 as the 'alg' value */
1060*bb154e3eSDorjoy Chowdhury cbor_set_uint8(value, 0);
1061*bb154e3eSDorjoy Chowdhury
1062*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_map_add(map, key, value)) {
1063*bb154e3eSDorjoy Chowdhury goto cleanup;
1064*bb154e3eSDorjoy Chowdhury }
1065*bb154e3eSDorjoy Chowdhury
1066*bb154e3eSDorjoy Chowdhury len = cbor_serialize(map, buf, buf_len);
1067*bb154e3eSDorjoy Chowdhury if (len == 0) {
1068*bb154e3eSDorjoy Chowdhury goto cleanup_map;
1069*bb154e3eSDorjoy Chowdhury }
1070*bb154e3eSDorjoy Chowdhury
1071*bb154e3eSDorjoy Chowdhury bs = cbor_build_bytestring(buf, len);
1072*bb154e3eSDorjoy Chowdhury if (!bs) {
1073*bb154e3eSDorjoy Chowdhury goto cleanup_map;
1074*bb154e3eSDorjoy Chowdhury }
1075*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_array_push(cose, bs)) {
1076*bb154e3eSDorjoy Chowdhury cbor_decref(&bs);
1077*bb154e3eSDorjoy Chowdhury goto cleanup_map;
1078*bb154e3eSDorjoy Chowdhury }
1079*bb154e3eSDorjoy Chowdhury r = true;
1080*bb154e3eSDorjoy Chowdhury goto cleanup_map;
1081*bb154e3eSDorjoy Chowdhury
1082*bb154e3eSDorjoy Chowdhury cleanup:
1083*bb154e3eSDorjoy Chowdhury if (key) {
1084*bb154e3eSDorjoy Chowdhury cbor_decref(&key);
1085*bb154e3eSDorjoy Chowdhury }
1086*bb154e3eSDorjoy Chowdhury if (value) {
1087*bb154e3eSDorjoy Chowdhury cbor_decref(&value);
1088*bb154e3eSDorjoy Chowdhury }
1089*bb154e3eSDorjoy Chowdhury
1090*bb154e3eSDorjoy Chowdhury cleanup_map:
1091*bb154e3eSDorjoy Chowdhury if (map) {
1092*bb154e3eSDorjoy Chowdhury cbor_decref(&map);
1093*bb154e3eSDorjoy Chowdhury }
1094*bb154e3eSDorjoy Chowdhury return r;
1095*bb154e3eSDorjoy Chowdhury }
1096*bb154e3eSDorjoy Chowdhury
add_unprotected_header_to_cose(cbor_item_t * cose)1097*bb154e3eSDorjoy Chowdhury static bool add_unprotected_header_to_cose(cbor_item_t *cose)
1098*bb154e3eSDorjoy Chowdhury {
1099*bb154e3eSDorjoy Chowdhury cbor_item_t *map = cbor_new_definite_map(0);
1100*bb154e3eSDorjoy Chowdhury if (!map) {
1101*bb154e3eSDorjoy Chowdhury goto cleanup;
1102*bb154e3eSDorjoy Chowdhury }
1103*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_array_push(cose, map)) {
1104*bb154e3eSDorjoy Chowdhury goto cleanup;
1105*bb154e3eSDorjoy Chowdhury }
1106*bb154e3eSDorjoy Chowdhury
1107*bb154e3eSDorjoy Chowdhury return true;
1108*bb154e3eSDorjoy Chowdhury
1109*bb154e3eSDorjoy Chowdhury cleanup:
1110*bb154e3eSDorjoy Chowdhury if (map) {
1111*bb154e3eSDorjoy Chowdhury cbor_decref(&map);
1112*bb154e3eSDorjoy Chowdhury }
1113*bb154e3eSDorjoy Chowdhury return false;
1114*bb154e3eSDorjoy Chowdhury }
1115*bb154e3eSDorjoy Chowdhury
add_ca_bundle_to_payload(cbor_item_t * map)1116*bb154e3eSDorjoy Chowdhury static bool add_ca_bundle_to_payload(cbor_item_t *map)
1117*bb154e3eSDorjoy Chowdhury {
1118*bb154e3eSDorjoy Chowdhury cbor_item_t *key_cbor = NULL;
1119*bb154e3eSDorjoy Chowdhury cbor_item_t *value_cbor = NULL;
1120*bb154e3eSDorjoy Chowdhury cbor_item_t *bs = NULL;
1121*bb154e3eSDorjoy Chowdhury uint8_t zero[64] = {0};
1122*bb154e3eSDorjoy Chowdhury
1123*bb154e3eSDorjoy Chowdhury key_cbor = cbor_build_string("cabundle");
1124*bb154e3eSDorjoy Chowdhury if (!key_cbor) {
1125*bb154e3eSDorjoy Chowdhury goto cleanup;
1126*bb154e3eSDorjoy Chowdhury }
1127*bb154e3eSDorjoy Chowdhury value_cbor = cbor_new_definite_array(1);
1128*bb154e3eSDorjoy Chowdhury if (!value_cbor) {
1129*bb154e3eSDorjoy Chowdhury goto cleanup;
1130*bb154e3eSDorjoy Chowdhury }
1131*bb154e3eSDorjoy Chowdhury bs = cbor_build_bytestring(zero, 64);
1132*bb154e3eSDorjoy Chowdhury if (!bs) {
1133*bb154e3eSDorjoy Chowdhury goto cleanup;
1134*bb154e3eSDorjoy Chowdhury }
1135*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_array_push(value_cbor, bs)) {
1136*bb154e3eSDorjoy Chowdhury cbor_decref(&bs);
1137*bb154e3eSDorjoy Chowdhury goto cleanup;
1138*bb154e3eSDorjoy Chowdhury }
1139*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_map_add(map, key_cbor, value_cbor)) {
1140*bb154e3eSDorjoy Chowdhury goto cleanup;
1141*bb154e3eSDorjoy Chowdhury }
1142*bb154e3eSDorjoy Chowdhury
1143*bb154e3eSDorjoy Chowdhury return true;
1144*bb154e3eSDorjoy Chowdhury
1145*bb154e3eSDorjoy Chowdhury cleanup:
1146*bb154e3eSDorjoy Chowdhury if (key_cbor) {
1147*bb154e3eSDorjoy Chowdhury cbor_decref(&key_cbor);
1148*bb154e3eSDorjoy Chowdhury }
1149*bb154e3eSDorjoy Chowdhury if (value_cbor) {
1150*bb154e3eSDorjoy Chowdhury cbor_decref(&value_cbor);
1151*bb154e3eSDorjoy Chowdhury }
1152*bb154e3eSDorjoy Chowdhury return false;
1153*bb154e3eSDorjoy Chowdhury }
1154*bb154e3eSDorjoy Chowdhury
add_payload_to_cose(cbor_item_t * cose,VirtIONSM * vnsm,NSMAttestationReq * req)1155*bb154e3eSDorjoy Chowdhury static bool add_payload_to_cose(cbor_item_t *cose, VirtIONSM *vnsm,
1156*bb154e3eSDorjoy Chowdhury NSMAttestationReq *req)
1157*bb154e3eSDorjoy Chowdhury {
1158*bb154e3eSDorjoy Chowdhury cbor_item_t *root = NULL;
1159*bb154e3eSDorjoy Chowdhury cbor_item_t *nested_map;
1160*bb154e3eSDorjoy Chowdhury cbor_item_t *bs = NULL;
1161*bb154e3eSDorjoy Chowdhury size_t locked_cnt;
1162*bb154e3eSDorjoy Chowdhury uint8_t ind[NSM_MAX_PCRS];
1163*bb154e3eSDorjoy Chowdhury size_t payload_map_size = 9;
1164*bb154e3eSDorjoy Chowdhury size_t len;
1165*bb154e3eSDorjoy Chowdhury struct PCRInfo *pcr;
1166*bb154e3eSDorjoy Chowdhury uint8_t zero[64] = {0};
1167*bb154e3eSDorjoy Chowdhury bool r = false;
1168*bb154e3eSDorjoy Chowdhury size_t buf_len = 16384;
1169*bb154e3eSDorjoy Chowdhury g_autofree uint8_t *buf = g_malloc(buf_len);
1170*bb154e3eSDorjoy Chowdhury
1171*bb154e3eSDorjoy Chowdhury root = cbor_new_definite_map(payload_map_size);
1172*bb154e3eSDorjoy Chowdhury if (!root) {
1173*bb154e3eSDorjoy Chowdhury goto cleanup;
1174*bb154e3eSDorjoy Chowdhury }
1175*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_string_to_map(root, "module_id", vnsm->module_id)) {
1176*bb154e3eSDorjoy Chowdhury goto cleanup;
1177*bb154e3eSDorjoy Chowdhury }
1178*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_string_to_map(root, "digest", vnsm->digest)) {
1179*bb154e3eSDorjoy Chowdhury goto cleanup;
1180*bb154e3eSDorjoy Chowdhury }
1181*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_uint64_to_map(root, "timestamp",
1182*bb154e3eSDorjoy Chowdhury (uint64_t) time(NULL) * 1000)) {
1183*bb154e3eSDorjoy Chowdhury goto cleanup;
1184*bb154e3eSDorjoy Chowdhury }
1185*bb154e3eSDorjoy Chowdhury
1186*bb154e3eSDorjoy Chowdhury locked_cnt = 0;
1187*bb154e3eSDorjoy Chowdhury for (uint8_t i = 0; i < NSM_MAX_PCRS; ++i) {
1188*bb154e3eSDorjoy Chowdhury if (vnsm->pcrs[i].locked) {
1189*bb154e3eSDorjoy Chowdhury ind[locked_cnt++] = i;
1190*bb154e3eSDorjoy Chowdhury }
1191*bb154e3eSDorjoy Chowdhury }
1192*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_map_to_map(root, "pcrs", locked_cnt, &nested_map)) {
1193*bb154e3eSDorjoy Chowdhury goto cleanup;
1194*bb154e3eSDorjoy Chowdhury }
1195*bb154e3eSDorjoy Chowdhury for (uint8_t i = 0; i < locked_cnt; ++i) {
1196*bb154e3eSDorjoy Chowdhury pcr = &(vnsm->pcrs[ind[i]]);
1197*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_uint8_key_bytestring_to_map(
1198*bb154e3eSDorjoy Chowdhury nested_map, ind[i],
1199*bb154e3eSDorjoy Chowdhury pcr->data,
1200*bb154e3eSDorjoy Chowdhury QCRYPTO_HASH_DIGEST_LEN_SHA384)) {
1201*bb154e3eSDorjoy Chowdhury goto cleanup;
1202*bb154e3eSDorjoy Chowdhury }
1203*bb154e3eSDorjoy Chowdhury }
1204*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_bytestring_to_map(root, "certificate", zero, 64)) {
1205*bb154e3eSDorjoy Chowdhury goto cleanup;
1206*bb154e3eSDorjoy Chowdhury }
1207*bb154e3eSDorjoy Chowdhury if (!add_ca_bundle_to_payload(root)) {
1208*bb154e3eSDorjoy Chowdhury goto cleanup;
1209*bb154e3eSDorjoy Chowdhury }
1210*bb154e3eSDorjoy Chowdhury
1211*bb154e3eSDorjoy Chowdhury if (req->public_key.is_null) {
1212*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_null_to_map(root, "public_key")) {
1213*bb154e3eSDorjoy Chowdhury goto cleanup;
1214*bb154e3eSDorjoy Chowdhury }
1215*bb154e3eSDorjoy Chowdhury } else if (!qemu_cbor_add_bytestring_to_map(root, "public_key",
1216*bb154e3eSDorjoy Chowdhury req->public_key.buf,
1217*bb154e3eSDorjoy Chowdhury req->public_key.len)) {
1218*bb154e3eSDorjoy Chowdhury goto cleanup;
1219*bb154e3eSDorjoy Chowdhury }
1220*bb154e3eSDorjoy Chowdhury
1221*bb154e3eSDorjoy Chowdhury if (req->user_data.is_null) {
1222*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_null_to_map(root, "user_data")) {
1223*bb154e3eSDorjoy Chowdhury goto cleanup;
1224*bb154e3eSDorjoy Chowdhury }
1225*bb154e3eSDorjoy Chowdhury } else if (!qemu_cbor_add_bytestring_to_map(root, "user_data",
1226*bb154e3eSDorjoy Chowdhury req->user_data.buf,
1227*bb154e3eSDorjoy Chowdhury req->user_data.len)) {
1228*bb154e3eSDorjoy Chowdhury goto cleanup;
1229*bb154e3eSDorjoy Chowdhury }
1230*bb154e3eSDorjoy Chowdhury
1231*bb154e3eSDorjoy Chowdhury if (req->nonce.is_null) {
1232*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_null_to_map(root, "nonce")) {
1233*bb154e3eSDorjoy Chowdhury goto cleanup;
1234*bb154e3eSDorjoy Chowdhury }
1235*bb154e3eSDorjoy Chowdhury } else if (!qemu_cbor_add_bytestring_to_map(root, "nonce",
1236*bb154e3eSDorjoy Chowdhury req->nonce.buf,
1237*bb154e3eSDorjoy Chowdhury req->nonce.len)) {
1238*bb154e3eSDorjoy Chowdhury goto cleanup;
1239*bb154e3eSDorjoy Chowdhury }
1240*bb154e3eSDorjoy Chowdhury
1241*bb154e3eSDorjoy Chowdhury len = cbor_serialize(root, buf, buf_len);
1242*bb154e3eSDorjoy Chowdhury if (len == 0) {
1243*bb154e3eSDorjoy Chowdhury goto cleanup;
1244*bb154e3eSDorjoy Chowdhury }
1245*bb154e3eSDorjoy Chowdhury
1246*bb154e3eSDorjoy Chowdhury bs = cbor_build_bytestring(buf, len);
1247*bb154e3eSDorjoy Chowdhury if (!bs) {
1248*bb154e3eSDorjoy Chowdhury goto cleanup;
1249*bb154e3eSDorjoy Chowdhury }
1250*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_array_push(cose, bs)) {
1251*bb154e3eSDorjoy Chowdhury cbor_decref(&bs);
1252*bb154e3eSDorjoy Chowdhury goto cleanup;
1253*bb154e3eSDorjoy Chowdhury }
1254*bb154e3eSDorjoy Chowdhury
1255*bb154e3eSDorjoy Chowdhury r = true;
1256*bb154e3eSDorjoy Chowdhury
1257*bb154e3eSDorjoy Chowdhury cleanup:
1258*bb154e3eSDorjoy Chowdhury if (root) {
1259*bb154e3eSDorjoy Chowdhury cbor_decref(&root);
1260*bb154e3eSDorjoy Chowdhury }
1261*bb154e3eSDorjoy Chowdhury return r;
1262*bb154e3eSDorjoy Chowdhury }
1263*bb154e3eSDorjoy Chowdhury
add_signature_to_cose(cbor_item_t * cose)1264*bb154e3eSDorjoy Chowdhury static bool add_signature_to_cose(cbor_item_t *cose)
1265*bb154e3eSDorjoy Chowdhury {
1266*bb154e3eSDorjoy Chowdhury cbor_item_t *bs = NULL;
1267*bb154e3eSDorjoy Chowdhury uint8_t zero[64] = {0};
1268*bb154e3eSDorjoy Chowdhury
1269*bb154e3eSDorjoy Chowdhury /* we don't actually sign the data, so we just put 64 zero bytes */
1270*bb154e3eSDorjoy Chowdhury bs = cbor_build_bytestring(zero, 64);
1271*bb154e3eSDorjoy Chowdhury if (!bs) {
1272*bb154e3eSDorjoy Chowdhury goto cleanup;
1273*bb154e3eSDorjoy Chowdhury }
1274*bb154e3eSDorjoy Chowdhury
1275*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_array_push(cose, bs)) {
1276*bb154e3eSDorjoy Chowdhury goto cleanup;
1277*bb154e3eSDorjoy Chowdhury }
1278*bb154e3eSDorjoy Chowdhury
1279*bb154e3eSDorjoy Chowdhury return true;
1280*bb154e3eSDorjoy Chowdhury
1281*bb154e3eSDorjoy Chowdhury cleanup:
1282*bb154e3eSDorjoy Chowdhury if (bs) {
1283*bb154e3eSDorjoy Chowdhury cbor_decref(&bs);
1284*bb154e3eSDorjoy Chowdhury }
1285*bb154e3eSDorjoy Chowdhury return false;
1286*bb154e3eSDorjoy Chowdhury }
1287*bb154e3eSDorjoy Chowdhury
1288*bb154e3eSDorjoy Chowdhury /*
1289*bb154e3eSDorjoy Chowdhury * Attestation response structure:
1290*bb154e3eSDorjoy Chowdhury *
1291*bb154e3eSDorjoy Chowdhury * {
1292*bb154e3eSDorjoy Chowdhury * Map(1) {
1293*bb154e3eSDorjoy Chowdhury * key = String("Attestation"),
1294*bb154e3eSDorjoy Chowdhury * value = Map(1) {
1295*bb154e3eSDorjoy Chowdhury * key = String("document"),
1296*bb154e3eSDorjoy Chowdhury * value = Byte_String()
1297*bb154e3eSDorjoy Chowdhury * }
1298*bb154e3eSDorjoy Chowdhury * }
1299*bb154e3eSDorjoy Chowdhury * }
1300*bb154e3eSDorjoy Chowdhury *
1301*bb154e3eSDorjoy Chowdhury * The document is a serialized COSE sign1 blob of the structure:
1302*bb154e3eSDorjoy Chowdhury * {
1303*bb154e3eSDorjoy Chowdhury * Array(4) {
1304*bb154e3eSDorjoy Chowdhury * [0] { ByteString() }, // serialized protected header
1305*bb154e3eSDorjoy Chowdhury * [1] { Map(0) }, // 0 length map
1306*bb154e3eSDorjoy Chowdhury * [2] { ByteString() }, // serialized payload
1307*bb154e3eSDorjoy Chowdhury * [3] { ByteString() }, // signature
1308*bb154e3eSDorjoy Chowdhury * }
1309*bb154e3eSDorjoy Chowdhury * }
1310*bb154e3eSDorjoy Chowdhury *
1311*bb154e3eSDorjoy Chowdhury * where [0] protected header is a serialized CBOR blob of the structure:
1312*bb154e3eSDorjoy Chowdhury * {
1313*bb154e3eSDorjoy Chowdhury * Map(1) {
1314*bb154e3eSDorjoy Chowdhury * key = Uint8(1) // alg
1315*bb154e3eSDorjoy Chowdhury * value = NegativeInt8() // Signing algorithm
1316*bb154e3eSDorjoy Chowdhury * }
1317*bb154e3eSDorjoy Chowdhury * }
1318*bb154e3eSDorjoy Chowdhury *
1319*bb154e3eSDorjoy Chowdhury * [2] payload is serialized CBOR blob of the structure:
1320*bb154e3eSDorjoy Chowdhury * {
1321*bb154e3eSDorjoy Chowdhury * Map(9) {
1322*bb154e3eSDorjoy Chowdhury * [0] { key = String("module_id"), value = String(module_id) },
1323*bb154e3eSDorjoy Chowdhury * [1] { key = String("digest"), value = String("SHA384") },
1324*bb154e3eSDorjoy Chowdhury * [2] {
1325*bb154e3eSDorjoy Chowdhury * key = String("timestamp"),
1326*bb154e3eSDorjoy Chowdhury * value = Uint64(unix epoch of when document was created)
1327*bb154e3eSDorjoy Chowdhury * },
1328*bb154e3eSDorjoy Chowdhury * [3] {
1329*bb154e3eSDorjoy Chowdhury * key = String("pcrs"),
1330*bb154e3eSDorjoy Chowdhury * value = Map(locked_pcr_cnt) {
1331*bb154e3eSDorjoy Chowdhury * key = Uint8(pcr_index),
1332*bb154e3eSDorjoy Chowdhury * value = ByteString(pcr_data)
1333*bb154e3eSDorjoy Chowdhury * },
1334*bb154e3eSDorjoy Chowdhury * },
1335*bb154e3eSDorjoy Chowdhury * [4] {
1336*bb154e3eSDorjoy Chowdhury * key = String("certificate"),
1337*bb154e3eSDorjoy Chowdhury * value = ByteString(Signing certificate)
1338*bb154e3eSDorjoy Chowdhury * },
1339*bb154e3eSDorjoy Chowdhury * [5] { key = String("cabundle"), value = Array(N) { ByteString()... } },
1340*bb154e3eSDorjoy Chowdhury * [6] { key = String("public_key"), value = ByteString() || null },
1341*bb154e3eSDorjoy Chowdhury * [7] { key = String("user_data"), value = ByteString() || null},
1342*bb154e3eSDorjoy Chowdhury * [8] { key = String("nonce"), value = ByteString() || null},
1343*bb154e3eSDorjoy Chowdhury * }
1344*bb154e3eSDorjoy Chowdhury * }
1345*bb154e3eSDorjoy Chowdhury */
handle_attestation(VirtIONSM * vnsm,struct iovec * request,struct iovec * response,Error ** errp)1346*bb154e3eSDorjoy Chowdhury static bool handle_attestation(VirtIONSM *vnsm, struct iovec *request,
1347*bb154e3eSDorjoy Chowdhury struct iovec *response, Error **errp)
1348*bb154e3eSDorjoy Chowdhury {
1349*bb154e3eSDorjoy Chowdhury cbor_item_t *root = NULL;
1350*bb154e3eSDorjoy Chowdhury cbor_item_t *cose = NULL;
1351*bb154e3eSDorjoy Chowdhury cbor_item_t *nested_map;
1352*bb154e3eSDorjoy Chowdhury size_t len;
1353*bb154e3eSDorjoy Chowdhury enum NSMResponseTypes type;
1354*bb154e3eSDorjoy Chowdhury bool r = false;
1355*bb154e3eSDorjoy Chowdhury size_t buf_len = 16384;
1356*bb154e3eSDorjoy Chowdhury g_autofree uint8_t *buf = g_malloc(buf_len);
1357*bb154e3eSDorjoy Chowdhury g_autofree NSMAttestationReq *nsm_req = g_malloc(sizeof(NSMAttestationReq));
1358*bb154e3eSDorjoy Chowdhury
1359*bb154e3eSDorjoy Chowdhury nsm_req->public_key.is_null = true;
1360*bb154e3eSDorjoy Chowdhury nsm_req->user_data.is_null = true;
1361*bb154e3eSDorjoy Chowdhury nsm_req->nonce.is_null = true;
1362*bb154e3eSDorjoy Chowdhury
1363*bb154e3eSDorjoy Chowdhury type = get_nsm_attestation_req(request->iov_base, request->iov_len,
1364*bb154e3eSDorjoy Chowdhury nsm_req);
1365*bb154e3eSDorjoy Chowdhury if (type != NSM_SUCCESS) {
1366*bb154e3eSDorjoy Chowdhury if (error_response(response, type, errp)) {
1367*bb154e3eSDorjoy Chowdhury r = true;
1368*bb154e3eSDorjoy Chowdhury }
1369*bb154e3eSDorjoy Chowdhury goto out;
1370*bb154e3eSDorjoy Chowdhury }
1371*bb154e3eSDorjoy Chowdhury
1372*bb154e3eSDorjoy Chowdhury cose = cbor_new_definite_array(4);
1373*bb154e3eSDorjoy Chowdhury if (!cose) {
1374*bb154e3eSDorjoy Chowdhury goto err;
1375*bb154e3eSDorjoy Chowdhury }
1376*bb154e3eSDorjoy Chowdhury if (!add_protected_header_to_cose(cose)) {
1377*bb154e3eSDorjoy Chowdhury goto err;
1378*bb154e3eSDorjoy Chowdhury }
1379*bb154e3eSDorjoy Chowdhury if (!add_unprotected_header_to_cose(cose)) {
1380*bb154e3eSDorjoy Chowdhury goto err;
1381*bb154e3eSDorjoy Chowdhury }
1382*bb154e3eSDorjoy Chowdhury if (!add_payload_to_cose(cose, vnsm, nsm_req)) {
1383*bb154e3eSDorjoy Chowdhury goto err;
1384*bb154e3eSDorjoy Chowdhury }
1385*bb154e3eSDorjoy Chowdhury if (!add_signature_to_cose(cose)) {
1386*bb154e3eSDorjoy Chowdhury goto err;
1387*bb154e3eSDorjoy Chowdhury }
1388*bb154e3eSDorjoy Chowdhury
1389*bb154e3eSDorjoy Chowdhury len = cbor_serialize(cose, buf, buf_len);
1390*bb154e3eSDorjoy Chowdhury if (len == 0) {
1391*bb154e3eSDorjoy Chowdhury goto err;
1392*bb154e3eSDorjoy Chowdhury }
1393*bb154e3eSDorjoy Chowdhury
1394*bb154e3eSDorjoy Chowdhury root = cbor_new_definite_map(1);
1395*bb154e3eSDorjoy Chowdhury if (!root) {
1396*bb154e3eSDorjoy Chowdhury goto err;
1397*bb154e3eSDorjoy Chowdhury }
1398*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_map_to_map(root, "Attestation", 1, &nested_map)) {
1399*bb154e3eSDorjoy Chowdhury goto err;
1400*bb154e3eSDorjoy Chowdhury }
1401*bb154e3eSDorjoy Chowdhury if (!qemu_cbor_add_bytestring_to_map(nested_map, "document", buf, len)) {
1402*bb154e3eSDorjoy Chowdhury goto err;
1403*bb154e3eSDorjoy Chowdhury }
1404*bb154e3eSDorjoy Chowdhury
1405*bb154e3eSDorjoy Chowdhury len = cbor_serialize(root, response->iov_base, response->iov_len);
1406*bb154e3eSDorjoy Chowdhury if (len == 0) {
1407*bb154e3eSDorjoy Chowdhury if (error_response(response, NSM_INPUT_TOO_LARGE, errp)) {
1408*bb154e3eSDorjoy Chowdhury r = true;
1409*bb154e3eSDorjoy Chowdhury }
1410*bb154e3eSDorjoy Chowdhury goto out;
1411*bb154e3eSDorjoy Chowdhury }
1412*bb154e3eSDorjoy Chowdhury
1413*bb154e3eSDorjoy Chowdhury response->iov_len = len;
1414*bb154e3eSDorjoy Chowdhury r = true;
1415*bb154e3eSDorjoy Chowdhury
1416*bb154e3eSDorjoy Chowdhury out:
1417*bb154e3eSDorjoy Chowdhury if (root) {
1418*bb154e3eSDorjoy Chowdhury cbor_decref(&root);
1419*bb154e3eSDorjoy Chowdhury }
1420*bb154e3eSDorjoy Chowdhury if (cose) {
1421*bb154e3eSDorjoy Chowdhury cbor_decref(&cose);
1422*bb154e3eSDorjoy Chowdhury }
1423*bb154e3eSDorjoy Chowdhury return r;
1424*bb154e3eSDorjoy Chowdhury
1425*bb154e3eSDorjoy Chowdhury err:
1426*bb154e3eSDorjoy Chowdhury error_setg(errp, "Failed to initialize Attestation response");
1427*bb154e3eSDorjoy Chowdhury goto out;
1428*bb154e3eSDorjoy Chowdhury }
1429*bb154e3eSDorjoy Chowdhury
1430*bb154e3eSDorjoy Chowdhury enum CBOR_ROOT_TYPE {
1431*bb154e3eSDorjoy Chowdhury CBOR_ROOT_TYPE_STRING = 0,
1432*bb154e3eSDorjoy Chowdhury CBOR_ROOT_TYPE_MAP = 1,
1433*bb154e3eSDorjoy Chowdhury };
1434*bb154e3eSDorjoy Chowdhury
1435*bb154e3eSDorjoy Chowdhury struct nsm_cmd {
1436*bb154e3eSDorjoy Chowdhury char name[16];
1437*bb154e3eSDorjoy Chowdhury /*
1438*bb154e3eSDorjoy Chowdhury * There are 2 types of request
1439*bb154e3eSDorjoy Chowdhury * 1) String(); "GetRandom", "DescribeNSM"
1440*bb154e3eSDorjoy Chowdhury * 2) Map(1) { key: String(), value: ... }
1441*bb154e3eSDorjoy Chowdhury */
1442*bb154e3eSDorjoy Chowdhury enum CBOR_ROOT_TYPE root_type;
1443*bb154e3eSDorjoy Chowdhury bool (*response_fn)(VirtIONSM *vnsm, struct iovec *request,
1444*bb154e3eSDorjoy Chowdhury struct iovec *response, Error **errp);
1445*bb154e3eSDorjoy Chowdhury };
1446*bb154e3eSDorjoy Chowdhury
1447*bb154e3eSDorjoy Chowdhury const struct nsm_cmd nsm_cmds[] = {
1448*bb154e3eSDorjoy Chowdhury { "GetRandom", CBOR_ROOT_TYPE_STRING, handle_get_random },
1449*bb154e3eSDorjoy Chowdhury { "DescribeNSM", CBOR_ROOT_TYPE_STRING, handle_describe_nsm },
1450*bb154e3eSDorjoy Chowdhury { "DescribePCR", CBOR_ROOT_TYPE_MAP, handle_describe_pcr },
1451*bb154e3eSDorjoy Chowdhury { "ExtendPCR", CBOR_ROOT_TYPE_MAP, handle_extend_pcr },
1452*bb154e3eSDorjoy Chowdhury { "LockPCR", CBOR_ROOT_TYPE_MAP, handle_lock_pcr },
1453*bb154e3eSDorjoy Chowdhury { "LockPCRs", CBOR_ROOT_TYPE_MAP, handle_lock_pcrs },
1454*bb154e3eSDorjoy Chowdhury { "Attestation", CBOR_ROOT_TYPE_MAP, handle_attestation },
1455*bb154e3eSDorjoy Chowdhury };
1456*bb154e3eSDorjoy Chowdhury
get_nsm_request_cmd(uint8_t * buf,size_t len)1457*bb154e3eSDorjoy Chowdhury static const struct nsm_cmd *get_nsm_request_cmd(uint8_t *buf, size_t len)
1458*bb154e3eSDorjoy Chowdhury {
1459*bb154e3eSDorjoy Chowdhury size_t size;
1460*bb154e3eSDorjoy Chowdhury uint8_t *req;
1461*bb154e3eSDorjoy Chowdhury enum CBOR_ROOT_TYPE root_type;
1462*bb154e3eSDorjoy Chowdhury struct cbor_load_result result;
1463*bb154e3eSDorjoy Chowdhury cbor_item_t *item = cbor_load(buf, len, &result);
1464*bb154e3eSDorjoy Chowdhury if (!item || result.error.code != CBOR_ERR_NONE) {
1465*bb154e3eSDorjoy Chowdhury goto cleanup;
1466*bb154e3eSDorjoy Chowdhury }
1467*bb154e3eSDorjoy Chowdhury
1468*bb154e3eSDorjoy Chowdhury if (cbor_isa_string(item)) {
1469*bb154e3eSDorjoy Chowdhury size = cbor_string_length(item);
1470*bb154e3eSDorjoy Chowdhury req = cbor_string_handle(item);
1471*bb154e3eSDorjoy Chowdhury root_type = CBOR_ROOT_TYPE_STRING;
1472*bb154e3eSDorjoy Chowdhury } else if (cbor_isa_map(item) && cbor_map_size(item) == 1) {
1473*bb154e3eSDorjoy Chowdhury struct cbor_pair *handle = cbor_map_handle(item);
1474*bb154e3eSDorjoy Chowdhury if (cbor_isa_string(handle->key)) {
1475*bb154e3eSDorjoy Chowdhury size = cbor_string_length(handle->key);
1476*bb154e3eSDorjoy Chowdhury req = cbor_string_handle(handle->key);
1477*bb154e3eSDorjoy Chowdhury root_type = CBOR_ROOT_TYPE_MAP;
1478*bb154e3eSDorjoy Chowdhury } else {
1479*bb154e3eSDorjoy Chowdhury goto cleanup;
1480*bb154e3eSDorjoy Chowdhury }
1481*bb154e3eSDorjoy Chowdhury } else {
1482*bb154e3eSDorjoy Chowdhury goto cleanup;
1483*bb154e3eSDorjoy Chowdhury }
1484*bb154e3eSDorjoy Chowdhury
1485*bb154e3eSDorjoy Chowdhury if (size == 0 || req == NULL) {
1486*bb154e3eSDorjoy Chowdhury goto cleanup;
1487*bb154e3eSDorjoy Chowdhury }
1488*bb154e3eSDorjoy Chowdhury
1489*bb154e3eSDorjoy Chowdhury for (int i = 0; i < ARRAY_SIZE(nsm_cmds); ++i) {
1490*bb154e3eSDorjoy Chowdhury if (nsm_cmds[i].root_type == root_type &&
1491*bb154e3eSDorjoy Chowdhury strlen(nsm_cmds[i].name) == size &&
1492*bb154e3eSDorjoy Chowdhury memcmp(nsm_cmds[i].name, req, size) == 0) {
1493*bb154e3eSDorjoy Chowdhury cbor_decref(&item);
1494*bb154e3eSDorjoy Chowdhury return &nsm_cmds[i];
1495*bb154e3eSDorjoy Chowdhury }
1496*bb154e3eSDorjoy Chowdhury }
1497*bb154e3eSDorjoy Chowdhury
1498*bb154e3eSDorjoy Chowdhury cleanup:
1499*bb154e3eSDorjoy Chowdhury if (item) {
1500*bb154e3eSDorjoy Chowdhury cbor_decref(&item);
1501*bb154e3eSDorjoy Chowdhury }
1502*bb154e3eSDorjoy Chowdhury return NULL;
1503*bb154e3eSDorjoy Chowdhury }
1504*bb154e3eSDorjoy Chowdhury
get_nsm_request_response(VirtIONSM * vnsm,struct iovec * req,struct iovec * resp,Error ** errp)1505*bb154e3eSDorjoy Chowdhury static bool get_nsm_request_response(VirtIONSM *vnsm, struct iovec *req,
1506*bb154e3eSDorjoy Chowdhury struct iovec *resp, Error **errp)
1507*bb154e3eSDorjoy Chowdhury {
1508*bb154e3eSDorjoy Chowdhury const struct nsm_cmd *cmd;
1509*bb154e3eSDorjoy Chowdhury
1510*bb154e3eSDorjoy Chowdhury if (req->iov_len > NSM_REQUEST_MAX_SIZE) {
1511*bb154e3eSDorjoy Chowdhury if (error_response(resp, NSM_INPUT_TOO_LARGE, errp)) {
1512*bb154e3eSDorjoy Chowdhury return true;
1513*bb154e3eSDorjoy Chowdhury }
1514*bb154e3eSDorjoy Chowdhury error_setg(errp, "Failed to initialize InputTooLarge response");
1515*bb154e3eSDorjoy Chowdhury return false;
1516*bb154e3eSDorjoy Chowdhury }
1517*bb154e3eSDorjoy Chowdhury
1518*bb154e3eSDorjoy Chowdhury cmd = get_nsm_request_cmd(req->iov_base, req->iov_len);
1519*bb154e3eSDorjoy Chowdhury
1520*bb154e3eSDorjoy Chowdhury if (cmd == NULL) {
1521*bb154e3eSDorjoy Chowdhury if (error_response(resp, NSM_INVALID_OPERATION, errp)) {
1522*bb154e3eSDorjoy Chowdhury return true;
1523*bb154e3eSDorjoy Chowdhury }
1524*bb154e3eSDorjoy Chowdhury error_setg(errp, "Failed to initialize InvalidOperation response");
1525*bb154e3eSDorjoy Chowdhury return false;
1526*bb154e3eSDorjoy Chowdhury }
1527*bb154e3eSDorjoy Chowdhury
1528*bb154e3eSDorjoy Chowdhury return cmd->response_fn(vnsm, req, resp, errp);
1529*bb154e3eSDorjoy Chowdhury }
1530*bb154e3eSDorjoy Chowdhury
handle_input(VirtIODevice * vdev,VirtQueue * vq)1531*bb154e3eSDorjoy Chowdhury static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
1532*bb154e3eSDorjoy Chowdhury {
1533*bb154e3eSDorjoy Chowdhury g_autofree VirtQueueElement *out_elem = NULL;
1534*bb154e3eSDorjoy Chowdhury g_autofree VirtQueueElement *in_elem = NULL;
1535*bb154e3eSDorjoy Chowdhury VirtIONSM *vnsm = VIRTIO_NSM(vdev);
1536*bb154e3eSDorjoy Chowdhury Error *err = NULL;
1537*bb154e3eSDorjoy Chowdhury size_t sz;
1538*bb154e3eSDorjoy Chowdhury struct iovec req = {.iov_base = NULL, .iov_len = 0};
1539*bb154e3eSDorjoy Chowdhury struct iovec res = {.iov_base = NULL, .iov_len = 0};
1540*bb154e3eSDorjoy Chowdhury
1541*bb154e3eSDorjoy Chowdhury out_elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
1542*bb154e3eSDorjoy Chowdhury if (!out_elem) {
1543*bb154e3eSDorjoy Chowdhury /* nothing in virtqueue */
1544*bb154e3eSDorjoy Chowdhury return;
1545*bb154e3eSDorjoy Chowdhury }
1546*bb154e3eSDorjoy Chowdhury
1547*bb154e3eSDorjoy Chowdhury sz = iov_size(out_elem->out_sg, out_elem->out_num);
1548*bb154e3eSDorjoy Chowdhury if (sz == 0) {
1549*bb154e3eSDorjoy Chowdhury virtio_error(vdev, "Expected non-zero sized request buffer in "
1550*bb154e3eSDorjoy Chowdhury "virtqueue");
1551*bb154e3eSDorjoy Chowdhury goto cleanup;
1552*bb154e3eSDorjoy Chowdhury }
1553*bb154e3eSDorjoy Chowdhury
1554*bb154e3eSDorjoy Chowdhury in_elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
1555*bb154e3eSDorjoy Chowdhury if (!in_elem) {
1556*bb154e3eSDorjoy Chowdhury virtio_error(vdev, "Expected response buffer after request buffer "
1557*bb154e3eSDorjoy Chowdhury "in virtqueue");
1558*bb154e3eSDorjoy Chowdhury goto cleanup;
1559*bb154e3eSDorjoy Chowdhury }
1560*bb154e3eSDorjoy Chowdhury if (iov_size(in_elem->in_sg, in_elem->in_num) != NSM_RESPONSE_BUF_SIZE) {
1561*bb154e3eSDorjoy Chowdhury virtio_error(vdev, "Expected response buffer of length 0x3000");
1562*bb154e3eSDorjoy Chowdhury goto cleanup;
1563*bb154e3eSDorjoy Chowdhury }
1564*bb154e3eSDorjoy Chowdhury
1565*bb154e3eSDorjoy Chowdhury req.iov_base = g_malloc(sz);
1566*bb154e3eSDorjoy Chowdhury req.iov_len = iov_to_buf(out_elem->out_sg, out_elem->out_num, 0,
1567*bb154e3eSDorjoy Chowdhury req.iov_base, sz);
1568*bb154e3eSDorjoy Chowdhury if (req.iov_len != sz) {
1569*bb154e3eSDorjoy Chowdhury virtio_error(vdev, "Failed to copy request buffer");
1570*bb154e3eSDorjoy Chowdhury goto cleanup;
1571*bb154e3eSDorjoy Chowdhury }
1572*bb154e3eSDorjoy Chowdhury
1573*bb154e3eSDorjoy Chowdhury res.iov_base = g_malloc(NSM_RESPONSE_BUF_SIZE);
1574*bb154e3eSDorjoy Chowdhury res.iov_len = NSM_RESPONSE_BUF_SIZE;
1575*bb154e3eSDorjoy Chowdhury
1576*bb154e3eSDorjoy Chowdhury if (!get_nsm_request_response(vnsm, &req, &res, &err)) {
1577*bb154e3eSDorjoy Chowdhury error_report_err(err);
1578*bb154e3eSDorjoy Chowdhury virtio_error(vdev, "Failed to get NSM request response");
1579*bb154e3eSDorjoy Chowdhury goto cleanup;
1580*bb154e3eSDorjoy Chowdhury }
1581*bb154e3eSDorjoy Chowdhury
1582*bb154e3eSDorjoy Chowdhury sz = iov_from_buf(in_elem->in_sg, in_elem->in_num, 0, res.iov_base,
1583*bb154e3eSDorjoy Chowdhury res.iov_len);
1584*bb154e3eSDorjoy Chowdhury if (sz != res.iov_len) {
1585*bb154e3eSDorjoy Chowdhury virtio_error(vdev, "Failed to copy response buffer");
1586*bb154e3eSDorjoy Chowdhury goto cleanup;
1587*bb154e3eSDorjoy Chowdhury }
1588*bb154e3eSDorjoy Chowdhury
1589*bb154e3eSDorjoy Chowdhury g_free(req.iov_base);
1590*bb154e3eSDorjoy Chowdhury g_free(res.iov_base);
1591*bb154e3eSDorjoy Chowdhury virtqueue_push(vq, out_elem, 0);
1592*bb154e3eSDorjoy Chowdhury virtqueue_push(vq, in_elem, in_elem->in_sg->iov_len);
1593*bb154e3eSDorjoy Chowdhury virtio_notify(vdev, vq);
1594*bb154e3eSDorjoy Chowdhury return;
1595*bb154e3eSDorjoy Chowdhury
1596*bb154e3eSDorjoy Chowdhury cleanup:
1597*bb154e3eSDorjoy Chowdhury g_free(req.iov_base);
1598*bb154e3eSDorjoy Chowdhury g_free(res.iov_base);
1599*bb154e3eSDorjoy Chowdhury if (out_elem) {
1600*bb154e3eSDorjoy Chowdhury virtqueue_detach_element(vq, out_elem, 0);
1601*bb154e3eSDorjoy Chowdhury }
1602*bb154e3eSDorjoy Chowdhury if (in_elem) {
1603*bb154e3eSDorjoy Chowdhury virtqueue_detach_element(vq, in_elem, 0);
1604*bb154e3eSDorjoy Chowdhury }
1605*bb154e3eSDorjoy Chowdhury return;
1606*bb154e3eSDorjoy Chowdhury }
1607*bb154e3eSDorjoy Chowdhury
get_features(VirtIODevice * vdev,uint64_t f,Error ** errp)1608*bb154e3eSDorjoy Chowdhury static uint64_t get_features(VirtIODevice *vdev, uint64_t f, Error **errp)
1609*bb154e3eSDorjoy Chowdhury {
1610*bb154e3eSDorjoy Chowdhury return f;
1611*bb154e3eSDorjoy Chowdhury }
1612*bb154e3eSDorjoy Chowdhury
extend_pcr(VirtIONSM * vnsm,int ind,uint8_t * data,uint16_t len)1613*bb154e3eSDorjoy Chowdhury static bool extend_pcr(VirtIONSM *vnsm, int ind, uint8_t *data, uint16_t len)
1614*bb154e3eSDorjoy Chowdhury {
1615*bb154e3eSDorjoy Chowdhury Error *err = NULL;
1616*bb154e3eSDorjoy Chowdhury struct PCRInfo *pcr = &(vnsm->pcrs[ind]);
1617*bb154e3eSDorjoy Chowdhury size_t digest_len = QCRYPTO_HASH_DIGEST_LEN_SHA384;
1618*bb154e3eSDorjoy Chowdhury uint8_t result[QCRYPTO_HASH_DIGEST_LEN_SHA384];
1619*bb154e3eSDorjoy Chowdhury uint8_t *ptr = result;
1620*bb154e3eSDorjoy Chowdhury struct iovec iov[2] = {
1621*bb154e3eSDorjoy Chowdhury { .iov_base = pcr->data, .iov_len = QCRYPTO_HASH_DIGEST_LEN_SHA384 },
1622*bb154e3eSDorjoy Chowdhury { .iov_base = data, .iov_len = len },
1623*bb154e3eSDorjoy Chowdhury };
1624*bb154e3eSDorjoy Chowdhury
1625*bb154e3eSDorjoy Chowdhury if (qcrypto_hash_bytesv(QCRYPTO_HASH_ALGO_SHA384, iov, 2, &ptr, &digest_len,
1626*bb154e3eSDorjoy Chowdhury &err) < 0) {
1627*bb154e3eSDorjoy Chowdhury return false;
1628*bb154e3eSDorjoy Chowdhury }
1629*bb154e3eSDorjoy Chowdhury
1630*bb154e3eSDorjoy Chowdhury memcpy(pcr->data, result, QCRYPTO_HASH_DIGEST_LEN_SHA384);
1631*bb154e3eSDorjoy Chowdhury return true;
1632*bb154e3eSDorjoy Chowdhury }
1633*bb154e3eSDorjoy Chowdhury
lock_pcr(VirtIONSM * vnsm,int ind)1634*bb154e3eSDorjoy Chowdhury static void lock_pcr(VirtIONSM *vnsm, int ind)
1635*bb154e3eSDorjoy Chowdhury {
1636*bb154e3eSDorjoy Chowdhury vnsm->pcrs[ind].locked = true;
1637*bb154e3eSDorjoy Chowdhury }
1638*bb154e3eSDorjoy Chowdhury
virtio_nsm_device_realize(DeviceState * dev,Error ** errp)1639*bb154e3eSDorjoy Chowdhury static void virtio_nsm_device_realize(DeviceState *dev, Error **errp)
1640*bb154e3eSDorjoy Chowdhury {
1641*bb154e3eSDorjoy Chowdhury VirtIODevice *vdev = VIRTIO_DEVICE(dev);
1642*bb154e3eSDorjoy Chowdhury VirtIONSM *vnsm = VIRTIO_NSM(dev);
1643*bb154e3eSDorjoy Chowdhury
1644*bb154e3eSDorjoy Chowdhury vnsm->max_pcrs = NSM_MAX_PCRS;
1645*bb154e3eSDorjoy Chowdhury vnsm->digest = (char *) "SHA384";
1646*bb154e3eSDorjoy Chowdhury if (vnsm->module_id == NULL) {
1647*bb154e3eSDorjoy Chowdhury vnsm->module_id = (char *) "i-234-enc5678";
1648*bb154e3eSDorjoy Chowdhury }
1649*bb154e3eSDorjoy Chowdhury vnsm->version_major = 1;
1650*bb154e3eSDorjoy Chowdhury vnsm->version_minor = 0;
1651*bb154e3eSDorjoy Chowdhury vnsm->version_patch = 0;
1652*bb154e3eSDorjoy Chowdhury vnsm->extend_pcr = extend_pcr;
1653*bb154e3eSDorjoy Chowdhury vnsm->lock_pcr = lock_pcr;
1654*bb154e3eSDorjoy Chowdhury
1655*bb154e3eSDorjoy Chowdhury virtio_init(vdev, VIRTIO_ID_NITRO_SEC_MOD, 0);
1656*bb154e3eSDorjoy Chowdhury
1657*bb154e3eSDorjoy Chowdhury vnsm->vq = virtio_add_queue(vdev, 2, handle_input);
1658*bb154e3eSDorjoy Chowdhury }
1659*bb154e3eSDorjoy Chowdhury
virtio_nsm_device_unrealize(DeviceState * dev)1660*bb154e3eSDorjoy Chowdhury static void virtio_nsm_device_unrealize(DeviceState *dev)
1661*bb154e3eSDorjoy Chowdhury {
1662*bb154e3eSDorjoy Chowdhury VirtIODevice *vdev = VIRTIO_DEVICE(dev);
1663*bb154e3eSDorjoy Chowdhury
1664*bb154e3eSDorjoy Chowdhury virtio_del_queue(vdev, 0);
1665*bb154e3eSDorjoy Chowdhury virtio_cleanup(vdev);
1666*bb154e3eSDorjoy Chowdhury }
1667*bb154e3eSDorjoy Chowdhury
1668*bb154e3eSDorjoy Chowdhury static const VMStateDescription vmstate_pcr_info_entry = {
1669*bb154e3eSDorjoy Chowdhury .name = "pcr_info_entry",
1670*bb154e3eSDorjoy Chowdhury .minimum_version_id = 1,
1671*bb154e3eSDorjoy Chowdhury .version_id = 1,
1672*bb154e3eSDorjoy Chowdhury .fields = (const VMStateField[]) {
1673*bb154e3eSDorjoy Chowdhury VMSTATE_BOOL(locked, struct PCRInfo),
1674*bb154e3eSDorjoy Chowdhury VMSTATE_UINT8_ARRAY(data, struct PCRInfo,
1675*bb154e3eSDorjoy Chowdhury QCRYPTO_HASH_DIGEST_LEN_SHA384),
1676*bb154e3eSDorjoy Chowdhury VMSTATE_END_OF_LIST()
1677*bb154e3eSDorjoy Chowdhury },
1678*bb154e3eSDorjoy Chowdhury };
1679*bb154e3eSDorjoy Chowdhury
1680*bb154e3eSDorjoy Chowdhury static const VMStateDescription vmstate_virtio_nsm_device = {
1681*bb154e3eSDorjoy Chowdhury .name = "virtio-nsm-device",
1682*bb154e3eSDorjoy Chowdhury .minimum_version_id = 1,
1683*bb154e3eSDorjoy Chowdhury .version_id = 1,
1684*bb154e3eSDorjoy Chowdhury .fields = (const VMStateField[]) {
1685*bb154e3eSDorjoy Chowdhury VMSTATE_STRUCT_ARRAY(pcrs, VirtIONSM, NSM_MAX_PCRS, 1,
1686*bb154e3eSDorjoy Chowdhury vmstate_pcr_info_entry, struct PCRInfo),
1687*bb154e3eSDorjoy Chowdhury VMSTATE_END_OF_LIST()
1688*bb154e3eSDorjoy Chowdhury },
1689*bb154e3eSDorjoy Chowdhury };
1690*bb154e3eSDorjoy Chowdhury
1691*bb154e3eSDorjoy Chowdhury static const VMStateDescription vmstate_virtio_nsm = {
1692*bb154e3eSDorjoy Chowdhury .name = "virtio-nsm",
1693*bb154e3eSDorjoy Chowdhury .minimum_version_id = 1,
1694*bb154e3eSDorjoy Chowdhury .version_id = 1,
1695*bb154e3eSDorjoy Chowdhury .fields = (const VMStateField[]) {
1696*bb154e3eSDorjoy Chowdhury VMSTATE_VIRTIO_DEVICE,
1697*bb154e3eSDorjoy Chowdhury VMSTATE_END_OF_LIST()
1698*bb154e3eSDorjoy Chowdhury },
1699*bb154e3eSDorjoy Chowdhury };
1700*bb154e3eSDorjoy Chowdhury
1701*bb154e3eSDorjoy Chowdhury static Property virtio_nsm_properties[] = {
1702*bb154e3eSDorjoy Chowdhury DEFINE_PROP_STRING("module-id", VirtIONSM, module_id),
1703*bb154e3eSDorjoy Chowdhury DEFINE_PROP_END_OF_LIST(),
1704*bb154e3eSDorjoy Chowdhury };
1705*bb154e3eSDorjoy Chowdhury
virtio_nsm_class_init(ObjectClass * klass,void * data)1706*bb154e3eSDorjoy Chowdhury static void virtio_nsm_class_init(ObjectClass *klass, void *data)
1707*bb154e3eSDorjoy Chowdhury {
1708*bb154e3eSDorjoy Chowdhury DeviceClass *dc = DEVICE_CLASS(klass);
1709*bb154e3eSDorjoy Chowdhury VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
1710*bb154e3eSDorjoy Chowdhury
1711*bb154e3eSDorjoy Chowdhury device_class_set_props(dc, virtio_nsm_properties);
1712*bb154e3eSDorjoy Chowdhury dc->vmsd = &vmstate_virtio_nsm;
1713*bb154e3eSDorjoy Chowdhury set_bit(DEVICE_CATEGORY_MISC, dc->categories);
1714*bb154e3eSDorjoy Chowdhury vdc->realize = virtio_nsm_device_realize;
1715*bb154e3eSDorjoy Chowdhury vdc->unrealize = virtio_nsm_device_unrealize;
1716*bb154e3eSDorjoy Chowdhury vdc->get_features = get_features;
1717*bb154e3eSDorjoy Chowdhury vdc->vmsd = &vmstate_virtio_nsm_device;
1718*bb154e3eSDorjoy Chowdhury }
1719*bb154e3eSDorjoy Chowdhury
1720*bb154e3eSDorjoy Chowdhury static const TypeInfo virtio_nsm_info = {
1721*bb154e3eSDorjoy Chowdhury .name = TYPE_VIRTIO_NSM,
1722*bb154e3eSDorjoy Chowdhury .parent = TYPE_VIRTIO_DEVICE,
1723*bb154e3eSDorjoy Chowdhury .instance_size = sizeof(VirtIONSM),
1724*bb154e3eSDorjoy Chowdhury .class_init = virtio_nsm_class_init,
1725*bb154e3eSDorjoy Chowdhury };
1726*bb154e3eSDorjoy Chowdhury
virtio_register_types(void)1727*bb154e3eSDorjoy Chowdhury static void virtio_register_types(void)
1728*bb154e3eSDorjoy Chowdhury {
1729*bb154e3eSDorjoy Chowdhury type_register_static(&virtio_nsm_info);
1730*bb154e3eSDorjoy Chowdhury }
1731*bb154e3eSDorjoy Chowdhury
1732*bb154e3eSDorjoy Chowdhury type_init(virtio_register_types)
1733