optee km4.0 VTS:PerInstance/SigningOperationsTest.NoUserConfirmation/0_default
异常日志:
# ./VtsHalKeymasterV4_0TargetTest --gtest_filter=PerInstance/SigningOperationsTest.NoUserConfirmation/0_default
Note: Google Test filter = PerInstance/SigningOperationsTest.NoUserConfirmation/0_default
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from PerInstance/SigningOperationsTest
[ RUN ] PerInstance/SigningOperationsTest.NoUserConfirmation/0_default
hardware/interfaces/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp:1025: Failure
Expected equality of these values:
ErrorCode::NO_USER_CONFIRMATION
Which is: NO_USER_CONFIRMATION
Finish(message, &signature)
Which is: OK
[ FAILED ] PerInstance/SigningOperationsTest.NoUserConfirmation/0_default, where GetParam() = "default" (3701 ms)
[----------] 1 test from PerInstance/SigningOperationsTest (3701 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (3702 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] PerInstance/SigningOperationsTest.NoUserConfirmation/0_default, where GetParam() = "default"
1 FAILED TEST
对应测试代码:
/* * SigningOperationsTest.NoUserConfirmation * * Verifies that keymaster rejects signing operations for keys with * TRUSTED_CONFIRMATION_REQUIRED and no valid confirmation token * presented. */ TEST_P(SigningOperationsTest, NoUserConfirmation) { if (SecLevel() == SecurityLevel::STRONGBOX) return; ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() .RsaSigningKey(1024, 65537) .Digest(Digest::NONE) .Padding(PaddingMode::NONE) .Authorization(TAG_NO_AUTH_REQUIRED) .Authorization(TAG_TRUSTED_CONFIRMATION_REQUIRED))); const string message = "12345678901234567890123456789012"; EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE))); string signature; EXPECT_EQ(ErrorCode::NO_USER_CONFIRMATION, Finish(message, &signature)); }
相关说明:
hardware/interfaces/keymaster/4.0/types.hal
/** Tag::TRUSTED_CONFIRMATION_REQUIRED is only applicable to keys with KeyPurpose SIGN, and
* specifies that this key must not be usable unless the user provides confirmation of the data
* to be signed. Confirmation is proven to keymaster via an approval token. See
* CONFIRMATION_TOKEN, as well as the ConfirmatinUI HAL.
*
* If an attempt to use a key with this tag does not have a cryptographically valid
* CONFIRMATION_TOKEN provided to finish() or if the data provided to update()/finish() does not
* match the data described in the token, keymaster must return NO_USER_CONFIRMATION.
*
* Must be hardware-enforced.
*/
TRUSTED_CONFIRMATION_REQUIRED = TagType:BOOL | 508,
/**
* Tag::CONFIRMATION_TOKEN is used to deliver a cryptographic token proving that the user
* confirmed a signing request. The content is a full-length HMAC-SHA256 value. See the
* ConfirmationUI HAL for details of token computation.
*
* Must never appear in KeyCharacteristics.
*/
CONFIRMATION_TOKEN = TagType:BYTES | 1005,
finish操作:
struct FinishOperationRequest : public KeymasterMessage { explicit FinishOperationRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} size_t SerializedSize() const override; uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override; bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override; keymaster_operation_handle_t op_handle; Buffer input; Buffer signature; AuthorizationSet additional_params; };
FinishOperationRequest的序列化:
uint8_t* FinishOperationRequest::Serialize(uint8_t* buf, const uint8_t* end) const { buf = append_uint64_to_buf(buf, end, op_handle); buf = signature.Serialize(buf, end); if (message_version > 0) buf = additional_params.Serialize(buf, end); if (message_version > 2) buf = input.Serialize(buf, end); return buf; }
TA_finish操作反序列化和解blob过程:
in += TA_deserialize_op_handle(in, in_end, &operation_handle, &res); if (res != KM_ERROR_OK) { goto out; } in += TA_deserialize_blob_akms(in, in_end, &signature, false, &res, false); if (res != KM_ERROR_OK) { goto out; } in += TA_deserialize_auth_set(in, in_end, &in_params, false, &res); if (res != KM_ERROR_OK) { goto out; } in += TA_deserialize_blob_akms(in, in_end, &input, false, &res, true); if (res != KM_ERROR_OK) { goto out; } res = TA_get_operation(operation_handle, &operation); if (res != KM_ERROR_OK) { goto out; } key_material = TEE_Malloc(operation.key->key_material_size, TEE_MALLOC_FILL_ZERO); res = TA_restore_key(key_material, operation.key, &key_size, &type, &obj_h, ¶ms_t);
解决方法:
参考VTS用例,params_t和in_params中token进行比较。判定条件包括Key purpose为sign,token比较是否一致。
代码如下:
该函数为本地新增,在TA_finish中被调用。
1 keymaster_error_t TA_check_confirmation_token(const keymaster_key_param_set_t *key_params, 2 const keymaster_key_param_set_t *in_params, 3 const keymaster_purpose_t op_purpose) 4 { 5 keymaster_error_t res = KM_ERROR_OK; 6 bool confirmation_token_need_check = false; 7 bool confirmation_token_check_res = false; 8 keymaster_blob_t token = {.data = NULL, .data_length = 0}; 9 DMSG("purpose = %d", op_purpose); 10 if (op_purpose != KM_PURPOSE_SIGN) { 11 return res; 12 } 13 for (size_t i = 0; i < key_params->length; i++) { 14 DMSG("in_params->params[%zu].tag = 0x%x", 15 i, key_params->params[i].tag); 16 switch (key_params->params[i].tag) { 17 case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED: 18 DMSG("KM_TAG_TRUSTED_CONFIRMATION_REQUIRED"); 19 confirmation_token_need_check = true; 20 break; 21 case KM_TAG_CONFIRMATION_TOKEN: 22 DMSG("KM_TAG_CONFIRMATION_TOKEN"); 23 token = key_params->params[i].key_param.blob; 24 break; 25 default: 26 DMSG("Unused parameter with tag 0x%x", 27 key_params->params[i].tag); 28 break; 29 } 30 } 31 for (size_t j = 0; j < in_params->length; j++) { 32 DMSG("in_params->params[%zu].tag = 0x%x", 33 j, in_params->params[j].tag); 34 switch (in_params->params[j].tag) { 35 case KM_TAG_CONFIRMATION_TOKEN: 36 DMSG("KM_TAG_CONFIRMATION_TOKEN"); 37 confirmation_token_check_res = !cmpBlobParam(token, 38 in_params->params[j]); 39 break; 40 default: 41 DMSG("Unused parameter with tag 0x%x", 42 in_params->params[j].tag); 43 break; 44 } 45 } 46 47 DMSG("confirmation_token_need_check = %d, confirmation_token_check_res = %d", 48 confirmation_token_need_check, confirmation_token_check_res); 49 if (confirmation_token_need_check && !confirmation_token_check_res) { 50 res = KM_ERROR_NO_USER_CONFIRMATION; 51 } 52 return res; 53 }
测试结果:
# ./VtsHalKeymasterV4_0TargetTest --gtest_filter=PerInstance/SigningOperationsTest.NoUserConfirmation/0_default
Note: Google Test filter = PerInstance/SigningOperationsTest.NoUserConfirmation/0_default
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from PerInstance/SigningOperationsTest
[ RUN ] PerInstance/SigningOperationsTest.NoUserConfirmation/0_default
[ OK ] PerInstance/SigningOperationsTest.NoUserConfirmation/0_default (3263 ms)
[----------] 1 test from PerInstance/SigningOperationsTest (3263 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (3263 ms total)
[ PASSED ] 1 test.
补充:
ta_ca_defs.h中增加部分定义:
KM_ERROR_NO_USER_CONFIRMATION = -71, KM_TAG_CONFIRMATION_TOKEN = KM_BYTES | 1005, /* Tag::CONFIRMATION_TOKEN is used to deliver a cryptographic token proving that the user confirmed a signing request. The content is a full-length HMAC-SHA256 value. See the ConfirmationUI HAL for details of token computation. Must never appear in KeyCharacteristics. */