diff --git a/doc/acrn.doxyfile b/doc/acrn.doxyfile index be8926b69..a8b1afc2b 100644 --- a/doc/acrn.doxyfile +++ b/doc/acrn.doxyfile @@ -813,6 +813,7 @@ INPUT = custom-doxygen/mainpage.md \ ../hypervisor/include/arch/x86/irq.h \ ../hypervisor/include/arch/x86/lapic.h \ ../hypervisor/include/common/irq.h \ + ../hypervisor/include/lib/crypto/crypto_api.h \ ../devicemodel/include/virtio_kernel.h \ ../devicemodel/include/vhost.h \ ../devicemodel/include/dm.h \ diff --git a/hypervisor/Makefile b/hypervisor/Makefile index 6cc4794b6..4a8b73335 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -155,7 +155,7 @@ C_SRCS += arch/x86/guest/pm.c C_SRCS += lib/misc.c C_SRCS += lib/string.c C_SRCS += lib/memory.c -C_SRCS += lib/crypto/hkdf_wrap.c +C_SRCS += lib/crypto/crypto_api.c C_SRCS += lib/crypto/mbedtls/hkdf.c C_SRCS += lib/crypto/mbedtls/sha256.c C_SRCS += lib/crypto/mbedtls/md.c diff --git a/hypervisor/arch/x86/trusty.c b/hypervisor/arch/x86/trusty.c index 36617bc50..8415eeadf 100644 --- a/hypervisor/arch/x86/trusty.c +++ b/hypervisor/arch/x86/trusty.c @@ -5,7 +5,7 @@ */ #include -#include +#include #define ACRN_DBG_TRUSTY 6U @@ -334,6 +334,54 @@ void switch_world(struct acrn_vcpu *vcpu, int next_world) arch->cur_context = next_world; } +static int32_t get_max_svn_index(void) +{ + uint32_t i, max_svn_idx = 0U; + + if ((g_key_info.num_seeds == 0U) || + (g_key_info.num_seeds > BOOTLOADER_SEED_MAX_ENTRIES)) { + return -1; + } + + for (i = 1U; i < g_key_info.num_seeds; i++) { + if (g_key_info.dseed_list[i].cse_svn > + g_key_info.dseed_list[i-1].cse_svn) { + max_svn_idx = i; + } + } + + return max_svn_idx; +} + +static bool derive_aek(uint8_t *attkb_key) +{ + const int8_t salt[] = "Attestation Keybox Encryption Key"; + const uint8_t *ikm; + uint32_t ikm_len; + int32_t max_svn_idx; + + if (!attkb_key) { + return false; + } + + max_svn_idx = get_max_svn_index(); + if (max_svn_idx < 0) { + return false; + } + + ikm = g_key_info.dseed_list[max_svn_idx].seed; + /* only the low 32 bits of seed are valid */ + ikm_len = 32; + + if (hmac_sha256(attkb_key, ikm, ikm_len, + (const uint8_t *)salt, sizeof(salt)) != 1) { + pr_err("%s: failed to derive key!\n", __func__); + return false; + } + + return true; +} + /* Put key_info and trusty_startup_param in the first Page of Trusty * runtime memory */ @@ -368,6 +416,13 @@ static bool setup_trusty_info(struct acrn_vcpu *vcpu, key_info->dseed_list[i].cse_svn = g_key_info.dseed_list[i].cse_svn; } + /* Derive decryption key of attestation keybox from dseed */ + if (!derive_aek(key_info->attkb_enc_key)) { + (void)memset(key_info, 0U, sizeof(struct trusty_key_info)); + pr_err("%s: derive key of att keybox failed!", __func__); + return false; + } + /* Prepare trusty startup param */ mem->first_page.data.startup_param.size_of_this_struct = sizeof(struct trusty_startup_param); diff --git a/hypervisor/include/lib/crypto/crypto_api.h b/hypervisor/include/lib/crypto/crypto_api.h new file mode 100644 index 000000000..f052e6f2f --- /dev/null +++ b/hypervisor/include/lib/crypto/crypto_api.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2018 Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file crypto_api.h + * + * @brief public APIs for crypto functions + */ + +#ifndef CRYPTO_API_H +#define CRYPTO_API_H + +#include + +/** + * @brief HMAC-based Extract-and-Expand Key Derivation Function. + * + * @param out_key Pointer to key buffer which is used to save + * hkdf_sha256 result + * @param out_len The length of out_key + * @param secret Pointer to input keying material + * @param secret_len The length of secret + * @param salt Pointer to salt buffer, it is optional + * if not provided (salt == NULL), it is set internally + * to a string of hashlen(32) zeros + * @param salt_len The length of the salt value + * Ignored if salt is NULL + * @param info Pointer to application specific information, it is + * optional. Ignored if info == NULL or a zero-length string + * @param info_len: The length of the info, ignored if info is NULL + * + * @return int 1 - Success 0 - Failure + */ +int hkdf_sha256(uint8_t *out_key, size_t out_len, + const uint8_t *secret, size_t secret_len, + const uint8_t *salt, size_t salt_len, + const uint8_t *info, size_t info_len); + +/** + * @brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The HMAC result is calculated as + * output = generic HMAC(hmac key, input buffer). + * + * @param out_key The generic HMAC result + * @param secret The HMAC secret key + * @param secret_len The length of the HMAC secret key in Bytes + * @param salt The buffer holding the input data + * @param salt_len The length of the input data + * + * @return int 1 - Success 0 - Failure + */ +int hmac_sha256(uint8_t *out_key, + const uint8_t *secret, size_t secret_len, + const uint8_t *salt, size_t salt_len); + +#endif /* CRYPTO_API_H */ diff --git a/hypervisor/include/lib/crypto/hkdf_wrap.h b/hypervisor/include/lib/crypto/hkdf_wrap.h deleted file mode 100644 index 335de18a3..000000000 --- a/hypervisor/include/lib/crypto/hkdf_wrap.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2018 Intel Corporation. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef HKDF_WRAP_H -#define HKDF_WRAP_H - -#include - -/* - * FUNCTION - * hkdf_sha256 - * - * Description - * HMAC-based Extract-and-Expand Key Derivation Function. - * - * Parameters: - * out_key Pointer to key buffer which is used to save - * hkdf_sha256 result - * out_len The length of out_key - * secret Pointer to input keying material - * secret_len The length of secret - * salt Pointer to salt buffer, it is optional - * if not provided (salt == NULL), it is set internally - * to a string of hashlen(32) zeros - * salt_len The length of the salt value - * Ignored if salt is NULL - * info Pointer to application specific information, it is - * optional - * Ignored if info == NULL or a zero-length string - * info_len: The length of the info, ignored if info is NULL - * - * OUTPUTS - * 1 - Success - * 0 - Failure - */ -int hkdf_sha256(uint8_t *out_key, size_t out_len, - const uint8_t *secret, size_t secret_len, - const uint8_t *salt, size_t salt_len, - const uint8_t *info, size_t info_len); - -#endif /* HKDF_WRAP_H */ diff --git a/hypervisor/lib/crypto/hkdf_wrap.c b/hypervisor/lib/crypto/crypto_api.c similarity index 53% rename from hypervisor/lib/crypto/hkdf_wrap.c rename to hypervisor/lib/crypto/crypto_api.c index c4554d9b9..b3f10cf76 100644 --- a/hypervisor/lib/crypto/hkdf_wrap.c +++ b/hypervisor/lib/crypto/crypto_api.c @@ -6,6 +6,7 @@ #include #include "mbedtls/hkdf.h" +#include "mbedtls/md.h" int hkdf_sha256(uint8_t *out_key, size_t out_len, const uint8_t *secret, size_t secret_len, @@ -14,6 +15,11 @@ int hkdf_sha256(uint8_t *out_key, size_t out_len, { const mbedtls_md_info_t *md; + /* salt and info can be NULL, others can't */ + if (!out_key || !secret) { + return 0; + } + md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); if (md == NULL) { return 0; @@ -29,3 +35,28 @@ int hkdf_sha256(uint8_t *out_key, size_t out_len, return 1; } + +int hmac_sha256(uint8_t *out_key, + const uint8_t *secret, size_t secret_len, + const uint8_t *salt, size_t salt_len) +{ + const mbedtls_md_info_t *md; + + if (!out_key || !secret || !salt) { + return 0; + } + + md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + if (md == NULL) { + return 0; + } + + if (mbedtls_md_hmac(md, + salt, salt_len, + secret, secret_len, + out_key) != 0) { + return 0; + } + + return 1; +}