1*7e203c67SJorge Ramirez-Ortiz // SPDX-License-Identifier: BSD-2-Clause 2*7e203c67SJorge Ramirez-Ortiz /* 3*7e203c67SJorge Ramirez-Ortiz * Copyright (c) 2022, Linaro Limited 4*7e203c67SJorge Ramirez-Ortiz * Copyright (c) 2022, Foundries.io Limited 5*7e203c67SJorge Ramirez-Ortiz */ 6*7e203c67SJorge Ramirez-Ortiz 7*7e203c67SJorge Ramirez-Ortiz #include <assert.h> 8*7e203c67SJorge Ramirez-Ortiz #include <config.h> 9*7e203c67SJorge Ramirez-Ortiz #include <crypto/crypto.h> 10*7e203c67SJorge Ramirez-Ortiz #include <drivers/stm32_bsec.h> 11*7e203c67SJorge Ramirez-Ortiz #include <kernel/tee_common_otp.h> 12*7e203c67SJorge Ramirez-Ortiz #include <mempool.h> 13*7e203c67SJorge Ramirez-Ortiz #include <platform_config.h> 14*7e203c67SJorge Ramirez-Ortiz #include <stm32_util.h> 15*7e203c67SJorge Ramirez-Ortiz #include <string.h> 16*7e203c67SJorge Ramirez-Ortiz #include <string_ext.h> 17*7e203c67SJorge Ramirez-Ortiz 18*7e203c67SJorge Ramirez-Ortiz static bool stm32mp15_huk_init; 19*7e203c67SJorge Ramirez-Ortiz 20*7e203c67SJorge Ramirez-Ortiz static TEE_Result stm32mp15_read_uid(uint32_t *uid) 21*7e203c67SJorge Ramirez-Ortiz { 22*7e203c67SJorge Ramirez-Ortiz uint32_t *q = uid; 23*7e203c67SJorge Ramirez-Ortiz 24*7e203c67SJorge Ramirez-Ortiz /* 25*7e203c67SJorge Ramirez-Ortiz * Shadow memory for UID words might not be locked: to guarante that 26*7e203c67SJorge Ramirez-Ortiz * the final values are read we must lock them. 27*7e203c67SJorge Ramirez-Ortiz */ 28*7e203c67SJorge Ramirez-Ortiz if (stm32_bsec_set_sw_lock(UID0_OTP) || 29*7e203c67SJorge Ramirez-Ortiz stm32_bsec_shadow_read_otp(q++, UID0_OTP)) 30*7e203c67SJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 31*7e203c67SJorge Ramirez-Ortiz 32*7e203c67SJorge Ramirez-Ortiz if (stm32_bsec_set_sw_lock(UID1_OTP) || 33*7e203c67SJorge Ramirez-Ortiz stm32_bsec_shadow_read_otp(q++, UID1_OTP)) 34*7e203c67SJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 35*7e203c67SJorge Ramirez-Ortiz 36*7e203c67SJorge Ramirez-Ortiz if (stm32_bsec_set_sw_lock(UID2_OTP) || 37*7e203c67SJorge Ramirez-Ortiz stm32_bsec_shadow_read_otp(q++, UID2_OTP)) 38*7e203c67SJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 39*7e203c67SJorge Ramirez-Ortiz 40*7e203c67SJorge Ramirez-Ortiz return TEE_SUCCESS; 41*7e203c67SJorge Ramirez-Ortiz } 42*7e203c67SJorge Ramirez-Ortiz 43*7e203c67SJorge Ramirez-Ortiz static TEE_Result stm32mp15_read_otp(uint32_t otp, uint32_t *key, bool *locked) 44*7e203c67SJorge Ramirez-Ortiz { 45*7e203c67SJorge Ramirez-Ortiz bool tmp = true; 46*7e203c67SJorge Ramirez-Ortiz 47*7e203c67SJorge Ramirez-Ortiz if (!stm32mp_is_closed_device()) { 48*7e203c67SJorge Ramirez-Ortiz /* 49*7e203c67SJorge Ramirez-Ortiz * When the device is not closed, the shadow memory for these 50*7e203c67SJorge Ramirez-Ortiz * words might not be locked: check and report them 51*7e203c67SJorge Ramirez-Ortiz */ 52*7e203c67SJorge Ramirez-Ortiz if (stm32_bsec_read_permanent_lock(otp, &tmp)) 53*7e203c67SJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 54*7e203c67SJorge Ramirez-Ortiz 55*7e203c67SJorge Ramirez-Ortiz if (tmp && stm32_bsec_read_sw_lock(otp, &tmp)) 56*7e203c67SJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 57*7e203c67SJorge Ramirez-Ortiz } 58*7e203c67SJorge Ramirez-Ortiz 59*7e203c67SJorge Ramirez-Ortiz if (stm32_bsec_shadow_read_otp(key, otp)) 60*7e203c67SJorge Ramirez-Ortiz return TEE_ERROR_GENERIC; 61*7e203c67SJorge Ramirez-Ortiz 62*7e203c67SJorge Ramirez-Ortiz *locked = *locked && tmp; 63*7e203c67SJorge Ramirez-Ortiz 64*7e203c67SJorge Ramirez-Ortiz return TEE_SUCCESS; 65*7e203c67SJorge Ramirez-Ortiz } 66*7e203c67SJorge Ramirez-Ortiz 67*7e203c67SJorge Ramirez-Ortiz /* 68*7e203c67SJorge Ramirez-Ortiz * AES-GCM: nonce must be unique per message and key. 69*7e203c67SJorge Ramirez-Ortiz * 70*7e203c67SJorge Ramirez-Ortiz * This function always uses the same key - once its locked - with the same 71*7e203c67SJorge Ramirez-Ortiz * unique message hence the nonce can be any constant. 72*7e203c67SJorge Ramirez-Ortiz */ 73*7e203c67SJorge Ramirez-Ortiz static TEE_Result aes_gcm_encrypt_uid(uint8_t *key, size_t key_len, 74*7e203c67SJorge Ramirez-Ortiz uint8_t *out, size_t *out_len) 75*7e203c67SJorge Ramirez-Ortiz { 76*7e203c67SJorge Ramirez-Ortiz TEE_Result ret = TEE_ERROR_GENERIC; 77*7e203c67SJorge Ramirez-Ortiz const uint8_t nonce[12] = { 0x55 }; 78*7e203c67SJorge Ramirez-Ortiz uint32_t uid[4] = { 0 }; 79*7e203c67SJorge Ramirez-Ortiz uint8_t tag[16] = { 0 }; 80*7e203c67SJorge Ramirez-Ortiz size_t nonce_len = sizeof(nonce); 81*7e203c67SJorge Ramirez-Ortiz size_t tag_len = sizeof(tag); 82*7e203c67SJorge Ramirez-Ortiz size_t uid_len = sizeof(uid); 83*7e203c67SJorge Ramirez-Ortiz void *ctx = NULL; 84*7e203c67SJorge Ramirez-Ortiz 85*7e203c67SJorge Ramirez-Ortiz ret = stm32mp15_read_uid(uid); 86*7e203c67SJorge Ramirez-Ortiz if (ret) 87*7e203c67SJorge Ramirez-Ortiz goto out; 88*7e203c67SJorge Ramirez-Ortiz 89*7e203c67SJorge Ramirez-Ortiz ret = crypto_authenc_alloc_ctx(&ctx, TEE_ALG_AES_GCM); 90*7e203c67SJorge Ramirez-Ortiz if (ret) 91*7e203c67SJorge Ramirez-Ortiz goto out; 92*7e203c67SJorge Ramirez-Ortiz 93*7e203c67SJorge Ramirez-Ortiz ret = crypto_authenc_init(ctx, TEE_MODE_ENCRYPT, key, key_len, nonce, 94*7e203c67SJorge Ramirez-Ortiz nonce_len, TEE_AES_BLOCK_SIZE, 0, uid_len); 95*7e203c67SJorge Ramirez-Ortiz if (ret) 96*7e203c67SJorge Ramirez-Ortiz goto out_free_ctx; 97*7e203c67SJorge Ramirez-Ortiz 98*7e203c67SJorge Ramirez-Ortiz ret = crypto_authenc_enc_final(ctx, (uint8_t *)uid, sizeof(uid), 99*7e203c67SJorge Ramirez-Ortiz out, out_len, tag, &tag_len); 100*7e203c67SJorge Ramirez-Ortiz if (ret) 101*7e203c67SJorge Ramirez-Ortiz goto out_free_ctx; 102*7e203c67SJorge Ramirez-Ortiz 103*7e203c67SJorge Ramirez-Ortiz crypto_authenc_final(ctx); 104*7e203c67SJorge Ramirez-Ortiz out_free_ctx: 105*7e203c67SJorge Ramirez-Ortiz crypto_authenc_free_ctx(ctx); 106*7e203c67SJorge Ramirez-Ortiz out: 107*7e203c67SJorge Ramirez-Ortiz if (ret) 108*7e203c67SJorge Ramirez-Ortiz memzero_explicit(out, *out_len); 109*7e203c67SJorge Ramirez-Ortiz 110*7e203c67SJorge Ramirez-Ortiz return ret; 111*7e203c67SJorge Ramirez-Ortiz } 112*7e203c67SJorge Ramirez-Ortiz 113*7e203c67SJorge Ramirez-Ortiz TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) 114*7e203c67SJorge Ramirez-Ortiz { 115*7e203c67SJorge Ramirez-Ortiz uint32_t otp_key[4] = { 0 }; 116*7e203c67SJorge Ramirez-Ortiz size_t len = sizeof(otp_key); 117*7e203c67SJorge Ramirez-Ortiz TEE_Result ret = TEE_SUCCESS; 118*7e203c67SJorge Ramirez-Ortiz uint32_t *key = otp_key; 119*7e203c67SJorge Ramirez-Ortiz bool lock = true; 120*7e203c67SJorge Ramirez-Ortiz 121*7e203c67SJorge Ramirez-Ortiz static_assert(CFG_STM32MP15_HUK_BSEC_KEY_0 < STM32MP1_OTP_MAX_ID); 122*7e203c67SJorge Ramirez-Ortiz static_assert(CFG_STM32MP15_HUK_BSEC_KEY_1 < STM32MP1_OTP_MAX_ID); 123*7e203c67SJorge Ramirez-Ortiz static_assert(CFG_STM32MP15_HUK_BSEC_KEY_2 < STM32MP1_OTP_MAX_ID); 124*7e203c67SJorge Ramirez-Ortiz static_assert(CFG_STM32MP15_HUK_BSEC_KEY_3 < STM32MP1_OTP_MAX_ID); 125*7e203c67SJorge Ramirez-Ortiz 126*7e203c67SJorge Ramirez-Ortiz ret = stm32mp15_read_otp(CFG_STM32MP15_HUK_BSEC_KEY_0, key++, &lock); 127*7e203c67SJorge Ramirez-Ortiz if (ret) 128*7e203c67SJorge Ramirez-Ortiz goto out; 129*7e203c67SJorge Ramirez-Ortiz 130*7e203c67SJorge Ramirez-Ortiz ret = stm32mp15_read_otp(CFG_STM32MP15_HUK_BSEC_KEY_1, key++, &lock); 131*7e203c67SJorge Ramirez-Ortiz if (ret) 132*7e203c67SJorge Ramirez-Ortiz goto out; 133*7e203c67SJorge Ramirez-Ortiz 134*7e203c67SJorge Ramirez-Ortiz ret = stm32mp15_read_otp(CFG_STM32MP15_HUK_BSEC_KEY_2, key++, &lock); 135*7e203c67SJorge Ramirez-Ortiz if (ret) 136*7e203c67SJorge Ramirez-Ortiz goto out; 137*7e203c67SJorge Ramirez-Ortiz 138*7e203c67SJorge Ramirez-Ortiz ret = stm32mp15_read_otp(CFG_STM32MP15_HUK_BSEC_KEY_3, key++, &lock); 139*7e203c67SJorge Ramirez-Ortiz if (ret) 140*7e203c67SJorge Ramirez-Ortiz goto out; 141*7e203c67SJorge Ramirez-Ortiz 142*7e203c67SJorge Ramirez-Ortiz ret = aes_gcm_encrypt_uid((uint8_t *)otp_key, len, hwkey->data, &len); 143*7e203c67SJorge Ramirez-Ortiz 144*7e203c67SJorge Ramirez-Ortiz if (len != HW_UNIQUE_KEY_LENGTH) 145*7e203c67SJorge Ramirez-Ortiz ret = TEE_ERROR_GENERIC; 146*7e203c67SJorge Ramirez-Ortiz out: 147*7e203c67SJorge Ramirez-Ortiz memzero_explicit(otp_key, HW_UNIQUE_KEY_LENGTH); 148*7e203c67SJorge Ramirez-Ortiz 149*7e203c67SJorge Ramirez-Ortiz if (!ret && !stm32mp15_huk_init) { 150*7e203c67SJorge Ramirez-Ortiz stm32mp15_huk_init = true; 151*7e203c67SJorge Ramirez-Ortiz IMSG("HUK %slocked", lock ? "" : "un"); 152*7e203c67SJorge Ramirez-Ortiz DHEXDUMP(hwkey->data, HW_UNIQUE_KEY_LENGTH); 153*7e203c67SJorge Ramirez-Ortiz } 154*7e203c67SJorge Ramirez-Ortiz 155*7e203c67SJorge Ramirez-Ortiz return ret; 156*7e203c67SJorge Ramirez-Ortiz } 157*7e203c67SJorge Ramirez-Ortiz 158