1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright 2021 Foundries.io Ltd. 4 * Jorge Ramirez-Ortiz <jorge@foundries.io> 5 */ 6 7 #include <assert.h> 8 #include <drivers/zynqmp_csu_aes.h> 9 #include <drivers/zynqmp_csu_puf.h> 10 #include <drivers/zynqmp_huk.h> 11 #include <drivers/zynqmp_pm.h> 12 #include <io.h> 13 #include <kernel/tee_common_otp.h> 14 #include <mm/core_memprot.h> 15 #include <string_ext.h> 16 #include <tee/tee_cryp_utl.h> 17 #include <trace.h> 18 #include <utee_defines.h> 19 20 static struct { 21 uint8_t key[HW_UNIQUE_KEY_LENGTH]; 22 bool ready; 23 } huk; 24 25 __weak TEE_Result tee_zynqmp_get_device_dna(uint8_t *device_dna, size_t size) 26 { 27 if (size != ZYNQMP_EFUSE_LEN(DNA)) 28 return TEE_ERROR_BAD_PARAMETERS; 29 30 /* Get Device DNA from the PS eFuses */ 31 return zynqmp_efuse_read(device_dna, size, DNA, false); 32 } 33 34 /* 35 * Generate HUK source data 36 * 37 * Performs SHA256 over of data: 38 * - Device DNA (from PL preferably) 39 * - Selected user eFuses (HUK seed) 40 * 41 * HUK source data is later on AES encrypted with device key to shuffle source 42 * data even further with secret key. 43 * 44 * Note: Even though the device key is secret used details for HUK source data 45 * should not be exposed to REE environment. 46 * 47 * Note: You should not change HUK source data generation parameters after 48 * devices have been deployed. 49 * 50 * @device_dna: Value of Device DNA 51 * @device_dna_size: Size of Device DNA 52 * @huk_source: Output buffer for HUK source data 53 * @huk_source_size: Output buffer size for HUK source data 54 * Return a TEE_Result compliant status 55 */ 56 static TEE_Result tee_zynqmp_generate_huk_src(const uint8_t *device_dna, 57 size_t device_dna_size, 58 uint8_t *huk_source, 59 size_t huk_source_size) 60 { 61 TEE_Result res = TEE_ERROR_GENERIC; 62 uint32_t user_efuse = 0; 63 void *ctx = NULL; 64 int i = 0; 65 66 assert(device_dna_size == ZYNQMP_EFUSE_LEN(DNA)); 67 assert(huk_source_size == HW_UNIQUE_KEY_LENGTH); 68 69 res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256); 70 if (res) 71 return res; 72 73 res = crypto_hash_init(ctx); 74 if (res) 75 goto out; 76 77 res = crypto_hash_update(ctx, device_dna, device_dna_size); 78 if (res) 79 goto out; 80 81 /* Hash selected user eFuses */ 82 for (i = 0; i < (USER7 - USER0 + 1); i++) { 83 if (CFG_ZYNQMP_HUK_USER_EFUSE_MASK & BIT(i)) { 84 DMSG("Use User eFuse %d for HUK source data", i); 85 86 res = zynqmp_efuse_read((uint8_t *)&user_efuse, 87 sizeof(user_efuse), USER0 + i, 88 false); 89 if (res) 90 goto out; 91 92 res = crypto_hash_update(ctx, (uint8_t *)&user_efuse, 93 sizeof(user_efuse)); 94 if (res) 95 goto out; 96 } 97 } 98 99 res = crypto_hash_final(ctx, huk_source, huk_source_size); 100 out: 101 crypto_hash_free_ctx(ctx); 102 memzero_explicit(&user_efuse, sizeof(user_efuse)); 103 return res; 104 } 105 106 TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) 107 { 108 vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE); 109 uint8_t device_dna[ZYNQMP_EFUSE_LEN(DNA)] = { 0 }; 110 uint8_t src[HW_UNIQUE_KEY_LENGTH] __aligned_csuaes = { 0 }; 111 uint8_t iv[ZYNQMP_GCM_IV_SIZE] = { 0 }; 112 uint8_t tag[ZYNQMP_GCM_TAG_SIZE] __aligned_csuaes = { 0 }; 113 uint8_t sha[HW_UNIQUE_KEY_LENGTH] = { 0 }; 114 uint8_t dst[ZYNQMP_CSU_AES_DST_LEN(sizeof(src))] 115 __aligned_csuaes = { 0 }; 116 TEE_Result ret = TEE_ERROR_GENERIC; 117 uint32_t status = 0; 118 119 static_assert(sizeof(device_dna) == ZYNQMP_GCM_IV_SIZE); 120 121 if (huk.ready) 122 goto out; 123 124 ret = tee_zynqmp_get_device_dna(device_dna, sizeof(device_dna)); 125 if (ret) { 126 EMSG("Can't read the Device DNA"); 127 goto cleanup; 128 } 129 130 status = io_read32(csu + ZYNQMP_CSU_STATUS_OFFSET); 131 if (!(status & ZYNQMP_CSU_STATUS_AUTH)) { 132 /* The DNA is a unique identifier valid but not secure */ 133 IMSG("CSU authentication disabled, using development HUK"); 134 135 /* Use hash of device DNA for development HUK */ 136 ret = tee_hash_createdigest(TEE_ALG_SHA256, device_dna, 137 sizeof(device_dna), huk.key, 138 sizeof(huk.key)); 139 if (ret) { 140 EMSG("Can't generate the SHA256 for the DNA eFuse"); 141 goto cleanup; 142 } 143 144 huk.ready = true; 145 goto out; 146 } 147 148 /* Use device DNA for IV */ 149 memcpy(iv, device_dna, sizeof(device_dna)); 150 151 /* Generate HUK source data */ 152 ret = tee_zynqmp_generate_huk_src(device_dna, sizeof(device_dna), src, 153 sizeof(src)); 154 if (ret) { 155 EMSG("Failed to generate HUK source data"); 156 goto cleanup; 157 } 158 159 #ifdef CFG_ZYNQMP_CSU_PUF 160 /* 161 * Neither the PMUFW nor the PUF hardware provide an indication of the 162 * PUF KEK registration status. The verification algorithm that follows 163 * encrypts and then decrypts the resulting string regenerating the 164 * PUF KEK in between: if the outputs match, then the PUF KEK was 165 * registered properly and we can use it to generate the HUK. 166 */ 167 zynqmp_csu_puf_reset(); 168 169 ret = zynqmp_csu_puf_regenerate(); 170 if (ret) { 171 EMSG("PUF regeneration error"); 172 goto cleanup; 173 } 174 #endif 175 176 memcpy(sha, src, sizeof(sha)); 177 /* The dst buffer must be large enough to include the generated tag */ 178 ret = zynqmp_csu_aes_encrypt_data(src, sizeof(src), dst, sizeof(dst), 179 tag, sizeof(tag), iv, sizeof(iv), 180 ZYNQMP_CSU_AES_KEY_SRC_DEV); 181 if (ret) { 182 EMSG("Can't encrypt DNA, please make sure PUF was registered"); 183 goto cleanup; 184 } 185 186 #ifdef CFG_ZYNQMP_CSU_PUF 187 /* regenerate the PUF KEK */ 188 ret = zynqmp_csu_puf_regenerate(); 189 if (ret) { 190 EMSG("PUF regeneration error"); 191 goto cleanup; 192 } 193 #endif 194 memset(src, 0, sizeof(src)); 195 /* Ignore the tag data from the dst buffer - pass a smaller size */ 196 ret = zynqmp_csu_aes_decrypt_data(dst, sizeof(src), src, sizeof(src), 197 tag, sizeof(tag), iv, 198 ZYNQMP_EFUSE_LEN(DNA), 199 ZYNQMP_CSU_AES_KEY_SRC_DEV); 200 if (ret) { 201 EMSG("Can't decrypt DNA, please make sure PUF was registered"); 202 goto cleanup; 203 } 204 205 if (memcmp(src, sha, sizeof(sha))) { 206 EMSG("PUF not ready, can't create HUK"); 207 ret = TEE_ERROR_GENERIC; 208 goto cleanup; 209 } 210 211 IMSG("HUK ready"); 212 213 /* 214 * The HUK is the SHA-256 of Device DNA with optional User eFuses 215 * included and then AES-GCM encrypted with the selected Device Key 216 * using the Device DNA as the IV. 217 */ 218 memcpy(huk.key, dst, sizeof(huk.key)); 219 huk.ready = true; 220 out: 221 memcpy(hwkey->data, huk.key, HW_UNIQUE_KEY_LENGTH); 222 ret = TEE_SUCCESS; 223 224 cleanup: 225 /* Cleanup stack memory so that there are no left overs */ 226 memzero_explicit(dst, sizeof(dst)); 227 memzero_explicit(sha, sizeof(sha)); 228 memzero_explicit(tag, sizeof(tag)); 229 memzero_explicit(iv, sizeof(iv)); 230 memzero_explicit(src, sizeof(src)); 231 memzero_explicit(device_dna, sizeof(device_dna)); 232 233 return ret; 234 } 235