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, &params_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. */

 

posted @ 2023-02-14 16:51  xiululu  阅读(31)  评论(0编辑  收藏  举报