Skip to content

Commit fc9ec5d

Browse files
GangSecuritylijinxia
authored andcommitted
hv: Derive decryption key from Seed for Trusty to decrypt attestation keybox
CSE FW uses an AEK (Attestation keybox Encryption Key) to encrypt the keybox with AES-256-GCM algorithm before sending it to Android/Trusty. This key is derived from the latest platform Seed by CSE FW with KDF (key derivation function) HMAC-SHA256. After Trusty retrieves this encrypted keybox over HECI/MEI driver, Trusty needs the same AEKkey to decrypt it. Hence, before Trusty launches, Hypervisor derives the same AEK key from Platform Seed with the same algorithm and the same derivation parameters, then sends this AEK along with Trusty vSeed to Trusty world memory. Since Platform Seed is only visible to Hypervisor and it must not be sent to any guest VM, only Hypervisor can derive this AEK from this Platform Seed, just like previous per-Trusty virtual Seed derivation. Please note that Android Attestation Keybox is shared in a single hardware platform, so all the Trusty instance/world can get the same AEK for decryption even if there are multiple Android User OS/VMs running on top of Hypervisor. v1 --> v2: Add detailed description why we need the patch to derive an extra key v2 --> v3: Convert API descriptions to Doxygen Tracked-On: #1812 Reviewed-by: Bing Zhu <bing.zhu@intel.com> Reviewed-by: Kai Wang <kai.z.wang@intel.com> Signed-off-by: Chen Gang G <gang.g.chen@intel.com> Acked-by: Bing Zhu <bing.zhu@intel.com>
1 parent 7978188 commit fc9ec5d

File tree

6 files changed

+153
-46
lines changed

6 files changed

+153
-46
lines changed

doc/acrn.doxyfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,7 @@ INPUT = custom-doxygen/mainpage.md \
813813
../hypervisor/include/arch/x86/irq.h \
814814
../hypervisor/include/arch/x86/lapic.h \
815815
../hypervisor/include/common/irq.h \
816+
../hypervisor/include/lib/crypto/crypto_api.h \
816817
../devicemodel/include/virtio_kernel.h \
817818
../devicemodel/include/vhost.h \
818819
../devicemodel/include/dm.h \

hypervisor/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ C_SRCS += arch/x86/guest/pm.c
155155
C_SRCS += lib/misc.c
156156
C_SRCS += lib/string.c
157157
C_SRCS += lib/memory.c
158-
C_SRCS += lib/crypto/hkdf_wrap.c
158+
C_SRCS += lib/crypto/crypto_api.c
159159
C_SRCS += lib/crypto/mbedtls/hkdf.c
160160
C_SRCS += lib/crypto/mbedtls/sha256.c
161161
C_SRCS += lib/crypto/mbedtls/md.c

hypervisor/arch/x86/trusty.c

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
#include <hypervisor.h>
8-
#include <hkdf_wrap.h>
8+
#include <crypto_api.h>
99

1010
#define ACRN_DBG_TRUSTY 6U
1111

@@ -334,6 +334,54 @@ void switch_world(struct acrn_vcpu *vcpu, int next_world)
334334
arch->cur_context = next_world;
335335
}
336336

337+
static int32_t get_max_svn_index(void)
338+
{
339+
uint32_t i, max_svn_idx = 0U;
340+
341+
if ((g_key_info.num_seeds == 0U) ||
342+
(g_key_info.num_seeds > BOOTLOADER_SEED_MAX_ENTRIES)) {
343+
return -1;
344+
}
345+
346+
for (i = 1U; i < g_key_info.num_seeds; i++) {
347+
if (g_key_info.dseed_list[i].cse_svn >
348+
g_key_info.dseed_list[i-1].cse_svn) {
349+
max_svn_idx = i;
350+
}
351+
}
352+
353+
return max_svn_idx;
354+
}
355+
356+
static bool derive_aek(uint8_t *attkb_key)
357+
{
358+
const int8_t salt[] = "Attestation Keybox Encryption Key";
359+
const uint8_t *ikm;
360+
uint32_t ikm_len;
361+
int32_t max_svn_idx;
362+
363+
if (!attkb_key) {
364+
return false;
365+
}
366+
367+
max_svn_idx = get_max_svn_index();
368+
if (max_svn_idx < 0) {
369+
return false;
370+
}
371+
372+
ikm = g_key_info.dseed_list[max_svn_idx].seed;
373+
/* only the low 32 bits of seed are valid */
374+
ikm_len = 32;
375+
376+
if (hmac_sha256(attkb_key, ikm, ikm_len,
377+
(const uint8_t *)salt, sizeof(salt)) != 1) {
378+
pr_err("%s: failed to derive key!\n", __func__);
379+
return false;
380+
}
381+
382+
return true;
383+
}
384+
337385
/* Put key_info and trusty_startup_param in the first Page of Trusty
338386
* runtime memory
339387
*/
@@ -368,6 +416,13 @@ static bool setup_trusty_info(struct acrn_vcpu *vcpu,
368416
key_info->dseed_list[i].cse_svn = g_key_info.dseed_list[i].cse_svn;
369417
}
370418

419+
/* Derive decryption key of attestation keybox from dseed */
420+
if (!derive_aek(key_info->attkb_enc_key)) {
421+
(void)memset(key_info, 0U, sizeof(struct trusty_key_info));
422+
pr_err("%s: derive key of att keybox failed!", __func__);
423+
return false;
424+
}
425+
371426
/* Prepare trusty startup param */
372427
mem->first_page.data.startup_param.size_of_this_struct =
373428
sizeof(struct trusty_startup_param);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (C) 2018 Intel Corporation. All rights reserved.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
/**
8+
* @file crypto_api.h
9+
*
10+
* @brief public APIs for crypto functions
11+
*/
12+
13+
#ifndef CRYPTO_API_H
14+
#define CRYPTO_API_H
15+
16+
#include <types.h>
17+
18+
/**
19+
* @brief HMAC-based Extract-and-Expand Key Derivation Function.
20+
*
21+
* @param out_key Pointer to key buffer which is used to save
22+
* hkdf_sha256 result
23+
* @param out_len The length of out_key
24+
* @param secret Pointer to input keying material
25+
* @param secret_len The length of secret
26+
* @param salt Pointer to salt buffer, it is optional
27+
* if not provided (salt == NULL), it is set internally
28+
* to a string of hashlen(32) zeros
29+
* @param salt_len The length of the salt value
30+
* Ignored if salt is NULL
31+
* @param info Pointer to application specific information, it is
32+
* optional. Ignored if info == NULL or a zero-length string
33+
* @param info_len: The length of the info, ignored if info is NULL
34+
*
35+
* @return int 1 - Success 0 - Failure
36+
*/
37+
int hkdf_sha256(uint8_t *out_key, size_t out_len,
38+
const uint8_t *secret, size_t secret_len,
39+
const uint8_t *salt, size_t salt_len,
40+
const uint8_t *info, size_t info_len);
41+
42+
/**
43+
* @brief This function calculates the full generic HMAC
44+
* on the input buffer with the provided key.
45+
*
46+
* The function allocates the context, performs the
47+
* calculation, and frees the context.
48+
*
49+
* The HMAC result is calculated as
50+
* output = generic HMAC(hmac key, input buffer).
51+
*
52+
* @param out_key The generic HMAC result
53+
* @param secret The HMAC secret key
54+
* @param secret_len The length of the HMAC secret key in Bytes
55+
* @param salt The buffer holding the input data
56+
* @param salt_len The length of the input data
57+
*
58+
* @return int 1 - Success 0 - Failure
59+
*/
60+
int hmac_sha256(uint8_t *out_key,
61+
const uint8_t *secret, size_t secret_len,
62+
const uint8_t *salt, size_t salt_len);
63+
64+
#endif /* CRYPTO_API_H */

hypervisor/include/lib/crypto/hkdf_wrap.h

Lines changed: 0 additions & 44 deletions
This file was deleted.

hypervisor/lib/crypto/hkdf_wrap.c renamed to hypervisor/lib/crypto/crypto_api.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <rtl.h>
88
#include "mbedtls/hkdf.h"
9+
#include "mbedtls/md.h"
910

1011
int hkdf_sha256(uint8_t *out_key, size_t out_len,
1112
const uint8_t *secret, size_t secret_len,
@@ -14,6 +15,11 @@ int hkdf_sha256(uint8_t *out_key, size_t out_len,
1415
{
1516
const mbedtls_md_info_t *md;
1617

18+
/* salt and info can be NULL, others can't */
19+
if (!out_key || !secret) {
20+
return 0;
21+
}
22+
1723
md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
1824
if (md == NULL) {
1925
return 0;
@@ -29,3 +35,28 @@ int hkdf_sha256(uint8_t *out_key, size_t out_len,
2935

3036
return 1;
3137
}
38+
39+
int hmac_sha256(uint8_t *out_key,
40+
const uint8_t *secret, size_t secret_len,
41+
const uint8_t *salt, size_t salt_len)
42+
{
43+
const mbedtls_md_info_t *md;
44+
45+
if (!out_key || !secret || !salt) {
46+
return 0;
47+
}
48+
49+
md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
50+
if (md == NULL) {
51+
return 0;
52+
}
53+
54+
if (mbedtls_md_hmac(md,
55+
salt, salt_len,
56+
secret, secret_len,
57+
out_key) != 0) {
58+
return 0;
59+
}
60+
61+
return 1;
62+
}

0 commit comments

Comments
 (0)