mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Revert "Keystore 2.0 SPI: Move keymint spec to security namespace." Revert "Keystore 2.0: Move keymint spec to security namespace." Revert "Keystore 2.0: Move keymint spec to security namespace." Revert "Move keymint to android.hardware.security." Revert "Configure CF to start KeyMint service by default." Revert "Move keymint to android.hardware.security." Revert "Move keymint to android.hardware.security." Revert submission 1522123-move_keymint Reason for revert: Build breakage Bug: 175345910 Bug: 171429297 Reverted Changes: Ief0e9884a:Keystore 2.0: Move keymint spec to security namesp... Idb54e8846:Keystore 2.0: Move keymint spec to security namesp... I9f70db0e4:Remove references to keymint1 I2b4ce3349:Keystore 2.0 SPI: Move keymint spec to security na... I2498073aa:Move keymint to android.hardware.security. I098711e7d:Move keymint to android.hardware.security. I3ec8d70fe:Configure CF to start KeyMint service by default. Icbb373c50:Move keymint to android.hardware.security. I86bccf40e:Move keymint to android.hardware.security. Change-Id: I160cae568ed6b15698bd0af0b19c6c949528762d
757 lines
28 KiB
C++
757 lines
28 KiB
C++
/*
|
|
* Copyright (C) 2020 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 "KeyMintAidlTestBase.h"
|
|
|
|
#include <chrono>
|
|
#include <vector>
|
|
|
|
#include <android-base/logging.h>
|
|
|
|
#include <keymintSupport/key_param_output.h>
|
|
#include <keymintSupport/keymint_utils.h>
|
|
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace keymint {
|
|
|
|
using namespace std::literals::chrono_literals;
|
|
using std::endl;
|
|
using std::optional;
|
|
|
|
::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 {
|
|
|
|
ErrorCode KeyMintAidlTestBase::GetReturnErrorCode(Status result) {
|
|
if (result.isOk()) return ErrorCode::OK;
|
|
|
|
if (result.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
|
|
return static_cast<ErrorCode>(result.serviceSpecificErrorCode());
|
|
}
|
|
|
|
return ErrorCode::UNKNOWN_ERROR;
|
|
}
|
|
|
|
void KeyMintAidlTestBase::InitializeKeyMint(sp<IKeyMintDevice> keyMint) {
|
|
ASSERT_NE(keyMint, nullptr);
|
|
keymint_ = keyMint;
|
|
|
|
KeyMintHardwareInfo info;
|
|
ASSERT_TRUE(keymint_->getHardwareInfo(&info).isOk());
|
|
|
|
securityLevel_ = info.securityLevel;
|
|
name_.assign(info.keyMintName.begin(), info.keyMintName.end());
|
|
author_.assign(info.keyMintAuthorName.begin(), info.keyMintAuthorName.end());
|
|
|
|
os_version_ = getOsVersion();
|
|
os_patch_level_ = getOsPatchlevel();
|
|
}
|
|
|
|
void KeyMintAidlTestBase::SetUp() {
|
|
InitializeKeyMint(
|
|
android::waitForDeclaredService<IKeyMintDevice>(String16(GetParam().c_str())));
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::GenerateKey(const AuthorizationSet& key_desc,
|
|
vector<uint8_t>* keyBlob, KeyCharacteristics* keyChar) {
|
|
EXPECT_NE(keyBlob, nullptr) << "Key blob pointer must not be null. Test bug";
|
|
EXPECT_NE(keyChar, nullptr)
|
|
<< "Previous characteristics not deleted before generating key. Test bug.";
|
|
|
|
// Aidl does not clear these output parameters if the function returns
|
|
// error. This is different from hal where output parameter is always
|
|
// cleared due to hal returning void. So now we need to do our own clearing
|
|
// of the output variables prior to calling keyMint aidl libraries.
|
|
keyBlob->clear();
|
|
keyChar->softwareEnforced.clear();
|
|
keyChar->hardwareEnforced.clear();
|
|
certChain_.clear();
|
|
|
|
Status result;
|
|
ByteArray blob;
|
|
|
|
result = keymint_->generateKey(key_desc.vector_data(), &blob, keyChar, &certChain_);
|
|
|
|
// On result, blob & characteristics should be empty.
|
|
if (result.isOk()) {
|
|
if (SecLevel() != SecurityLevel::SOFTWARE) {
|
|
EXPECT_GT(keyChar->hardwareEnforced.size(), 0);
|
|
}
|
|
EXPECT_GT(keyChar->softwareEnforced.size(), 0);
|
|
// TODO(seleneh) in a later version where we return @nullable
|
|
// single Certificate, check non-null single certificate is always
|
|
// non-empty.
|
|
*keyBlob = blob.data;
|
|
}
|
|
|
|
return GetReturnErrorCode(result);
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::GenerateKey(const AuthorizationSet& key_desc) {
|
|
return GenerateKey(key_desc, &key_blob_, &key_characteristics_);
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
|
|
const string& key_material, vector<uint8_t>* key_blob,
|
|
KeyCharacteristics* key_characteristics) {
|
|
Status result;
|
|
|
|
certChain_.clear();
|
|
key_characteristics->softwareEnforced.clear();
|
|
key_characteristics->hardwareEnforced.clear();
|
|
key_blob->clear();
|
|
|
|
ByteArray blob;
|
|
result = keymint_->importKey(key_desc.vector_data(), format,
|
|
vector<uint8_t>(key_material.begin(), key_material.end()), &blob,
|
|
key_characteristics, &certChain_);
|
|
|
|
if (result.isOk()) {
|
|
if (SecLevel() != SecurityLevel::SOFTWARE) {
|
|
EXPECT_GT(key_characteristics->hardwareEnforced.size(), 0);
|
|
}
|
|
EXPECT_GT(key_characteristics->softwareEnforced.size(), 0);
|
|
*key_blob = blob.data;
|
|
}
|
|
|
|
return GetReturnErrorCode(result);
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
|
|
const string& key_material) {
|
|
return ImportKey(key_desc, format, key_material, &key_blob_, &key_characteristics_);
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::ImportWrappedKey(string wrapped_key, string wrapping_key,
|
|
const AuthorizationSet& wrapping_key_desc,
|
|
string masking_key,
|
|
const AuthorizationSet& unwrapping_params) {
|
|
Status result;
|
|
EXPECT_EQ(ErrorCode::OK, ImportKey(wrapping_key_desc, KeyFormat::PKCS8, wrapping_key));
|
|
|
|
ByteArray outBlob;
|
|
key_characteristics_.softwareEnforced.clear();
|
|
key_characteristics_.hardwareEnforced.clear();
|
|
|
|
result = keymint_->importWrappedKey(vector<uint8_t>(wrapped_key.begin(), wrapped_key.end()),
|
|
key_blob_,
|
|
vector<uint8_t>(masking_key.begin(), masking_key.end()),
|
|
unwrapping_params.vector_data(), 0 /* passwordSid */,
|
|
0 /* biometricSid */, &outBlob, &key_characteristics_);
|
|
|
|
if (result.isOk()) {
|
|
key_blob_ = outBlob.data;
|
|
if (SecLevel() != SecurityLevel::SOFTWARE) {
|
|
EXPECT_GT(key_characteristics_.hardwareEnforced.size(), 0);
|
|
}
|
|
EXPECT_GT(key_characteristics_.softwareEnforced.size(), 0);
|
|
}
|
|
|
|
return GetReturnErrorCode(result);
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::DeleteKey(vector<uint8_t>* key_blob, bool keep_key_blob) {
|
|
Status result = keymint_->deleteKey(*key_blob);
|
|
if (!keep_key_blob) {
|
|
*key_blob = vector<uint8_t>();
|
|
}
|
|
|
|
EXPECT_TRUE(result.isOk()) << result.serviceSpecificErrorCode() << endl;
|
|
return GetReturnErrorCode(result);
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::DeleteKey(bool keep_key_blob) {
|
|
return DeleteKey(&key_blob_, keep_key_blob);
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::DeleteAllKeys() {
|
|
Status result = keymint_->deleteAllKeys();
|
|
EXPECT_TRUE(result.isOk()) << result.serviceSpecificErrorCode() << endl;
|
|
return GetReturnErrorCode(result);
|
|
}
|
|
|
|
void KeyMintAidlTestBase::CheckedDeleteKey(vector<uint8_t>* key_blob, bool keep_key_blob) {
|
|
ErrorCode result = DeleteKey(key_blob, keep_key_blob);
|
|
EXPECT_TRUE(result == ErrorCode::OK || result == ErrorCode::UNIMPLEMENTED) << result << endl;
|
|
}
|
|
|
|
void KeyMintAidlTestBase::CheckedDeleteKey() {
|
|
CheckedDeleteKey(&key_blob_);
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::Begin(KeyPurpose purpose, const vector<uint8_t>& key_blob,
|
|
const AuthorizationSet& in_params,
|
|
AuthorizationSet* out_params, sp<IKeyMintOperation>& op) {
|
|
SCOPED_TRACE("Begin");
|
|
Status result;
|
|
BeginResult out;
|
|
result = keymint_->begin(purpose, key_blob, in_params.vector_data(), HardwareAuthToken(), &out);
|
|
|
|
if (result.isOk()) {
|
|
*out_params = out.params;
|
|
challenge_ = out.challenge;
|
|
op = out.operation;
|
|
}
|
|
|
|
return GetReturnErrorCode(result);
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::Begin(KeyPurpose purpose, const vector<uint8_t>& key_blob,
|
|
const AuthorizationSet& in_params,
|
|
AuthorizationSet* out_params) {
|
|
SCOPED_TRACE("Begin");
|
|
Status result;
|
|
BeginResult out;
|
|
|
|
result = keymint_->begin(purpose, key_blob, in_params.vector_data(), HardwareAuthToken(), &out);
|
|
|
|
if (result.isOk()) {
|
|
*out_params = out.params;
|
|
challenge_ = out.challenge;
|
|
op_ = out.operation;
|
|
}
|
|
|
|
return GetReturnErrorCode(result);
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::Begin(KeyPurpose purpose, const AuthorizationSet& in_params,
|
|
AuthorizationSet* out_params) {
|
|
SCOPED_TRACE("Begin");
|
|
EXPECT_EQ(nullptr, op_);
|
|
return Begin(purpose, key_blob_, in_params, out_params);
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::Begin(KeyPurpose purpose, const AuthorizationSet& in_params) {
|
|
SCOPED_TRACE("Begin");
|
|
AuthorizationSet out_params;
|
|
ErrorCode result = Begin(purpose, in_params, &out_params);
|
|
EXPECT_TRUE(out_params.empty());
|
|
return result;
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::Update(const AuthorizationSet& in_params, const string& input,
|
|
AuthorizationSet* out_params, string* output,
|
|
int32_t* input_consumed) {
|
|
SCOPED_TRACE("Update");
|
|
|
|
Status result;
|
|
EXPECT_NE(op_, nullptr);
|
|
if (!op_) {
|
|
return ErrorCode::UNEXPECTED_NULL_POINTER;
|
|
}
|
|
|
|
KeyParameterArray key_params;
|
|
key_params.params = in_params.vector_data();
|
|
|
|
KeyParameterArray in_keyParams;
|
|
in_keyParams.params = in_params.vector_data();
|
|
|
|
optional<KeyParameterArray> out_keyParams;
|
|
optional<ByteArray> o_put;
|
|
result = op_->update(in_keyParams, vector<uint8_t>(input.begin(), input.end()), {}, {},
|
|
&out_keyParams, &o_put, input_consumed);
|
|
|
|
if (result.isOk()) {
|
|
if (o_put) {
|
|
output->append(o_put->data.begin(), o_put->data.end());
|
|
}
|
|
|
|
if (out_keyParams) {
|
|
out_params->push_back(AuthorizationSet(out_keyParams->params));
|
|
}
|
|
}
|
|
|
|
return GetReturnErrorCode(result);
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::Update(const string& input, string* out, int32_t* input_consumed) {
|
|
SCOPED_TRACE("Update");
|
|
AuthorizationSet out_params;
|
|
ErrorCode result =
|
|
Update(AuthorizationSet() /* in_params */, input, &out_params, out, input_consumed);
|
|
EXPECT_TRUE(out_params.empty());
|
|
return result;
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::Finish(const AuthorizationSet& in_params, const string& input,
|
|
const string& signature, AuthorizationSet* out_params,
|
|
string* output) {
|
|
SCOPED_TRACE("Finish");
|
|
Status result;
|
|
|
|
EXPECT_NE(op_, nullptr);
|
|
if (!op_) {
|
|
return ErrorCode::UNEXPECTED_NULL_POINTER;
|
|
}
|
|
|
|
KeyParameterArray key_params;
|
|
key_params.params = in_params.vector_data();
|
|
|
|
KeyParameterArray in_keyParams;
|
|
in_keyParams.params = in_params.vector_data();
|
|
|
|
optional<KeyParameterArray> out_keyParams;
|
|
optional<vector<uint8_t>> o_put;
|
|
|
|
vector<uint8_t> oPut;
|
|
result = op_->finish(in_keyParams, vector<uint8_t>(input.begin(), input.end()),
|
|
vector<uint8_t>(signature.begin(), signature.end()), {}, {},
|
|
&out_keyParams, &oPut);
|
|
|
|
if (result.isOk()) {
|
|
if (out_keyParams) {
|
|
out_params->push_back(AuthorizationSet(out_keyParams->params));
|
|
}
|
|
|
|
output->append(oPut.begin(), oPut.end());
|
|
}
|
|
|
|
op_.clear(); // So dtor doesn't Abort().
|
|
return GetReturnErrorCode(result);
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::Finish(const string& message, string* output) {
|
|
SCOPED_TRACE("Finish");
|
|
AuthorizationSet out_params;
|
|
string finish_output;
|
|
ErrorCode result = Finish(AuthorizationSet() /* in_params */, message, "" /* signature */,
|
|
&out_params, output);
|
|
if (result != ErrorCode::OK) {
|
|
return result;
|
|
}
|
|
EXPECT_EQ(0U, out_params.size());
|
|
return result;
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::Finish(const string& message, const string& signature,
|
|
string* output) {
|
|
SCOPED_TRACE("Finish");
|
|
AuthorizationSet out_params;
|
|
ErrorCode result =
|
|
Finish(AuthorizationSet() /* in_params */, message, signature, &out_params, output);
|
|
|
|
if (result != ErrorCode::OK) {
|
|
return result;
|
|
}
|
|
|
|
EXPECT_EQ(0U, out_params.size());
|
|
return result;
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::Abort(const sp<IKeyMintOperation>& op) {
|
|
SCOPED_TRACE("Abort");
|
|
|
|
EXPECT_NE(op, nullptr);
|
|
if (!op) {
|
|
return ErrorCode::UNEXPECTED_NULL_POINTER;
|
|
}
|
|
|
|
Status retval = op->abort();
|
|
EXPECT_TRUE(retval.isOk());
|
|
return static_cast<ErrorCode>(retval.serviceSpecificErrorCode());
|
|
}
|
|
|
|
ErrorCode KeyMintAidlTestBase::Abort() {
|
|
SCOPED_TRACE("Abort");
|
|
|
|
EXPECT_NE(op_, nullptr);
|
|
if (!op_) {
|
|
return ErrorCode::UNEXPECTED_NULL_POINTER;
|
|
}
|
|
|
|
Status retval = op_->abort();
|
|
return static_cast<ErrorCode>(retval.serviceSpecificErrorCode());
|
|
}
|
|
|
|
void KeyMintAidlTestBase::AbortIfNeeded() {
|
|
SCOPED_TRACE("AbortIfNeeded");
|
|
if (op_) {
|
|
EXPECT_EQ(ErrorCode::OK, Abort());
|
|
op_.clear();
|
|
}
|
|
}
|
|
|
|
string KeyMintAidlTestBase::ProcessMessage(const vector<uint8_t>& key_blob, KeyPurpose operation,
|
|
const string& message, const AuthorizationSet& in_params,
|
|
AuthorizationSet* out_params) {
|
|
SCOPED_TRACE("ProcessMessage");
|
|
AuthorizationSet begin_out_params;
|
|
ErrorCode result = Begin(operation, key_blob, in_params, &begin_out_params);
|
|
EXPECT_EQ(ErrorCode::OK, result);
|
|
if (result != ErrorCode::OK) {
|
|
return "";
|
|
}
|
|
|
|
string output;
|
|
int32_t consumed = 0;
|
|
AuthorizationSet update_params;
|
|
AuthorizationSet update_out_params;
|
|
result = Update(update_params, message, &update_out_params, &output, &consumed);
|
|
EXPECT_EQ(ErrorCode::OK, result);
|
|
if (result != ErrorCode::OK) {
|
|
return "";
|
|
}
|
|
|
|
string unused;
|
|
AuthorizationSet finish_params;
|
|
AuthorizationSet finish_out_params;
|
|
EXPECT_EQ(ErrorCode::OK,
|
|
Finish(finish_params, message.substr(consumed), unused, &finish_out_params, &output));
|
|
|
|
out_params->push_back(begin_out_params);
|
|
out_params->push_back(finish_out_params);
|
|
return output;
|
|
}
|
|
|
|
string KeyMintAidlTestBase::SignMessage(const vector<uint8_t>& 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 KeyMintAidlTestBase::SignMessage(const string& message, const AuthorizationSet& params) {
|
|
SCOPED_TRACE("SignMessage");
|
|
return SignMessage(key_blob_, message, params);
|
|
}
|
|
|
|
string KeyMintAidlTestBase::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 KeyMintAidlTestBase::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 KeyMintAidlTestBase::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 KeyMintAidlTestBase::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));
|
|
ASSERT_GT(key_blob_.size(), 0U);
|
|
|
|
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 KeyMintAidlTestBase::VerifyMessage(const vector<uint8_t>& 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));
|
|
|
|
string output;
|
|
AuthorizationSet update_params;
|
|
AuthorizationSet update_out_params;
|
|
int32_t consumed;
|
|
ASSERT_EQ(ErrorCode::OK,
|
|
Update(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(finish_params, message.substr(consumed), signature,
|
|
&finish_out_params, &output));
|
|
op_.clear();
|
|
EXPECT_TRUE(output.empty());
|
|
}
|
|
|
|
void KeyMintAidlTestBase::VerifyMessage(const string& message, const string& signature,
|
|
const AuthorizationSet& params) {
|
|
SCOPED_TRACE("VerifyMessage");
|
|
VerifyMessage(key_blob_, message, signature, params);
|
|
}
|
|
|
|
string KeyMintAidlTestBase::EncryptMessage(const vector<uint8_t>& 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 KeyMintAidlTestBase::EncryptMessage(const string& message, const AuthorizationSet& params,
|
|
AuthorizationSet* out_params) {
|
|
SCOPED_TRACE("EncryptMessage");
|
|
return EncryptMessage(key_blob_, message, params, out_params);
|
|
}
|
|
|
|
string KeyMintAidlTestBase::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 KeyMintAidlTestBase::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 KeyMintAidlTestBase::EncryptMessage(const string& message, BlockMode block_mode,
|
|
PaddingMode padding, vector<uint8_t>* 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 KeyMintAidlTestBase::EncryptMessage(const string& message, BlockMode block_mode,
|
|
PaddingMode padding, const vector<uint8_t>& 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 KeyMintAidlTestBase::EncryptMessage(const string& message, BlockMode block_mode,
|
|
PaddingMode padding, uint8_t mac_length_bits,
|
|
const vector<uint8_t>& 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 KeyMintAidlTestBase::DecryptMessage(const vector<uint8_t>& 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 KeyMintAidlTestBase::DecryptMessage(const string& ciphertext,
|
|
const AuthorizationSet& params) {
|
|
SCOPED_TRACE("DecryptMessage");
|
|
return DecryptMessage(key_blob_, ciphertext, params);
|
|
}
|
|
|
|
string KeyMintAidlTestBase::DecryptMessage(const string& ciphertext, BlockMode block_mode,
|
|
PaddingMode padding_mode, const vector<uint8_t>& 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, vector<uint8_t>> KeyMintAidlTestBase::UpgradeKey(
|
|
const vector<uint8_t>& key_blob) {
|
|
std::pair<ErrorCode, vector<uint8_t>> retval;
|
|
vector<uint8_t> outKeyBlob;
|
|
Status result = keymint_->upgradeKey(key_blob, vector<KeyParameter>(), &outKeyBlob);
|
|
ErrorCode errorcode = GetReturnErrorCode(result);
|
|
retval = std::tie(errorcode, outKeyBlob);
|
|
|
|
return retval;
|
|
}
|
|
vector<uint32_t> KeyMintAidlTestBase::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: {
|
|
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 {};
|
|
}
|
|
|
|
vector<uint32_t> KeyMintAidlTestBase::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:
|
|
return {192};
|
|
default:
|
|
return {};
|
|
}
|
|
}
|
|
return {};
|
|
}
|
|
|
|
vector<EcCurve> KeyMintAidlTestBase::ValidCurves() {
|
|
if (securityLevel_ == SecurityLevel::STRONGBOX) {
|
|
return {EcCurve::P_256};
|
|
} else {
|
|
return {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521};
|
|
}
|
|
}
|
|
|
|
vector<EcCurve> KeyMintAidlTestBase::InvalidCurves() {
|
|
if (SecLevel() == SecurityLevel::TRUSTED_ENVIRONMENT) return {};
|
|
CHECK(SecLevel() == SecurityLevel::STRONGBOX);
|
|
return {EcCurve::P_224, EcCurve::P_384, EcCurve::P_521};
|
|
}
|
|
|
|
vector<Digest> KeyMintAidlTestBase::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 {};
|
|
}
|
|
|
|
} // namespace test
|
|
} // namespace keymint
|
|
} // namespace hardware
|
|
} // namespace android
|