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