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 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 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 */ 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 */ 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 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 */ 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 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 */ 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 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 */ 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 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 */ 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 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 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 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 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 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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