1fa0525faSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 2fa0525faSJens Wiklander /* 3fa0525faSJens Wiklander * Copyright (c) 2019, Linaro Limited 4fa0525faSJens Wiklander */ 5fa0525faSJens Wiklander 6*33b38f8cSRuslan Piasetskyi #include <config.h> 7fa0525faSJens Wiklander #include <crypto/crypto.h> 8fa0525faSJens Wiklander #include <kernel/huk_subkey.h> 9fa0525faSJens Wiklander #include <kernel/tee_common_otp.h> 103ca4a1caSJerome Forissier #include <string_ext.h> 1117888736SJens Wiklander #include <tee/tee_fs_key_manager.h> 12fa0525faSJens Wiklander 13fa0525faSJens Wiklander static TEE_Result mac_usage(void *ctx, uint32_t usage) 14fa0525faSJens Wiklander { 15c69bc615SJens Wiklander return crypto_mac_update(ctx, (const void *)&usage, sizeof(usage)); 16fa0525faSJens Wiklander } 17fa0525faSJens Wiklander 1817888736SJens Wiklander #ifdef CFG_CORE_HUK_SUBKEY_COMPAT 19*33b38f8cSRuslan Piasetskyi static TEE_Result get_otp_die_id(uint8_t *buffer, size_t len) 2017888736SJens Wiklander { 2117888736SJens Wiklander static const char pattern[4] = { 'B', 'E', 'E', 'F' }; 2217888736SJens Wiklander size_t i; 2317888736SJens Wiklander 24*33b38f8cSRuslan Piasetskyi if (IS_ENABLED(CFG_CORE_HUK_SUBKEY_COMPAT_USE_OTP_DIE_ID)) 25*33b38f8cSRuslan Piasetskyi return tee_otp_get_die_id(buffer, len); 26*33b38f8cSRuslan Piasetskyi 2717888736SJens Wiklander for (i = 0; i < len; i++) 2817888736SJens Wiklander buffer[i] = pattern[i % 4]; 29*33b38f8cSRuslan Piasetskyi 30*33b38f8cSRuslan Piasetskyi return TEE_SUCCESS; 3117888736SJens Wiklander } 3217888736SJens Wiklander 3317888736SJens Wiklander /* 3417888736SJens Wiklander * This does special treatment for RPMB and SSK key derivations to give 3517888736SJens Wiklander * the same result as when huk_subkey_derive() wasn't used. 3617888736SJens Wiklander */ 3717888736SJens Wiklander static TEE_Result huk_compat(void *ctx, enum huk_subkey_usage usage) 3817888736SJens Wiklander { 3917888736SJens Wiklander TEE_Result res = TEE_SUCCESS; 4017888736SJens Wiklander uint8_t chip_id[TEE_FS_KM_CHIP_ID_LENGTH] = { 0 }; 4117888736SJens Wiklander static uint8_t ssk_str[] = "ONLY_FOR_tee_fs_ssk"; 4217888736SJens Wiklander 4317888736SJens Wiklander switch (usage) { 4417888736SJens Wiklander case HUK_SUBKEY_RPMB: 4517888736SJens Wiklander return TEE_SUCCESS; 4617888736SJens Wiklander case HUK_SUBKEY_SSK: 47*33b38f8cSRuslan Piasetskyi res = get_otp_die_id(chip_id, sizeof(chip_id)); 48*33b38f8cSRuslan Piasetskyi if (res) 49*33b38f8cSRuslan Piasetskyi return res; 50c69bc615SJens Wiklander res = crypto_mac_update(ctx, chip_id, sizeof(chip_id)); 5117888736SJens Wiklander if (res) 5217888736SJens Wiklander return res; 53c69bc615SJens Wiklander return crypto_mac_update(ctx, ssk_str, sizeof(ssk_str)); 5417888736SJens Wiklander default: 5517888736SJens Wiklander return mac_usage(ctx, usage); 5617888736SJens Wiklander } 5717888736SJens Wiklander 5817888736SJens Wiklander } 5917888736SJens Wiklander #endif /*CFG_CORE_HUK_SUBKEY_COMPAT*/ 6017888736SJens Wiklander 61fa0525faSJens Wiklander TEE_Result huk_subkey_derive(enum huk_subkey_usage usage, 62fa0525faSJens Wiklander const void *const_data, size_t const_data_len, 63fa0525faSJens Wiklander uint8_t *subkey, size_t subkey_len) 64fa0525faSJens Wiklander { 65fa0525faSJens Wiklander void *ctx = NULL; 66fa0525faSJens Wiklander struct tee_hw_unique_key huk = { }; 67fa0525faSJens Wiklander TEE_Result res = TEE_SUCCESS; 68fa0525faSJens Wiklander 69fa0525faSJens Wiklander if (subkey_len > HUK_SUBKEY_MAX_LEN) 70fa0525faSJens Wiklander return TEE_ERROR_BAD_PARAMETERS; 71fa0525faSJens Wiklander if (!const_data && const_data_len) 72fa0525faSJens Wiklander return TEE_ERROR_BAD_PARAMETERS; 73fa0525faSJens Wiklander 74fa0525faSJens Wiklander res = crypto_mac_alloc_ctx(&ctx, TEE_ALG_HMAC_SHA256); 75fa0525faSJens Wiklander if (res) 76fa0525faSJens Wiklander return res; 77fa0525faSJens Wiklander 78fa0525faSJens Wiklander res = tee_otp_get_hw_unique_key(&huk); 79fa0525faSJens Wiklander if (res) 80fa0525faSJens Wiklander goto out; 81fa0525faSJens Wiklander 82c69bc615SJens Wiklander res = crypto_mac_init(ctx, huk.data, sizeof(huk.data)); 83fa0525faSJens Wiklander if (res) 84fa0525faSJens Wiklander goto out; 85fa0525faSJens Wiklander 8617888736SJens Wiklander #ifdef CFG_CORE_HUK_SUBKEY_COMPAT 8717888736SJens Wiklander res = huk_compat(ctx, usage); 8817888736SJens Wiklander #else 89fa0525faSJens Wiklander res = mac_usage(ctx, usage); 9017888736SJens Wiklander #endif 91fa0525faSJens Wiklander if (res) 92fa0525faSJens Wiklander goto out; 93fa0525faSJens Wiklander 94fa0525faSJens Wiklander if (const_data) { 95c69bc615SJens Wiklander res = crypto_mac_update(ctx, const_data, const_data_len); 96fa0525faSJens Wiklander if (res) 97fa0525faSJens Wiklander goto out; 98fa0525faSJens Wiklander } 99fa0525faSJens Wiklander 100c69bc615SJens Wiklander res = crypto_mac_final(ctx, subkey, subkey_len); 101fa0525faSJens Wiklander out: 102fa0525faSJens Wiklander if (res) 1033ca4a1caSJerome Forissier memzero_explicit(subkey, subkey_len); 1043ca4a1caSJerome Forissier memzero_explicit(&huk, sizeof(huk)); 105c69bc615SJens Wiklander crypto_mac_free_ctx(ctx); 106fa0525faSJens Wiklander return res; 107fa0525faSJens Wiklander } 108