mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
This change clarifies the language to specify that StrongBox devices must only support key sizes of 128 and 256. Additionally, it changes the new AesInvalidKeySize test to only enforce against StrongBox instances on devices that launch on S or later, not previously launched devices. Ignore-AOSP-First: CP to AOSP Bug: 191736606 Test: Test passes on a StrongBox enabled device Change-Id: I1a27a0d61e5247ad90c8f5b1423f2a1567016bac
758 lines
32 KiB
C++
758 lines
32 KiB
C++
/*
|
|
* Copyright (C) 2017 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.
|
|
*/
|
|
|
|
#include "KeymasterHidlTest.h"
|
|
|
|
#include <chrono>
|
|
#include <vector>
|
|
|
|
#include <android-base/logging.h>
|
|
#include <android/hidl/manager/1.0/IServiceManager.h>
|
|
#include <cutils/properties.h>
|
|
|
|
#include <keymasterV4_0/key_param_output.h>
|
|
#include <keymasterV4_0/keymaster_utils.h>
|
|
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace keymaster {
|
|
namespace V4_0 {
|
|
|
|
::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set) {
|
|
if (set.size() == 0)
|
|
os << "(Empty)" << ::std::endl;
|
|
else {
|
|
os << "\n";
|
|
for (size_t i = 0; i < set.size(); ++i) os << set[i] << ::std::endl;
|
|
}
|
|
return os;
|
|
}
|
|
|
|
namespace test {
|
|
|
|
using namespace std::literals::chrono_literals;
|
|
|
|
void KeymasterHidlTest::InitializeKeymaster(sp<IKeymasterDevice> keymaster) {
|
|
ASSERT_NE(keymaster, nullptr);
|
|
keymaster_ = keymaster;
|
|
ASSERT_TRUE(keymaster_
|
|
->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& name,
|
|
const hidl_string& author) {
|
|
securityLevel_ = securityLevel;
|
|
name_ = name;
|
|
author_ = author;
|
|
})
|
|
.isOk());
|
|
|
|
os_version_ = support::getOsVersion();
|
|
os_patch_level_ = support::getOsPatchlevel();
|
|
}
|
|
|
|
void KeymasterHidlTest::SetUp() {
|
|
InitializeKeymaster(IKeymasterDevice::getService(GetParam()));
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::GenerateKey(const AuthorizationSet& key_desc, HidlBuf* key_blob,
|
|
KeyCharacteristics* key_characteristics) {
|
|
EXPECT_NE(key_blob, nullptr) << "Key blob pointer must not be null. Test bug";
|
|
EXPECT_EQ(0U, key_blob->size()) << "Key blob not empty before generating key. Test bug.";
|
|
EXPECT_NE(key_characteristics, nullptr)
|
|
<< "Previous characteristics not deleted before generating key. Test bug.";
|
|
|
|
ErrorCode error;
|
|
EXPECT_TRUE(keymaster_
|
|
->generateKey(key_desc.hidl_data(),
|
|
[&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
|
|
const KeyCharacteristics& hidl_key_characteristics) {
|
|
error = hidl_error;
|
|
*key_blob = hidl_key_blob;
|
|
*key_characteristics = hidl_key_characteristics;
|
|
})
|
|
.isOk());
|
|
// On error, blob & characteristics should be empty.
|
|
if (error != ErrorCode::OK) {
|
|
EXPECT_EQ(0U, key_blob->size());
|
|
EXPECT_EQ(0U, (key_characteristics->softwareEnforced.size() +
|
|
key_characteristics->hardwareEnforced.size()));
|
|
}
|
|
return error;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::GenerateKey(const AuthorizationSet& key_desc) {
|
|
return GenerateKey(key_desc, &key_blob_, &key_characteristics_);
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
|
|
const string& key_material, HidlBuf* key_blob,
|
|
KeyCharacteristics* key_characteristics) {
|
|
ErrorCode error;
|
|
EXPECT_TRUE(keymaster_
|
|
->importKey(key_desc.hidl_data(), format, HidlBuf(key_material),
|
|
[&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
|
|
const KeyCharacteristics& hidl_key_characteristics) {
|
|
error = hidl_error;
|
|
*key_blob = hidl_key_blob;
|
|
*key_characteristics = hidl_key_characteristics;
|
|
})
|
|
.isOk());
|
|
// On error, blob & characteristics should be empty.
|
|
if (error != ErrorCode::OK) {
|
|
EXPECT_EQ(0U, key_blob->size());
|
|
EXPECT_EQ(0U, (key_characteristics->softwareEnforced.size() +
|
|
key_characteristics->hardwareEnforced.size()));
|
|
}
|
|
return error;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
|
|
const string& key_material) {
|
|
return ImportKey(key_desc, format, key_material, &key_blob_, &key_characteristics_);
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::ImportWrappedKey(string wrapped_key, string wrapping_key,
|
|
const AuthorizationSet& wrapping_key_desc,
|
|
string masking_key,
|
|
const AuthorizationSet& unwrapping_params) {
|
|
ErrorCode error;
|
|
EXPECT_EQ(ErrorCode::OK, ImportKey(wrapping_key_desc, KeyFormat::PKCS8, wrapping_key));
|
|
EXPECT_TRUE(keymaster_
|
|
->importWrappedKey(HidlBuf(wrapped_key), key_blob_, HidlBuf(masking_key),
|
|
unwrapping_params.hidl_data(), 0 /* passwordSid */,
|
|
0 /* biometricSid */,
|
|
[&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
|
|
const KeyCharacteristics& hidl_key_characteristics) {
|
|
error = hidl_error;
|
|
key_blob_ = hidl_key_blob;
|
|
key_characteristics_ = hidl_key_characteristics;
|
|
})
|
|
.isOk());
|
|
return error;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::ExportKey(KeyFormat format, const HidlBuf& key_blob,
|
|
const HidlBuf& client_id, const HidlBuf& app_data,
|
|
HidlBuf* key_material) {
|
|
ErrorCode error;
|
|
EXPECT_TRUE(keymaster_
|
|
->exportKey(format, key_blob, client_id, app_data,
|
|
[&](ErrorCode hidl_error_code, const HidlBuf& hidl_key_material) {
|
|
error = hidl_error_code;
|
|
*key_material = hidl_key_material;
|
|
})
|
|
.isOk());
|
|
// On error, blob should be empty.
|
|
if (error != ErrorCode::OK) {
|
|
EXPECT_EQ(0U, key_material->size());
|
|
}
|
|
return error;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::ExportKey(KeyFormat format, HidlBuf* key_material) {
|
|
HidlBuf client_id, app_data;
|
|
return ExportKey(format, key_blob_, client_id, app_data, key_material);
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::DeleteKey(HidlBuf* key_blob, bool keep_key_blob) {
|
|
auto rc = keymaster_->deleteKey(*key_blob);
|
|
if (!keep_key_blob) *key_blob = HidlBuf();
|
|
if (!rc.isOk()) return ErrorCode::UNKNOWN_ERROR;
|
|
return rc;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::DeleteKey(bool keep_key_blob) {
|
|
return DeleteKey(&key_blob_, keep_key_blob);
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::DeleteAllKeys() {
|
|
ErrorCode error = keymaster_->deleteAllKeys();
|
|
return error;
|
|
}
|
|
|
|
void KeymasterHidlTest::CheckedDeleteKey(HidlBuf* key_blob, bool keep_key_blob) {
|
|
auto rc = DeleteKey(key_blob, keep_key_blob);
|
|
EXPECT_TRUE(rc == ErrorCode::OK || rc == ErrorCode::UNIMPLEMENTED);
|
|
}
|
|
|
|
void KeymasterHidlTest::CheckedDeleteKey() {
|
|
CheckedDeleteKey(&key_blob_);
|
|
}
|
|
|
|
void KeymasterHidlTest::CheckGetCharacteristics(const HidlBuf& key_blob, const HidlBuf& client_id,
|
|
const HidlBuf& app_data,
|
|
KeyCharacteristics* key_characteristics) {
|
|
HidlBuf empty_buf = {};
|
|
EXPECT_EQ(ErrorCode::OK,
|
|
GetCharacteristics(key_blob, client_id, app_data, key_characteristics));
|
|
if (SecLevel() != SecurityLevel::SOFTWARE) {
|
|
EXPECT_GT(key_characteristics->hardwareEnforced.size(), 0);
|
|
}
|
|
EXPECT_GT(key_characteristics->softwareEnforced.size(), 0);
|
|
|
|
EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
|
|
GetCharacteristics(key_blob, empty_buf, app_data, key_characteristics));
|
|
EXPECT_EQ(key_characteristics->hardwareEnforced.size(), 0);
|
|
EXPECT_EQ(key_characteristics->softwareEnforced.size(), 0);
|
|
|
|
EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
|
|
GetCharacteristics(key_blob, client_id, empty_buf, key_characteristics));
|
|
EXPECT_EQ(key_characteristics->hardwareEnforced.size(), 0);
|
|
EXPECT_EQ(key_characteristics->softwareEnforced.size(), 0);
|
|
|
|
EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
|
|
GetCharacteristics(key_blob, empty_buf, empty_buf, key_characteristics));
|
|
EXPECT_EQ(key_characteristics->hardwareEnforced.size(), 0);
|
|
EXPECT_EQ(key_characteristics->softwareEnforced.size(), 0);
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::GetCharacteristics(const HidlBuf& key_blob, const HidlBuf& client_id,
|
|
const HidlBuf& app_data,
|
|
KeyCharacteristics* key_characteristics) {
|
|
ErrorCode error = ErrorCode::UNKNOWN_ERROR;
|
|
EXPECT_TRUE(
|
|
keymaster_
|
|
->getKeyCharacteristics(
|
|
key_blob, client_id, app_data,
|
|
[&](ErrorCode hidl_error, const KeyCharacteristics& hidl_key_characteristics) {
|
|
error = hidl_error, *key_characteristics = hidl_key_characteristics;
|
|
})
|
|
.isOk());
|
|
return error;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::GetCharacteristics(const HidlBuf& key_blob,
|
|
KeyCharacteristics* key_characteristics) {
|
|
HidlBuf client_id, app_data;
|
|
return GetCharacteristics(key_blob, client_id, app_data, key_characteristics);
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::GetDebugInfo(DebugInfo* debug_info) {
|
|
EXPECT_TRUE(keymaster_->getDebugInfo([&](const DebugInfo& hidl_debug_info) {
|
|
*debug_info = hidl_debug_info;
|
|
}).isOk());
|
|
return ErrorCode::OK;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::Begin(KeyPurpose purpose, const HidlBuf& key_blob,
|
|
const AuthorizationSet& in_params, AuthorizationSet* out_params,
|
|
OperationHandle* op_handle) {
|
|
SCOPED_TRACE("Begin");
|
|
ErrorCode error;
|
|
OperationHandle saved_handle = *op_handle;
|
|
EXPECT_TRUE(keymaster_
|
|
->begin(purpose, key_blob, in_params.hidl_data(), HardwareAuthToken(),
|
|
[&](ErrorCode hidl_error, const hidl_vec<KeyParameter>& hidl_out_params,
|
|
uint64_t hidl_op_handle) {
|
|
error = hidl_error;
|
|
*out_params = hidl_out_params;
|
|
*op_handle = hidl_op_handle;
|
|
})
|
|
.isOk());
|
|
if (error != ErrorCode::OK) {
|
|
// Some implementations may modify *op_handle on error.
|
|
*op_handle = saved_handle;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::Begin(KeyPurpose purpose, const AuthorizationSet& in_params,
|
|
AuthorizationSet* out_params) {
|
|
SCOPED_TRACE("Begin");
|
|
EXPECT_EQ(kOpHandleSentinel, op_handle_);
|
|
return Begin(purpose, key_blob_, in_params, out_params, &op_handle_);
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::Begin(KeyPurpose purpose, const AuthorizationSet& in_params) {
|
|
SCOPED_TRACE("Begin");
|
|
AuthorizationSet out_params;
|
|
ErrorCode error = Begin(purpose, in_params, &out_params);
|
|
EXPECT_TRUE(out_params.empty());
|
|
return error;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::Update(OperationHandle op_handle, const AuthorizationSet& in_params,
|
|
const string& input, AuthorizationSet* out_params,
|
|
string* output, size_t* input_consumed) {
|
|
SCOPED_TRACE("Update");
|
|
ErrorCode error;
|
|
EXPECT_TRUE(keymaster_
|
|
->update(op_handle, in_params.hidl_data(), HidlBuf(input), HardwareAuthToken(),
|
|
VerificationToken(),
|
|
[&](ErrorCode hidl_error, uint32_t hidl_input_consumed,
|
|
const hidl_vec<KeyParameter>& hidl_out_params,
|
|
const HidlBuf& hidl_output) {
|
|
error = hidl_error;
|
|
out_params->push_back(AuthorizationSet(hidl_out_params));
|
|
output->append(hidl_output.to_string());
|
|
*input_consumed = hidl_input_consumed;
|
|
})
|
|
.isOk());
|
|
return error;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::Update(const string& input, string* out, size_t* input_consumed) {
|
|
SCOPED_TRACE("Update");
|
|
AuthorizationSet out_params;
|
|
ErrorCode error = Update(op_handle_, AuthorizationSet() /* in_params */, input, &out_params,
|
|
out, input_consumed);
|
|
EXPECT_TRUE(out_params.empty());
|
|
return error;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::Finish(OperationHandle op_handle, const AuthorizationSet& in_params,
|
|
const string& input, const string& signature,
|
|
AuthorizationSet* out_params, string* output) {
|
|
SCOPED_TRACE("Finish");
|
|
ErrorCode error;
|
|
EXPECT_TRUE(
|
|
keymaster_
|
|
->finish(op_handle, in_params.hidl_data(), HidlBuf(input), HidlBuf(signature),
|
|
HardwareAuthToken(), VerificationToken(),
|
|
[&](ErrorCode hidl_error, const hidl_vec<KeyParameter>& hidl_out_params,
|
|
const HidlBuf& hidl_output) {
|
|
error = hidl_error;
|
|
*out_params = hidl_out_params;
|
|
output->append(hidl_output.to_string());
|
|
})
|
|
.isOk());
|
|
op_handle_ = kOpHandleSentinel; // So dtor doesn't Abort().
|
|
return error;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::Finish(const string& message, string* output) {
|
|
SCOPED_TRACE("Finish");
|
|
AuthorizationSet out_params;
|
|
string finish_output;
|
|
ErrorCode error = Finish(op_handle_, AuthorizationSet() /* in_params */, message,
|
|
"" /* signature */, &out_params, output);
|
|
if (error != ErrorCode::OK) {
|
|
return error;
|
|
}
|
|
EXPECT_EQ(0U, out_params.size());
|
|
return error;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::Finish(const string& message, const string& signature,
|
|
string* output) {
|
|
SCOPED_TRACE("Finish");
|
|
AuthorizationSet out_params;
|
|
ErrorCode error = Finish(op_handle_, AuthorizationSet() /* in_params */, message, signature,
|
|
&out_params, output);
|
|
op_handle_ = kOpHandleSentinel; // So dtor doesn't Abort().
|
|
if (error != ErrorCode::OK) {
|
|
return error;
|
|
}
|
|
EXPECT_EQ(0U, out_params.size());
|
|
return error;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::Abort(OperationHandle op_handle) {
|
|
SCOPED_TRACE("Abort");
|
|
auto retval = keymaster_->abort(op_handle);
|
|
EXPECT_TRUE(retval.isOk());
|
|
return retval;
|
|
}
|
|
|
|
void KeymasterHidlTest::AbortIfNeeded() {
|
|
SCOPED_TRACE("AbortIfNeeded");
|
|
if (op_handle_ != kOpHandleSentinel) {
|
|
EXPECT_EQ(ErrorCode::OK, Abort(op_handle_));
|
|
op_handle_ = kOpHandleSentinel;
|
|
}
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::AttestKey(const HidlBuf& key_blob,
|
|
const AuthorizationSet& attest_params,
|
|
hidl_vec<hidl_vec<uint8_t>>* cert_chain) {
|
|
SCOPED_TRACE("AttestKey");
|
|
ErrorCode error;
|
|
auto rc = keymaster_->attestKey(
|
|
key_blob, attest_params.hidl_data(),
|
|
[&](ErrorCode hidl_error, const hidl_vec<hidl_vec<uint8_t>>& hidl_cert_chain) {
|
|
error = hidl_error;
|
|
*cert_chain = hidl_cert_chain;
|
|
});
|
|
|
|
EXPECT_TRUE(rc.isOk()) << rc.description();
|
|
if (!rc.isOk()) return ErrorCode::UNKNOWN_ERROR;
|
|
|
|
return error;
|
|
}
|
|
|
|
ErrorCode KeymasterHidlTest::AttestKey(const AuthorizationSet& attest_params,
|
|
hidl_vec<hidl_vec<uint8_t>>* cert_chain) {
|
|
SCOPED_TRACE("AttestKey");
|
|
return AttestKey(key_blob_, attest_params, cert_chain);
|
|
}
|
|
|
|
string KeymasterHidlTest::ProcessMessage(const HidlBuf& key_blob, KeyPurpose operation,
|
|
const string& message, const AuthorizationSet& in_params,
|
|
AuthorizationSet* out_params) {
|
|
SCOPED_TRACE("ProcessMessage");
|
|
AuthorizationSet begin_out_params;
|
|
EXPECT_EQ(ErrorCode::OK, Begin(operation, key_blob, in_params, &begin_out_params, &op_handle_));
|
|
|
|
string output;
|
|
size_t consumed = 0;
|
|
AuthorizationSet update_params;
|
|
AuthorizationSet update_out_params;
|
|
EXPECT_EQ(ErrorCode::OK,
|
|
Update(op_handle_, update_params, message, &update_out_params, &output, &consumed));
|
|
|
|
string unused;
|
|
AuthorizationSet finish_params;
|
|
AuthorizationSet finish_out_params;
|
|
EXPECT_EQ(ErrorCode::OK, Finish(op_handle_, finish_params, message.substr(consumed), unused,
|
|
&finish_out_params, &output));
|
|
op_handle_ = kOpHandleSentinel;
|
|
|
|
out_params->push_back(begin_out_params);
|
|
out_params->push_back(finish_out_params);
|
|
return output;
|
|
}
|
|
|
|
string KeymasterHidlTest::SignMessage(const HidlBuf& key_blob, const string& message,
|
|
const AuthorizationSet& params) {
|
|
SCOPED_TRACE("SignMessage");
|
|
AuthorizationSet out_params;
|
|
string signature = ProcessMessage(key_blob, KeyPurpose::SIGN, message, params, &out_params);
|
|
EXPECT_TRUE(out_params.empty());
|
|
return signature;
|
|
}
|
|
|
|
string KeymasterHidlTest::SignMessage(const string& message, const AuthorizationSet& params) {
|
|
SCOPED_TRACE("SignMessage");
|
|
return SignMessage(key_blob_, message, params);
|
|
}
|
|
|
|
string KeymasterHidlTest::MacMessage(const string& message, Digest digest, size_t mac_length) {
|
|
SCOPED_TRACE("MacMessage");
|
|
return SignMessage(
|
|
key_blob_, message,
|
|
AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
|
|
}
|
|
|
|
void KeymasterHidlTest::CheckHmacTestVector(const string& key, const string& message, Digest digest,
|
|
const string& expected_mac) {
|
|
SCOPED_TRACE("CheckHmacTestVector");
|
|
ASSERT_EQ(ErrorCode::OK,
|
|
ImportKey(AuthorizationSetBuilder()
|
|
.Authorization(TAG_NO_AUTH_REQUIRED)
|
|
.HmacKey(key.size() * 8)
|
|
.Authorization(TAG_MIN_MAC_LENGTH, expected_mac.size() * 8)
|
|
.Digest(digest),
|
|
KeyFormat::RAW, key));
|
|
string signature = MacMessage(message, digest, expected_mac.size() * 8);
|
|
EXPECT_EQ(expected_mac, signature)
|
|
<< "Test vector didn't match for key of size " << key.size() << " message of size "
|
|
<< message.size() << " and digest " << digest;
|
|
CheckedDeleteKey();
|
|
}
|
|
|
|
void KeymasterHidlTest::CheckAesCtrTestVector(const string& key, const string& nonce,
|
|
const string& message,
|
|
const string& expected_ciphertext) {
|
|
SCOPED_TRACE("CheckAesCtrTestVector");
|
|
ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
|
|
.Authorization(TAG_NO_AUTH_REQUIRED)
|
|
.AesEncryptionKey(key.size() * 8)
|
|
.BlockMode(BlockMode::CTR)
|
|
.Authorization(TAG_CALLER_NONCE)
|
|
.Padding(PaddingMode::NONE),
|
|
KeyFormat::RAW, key));
|
|
|
|
auto params = AuthorizationSetBuilder()
|
|
.Authorization(TAG_NONCE, nonce.data(), nonce.size())
|
|
.BlockMode(BlockMode::CTR)
|
|
.Padding(PaddingMode::NONE);
|
|
AuthorizationSet out_params;
|
|
string ciphertext = EncryptMessage(key_blob_, message, params, &out_params);
|
|
EXPECT_EQ(expected_ciphertext, ciphertext);
|
|
}
|
|
|
|
void KeymasterHidlTest::CheckTripleDesTestVector(KeyPurpose purpose, BlockMode block_mode,
|
|
PaddingMode padding_mode, const string& key,
|
|
const string& iv, const string& input,
|
|
const string& expected_output) {
|
|
auto authset = AuthorizationSetBuilder()
|
|
.TripleDesEncryptionKey(key.size() * 7)
|
|
.BlockMode(block_mode)
|
|
.Authorization(TAG_NO_AUTH_REQUIRED)
|
|
.Padding(padding_mode);
|
|
if (iv.size()) authset.Authorization(TAG_CALLER_NONCE);
|
|
ASSERT_EQ(ErrorCode::OK, ImportKey(authset, KeyFormat::RAW, key));
|
|
auto begin_params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding_mode);
|
|
if (iv.size()) begin_params.Authorization(TAG_NONCE, iv.data(), iv.size());
|
|
AuthorizationSet output_params;
|
|
string output = ProcessMessage(key_blob_, purpose, input, begin_params, &output_params);
|
|
EXPECT_EQ(expected_output, output);
|
|
}
|
|
|
|
void KeymasterHidlTest::VerifyMessage(const HidlBuf& key_blob, const string& message,
|
|
const string& signature, const AuthorizationSet& params) {
|
|
SCOPED_TRACE("VerifyMessage");
|
|
AuthorizationSet begin_out_params;
|
|
ASSERT_EQ(ErrorCode::OK,
|
|
Begin(KeyPurpose::VERIFY, key_blob, params, &begin_out_params, &op_handle_));
|
|
|
|
string output;
|
|
AuthorizationSet update_params;
|
|
AuthorizationSet update_out_params;
|
|
size_t consumed;
|
|
ASSERT_EQ(ErrorCode::OK,
|
|
Update(op_handle_, update_params, message, &update_out_params, &output, &consumed));
|
|
EXPECT_TRUE(output.empty());
|
|
EXPECT_GT(consumed, 0U);
|
|
|
|
string unused;
|
|
AuthorizationSet finish_params;
|
|
AuthorizationSet finish_out_params;
|
|
EXPECT_EQ(ErrorCode::OK, Finish(op_handle_, finish_params, message.substr(consumed), signature,
|
|
&finish_out_params, &output));
|
|
op_handle_ = kOpHandleSentinel;
|
|
EXPECT_TRUE(output.empty());
|
|
}
|
|
|
|
void KeymasterHidlTest::VerifyMessage(const string& message, const string& signature,
|
|
const AuthorizationSet& params) {
|
|
SCOPED_TRACE("VerifyMessage");
|
|
VerifyMessage(key_blob_, message, signature, params);
|
|
}
|
|
|
|
string KeymasterHidlTest::EncryptMessage(const HidlBuf& key_blob, const string& message,
|
|
const AuthorizationSet& in_params,
|
|
AuthorizationSet* out_params) {
|
|
SCOPED_TRACE("EncryptMessage");
|
|
return ProcessMessage(key_blob, KeyPurpose::ENCRYPT, message, in_params, out_params);
|
|
}
|
|
|
|
string KeymasterHidlTest::EncryptMessage(const string& message, const AuthorizationSet& params,
|
|
AuthorizationSet* out_params) {
|
|
SCOPED_TRACE("EncryptMessage");
|
|
return EncryptMessage(key_blob_, message, params, out_params);
|
|
}
|
|
|
|
string KeymasterHidlTest::EncryptMessage(const string& message, const AuthorizationSet& params) {
|
|
SCOPED_TRACE("EncryptMessage");
|
|
AuthorizationSet out_params;
|
|
string ciphertext = EncryptMessage(message, params, &out_params);
|
|
EXPECT_TRUE(out_params.empty()) << "Output params should be empty. Contained: " << out_params;
|
|
return ciphertext;
|
|
}
|
|
|
|
string KeymasterHidlTest::EncryptMessage(const string& message, BlockMode block_mode,
|
|
PaddingMode padding) {
|
|
SCOPED_TRACE("EncryptMessage");
|
|
auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding);
|
|
AuthorizationSet out_params;
|
|
string ciphertext = EncryptMessage(message, params, &out_params);
|
|
EXPECT_TRUE(out_params.empty()) << "Output params should be empty. Contained: " << out_params;
|
|
return ciphertext;
|
|
}
|
|
|
|
string KeymasterHidlTest::EncryptMessage(const string& message, BlockMode block_mode,
|
|
PaddingMode padding, HidlBuf* iv_out) {
|
|
SCOPED_TRACE("EncryptMessage");
|
|
auto params = AuthorizationSetBuilder().BlockMode(block_mode).Padding(padding);
|
|
AuthorizationSet out_params;
|
|
string ciphertext = EncryptMessage(message, params, &out_params);
|
|
EXPECT_EQ(1U, out_params.size());
|
|
auto ivVal = out_params.GetTagValue(TAG_NONCE);
|
|
EXPECT_TRUE(ivVal.isOk());
|
|
if (ivVal.isOk()) *iv_out = ivVal.value();
|
|
return ciphertext;
|
|
}
|
|
|
|
string KeymasterHidlTest::EncryptMessage(const string& message, BlockMode block_mode,
|
|
PaddingMode padding, const HidlBuf& iv_in) {
|
|
SCOPED_TRACE("EncryptMessage");
|
|
auto params = AuthorizationSetBuilder()
|
|
.BlockMode(block_mode)
|
|
.Padding(padding)
|
|
.Authorization(TAG_NONCE, iv_in);
|
|
AuthorizationSet out_params;
|
|
string ciphertext = EncryptMessage(message, params, &out_params);
|
|
return ciphertext;
|
|
}
|
|
|
|
string KeymasterHidlTest::EncryptMessage(const string& message, BlockMode block_mode,
|
|
PaddingMode padding, uint8_t mac_length_bits,
|
|
const HidlBuf& iv_in) {
|
|
SCOPED_TRACE("EncryptMessage");
|
|
auto params = AuthorizationSetBuilder()
|
|
.BlockMode(block_mode)
|
|
.Padding(padding)
|
|
.Authorization(TAG_MAC_LENGTH, mac_length_bits)
|
|
.Authorization(TAG_NONCE, iv_in);
|
|
AuthorizationSet out_params;
|
|
string ciphertext = EncryptMessage(message, params, &out_params);
|
|
return ciphertext;
|
|
}
|
|
|
|
string KeymasterHidlTest::DecryptMessage(const HidlBuf& key_blob, const string& ciphertext,
|
|
const AuthorizationSet& params) {
|
|
SCOPED_TRACE("DecryptMessage");
|
|
AuthorizationSet out_params;
|
|
string plaintext =
|
|
ProcessMessage(key_blob, KeyPurpose::DECRYPT, ciphertext, params, &out_params);
|
|
EXPECT_TRUE(out_params.empty());
|
|
return plaintext;
|
|
}
|
|
|
|
string KeymasterHidlTest::DecryptMessage(const string& ciphertext, const AuthorizationSet& params) {
|
|
SCOPED_TRACE("DecryptMessage");
|
|
return DecryptMessage(key_blob_, ciphertext, params);
|
|
}
|
|
|
|
string KeymasterHidlTest::DecryptMessage(const string& ciphertext, BlockMode block_mode,
|
|
PaddingMode padding_mode, const HidlBuf& iv) {
|
|
SCOPED_TRACE("DecryptMessage");
|
|
auto params = AuthorizationSetBuilder()
|
|
.BlockMode(block_mode)
|
|
.Padding(padding_mode)
|
|
.Authorization(TAG_NONCE, iv);
|
|
return DecryptMessage(key_blob_, ciphertext, params);
|
|
}
|
|
|
|
std::pair<ErrorCode, HidlBuf> KeymasterHidlTest::UpgradeKey(const HidlBuf& key_blob) {
|
|
std::pair<ErrorCode, HidlBuf> retval;
|
|
keymaster_->upgradeKey(key_blob, hidl_vec<KeyParameter>(),
|
|
[&](ErrorCode error, const hidl_vec<uint8_t>& upgraded_blob) {
|
|
retval = std::tie(error, upgraded_blob);
|
|
});
|
|
return retval;
|
|
}
|
|
std::vector<uint32_t> KeymasterHidlTest::ValidKeySizes(Algorithm algorithm) {
|
|
switch (algorithm) {
|
|
case Algorithm::RSA:
|
|
switch (SecLevel()) {
|
|
case SecurityLevel::SOFTWARE:
|
|
case SecurityLevel::TRUSTED_ENVIRONMENT:
|
|
return {2048, 3072, 4096};
|
|
case SecurityLevel::STRONGBOX:
|
|
return {2048};
|
|
default:
|
|
ADD_FAILURE() << "Invalid security level " << uint32_t(SecLevel());
|
|
break;
|
|
}
|
|
break;
|
|
case Algorithm::EC:
|
|
switch (SecLevel()) {
|
|
case SecurityLevel::SOFTWARE:
|
|
case SecurityLevel::TRUSTED_ENVIRONMENT:
|
|
return {224, 256, 384, 521};
|
|
case SecurityLevel::STRONGBOX:
|
|
return {256};
|
|
default:
|
|
ADD_FAILURE() << "Invalid security level " << uint32_t(SecLevel());
|
|
break;
|
|
}
|
|
break;
|
|
case Algorithm::AES:
|
|
return {128, 256};
|
|
case Algorithm::TRIPLE_DES:
|
|
return {168};
|
|
case Algorithm::HMAC: {
|
|
std::vector<uint32_t> retval((512 - 64) / 8 + 1);
|
|
uint32_t size = 64 - 8;
|
|
std::generate(retval.begin(), retval.end(), [&]() { return (size += 8); });
|
|
return retval;
|
|
}
|
|
default:
|
|
ADD_FAILURE() << "Invalid Algorithm: " << algorithm;
|
|
return {};
|
|
}
|
|
ADD_FAILURE() << "Should be impossible to get here";
|
|
return {};
|
|
}
|
|
|
|
std::vector<uint32_t> KeymasterHidlTest::InvalidKeySizes(Algorithm algorithm) {
|
|
if (SecLevel() == SecurityLevel::STRONGBOX) {
|
|
switch (algorithm) {
|
|
case Algorithm::RSA:
|
|
return {3072, 4096};
|
|
case Algorithm::EC:
|
|
return {224, 384, 521};
|
|
case Algorithm::AES:
|
|
// The HAL language was clarified to exclude AES key sizes of 192 for StrongBox
|
|
// instances on devices launched on API Level 31 and above.
|
|
if (property_get_int32("ro.board.first_api_level", 0) < 31) return {};
|
|
return {192};
|
|
default:
|
|
return {};
|
|
}
|
|
}
|
|
return {};
|
|
}
|
|
|
|
std::vector<EcCurve> KeymasterHidlTest::ValidCurves() {
|
|
if (securityLevel_ == SecurityLevel::STRONGBOX) {
|
|
return {EcCurve::P_256};
|
|
} else {
|
|
return {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521};
|
|
}
|
|
}
|
|
|
|
std::vector<EcCurve> KeymasterHidlTest::InvalidCurves() {
|
|
if (SecLevel() == SecurityLevel::TRUSTED_ENVIRONMENT) return {};
|
|
CHECK(SecLevel() == SecurityLevel::STRONGBOX);
|
|
return {EcCurve::P_224, EcCurve::P_384, EcCurve::P_521};
|
|
}
|
|
|
|
std::vector<Digest> KeymasterHidlTest::ValidDigests(bool withNone, bool withMD5) {
|
|
switch (SecLevel()) {
|
|
case SecurityLevel::SOFTWARE:
|
|
case SecurityLevel::TRUSTED_ENVIRONMENT:
|
|
if (withNone) {
|
|
if (withMD5)
|
|
return {Digest::NONE, Digest::MD5, Digest::SHA1,
|
|
Digest::SHA_2_224, Digest::SHA_2_256, Digest::SHA_2_384,
|
|
Digest::SHA_2_512};
|
|
else
|
|
return {Digest::NONE, Digest::SHA1, Digest::SHA_2_224,
|
|
Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512};
|
|
} else {
|
|
if (withMD5)
|
|
return {Digest::MD5, Digest::SHA1, Digest::SHA_2_224,
|
|
Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512};
|
|
else
|
|
return {Digest::SHA1, Digest::SHA_2_224, Digest::SHA_2_256, Digest::SHA_2_384,
|
|
Digest::SHA_2_512};
|
|
}
|
|
break;
|
|
case SecurityLevel::STRONGBOX:
|
|
if (withNone)
|
|
return {Digest::NONE, Digest::SHA_2_256};
|
|
else
|
|
return {Digest::SHA_2_256};
|
|
break;
|
|
default:
|
|
ADD_FAILURE() << "Invalid security level " << uint32_t(SecLevel());
|
|
break;
|
|
}
|
|
ADD_FAILURE() << "Should be impossible to get here";
|
|
return {};
|
|
}
|
|
|
|
std::vector<Digest> KeymasterHidlTest::InvalidDigests() {
|
|
return {};
|
|
}
|
|
|
|
} // namespace test
|
|
} // namespace V4_0
|
|
} // namespace keymaster
|
|
} // namespace hardware
|
|
} // namespace android
|