blob: 8b741dd6d171b9433819f667d41dbb27818fee81 [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "arc/keymint/conversion.h"
#include <array>
#include <memory>
#include <utility>
#include <vector>
#include <gtest/gtest.h>
namespace arc::keymint {
namespace {
constexpr std::array<uint8_t, 3> kBlob1{{3, 23, 59}};
constexpr std::array<uint8_t, 4> kBlob2{{23, 46, 69, 92}};
::testing::AssertionResult VerifyVectorUint8(const uint8_t* a,
const size_t a_size,
const std::vector<uint8_t>& b) {
if (a_size != b.size()) {
return ::testing::AssertionFailure()
<< "Sizes differ: a=" << a_size << " b=" << b.size();
}
for (size_t i = 0; i < a_size; ++i) {
if (a[i] != b[i]) {
return ::testing::AssertionFailure()
<< "Elements differ: a=" << static_cast<int>(a[i])
<< " b=" << static_cast<int>(b[i]);
}
}
return ::testing::AssertionSuccess();
}
::testing::AssertionResult VerifyKeyParametersWithStrictInputs(
const ::keymaster::AuthorizationSet& a,
const std::vector<arc::mojom::keymint::KeyParameterPtr>& b) {
if (a.size() != b.size()) {
return ::testing::AssertionFailure()
<< "Sizes differ: a=" << a.size() << " b=" << b.size();
}
for (size_t i = 0; i < a.size(); ++i) {
if (a[i].tag != static_cast<uint32_t>(b[i]->tag)) {
return ::testing::AssertionFailure()
<< "Tags differ: i=" << i
<< " a=" << static_cast<uint32_t>(a[i].tag) << " b=" << b[i]->tag;
}
}
if (!(b[0]->value->is_bool_value() && b[1]->value->is_integer() &&
b[2]->value->is_long_integer() && b[3]->value->is_date_time() &&
b[4]->value->is_blob())) {
return ::testing::AssertionFailure() << "Incorrect union value type";
}
if (!(a[0].boolean == b[0]->value->get_bool_value() &&
a[1].integer == b[1]->value->get_integer() &&
a[2].long_integer == b[2]->value->get_long_integer() &&
a[3].date_time == b[3]->value->get_date_time())) {
return ::testing::AssertionFailure() << "Values differ";
}
return VerifyVectorUint8(a[4].blob.data, a[4].blob.data_length,
b[4]->value->get_blob());
}
} // namespace
TEST(ConvertFromKeymasterMessage, Uint8Vector) {
// Convert.
std::vector<uint8_t> output =
ConvertFromKeymasterMessage(kBlob1.data(), kBlob1.size());
// Verify.
EXPECT_TRUE(VerifyVectorUint8(kBlob1.data(), kBlob1.size(), output));
}
TEST(ConvertFromKeymasterMessage, KeyParameterVector) {
// Prepare.
::keymaster::AuthorizationSet input;
input.push_back(keymaster_param_bool(KM_TAG_EARLY_BOOT_ONLY)); // bool
input.push_back(keymaster_param_enum(
KM_TAG_ALGORITHM,
KM_ALGORITHM_TRIPLE_DES)); // enum, enum_rep, int, int_rep
input.push_back(keymaster_param_long(KM_TAG_USER_SECURE_ID, 65537)); // long
input.push_back(
keymaster_param_date(KM_TAG_USAGE_EXPIRE_DATETIME, 1507)); // date
input.push_back(keymaster_param_blob(KM_TAG_APPLICATION_DATA, kBlob1.data(),
kBlob1.size())); // bignum, bytes
// Convert.
std::vector<arc::mojom::keymint::KeyParameterPtr> output =
ConvertFromKeymasterMessage(input);
// Verify.
EXPECT_TRUE(VerifyKeyParametersWithStrictInputs(input, output));
}
TEST(ConvertToKeymasterMessage, Buffer) {
// Prepare.
std::vector<uint8_t> input(kBlob1.begin(), kBlob1.end());
// Convert.
::keymaster::Buffer buffer;
ConvertToKeymasterMessage(input, &buffer);
uint8_t output[kBlob1.size()];
// Verify.
EXPECT_TRUE(buffer.read(output, input.size()));
EXPECT_TRUE(VerifyVectorUint8(output, input.size(), input));
}
TEST(ConvertToKeymasterMessage, ReusedBuffer) {
// Prepare.
std::vector<uint8_t> input1(kBlob1.begin(), kBlob1.end());
std::vector<uint8_t> input2(kBlob2.begin(), kBlob2.end());
// Convert.
::keymaster::Buffer buffer;
ConvertToKeymasterMessage(input1, &buffer);
ConvertToKeymasterMessage(input2, &buffer);
uint8_t output[kBlob2.size()];
// Verify.
EXPECT_TRUE(buffer.read(output, kBlob2.size()));
EXPECT_TRUE(VerifyVectorUint8(output, kBlob2.size(), input2));
}
TEST(ConvertToKeymasterMessage, ClientIdAndAppData) {
// Prepare.
std::vector<uint8_t> clientId(kBlob1.begin(), kBlob1.end());
std::vector<uint8_t> appData(kBlob2.begin(), kBlob2.end());
// Convert.
::keymaster::AuthorizationSet output;
ConvertToKeymasterMessage(clientId, appData, &output);
// Verify.
ASSERT_EQ(2, output.size());
EXPECT_EQ(KM_TAG_APPLICATION_ID, output[0].tag);
EXPECT_EQ(KM_TAG_APPLICATION_DATA, output[1].tag);
EXPECT_TRUE(VerifyVectorUint8(output[0].blob.data, output[0].blob.data_length,
clientId));
EXPECT_TRUE(VerifyVectorUint8(output[1].blob.data, output[1].blob.data_length,
appData));
}
} // namespace arc::keymint