blob: d0611fc4a5d59c8d5bdfb0e4fe03b2aea04a9d68 [file] [log] [blame]
/*
* 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 <../proto_utils.h>
#include <nugget/app/keymaster/keymaster.pb.h>
#include <MockKeymaster.client.h>
#include <KeymasterDevice.h>
#include <keymasterV4_0/keymaster_tags.h>
#include <android-base/logging.h>
#include <gtest/gtest.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/pkcs8.h>
#include <string>
using ::std::string;
using ::std::unique_ptr;
using ::testing::_;
using ::testing::DoAll;
using ::testing::Eq;
using ::testing::Matcher;
using ::testing::MatcherInterface;
using ::testing::MatchResultListener;
using ::testing::Return;
using ::testing::SetArgPointee;
// Hardware
using ::android::hardware::hidl_vec;
using ::android::hardware::keymaster::KeymasterDevice;
// HAL
using ::android::hardware::keymaster::V4_0::Algorithm;
using ::android::hardware::keymaster::V4_0::EcCurve;
using ::android::hardware::keymaster::V4_0::ErrorCode;
using ::android::hardware::keymaster::V4_0::KeyFormat;
using ::android::hardware::keymaster::V4_0::KeyParameter;
using ::android::hardware::keymaster::V4_0::KeyCharacteristics;
using ::android::hardware::keymaster::V4_0::Tag;
using android::hardware::keymaster::pb_to_hidl_params;
// App
//using namespace ::nugget::app::keymaster;
namespace nosapp = ::nugget::app::keymaster;
using ::nugget::app::keymaster::MockKeymaster;
using ::nugget::app::keymaster::ImportWrappedKeyRequest;
using ::nugget::app::keymaster::ImportKeyResponse;
// ImportWrappedKey
static const hidl_vec<uint8_t> WRAPPED_KEY_DER{
0x30, 0x82, 0x01, 0x5f, 0x02, 0x01, 0x00, 0x04, 0x82, 0x01, 0x00, 0x99,
0xb0, 0xad, 0xd4, 0xe4, 0x0c, 0x82, 0x37, 0x33, 0x0c, 0x12, 0xe1, 0x2a,
0x5c, 0x22, 0x5b, 0xdc, 0xb4, 0x36, 0xae, 0xb5, 0xb1, 0x90, 0xbb, 0xc7,
0x09, 0x13, 0xe4, 0x12, 0xf2, 0x5b, 0x20, 0x3e, 0xe5, 0xd2, 0x6d, 0x69,
0x25, 0xa8, 0x3e, 0x59, 0x43, 0x31, 0x3a, 0x29, 0x06, 0x97, 0xae, 0x0f,
0x30, 0x38, 0x18, 0x6e, 0x3a, 0xac, 0x6a, 0xb7, 0xa4, 0x36, 0x87, 0xc4,
0xde, 0xdb, 0xa3, 0x46, 0x78, 0x64, 0xd7, 0x2b, 0x51, 0x51, 0x34, 0x36,
0x98, 0x66, 0x72, 0xd2, 0x48, 0x98, 0x61, 0x67, 0x87, 0xcf, 0x29, 0xba,
0x9b, 0xf7, 0xcd, 0x14, 0x33, 0xd2, 0x67, 0x9b, 0x9c, 0x55, 0x3b, 0xf0,
0x72, 0x13, 0x75, 0xbc, 0x55, 0x95, 0xd9, 0x0d, 0xb3, 0xe5, 0x6b, 0x88,
0x4a, 0xae, 0xe5, 0xc0, 0xf2, 0x17, 0x01, 0x92, 0xfb, 0x68, 0x08, 0x8e,
0x91, 0x96, 0x5f, 0x2f, 0x19, 0x63, 0xeb, 0x95, 0xb2, 0xd2, 0x89, 0x5b,
0xb5, 0x96, 0xa6, 0x6f, 0x50, 0x63, 0x6d, 0x05, 0x9f, 0x06, 0x29, 0x81,
0xc2, 0x85, 0x3a, 0xd0, 0x63, 0x78, 0xc8, 0x78, 0x95, 0xde, 0x49, 0xa1,
0xb7, 0xdd, 0xde, 0xaf, 0x6a, 0xa2, 0xf6, 0xb5, 0xe2, 0x51, 0x21, 0xad,
0x5e, 0x81, 0xa3, 0x2c, 0xf4, 0xb5, 0x5d, 0x1f, 0x7e, 0x45, 0xe8, 0xdc,
0x7c, 0xab, 0x3b, 0xaa, 0x49, 0xee, 0xa9, 0xd5, 0x9d, 0xe1, 0x78, 0x39,
0xe9, 0xb4, 0x91, 0xf7, 0x2e, 0xbf, 0xc5, 0xbc, 0xb5, 0x26, 0x48, 0x05,
0x9f, 0x49, 0x31, 0xa7, 0xa2, 0x56, 0xea, 0x79, 0x61, 0x28, 0x23, 0x67,
0x8e, 0x12, 0xbd, 0x4b, 0xe7, 0xbd, 0x8f, 0x10, 0x45, 0xbc, 0x3c, 0xd0,
0x4b, 0xa9, 0x28, 0xd2, 0xf3, 0x59, 0xfb, 0x10, 0x08, 0xd0, 0x91, 0x74,
0xd8, 0xd1, 0x89, 0x6c, 0xda, 0xc7, 0x6e, 0x4f, 0x44, 0x09, 0x89, 0x4f,
0x2d, 0x7c, 0xa7, 0x04, 0x0c, 0xd7, 0x96, 0xb0, 0x2c, 0x37, 0x0f, 0x1f,
0xa4, 0xcc, 0x01, 0x24, 0xf1, 0x30, 0x14, 0x02, 0x01, 0x03, 0x30, 0x0f,
0xa1, 0x02, 0x31, 0x00, 0xa2, 0x03, 0x02, 0x01, 0x20, 0xa3, 0x04, 0x02,
0x02, 0x01, 0x00, 0x04, 0x20, 0xcc, 0xd5, 0x40, 0x85, 0x5f, 0x83, 0x3a,
0x5e, 0x14, 0x80, 0xbf, 0xd2, 0xd3, 0x6f, 0xaf, 0x3a, 0xee, 0xe1, 0x5d,
0xf5, 0xbe, 0xab, 0xe2, 0x69, 0x1b, 0xc8, 0x2d, 0xde, 0x2a, 0x7a, 0xa9,
0x10, 0x04, 0x10, 0x0a, 0xa4, 0x6a, 0x14, 0xa0, 0x24, 0x90, 0xea, 0xf5,
0xef, 0x32, 0x86, 0x2e, 0x4c, 0x03, 0x4e
};
static const hidl_vec<uint8_t> RSA_ENVELOPE{
0x99, 0xb0, 0xad, 0xd4, 0xe4, 0x0c, 0x82, 0x37, 0x33, 0x0c, 0x12, 0xe1,
0x2a, 0x5c, 0x22, 0x5b, 0xdc, 0xb4, 0x36, 0xae, 0xb5, 0xb1, 0x90, 0xbb,
0xc7, 0x09, 0x13, 0xe4, 0x12, 0xf2, 0x5b, 0x20, 0x3e, 0xe5, 0xd2, 0x6d,
0x69, 0x25, 0xa8, 0x3e, 0x59, 0x43, 0x31, 0x3a, 0x29, 0x06, 0x97, 0xae,
0x0f, 0x30, 0x38, 0x18, 0x6e, 0x3a, 0xac, 0x6a, 0xb7, 0xa4, 0x36, 0x87,
0xc4, 0xde, 0xdb, 0xa3, 0x46, 0x78, 0x64, 0xd7, 0x2b, 0x51, 0x51, 0x34,
0x36, 0x98, 0x66, 0x72, 0xd2, 0x48, 0x98, 0x61, 0x67, 0x87, 0xcf, 0x29,
0xba, 0x9b, 0xf7, 0xcd, 0x14, 0x33, 0xd2, 0x67, 0x9b, 0x9c, 0x55, 0x3b,
0xf0, 0x72, 0x13, 0x75, 0xbc, 0x55, 0x95, 0xd9, 0x0d, 0xb3, 0xe5, 0x6b,
0x88, 0x4a, 0xae, 0xe5, 0xc0, 0xf2, 0x17, 0x01, 0x92, 0xfb, 0x68, 0x08,
0x8e, 0x91, 0x96, 0x5f, 0x2f, 0x19, 0x63, 0xeb, 0x95, 0xb2, 0xd2, 0x89,
0x5b, 0xb5, 0x96, 0xa6, 0x6f, 0x50, 0x63, 0x6d, 0x05, 0x9f, 0x06, 0x29,
0x81, 0xc2, 0x85, 0x3a, 0xd0, 0x63, 0x78, 0xc8, 0x78, 0x95, 0xde, 0x49,
0xa1, 0xb7, 0xdd, 0xde, 0xaf, 0x6a, 0xa2, 0xf6, 0xb5, 0xe2, 0x51, 0x21,
0xad, 0x5e, 0x81, 0xa3, 0x2c, 0xf4, 0xb5, 0x5d, 0x1f, 0x7e, 0x45, 0xe8,
0xdc, 0x7c, 0xab, 0x3b, 0xaa, 0x49, 0xee, 0xa9, 0xd5, 0x9d, 0xe1, 0x78,
0x39, 0xe9, 0xb4, 0x91, 0xf7, 0x2e, 0xbf, 0xc5, 0xbc, 0xb5, 0x26, 0x48,
0x05, 0x9f, 0x49, 0x31, 0xa7, 0xa2, 0x56, 0xea, 0x79, 0x61, 0x28, 0x23,
0x67, 0x8e, 0x12, 0xbd, 0x4b, 0xe7, 0xbd, 0x8f, 0x10, 0x45, 0xbc, 0x3c,
0xd0, 0x4b, 0xa9, 0x28, 0xd2, 0xf3, 0x59, 0xfb, 0x10, 0x08, 0xd0, 0x91,
0x74, 0xd8, 0xd1, 0x89, 0x6c, 0xda, 0xc7, 0x6e, 0x4f, 0x44, 0x09, 0x89,
0x4f, 0x2d, 0x7c, 0xa7
};
static const hidl_vec<uint8_t> INITIALIZATION_VECTOR{
0xd7, 0x96, 0xb0, 0x2c, 0x37, 0x0f, 0x1f, 0xa4, 0xcc, 0x01, 0x24, 0xf1
};
static const hidl_vec<uint8_t> ENCRYPTED_IMPORT_KEY{
0xcc, 0xd5, 0x40, 0x85, 0x5f, 0x83, 0x3a, 0x5e, 0x14, 0x80, 0xbf, 0xd2,
0xd3, 0x6f, 0xaf, 0x3a, 0xee, 0xe1, 0x5d, 0xf5, 0xbe, 0xab, 0xe2, 0x69,
0x1b, 0xc8, 0x2d, 0xde, 0x2a, 0x7a, 0xa9, 0x10
};
static const hidl_vec<uint8_t> AAD{
0x30, 0x14, 0x02, 0x01, 0x03, 0x30, 0x0f, 0xa1, 0x02, 0x31, 0x00, 0xa2,
0x03, 0x02, 0x01, 0x20, 0xa3, 0x04, 0x02, 0x02, 0x01, 0x00
};
static const hidl_vec<uint8_t> GCM_TAG{
0x0a, 0xa4, 0x6a, 0x14, 0xa0, 0x24, 0x90, 0xea, 0xf5, 0xef, 0x32, 0x86,
0x2e, 0x4c, 0x03, 0x4e
};
class ImportWrappedKeyRequestMatcher
: public MatcherInterface<const ImportWrappedKeyRequest&> {
public:
explicit ImportWrappedKeyRequestMatcher(
KeyFormat key_format,
const hidl_vec<KeyParameter>& params,
const hidl_vec<uint8_t>& rsa_envelope,
const hidl_vec<uint8_t>& initialization_vector,
const hidl_vec<uint8_t>& encrypted_import_key,
const hidl_vec<uint8_t>& aad,
const hidl_vec<uint8_t>& gcm_tag,
const hidl_vec<uint8_t>& wrapping_key_blob,
const hidl_vec<uint8_t>& masking_key)
: key_format_(key_format),
params_(params),
rsa_envelope_(rsa_envelope),
initialization_vector_(initialization_vector),
encrypted_import_key_(encrypted_import_key),
aad_(aad),
gcm_tag_(gcm_tag),
wrapping_key_blob_(wrapping_key_blob),
masking_key_(masking_key) {
}
virtual void DescribeTo(::std::ostream* os) const {
*os << "ImportWrappedKeyRequest matched expectation";
}
virtual void DescribeNegationTo(::std::ostream* os) const {
*os << "ImportWrappedKeyRequest mis-matched expectation";
}
virtual bool MatchAndExplain(const ImportWrappedKeyRequest& request,
MatchResultListener* listener) const {
if ((uint32_t)key_format_ != request.key_format()) {
*listener << "Expected key_format: " << (uint32_t)key_format_
<< " got: " << request.key_format();
return false;
}
(void)params_;
if (!MatchByteArray(
"RSA envelope",
listener,
rsa_envelope_.data(),
rsa_envelope_.size(),
(const uint8_t *)request.rsa_envelope().data(),
request.rsa_envelope().size())) {
return false;
}
if (!MatchByteArray(
"Initialization vector",
listener,
initialization_vector_.data(),
initialization_vector_.size(),
(const uint8_t *)request.initialization_vector().data(),
request.initialization_vector().size())) {
return false;
}
if (!MatchByteArray(
"Encrypted import key",
listener,
encrypted_import_key_.data(),
encrypted_import_key_.size(),
(const uint8_t *)request.encrypted_import_key().data(),
request.encrypted_import_key().size())) {
return false;
}
if (!MatchByteArray(
"AAD",
listener,
aad_.data(),
aad_.size(),
(const uint8_t *)request.aad().data(),
request.aad().size())) {
return false;
}
if (!MatchByteArray(
"GCM TAG",
listener,
gcm_tag_.data(),
gcm_tag_.size(),
(const uint8_t *)request.gcm_tag().data(),
request.gcm_tag().size())) {
return false;
}
if (!MatchByteArray(
"Wrapping key blob",
listener,
wrapping_key_blob_.data(),
wrapping_key_blob_.size(),
(const uint8_t *)request.wrapping_key_blob().blob().data(),
request.wrapping_key_blob().blob().size())) {
return false;
}
if (!MatchByteArray(
"Masking key",
listener,
masking_key_.data(),
masking_key_.size(),
(const uint8_t *)request.masking_key().data(),
request.masking_key().size())) {
return false;
}
return true;
}
private:
bool MatchByteArray(const char *label, MatchResultListener *listener,
const uint8_t *expected, size_t expected_len,
const uint8_t *got, size_t got_len) const {
if (expected_len != got_len) {
*listener << label << ": expected len: " << expected_len
<< " got len: " << got_len;
return false;
}
for (size_t i = 0; i < expected_len; i++) {
if (expected[i] != got[i]) {
*listener << label << ": mismatch at index: " << i
<< " expected: " << std::hex << (int)expected[i]
<< " got: " << std::hex << (int)got[i];
return false;
}
}
return true;
}
KeyFormat key_format_;
const hidl_vec<KeyParameter>& params_;
const hidl_vec<uint8_t>& rsa_envelope_;
const hidl_vec<uint8_t>& initialization_vector_;
const hidl_vec<uint8_t>& encrypted_import_key_;
const hidl_vec<uint8_t>& aad_;
const hidl_vec<uint8_t>& gcm_tag_;
const hidl_vec<uint8_t>& wrapping_key_blob_;
const hidl_vec<uint8_t>& masking_key_;
};
static Matcher<const ImportWrappedKeyRequest&> ImportWrappedKeyRequestEq(
KeyFormat key_format,
const hidl_vec<KeyParameter>& params,
const hidl_vec<uint8_t>& rsa_envelope,
const hidl_vec<uint8_t>& initialization_vector,
const hidl_vec<uint8_t>& encrypted_import_key,
const hidl_vec<uint8_t>& aad,
const hidl_vec<uint8_t>& gcm_tag,
const hidl_vec<uint8_t>& wrapping_key_blob,
const hidl_vec<uint8_t>& masking_key) {
return MakeMatcher(new ImportWrappedKeyRequestMatcher(
key_format, params,
rsa_envelope, initialization_vector,
encrypted_import_key, aad, gcm_tag,
wrapping_key_blob, masking_key));
}
TEST(KeymasterHalTest, importWrappedKeyRAWSuccess) {
MockKeymaster mockService;
ImportKeyResponse response;
// request
KeyParameter kp1;
kp1.tag = Tag::ALGORITHM;
kp1.f.algorithm = Algorithm::AES;
KeyParameter kp2;
kp2.tag = Tag::KEY_SIZE;
kp2.f.integer = 256;
uint8_t masking_key_data[32] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
};
hidl_vec<uint8_t> masking_key;
masking_key.setToExternal(
masking_key_data, sizeof(masking_key_data), false);
uint8_t wrapping_key_blob_data[32] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
};
hidl_vec<uint8_t> wrapping_key_blob;
wrapping_key_blob.setToExternal(
wrapping_key_blob_data, sizeof(wrapping_key_blob_data), false);
// response
string response_key_blob("Dummy-rkb");
response.mutable_blob()->set_blob(response_key_blob);
nosapp::KeyParameter *noskp =
response.mutable_characteristics()->
mutable_tee_enforced()->add_params();
noskp->set_tag(nosapp::Tag::ALGORITHM);
noskp->set_integer((uint32_t)nosapp::Algorithm::AES);
noskp = response.mutable_characteristics()->
mutable_tee_enforced()->add_params();
noskp->set_tag(nosapp::Tag::KEY_SIZE);
noskp->set_integer(256);
EXPECT_CALL(
mockService,
ImportWrappedKey(ImportWrappedKeyRequestEq(
KeyFormat::RAW,
hidl_vec<KeyParameter>{kp1, kp2},
RSA_ENVELOPE,
INITIALIZATION_VECTOR,
ENCRYPTED_IMPORT_KEY,
AAD,
GCM_TAG,
wrapping_key_blob,
masking_key), _))
.WillOnce(DoAll(SetArgPointee<1>(response), Return(APP_SUCCESS)));
KeymasterDevice hal{mockService};
/*
* TODO: extend test cases & matchers to include unwrappingParams,
* passwordSid, biometricSid.
*/
hal.importWrappedKey(
WRAPPED_KEY_DER,
wrapping_key_blob,
masking_key,
{}, /* unwrappingParams */
0, /* passwordSid */
0, /* biometricSid */
[&](ErrorCode error, hidl_vec<uint8_t> blob,
KeyCharacteristics characteristics) {
EXPECT_EQ(error, ErrorCode::OK);
EXPECT_THAT(blob, Eq(hidl_vec<uint8_t>{'D', 'u', 'm', 'm', 'y',
'-', 'r', 'k', 'b'}));;
EXPECT_EQ(characteristics.hardwareEnforced.size(), 2u);
EXPECT_EQ(characteristics.hardwareEnforced[0].tag, Tag::ALGORITHM);
EXPECT_EQ(characteristics.hardwareEnforced[0].f.algorithm,
Algorithm::AES);
EXPECT_EQ(characteristics.hardwareEnforced[1].tag, Tag::KEY_SIZE);
EXPECT_EQ(characteristics.hardwareEnforced[1].f.integer,
256u);
});
}