summaryrefslogtreecommitdiff
path: root/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp')
-rw-r--r--security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp194
1 files changed, 170 insertions, 24 deletions
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 3da048449b..47892042e7 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -23,12 +23,12 @@
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <cppbor_parse.h>
-#include <cppcose/cppcose.h>
#include <cutils/properties.h>
#include <gmock/gmock.h>
#include <openssl/mem.h>
#include <remote_prov/remote_prov_utils.h>
+#include <keymaster/cppcose/cppcose.h>
#include <keymint_support/attestation_record.h>
#include <keymint_support/key_param_output.h>
#include <keymint_support/keymint_utils.h>
@@ -119,7 +119,6 @@ char nibble2hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
// Attestations don't contain everything in key authorization lists, so we need to filter the key
// lists to produce the lists that we expect to match the attestations.
auto kTagsToFilter = {
- Tag::BLOB_USAGE_REQUIREMENTS, //
Tag::CREATION_DATETIME, //
Tag::EC_CURVE,
Tag::HARDWARE_TYPE,
@@ -168,9 +167,11 @@ void KeyMintAidlTestBase::InitializeKeyMint(std::shared_ptr<IKeyMintDevice> keyM
securityLevel_ = info.securityLevel;
name_.assign(info.keyMintName.begin(), info.keyMintName.end());
author_.assign(info.keyMintAuthorName.begin(), info.keyMintAuthorName.end());
+ timestamp_token_required_ = info.timestampTokenRequired;
os_version_ = getOsVersion();
os_patch_level_ = getOsPatchlevel();
+ vendor_patch_level_ = getVendorPatchlevel();
}
void KeyMintAidlTestBase::SetUp() {
@@ -273,7 +274,8 @@ ErrorCode KeyMintAidlTestBase::ImportKey(const AuthorizationSet& key_desc, KeyFo
ErrorCode KeyMintAidlTestBase::ImportWrappedKey(string wrapped_key, string wrapping_key,
const AuthorizationSet& wrapping_key_desc,
string masking_key,
- const AuthorizationSet& unwrapping_params) {
+ const AuthorizationSet& unwrapping_params,
+ int64_t password_sid, int64_t biometric_sid) {
EXPECT_EQ(ErrorCode::OK, ImportKey(wrapping_key_desc, KeyFormat::PKCS8, wrapping_key));
key_characteristics_.clear();
@@ -282,8 +284,7 @@ ErrorCode KeyMintAidlTestBase::ImportWrappedKey(string wrapped_key, string wrapp
Status 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 */,
- &creationResult);
+ unwrapping_params.vector_data(), password_sid, biometric_sid, &creationResult);
if (result.isOk()) {
EXPECT_PRED2(KeyCharacteristicsBasicallyValid, SecLevel(),
@@ -332,6 +333,11 @@ ErrorCode KeyMintAidlTestBase::DeleteAllKeys() {
return GetReturnErrorCode(result);
}
+ErrorCode KeyMintAidlTestBase::DestroyAttestationIds() {
+ Status result = keymint_->destroyAttestationIds();
+ 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;
@@ -348,7 +354,7 @@ ErrorCode KeyMintAidlTestBase::Begin(KeyPurpose purpose, const vector<uint8_t>&
SCOPED_TRACE("Begin");
Status result;
BeginResult out;
- result = keymint_->begin(purpose, key_blob, in_params.vector_data(), HardwareAuthToken(), &out);
+ result = keymint_->begin(purpose, key_blob, in_params.vector_data(), std::nullopt, &out);
if (result.isOk()) {
*out_params = out.params;
@@ -366,7 +372,7 @@ ErrorCode KeyMintAidlTestBase::Begin(KeyPurpose purpose, const vector<uint8_t>&
Status result;
BeginResult out;
- result = keymint_->begin(purpose, key_blob, in_params.vector_data(), HardwareAuthToken(), &out);
+ result = keymint_->begin(purpose, key_blob, in_params.vector_data(), std::nullopt, &out);
if (result.isOk()) {
*out_params = out.params;
@@ -654,6 +660,18 @@ string KeyMintAidlTestBase::EncryptMessage(const string& message, BlockMode bloc
return ciphertext;
}
+string KeyMintAidlTestBase::EncryptMessage(const string& message, BlockMode block_mode,
+ PaddingMode padding, uint8_t mac_length_bits) {
+ SCOPED_TRACE("EncryptMessage");
+ auto params = AuthorizationSetBuilder()
+ .BlockMode(block_mode)
+ .Padding(padding)
+ .Authorization(TAG_MAC_LENGTH, mac_length_bits);
+ 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) {
@@ -744,6 +762,15 @@ vector<uint32_t> KeyMintAidlTestBase::InvalidKeySizes(Algorithm algorithm) {
return {224, 384, 521};
case Algorithm::AES:
return {192};
+ case Algorithm::TRIPLE_DES:
+ return {56};
+ default:
+ return {};
+ }
+ } else {
+ switch (algorithm) {
+ case Algorithm::TRIPLE_DES:
+ return {56};
default:
return {};
}
@@ -751,6 +778,68 @@ vector<uint32_t> KeyMintAidlTestBase::InvalidKeySizes(Algorithm algorithm) {
return {};
}
+vector<BlockMode> KeyMintAidlTestBase::ValidBlockModes(Algorithm algorithm) {
+ switch (algorithm) {
+ case Algorithm::AES:
+ return {
+ BlockMode::CBC,
+ BlockMode::CTR,
+ BlockMode::ECB,
+ BlockMode::GCM,
+ };
+ case Algorithm::TRIPLE_DES:
+ return {
+ BlockMode::CBC,
+ BlockMode::ECB,
+ };
+ default:
+ return {};
+ }
+}
+
+vector<PaddingMode> KeyMintAidlTestBase::ValidPaddingModes(Algorithm algorithm,
+ BlockMode blockMode) {
+ switch (algorithm) {
+ case Algorithm::AES:
+ switch (blockMode) {
+ case BlockMode::CBC:
+ case BlockMode::ECB:
+ return {PaddingMode::NONE, PaddingMode::PKCS7};
+ case BlockMode::CTR:
+ case BlockMode::GCM:
+ return {PaddingMode::NONE};
+ default:
+ return {};
+ };
+ case Algorithm::TRIPLE_DES:
+ switch (blockMode) {
+ case BlockMode::CBC:
+ case BlockMode::ECB:
+ return {PaddingMode::NONE, PaddingMode::PKCS7};
+ default:
+ return {};
+ };
+ default:
+ return {};
+ }
+}
+
+vector<PaddingMode> KeyMintAidlTestBase::InvalidPaddingModes(Algorithm algorithm,
+ BlockMode blockMode) {
+ switch (algorithm) {
+ case Algorithm::AES:
+ switch (blockMode) {
+ case BlockMode::CTR:
+ case BlockMode::GCM:
+ return {PaddingMode::PKCS7};
+ default:
+ return {};
+ };
+ default:
+ return {};
+ }
+}
+
vector<EcCurve> KeyMintAidlTestBase::ValidCurves() {
if (securityLevel_ == SecurityLevel::STRONGBOX) {
return {EcCurve::P_256};
@@ -845,6 +934,66 @@ ErrorCode KeyMintAidlTestBase::UseEcdsaKey(const vector<uint8_t>& ecdsaKeyBlob)
return result;
}
+void verify_serial(X509* cert, const uint64_t expected_serial) {
+ BIGNUM_Ptr ser(BN_new());
+ EXPECT_TRUE(ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), ser.get()));
+
+ uint64_t serial;
+ EXPECT_TRUE(BN_get_u64(ser.get(), &serial));
+ EXPECT_EQ(serial, expected_serial);
+}
+
+// Please set self_signed to true for fake certificates or self signed
+// certificates
+void verify_subject(const X509* cert, //
+ const string& subject, //
+ bool self_signed) {
+ char* cert_issuer = //
+ X509_NAME_oneline(X509_get_issuer_name(cert), nullptr, 0);
+
+ char* cert_subj = X509_NAME_oneline(X509_get_subject_name(cert), nullptr, 0);
+
+ string expected_subject("/CN=");
+ if (subject.empty()) {
+ expected_subject.append("Android Keystore Key");
+ } else {
+ expected_subject.append(subject);
+ }
+
+ EXPECT_STREQ(expected_subject.c_str(), cert_subj) << "Cert has wrong subject." << cert_subj;
+
+ if (self_signed) {
+ EXPECT_STREQ(cert_issuer, cert_subj)
+ << "Cert issuer and subject mismatch for self signed certificate.";
+ }
+
+ OPENSSL_free(cert_subj);
+ OPENSSL_free(cert_issuer);
+}
+
+vector<uint8_t> build_serial_blob(const uint64_t serial_int) {
+ BIGNUM_Ptr serial(BN_new());
+ EXPECT_TRUE(BN_set_u64(serial.get(), serial_int));
+
+ int len = BN_num_bytes(serial.get());
+ vector<uint8_t> serial_blob(len);
+ if (BN_bn2bin(serial.get(), serial_blob.data()) != len) {
+ return {};
+ }
+
+ return serial_blob;
+}
+
+void verify_subject_and_serial(const Certificate& certificate, //
+ const uint64_t expected_serial, //
+ const string& subject, bool self_signed) {
+ X509_Ptr cert(parse_cert_blob(certificate.encodedCertificate));
+ ASSERT_TRUE(!!cert.get());
+
+ verify_serial(cert.get(), expected_serial);
+ verify_subject(cert.get(), subject, self_signed);
+}
+
bool verify_attestation_record(const string& challenge, //
const string& app_id, //
AuthorizationSet expected_sw_enforced, //
@@ -882,17 +1031,21 @@ bool verify_attestation_record(const string& challenge, //
EXPECT_EQ(ErrorCode::OK, error);
if (error != ErrorCode::OK) return false;
- EXPECT_GE(att_attestation_version, 3U);
+ EXPECT_EQ(att_attestation_version, 100U);
+ vector<uint8_t> appId(app_id.begin(), app_id.end());
+
+ // check challenge and app id only if we expects a non-fake certificate
+ if (challenge.length() > 0) {
+ EXPECT_EQ(challenge.length(), att_challenge.size());
+ EXPECT_EQ(0, memcmp(challenge.data(), att_challenge.data(), challenge.length()));
- expected_sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID,
- vector<uint8_t>(app_id.begin(), app_id.end()));
+ expected_sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, appId);
+ }
- EXPECT_GE(att_keymaster_version, 4U);
+ EXPECT_EQ(att_keymaster_version, 100U);
EXPECT_EQ(security_level, att_keymaster_security_level);
EXPECT_EQ(security_level, att_attestation_security_level);
- EXPECT_EQ(challenge.length(), att_challenge.size());
- EXPECT_EQ(0, memcmp(challenge.data(), att_challenge.data(), challenge.length()));
char property_value[PROPERTY_VALUE_MAX] = {};
// TODO(b/136282179): When running under VTS-on-GSI the TEE-backed
@@ -1078,17 +1231,10 @@ AssertionResult ChainSignaturesAreValid(const vector<Certificate>& chain) {
string cert_issuer = x509NameToStr(X509_get_issuer_name(key_cert.get()));
string signer_subj = x509NameToStr(X509_get_subject_name(signing_cert.get()));
if (cert_issuer != signer_subj) {
- return AssertionFailure() << "Cert " << i << " has wrong issuer.\n" << cert_data.str();
- }
-
- if (i == 0) {
- string cert_sub = x509NameToStr(X509_get_subject_name(key_cert.get()));
- if ("/CN=Android Keystore Key" != cert_sub) {
- return AssertionFailure()
- << "Leaf cert has wrong subject, should be CN=Android Keystore Key, was "
- << cert_sub << '\n'
- << cert_data.str();
- }
+ return AssertionFailure() << "Cert " << i << " has wrong issuer.\n"
+ << " Signer subject is " << signer_subj
+ << " Issuer subject is " << cert_issuer << endl
+ << cert_data.str();
}
}