Merge changes I8539455e,I14f0d535 into main
* changes:
Cope with Keymaster->KeyMint device upgrade
Commonize upgrade_keyblob_if_required_with
diff --git a/identity/Android.bp b/identity/Android.bp
index 007a310..f7a540a 100644
--- a/identity/Android.bp
+++ b/identity/Android.bp
@@ -51,6 +51,7 @@
"liblog",
"libutils",
"libutilscallstack",
+ "libkeystore-attestation-application-id",
],
static_libs: [
"android.hardware.keymaster-V3-cpp",
@@ -60,7 +61,6 @@
"libcppbor_external",
"libcredstore_aidl",
"libkeymaster4support",
- "libkeystore-attestation-application-id",
"librkp_support",
],
}
diff --git a/keystore/Android.bp b/keystore/Android.bp
index 221ead9..c79d00b 100644
--- a/keystore/Android.bp
+++ b/keystore/Android.bp
@@ -69,19 +69,16 @@
defaults: ["keystore_defaults"],
srcs: [
- ":IKeyAttestationApplicationIdProvider.aidl",
"keystore_attestation_id.cpp",
- "KeyAttestationApplicationId.cpp",
- "KeyAttestationPackageInfo.cpp",
- "Signature.cpp",
],
shared_libs: [
+ "android.security.aaid_aidl-cpp",
"libbase",
"libbinder",
+ "libcrypto",
"libhidlbase",
"liblog",
"libutils",
- "libcrypto",
],
export_include_dirs: ["include"],
diff --git a/keystore/KeyAttestationApplicationId.cpp b/keystore/KeyAttestationApplicationId.cpp
deleted file mode 100644
index 1838b07..0000000
--- a/keystore/KeyAttestationApplicationId.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-**
-** Copyright 2016, 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 "include/keystore/KeyAttestationApplicationId.h"
-
-#include <binder/Parcel.h>
-
-namespace android {
-namespace security {
-namespace keymaster {
-
-KeyAttestationApplicationId::KeyAttestationApplicationId() = default;
-
-KeyAttestationApplicationId::KeyAttestationApplicationId(
- std::optional<KeyAttestationPackageInfo> package)
- : packageInfos_(new std::vector<std::optional<KeyAttestationPackageInfo>>()) {
- packageInfos_->push_back(std::move(package));
-}
-
-KeyAttestationApplicationId::KeyAttestationApplicationId(PackageInfoVector packages)
- : packageInfos_(std::make_shared<PackageInfoVector>(std::move(packages))) {}
-
-status_t KeyAttestationApplicationId::writeToParcel(Parcel* parcel) const {
- return parcel->writeParcelableVector(packageInfos_);
-}
-
-status_t KeyAttestationApplicationId::readFromParcel(const Parcel* parcel) {
- std::optional<std::vector<std::optional<KeyAttestationPackageInfo>>> temp_vector;
- auto rc = parcel->readParcelableVector(&temp_vector);
- if (rc != NO_ERROR) return rc;
- packageInfos_.reset();
- if (temp_vector) {
- packageInfos_ = std::make_shared<PackageInfoVector>(std::move(*temp_vector));
- }
- return NO_ERROR;
-}
-
-} // namespace keymaster
-} // namespace security
-} // namespace android
diff --git a/keystore/KeyAttestationPackageInfo.cpp b/keystore/KeyAttestationPackageInfo.cpp
deleted file mode 100644
index 8e9a36a..0000000
--- a/keystore/KeyAttestationPackageInfo.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-**
-** Copyright 2016, 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 "include/keystore/KeyAttestationPackageInfo.h"
-
-#include <binder/Parcel.h>
-
-namespace android {
-namespace security {
-namespace keymaster {
-
-KeyAttestationPackageInfo::KeyAttestationPackageInfo() = default;
-
-KeyAttestationPackageInfo::KeyAttestationPackageInfo(const String16& packageName,
- int64_t versionCode,
- SharedSignaturesVector signatures)
- : packageName_(packageName), versionCode_(versionCode), signatures_(signatures) {}
-
-status_t KeyAttestationPackageInfo::writeToParcel(Parcel* parcel) const {
- auto rc = parcel->writeString16(packageName_);
- if (rc != NO_ERROR) return rc;
- rc = parcel->writeInt64(versionCode_);
- if (rc != NO_ERROR) return rc;
- return parcel->writeParcelableVector(signatures_);
-}
-
-status_t KeyAttestationPackageInfo::readFromParcel(const Parcel* parcel) {
- auto rc = parcel->readString16(&packageName_);
- if (rc != NO_ERROR) return rc;
- rc = parcel->readInt64(&versionCode_);
- if (rc != NO_ERROR) return rc;
-
- std::optional<SignaturesVector> temp_vector;
- rc = parcel->readParcelableVector(&temp_vector);
- if (rc != NO_ERROR) return rc;
- signatures_.reset();
- if (temp_vector) {
- signatures_ = std::make_shared<SignaturesVector>(std::move(*temp_vector));
- }
- return NO_ERROR;
-}
-
-} // namespace keymaster
-} // namespace security
-} // namespace android
diff --git a/keystore/Signature.cpp b/keystore/Signature.cpp
deleted file mode 100644
index 284f358..0000000
--- a/keystore/Signature.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-**
-** Copyright 2016, 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 "include/keystore/Signature.h"
-
-#include <binder/Parcel.h>
-
-namespace android {
-namespace content {
-namespace pm {
-
-status_t Signature::writeToParcel(Parcel* parcel) const {
- return parcel->writeByteVector(sig_data_);
-}
-
-status_t Signature::readFromParcel(const Parcel* parcel) {
- return parcel->readByteVector(&sig_data_);
-}
-
-Signature::Signature(std::vector<uint8_t> signature_data) : sig_data_(std::move(signature_data)) {}
-
-} // namespace pm
-} // namespace content
-} // namespace android
diff --git a/keystore/include/keystore/KeyAttestationApplicationId.h b/keystore/include/keystore/KeyAttestationApplicationId.h
deleted file mode 100644
index 0bf1aad..0000000
--- a/keystore/include/keystore/KeyAttestationApplicationId.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
-#define KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
-
-#include <memory>
-#include <optional>
-#include <vector>
-
-#include <binder/Parcelable.h>
-
-#include "KeyAttestationPackageInfo.h"
-
-namespace android {
-namespace security {
-namespace keymaster {
-
-class KeyAttestationApplicationId : public Parcelable {
- public:
- typedef SharedNullableIterator<const KeyAttestationPackageInfo, std::vector>
- ConstKeyAttestationPackageInfoIterator;
- typedef std::vector<std::optional<KeyAttestationPackageInfo>> PackageInfoVector;
- KeyAttestationApplicationId();
- // Following c'tors are for initializing instances containing test data.
- explicit KeyAttestationApplicationId(std::optional<KeyAttestationPackageInfo> package);
- explicit KeyAttestationApplicationId(PackageInfoVector packages);
-
- status_t writeToParcel(Parcel*) const override;
- status_t readFromParcel(const Parcel* parcel) override;
-
- ConstKeyAttestationPackageInfoIterator pinfos_begin() const {
- return ConstKeyAttestationPackageInfoIterator(packageInfos_);
- }
- ConstKeyAttestationPackageInfoIterator pinfos_end() const {
- return ConstKeyAttestationPackageInfoIterator();
- }
-
- private:
- std::shared_ptr<PackageInfoVector> packageInfos_;
-};
-
-} // namespace keymaster
-} // namespace security
-} // namespace android
-
-#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
diff --git a/keystore/include/keystore/KeyAttestationPackageInfo.h b/keystore/include/keystore/KeyAttestationPackageInfo.h
deleted file mode 100644
index fa638f9..0000000
--- a/keystore/include/keystore/KeyAttestationPackageInfo.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
-#define KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <optional>
-#include <vector>
-
-#include <binder/Parcelable.h>
-
-#include "Signature.h"
-#include "utils.h"
-
-namespace android {
-namespace security {
-namespace keymaster {
-
-class KeyAttestationPackageInfo : public Parcelable {
- public:
- typedef SharedNullableIterator<const content::pm::Signature, std::vector>
- ConstSignatureIterator;
- typedef std::vector<std::optional<content::pm::Signature>> SignaturesVector;
- typedef std::shared_ptr<SignaturesVector> SharedSignaturesVector;
-
- KeyAttestationPackageInfo(const String16& packageName, int64_t versionCode,
- SharedSignaturesVector signatures);
- KeyAttestationPackageInfo();
-
- status_t writeToParcel(Parcel*) const override;
- status_t readFromParcel(const Parcel* parcel) override;
-
- const std::optional<String16>& package_name() const { return packageName_; }
- int64_t version_code() const { return versionCode_; }
-
- ConstSignatureIterator sigs_begin() const { return ConstSignatureIterator(signatures_); }
- ConstSignatureIterator sigs_end() const { return ConstSignatureIterator(); }
-
- private:
- std::optional<String16> packageName_;
- int64_t versionCode_;
- SharedSignaturesVector signatures_;
-};
-
-} // namespace keymaster
-} // namespace security
-} // namespace android
-
-#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
diff --git a/keystore/include/keystore/Signature.h b/keystore/include/keystore/Signature.h
deleted file mode 100644
index f39acec..0000000
--- a/keystore/include/keystore/Signature.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef KEYSTORE_INCLUDE_KEYSTORE_SIGNATURE_H_
-#define KEYSTORE_INCLUDE_KEYSTORE_SIGNATURE_H_
-
-#include <vector>
-
-#include <binder/Parcelable.h>
-
-namespace android {
-namespace content {
-namespace pm {
-
-class Signature : public Parcelable {
- public:
- Signature() = default;
- // Intended for initializing instances containing test data.
- explicit Signature(std::vector<uint8_t> signature_data);
-
- status_t writeToParcel(Parcel*) const override;
- status_t readFromParcel(const Parcel* parcel) override;
-
- const std::vector<uint8_t>& data() const & { return sig_data_; }
- std::vector<uint8_t>& data() & { return sig_data_; }
- std::vector<uint8_t>&& data() && { return std::move(sig_data_); }
-
- private:
- std::vector<uint8_t> sig_data_;
-};
-
-} // namespace pm
-} // namespace content
-} // namespace android
-
-#endif // KEYSTORE_INCLUDE_KEYSTORE_SIGNATURE_H_
diff --git a/keystore/include/keystore/keystore_attestation_id.h b/keystore/include/keystore/keystore_attestation_id.h
index 238f4b1..a0d43ad 100644
--- a/keystore/include/keystore/keystore_attestation_id.h
+++ b/keystore/include/keystore/keystore_attestation_id.h
@@ -25,11 +25,11 @@
constexpr size_t KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE = 1024;
-namespace keymaster {
+namespace keystore {
class KeyAttestationApplicationId;
-} // namespace keymaster
+} // namespace keystore
template <typename T> class StatusOr {
public:
@@ -77,7 +77,7 @@
*/
StatusOr<std::vector<uint8_t>> build_attestation_application_id(
- const ::android::security::keymaster::KeyAttestationApplicationId& key_attestation_id);
+ const ::android::security::keystore::KeyAttestationApplicationId& key_attestation_id);
} // namespace security
} // namespace android
diff --git a/keystore/keystore_attestation_id.cpp b/keystore/keystore_attestation_id.cpp
index 8eade97..1534be1 100644
--- a/keystore/keystore_attestation_id.cpp
+++ b/keystore/keystore_attestation_id.cpp
@@ -29,11 +29,11 @@
#include <binder/Parcelable.h>
#include <binder/PersistableBundle.h>
-#include <android/security/keymaster/BpKeyAttestationApplicationIdProvider.h>
-#include <android/security/keymaster/IKeyAttestationApplicationIdProvider.h>
-#include <keystore/KeyAttestationApplicationId.h>
-#include <keystore/KeyAttestationPackageInfo.h>
-#include <keystore/Signature.h>
+#include <android/security/keystore/BpKeyAttestationApplicationIdProvider.h>
+#include <android/security/keystore/IKeyAttestationApplicationIdProvider.h>
+#include <android/security/keystore/KeyAttestationApplicationId.h>
+#include <android/security/keystore/KeyAttestationPackageInfo.h>
+#include <android/security/keystore/Signature.h>
#include <private/android_filesystem_config.h> /* for AID_SYSTEM */
@@ -50,13 +50,13 @@
constexpr const char* kAttestationSystemPackageName = "AndroidSystem";
constexpr const char* kUnknownPackageName = "UnknownPackage";
-std::vector<uint8_t> signature2SHA256(const content::pm::Signature& sig) {
+std::vector<uint8_t> signature2SHA256(const security::keystore::Signature& sig) {
std::vector<uint8_t> digest_buffer(SHA256_DIGEST_LENGTH);
- SHA256(sig.data().data(), sig.data().size(), digest_buffer.data());
+ SHA256(sig.data.data(), sig.data.size(), digest_buffer.data());
return digest_buffer;
}
-using ::android::security::keymaster::BpKeyAttestationApplicationIdProvider;
+using ::android::security::keystore::BpKeyAttestationApplicationIdProvider;
class KeyAttestationApplicationIdProvider : public BpKeyAttestationApplicationIdProvider {
public:
@@ -141,8 +141,8 @@
namespace security {
namespace {
-using ::android::security::keymaster::KeyAttestationApplicationId;
-using ::android::security::keymaster::KeyAttestationPackageInfo;
+using ::android::security::keystore::KeyAttestationApplicationId;
+using ::android::security::keystore::KeyAttestationPackageInfo;
status_t build_attestation_package_info(const KeyAttestationPackageInfo& pinfo,
std::unique_ptr<KM_ATTESTATION_PACKAGE_INFO>* attestation_package_info_ptr) {
@@ -153,12 +153,12 @@
attestation_package_info.reset(KM_ATTESTATION_PACKAGE_INFO_new());
if (!attestation_package_info.get()) return NO_MEMORY;
- if (!pinfo.package_name()) {
+ if (!pinfo.packageName) {
ALOGE("Key attestation package info lacks package name");
return BAD_VALUE;
}
- std::string pkg_name(String8(*pinfo.package_name()).c_str());
+ std::string pkg_name(String8(pinfo.packageName).c_str());
if (!ASN1_OCTET_STRING_set(attestation_package_info->package_name,
reinterpret_cast<const unsigned char*>(pkg_name.data()),
pkg_name.size())) {
@@ -169,7 +169,7 @@
if (bn_version == nullptr) {
return NO_MEMORY;
}
- if (BN_set_u64(bn_version, static_cast<uint64_t>(pinfo.version_code())) != 1) {
+ if (BN_set_u64(bn_version, static_cast<uint64_t>(pinfo.versionCode)) != 1) {
BN_free(bn_version);
return UNKNOWN_ERROR;
}
@@ -201,15 +201,16 @@
auto attestation_pinfo_stack = reinterpret_cast<_STACK*>(attestation_id->package_infos);
- if (key_attestation_id.pinfos_begin() == key_attestation_id.pinfos_end()) return BAD_VALUE;
+ if (key_attestation_id.packageInfos.begin() == key_attestation_id.packageInfos.end())
+ return BAD_VALUE;
- for (auto pinfo = key_attestation_id.pinfos_begin(); pinfo != key_attestation_id.pinfos_end();
- ++pinfo) {
- if (!pinfo->package_name()) {
+ for (auto pinfo = key_attestation_id.packageInfos.begin();
+ pinfo != key_attestation_id.packageInfos.end(); ++pinfo) {
+ if (!pinfo->packageName) {
ALOGE("Key attestation package info lacks package name");
return BAD_VALUE;
}
- std::string package_name(String8(*pinfo->package_name()).c_str());
+ std::string package_name(String8(pinfo->packageName).c_str());
std::unique_ptr<KM_ATTESTATION_PACKAGE_INFO> attestation_package_info;
auto rc = build_attestation_package_info(*pinfo, &attestation_package_info);
if (rc != NO_ERROR) {
@@ -231,10 +232,10 @@
* signature field actually holds the signing certificate, rather than a signature, we can
* simply use the set of signature digests of the first package info.
*/
- const auto& pinfo = *key_attestation_id.pinfos_begin();
+ const auto& pinfo = *key_attestation_id.packageInfos.begin();
std::vector<std::vector<uint8_t>> signature_digests;
- for (auto sig = pinfo.sigs_begin(); sig != pinfo.sigs_end(); ++sig) {
+ for (auto sig = pinfo.signatures.begin(); sig != pinfo.signatures.end(); ++sig) {
signature_digests.push_back(signature2SHA256(*sig));
}
@@ -271,10 +272,10 @@
if (uid == AID_SYSTEM) {
/* Use a fixed ID for system callers */
- auto pinfo = std::make_optional<KeyAttestationPackageInfo>(
- String16(kAttestationSystemPackageName), 1 /* version code */,
- std::make_shared<KeyAttestationPackageInfo::SignaturesVector>());
- key_attestation_id = KeyAttestationApplicationId(std::move(pinfo));
+ auto pinfo = KeyAttestationPackageInfo();
+ pinfo.packageName = String16(kAttestationSystemPackageName);
+ pinfo.versionCode = 1;
+ key_attestation_id.packageInfos.push_back(std::move(pinfo));
} else {
/* Get the attestation application ID from package manager */
auto& pm = KeyAttestationApplicationIdProvider::get();
@@ -284,10 +285,11 @@
if (!status.isOk()) {
ALOGW("package manager request for key attestation ID failed with: %s %d",
status.exceptionMessage().c_str(), status.exceptionCode());
- auto pinfo = std::make_optional<KeyAttestationPackageInfo>(
- String16(kUnknownPackageName), 1 /* version code */,
- std::make_shared<KeyAttestationPackageInfo::SignaturesVector>());
- key_attestation_id = KeyAttestationApplicationId(std::move(pinfo));
+
+ auto pinfo = KeyAttestationPackageInfo();
+ pinfo.packageName = String16(kUnknownPackageName);
+ pinfo.versionCode = 1;
+ key_attestation_id.packageInfos.push_back(std::move(pinfo));
}
}
diff --git a/keystore/tests/Android.bp b/keystore/tests/Android.bp
index f51cc2f..e641f44 100644
--- a/keystore/tests/Android.bp
+++ b/keystore/tests/Android.bp
@@ -35,6 +35,7 @@
"libutils",
],
shared_libs: [
+ "android.security.aaid_aidl-cpp",
"libbinder",
"libkeymaster_messages",
"libkeystore-attestation-application-id",
diff --git a/keystore/tests/aaid_truncation_test.cpp b/keystore/tests/aaid_truncation_test.cpp
index fa4d769..3a94ec1 100644
--- a/keystore/tests/aaid_truncation_test.cpp
+++ b/keystore/tests/aaid_truncation_test.cpp
@@ -22,14 +22,14 @@
#include <keymaster/logger.h>
#include <keystore/keystore_attestation_id.h>
-#include <keystore/KeyAttestationApplicationId.h>
-#include <keystore/KeyAttestationPackageInfo.h>
-#include <keystore/Signature.h>
+#include <android/security/keystore/KeyAttestationApplicationId.h>
+#include <android/security/keystore/KeyAttestationPackageInfo.h>
+#include <android/security/keystore/Signature.h>
using ::android::String16;
using ::android::security::KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE;
-using ::android::security::keymaster::KeyAttestationApplicationId;
-using ::android::security::keymaster::KeyAttestationPackageInfo;
+using ::android::security::keystore::KeyAttestationApplicationId;
+using ::android::security::keystore::KeyAttestationPackageInfo;
using std::vector;
namespace keystore {
@@ -72,24 +72,27 @@
} // namespace
-using ::android::content::pm::Signature;
using ::android::security::build_attestation_application_id;
+using ::android::security::keystore::Signature;
-std::optional<KeyAttestationPackageInfo>
-make_package_info_with_signatures(const char* package_name,
- KeyAttestationPackageInfo::SignaturesVector signatures) {
- return std::make_optional<KeyAttestationPackageInfo>(
- String16(package_name), 1 /* version code */,
- std::make_shared<KeyAttestationPackageInfo::SignaturesVector>(std::move(signatures)));
+KeyAttestationPackageInfo make_package_info_with_signatures(const char* package_name,
+ std::vector<Signature> signatures) {
+ auto pInfo = KeyAttestationPackageInfo();
+ pInfo.packageName = String16(package_name);
+ pInfo.versionCode = 1;
+ std::move(signatures.begin(), signatures.end(), std::back_inserter(pInfo.signatures));
+
+ return pInfo;
}
-std::optional<KeyAttestationPackageInfo> make_package_info(const char* package_name) {
- return make_package_info_with_signatures(package_name,
- KeyAttestationPackageInfo::SignaturesVector());
+KeyAttestationPackageInfo make_package_info(const char* package_name) {
+ return make_package_info_with_signatures(package_name, std::vector<Signature>());
}
TEST(AaidTruncationTest, shortPackageInfoTest) {
- KeyAttestationApplicationId app_id(make_package_info(kDummyPackageName));
+ KeyAttestationApplicationId app_id;
+ auto pInfo = make_package_info(kDummyPackageName);
+ app_id.packageInfos.push_back(std::move(pInfo));
auto result = build_attestation_application_id(app_id);
ASSERT_TRUE(result.isOk());
@@ -98,7 +101,9 @@
}
TEST(AaidTruncationTest, tooLongPackageNameTest) {
- KeyAttestationApplicationId app_id(make_package_info(kLongPackageName));
+ KeyAttestationApplicationId app_id;
+ auto pInfo = make_package_info(kLongPackageName);
+ app_id.packageInfos.push_back(std::move(pInfo));
auto result = build_attestation_application_id(app_id);
ASSERT_TRUE(result.isOk());
@@ -108,14 +113,17 @@
TEST(AaidTruncationTest, tooManySignaturesTest) {
std::vector<uint8_t> dummy_sig_data(kDummySignature, kDummySignature + 32);
- KeyAttestationPackageInfo::SignaturesVector signatures;
+ std::vector<Signature> signatures;
// Add 35 signatures which will surely exceed the 1K limit.
for (size_t i = 0; i < kTooManySignatures; ++i) {
- signatures.push_back(std::make_optional<Signature>(dummy_sig_data));
+ auto sign = Signature();
+ sign.data = dummy_sig_data;
+ signatures.push_back(std::move(sign));
}
- KeyAttestationApplicationId app_id(
- make_package_info_with_signatures(kDummyPackageName, std::move(signatures)));
+ auto pInfo = make_package_info_with_signatures(kDummyPackageName, std::move(signatures));
+ KeyAttestationApplicationId app_id;
+ app_id.packageInfos.push_back(std::move(pInfo));
auto result = build_attestation_application_id(app_id);
ASSERT_TRUE(result.isOk());
@@ -125,19 +133,22 @@
TEST(AaidTruncationTest, combinedPackagesAndSignaturesTest) {
std::vector<uint8_t> dummy_sig_data(kDummySignature, kDummySignature + 32);
- KeyAttestationApplicationId::PackageInfoVector packages;
+ ::std::vector<KeyAttestationPackageInfo> packages;
for (size_t i = 0; i < kTooManyPackages; ++i) {
- KeyAttestationPackageInfo::SignaturesVector signatures;
+ std::vector<Signature> signatures;
// Add a few signatures for each package
for (int j = 0; j < 3; ++j) {
- signatures.push_back(std::make_optional<Signature>(dummy_sig_data));
+ auto sign = Signature();
+ sign.data = dummy_sig_data;
+ signatures.push_back(std::move(sign));
}
- packages.push_back(
- make_package_info_with_signatures(kReasonablePackageName, std::move(signatures)));
+ packages.push_back(std::move(
+ make_package_info_with_signatures(kReasonablePackageName, std::move(signatures))));
}
+ KeyAttestationApplicationId app_id;
+ std::move(packages.begin(), packages.end(), std::back_inserter(app_id.packageInfos));
- KeyAttestationApplicationId app_id(std::move(packages));
auto result = build_attestation_application_id(app_id);
ASSERT_TRUE(result.isOk());
std::vector<uint8_t>& encoded_app_id = result;
diff --git a/keystore/tests/fuzzer/Android.bp b/keystore/tests/fuzzer/Android.bp
index 4116ae1..5df5c7a 100644
--- a/keystore/tests/fuzzer/Android.bp
+++ b/keystore/tests/fuzzer/Android.bp
@@ -55,6 +55,7 @@
"libhidlbase",
],
shared_libs: [
+ "android.security.aaid_aidl-cpp",
"libbinder",
"libcrypto",
"libutils",
diff --git a/keystore/tests/fuzzer/keystoreApplicationId_fuzzer.cpp b/keystore/tests/fuzzer/keystoreApplicationId_fuzzer.cpp
index 0eddb9a..9388001 100644
--- a/keystore/tests/fuzzer/keystoreApplicationId_fuzzer.cpp
+++ b/keystore/tests/fuzzer/keystoreApplicationId_fuzzer.cpp
@@ -15,9 +15,9 @@
*/
#include "keystoreCommon.h"
-#include <keystore/KeyAttestationApplicationId.h>
+#include <android/security/keystore/KeyAttestationApplicationId.h>
-using ::security::keymaster::KeyAttestationApplicationId;
+using ::android::security::keystore::KeyAttestationApplicationId;
constexpr size_t kPackageVectorSizeMin = 1;
constexpr size_t kPackageVectorSizeMax = 10;
@@ -33,26 +33,37 @@
};
void KeystoreApplicationId::invokeApplicationId() {
- std::optional<KeyAttestationApplicationId> applicationId;
+ KeyAttestationApplicationId applicationId;
bool shouldUsePackageInfoVector = mFdp->ConsumeBool();
if (shouldUsePackageInfoVector) {
- KeyAttestationApplicationId::PackageInfoVector packageInfoVector;
+ ::std::vector<KeyAttestationPackageInfo> packageInfoVector;
int32_t packageVectorSize =
mFdp->ConsumeIntegralInRange<int32_t>(kPackageVectorSizeMin, kPackageVectorSizeMax);
for (int32_t packageSize = 0; packageSize < packageVectorSize; ++packageSize) {
auto packageInfoData = initPackageInfoData(mFdp.get());
- packageInfoVector.push_back(make_optional<KeyAttestationPackageInfo>(
- String16((packageInfoData.packageName).c_str()), packageInfoData.versionCode,
- packageInfoData.sharedSignaturesVector));
+ auto pInfo = KeyAttestationPackageInfo();
+ pInfo.packageName = String16((packageInfoData.packageName).c_str());
+ pInfo.versionCode = packageInfoData.versionCode;
+ std::move(packageInfoData.sharedSignaturesVector->begin(),
+ packageInfoData.sharedSignaturesVector->end(),
+ std::back_inserter(pInfo.signatures));
+
+ packageInfoVector.push_back(std::move(pInfo));
}
- applicationId = KeyAttestationApplicationId(std::move(packageInfoVector));
+
+ std::move(packageInfoVector.begin(), packageInfoVector.end(),
+ std::back_inserter(applicationId.packageInfos));
} else {
auto packageInfoData = initPackageInfoData(mFdp.get());
- applicationId = KeyAttestationApplicationId(make_optional<KeyAttestationPackageInfo>(
- String16((packageInfoData.packageName).c_str()), packageInfoData.versionCode,
- packageInfoData.sharedSignaturesVector));
+ auto pInfo = KeyAttestationPackageInfo();
+ pInfo.packageName = String16((packageInfoData.packageName).c_str());
+ pInfo.versionCode = packageInfoData.versionCode;
+ std::move(packageInfoData.sharedSignaturesVector->begin(),
+ packageInfoData.sharedSignaturesVector->end(),
+ std::back_inserter(pInfo.signatures));
+ applicationId.packageInfos.push_back(std::move(pInfo));
}
- invokeReadWriteParcel(&applicationId.value());
+ invokeReadWriteParcel(&applicationId);
}
void KeystoreApplicationId::process(const uint8_t* data, size_t size) {
diff --git a/keystore/tests/fuzzer/keystoreCommon.h b/keystore/tests/fuzzer/keystoreCommon.h
index e1265bf..77d39e0 100644
--- a/keystore/tests/fuzzer/keystoreCommon.h
+++ b/keystore/tests/fuzzer/keystoreCommon.h
@@ -16,18 +16,18 @@
#ifndef KEYSTORECOMMON_H
#define KEYSTORECOMMON_H
+#include <android/security/keystore/KeyAttestationPackageInfo.h>
+#include <android/security/keystore/Signature.h>
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
-#include <keystore/KeyAttestationPackageInfo.h>
-#include <keystore/Signature.h>
#include <vector>
#include "fuzzer/FuzzedDataProvider.h"
using namespace android;
using namespace std;
-using ::content::pm::Signature;
-using ::security::keymaster::KeyAttestationPackageInfo;
+using ::android::security::keystore::KeyAttestationPackageInfo;
+using ::android::security::keystore::Signature;
constexpr size_t kSignatureSizeMin = 1;
constexpr size_t kSignatureSizeMax = 1000;
@@ -38,7 +38,7 @@
struct PackageInfoData {
string packageName;
int64_t versionCode;
- KeyAttestationPackageInfo::SharedSignaturesVector sharedSignaturesVector;
+ std::shared_ptr<std::vector<Signature>> sharedSignaturesVector;
};
inline void invokeReadWriteParcel(Parcelable* obj) {
@@ -60,18 +60,20 @@
packageInfoData.versionCode = fdp->ConsumeIntegral<int64_t>();
size_t signatureVectorSize =
fdp->ConsumeIntegralInRange(kSignatureVectorSizeMin, kSignatureVectorSizeMax);
- KeyAttestationPackageInfo::SignaturesVector signatureVector;
+ std::vector<Signature> signatureVector;
for (size_t size = 0; size < signatureVectorSize; ++size) {
bool shouldUseParameterizedConstructor = fdp->ConsumeBool();
if (shouldUseParameterizedConstructor) {
vector<uint8_t> signatureData = initSignatureData(fdp);
- signatureVector.push_back(make_optional<Signature>(signatureData));
+ auto sign = Signature();
+ sign.data = signatureData;
+ signatureVector.push_back(std::move(sign));
} else {
- signatureVector.push_back(std::nullopt);
+ signatureVector.push_back(Signature());
}
}
packageInfoData.sharedSignaturesVector =
- make_shared<KeyAttestationPackageInfo::SignaturesVector>(std::move(signatureVector));
+ make_shared<std::vector<Signature>>(std::move(signatureVector));
return packageInfoData;
}
#endif // KEYSTORECOMMON_H
diff --git a/keystore/tests/fuzzer/keystorePackageInfo_fuzzer.cpp b/keystore/tests/fuzzer/keystorePackageInfo_fuzzer.cpp
index 63899ff..f1e4204 100644
--- a/keystore/tests/fuzzer/keystorePackageInfo_fuzzer.cpp
+++ b/keystore/tests/fuzzer/keystorePackageInfo_fuzzer.cpp
@@ -28,9 +28,12 @@
void KeystorePackageInfoFuzzer::invokePackageInfo() {
auto packageInfoData = initPackageInfoData(mFdp.get());
- KeyAttestationPackageInfo packageInfo(String16((packageInfoData.packageName).c_str()),
- packageInfoData.versionCode,
- packageInfoData.sharedSignaturesVector);
+ auto packageInfo = KeyAttestationPackageInfo();
+ packageInfo.packageName = String16((packageInfoData.packageName).c_str());
+ packageInfo.versionCode = packageInfoData.versionCode;
+ std::move(packageInfoData.sharedSignaturesVector->begin(),
+ packageInfoData.sharedSignaturesVector->end(),
+ std::back_inserter(packageInfo.signatures));
invokeReadWriteParcel(&packageInfo);
}
diff --git a/keystore/tests/fuzzer/keystoreSignature_fuzzer.cpp b/keystore/tests/fuzzer/keystoreSignature_fuzzer.cpp
index b8f8a73..aab1f25 100644
--- a/keystore/tests/fuzzer/keystoreSignature_fuzzer.cpp
+++ b/keystore/tests/fuzzer/keystoreSignature_fuzzer.cpp
@@ -14,7 +14,9 @@
* limitations under the License.
*/
#include "keystoreCommon.h"
-#include <keystore/Signature.h>
+#include <android/security/keystore/Signature.h>
+
+using ::android::security::keystore::Signature;
class KeystoreSignatureFuzzer {
public:
@@ -27,15 +29,15 @@
};
void KeystoreSignatureFuzzer::invokeSignature() {
- std::optional<Signature> signature;
+ Signature signature;
bool shouldUseParameterizedConstructor = mFdp->ConsumeBool();
if (shouldUseParameterizedConstructor) {
std::vector<uint8_t> signatureData = initSignatureData(mFdp.get());
- signature = Signature(signatureData);
+ signature.data = signatureData;
} else {
signature = Signature();
}
- invokeReadWriteParcel(&signature.value());
+ invokeReadWriteParcel(&signature);
}
void KeystoreSignatureFuzzer::process(const uint8_t* data, size_t size) {
diff --git a/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl b/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
index 6a37c78..9618842 100644
--- a/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
+++ b/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
@@ -28,10 +28,10 @@
/**
* Allows LockSettingsService to inform keystore about adding a new user.
- * Callers require 'AddUser' permission.
+ * Callers require 'ChangeUser' permission.
*
* ## Error conditions:
- * `ResponseCode::PERMISSION_DENIED` - if the callers do not have the 'AddUser' permission.
+ * `ResponseCode::PERMISSION_DENIED` - if the callers do not have the 'ChangeUser' permission.
* `ResponseCode::SYSTEM_ERROR` - if failed to delete the keys of an existing user with the same
* user id.
*
@@ -41,10 +41,10 @@
/**
* Allows LockSettingsService to inform keystore about removing a user.
- * Callers require 'RemoveUser' permission.
+ * Callers require 'ChangeUser' permission.
*
* ## Error conditions:
- * `ResponseCode::PERMISSION_DENIED` - if the callers do not have the 'RemoveUser' permission.
+ * `ResponseCode::PERMISSION_DENIED` - if the callers do not have the 'ChangeUser' permission.
* `ResponseCode::SYSTEM_ERROR` - if failed to delete the keys of the user being deleted.
*
* @param userId - Android user id
diff --git a/keystore2/test_utils/Android.bp b/keystore2/test_utils/Android.bp
index b2360db..a3c40cb 100644
--- a/keystore2/test_utils/Android.bp
+++ b/keystore2/test_utils/Android.bp
@@ -35,6 +35,7 @@
"liblog_rust",
"libnix",
"librand",
+ "librustutils",
"libserde",
"libserde_cbor",
"libthiserror",
@@ -43,11 +44,10 @@
"libkeystore2_ffi_test_utils",
],
shared_libs: [
+ "libbase",
"libcrypto",
- "libkeymaster_messages",
"libkeymaster_portable",
"libkeymint_support",
- "libkeymint_vts_test_utils",
"libkeystore-engine",
],
}
@@ -73,8 +73,7 @@
name: "libkeystore2_ffi_test_utils",
srcs: ["ffi_test_utils.cpp"],
defaults: [
- "keymint_vts_defaults",
- "hidl_defaults",
+ "keymint_use_latest_hal_aidl_ndk_shared",
],
generated_headers: [
"cxx-bridge-header",
@@ -82,11 +81,11 @@
],
generated_sources: ["libkeystore2_ffi_test_utils_bridge_code"],
shared_libs: [
- "libcppbor_external",
- "libkeymaster_messages",
+ "libbase",
+ "libcrypto",
"libkeymaster_portable",
"libkeystore-engine",
- "libkeymint_vts_test_utils",
+ "libkeymint_support",
],
}
diff --git a/keystore2/test_utils/authorizations.rs b/keystore2/test_utils/authorizations.rs
index 514cbd3..aa75982 100644
--- a/keystore2/test_utils/authorizations.rs
+++ b/keystore2/test_utils/authorizations.rs
@@ -242,6 +242,33 @@
});
self
}
+
+ /// Set active date-time.
+ pub fn active_date_time(mut self, date: i64) -> Self {
+ self.0.push(KeyParameter {
+ tag: Tag::ACTIVE_DATETIME,
+ value: KeyParameterValue::DateTime(date),
+ });
+ self
+ }
+
+ /// Set origination expire date-time.
+ pub fn origination_expire_date_time(mut self, date: i64) -> Self {
+ self.0.push(KeyParameter {
+ tag: Tag::ORIGINATION_EXPIRE_DATETIME,
+ value: KeyParameterValue::DateTime(date),
+ });
+ self
+ }
+
+ /// Set usage expire date-time.
+ pub fn usage_expire_date_time(mut self, date: i64) -> Self {
+ self.0.push(KeyParameter {
+ tag: Tag::USAGE_EXPIRE_DATETIME,
+ value: KeyParameterValue::DateTime(date),
+ });
+ self
+ }
}
impl Deref for AuthSetBuilder {
diff --git a/keystore2/test_utils/ffi_test_utils.cpp b/keystore2/test_utils/ffi_test_utils.cpp
index 7fbfb8b..0740804 100644
--- a/keystore2/test_utils/ffi_test_utils.cpp
+++ b/keystore2/test_utils/ffi_test_utils.cpp
@@ -1,26 +1,22 @@
#include "ffi_test_utils.hpp"
#include <iostream>
-
-#include <android-base/logging.h>
-
-#include <KeyMintAidlTestBase.h>
-#include <aidl/android/hardware/security/keymint/ErrorCode.h>
-#include <keymaster/UniquePtr.h>
-
#include <vector>
-#include <hardware/keymaster_defs.h>
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/keymaster_tags.h>
-
+#include <android-base/logging.h>
#include <keymaster/km_openssl/attestation_record.h>
#include <keymaster/km_openssl/openssl_err.h>
#include <keymaster/km_openssl/openssl_utils.h>
+#include <keymint_support/attestation_record.h>
+#include <keymint_support/keymint_utils.h>
+#include <openssl/mem.h>
-#include <android-base/logging.h>
-
-using aidl::android::hardware::security::keymint::ErrorCode;
+using keymaster::ASN1_OBJECT_Ptr;
+using keymaster::EVP_PKEY_Ptr;
+using keymaster::X509_Ptr;
+using std::endl;
+using std::string;
+using std::vector;
#define TAG_SEQUENCE 0x30
#define LENGTH_MASK 0x80
@@ -29,6 +25,8 @@
/* EVP_PKEY_from_keystore is from system/security/keystore-engine. */
extern "C" EVP_PKEY* EVP_PKEY_from_keystore(const char* key_id);
+typedef std::vector<uint8_t> certificate_t;
+
/**
* ASN.1 structure for `KeyDescription` Schema.
* See `IKeyMintDevice.aidl` for documentation of the `KeyDescription` schema.
@@ -91,6 +89,94 @@
const std::string keystore2_grant_id_prefix("ks2_keystore-engine_grant_id:");
+string bin2hex(const vector<uint8_t>& data) {
+ string retval;
+ char nibble2hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ retval.reserve(data.size() * 2 + 1);
+ for (uint8_t byte : data) {
+ retval.push_back(nibble2hex[0x0F & (byte >> 4)]);
+ retval.push_back(nibble2hex[0x0F & byte]);
+ }
+ return retval;
+}
+
+string x509NameToStr(X509_NAME* name) {
+ char* s = X509_NAME_oneline(name, nullptr, 0);
+ string retval(s);
+ OPENSSL_free(s);
+ return retval;
+}
+
+X509_Ptr parseCertBlob(const vector<uint8_t>& blob) {
+ const uint8_t* p = blob.data();
+ return X509_Ptr(d2i_X509(nullptr /* allocate new */, &p, blob.size()));
+}
+
+// Extract attestation record from cert. Returned object is still part of cert; don't free it
+// separately.
+ASN1_OCTET_STRING* getAttestationRecord(X509* certificate) {
+ ASN1_OBJECT_Ptr oid(OBJ_txt2obj(aidl::android::hardware::security::keymint::kAttestionRecordOid,
+ 1 /* dotted string format */));
+ if (!oid.get()) return nullptr;
+
+ int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */);
+ if (location == -1) return nullptr;
+
+ X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location);
+ if (!attest_rec_ext) return nullptr;
+
+ ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
+ return attest_rec;
+}
+
+bool ChainSignaturesAreValid(const vector<certificate_t>& chain, bool strict_issuer_check) {
+ std::stringstream cert_data;
+
+ for (size_t i = 0; i < chain.size(); ++i) {
+ cert_data << bin2hex(chain[i]) << std::endl;
+
+ X509_Ptr key_cert(parseCertBlob(chain[i]));
+ X509_Ptr signing_cert;
+ if (i < chain.size() - 1) {
+ signing_cert = parseCertBlob(chain[i + 1]);
+ } else {
+ signing_cert = parseCertBlob(chain[i]);
+ }
+ if (!key_cert.get() || !signing_cert.get()) {
+ LOG(ERROR) << cert_data.str();
+ return false;
+ }
+
+ EVP_PKEY_Ptr signing_pubkey(X509_get_pubkey(signing_cert.get()));
+ if (!signing_pubkey.get()) {
+ LOG(ERROR) << cert_data.str();
+ return false;
+ }
+
+ if (!X509_verify(key_cert.get(), signing_pubkey.get())) {
+ LOG(ERROR) << "Verification of certificate " << i << " failed "
+ << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL)
+ << '\n'
+ << cert_data.str();
+ return false;
+ }
+
+ 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 && strict_issuer_check) {
+ LOG(ERROR) << "Cert " << i << " has wrong issuer.\n"
+ << " Signer subject is " << signer_subj << " Issuer subject is "
+ << cert_issuer << endl
+ << cert_data.str();
+ }
+ }
+
+ // Dump cert data.
+ LOG(ERROR) << cert_data.str();
+ return true;
+}
+
/* This function extracts a certificate from the certs_chain_buffer at the given
* offset. Each DER encoded certificate starts with TAG_SEQUENCE followed by the
* total length of the certificate. The length of the certificate is determined
@@ -101,13 +187,12 @@
* @data_size: Length of the DER encoded X.509 certificates buffer.
* @index: DER encoded X.509 certificates buffer offset.
* @cert: Encoded certificate to be extracted from buffer as outcome.
- * @return: ErrorCode::OK on success, otherwise ErrorCode::UNKNOWN_ERROR.
+ * @return: true on success, otherwise false.
*/
-ErrorCode
-extractCertFromCertChainBuffer(uint8_t* certs_chain_buffer, int certs_chain_buffer_size, int& index,
- aidl::android::hardware::security::keymint::Certificate& cert) {
+bool extractCertFromCertChainBuffer(uint8_t* certs_chain_buffer, int certs_chain_buffer_size,
+ int& index, certificate_t& cert) {
if (index >= certs_chain_buffer_size) {
- return ErrorCode::UNKNOWN_ERROR;
+ return false;
}
uint32_t length = 0;
@@ -140,7 +225,7 @@
length += 6;
} else {
// Length is larger than uint32_t max limit.
- return ErrorCode::UNKNOWN_ERROR;
+ return false;
}
}
cert_bytes.insert(cert_bytes.end(), (certs_chain_buffer + index),
@@ -148,53 +233,47 @@
index += length;
for (int i = 0; i < cert_bytes.size(); i++) {
- cert.encodedCertificate = std::move(cert_bytes);
+ cert = std::move(cert_bytes);
}
} else {
// SEQUENCE TAG MISSING.
- return ErrorCode::UNKNOWN_ERROR;
+ return false;
}
- return ErrorCode::OK;
+ return true;
}
-ErrorCode getCertificateChain(
- rust::Vec<rust::u8>& chainBuffer,
- std::vector<aidl::android::hardware::security::keymint::Certificate>& certChain) {
+bool getCertificateChain(rust::Vec<rust::u8>& chainBuffer, std::vector<certificate_t>& certChain) {
uint8_t* data = chainBuffer.data();
int index = 0;
int data_size = chainBuffer.size();
while (index < data_size) {
- aidl::android::hardware::security::keymint::Certificate cert =
- aidl::android::hardware::security::keymint::Certificate();
- if (extractCertFromCertChainBuffer(data, data_size, index, cert) != ErrorCode::OK) {
- return ErrorCode::UNKNOWN_ERROR;
+ certificate_t cert;
+ if (!extractCertFromCertChainBuffer(data, data_size, index, cert)) {
+ return false;
}
certChain.push_back(std::move(cert));
}
- return ErrorCode::OK;
+ return true;
}
bool validateCertChain(rust::Vec<rust::u8> cert_buf, uint32_t cert_len, bool strict_issuer_check) {
- std::vector<aidl::android::hardware::security::keymint::Certificate> cert_chain =
- std::vector<aidl::android::hardware::security::keymint::Certificate>();
+ std::vector<certificate_t> cert_chain = std::vector<certificate_t>();
if (cert_len <= 0) {
return false;
}
- if (getCertificateChain(cert_buf, cert_chain) != ErrorCode::OK) {
+ if (!getCertificateChain(cert_buf, cert_chain)) {
return false;
}
+ std::stringstream cert_data;
for (int i = 0; i < cert_chain.size(); i++) {
- std::cout << cert_chain[i].toString() << "\n";
+ cert_data << bin2hex(cert_chain[i]) << std::endl;
}
- auto result = aidl::android::hardware::security::keymint::test::ChainSignaturesAreValid(
- cert_chain, strict_issuer_check);
+ LOG(INFO) << cert_data.str() << "\n";
- if (result == testing::AssertionSuccess()) return true;
-
- return false;
+ return ChainSignaturesAreValid(cert_chain, strict_issuer_check);
}
/**
@@ -278,7 +357,7 @@
rust::Vec<rust::u8> tag) {
CxxResult cxx_result{};
keymaster_error_t error;
- cxx_result.error = KM_ERROR_OK;
+ cxx_result.error = false;
uint8_t* enc_secure_key_data = encrypted_secure_key.data();
int enc_secure_key_size = encrypted_secure_key.size();
@@ -295,13 +374,16 @@
keymaster::UniquePtr<TEST_SECURE_KEY_WRAPPER, TEST_SECURE_KEY_WRAPPER_Delete> sec_key_wrapper(
TEST_SECURE_KEY_WRAPPER_new());
if (!sec_key_wrapper.get()) {
- cxx_result.error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ LOG(ERROR) << "createWrappedKey - Failed to allocate a memory";
+ cxx_result.error = true;
return cxx_result;
}
// Fill version = 0
if (!ASN1_INTEGER_set(sec_key_wrapper->version, 0)) {
- cxx_result.error = keymaster::TranslateLastOpenSslError();
+ LOG(ERROR) << "createWrappedKey - Error while filling version: "
+ << keymaster::TranslateLastOpenSslError();
+ cxx_result.error = true;
return cxx_result;
}
@@ -309,14 +391,18 @@
if (enc_transport_key_size &&
!ASN1_OCTET_STRING_set(sec_key_wrapper->encrypted_transport_key, enc_transport_key_data,
enc_transport_key_size)) {
- cxx_result.error = keymaster::TranslateLastOpenSslError();
+ LOG(ERROR) << "createWrappedKey - Error while filling encrypted transport key: "
+ << keymaster::TranslateLastOpenSslError();
+ cxx_result.error = true;
return cxx_result;
}
// Fill encrypted secure key.
if (enc_secure_key_size && !ASN1_OCTET_STRING_set(sec_key_wrapper->encrypted_key,
enc_secure_key_data, enc_secure_key_size)) {
- cxx_result.error = keymaster::TranslateLastOpenSslError();
+ LOG(ERROR) << "createWrappedKey - Error while filling encrypted secure key: "
+ << keymaster::TranslateLastOpenSslError();
+ cxx_result.error = true;
return cxx_result;
}
@@ -324,46 +410,55 @@
keymaster::AuthorizationSet auth_list = build_wrapped_key_auth_list();
error = build_auth_list(auth_list, sec_key_wrapper->key_desc->key_params);
if (error != KM_ERROR_OK) {
- cxx_result.error = error;
+ cxx_result.error = true;
return cxx_result;
}
// Fill secure key format.
if (!ASN1_INTEGER_set(sec_key_wrapper->key_desc->key_format, KM_KEY_FORMAT_RAW)) {
- cxx_result.error = keymaster::TranslateLastOpenSslError();
+ LOG(ERROR) << "createWrappedKey - Error while filling secure key format: "
+ << keymaster::TranslateLastOpenSslError();
+ cxx_result.error = true;
return cxx_result;
}
// Fill initialization vector used for encrypting secure key.
if (iv_size &&
!ASN1_OCTET_STRING_set(sec_key_wrapper->initialization_vector, iv_data, iv_size)) {
- cxx_result.error = keymaster::TranslateLastOpenSslError();
+ LOG(ERROR) << "createWrappedKey - Error while filling IV: "
+ << keymaster::TranslateLastOpenSslError();
+ cxx_result.error = true;
return cxx_result;
}
// Fill GCM-tag, extracted during secure key encryption.
if (tag_size && !ASN1_OCTET_STRING_set(sec_key_wrapper->tag, tag_data, tag_size)) {
- cxx_result.error = keymaster::TranslateLastOpenSslError();
+ LOG(ERROR) << "createWrappedKey - Error while filling GCM-tag: "
+ << keymaster::TranslateLastOpenSslError();
+ cxx_result.error = true;
return cxx_result;
}
// ASN.1 DER-encoding of secure key wrapper.
int asn1_data_len = i2d_TEST_SECURE_KEY_WRAPPER(sec_key_wrapper.get(), nullptr);
if (asn1_data_len < 0) {
- cxx_result.error = keymaster::TranslateLastOpenSslError();
+ LOG(ERROR) << "createWrappedKey - Error while performing DER encode: "
+ << keymaster::TranslateLastOpenSslError();
+ cxx_result.error = true;
return cxx_result;
}
std::vector<uint8_t> asn1_data(asn1_data_len, 0);
if (!asn1_data.data()) {
- cxx_result.error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ LOG(ERROR) << "createWrappedKey - Failed to allocate a memory for asn1_data";
+ cxx_result.error = true;
return cxx_result;
}
uint8_t* p = asn1_data.data();
asn1_data_len = i2d_TEST_SECURE_KEY_WRAPPER(sec_key_wrapper.get(), &p);
if (asn1_data_len < 0) {
- cxx_result.error = keymaster::TranslateLastOpenSslError();
+ cxx_result.error = true;
return cxx_result;
}
@@ -508,7 +603,7 @@
CxxResult getValueFromAttestRecord(rust::Vec<rust::u8> cert_buf, int32_t tag) {
CxxResult cxx_result{};
- cxx_result.error = KM_ERROR_OK;
+ cxx_result.error = false;
uint8_t* cert_data = cert_buf.data();
int cert_data_size = cert_buf.size();
@@ -516,17 +611,18 @@
std::vector<uint8_t> cert_bytes;
cert_bytes.insert(cert_bytes.end(), cert_data, (cert_data + cert_data_size));
- aidl::android::hardware::security::keymint::X509_Ptr cert(
- aidl::android::hardware::security::keymint::test::parse_cert_blob(cert_bytes));
+ X509_Ptr cert(parseCertBlob(cert_bytes));
if (!cert.get()) {
- cxx_result.error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+ LOG(ERROR) << "getValueFromAttestRecord - Failed to allocate a memory for certificate";
+ cxx_result.error = true;
return cxx_result;
}
- ASN1_OCTET_STRING* attest_rec =
- aidl::android::hardware::security::keymint::test::get_attestation_record(cert.get());
+ ASN1_OCTET_STRING* attest_rec = getAttestationRecord(cert.get());
if (!attest_rec) {
- cxx_result.error = keymaster::TranslateLastOpenSslError();
+ LOG(ERROR) << "getValueFromAttestRecord - Error in getAttestationRecord: "
+ << keymaster::TranslateLastOpenSslError();
+ cxx_result.error = true;
return cxx_result;
}
@@ -540,13 +636,14 @@
std::vector<uint8_t> att_unique_id;
std::vector<uint8_t> att_app_id;
- auto error = aidl::android::hardware::security::keymint::parse_attestation_record(
- attest_rec->data, attest_rec->length, &att_attestation_version,
- &att_attestation_security_level, &att_keymint_version, &att_keymint_security_level,
- &att_challenge, &att_sw_enforced, &att_hw_enforced, &att_unique_id);
- EXPECT_EQ(ErrorCode::OK, error);
- if (error != ErrorCode::OK) {
- cxx_result.error = static_cast<int32_t>(error);
+ int32_t error =
+ static_cast<int32_t>(aidl::android::hardware::security::keymint::parse_attestation_record(
+ attest_rec->data, attest_rec->length, &att_attestation_version,
+ &att_attestation_security_level, &att_keymint_version, &att_keymint_security_level,
+ &att_challenge, &att_sw_enforced, &att_hw_enforced, &att_unique_id));
+ if (error) {
+ LOG(ERROR) << "getValueFromAttestRecord - Error in parse_attestation_record: " << error;
+ cxx_result.error = true;
return cxx_result;
}
@@ -557,7 +654,8 @@
int pos = att_sw_enforced.find(
aidl::android::hardware::security::keymint::Tag::ATTESTATION_APPLICATION_ID);
if (pos == -1) {
- cxx_result.error = KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING;
+ LOG(ERROR) << "getValueFromAttestRecord - Attestation-application-id missing.";
+ cxx_result.error = true;
return cxx_result;
}
aidl::android::hardware::security::keymint::KeyParameter param = att_sw_enforced[pos];
@@ -569,7 +667,8 @@
if (auth_tag == aidl::android::hardware::security::keymint::Tag::ATTESTATION_CHALLENGE) {
if (att_challenge.size() == 0) {
- cxx_result.error = KM_ERROR_ATTESTATION_CHALLENGE_MISSING;
+ LOG(ERROR) << "getValueFromAttestRecord - Attestation-challenge missing.";
+ cxx_result.error = true;
return cxx_result;
}
std::move(att_challenge.begin(), att_challenge.end(), std::back_inserter(cxx_result.data));
@@ -578,7 +677,8 @@
if (auth_tag == aidl::android::hardware::security::keymint::Tag::UNIQUE_ID) {
if (att_unique_id.size() == 0) {
- cxx_result.error = KM_ERROR_UNSUPPORTED_TAG;
+ LOG(ERROR) << "getValueFromAttestRecord - unsupported tag - UNIQUE_ID.";
+ cxx_result.error = true;
return cxx_result;
}
std::move(att_unique_id.begin(), att_unique_id.end(), std::back_inserter(cxx_result.data));
@@ -587,7 +687,8 @@
int pos = att_hw_enforced.find(auth_tag);
if (pos == -1) {
- cxx_result.error = KM_ERROR_UNSUPPORTED_TAG;
+ LOG(ERROR) << "getValueFromAttestRecord - unsupported tag.";
+ cxx_result.error = true;
return cxx_result;
}
aidl::android::hardware::security::keymint::KeyParameter param = att_hw_enforced[pos];
@@ -596,3 +697,15 @@
std::move(val.begin(), val.end(), std::back_inserter(cxx_result.data));
return cxx_result;
}
+
+uint32_t getOsVersion() {
+ return aidl::android::hardware::security::keymint::getOsVersion();
+}
+
+uint32_t getOsPatchlevel() {
+ return aidl::android::hardware::security::keymint::getOsPatchlevel();
+}
+
+uint32_t getVendorPatchlevel() {
+ return aidl::android::hardware::security::keymint::getVendorPatchlevel();
+}
diff --git a/keystore2/test_utils/ffi_test_utils.hpp b/keystore2/test_utils/ffi_test_utils.hpp
index 3ed7edc..69f558a 100644
--- a/keystore2/test_utils/ffi_test_utils.hpp
+++ b/keystore2/test_utils/ffi_test_utils.hpp
@@ -11,3 +11,6 @@
CxxResult buildAsn1DerEncodedWrappedKeyDescription();
bool performCryptoOpUsingKeystoreEngine(int64_t grant_id);
CxxResult getValueFromAttestRecord(rust::Vec<rust::u8> cert_buf, int32_t tag);
+uint32_t getOsVersion();
+uint32_t getOsPatchlevel();
+uint32_t getVendorPatchlevel();
diff --git a/keystore2/test_utils/ffi_test_utils.rs b/keystore2/test_utils/ffi_test_utils.rs
index 019c26b..04d82f1 100644
--- a/keystore2/test_utils/ffi_test_utils.rs
+++ b/keystore2/test_utils/ffi_test_utils.rs
@@ -21,7 +21,7 @@
mod ffi {
struct CxxResult {
data: Vec<u8>,
- error: i32,
+ error: bool,
}
unsafe extern "C++" {
@@ -36,6 +36,9 @@
fn buildAsn1DerEncodedWrappedKeyDescription() -> CxxResult;
fn performCryptoOpUsingKeystoreEngine(grant_id: i64) -> bool;
fn getValueFromAttestRecord(cert_buf: Vec<u8>, tag: i32) -> CxxResult;
+ fn getOsVersion() -> u32;
+ fn getOsPatchlevel() -> u32;
+ fn getVendorPatchlevel() -> u32;
}
}
@@ -50,7 +53,7 @@
/// Collect the result from CxxResult into a Rust supported structure.
fn get_result(result: ffi::CxxResult) -> Result<Vec<u8>, Error> {
- if result.error == 0 && !result.data.is_empty() {
+ if !result.error && !result.data.is_empty() {
Ok(result.data)
} else {
Err(Error::DerEncodeFailed)
@@ -97,8 +100,23 @@
/// Get the value of the given `Tag` from attestation record.
pub fn get_value_from_attest_record(cert_buf: &[u8], tag: Tag) -> Result<Vec<u8>, Error> {
let result = ffi::getValueFromAttestRecord(cert_buf.to_vec(), tag.0);
- if result.error == 0 && !result.data.is_empty() {
+ if !result.error && !result.data.is_empty() {
return Ok(result.data);
}
Err(Error::AttestRecordGetValueFailed)
}
+
+/// Get OS Version
+pub fn get_os_version() -> u32 {
+ ffi::getOsVersion()
+}
+
+/// Get OS Patch Level
+pub fn get_os_patchlevel() -> u32 {
+ ffi::getOsPatchlevel()
+}
+
+/// Get vendor Patch Level
+pub fn get_vendor_patchlevel() -> u32 {
+ ffi::getVendorPatchlevel()
+}
diff --git a/keystore2/test_utils/key_generations.rs b/keystore2/test_utils/key_generations.rs
index 0f9ecbe..24ce6e1 100644
--- a/keystore2/test_utils/key_generations.rs
+++ b/keystore2/test_utils/key_generations.rs
@@ -15,11 +15,13 @@
//! This module implements test utils to generate various types of keys.
use anyhow::Result;
-
use core::ops::Range;
+use nix::unistd::getuid;
use std::collections::HashSet;
use std::fmt::Write;
+use binder::ThreadState;
+
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
ErrorCode::ErrorCode, HardwareAuthenticatorType::HardwareAuthenticatorType,
@@ -27,7 +29,8 @@
KeyPurpose::KeyPurpose, PaddingMode::PaddingMode, Tag::Tag,
};
use android_system_keystore2::aidl::android::system::keystore2::{
- AuthenticatorSpec::AuthenticatorSpec, Authorization::Authorization, Domain::Domain,
+ AuthenticatorSpec::AuthenticatorSpec, Authorization::Authorization,
+ CreateOperationResponse::CreateOperationResponse, Domain::Domain,
IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
KeyMetadata::KeyMetadata, ResponseCode::ResponseCode,
};
@@ -35,6 +38,8 @@
use crate::authorizations::AuthSetBuilder;
use android_system_keystore2::binder::{ExceptionCode, Result as BinderResult};
+use crate::ffi_test_utils::{get_os_patchlevel, get_os_version, get_vendor_patchlevel};
+
/// Shell namespace.
pub const SELINUX_SHELL_NAMESPACE: i64 = 1;
/// Vold namespace.
@@ -388,7 +393,12 @@
authorizations.iter().any(|auth| &auth.keyParameter == key_param)
}
-fn check_key_authorizations(authorizations: &[Authorization], expected_params: &[KeyParameter]) {
+/// Verify the given key authorizations with the expected authorizations.
+pub fn check_key_authorizations(
+ authorizations: &[Authorization],
+ expected_params: &[KeyParameter],
+ expected_key_origin: KeyOrigin,
+) {
// Make sure key authorizations contains only `ALLOWED_TAGS_IN_KEY_AUTHS`
authorizations.iter().all(|auth| {
assert!(
@@ -410,6 +420,54 @@
}
true
});
+
+ check_common_auths(authorizations, expected_key_origin);
+}
+
+/// Verify common key authorizations.
+fn check_common_auths(authorizations: &[Authorization], expected_key_origin: KeyOrigin) {
+ assert!(check_key_param(
+ authorizations,
+ &KeyParameter {
+ tag: Tag::OS_VERSION,
+ value: KeyParameterValue::Integer(get_os_version().try_into().unwrap())
+ }
+ ));
+ assert!(check_key_param(
+ authorizations,
+ &KeyParameter {
+ tag: Tag::OS_PATCHLEVEL,
+ value: KeyParameterValue::Integer(get_os_patchlevel().try_into().unwrap())
+ }
+ ));
+
+ // Access denied for finding vendor-patch-level ("ro.vendor.build.security_patch") property
+ // in a test running with `untrusted_app` context. Keeping this check to verify
+ // vendor-patch-level in tests running with `su` context.
+ if getuid().is_root() {
+ assert!(check_key_param(
+ authorizations,
+ &KeyParameter {
+ tag: Tag::VENDOR_PATCHLEVEL,
+ value: KeyParameterValue::Integer(get_vendor_patchlevel().try_into().unwrap())
+ }
+ ));
+ }
+ assert!(check_key_param(
+ authorizations,
+ &KeyParameter { tag: Tag::ORIGIN, value: KeyParameterValue::Origin(expected_key_origin) }
+ ));
+ assert!(check_key_param(
+ authorizations,
+ &KeyParameter {
+ tag: Tag::USER_ID,
+ value: KeyParameterValue::Integer(
+ rustutils::users::multiuser_get_user_id(ThreadState::get_calling_uid())
+ .try_into()
+ .unwrap()
+ )
+ }
+ ));
}
/// Generate EC Key using given security level and domain with below key parameters and
@@ -455,7 +513,11 @@
assert!(key_metadata.key.blob.is_some());
}
- check_key_authorizations(&key_metadata.authorizations, &gen_params);
+ check_key_authorizations(
+ &key_metadata.authorizations,
+ &gen_params,
+ KeyOrigin::GENERATED,
+ );
Ok(key_metadata)
}
Err(e) => Err(e),
@@ -498,7 +560,7 @@
} else {
assert!(key_metadata.key.blob.is_none());
}
- check_key_authorizations(&key_metadata.authorizations, &gen_params);
+ check_key_authorizations(&key_metadata.authorizations, &gen_params, KeyOrigin::GENERATED);
Ok(key_metadata)
}
@@ -560,7 +622,7 @@
|| key_metadata.key.blob.is_none()
);
- check_key_authorizations(&key_metadata.authorizations, &gen_params);
+ check_key_authorizations(&key_metadata.authorizations, &gen_params, KeyOrigin::GENERATED);
// If `RSA_OAEP_MGF_DIGEST` tag is not mentioned explicitly while generating/importing a key,
// then make sure `RSA_OAEP_MGF_DIGEST` tag with default value (SHA1) must not be included in
// key authorization list.
@@ -617,7 +679,7 @@
// Should not have an attestation record.
assert!(key_metadata.certificateChain.is_none());
- check_key_authorizations(&key_metadata.authorizations, &gen_params);
+ check_key_authorizations(&key_metadata.authorizations, &gen_params, KeyOrigin::GENERATED);
Ok(key_metadata)
}
@@ -657,7 +719,7 @@
// Should not have an attestation record.
assert!(key_metadata.certificateChain.is_none());
- check_key_authorizations(&key_metadata.authorizations, &gen_params);
+ check_key_authorizations(&key_metadata.authorizations, &gen_params, KeyOrigin::GENERATED);
Ok(key_metadata)
}
@@ -742,7 +804,11 @@
// Should have an attestation record.
assert!(attestation_key_metadata.certificateChain.is_some());
- check_key_authorizations(&attestation_key_metadata.authorizations, &gen_params);
+ check_key_authorizations(
+ &attestation_key_metadata.authorizations,
+ &gen_params,
+ KeyOrigin::GENERATED,
+ );
Ok(attestation_key_metadata)
}
@@ -777,7 +843,7 @@
// Shouldn't have an attestation record.
assert!(ec_key_metadata.certificateChain.is_none());
- check_key_authorizations(&ec_key_metadata.authorizations, &ec_gen_params);
+ check_key_authorizations(&ec_key_metadata.authorizations, &ec_gen_params, KeyOrigin::GENERATED);
Ok(ec_key_metadata)
}
@@ -802,7 +868,7 @@
assert!(key_metadata.certificate.is_some());
assert!(key_metadata.certificateChain.is_none());
- check_key_authorizations(&key_metadata.authorizations, &import_params);
+ check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED);
// Check below auths explicitly, they might not be addd in import parameters.
assert!(check_key_param(
@@ -865,7 +931,7 @@
assert!(key_metadata.certificate.is_some());
assert!(key_metadata.certificateChain.is_none());
- check_key_authorizations(&key_metadata.authorizations, &import_params);
+ check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED);
// Check below auths explicitly, they might not be addd in import parameters.
assert!(check_key_param(
@@ -917,7 +983,7 @@
AES_KEY,
)?;
- check_key_authorizations(&key_metadata.authorizations, &import_params);
+ check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED);
// Check below auths explicitly, they might not be addd in import parameters.
assert!(check_key_param(
@@ -976,7 +1042,7 @@
TRIPLE_DES_KEY,
)?;
- check_key_authorizations(&key_metadata.authorizations, &import_params);
+ check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED);
// Check below auths explicitly, they might not be addd in import parameters.
assert!(check_key_param(
@@ -1036,7 +1102,7 @@
HMAC_KEY,
)?;
- check_key_authorizations(&key_metadata.authorizations, &import_params);
+ check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED);
// Check below auths explicitly, they might not be addd in import parameters.
assert!(check_key_param(
@@ -1188,7 +1254,11 @@
assert!(key_metadata.key.blob.is_some());
}
- check_key_authorizations(&key_metadata.authorizations, &gen_params);
+ check_key_authorizations(
+ &key_metadata.authorizations,
+ &gen_params,
+ KeyOrigin::GENERATED,
+ );
Ok(key_metadata)
}
Err(e) => Err(e),
@@ -1288,3 +1358,51 @@
b"entropy",
)
}
+
+/// Generate Key and validate key characteristics.
+pub fn generate_key(
+ sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+ gen_params: &AuthSetBuilder,
+ alias: &str,
+) -> binder::Result<KeyMetadata> {
+ let key_metadata = sec_level.generateKey(
+ &KeyDescriptor {
+ domain: Domain::APP,
+ nspace: -1,
+ alias: Some(alias.to_string()),
+ blob: None,
+ },
+ None,
+ gen_params,
+ 0,
+ b"entropy",
+ )?;
+
+ if gen_params.iter().any(|kp| {
+ matches!(
+ kp.value,
+ KeyParameterValue::Algorithm(Algorithm::RSA)
+ | KeyParameterValue::Algorithm(Algorithm::EC)
+ )
+ }) {
+ assert!(key_metadata.certificate.is_some());
+ if gen_params.iter().any(|kp| kp.tag == Tag::ATTESTATION_CHALLENGE) {
+ assert!(key_metadata.certificateChain.is_some());
+ }
+ }
+ check_key_authorizations(&key_metadata.authorizations, gen_params, KeyOrigin::GENERATED);
+
+ Ok(key_metadata)
+}
+
+/// Generate a key using given authorizations and create an operation using the generated key.
+pub fn create_key_and_operation(
+ sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+ gen_params: &AuthSetBuilder,
+ op_params: &AuthSetBuilder,
+ alias: &str,
+) -> binder::Result<CreateOperationResponse> {
+ let key_metadata = generate_key(sec_level, gen_params, alias)?;
+
+ sec_level.createOperation(&key_metadata.key, op_params, false)
+}
diff --git a/keystore2/tests/keystore2_client_authorizations_tests.rs b/keystore2/tests/keystore2_client_authorizations_tests.rs
new file mode 100644
index 0000000..e518a1c
--- /dev/null
+++ b/keystore2/tests/keystore2_client_authorizations_tests.rs
@@ -0,0 +1,322 @@
+// Copyright 2023, 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.
+
+use std::time::SystemTime;
+
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+ Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
+ ErrorCode::ErrorCode, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
+ SecurityLevel::SecurityLevel,
+};
+
+use keystore2_test_utils::{
+ authorizations, get_keystore_service, key_generations, key_generations::Error,
+};
+
+use crate::keystore2_client_test_utils::{
+ delete_app_key, perform_sample_hmac_sign_verify_op, perform_sample_sym_key_decrypt_op,
+ perform_sample_sym_key_encrypt_op, SAMPLE_PLAIN_TEXT,
+};
+
+/// Generate a key with `ACTIVE_DATETIME` set to current time. Test should successfully generate
+/// a key and verify the key characteristics. Test should be able to create a sign operation using
+/// the generated key successfully.
+#[test]
+fn keystore2_gen_key_auth_active_datetime_test_success() {
+ let keystore2 = get_keystore_service();
+ let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+ let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
+ let active_datetime = duration_since_epoch.as_millis();
+ let gen_params = authorizations::AuthSetBuilder::new()
+ .no_auth_required()
+ .algorithm(Algorithm::EC)
+ .purpose(KeyPurpose::SIGN)
+ .purpose(KeyPurpose::VERIFY)
+ .digest(Digest::SHA_2_256)
+ .ec_curve(EcCurve::P_256)
+ .attestation_challenge(b"foo".to_vec())
+ .active_date_time(active_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_test";
+ let result = key_generations::create_key_and_operation(
+ &sec_level,
+ &gen_params,
+ &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(Digest::SHA_2_256),
+ alias,
+ );
+
+ assert!(result.is_ok());
+ delete_app_key(&keystore2, alias).unwrap();
+}
+
+/// Generate a key with `ACTIVE_DATETIME` set to future date and time. Test should successfully
+/// generate a key and verify the key characteristics. Try to create a sign operation
+/// using the generated key, test should fail to create an operation with error code
+/// `KEY_NOT_YET_VALID`.
+#[test]
+fn keystore2_gen_key_auth_future_active_datetime_test_op_fail() {
+ let keystore2 = get_keystore_service();
+ let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+ let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
+ let future_active_datetime = duration_since_epoch.as_millis() + (24 * 60 * 60 * 1000);
+ let gen_params = authorizations::AuthSetBuilder::new()
+ .no_auth_required()
+ .algorithm(Algorithm::EC)
+ .purpose(KeyPurpose::SIGN)
+ .purpose(KeyPurpose::VERIFY)
+ .digest(Digest::SHA_2_256)
+ .ec_curve(EcCurve::P_256)
+ .attestation_challenge(b"foo".to_vec())
+ .active_date_time(future_active_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_test";
+ let result = key_generations::map_ks_error(key_generations::create_key_and_operation(
+ &sec_level,
+ &gen_params,
+ &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(Digest::SHA_2_256),
+ alias,
+ ));
+ assert!(result.is_err());
+ assert_eq!(Error::Km(ErrorCode::KEY_NOT_YET_VALID), result.unwrap_err());
+ delete_app_key(&keystore2, alias).unwrap();
+}
+
+/// Generate a key with `ORIGINATION_EXPIRE_DATETIME` set to future date and time. Test should
+/// successfully generate a key and verify the key characteristics. Test should be able to create
+/// sign operation using the generated key successfully.
+#[test]
+fn keystore2_gen_key_auth_future_origination_expire_datetime_test_success() {
+ let keystore2 = get_keystore_service();
+ let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+ let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
+ let origination_expire_datetime = duration_since_epoch.as_millis() + (24 * 60 * 60 * 1000);
+ let gen_params = authorizations::AuthSetBuilder::new()
+ .no_auth_required()
+ .algorithm(Algorithm::EC)
+ .purpose(KeyPurpose::SIGN)
+ .purpose(KeyPurpose::VERIFY)
+ .digest(Digest::SHA_2_256)
+ .ec_curve(EcCurve::P_256)
+ .attestation_challenge(b"foo".to_vec())
+ .origination_expire_date_time(origination_expire_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_test";
+ let result = key_generations::create_key_and_operation(
+ &sec_level,
+ &gen_params,
+ &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(Digest::SHA_2_256),
+ alias,
+ );
+ assert!(result.is_ok());
+ delete_app_key(&keystore2, alias).unwrap();
+}
+
+/// Generate a key with `ORIGINATION_EXPIRE_DATETIME` set to current date and time. Test should
+/// successfully generate a key and verify the key characteristics. Try to create a sign operation
+/// using the generated key, test should fail to create an operation with error code
+/// `KEY_EXPIRED`.
+#[test]
+fn keystore2_gen_key_auth_origination_expire_datetime_test_op_fail() {
+ let keystore2 = get_keystore_service();
+ let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+ let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
+ let origination_expire_datetime = duration_since_epoch.as_millis();
+ let gen_params = authorizations::AuthSetBuilder::new()
+ .no_auth_required()
+ .algorithm(Algorithm::EC)
+ .purpose(KeyPurpose::SIGN)
+ .purpose(KeyPurpose::VERIFY)
+ .digest(Digest::SHA_2_256)
+ .ec_curve(EcCurve::P_256)
+ .attestation_challenge(b"foo".to_vec())
+ .origination_expire_date_time(origination_expire_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_test";
+ let result = key_generations::map_ks_error(key_generations::create_key_and_operation(
+ &sec_level,
+ &gen_params,
+ &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(Digest::SHA_2_256),
+ alias,
+ ));
+ assert!(result.is_err());
+ assert_eq!(Error::Km(ErrorCode::KEY_EXPIRED), result.unwrap_err());
+ delete_app_key(&keystore2, alias).unwrap();
+}
+
+/// Generate a HMAC key with `USAGE_EXPIRE_DATETIME` set to future date and time. Test should
+/// successfully generate a key and verify the key characteristics. Test should be able to create
+/// sign and verify operations using the generated key successfully.
+#[test]
+fn keystore2_gen_key_auth_future_usage_expire_datetime_hmac_verify_op_success() {
+ let keystore2 = get_keystore_service();
+ let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+ let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
+ let usage_expire_datetime = duration_since_epoch.as_millis() + (24 * 60 * 60 * 1000);
+ let gen_params = authorizations::AuthSetBuilder::new()
+ .no_auth_required()
+ .algorithm(Algorithm::HMAC)
+ .purpose(KeyPurpose::SIGN)
+ .purpose(KeyPurpose::VERIFY)
+ .key_size(128)
+ .min_mac_length(256)
+ .digest(Digest::SHA_2_256)
+ .usage_expire_date_time(usage_expire_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_hmac_verify_success";
+ let key_metadata = key_generations::generate_key(&sec_level, &gen_params, alias).unwrap();
+
+ perform_sample_hmac_sign_verify_op(&sec_level, &key_metadata.key);
+ delete_app_key(&keystore2, alias).unwrap();
+}
+
+/// Generate a key with `USAGE_EXPIRE_DATETIME` set to current date and time. Test should
+/// successfully generate a key and verify the key characteristics. Test should be able to create
+/// sign operation successfully and fail while performing verify operation with error code
+/// `KEY_EXPIRED`.
+#[test]
+fn keystore2_gen_key_auth_usage_expire_datetime_hmac_verify_op_fail() {
+ let keystore2 = get_keystore_service();
+ let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+ let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
+ let usage_expire_datetime = duration_since_epoch.as_millis();
+ let gen_params = authorizations::AuthSetBuilder::new()
+ .no_auth_required()
+ .algorithm(Algorithm::HMAC)
+ .purpose(KeyPurpose::SIGN)
+ .purpose(KeyPurpose::VERIFY)
+ .key_size(128)
+ .min_mac_length(256)
+ .digest(Digest::SHA_2_256)
+ .usage_expire_date_time(usage_expire_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_hamc_verify_fail";
+ let key_metadata = key_generations::generate_key(&sec_level, &gen_params, alias).unwrap();
+
+ let result = key_generations::map_ks_error(
+ sec_level.createOperation(
+ &key_metadata.key,
+ &authorizations::AuthSetBuilder::new()
+ .purpose(KeyPurpose::VERIFY)
+ .digest(Digest::SHA_2_256),
+ false,
+ ),
+ );
+ assert!(result.is_err());
+ assert_eq!(Error::Km(ErrorCode::KEY_EXPIRED), result.unwrap_err());
+ delete_app_key(&keystore2, alias).unwrap();
+}
+
+/// Generate AES key with `USAGE_EXPIRE_DATETIME` set to future date and time. Test should
+/// successfully generate a key and verify the key characteristics. Test should be able to create
+/// Encrypt and Decrypt operations successfully.
+#[test]
+fn keystore2_gen_key_auth_usage_future_expire_datetime_decrypt_op_success() {
+ let keystore2 = get_keystore_service();
+ let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+ let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
+ let usage_expire_datetime = duration_since_epoch.as_millis() + (24 * 60 * 60 * 1000);
+ let gen_params = authorizations::AuthSetBuilder::new()
+ .no_auth_required()
+ .algorithm(Algorithm::AES)
+ .purpose(KeyPurpose::ENCRYPT)
+ .purpose(KeyPurpose::DECRYPT)
+ .key_size(128)
+ .padding_mode(PaddingMode::PKCS7)
+ .block_mode(BlockMode::ECB)
+ .usage_expire_date_time(usage_expire_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_test";
+ let key_metadata = key_generations::generate_key(&sec_level, &gen_params, alias).unwrap();
+ let cipher_text = perform_sample_sym_key_encrypt_op(
+ &sec_level,
+ PaddingMode::PKCS7,
+ BlockMode::ECB,
+ &mut None,
+ None,
+ &key_metadata.key,
+ )
+ .unwrap();
+
+ assert!(cipher_text.is_some());
+
+ let plain_text = perform_sample_sym_key_decrypt_op(
+ &sec_level,
+ &cipher_text.unwrap(),
+ PaddingMode::PKCS7,
+ BlockMode::ECB,
+ &mut None,
+ None,
+ &key_metadata.key,
+ )
+ .unwrap();
+ assert!(plain_text.is_some());
+ assert_eq!(plain_text.unwrap(), SAMPLE_PLAIN_TEXT.to_vec());
+ delete_app_key(&keystore2, alias).unwrap();
+}
+
+/// Generate AES key with `USAGE_EXPIRE_DATETIME` set to current date and time. Test should
+/// successfully generate a key and verify the key characteristics. Test should be able to create
+/// Encrypt operation successfully and fail while performing decrypt operation with error code
+/// `KEY_EXPIRED`.
+#[test]
+fn keystore2_gen_key_auth_usage_expire_datetime_decrypt_op_fail() {
+ let keystore2 = get_keystore_service();
+ let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+ let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
+ let usage_expire_datetime = duration_since_epoch.as_millis();
+ let gen_params = authorizations::AuthSetBuilder::new()
+ .no_auth_required()
+ .algorithm(Algorithm::AES)
+ .purpose(KeyPurpose::ENCRYPT)
+ .purpose(KeyPurpose::DECRYPT)
+ .key_size(128)
+ .padding_mode(PaddingMode::PKCS7)
+ .block_mode(BlockMode::ECB)
+ .usage_expire_date_time(usage_expire_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_test";
+ let key_metadata = key_generations::generate_key(&sec_level, &gen_params, alias).unwrap();
+ let cipher_text = perform_sample_sym_key_encrypt_op(
+ &sec_level,
+ PaddingMode::PKCS7,
+ BlockMode::ECB,
+ &mut None,
+ None,
+ &key_metadata.key,
+ )
+ .unwrap();
+
+ assert!(cipher_text.is_some());
+
+ let result = key_generations::map_ks_error(perform_sample_sym_key_decrypt_op(
+ &sec_level,
+ &cipher_text.unwrap(),
+ PaddingMode::PKCS7,
+ BlockMode::ECB,
+ &mut None,
+ None,
+ &key_metadata.key,
+ ));
+ assert!(result.is_err());
+ assert_eq!(Error::Km(ErrorCode::KEY_EXPIRED), result.unwrap_err());
+ delete_app_key(&keystore2, alias).unwrap();
+}
diff --git a/keystore2/tests/keystore2_client_tests.rs b/keystore2/tests/keystore2_client_tests.rs
index 3b6a78c..ac7f19f 100644
--- a/keystore2/tests/keystore2_client_tests.rs
+++ b/keystore2/tests/keystore2_client_tests.rs
@@ -15,6 +15,7 @@
pub mod keystore2_client_3des_key_tests;
pub mod keystore2_client_aes_key_tests;
pub mod keystore2_client_attest_key_tests;
+pub mod keystore2_client_authorizations_tests;
pub mod keystore2_client_delete_key_tests;
pub mod keystore2_client_ec_key_tests;
pub mod keystore2_client_grant_key_tests;