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