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, (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, chip_id, sizeof(chip_id)); 47 if (res) 48 return res; 49 return crypto_mac_update(ctx, ssk_str, sizeof(ssk_str)); 50 default: 51 return mac_usage(ctx, usage); 52 } 53 54 } 55 #endif /*CFG_CORE_HUK_SUBKEY_COMPAT*/ 56 57 TEE_Result huk_subkey_derive(enum huk_subkey_usage usage, 58 const void *const_data, size_t const_data_len, 59 uint8_t *subkey, size_t subkey_len) 60 { 61 void *ctx = NULL; 62 struct tee_hw_unique_key huk = { }; 63 TEE_Result res = TEE_SUCCESS; 64 65 if (subkey_len > HUK_SUBKEY_MAX_LEN) 66 return TEE_ERROR_BAD_PARAMETERS; 67 if (!const_data && const_data_len) 68 return TEE_ERROR_BAD_PARAMETERS; 69 70 res = crypto_mac_alloc_ctx(&ctx, TEE_ALG_HMAC_SHA256); 71 if (res) 72 return res; 73 74 res = tee_otp_get_hw_unique_key(&huk); 75 if (res) 76 goto out; 77 78 res = crypto_mac_init(ctx, huk.data, sizeof(huk.data)); 79 if (res) 80 goto out; 81 82 #ifdef CFG_CORE_HUK_SUBKEY_COMPAT 83 res = huk_compat(ctx, usage); 84 #else 85 res = mac_usage(ctx, usage); 86 #endif 87 if (res) 88 goto out; 89 90 if (const_data) { 91 res = crypto_mac_update(ctx, const_data, const_data_len); 92 if (res) 93 goto out; 94 } 95 96 res = crypto_mac_final(ctx, subkey, subkey_len); 97 out: 98 if (res) 99 memzero_explicit(subkey, subkey_len); 100 memzero_explicit(&huk, sizeof(huk)); 101 crypto_mac_free_ctx(ctx); 102 return res; 103 } 104