/*
* Copyright ( C ) 2022 The Android Open Source Project
*
* Licensed under the Apache License , Version 2 . 0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
*/
#define TLOG_TAG "hwbcc-test"
#include <cppbor.h>
#include <cppbor_parse.h>
#include <dice/config.h>
#include <dice/dice.h>
#include <lib/hwbcc/client/hwbcc.h>
#include <lib/hwbcc/common/common.h>
#include <lib/hwbcc/common/swbcc.h>
#include <lib/system_state/system_state.h>
#include <openssl/curve25519.h>
#include <trusty_unittest.h>
#include <uapi/err.h>
#include <array>
#include <vector>
typedef struct {
swbcc_session_t s;
} swbcc_t;
/* UUID of this test TA: {0e109d31-8bbe-47d6-bb47-e1dd08910e16} */
static const struct uuid self_uuid = {
0 x0e109d31,
0 x8bbe,
0 x47d6,
{0 xbb, 0 x47, 0 xe1, 0 xdd, 0 x08, 0 x91, 0 x0e, 0 x16},
};
static const std::array<uint8_t, HWBCC_MAX_DATA_TO_SIGN_SIZE> test_data = {};
static const uint8_t test_aad[] = {0 xcf, 0 xe1, 0 x89, 0 x39, 0 xb1,
0 x72, 0 xbf, 0 x4f, 0 xa8, 0 x0f};
TEST_F_SETUP(swbcc) {
_state->s = 0 ;
int rc = swbcc_init(&_state->s, &self_uuid);
ASSERT_EQ(rc, 0 );
test_abort:;
}
TEST_F_TEARDOWN(swbcc) {
swbcc_close(_state->s);
}
TEST_F(swbcc, get_client) {
struct uuid client;
swbcc_get_client(_state->s, &client);
ASSERT_EQ(memcmp(&client, &self_uuid, sizeof (struct uuid)), 0 );
test_abort:;
}
TEST_F(swbcc, mac) {
int rc;
uint8_t cose_sign1[HWBCC_MAX_RESP_PAYLOAD_SIZE];
size_t cose_sign1_size = 0 ;
memset(cose_sign1, 0 , sizeof (cose_sign1));
rc = swbcc_sign_key(_state->s, true , HWBCC_ALGORITHM_ED25519,
test_data.data(), test_data.size(), test_aad,
sizeof (test_aad), cose_sign1, sizeof (cose_sign1),
&cose_sign1_size);
ASSERT_EQ(rc, 0 );
ASSERT_GT(cose_sign1_size, 0 );
/* TODO: Check contents of cose_sign1. */
test_abort:;
}
TEST_F(swbcc, bcc) {
int rc;
uint8_t bcc[HWBCC_MAX_RESP_PAYLOAD_SIZE];
size_t bcc_size = 0 ;
std::vector<PubKey> keys;
uint8_t* dk_pub_key;
uint8_t* km_pub_key;
memset(bcc, 0 , sizeof (bcc));
rc = swbcc_get_bcc(_state->s, true , bcc, sizeof (bcc), &bcc_size);
ASSERT_EQ(rc, 0 );
ASSERT_GT(bcc_size, 0 );
ASSERT_EQ(validate_bcc_impl(bcc, bcc_size, &keys), true );
/* Only a degenerate self-signed BCC is currently supported. */
ASSERT_EQ(keys.size(), 2 );
dk_pub_key = keys[0 ].data();
km_pub_key = keys[1 ].data();
ASSERT_EQ(memcmp(dk_pub_key, km_pub_key, ED25519_PUBLIC_KEY_LEN), 0 );
test_abort:;
}
/* Check that test mode yields different output every time */
TEST(hwbcc, protected_data_test_mode) {
int rc;
uint8_t cose_sign1[HWBCC_MAX_RESP_PAYLOAD_SIZE];
size_t cose_sign1_size;
uint8_t bcc[HWBCC_MAX_RESP_PAYLOAD_SIZE];
size_t bcc_size;
std::vector<PubKey> keys1;
std::vector<PubKey> keys2;
/* Get first set of keys */
memset(cose_sign1, 0 , sizeof (cose_sign1));
memset(bcc, 0 , sizeof (bcc));
rc = hwbcc_get_protected_data(
true , HWBCC_ALGORITHM_ED25519, test_data.data(), test_data.size(),
test_aad, sizeof (test_aad), cose_sign1, sizeof (cose_sign1),
&cose_sign1_size, bcc, sizeof (bcc), &bcc_size);
ASSERT_EQ(rc, 0 );
ASSERT_GT(cose_sign1_size, 0 );
ASSERT_GT(bcc_size, 0 );
ASSERT_EQ(validate_bcc_impl(bcc, bcc_size, &keys1), true );
/* Get second set of keys */
memset(cose_sign1, 0 , sizeof (cose_sign1));
memset(bcc, 0 , sizeof (bcc));
rc = hwbcc_get_protected_data(
true , HWBCC_ALGORITHM_ED25519, test_data.data(), test_data.size(),
test_aad, sizeof (test_aad), cose_sign1, sizeof (cose_sign1),
&cose_sign1_size, bcc, sizeof (bcc), &bcc_size);
ASSERT_EQ(rc, 0 );
ASSERT_GT(cose_sign1_size, 0 );
ASSERT_GT(bcc_size, 0 );
ASSERT_EQ(validate_bcc_impl(bcc, bcc_size, &keys2), true );
/* The two sets of keys must be different in test mode. */
ASSERT_NE(memcmp(keys1[0 ].data(), keys2[0 ].data(), ED25519_PUBLIC_KEY_LEN),
0 );
ASSERT_NE(memcmp(keys1[1 ].data(), keys2[1 ].data(), ED25519_PUBLIC_KEY_LEN),
0 );
test_abort:;
}
/*
* Macro to enable test cases for generic ARM64 platform only .
* ( This includes generic_arm32 targets too ) .
*/
#if defined (PLATFORM_GENERIC_ARM64)
#define GENERIC_ARM64_PLATFORM_ONLY_TEST(name) name
#else
#define GENERIC_ARM64_PLATFORM_ONLY_TEST(name) DISABLED_## name
#endif
/*
* Device key is hard - coded on emulator targets , i . e . BCC keys are fixed too .
* We test that BCC keys don ' t change to make sure that we don ' t accidentally
* change the key derivation procedure .
*/
static const uint8_t emulator_pub_key[ED25519_PUBLIC_KEY_LEN] = {
0 xc0, 0 xdd, 0 x6c, 0 xf4, 0 x3e, 0 x66, 0 x15, 0 xc7, 0 x4d, 0 x23, 0 xb8,
0 x96, 0 x11, 0 x11, 0 xc9, 0 x88, 0 x07, 0 x92, 0 x2c, 0 x8f, 0 x32, 0 xf6,
0 x79, 0 x85, 0 x86, 0 x36, 0 xad, 0 xbd, 0 x20, 0 xf0, 0 x9b, 0 x21};
TEST(hwbcc, GENERIC_ARM64_PLATFORM_ONLY_TEST(protected_data)) {
int rc;
uint8_t cose_sign1[HWBCC_MAX_RESP_PAYLOAD_SIZE];
size_t cose_sign1_size;
uint8_t bcc[HWBCC_MAX_RESP_PAYLOAD_SIZE];
size_t bcc_size;
std::vector<PubKey> keys;
uint8_t* dk_pub_key;
uint8_t* km_pub_key;
memset(cose_sign1, 0 , sizeof (cose_sign1));
memset(bcc, 0 , sizeof (bcc));
rc = hwbcc_get_protected_data(
false , HWBCC_ALGORITHM_ED25519, test_data.data(), test_data.size(),
test_aad, sizeof (test_aad), cose_sign1, sizeof (cose_sign1),
&cose_sign1_size, bcc, sizeof (bcc), &bcc_size);
ASSERT_EQ(rc, 0 );
ASSERT_GT(cose_sign1_size, 0 );
ASSERT_GT(bcc_size, 0 );
ASSERT_EQ(validate_bcc_impl(bcc, bcc_size, &keys), true );
ASSERT_EQ(keys.size(), 2 );
dk_pub_key = keys[0 ].data();
km_pub_key = keys[1 ].data();
ASSERT_EQ(memcmp(emulator_pub_key, dk_pub_key, ED25519_PUBLIC_KEY_LEN), 0 );
ASSERT_EQ(memcmp(dk_pub_key, km_pub_key, ED25519_PUBLIC_KEY_LEN), 0 );
test_abort:;
}
static const uint8_t emulator_cdi_attest[DICE_CDI_SIZE] = {
0 x44, 0 x26, 0 x69, 0 x94, 0 x02, 0 x34, 0 x1c, 0 xc8, 0 x1d, 0 x93, 0 xc7,
0 xb8, 0 x47, 0 xaf, 0 x55, 0 xe8, 0 xde, 0 x8e, 0 x79, 0 x4c, 0 x1b, 0 x0f,
0 xea, 0 x99, 0 x7f, 0 x91, 0 x83, 0 x83, 0 x7f, 0 x26, 0 x7f, 0 x93};
static const uint8_t emulator_cdi_seal[DICE_CDI_SIZE] = {
0 xf7, 0 xe5, 0 xb0, 0 x2b, 0 xd0, 0 xfa, 0 x4d, 0 x5b, 0 xfa, 0 xd8, 0 x16,
0 x24, 0 xfa, 0 xc8, 0 x50, 0 xac, 0 x4f, 0 x1a, 0 x3d, 0 xb4, 0 xbc, 0 x02,
0 xc9, 0 xfd, 0 xeb, 0 xfe, 0 x26, 0 xfc, 0 x28, 0 x98, 0 x5b, 0 xe8,
};
/**
* Test the two CDIs : CDI_Attest and CDI_Seal ; and the UDS included
* in the BCC , all of which are retrieved from get_dice_artifacts , with those
* values specific to ARM64 emulator , given that the hwkey for the emulator
* is hardcoded .
*/
TEST(hwbcc, GENERIC_ARM64_PLATFORM_ONLY_TEST(test_get_dice_artifacts)) {
int rc;
uint8_t dice_artifacts[HWBCC_MAX_RESP_PAYLOAD_SIZE];
size_t dice_artifacts_size;
CDI next_cdi_attest;
CDI next_cdi_seal;
/**
* dice_artifacts expects the following CBOR encoded structure .
* Since the implementation of hwbcc_get_dice_artifacts serves only the
* non - secure world , Bcc is not present in the returned dice_artifacts .
* We calculate the expected size , including CBOR header sizes .
* BccHandover = {
* 1 : bstr . size 32 , // CDI_Attest
* 2 : bstr . size 32 , // CDI_Seal
* ? 3 : Bcc , // Cert_Chain
* }
* Bcc = [
* PubKeyEd25519 , // UDS
* + BccEntry , // Root -> leaf
* ]
*/
size_t bcc_handover_size = 2 * DICE_CDI_SIZE + 7 /*CBOR tags*/;
memset(dice_artifacts, 0 , sizeof (dice_artifacts));
rc = hwbcc_get_dice_artifacts(0 , dice_artifacts, sizeof (dice_artifacts),
&dice_artifacts_size);
ASSERT_EQ(rc, 0 );
ASSERT_GT(dice_artifacts_size, 0 );
ASSERT_EQ(dice_artifacts_size, bcc_handover_size);
ASSERT_EQ(validate_bcc_handover_impl(dice_artifacts, dice_artifacts_size,
&next_cdi_attest, &next_cdi_seal),
true );
if (system_state_app_loading_unlocked()) {
ASSERT_EQ(memcmp(emulator_cdi_attest, next_cdi_attest.data(),
DICE_CDI_SIZE),
0 );
ASSERT_EQ(
memcmp(emulator_cdi_seal, next_cdi_seal.data(), DICE_CDI_SIZE),
0 );
}
test_abort:;
}
/**
* Test that ns_deprivilege does not block the calls to hwbcc from Trusty Apps
* such as this test TA .
*/
TEST(hwbcc, test_ns_deprivilege) {
int rc;
uint8_t dice_artifacts[HWBCC_MAX_RESP_PAYLOAD_SIZE];
size_t dice_artifacts_size;
rc = hwbcc_ns_deprivilege();
ASSERT_EQ(rc, 0 );
/* ns_deprivilege should not block calls from secure world. */
memset(dice_artifacts, 0 , sizeof (dice_artifacts));
dice_artifacts_size = 0 ;
rc = hwbcc_get_dice_artifacts(0 , dice_artifacts, sizeof (dice_artifacts),
&dice_artifacts_size);
ASSERT_EQ(rc, 0 );
test_abort:;
}
PORT_TEST(hwbcc, "com.android.trusty.hwbcc.test" );
Messung V0.5 in Prozent C=90 H=88 G=88
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-06-26)
¤
*© Formatika GbR, Deutschland