1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2019, Linaro Limited 4 */ 5 6 #include <config.h> 7 #include <crypto/crypto.h> 8 #include <kernel/huk_subkey.h> 9 #include <kernel/tee_common_otp.h> 10 #include <string_ext.h> 11 #include <tee/tee_fs_key_manager.h> 12 13 static TEE_Result mac_usage(void *ctx, uint32_t usage) 14 { 15 return crypto_mac_update(ctx, (const void *)&usage, sizeof(usage)); 16 } 17 18 #ifdef CFG_CORE_HUK_SUBKEY_COMPAT 19 static TEE_Result get_otp_die_id(uint8_t *buffer, size_t len) 20 { 21 static const char pattern[4] = { 'B', 'E', 'E', 'F' }; 22 size_t i; 23 24 if (IS_ENABLED(CFG_CORE_HUK_SUBKEY_COMPAT_USE_OTP_DIE_ID)) 25 return tee_otp_get_die_id(buffer, len); 26 27 for (i = 0; i < len; i++) 28 buffer[i] = pattern[i % 4]; 29 30 return TEE_SUCCESS; 31 } 32 33 /* 34 * This does special treatment for RPMB and SSK key derivations to give 35 * the same result as when huk_subkey_derive() wasn't used. 36 */ 37 static TEE_Result huk_compat(void *ctx, enum huk_subkey_usage usage) 38 { 39 TEE_Result res = TEE_SUCCESS; 40 uint8_t chip_id[TEE_FS_KM_CHIP_ID_LENGTH] = { 0 }; 41 static uint8_t ssk_str[] = "ONLY_FOR_tee_fs_ssk"; 42 43 switch (usage) { 44 case HUK_SUBKEY_RPMB: 45 return TEE_SUCCESS; 46 case HUK_SUBKEY_SSK: 47 res = get_otp_die_id(chip_id, sizeof(chip_id)); 48 if (res) 49 return res; 50 res = crypto_mac_update(ctx, chip_id, sizeof(chip_id)); 51 if (res) 52 return res; 53 return crypto_mac_update(ctx, ssk_str, sizeof(ssk_str)); 54 default: 55 return mac_usage(ctx, usage); 56 } 57 58 } 59 #endif /*CFG_CORE_HUK_SUBKEY_COMPAT*/ 60 61 TEE_Result __huk_subkey_derive(enum huk_subkey_usage usage, 62 const void *const_data, size_t const_data_len, 63 uint8_t *subkey, size_t subkey_len) 64 { 65 void *ctx = NULL; 66 struct tee_hw_unique_key huk = { }; 67 TEE_Result res = TEE_SUCCESS; 68 69 if (subkey_len > HUK_SUBKEY_MAX_LEN) 70 return TEE_ERROR_BAD_PARAMETERS; 71 if (!const_data && const_data_len) 72 return TEE_ERROR_BAD_PARAMETERS; 73 74 res = crypto_mac_alloc_ctx(&ctx, TEE_ALG_HMAC_SHA256); 75 if (res) 76 return res; 77 78 res = tee_otp_get_hw_unique_key(&huk); 79 if (res) 80 goto out; 81 82 res = crypto_mac_init(ctx, huk.data, sizeof(huk.data)); 83 if (res) 84 goto out; 85 86 #ifdef CFG_CORE_HUK_SUBKEY_COMPAT 87 res = huk_compat(ctx, usage); 88 #else 89 res = mac_usage(ctx, usage); 90 #endif 91 if (res) 92 goto out; 93 94 if (const_data) { 95 res = crypto_mac_update(ctx, const_data, const_data_len); 96 if (res) 97 goto out; 98 } 99 100 res = crypto_mac_final(ctx, subkey, subkey_len); 101 out: 102 if (res) 103 memzero_explicit(subkey, subkey_len); 104 memzero_explicit(&huk, sizeof(huk)); 105 crypto_mac_free_ctx(ctx); 106 return res; 107 } 108 109 TEE_Result huk_subkey_derive(enum huk_subkey_usage usage, 110 const void *const_data, size_t const_data_len, 111 uint8_t *subkey, size_t subkey_len) 112 __weak __alias("__huk_subkey_derive"); 113