1*8348b72dSSteffen Eiden /* SPDX-License-Identifier: GPL-2.0-only */ 2*8348b72dSSteffen Eiden /* 3*8348b72dSSteffen Eiden * Retrieve Attestation Measurement Utravisor Call tests 4*8348b72dSSteffen Eiden * 5*8348b72dSSteffen Eiden * Copyright IBM Corp. 2022 6*8348b72dSSteffen Eiden * 7*8348b72dSSteffen Eiden * Authors: 8*8348b72dSSteffen Eiden * Steffen Eiden <seiden@linux.ibm.com> 9*8348b72dSSteffen Eiden */ 10*8348b72dSSteffen Eiden 11*8348b72dSSteffen Eiden #include <libcflat.h> 12*8348b72dSSteffen Eiden #include <alloc_page.h> 13*8348b72dSSteffen Eiden #include <asm/page.h> 14*8348b72dSSteffen Eiden #include <asm/facility.h> 15*8348b72dSSteffen Eiden #include <asm/uv.h> 16*8348b72dSSteffen Eiden #include <sclp.h> 17*8348b72dSSteffen Eiden #include <uv.h> 18*8348b72dSSteffen Eiden 19*8348b72dSSteffen Eiden #define ARCB_VERSION_NONE 0 20*8348b72dSSteffen Eiden #define ARCB_VERSION_1 0x100 21*8348b72dSSteffen Eiden #define ARCB_MEAS_NONE 0 22*8348b72dSSteffen Eiden #define ARCB_MEAS_HMAC_SHA512 1 23*8348b72dSSteffen Eiden #define MEASUREMENT_SIZE_HMAC_SHA512 64 24*8348b72dSSteffen Eiden #define PAF_PHKH_ATT (1ULL << 61) 25*8348b72dSSteffen Eiden #define ADDITIONAL_SIZE_PAF_PHKH_ATT 32 26*8348b72dSSteffen Eiden /* arcb with one key slot and no nonce */ 27*8348b72dSSteffen Eiden struct uv_arcb_v1 { 28*8348b72dSSteffen Eiden uint64_t reserved0; /* 0x0000 */ 29*8348b72dSSteffen Eiden uint32_t req_ver; /* 0x0008 */ 30*8348b72dSSteffen Eiden uint32_t req_len; /* 0x000c */ 31*8348b72dSSteffen Eiden uint8_t iv[12]; /* 0x0010 */ 32*8348b72dSSteffen Eiden uint32_t reserved1c; /* 0x001c */ 33*8348b72dSSteffen Eiden uint8_t reserved20[7]; /* 0x0020 */ 34*8348b72dSSteffen Eiden uint8_t nks; /* 0x0027 */ 35*8348b72dSSteffen Eiden int32_t reserved28; /* 0x0028 */ 36*8348b72dSSteffen Eiden uint32_t sea; /* 0x002c */ 37*8348b72dSSteffen Eiden uint64_t plaint_att_flags; /* 0x0030 */ 38*8348b72dSSteffen Eiden uint32_t meas_alg_id; /* 0x0038 */ 39*8348b72dSSteffen Eiden uint32_t reserved3c; /* 0x003c */ 40*8348b72dSSteffen Eiden uint8_t cpk[160]; /* 0x0040 */ 41*8348b72dSSteffen Eiden uint8_t key_slot[80]; /* 0x00e0 */ 42*8348b72dSSteffen Eiden uint8_t meas_key[64]; /* 0x0130 */ 43*8348b72dSSteffen Eiden uint8_t tag[16]; /* 0x0170 */ 44*8348b72dSSteffen Eiden } __attribute__((packed)); 45*8348b72dSSteffen Eiden 46*8348b72dSSteffen Eiden struct attest_request_v1 { 47*8348b72dSSteffen Eiden struct uv_arcb_v1 arcb; 48*8348b72dSSteffen Eiden uint8_t measurement[MEASUREMENT_SIZE_HMAC_SHA512]; 49*8348b72dSSteffen Eiden uint8_t additional[ADDITIONAL_SIZE_PAF_PHKH_ATT]; 50*8348b72dSSteffen Eiden }; 51*8348b72dSSteffen Eiden 52*8348b72dSSteffen Eiden static void test_attest_v1(uint64_t page) 53*8348b72dSSteffen Eiden { 54*8348b72dSSteffen Eiden struct uv_cb_attest uvcb = { 55*8348b72dSSteffen Eiden .header.cmd = UVC_CMD_ATTESTATION, 56*8348b72dSSteffen Eiden .header.len = sizeof(uvcb), 57*8348b72dSSteffen Eiden }; 58*8348b72dSSteffen Eiden const struct uv_cb_qui *uvcb_qui = uv_get_query_data(); 59*8348b72dSSteffen Eiden struct attest_request_v1 *attest_req = (void *)page; 60*8348b72dSSteffen Eiden struct uv_arcb_v1 *arcb = &attest_req->arcb; 61*8348b72dSSteffen Eiden int cc; 62*8348b72dSSteffen Eiden 63*8348b72dSSteffen Eiden report_prefix_push("v1"); 64*8348b72dSSteffen Eiden if (!test_bit_inv(0, &uvcb_qui->supp_att_hdr_ver)) { 65*8348b72dSSteffen Eiden report_skip("Attestation version 1 not supported"); 66*8348b72dSSteffen Eiden goto done; 67*8348b72dSSteffen Eiden } 68*8348b72dSSteffen Eiden 69*8348b72dSSteffen Eiden memset((void *)page, 0, PAGE_SIZE); 70*8348b72dSSteffen Eiden 71*8348b72dSSteffen Eiden /* 72*8348b72dSSteffen Eiden * Create a minimal arcb/uvcb such that FW has everything to start 73*8348b72dSSteffen Eiden * unsealing the request. However, this unsealing will fail as the 74*8348b72dSSteffen Eiden * kvm-unit-test framework provides no cryptography functions that 75*8348b72dSSteffen Eiden * would be needed to seal such requests. 76*8348b72dSSteffen Eiden */ 77*8348b72dSSteffen Eiden arcb->req_ver = ARCB_VERSION_1; 78*8348b72dSSteffen Eiden arcb->req_len = sizeof(*arcb); 79*8348b72dSSteffen Eiden arcb->nks = 1; 80*8348b72dSSteffen Eiden arcb->sea = sizeof(arcb->meas_key); 81*8348b72dSSteffen Eiden arcb->plaint_att_flags = PAF_PHKH_ATT; 82*8348b72dSSteffen Eiden arcb->meas_alg_id = ARCB_MEAS_HMAC_SHA512; 83*8348b72dSSteffen Eiden uvcb.arcb_addr = (uint64_t)&attest_req->arcb; 84*8348b72dSSteffen Eiden uvcb.measurement_address = (uint64_t)attest_req->measurement; 85*8348b72dSSteffen Eiden uvcb.measurement_length = sizeof(attest_req->measurement); 86*8348b72dSSteffen Eiden uvcb.add_data_address = (uint64_t)attest_req->additional; 87*8348b72dSSteffen Eiden uvcb.add_data_length = sizeof(attest_req->additional); 88*8348b72dSSteffen Eiden 89*8348b72dSSteffen Eiden uvcb.continuation_token = 0xff; 90*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 91*8348b72dSSteffen Eiden report(cc == 1 && uvcb.header.rc == 0x101, "invalid continuation token"); 92*8348b72dSSteffen Eiden uvcb.continuation_token = 0; 93*8348b72dSSteffen Eiden 94*8348b72dSSteffen Eiden uvcb.user_data_length = sizeof(uvcb.user_data) + 1; 95*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 96*8348b72dSSteffen Eiden report(cc == 1 && uvcb.header.rc == 0x102, "invalid user data size"); 97*8348b72dSSteffen Eiden uvcb.user_data_length = 0; 98*8348b72dSSteffen Eiden 99*8348b72dSSteffen Eiden uvcb.arcb_addr = get_ram_size() + PAGE_SIZE; 100*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 101*8348b72dSSteffen Eiden report(cc == 1 && uvcb.header.rc == 0x103, "invalid address arcb"); 102*8348b72dSSteffen Eiden uvcb.arcb_addr = page; 103*8348b72dSSteffen Eiden 104*8348b72dSSteffen Eiden /* 0x104 - 0x105 need an unseal-able request */ 105*8348b72dSSteffen Eiden 106*8348b72dSSteffen Eiden arcb->req_ver = ARCB_VERSION_NONE; 107*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 108*8348b72dSSteffen Eiden report(cc == 1 && uvcb.header.rc == 0x106, "unsupported version"); 109*8348b72dSSteffen Eiden arcb->req_ver = ARCB_VERSION_1; 110*8348b72dSSteffen Eiden 111*8348b72dSSteffen Eiden arcb->req_len += 1; 112*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 113*8348b72dSSteffen Eiden report(cc == 1 && uvcb.header.rc == 0x107, "arcb too big"); 114*8348b72dSSteffen Eiden arcb->req_len -= 1; 115*8348b72dSSteffen Eiden 116*8348b72dSSteffen Eiden /* 117*8348b72dSSteffen Eiden * The arcb needs to grow as well if number of key slots (nks) 118*8348b72dSSteffen Eiden * is increased. However, this is not the case and there is no explicit 119*8348b72dSSteffen Eiden * 'too many/less nks for that arcb size' error code -> expect 0x107 120*8348b72dSSteffen Eiden */ 121*8348b72dSSteffen Eiden arcb->nks = 2; 122*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 123*8348b72dSSteffen Eiden report(cc == 1 && uvcb.header.rc == 0x107, "too many nks for arcb"); 124*8348b72dSSteffen Eiden arcb->nks = 1; 125*8348b72dSSteffen Eiden 126*8348b72dSSteffen Eiden arcb->nks = 0; 127*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 128*8348b72dSSteffen Eiden report(cc == 1 && uvcb.header.rc == 0x108, "invalid num key slots"); 129*8348b72dSSteffen Eiden arcb->nks = 1; 130*8348b72dSSteffen Eiden 131*8348b72dSSteffen Eiden /* 132*8348b72dSSteffen Eiden * Possible valid size (when using nonce). 133*8348b72dSSteffen Eiden * However, req_len too small to host a nonce 134*8348b72dSSteffen Eiden */ 135*8348b72dSSteffen Eiden arcb->sea = 80; 136*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 137*8348b72dSSteffen Eiden report(cc == 1 && uvcb.header.rc == 0x109, "encrypted size too big"); 138*8348b72dSSteffen Eiden arcb->sea = 17; 139*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 140*8348b72dSSteffen Eiden report(cc == 1 && uvcb.header.rc == 0x109, "encrypted size too small"); 141*8348b72dSSteffen Eiden arcb->sea = 64; 142*8348b72dSSteffen Eiden 143*8348b72dSSteffen Eiden arcb->plaint_att_flags = uvcb_qui->supp_paf ^ GENMASK_ULL(63, 0); 144*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 145*8348b72dSSteffen Eiden report(cc == 1 && uvcb.header.rc == 0x10a, "invalid flag"); 146*8348b72dSSteffen Eiden arcb->plaint_att_flags = PAF_PHKH_ATT; 147*8348b72dSSteffen Eiden 148*8348b72dSSteffen Eiden arcb->meas_alg_id = ARCB_MEAS_NONE; 149*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 150*8348b72dSSteffen Eiden report(cc == 1 && uvcb.header.rc == 0x10b, "invalid measurement algorithm"); 151*8348b72dSSteffen Eiden arcb->meas_alg_id = ARCB_MEAS_HMAC_SHA512; 152*8348b72dSSteffen Eiden 153*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 154*8348b72dSSteffen Eiden report(cc == 1 && uvcb.header.rc == 0x10c, "unable unseal"); 155*8348b72dSSteffen Eiden 156*8348b72dSSteffen Eiden uvcb.measurement_length = 0; 157*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 158*8348b72dSSteffen Eiden report(cc == 1 && uvcb.header.rc == 0x10d, "invalid measurement size"); 159*8348b72dSSteffen Eiden uvcb.measurement_length = sizeof(attest_req->measurement); 160*8348b72dSSteffen Eiden 161*8348b72dSSteffen Eiden uvcb.add_data_length = 0; 162*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 163*8348b72dSSteffen Eiden report(cc == 1 && uvcb.header.rc == 0x10e, "invalid additional size"); 164*8348b72dSSteffen Eiden uvcb.add_data_length = sizeof(attest_req->additional); 165*8348b72dSSteffen Eiden 166*8348b72dSSteffen Eiden done: 167*8348b72dSSteffen Eiden report_prefix_pop(); 168*8348b72dSSteffen Eiden } 169*8348b72dSSteffen Eiden 170*8348b72dSSteffen Eiden static void test_attest(uint64_t page) 171*8348b72dSSteffen Eiden { 172*8348b72dSSteffen Eiden struct uv_cb_attest uvcb = { 173*8348b72dSSteffen Eiden .header.cmd = UVC_CMD_ATTESTATION, 174*8348b72dSSteffen Eiden .header.len = sizeof(uvcb), 175*8348b72dSSteffen Eiden }; 176*8348b72dSSteffen Eiden const struct uv_cb_qui *uvcb_qui = uv_get_query_data(); 177*8348b72dSSteffen Eiden int cc; 178*8348b72dSSteffen Eiden 179*8348b72dSSteffen Eiden /* Verify that the UV supports at least one header version */ 180*8348b72dSSteffen Eiden report(uvcb_qui->supp_att_hdr_ver, "has hdr support"); 181*8348b72dSSteffen Eiden 182*8348b72dSSteffen Eiden memset((void *)page, 0, PAGE_SIZE); 183*8348b72dSSteffen Eiden 184*8348b72dSSteffen Eiden uvcb.header.len -= 1; 185*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 186*8348b72dSSteffen Eiden report(cc && uvcb.header.rc == UVC_RC_INV_LEN, "uvcb too small"); 187*8348b72dSSteffen Eiden uvcb.header.len += 1; 188*8348b72dSSteffen Eiden 189*8348b72dSSteffen Eiden uvcb.header.len += 1; 190*8348b72dSSteffen Eiden cc = uv_call(0, (uint64_t)&uvcb); 191*8348b72dSSteffen Eiden report(cc && uvcb.header.rc == UVC_RC_INV_LEN, "uvcb too large"); 192*8348b72dSSteffen Eiden uvcb.header.len -= 1; 193*8348b72dSSteffen Eiden } 194*8348b72dSSteffen Eiden 195*8348b72dSSteffen Eiden int main(void) 196*8348b72dSSteffen Eiden { 197*8348b72dSSteffen Eiden bool has_uvc = test_facility(158); 198*8348b72dSSteffen Eiden uint64_t page; 199*8348b72dSSteffen Eiden 200*8348b72dSSteffen Eiden 201*8348b72dSSteffen Eiden report_prefix_push("attestation"); 202*8348b72dSSteffen Eiden if (!has_uvc) { 203*8348b72dSSteffen Eiden report_skip("Ultravisor call facility is not available"); 204*8348b72dSSteffen Eiden goto done; 205*8348b72dSSteffen Eiden } 206*8348b72dSSteffen Eiden 207*8348b72dSSteffen Eiden if (!uv_os_is_guest()) { 208*8348b72dSSteffen Eiden report_skip("Not a protected guest"); 209*8348b72dSSteffen Eiden goto done; 210*8348b72dSSteffen Eiden } 211*8348b72dSSteffen Eiden 212*8348b72dSSteffen Eiden if (!uv_query_test_call(BIT_UVC_CMD_ATTESTATION)) { 213*8348b72dSSteffen Eiden report_skip("Attestation not supported."); 214*8348b72dSSteffen Eiden goto done; 215*8348b72dSSteffen Eiden } 216*8348b72dSSteffen Eiden 217*8348b72dSSteffen Eiden page = (uint64_t)alloc_page(); 218*8348b72dSSteffen Eiden /* The privilege check is done in uv-guest.c */ 219*8348b72dSSteffen Eiden test_attest(page); 220*8348b72dSSteffen Eiden test_attest_v1(page); 221*8348b72dSSteffen Eiden free_page((void *)page); 222*8348b72dSSteffen Eiden done: 223*8348b72dSSteffen Eiden report_prefix_pop(); 224*8348b72dSSteffen Eiden return report_summary(); 225*8348b72dSSteffen Eiden } 226