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