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