Mark ab/6881855 as merged
Bug: 172690556
Change-Id: I9ecdb6b4c377eabf1d0778db70814067f9bcfb74
diff --git a/keystore/KeyAttestationApplicationId.cpp b/keystore/KeyAttestationApplicationId.cpp
index c62571f..1838b07 100644
--- a/keystore/KeyAttestationApplicationId.cpp
+++ b/keystore/KeyAttestationApplicationId.cpp
@@ -26,8 +26,8 @@
KeyAttestationApplicationId::KeyAttestationApplicationId() = default;
KeyAttestationApplicationId::KeyAttestationApplicationId(
- std::unique_ptr<KeyAttestationPackageInfo> package) :
- packageInfos_(new std::vector<std::unique_ptr<KeyAttestationPackageInfo>>()) {
+ std::optional<KeyAttestationPackageInfo> package)
+ : packageInfos_(new std::vector<std::optional<KeyAttestationPackageInfo>>()) {
packageInfos_->push_back(std::move(package));
}
@@ -39,10 +39,13 @@
}
status_t KeyAttestationApplicationId::readFromParcel(const Parcel* parcel) {
- std::unique_ptr<std::vector<std::unique_ptr<KeyAttestationPackageInfo>>> temp_vector;
+ std::optional<std::vector<std::optional<KeyAttestationPackageInfo>>> temp_vector;
auto rc = parcel->readParcelableVector(&temp_vector);
if (rc != NO_ERROR) return rc;
- packageInfos_.reset(temp_vector.release());
+ packageInfos_.reset();
+ if (temp_vector) {
+ packageInfos_ = std::make_shared<PackageInfoVector>(std::move(*temp_vector));
+ }
return NO_ERROR;
}
diff --git a/keystore/KeyAttestationPackageInfo.cpp b/keystore/KeyAttestationPackageInfo.cpp
index 75fbb7a..8e9a36a 100644
--- a/keystore/KeyAttestationPackageInfo.cpp
+++ b/keystore/KeyAttestationPackageInfo.cpp
@@ -28,7 +28,7 @@
KeyAttestationPackageInfo::KeyAttestationPackageInfo(const String16& packageName,
int64_t versionCode,
SharedSignaturesVector signatures)
- : packageName_(new String16(packageName)), versionCode_(versionCode), signatures_(signatures) {}
+ : packageName_(packageName), versionCode_(versionCode), signatures_(signatures) {}
status_t KeyAttestationPackageInfo::writeToParcel(Parcel* parcel) const {
auto rc = parcel->writeString16(packageName_);
@@ -44,10 +44,13 @@
rc = parcel->readInt64(&versionCode_);
if (rc != NO_ERROR) return rc;
- std::unique_ptr<SignaturesVector> temp_vector;
+ std::optional<SignaturesVector> temp_vector;
rc = parcel->readParcelableVector(&temp_vector);
if (rc != NO_ERROR) return rc;
- signatures_.reset(temp_vector.release());
+ signatures_.reset();
+ if (temp_vector) {
+ signatures_ = std::make_shared<SignaturesVector>(std::move(*temp_vector));
+ }
return NO_ERROR;
}
diff --git a/keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl b/keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl
index 0a51511..f37b838 100644
--- a/keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl
+++ b/keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl
@@ -22,6 +22,7 @@
/**
* @hide
*/
+@SensitiveData
oneway interface IKeystoreOperationResultCallback {
void onFinished(in OperationResult result);
-}
\ No newline at end of file
+}
diff --git a/keystore/binder/android/security/keystore/IKeystoreService.aidl b/keystore/binder/android/security/keystore/IKeystoreService.aidl
index 6edca56..e0879dd 100644
--- a/keystore/binder/android/security/keystore/IKeystoreService.aidl
+++ b/keystore/binder/android/security/keystore/IKeystoreService.aidl
@@ -29,10 +29,11 @@
/**
* @hide
*/
+@SensitiveData
interface IKeystoreService {
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
int getState(int userId);
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
byte[] get(String name, int uid);
@UnsupportedAppUsage
int insert(String name, in byte[] item, int uid, int flags);
@@ -40,7 +41,7 @@
int del(String name, int uid);
@UnsupportedAppUsage
int exist(String name, int uid);
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
String[] list(String namePrefix, int uid);
int onUserPasswordChanged(int userId, String newPassword);
int lock(int userId);
diff --git a/keystore/include/keystore/KeyAttestationApplicationId.h b/keystore/include/keystore/KeyAttestationApplicationId.h
index 861c2e1..0bf1aad 100644
--- a/keystore/include/keystore/KeyAttestationApplicationId.h
+++ b/keystore/include/keystore/KeyAttestationApplicationId.h
@@ -16,6 +16,7 @@
#define KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
#include <memory>
+#include <optional>
#include <vector>
#include <binder/Parcelable.h>
@@ -30,10 +31,10 @@
public:
typedef SharedNullableIterator<const KeyAttestationPackageInfo, std::vector>
ConstKeyAttestationPackageInfoIterator;
- typedef std::vector<std::unique_ptr<KeyAttestationPackageInfo>> PackageInfoVector;
+ typedef std::vector<std::optional<KeyAttestationPackageInfo>> PackageInfoVector;
KeyAttestationApplicationId();
// Following c'tors are for initializing instances containing test data.
- explicit KeyAttestationApplicationId(std::unique_ptr<KeyAttestationPackageInfo> package);
+ explicit KeyAttestationApplicationId(std::optional<KeyAttestationPackageInfo> package);
explicit KeyAttestationApplicationId(PackageInfoVector packages);
status_t writeToParcel(Parcel*) const override;
@@ -47,7 +48,7 @@
}
private:
- std::shared_ptr<std::vector<std::unique_ptr<KeyAttestationPackageInfo>>> packageInfos_;
+ std::shared_ptr<PackageInfoVector> packageInfos_;
};
} // namespace keymaster
diff --git a/keystore/include/keystore/KeyAttestationPackageInfo.h b/keystore/include/keystore/KeyAttestationPackageInfo.h
index 92d4863..fa638f9 100644
--- a/keystore/include/keystore/KeyAttestationPackageInfo.h
+++ b/keystore/include/keystore/KeyAttestationPackageInfo.h
@@ -18,6 +18,7 @@
#include <stdint.h>
#include <memory>
+#include <optional>
#include <vector>
#include <binder/Parcelable.h>
@@ -33,8 +34,7 @@
public:
typedef SharedNullableIterator<const content::pm::Signature, std::vector>
ConstSignatureIterator;
- typedef std::vector<std::unique_ptr<content::pm::Signature>>
- SignaturesVector;
+ typedef std::vector<std::optional<content::pm::Signature>> SignaturesVector;
typedef std::shared_ptr<SignaturesVector> SharedSignaturesVector;
KeyAttestationPackageInfo(const String16& packageName, int64_t versionCode,
@@ -44,14 +44,14 @@
status_t writeToParcel(Parcel*) const override;
status_t readFromParcel(const Parcel* parcel) override;
- const std::unique_ptr<String16>& package_name() const { return packageName_; }
+ 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::unique_ptr<String16> packageName_;
+ std::optional<String16> packageName_;
int64_t versionCode_;
SharedSignaturesVector signatures_;
};
diff --git a/keystore/include/keystore/KeystoreResponse.h b/keystore/include/keystore/KeystoreResponse.h
index 20f7274..4a7ef0d 100644
--- a/keystore/include/keystore/KeystoreResponse.h
+++ b/keystore/include/keystore/KeystoreResponse.h
@@ -31,29 +31,24 @@
public:
KeystoreResponse() = default;
explicit KeystoreResponse(const int response_code, const String16& error_msg)
- : response_code_(response_code), error_msg_(std::make_unique<String16>(error_msg)) {}
+ : response_code_(response_code), error_msg_(error_msg) {}
explicit KeystoreResponse(const int response_code)
: response_code_(response_code), error_msg_() {}
// NOLINTNEXTLINE(google-explicit-constructor)
KeystoreResponse(const ::keystore::KeyStoreServiceReturnCode& rc)
: response_code_(rc.getErrorCode()), error_msg_() {}
- KeystoreResponse(const KeystoreResponse& other)
- : response_code_(other.response_code_), error_msg_() {
- if (other.error_msg_) {
- error_msg_ = std::make_unique<String16>(*other.error_msg_);
- }
- }
+ KeystoreResponse(const KeystoreResponse& other) = default;
KeystoreResponse(KeystoreResponse&& other) = default;
status_t readFromParcel(const Parcel* in) override;
status_t writeToParcel(Parcel* out) const override;
int response_code() const { return response_code_; }
- const String16* error_msg() const { return error_msg_.get(); }
+ const std::optional<String16>& error_msg() const { return error_msg_; }
private:
int response_code_;
- std::unique_ptr<String16> error_msg_;
+ std::optional<String16> error_msg_;
};
} // namespace keystore
diff --git a/keystore/include/keystore/utils.h b/keystore/include/keystore/utils.h
index 544dd21..2143d3a 100644
--- a/keystore/include/keystore/utils.h
+++ b/keystore/include/keystore/utils.h
@@ -5,6 +5,7 @@
#include <iterator>
#include <memory>
+#include <optional>
#include <vector>
namespace android {
@@ -12,7 +13,7 @@
/*
* This iterator abstracts from a collection of the form
- * std::shared_ptr<COLLECTION_TYPE<std::unique_ptr<T>>>
+ * std::shared_ptr<COLLECTION_TYPE<std::optional<T>>>
* such that it is defined both for nulled outer pointer and
* nulled entries. If shared_ptr(nullptr) is passed in, the iterator behaves
* like the end iterator yielding an empty collection. Nulled
@@ -25,7 +26,7 @@
template <typename T, template <typename...> class Coll = std::vector>
class SharedNullableIterator {
public:
- typedef Coll<std::unique_ptr<typename std::remove_const<T>::type>> CollectionType;
+ typedef Coll<std::optional<typename std::remove_const<T>::type>> CollectionType;
typedef std::shared_ptr<CollectionType> CollectionPtr;
SharedNullableIterator() {}
diff --git a/keystore/key_attestation_log_handler.cpp b/keystore/key_attestation_log_handler.cpp
index 34c76a3..c3278cb 100644
--- a/keystore/key_attestation_log_handler.cpp
+++ b/keystore/key_attestation_log_handler.cpp
@@ -17,7 +17,11 @@
namespace keystore {
void logKeystoreKeyAttestationEvent(bool wasSuccessful, int32_t errorCode) {
- android::util::stats_write(android::util::KEYSTORE_KEY_EVENT_REPORTED,
+ // Due to a requirement in stats-write() method, the optional fields
+ // which are not required for attestation logging, are marked with -1 for
+ // non-repeated fields and 0 for repeated fields.
+ android::util::stats_write(android::util::KEYSTORE_KEY_EVENT_REPORTED, -1, -1, -1, -1, -1, 0, 0,
+ 0, 0, -1, -1,
android::util::KEYSTORE_KEY_EVENT_REPORTED__TYPE__KEY_ATTESTATION,
wasSuccessful, errorCode);
}
diff --git a/keystore/keystore_attestation_id.cpp b/keystore/keystore_attestation_id.cpp
index 3d9e87e..ccd3808 100644
--- a/keystore/keystore_attestation_id.cpp
+++ b/keystore/keystore_attestation_id.cpp
@@ -271,7 +271,7 @@
if (uid == AID_SYSTEM) {
/* Use a fixed ID for system callers */
- auto pinfo = std::make_unique<KeyAttestationPackageInfo>(
+ auto pinfo = std::make_optional<KeyAttestationPackageInfo>(
String16(kAttestationSystemPackageName), 1 /* version code */,
std::make_shared<KeyAttestationPackageInfo::SignaturesVector>());
key_attestation_id = KeyAttestationApplicationId(std::move(pinfo));
@@ -284,7 +284,7 @@
if (!status.isOk()) {
ALOGW("package manager request for key attestation ID failed with: %s %d",
status.exceptionMessage().string(), status.exceptionCode());
- auto pinfo = std::make_unique<KeyAttestationPackageInfo>(
+ auto pinfo = std::make_optional<KeyAttestationPackageInfo>(
String16(kUnknownPackageName), 1 /* version code */,
std::make_shared<KeyAttestationPackageInfo::SignaturesVector>());
key_attestation_id = KeyAttestationApplicationId(std::move(pinfo));
diff --git a/keystore/tests/aaid_truncation_test.cpp b/keystore/tests/aaid_truncation_test.cpp
index 45c54df..fa4d769 100644
--- a/keystore/tests/aaid_truncation_test.cpp
+++ b/keystore/tests/aaid_truncation_test.cpp
@@ -75,15 +75,15 @@
using ::android::content::pm::Signature;
using ::android::security::build_attestation_application_id;
-std::unique_ptr<KeyAttestationPackageInfo>
+std::optional<KeyAttestationPackageInfo>
make_package_info_with_signatures(const char* package_name,
KeyAttestationPackageInfo::SignaturesVector signatures) {
- return std::make_unique<KeyAttestationPackageInfo>(
+ return std::make_optional<KeyAttestationPackageInfo>(
String16(package_name), 1 /* version code */,
std::make_shared<KeyAttestationPackageInfo::SignaturesVector>(std::move(signatures)));
}
-std::unique_ptr<KeyAttestationPackageInfo> make_package_info(const char* package_name) {
+std::optional<KeyAttestationPackageInfo> make_package_info(const char* package_name) {
return make_package_info_with_signatures(package_name,
KeyAttestationPackageInfo::SignaturesVector());
}
@@ -111,7 +111,7 @@
KeyAttestationPackageInfo::SignaturesVector signatures;
// Add 35 signatures which will surely exceed the 1K limit.
for (size_t i = 0; i < kTooManySignatures; ++i) {
- signatures.push_back(std::make_unique<Signature>(dummy_sig_data));
+ signatures.push_back(std::make_optional<Signature>(dummy_sig_data));
}
KeyAttestationApplicationId app_id(
@@ -131,7 +131,7 @@
KeyAttestationPackageInfo::SignaturesVector signatures;
// Add a few signatures for each package
for (int j = 0; j < 3; ++j) {
- signatures.push_back(std::make_unique<Signature>(dummy_sig_data));
+ signatures.push_back(std::make_optional<Signature>(dummy_sig_data));
}
packages.push_back(
make_package_info_with_signatures(kReasonablePackageName, std::move(signatures)));
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index b5728a3..40d91c2 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -18,8 +18,8 @@
srcs: ["src/lib.rs"],
rustlibs: [
- "libandroid_hardware_keymint",
- "libandroid_security_keystore2",
+ "android.system.keystore2-rust",
+ "android.hardware.keymint-rust",
"libanyhow",
"libbinder_rs",
"libkeystore2_selinux",
@@ -39,11 +39,12 @@
test_suites: ["general-tests"],
auto_gen_config: true,
rustlibs: [
+ "android.system.keystore2-rust",
+ "android.hardware.keymint-rust",
"libandroid_logger",
- "libandroid_hardware_keymint",
- "libandroid_security_keystore2",
"libanyhow",
"libbinder_rs",
+ "libkeystore2_crypto_bindgen",
"libkeystore2_selinux",
"liblazy_static",
"liblibsqlite3_sys",
@@ -51,33 +52,57 @@
"librusqlite",
"libthiserror",
],
+ shared_libs: ["libkeystore2_crypto"],
}
-// This is a placeholder for the libraries that will be generated from the AIDL specs
-// eventually.
-rust_library {
- name: "libandroid_hardware_keymint",
- crate_name: "android_hardware_keymint",
-
- srcs: ["src/android_hardware_keymint.rs"],
-
- rustlibs: [
- "libbinder_rs",
- "liblazy_static",
+cc_library {
+ name: "libkeystore2_crypto",
+ srcs: [
+ "src/crypto.cpp",
+ "src/certificate_utils.cpp",
+ ],
+ export_include_dirs: ["include",],
+ shared_libs: [
+ "libcrypto",
+ "liblog",
],
}
-// This is a placeholder for the libraries that will be generated from the AIDL specs
-// eventually.
-rust_library {
- name: "libandroid_security_keystore2",
- crate_name: "android_security_keystore2",
+rust_bindgen {
+ name: "libkeystore2_crypto_bindgen",
+ wrapper_src: "src/crypto.hpp",
+ crate_name: "keystore2_crypto_bindgen",
+ source_stem: "bindings",
+ host_supported: true,
+}
- srcs: ["src/android_security_keystore2.rs"],
-
+rust_binary {
+ name: "keystore2",
+ srcs: ["src/keystore2_main.rs"],
rustlibs: [
- "libandroid_hardware_keymint",
+ "libandroid_logger",
"libbinder_rs",
- "liblazy_static",
+ "libkeystore2",
+ "liblog_rust",
],
+ init_rc: ["keystore2.rc"],
+}
+
+cc_test {
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+ srcs: [
+ "src/tests/certificate_utils_test.cpp",
+ "src/tests/gtest_main.cpp",
+ ],
+ static_libs: [
+ "libkeystore2_crypto",
+ ],
+ shared_libs: [
+ "libcrypto",
+ ],
+ name: "keystore2_crypto_test",
}
diff --git a/keystore2/include/certificate_utils.h b/keystore2/include/certificate_utils.h
new file mode 100644
index 0000000..9d41eb8
--- /dev/null
+++ b/keystore2/include/certificate_utils.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <openssl/err.h>
+#include <openssl/x509.h>
+#include <stdint.h>
+
+#include <memory>
+#include <optional>
+#include <variant>
+
+namespace keystore {
+// We use boringssl error codes. Error codes that we add are folded into LIB_USER.
+// The CertificateUtilsInternallErrorCodes enum should not be used by callers, instead use the
+// BoringSslError constant definitions below for error codes.
+using BoringSslError = unsigned long;
+
+#define DEFINE_OPENSSL_OBJECT_POINTER(name) using name##_Ptr = bssl::UniquePtr<name>
+
+DEFINE_OPENSSL_OBJECT_POINTER(ASN1_BIT_STRING);
+DEFINE_OPENSSL_OBJECT_POINTER(ASN1_STRING);
+DEFINE_OPENSSL_OBJECT_POINTER(ASN1_INTEGER);
+DEFINE_OPENSSL_OBJECT_POINTER(ASN1_OCTET_STRING);
+DEFINE_OPENSSL_OBJECT_POINTER(ASN1_TIME);
+DEFINE_OPENSSL_OBJECT_POINTER(EVP_PKEY);
+DEFINE_OPENSSL_OBJECT_POINTER(X509);
+DEFINE_OPENSSL_OBJECT_POINTER(X509_EXTENSION);
+DEFINE_OPENSSL_OBJECT_POINTER(X509_NAME);
+DEFINE_OPENSSL_OBJECT_POINTER(EVP_PKEY_CTX);
+
+class CertUtilsError {
+ public:
+ enum Error {
+ Ok = 0,
+ BoringSsl,
+ Encoding,
+ MemoryAllocation,
+ InvalidArgument,
+ UnexpectedNullPointer,
+ };
+
+ private:
+ Error e_;
+
+ public:
+ constexpr CertUtilsError(Error e) : e_(e) {}
+ explicit constexpr operator bool() const { return e_ != Ok; }
+};
+
+struct KeyUsageExtension {
+ bool isSigningKey;
+ bool isEncryptionKey;
+ bool isCertificationKey;
+};
+
+struct BasicConstraintsExtension {
+ bool isCa;
+ std::optional<int> pathLength;
+};
+
+/**
+ * This function allocates and prepares an X509 certificate structure with all of the information
+ * given. Next steps would be to set an Issuer with `setIssuer` and sign it with either
+ * `signCert` or `signCertWith`.
+ * @param evp_pkey The public key that the certificate is issued for.
+ * @param serial The certificate serial number.
+ * @param subject The subject common name.
+ * @param activeDateTimeMilliSeconds The not before date in epoch milliseconds.
+ * @param usageExpireDateTimeMilliSeconds The not after date in epoch milliseconds.
+ * @param addSubjectKeyIdEx If true, adds the subject key id extension.
+ * @param keyUsageEx If given adds, the key usage extension with the given flags.
+ * @param basicConstraints If given, adds the basic constraints extension with the given data.
+ * @return CertUtilsError::Ok on success.
+ */
+std::variant<CertUtilsError, X509_Ptr>
+makeCert(const EVP_PKEY* evp_pkey, //
+ const uint32_t serial, //
+ const char subject[], //
+ const uint64_t activeDateTimeMilliSeconds, //
+ const uint64_t usageExpireDateTimeMilliSeconds, //
+ bool addSubjectKeyIdEx, //
+ std::optional<KeyUsageExtension> keyUsageEx, //
+ std::optional<BasicConstraintsExtension> basicConstraints); //
+
+/**
+ * Takes the subject name from `signingCert` and sets it as issuer name in `cert`.
+ * if `addAuthKeyExt` is true it also generates the digest of the signing certificates's public key
+ * and sets it as authority key id extension in `cert`.
+ * For self signed certificates pass the same pointer to both `cert` and `signingCert`.
+ *
+ * @param cert
+ * @param signingCert
+ * @param addAuthKeyExt
+ * @return CertUtilsError::Ok on success.
+ */
+CertUtilsError setIssuer(X509* cert, const X509* signingCert, bool addAuthKeyExt);
+
+/**
+ * Takes a certificate, and private signing_key.
+ * Signs the certificate with the latter.
+ */
+CertUtilsError signCert(X509* certificate, EVP_PKEY* signing_key);
+
+enum class Digest {
+ SHA1,
+ SHA224,
+ SHA256,
+ SHA384,
+ SHA512,
+};
+
+enum class Algo {
+ ECDSA,
+ RSA,
+};
+
+enum class Padding {
+ Ignored,
+ PKCS1_5,
+ PSS,
+};
+
+/**
+ * Sets the signature specifier of the certificate and the signature according to the parameters
+ * c. Then it signs the certificate with the `sign` callback.
+ * IMPORTANT: The parameters `algo`, `padding`, and `digest` do not control the actual signing
+ * algorithm. The caller is responsible to provide a callback that actually performs the signature
+ * as described by this triplet.
+ * The `padding` argument is ignored if `algo` is Algo::EC.
+ * The `digest` field controls the message digest used, and, in case of RSA with PSS padding,
+ * also the MGF1 digest.
+ *
+ * @param certificate X509 certificate structure to be signed.
+ * @param sign Callback function used to digest and sign the DER encoded to-be-signed certificate.
+ * @param algo Algorithm specifier used to encode the signing algorithm id of the X509 certificate.
+ * @param padding Padding specifier used to encode the signing algorithm id of the X509 certificate.
+ * @param digest Digest specifier used to encode the signing algorithm id of the X509 certificate.
+ * @return CertUtilsError::Ok on success.
+ */
+CertUtilsError signCertWith(X509* certificate,
+ std::function<std::vector<uint8_t>(const uint8_t*, size_t)> sign,
+ Algo algo, Padding padding, Digest digest);
+
+/**
+ * Generates the DER representation of the given signed X509 certificate structure.
+ * @param certificate
+ * @return std::vector<uint8_t> with the DER encoded certificate on success. An error code
+ * otherwise.
+ */
+std::variant<CertUtilsError, std::vector<uint8_t>> encodeCert(X509* certificate);
+
+} // namespace keystore
diff --git a/keystore2/keystore2.rc b/keystore2/keystore2.rc
new file mode 100644
index 0000000..bc040e5
--- /dev/null
+++ b/keystore2/keystore2.rc
@@ -0,0 +1,20 @@
+# Start the keystore2 service.
+# Keystore 2.0 changes its working directory to the first positional
+# command line option, i.e., /data/misc/keystore, where it stores its
+# database.
+# Keystore shall run as user keystore and groups keystore, readproc, and log.
+#
+# See system/core/init/README.md for information on the init.rc language.
+
+# Start Keystore 2 conditionally
+# TODO b/171563717 Remove when Keystore 2 migration is complete.
+on nonencrypted && property:ro.android.security.keystore2.enable=true
+ enable keystore2
+
+service keystore2 /system/bin/keystore2 /data/misc/keystore
+ class main
+ user keystore
+ group keystore readproc log
+ writepid /dev/cpuset/foreground/tasks
+ # TODO b/171563717 Remove when Keystore 2 migration is complete.
+ disabled
diff --git a/keystore2/src/android_hardware_keymint.rs b/keystore2/src/android_hardware_keymint.rs
deleted file mode 100644
index deb9f7b..0000000
--- a/keystore2/src/android_hardware_keymint.rs
+++ /dev/null
@@ -1,1640 +0,0 @@
-#![allow(non_snake_case)]
-#![allow(missing_docs)]
-#![allow(clippy::identity_op)]
-#![allow(clippy::excessive_precision)]
-#![allow(clippy::too_many_arguments)]
-pub use binder::public_api as binder;
-pub mod aidl {
- pub mod android {
- pub mod hardware {
- pub mod keymint {
- pub mod Algorithm {
- #![allow(non_upper_case_globals)]
- pub type Algorithm = i32;
- pub const RSA: Algorithm = 1;
- pub const EC: Algorithm = 3;
- pub const AES: Algorithm = 32;
- pub const TRIPLE_DES: Algorithm = 33;
- pub const HMAC: Algorithm = 128;
- pub(crate) mod mangled { pub use super::Algorithm as _7_android_8_hardware_7_keymint_9_Algorithm; }
- }
- pub mod BeginResult {
- pub struct BeginResult {
- pub challenge: i64,
- pub params: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>,
- pub operation: Option<Box<dyn crate::mangled::_7_android_8_hardware_7_keymint_17_IKeyMintOperation>>,
- }
- pub(crate) mod mangled { pub use super::BeginResult as _7_android_8_hardware_7_keymint_11_BeginResult; }
- impl Default for BeginResult {
- fn default() -> Self {
- Self {
- challenge: 0,
- params: Default::default(),
- operation: Default::default(),
- }
- }
- }
- impl binder::parcel::Serialize for BeginResult {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for BeginResult {}
- impl binder::parcel::SerializeOption for BeginResult {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.challenge)?;
- parcel.write(&this.params)?;
- let __field_ref = this.operation.as_ref().ok_or(binder::StatusCode::UNEXPECTED_NULL)?;
- parcel.write(__field_ref)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for BeginResult {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for BeginResult {}
- impl binder::parcel::DeserializeOption for BeginResult {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.challenge = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.params = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.operation = Some(parcel.read()?);
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- pub mod BlockMode {
- #![allow(non_upper_case_globals)]
- pub type BlockMode = i32;
- pub const ECB: BlockMode = 1;
- pub const CBC: BlockMode = 2;
- pub const CTR: BlockMode = 3;
- pub const GCM: BlockMode = 32;
- pub(crate) mod mangled { pub use super::BlockMode as _7_android_8_hardware_7_keymint_9_BlockMode; }
- }
- pub mod Certificate {
- pub struct Certificate {
- pub encodedCertificate: Vec<u8>,
- }
- pub(crate) mod mangled { pub use super::Certificate as _7_android_8_hardware_7_keymint_11_Certificate; }
- impl Default for Certificate {
- fn default() -> Self {
- Self {
- encodedCertificate: Default::default(),
- }
- }
- }
- impl binder::parcel::Serialize for Certificate {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for Certificate {}
- impl binder::parcel::SerializeOption for Certificate {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.encodedCertificate)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for Certificate {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for Certificate {}
- impl binder::parcel::DeserializeOption for Certificate {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.encodedCertificate = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- pub mod Constants {
- #![allow(non_upper_case_globals)]
- pub type Constants = i32;
- pub const AUTH_TOKEN_MAC_LENGTH: Constants = 32;
- pub(crate) mod mangled { pub use super::Constants as _7_android_8_hardware_7_keymint_9_Constants; }
- }
- pub mod Digest {
- #![allow(non_upper_case_globals)]
- pub type Digest = i32;
- pub const NONE: Digest = 0;
- pub const MD5: Digest = 1;
- pub const SHA1: Digest = 2;
- pub const SHA_2_224: Digest = 3;
- pub const SHA_2_256: Digest = 4;
- pub const SHA_2_384: Digest = 5;
- pub const SHA_2_512: Digest = 6;
- pub(crate) mod mangled { pub use super::Digest as _7_android_8_hardware_7_keymint_6_Digest; }
- }
- pub mod EcCurve {
- #![allow(non_upper_case_globals)]
- pub type EcCurve = i32;
- pub const P_224: EcCurve = 0;
- pub const P_256: EcCurve = 1;
- pub const P_384: EcCurve = 2;
- pub const P_521: EcCurve = 3;
- pub(crate) mod mangled { pub use super::EcCurve as _7_android_8_hardware_7_keymint_7_EcCurve; }
- }
- pub mod ErrorCode {
- #![allow(non_upper_case_globals)]
- pub type ErrorCode = i32;
- pub const OK: ErrorCode = 0;
- pub const ROOT_OF_TRUST_ALREADY_SET: ErrorCode = -1;
- pub const UNSUPPORTED_PURPOSE: ErrorCode = -2;
- pub const INCOMPATIBLE_PURPOSE: ErrorCode = -3;
- pub const UNSUPPORTED_ALGORITHM: ErrorCode = -4;
- pub const INCOMPATIBLE_ALGORITHM: ErrorCode = -5;
- pub const UNSUPPORTED_KEY_SIZE: ErrorCode = -6;
- pub const UNSUPPORTED_BLOCK_MODE: ErrorCode = -7;
- pub const INCOMPATIBLE_BLOCK_MODE: ErrorCode = -8;
- pub const UNSUPPORTED_MAC_LENGTH: ErrorCode = -9;
- pub const UNSUPPORTED_PADDING_MODE: ErrorCode = -10;
- pub const INCOMPATIBLE_PADDING_MODE: ErrorCode = -11;
- pub const UNSUPPORTED_DIGEST: ErrorCode = -12;
- pub const INCOMPATIBLE_DIGEST: ErrorCode = -13;
- pub const INVALID_EXPIRATION_TIME: ErrorCode = -14;
- pub const INVALID_USER_ID: ErrorCode = -15;
- pub const INVALID_AUTHORIZATION_TIMEOUT: ErrorCode = -16;
- pub const UNSUPPORTED_KEY_FORMAT: ErrorCode = -17;
- pub const INCOMPATIBLE_KEY_FORMAT: ErrorCode = -18;
- pub const UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM: ErrorCode = -19;
- pub const UNSUPPORTED_KEY_VERIFICATION_ALGORITHM: ErrorCode = -20;
- pub const INVALID_INPUT_LENGTH: ErrorCode = -21;
- pub const KEY_EXPORT_OPTIONS_INVALID: ErrorCode = -22;
- pub const DELEGATION_NOT_ALLOWED: ErrorCode = -23;
- pub const KEY_NOT_YET_VALID: ErrorCode = -24;
- pub const KEY_EXPIRED: ErrorCode = -25;
- pub const KEY_USER_NOT_AUTHENTICATED: ErrorCode = -26;
- pub const OUTPUT_PARAMETER_NULL: ErrorCode = -27;
- pub const INVALID_OPERATION_HANDLE: ErrorCode = -28;
- pub const INSUFFICIENT_BUFFER_SPACE: ErrorCode = -29;
- pub const VERIFICATION_FAILED: ErrorCode = -30;
- pub const TOO_MANY_OPERATIONS: ErrorCode = -31;
- pub const UNEXPECTED_NULL_POINTER: ErrorCode = -32;
- pub const INVALID_KEY_BLOB: ErrorCode = -33;
- pub const IMPORTED_KEY_NOT_ENCRYPTED: ErrorCode = -34;
- pub const IMPORTED_KEY_DECRYPTION_FAILED: ErrorCode = -35;
- pub const IMPORTED_KEY_NOT_SIGNED: ErrorCode = -36;
- pub const IMPORTED_KEY_VERIFICATION_FAILED: ErrorCode = -37;
- pub const INVALID_ARGUMENT: ErrorCode = -38;
- pub const UNSUPPORTED_TAG: ErrorCode = -39;
- pub const INVALID_TAG: ErrorCode = -40;
- pub const MEMORY_ALLOCATION_FAILED: ErrorCode = -41;
- pub const IMPORT_PARAMETER_MISMATCH: ErrorCode = -44;
- pub const SECURE_HW_ACCESS_DENIED: ErrorCode = -45;
- pub const OPERATION_CANCELLED: ErrorCode = -46;
- pub const CONCURRENT_ACCESS_CONFLICT: ErrorCode = -47;
- pub const SECURE_HW_BUSY: ErrorCode = -48;
- pub const SECURE_HW_COMMUNICATION_FAILED: ErrorCode = -49;
- pub const UNSUPPORTED_EC_FIELD: ErrorCode = -50;
- pub const MISSING_NONCE: ErrorCode = -51;
- pub const INVALID_NONCE: ErrorCode = -52;
- pub const MISSING_MAC_LENGTH: ErrorCode = -53;
- pub const KEY_RATE_LIMIT_EXCEEDED: ErrorCode = -54;
- pub const CALLER_NONCE_PROHIBITED: ErrorCode = -55;
- pub const KEY_MAX_OPS_EXCEEDED: ErrorCode = -56;
- pub const INVALID_MAC_LENGTH: ErrorCode = -57;
- pub const MISSING_MIN_MAC_LENGTH: ErrorCode = -58;
- pub const UNSUPPORTED_MIN_MAC_LENGTH: ErrorCode = -59;
- pub const UNSUPPORTED_KDF: ErrorCode = -60;
- pub const UNSUPPORTED_EC_CURVE: ErrorCode = -61;
- pub const KEY_REQUIRES_UPGRADE: ErrorCode = -62;
- pub const ATTESTATION_CHALLENGE_MISSING: ErrorCode = -63;
- pub const KEYMINT_NOT_CONFIGURED: ErrorCode = -64;
- pub const ATTESTATION_APPLICATION_ID_MISSING: ErrorCode = -65;
- pub const CANNOT_ATTEST_IDS: ErrorCode = -66;
- pub const ROLLBACK_RESISTANCE_UNAVAILABLE: ErrorCode = -67;
- pub const HARDWARE_TYPE_UNAVAILABLE: ErrorCode = -68;
- pub const PROOF_OF_PRESENCE_REQUIRED: ErrorCode = -69;
- pub const CONCURRENT_PROOF_OF_PRESENCE_REQUESTED: ErrorCode = -70;
- pub const NO_USER_CONFIRMATION: ErrorCode = -71;
- pub const DEVICE_LOCKED: ErrorCode = -72;
- pub const EARLY_BOOT_ENDED: ErrorCode = -73;
- pub const ATTESTATION_KEYS_NOT_PROVISIONED: ErrorCode = -74;
- pub const ATTESTATION_IDS_NOT_PROVISIONED: ErrorCode = -75;
- pub const INVALID_OPERATION: ErrorCode = -76;
- pub const STORAGE_KEY_UNSUPPORTED: ErrorCode = -77;
- pub const UNIMPLEMENTED: ErrorCode = -100;
- pub const VERSION_MISMATCH: ErrorCode = -101;
- pub const UNKNOWN_ERROR: ErrorCode = -1000;
- pub(crate) mod mangled { pub use super::ErrorCode as _7_android_8_hardware_7_keymint_9_ErrorCode; }
- }
- pub mod HardwareAuthToken {
- pub struct HardwareAuthToken {
- pub challenge: i64,
- pub userId: i64,
- pub authenticatorId: i64,
- pub authenticatorType: crate::mangled::_7_android_8_hardware_7_keymint_25_HardwareAuthenticatorType,
- pub timestamp: crate::mangled::_7_android_8_hardware_7_keymint_9_Timestamp,
- pub mac: Vec<u8>,
- }
- pub(crate) mod mangled { pub use super::HardwareAuthToken as _7_android_8_hardware_7_keymint_17_HardwareAuthToken; }
- impl Default for HardwareAuthToken {
- fn default() -> Self {
- Self {
- challenge: 0,
- userId: 0,
- authenticatorId: 0,
- authenticatorType: Default::default(),
- timestamp: Default::default(),
- mac: Default::default(),
- }
- }
- }
- impl binder::parcel::Serialize for HardwareAuthToken {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for HardwareAuthToken {}
- impl binder::parcel::SerializeOption for HardwareAuthToken {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.challenge)?;
- parcel.write(&this.userId)?;
- parcel.write(&this.authenticatorId)?;
- parcel.write(&this.authenticatorType)?;
- parcel.write(&this.timestamp)?;
- parcel.write(&this.mac)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for HardwareAuthToken {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for HardwareAuthToken {}
- impl binder::parcel::DeserializeOption for HardwareAuthToken {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.challenge = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.userId = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.authenticatorId = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.authenticatorType = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.timestamp = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.mac = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- pub mod HardwareAuthenticatorType {
- #![allow(non_upper_case_globals)]
- pub type HardwareAuthenticatorType = i32;
- pub const NONE: HardwareAuthenticatorType = 0;
- pub const PASSWORD: HardwareAuthenticatorType = 1;
- pub const FINGERPRINT: HardwareAuthenticatorType = 2;
- pub const ANY: HardwareAuthenticatorType = -1;
- pub(crate) mod mangled { pub use super::HardwareAuthenticatorType as _7_android_8_hardware_7_keymint_25_HardwareAuthenticatorType; }
- }
- pub mod HmacSharingParameters {
- pub struct HmacSharingParameters {
- pub seed: Vec<u8>,
- pub nonce: Vec<u8>,
- }
- pub(crate) mod mangled { pub use super::HmacSharingParameters as _7_android_8_hardware_7_keymint_21_HmacSharingParameters; }
- impl Default for HmacSharingParameters {
- fn default() -> Self {
- Self {
- seed: Default::default(),
- nonce: Default::default(),
- }
- }
- }
- impl binder::parcel::Serialize for HmacSharingParameters {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for HmacSharingParameters {}
- impl binder::parcel::SerializeOption for HmacSharingParameters {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.seed)?;
- parcel.write(&this.nonce)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for HmacSharingParameters {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for HmacSharingParameters {}
- impl binder::parcel::DeserializeOption for HmacSharingParameters {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.seed = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.nonce = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- pub mod IKeyMintDevice {
- #![allow(non_upper_case_globals)]
- #![allow(non_snake_case)]
- #[allow(unused_imports)] use binder::IBinder;
- use binder::declare_binder_interface;
- declare_binder_interface! {
- IKeyMintDevice["android.hardware.keymint.IKeyMintDevice"] {
- native: BnKeyMintDevice(on_transact),
- proxy: BpKeyMintDevice {
- },
- }
- }
- pub trait IKeyMintDevice: binder::Interface + Send {
- fn get_descriptor() -> &'static str where Self: Sized { "android.hardware.keymint.IKeyMintDevice" }
- fn getHardwareInfo(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn verifyAuthorization(&self, _arg_challenge: i64, _arg_parametersToVerify: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_token: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn addRngEntropy(&self, _arg_data: &[u8]) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn generateKey(&self, _arg_keyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_generatedKeyBlob: &mut Vec<u8>, _arg_generatedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn importKey(&self, _arg_inKeyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat, _arg_inKeyData: &[u8], _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn importWrappedKey(&self, _arg_inWrappedKeyData: &[u8], _arg_inWrappingKeyBlob: &[u8], _arg_inMaskingKey: &[u8], _arg_inUnwrappingParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inPasswordSid: i64, _arg_inBiometricSid: i64, _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn upgradeKey(&self, _arg_inKeyBlobToUpgrade: &[u8], _arg_inUpgradeParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter]) -> binder::public_api::Result<Vec<u8>> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn deleteKey(&self, _arg_inKeyBlob: &[u8]) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn deleteAllKeys(&self) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn destroyAttestationIds(&self) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn begin(&self, _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose, _arg_inKeyBlob: &[u8], _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inAuthToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn getDefaultImpl() -> DefaultImpl where Self: Sized {
- DEFAULT_IMPL.lock().unwrap().clone()
- }
- fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
- std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
- }
- }
- pub const TRANSACTION_getHardwareInfo: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
- pub const TRANSACTION_verifyAuthorization: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
- pub const TRANSACTION_addRngEntropy: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
- pub const TRANSACTION_generateKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 3;
- pub const TRANSACTION_importKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 4;
- pub const TRANSACTION_importWrappedKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 5;
- pub const TRANSACTION_upgradeKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 6;
- pub const TRANSACTION_deleteKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 7;
- pub const TRANSACTION_deleteAllKeys: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 8;
- pub const TRANSACTION_destroyAttestationIds: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 9;
- pub const TRANSACTION_begin: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 10;
- pub type DefaultImpl = Option<std::sync::Arc<dyn IKeyMintDevice + Sync>>;
- use lazy_static::lazy_static;
- lazy_static! {
- static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
- }
- pub(crate) mod mangled { pub use super::IKeyMintDevice as _7_android_8_hardware_7_keymint_14_IKeyMintDevice; }
- impl IKeyMintDevice for BpKeyMintDevice {
- fn getHardwareInfo(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo> {
- let _aidl_reply = self.binder.transact(TRANSACTION_getHardwareInfo, 0, |_aidl_data| {
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
- return _aidl_default_impl.getHardwareInfo();
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- let _aidl_return: crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo = _aidl_reply.read()?;
- Ok(_aidl_return)
- }
- fn verifyAuthorization(&self, _arg_challenge: i64, _arg_parametersToVerify: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_token: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken> {
- let _aidl_reply = self.binder.transact(TRANSACTION_verifyAuthorization, 0, |_aidl_data| {
- _aidl_data.write(&_arg_challenge)?;
- _aidl_data.write(_arg_parametersToVerify)?;
- _aidl_data.write(_arg_token)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
- return _aidl_default_impl.verifyAuthorization(_arg_challenge, _arg_parametersToVerify, _arg_token);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- let _aidl_return: crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken = _aidl_reply.read()?;
- Ok(_aidl_return)
- }
- fn addRngEntropy(&self, _arg_data: &[u8]) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_addRngEntropy, 0, |_aidl_data| {
- _aidl_data.write(_arg_data)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
- return _aidl_default_impl.addRngEntropy(_arg_data);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- Ok(())
- }
- fn generateKey(&self, _arg_keyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_generatedKeyBlob: &mut Vec<u8>, _arg_generatedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_generateKey, 0, |_aidl_data| {
- _aidl_data.write(_arg_keyParams)?;
- _aidl_data.write_slice_size(Some(_arg_generatedKeyBlob))?;
- _aidl_data.write_slice_size(Some(_arg_outCertChain))?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
- return _aidl_default_impl.generateKey(_arg_keyParams, _arg_generatedKeyBlob, _arg_generatedKeyCharacteristics, _arg_outCertChain);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- *_arg_generatedKeyBlob = _aidl_reply.read()?;
- *_arg_generatedKeyCharacteristics = _aidl_reply.read()?;
- *_arg_outCertChain = _aidl_reply.read()?;
- Ok(())
- }
- fn importKey(&self, _arg_inKeyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat, _arg_inKeyData: &[u8], _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_importKey, 0, |_aidl_data| {
- _aidl_data.write(_arg_inKeyParams)?;
- _aidl_data.write(&_arg_inKeyFormat)?;
- _aidl_data.write(_arg_inKeyData)?;
- _aidl_data.write_slice_size(Some(_arg_outImportedKeyBlob))?;
- _aidl_data.write_slice_size(Some(_arg_outCertChain))?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
- return _aidl_default_impl.importKey(_arg_inKeyParams, _arg_inKeyFormat, _arg_inKeyData, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics, _arg_outCertChain);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- *_arg_outImportedKeyBlob = _aidl_reply.read()?;
- *_arg_outImportedKeyCharacteristics = _aidl_reply.read()?;
- *_arg_outCertChain = _aidl_reply.read()?;
- Ok(())
- }
- fn importWrappedKey(&self, _arg_inWrappedKeyData: &[u8], _arg_inWrappingKeyBlob: &[u8], _arg_inMaskingKey: &[u8], _arg_inUnwrappingParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inPasswordSid: i64, _arg_inBiometricSid: i64, _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_importWrappedKey, 0, |_aidl_data| {
- _aidl_data.write(_arg_inWrappedKeyData)?;
- _aidl_data.write(_arg_inWrappingKeyBlob)?;
- _aidl_data.write(_arg_inMaskingKey)?;
- _aidl_data.write(_arg_inUnwrappingParams)?;
- _aidl_data.write(&_arg_inPasswordSid)?;
- _aidl_data.write(&_arg_inBiometricSid)?;
- _aidl_data.write_slice_size(Some(_arg_outImportedKeyBlob))?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
- return _aidl_default_impl.importWrappedKey(_arg_inWrappedKeyData, _arg_inWrappingKeyBlob, _arg_inMaskingKey, _arg_inUnwrappingParams, _arg_inPasswordSid, _arg_inBiometricSid, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- *_arg_outImportedKeyBlob = _aidl_reply.read()?;
- *_arg_outImportedKeyCharacteristics = _aidl_reply.read()?;
- Ok(())
- }
- fn upgradeKey(&self, _arg_inKeyBlobToUpgrade: &[u8], _arg_inUpgradeParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter]) -> binder::public_api::Result<Vec<u8>> {
- let _aidl_reply = self.binder.transact(TRANSACTION_upgradeKey, 0, |_aidl_data| {
- _aidl_data.write(_arg_inKeyBlobToUpgrade)?;
- _aidl_data.write(_arg_inUpgradeParams)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
- return _aidl_default_impl.upgradeKey(_arg_inKeyBlobToUpgrade, _arg_inUpgradeParams);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- let _aidl_return: Vec<u8> = _aidl_reply.read()?;
- Ok(_aidl_return)
- }
- fn deleteKey(&self, _arg_inKeyBlob: &[u8]) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_deleteKey, 0, |_aidl_data| {
- _aidl_data.write(_arg_inKeyBlob)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
- return _aidl_default_impl.deleteKey(_arg_inKeyBlob);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- Ok(())
- }
- fn deleteAllKeys(&self) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_deleteAllKeys, 0, |_aidl_data| {
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
- return _aidl_default_impl.deleteAllKeys();
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- Ok(())
- }
- fn destroyAttestationIds(&self) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_destroyAttestationIds, 0, |_aidl_data| {
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
- return _aidl_default_impl.destroyAttestationIds();
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- Ok(())
- }
- fn begin(&self, _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose, _arg_inKeyBlob: &[u8], _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inAuthToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult> {
- let _aidl_reply = self.binder.transact(TRANSACTION_begin, 0, |_aidl_data| {
- _aidl_data.write(&_arg_inPurpose)?;
- _aidl_data.write(_arg_inKeyBlob)?;
- _aidl_data.write(_arg_inParams)?;
- _aidl_data.write(_arg_inAuthToken)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
- return _aidl_default_impl.begin(_arg_inPurpose, _arg_inKeyBlob, _arg_inParams, _arg_inAuthToken);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- let _aidl_return: crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult = _aidl_reply.read()?;
- Ok(_aidl_return)
- }
- }
- impl IKeyMintDevice for binder::Binder<BnKeyMintDevice> {
- fn getHardwareInfo(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo> { self.0.getHardwareInfo() }
- fn verifyAuthorization(&self, _arg_challenge: i64, _arg_parametersToVerify: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_token: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken> { self.0.verifyAuthorization(_arg_challenge, _arg_parametersToVerify, _arg_token) }
- fn addRngEntropy(&self, _arg_data: &[u8]) -> binder::public_api::Result<()> { self.0.addRngEntropy(_arg_data) }
- fn generateKey(&self, _arg_keyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_generatedKeyBlob: &mut Vec<u8>, _arg_generatedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> { self.0.generateKey(_arg_keyParams, _arg_generatedKeyBlob, _arg_generatedKeyCharacteristics, _arg_outCertChain) }
- fn importKey(&self, _arg_inKeyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat, _arg_inKeyData: &[u8], _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> { self.0.importKey(_arg_inKeyParams, _arg_inKeyFormat, _arg_inKeyData, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics, _arg_outCertChain) }
- fn importWrappedKey(&self, _arg_inWrappedKeyData: &[u8], _arg_inWrappingKeyBlob: &[u8], _arg_inMaskingKey: &[u8], _arg_inUnwrappingParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inPasswordSid: i64, _arg_inBiometricSid: i64, _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics) -> binder::public_api::Result<()> { self.0.importWrappedKey(_arg_inWrappedKeyData, _arg_inWrappingKeyBlob, _arg_inMaskingKey, _arg_inUnwrappingParams, _arg_inPasswordSid, _arg_inBiometricSid, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics) }
- fn upgradeKey(&self, _arg_inKeyBlobToUpgrade: &[u8], _arg_inUpgradeParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter]) -> binder::public_api::Result<Vec<u8>> { self.0.upgradeKey(_arg_inKeyBlobToUpgrade, _arg_inUpgradeParams) }
- fn deleteKey(&self, _arg_inKeyBlob: &[u8]) -> binder::public_api::Result<()> { self.0.deleteKey(_arg_inKeyBlob) }
- fn deleteAllKeys(&self) -> binder::public_api::Result<()> { self.0.deleteAllKeys() }
- fn destroyAttestationIds(&self) -> binder::public_api::Result<()> { self.0.destroyAttestationIds() }
- fn begin(&self, _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose, _arg_inKeyBlob: &[u8], _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inAuthToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult> { self.0.begin(_arg_inPurpose, _arg_inKeyBlob, _arg_inParams, _arg_inAuthToken) }
- }
- fn on_transact(_aidl_service: &dyn IKeyMintDevice, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
- match _aidl_code {
- TRANSACTION_getHardwareInfo => {
- let _aidl_return = _aidl_service.getHardwareInfo();
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(_aidl_return)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_verifyAuthorization => {
- let _arg_challenge: i64 = _aidl_data.read()?;
- let _arg_parametersToVerify: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
- let _arg_token: crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken = _aidl_data.read()?;
- let _aidl_return = _aidl_service.verifyAuthorization(_arg_challenge, &_arg_parametersToVerify, &_arg_token);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(_aidl_return)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_addRngEntropy => {
- let _arg_data: Vec<u8> = _aidl_data.read()?;
- let _aidl_return = _aidl_service.addRngEntropy(&_arg_data);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_generateKey => {
- let _arg_keyParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
- let mut _arg_generatedKeyBlob: Vec<u8> = Default::default();
- _aidl_data.resize_out_vec(&mut _arg_generatedKeyBlob)?;
- let mut _arg_generatedKeyCharacteristics: crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics = Default::default();
- let mut _arg_outCertChain: Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate> = Default::default();
- _aidl_data.resize_out_vec(&mut _arg_outCertChain)?;
- let _aidl_return = _aidl_service.generateKey(&_arg_keyParams, &mut _arg_generatedKeyBlob, &mut _arg_generatedKeyCharacteristics, &mut _arg_outCertChain);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(&_arg_generatedKeyBlob)?;
- _aidl_reply.write(&_arg_generatedKeyCharacteristics)?;
- _aidl_reply.write(&_arg_outCertChain)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_importKey => {
- let _arg_inKeyParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
- let _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat = _aidl_data.read()?;
- let _arg_inKeyData: Vec<u8> = _aidl_data.read()?;
- let mut _arg_outImportedKeyBlob: Vec<u8> = Default::default();
- _aidl_data.resize_out_vec(&mut _arg_outImportedKeyBlob)?;
- let mut _arg_outImportedKeyCharacteristics: crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics = Default::default();
- let mut _arg_outCertChain: Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate> = Default::default();
- _aidl_data.resize_out_vec(&mut _arg_outCertChain)?;
- let _aidl_return = _aidl_service.importKey(&_arg_inKeyParams, _arg_inKeyFormat, &_arg_inKeyData, &mut _arg_outImportedKeyBlob, &mut _arg_outImportedKeyCharacteristics, &mut _arg_outCertChain);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(&_arg_outImportedKeyBlob)?;
- _aidl_reply.write(&_arg_outImportedKeyCharacteristics)?;
- _aidl_reply.write(&_arg_outCertChain)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_importWrappedKey => {
- let _arg_inWrappedKeyData: Vec<u8> = _aidl_data.read()?;
- let _arg_inWrappingKeyBlob: Vec<u8> = _aidl_data.read()?;
- let _arg_inMaskingKey: Vec<u8> = _aidl_data.read()?;
- let _arg_inUnwrappingParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
- let _arg_inPasswordSid: i64 = _aidl_data.read()?;
- let _arg_inBiometricSid: i64 = _aidl_data.read()?;
- let mut _arg_outImportedKeyBlob: Vec<u8> = Default::default();
- _aidl_data.resize_out_vec(&mut _arg_outImportedKeyBlob)?;
- let mut _arg_outImportedKeyCharacteristics: crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics = Default::default();
- let _aidl_return = _aidl_service.importWrappedKey(&_arg_inWrappedKeyData, &_arg_inWrappingKeyBlob, &_arg_inMaskingKey, &_arg_inUnwrappingParams, _arg_inPasswordSid, _arg_inBiometricSid, &mut _arg_outImportedKeyBlob, &mut _arg_outImportedKeyCharacteristics);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(&_arg_outImportedKeyBlob)?;
- _aidl_reply.write(&_arg_outImportedKeyCharacteristics)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_upgradeKey => {
- let _arg_inKeyBlobToUpgrade: Vec<u8> = _aidl_data.read()?;
- let _arg_inUpgradeParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
- let _aidl_return = _aidl_service.upgradeKey(&_arg_inKeyBlobToUpgrade, &_arg_inUpgradeParams);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(_aidl_return)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_deleteKey => {
- let _arg_inKeyBlob: Vec<u8> = _aidl_data.read()?;
- let _aidl_return = _aidl_service.deleteKey(&_arg_inKeyBlob);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_deleteAllKeys => {
- let _aidl_return = _aidl_service.deleteAllKeys();
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_destroyAttestationIds => {
- let _aidl_return = _aidl_service.destroyAttestationIds();
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_begin => {
- let _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose = _aidl_data.read()?;
- let _arg_inKeyBlob: Vec<u8> = _aidl_data.read()?;
- let _arg_inParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
- let _arg_inAuthToken: crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken = _aidl_data.read()?;
- let _aidl_return = _aidl_service.begin(_arg_inPurpose, &_arg_inKeyBlob, &_arg_inParams, &_arg_inAuthToken);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(_aidl_return)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
- }
- }
- }
- pub mod IKeyMintOperation {
- #![allow(non_upper_case_globals)]
- #![allow(non_snake_case)]
- #[allow(unused_imports)] use binder::IBinder;
- use binder::declare_binder_interface;
- declare_binder_interface! {
- IKeyMintOperation["android.hardware.keymint.IKeyMintOperation"] {
- native: BnKeyMintOperation(on_transact),
- proxy: BpKeyMintOperation {
- },
- }
- }
- pub trait IKeyMintOperation: binder::Interface + Send {
- fn get_descriptor() -> &'static str where Self: Sized { "android.hardware.keymint.IKeyMintOperation" }
- fn update(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<i32> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn finish(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inSignature: &[u8], _arg_authToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken, _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn abort(&self) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn getDefaultImpl() -> DefaultImpl where Self: Sized {
- DEFAULT_IMPL.lock().unwrap().clone()
- }
- fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
- std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
- }
- }
- pub const TRANSACTION_update: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
- pub const TRANSACTION_finish: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
- pub const TRANSACTION_abort: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
- pub type DefaultImpl = Option<std::sync::Arc<dyn IKeyMintOperation + Sync>>;
- use lazy_static::lazy_static;
- lazy_static! {
- static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
- }
- pub(crate) mod mangled { pub use super::IKeyMintOperation as _7_android_8_hardware_7_keymint_17_IKeyMintOperation; }
- impl IKeyMintOperation for BpKeyMintOperation {
- fn update(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<i32> {
- let _aidl_reply = self.binder.transact(TRANSACTION_update, 0, |_aidl_data| {
- _aidl_data.write(_arg_inParams)?;
- _aidl_data.write(_arg_input)?;
- _aidl_data.write(_arg_inVerificationToken)?;
- _aidl_data.write_slice_size(Some(_arg_outParams))?;
- _aidl_data.write_slice_size(Some(_arg_output))?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeyMintOperation>::getDefaultImpl() {
- return _aidl_default_impl.update(_arg_inParams, _arg_input, _arg_inVerificationToken, _arg_outParams, _arg_output);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- let _aidl_return: i32 = _aidl_reply.read()?;
- *_arg_outParams = _aidl_reply.read()?;
- *_arg_output = _aidl_reply.read()?;
- Ok(_aidl_return)
- }
- fn finish(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inSignature: &[u8], _arg_authToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken, _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_finish, 0, |_aidl_data| {
- _aidl_data.write(_arg_inParams)?;
- _aidl_data.write(_arg_input)?;
- _aidl_data.write(_arg_inSignature)?;
- _aidl_data.write(_arg_authToken)?;
- _aidl_data.write(_arg_inVerificationToken)?;
- _aidl_data.write_slice_size(Some(_arg_outParams))?;
- _aidl_data.write_slice_size(Some(_arg_output))?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeyMintOperation>::getDefaultImpl() {
- return _aidl_default_impl.finish(_arg_inParams, _arg_input, _arg_inSignature, _arg_authToken, _arg_inVerificationToken, _arg_outParams, _arg_output);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- *_arg_outParams = _aidl_reply.read()?;
- *_arg_output = _aidl_reply.read()?;
- Ok(())
- }
- fn abort(&self) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_abort, 0, |_aidl_data| {
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeyMintOperation>::getDefaultImpl() {
- return _aidl_default_impl.abort();
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- Ok(())
- }
- }
- impl IKeyMintOperation for binder::Binder<BnKeyMintOperation> {
- fn update(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<i32> { self.0.update(_arg_inParams, _arg_input, _arg_inVerificationToken, _arg_outParams, _arg_output) }
- fn finish(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inSignature: &[u8], _arg_authToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken, _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<()> { self.0.finish(_arg_inParams, _arg_input, _arg_inSignature, _arg_authToken, _arg_inVerificationToken, _arg_outParams, _arg_output) }
- fn abort(&self) -> binder::public_api::Result<()> { self.0.abort() }
- }
- fn on_transact(_aidl_service: &dyn IKeyMintOperation, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
- match _aidl_code {
- TRANSACTION_update => {
- let _arg_inParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
- let _arg_input: Vec<u8> = _aidl_data.read()?;
- let _arg_inVerificationToken: crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken = _aidl_data.read()?;
- let mut _arg_outParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = Default::default();
- _aidl_data.resize_out_vec(&mut _arg_outParams)?;
- let mut _arg_output: Vec<u8> = Default::default();
- _aidl_data.resize_out_vec(&mut _arg_output)?;
- let _aidl_return = _aidl_service.update(&_arg_inParams, &_arg_input, &_arg_inVerificationToken, &mut _arg_outParams, &mut _arg_output);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(_aidl_return)?;
- _aidl_reply.write(&_arg_outParams)?;
- _aidl_reply.write(&_arg_output)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_finish => {
- let _arg_inParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
- let _arg_input: Vec<u8> = _aidl_data.read()?;
- let _arg_inSignature: Vec<u8> = _aidl_data.read()?;
- let _arg_authToken: crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken = _aidl_data.read()?;
- let _arg_inVerificationToken: crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken = _aidl_data.read()?;
- let mut _arg_outParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = Default::default();
- _aidl_data.resize_out_vec(&mut _arg_outParams)?;
- let mut _arg_output: Vec<u8> = Default::default();
- _aidl_data.resize_out_vec(&mut _arg_output)?;
- let _aidl_return = _aidl_service.finish(&_arg_inParams, &_arg_input, &_arg_inSignature, &_arg_authToken, &_arg_inVerificationToken, &mut _arg_outParams, &mut _arg_output);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(&_arg_outParams)?;
- _aidl_reply.write(&_arg_output)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_abort => {
- let _aidl_return = _aidl_service.abort();
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
- }
- }
- }
- pub mod KeyCharacteristics {
- pub struct KeyCharacteristics {
- pub softwareEnforced: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>,
- pub hardwareEnforced: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>,
- }
- pub(crate) mod mangled { pub use super::KeyCharacteristics as _7_android_8_hardware_7_keymint_18_KeyCharacteristics; }
- impl Default for KeyCharacteristics {
- fn default() -> Self {
- Self {
- softwareEnforced: Default::default(),
- hardwareEnforced: Default::default(),
- }
- }
- }
- impl binder::parcel::Serialize for KeyCharacteristics {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for KeyCharacteristics {}
- impl binder::parcel::SerializeOption for KeyCharacteristics {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.softwareEnforced)?;
- parcel.write(&this.hardwareEnforced)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for KeyCharacteristics {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for KeyCharacteristics {}
- impl binder::parcel::DeserializeOption for KeyCharacteristics {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.softwareEnforced = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.hardwareEnforced = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- pub mod KeyDerivationFunction {
- #![allow(non_upper_case_globals)]
- pub type KeyDerivationFunction = i32;
- pub const NONE: KeyDerivationFunction = 0;
- pub const RFC5869_SHA256: KeyDerivationFunction = 1;
- pub const ISO18033_2_KDF1_SHA1: KeyDerivationFunction = 2;
- pub const ISO18033_2_KDF1_SHA256: KeyDerivationFunction = 3;
- pub const ISO18033_2_KDF2_SHA1: KeyDerivationFunction = 4;
- pub const ISO18033_2_KDF2_SHA256: KeyDerivationFunction = 5;
- pub(crate) mod mangled { pub use super::KeyDerivationFunction as _7_android_8_hardware_7_keymint_21_KeyDerivationFunction; }
- }
- pub mod KeyFormat {
- #![allow(non_upper_case_globals)]
- pub type KeyFormat = i32;
- pub const X509: KeyFormat = 0;
- pub const PKCS8: KeyFormat = 1;
- pub const RAW: KeyFormat = 3;
- pub(crate) mod mangled { pub use super::KeyFormat as _7_android_8_hardware_7_keymint_9_KeyFormat; }
- }
- pub mod KeyMintHardwareInfo {
- pub struct KeyMintHardwareInfo {
- pub versionNumber: i32,
- pub securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel,
- pub keyMintName: String,
- pub keyMintAuthorName: String,
- }
- pub(crate) mod mangled { pub use super::KeyMintHardwareInfo as _7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo; }
- impl Default for KeyMintHardwareInfo {
- fn default() -> Self {
- Self {
- versionNumber: 0,
- securityLevel: Default::default(),
- keyMintName: Default::default(),
- keyMintAuthorName: Default::default(),
- }
- }
- }
- impl binder::parcel::Serialize for KeyMintHardwareInfo {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for KeyMintHardwareInfo {}
- impl binder::parcel::SerializeOption for KeyMintHardwareInfo {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.versionNumber)?;
- parcel.write(&this.securityLevel)?;
- parcel.write(&this.keyMintName)?;
- parcel.write(&this.keyMintAuthorName)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for KeyMintHardwareInfo {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for KeyMintHardwareInfo {}
- impl binder::parcel::DeserializeOption for KeyMintHardwareInfo {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.versionNumber = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.securityLevel = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.keyMintName = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.keyMintAuthorName = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- pub mod KeyOrigin {
- #![allow(non_upper_case_globals)]
- pub type KeyOrigin = i32;
- pub const GENERATED: KeyOrigin = 0;
- pub const DERIVED: KeyOrigin = 1;
- pub const IMPORTED: KeyOrigin = 2;
- pub const RESERVED: KeyOrigin = 3;
- pub const SECURELY_IMPORTED: KeyOrigin = 4;
- pub(crate) mod mangled { pub use super::KeyOrigin as _7_android_8_hardware_7_keymint_9_KeyOrigin; }
- }
- pub mod KeyParameter {
- pub struct KeyParameter {
- pub tag: crate::mangled::_7_android_8_hardware_7_keymint_3_Tag,
- pub boolValue: bool,
- pub integer: i32,
- pub longInteger: i64,
- pub dateTime: i64,
- pub blob: Vec<u8>,
- }
- pub(crate) mod mangled { pub use super::KeyParameter as _7_android_8_hardware_7_keymint_12_KeyParameter; }
- impl Default for KeyParameter {
- fn default() -> Self {
- Self {
- tag: Default::default(),
- boolValue: false,
- integer: 0,
- longInteger: 0,
- dateTime: 0,
- blob: Default::default(),
- }
- }
- }
- impl binder::parcel::Serialize for KeyParameter {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for KeyParameter {}
- impl binder::parcel::SerializeOption for KeyParameter {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.tag)?;
- parcel.write(&this.boolValue)?;
- parcel.write(&this.integer)?;
- parcel.write(&this.longInteger)?;
- parcel.write(&this.dateTime)?;
- parcel.write(&this.blob)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for KeyParameter {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for KeyParameter {}
- impl binder::parcel::DeserializeOption for KeyParameter {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.tag = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.boolValue = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.integer = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.longInteger = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.dateTime = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.blob = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- pub mod KeyPurpose {
- #![allow(non_upper_case_globals)]
- pub type KeyPurpose = i32;
- pub const ENCRYPT: KeyPurpose = 0;
- pub const DECRYPT: KeyPurpose = 1;
- pub const SIGN: KeyPurpose = 2;
- pub const VERIFY: KeyPurpose = 3;
- pub const WRAP_KEY: KeyPurpose = 5;
- pub(crate) mod mangled { pub use super::KeyPurpose as _7_android_8_hardware_7_keymint_10_KeyPurpose; }
- }
- pub mod PaddingMode {
- #![allow(non_upper_case_globals)]
- pub type PaddingMode = i32;
- pub const NONE: PaddingMode = 1;
- pub const RSA_OAEP: PaddingMode = 2;
- pub const RSA_PSS: PaddingMode = 3;
- pub const RSA_PKCS1_1_5_ENCRYPT: PaddingMode = 4;
- pub const RSA_PKCS1_1_5_SIGN: PaddingMode = 5;
- pub const PKCS7: PaddingMode = 64;
- pub(crate) mod mangled { pub use super::PaddingMode as _7_android_8_hardware_7_keymint_11_PaddingMode; }
- }
- pub mod SecurityLevel {
- #![allow(non_upper_case_globals)]
- pub type SecurityLevel = i32;
- pub const SOFTWARE: SecurityLevel = 0;
- pub const TRUSTED_ENVIRONMENT: SecurityLevel = 1;
- pub const STRONGBOX: SecurityLevel = 2;
- pub(crate) mod mangled { pub use super::SecurityLevel as _7_android_8_hardware_7_keymint_13_SecurityLevel; }
- }
- pub mod Tag {
- #![allow(non_upper_case_globals)]
- pub type Tag = i32;
- pub const INVALID: Tag = 0;
- pub const PURPOSE: Tag = 536870913;
- pub const ALGORITHM: Tag = 268435458;
- pub const KEY_SIZE: Tag = 805306371;
- pub const BLOCK_MODE: Tag = 536870916;
- pub const DIGEST: Tag = 536870917;
- pub const PADDING: Tag = 536870918;
- pub const CALLER_NONCE: Tag = 1879048199;
- pub const MIN_MAC_LENGTH: Tag = 805306376;
- pub const EC_CURVE: Tag = 268435466;
- pub const RSA_PUBLIC_EXPONENT: Tag = 1342177480;
- pub const INCLUDE_UNIQUE_ID: Tag = 1879048394;
- pub const BLOB_USAGE_REQUIREMENTS: Tag = 268435757;
- pub const BOOTLOADER_ONLY: Tag = 1879048494;
- pub const ROLLBACK_RESISTANCE: Tag = 1879048495;
- pub const HARDWARE_TYPE: Tag = 268435760;
- pub const EARLY_BOOT_ONLY: Tag = 1879048497;
- pub const ACTIVE_DATETIME: Tag = 1610613136;
- pub const ORIGINATION_EXPIRE_DATETIME: Tag = 1610613137;
- pub const USAGE_EXPIRE_DATETIME: Tag = 1610613138;
- pub const MIN_SECONDS_BETWEEN_OPS: Tag = 805306771;
- pub const MAX_USES_PER_BOOT: Tag = 805306772;
- pub const USER_ID: Tag = 805306869;
- pub const USER_SECURE_ID: Tag = 1073742326;
- pub const NO_AUTH_REQUIRED: Tag = 1879048695;
- pub const USER_AUTH_TYPE: Tag = 268435960;
- pub const AUTH_TIMEOUT: Tag = 805306873;
- pub const ALLOW_WHILE_ON_BODY: Tag = 1879048698;
- pub const TRUSTED_USER_PRESENCE_REQUIRED: Tag = 1879048699;
- pub const TRUSTED_CONFIRMATION_REQUIRED: Tag = 1879048700;
- pub const UNLOCKED_DEVICE_REQUIRED: Tag = 1879048701;
- pub const APPLICATION_ID: Tag = -1879047591;
- pub const APPLICATION_DATA: Tag = -1879047492;
- pub const CREATION_DATETIME: Tag = 1610613437;
- pub const ORIGIN: Tag = 268436158;
- pub const ROOT_OF_TRUST: Tag = -1879047488;
- pub const OS_VERSION: Tag = 805307073;
- pub const OS_PATCHLEVEL: Tag = 805307074;
- pub const UNIQUE_ID: Tag = -1879047485;
- pub const ATTESTATION_CHALLENGE: Tag = -1879047484;
- pub const ATTESTATION_APPLICATION_ID: Tag = -1879047483;
- pub const ATTESTATION_ID_BRAND: Tag = -1879047482;
- pub const ATTESTATION_ID_DEVICE: Tag = -1879047481;
- pub const ATTESTATION_ID_PRODUCT: Tag = -1879047480;
- pub const ATTESTATION_ID_SERIAL: Tag = -1879047479;
- pub const ATTESTATION_ID_IMEI: Tag = -1879047478;
- pub const ATTESTATION_ID_MEID: Tag = -1879047477;
- pub const ATTESTATION_ID_MANUFACTURER: Tag = -1879047476;
- pub const ATTESTATION_ID_MODEL: Tag = -1879047475;
- pub const VENDOR_PATCHLEVEL: Tag = 805307086;
- pub const BOOT_PATCHLEVEL: Tag = 805307087;
- pub const DEVICE_UNIQUE_ATTESTATION: Tag = 1879048912;
- pub const IDENTITY_CREDENTIAL_KEY: Tag = 1879048913;
- pub const STORAGE_KEY: Tag = 1879048914;
- pub const ASSOCIATED_DATA: Tag = -1879047192;
- pub const NONCE: Tag = -1879047191;
- pub const MAC_LENGTH: Tag = 805307371;
- pub const RESET_SINCE_ID_ROTATION: Tag = 1879049196;
- pub const CONFIRMATION_TOKEN: Tag = -1879047187;
- pub(crate) mod mangled { pub use super::Tag as _7_android_8_hardware_7_keymint_3_Tag; }
- }
- pub mod TagType {
- #![allow(non_upper_case_globals)]
- pub type TagType = i32;
- pub const INVALID: TagType = 0;
- pub const ENUM: TagType = 268435456;
- pub const ENUM_REP: TagType = 536870912;
- pub const UINT: TagType = 805306368;
- pub const UINT_REP: TagType = 1073741824;
- pub const ULONG: TagType = 1342177280;
- pub const DATE: TagType = 1610612736;
- pub const BOOL: TagType = 1879048192;
- pub const BIGNUM: TagType = -2147483648;
- pub const BYTES: TagType = -1879048192;
- pub const ULONG_REP: TagType = -1610612736;
- pub(crate) mod mangled { pub use super::TagType as _7_android_8_hardware_7_keymint_7_TagType; }
- }
- pub mod Timestamp {
- pub struct Timestamp {
- pub milliSeconds: i64,
- }
- pub(crate) mod mangled { pub use super::Timestamp as _7_android_8_hardware_7_keymint_9_Timestamp; }
- impl Default for Timestamp {
- fn default() -> Self {
- Self {
- milliSeconds: 0,
- }
- }
- }
- impl binder::parcel::Serialize for Timestamp {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for Timestamp {}
- impl binder::parcel::SerializeOption for Timestamp {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.milliSeconds)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for Timestamp {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for Timestamp {}
- impl binder::parcel::DeserializeOption for Timestamp {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.milliSeconds = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- pub mod VerificationToken {
- pub struct VerificationToken {
- pub challenge: i64,
- pub timestamp: crate::mangled::_7_android_8_hardware_7_keymint_9_Timestamp,
- pub securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel,
- pub mac: Vec<u8>,
- }
- pub(crate) mod mangled { pub use super::VerificationToken as _7_android_8_hardware_7_keymint_17_VerificationToken; }
- impl Default for VerificationToken {
- fn default() -> Self {
- Self {
- challenge: 0,
- timestamp: Default::default(),
- securityLevel: Default::default(),
- mac: Default::default(),
- }
- }
- }
- impl binder::parcel::Serialize for VerificationToken {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for VerificationToken {}
- impl binder::parcel::SerializeOption for VerificationToken {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.challenge)?;
- parcel.write(&this.timestamp)?;
- parcel.write(&this.securityLevel)?;
- parcel.write(&this.mac)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for VerificationToken {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for VerificationToken {}
- impl binder::parcel::DeserializeOption for VerificationToken {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.challenge = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.timestamp = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.securityLevel = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.mac = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- }
- }
- }
-}
-pub mod mangled {
- pub use super::aidl::android::hardware::keymint::Algorithm::mangled::*;
- pub use super::aidl::android::hardware::keymint::BeginResult::mangled::*;
- pub use super::aidl::android::hardware::keymint::BlockMode::mangled::*;
- pub use super::aidl::android::hardware::keymint::Certificate::mangled::*;
- pub use super::aidl::android::hardware::keymint::Constants::mangled::*;
- pub use super::aidl::android::hardware::keymint::Digest::mangled::*;
- pub use super::aidl::android::hardware::keymint::EcCurve::mangled::*;
- pub use super::aidl::android::hardware::keymint::ErrorCode::mangled::*;
- pub use super::aidl::android::hardware::keymint::HardwareAuthToken::mangled::*;
- pub use super::aidl::android::hardware::keymint::HardwareAuthenticatorType::mangled::*;
- pub use super::aidl::android::hardware::keymint::HmacSharingParameters::mangled::*;
- pub use super::aidl::android::hardware::keymint::IKeyMintDevice::mangled::*;
- pub use super::aidl::android::hardware::keymint::IKeyMintOperation::mangled::*;
- pub use super::aidl::android::hardware::keymint::KeyCharacteristics::mangled::*;
- pub use super::aidl::android::hardware::keymint::KeyDerivationFunction::mangled::*;
- pub use super::aidl::android::hardware::keymint::KeyFormat::mangled::*;
- pub use super::aidl::android::hardware::keymint::KeyMintHardwareInfo::mangled::*;
- pub use super::aidl::android::hardware::keymint::KeyOrigin::mangled::*;
- pub use super::aidl::android::hardware::keymint::KeyParameter::mangled::*;
- pub use super::aidl::android::hardware::keymint::KeyPurpose::mangled::*;
- pub use super::aidl::android::hardware::keymint::PaddingMode::mangled::*;
- pub use super::aidl::android::hardware::keymint::SecurityLevel::mangled::*;
- pub use super::aidl::android::hardware::keymint::Tag::mangled::*;
- pub use super::aidl::android::hardware::keymint::TagType::mangled::*;
- pub use super::aidl::android::hardware::keymint::Timestamp::mangled::*;
- pub use super::aidl::android::hardware::keymint::VerificationToken::mangled::*;
-}
diff --git a/keystore2/src/android_security_keystore2.rs b/keystore2/src/android_security_keystore2.rs
deleted file mode 100644
index d22a593..0000000
--- a/keystore2/src/android_security_keystore2.rs
+++ /dev/null
@@ -1,1143 +0,0 @@
-#![allow(non_snake_case)]
-#![allow(missing_docs)]
-#![allow(clippy::identity_op)]
-#![allow(clippy::excessive_precision)]
-#![allow(clippy::too_many_arguments)]
-pub use binder::public_api as binder;
-pub mod aidl {
- pub mod android {
- pub mod security {
- pub mod keystore2 {
- pub mod AuthenticatorSpec {
- pub struct AuthenticatorSpec {
- pub authenticatorType: crate::mangled::_7_android_8_hardware_7_keymint_25_HardwareAuthenticatorType,
- pub authenticatorId: i64,
- }
- pub(crate) mod mangled { pub use super::AuthenticatorSpec as _7_android_8_security_9_keystore2_17_AuthenticatorSpec; }
- impl Default for AuthenticatorSpec {
- fn default() -> Self {
- Self {
- authenticatorType: Default::default(),
- authenticatorId: 0,
- }
- }
- }
- impl binder::parcel::Serialize for AuthenticatorSpec {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for AuthenticatorSpec {}
- impl binder::parcel::SerializeOption for AuthenticatorSpec {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.authenticatorType)?;
- parcel.write(&this.authenticatorId)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for AuthenticatorSpec {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for AuthenticatorSpec {}
- impl binder::parcel::DeserializeOption for AuthenticatorSpec {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.authenticatorType = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.authenticatorId = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- pub mod Certificate {
- pub struct Certificate {
- pub data: Vec<u8>,
- }
- pub(crate) mod mangled { pub use super::Certificate as _7_android_8_security_9_keystore2_11_Certificate; }
- impl Default for Certificate {
- fn default() -> Self {
- Self {
- data: Default::default(),
- }
- }
- }
- impl binder::parcel::Serialize for Certificate {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for Certificate {}
- impl binder::parcel::SerializeOption for Certificate {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.data)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for Certificate {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for Certificate {}
- impl binder::parcel::DeserializeOption for Certificate {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.data = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- pub mod CertificateChain {
- pub struct CertificateChain {
- pub data: Vec<u8>,
- }
- pub(crate) mod mangled { pub use super::CertificateChain as _7_android_8_security_9_keystore2_16_CertificateChain; }
- impl Default for CertificateChain {
- fn default() -> Self {
- Self {
- data: Default::default(),
- }
- }
- }
- impl binder::parcel::Serialize for CertificateChain {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for CertificateChain {}
- impl binder::parcel::SerializeOption for CertificateChain {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.data)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for CertificateChain {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for CertificateChain {}
- impl binder::parcel::DeserializeOption for CertificateChain {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.data = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- pub mod Domain {
- #![allow(non_upper_case_globals)]
- pub type Domain = i32;
- pub const App: Domain = 0;
- pub const Grant: Domain = 1;
- pub const SELinux: Domain = 2;
- pub const Blob: Domain = 3;
- pub const KeyId: Domain = 4;
- pub(crate) mod mangled { pub use super::Domain as _7_android_8_security_9_keystore2_6_Domain; }
- }
- pub mod IKeystoreOperation {
- #![allow(non_upper_case_globals)]
- #![allow(non_snake_case)]
- #[allow(unused_imports)] use binder::IBinder;
- use binder::declare_binder_interface;
- declare_binder_interface! {
- IKeystoreOperation["android.security.keystore2.IKeystoreOperation"] {
- native: BnKeystoreOperation(on_transact),
- proxy: BpKeystoreOperation {
- },
- }
- }
- pub trait IKeystoreOperation: binder::Interface + Send {
- fn get_descriptor() -> &'static str where Self: Sized { "android.security.keystore2.IKeystoreOperation" }
- fn update(&self, _arg_input: Option<&[u8]>, _arg_aadInput: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn finish(&self, _arg_input: Option<&[u8]>, _arg_signature: Option<&[u8]>, _arg_entropy: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn abort(&self) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn getDefaultImpl() -> DefaultImpl where Self: Sized {
- DEFAULT_IMPL.lock().unwrap().clone()
- }
- fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
- std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
- }
- }
- pub const TRANSACTION_update: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
- pub const TRANSACTION_finish: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
- pub const TRANSACTION_abort: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
- pub type DefaultImpl = Option<std::sync::Arc<dyn IKeystoreOperation + Sync>>;
- use lazy_static::lazy_static;
- lazy_static! {
- static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
- }
- pub(crate) mod mangled { pub use super::IKeystoreOperation as _7_android_8_security_9_keystore2_18_IKeystoreOperation; }
- impl IKeystoreOperation for BpKeystoreOperation {
- fn update(&self, _arg_input: Option<&[u8]>, _arg_aadInput: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_update, 0, |_aidl_data| {
- _aidl_data.write(&_arg_input)?;
- _aidl_data.write(&_arg_aadInput)?;
- _aidl_data.write_slice_size(_arg_output.as_deref())?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeystoreOperation>::getDefaultImpl() {
- return _aidl_default_impl.update(_arg_input, _arg_aadInput, _arg_output);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- *_arg_output = _aidl_reply.read()?;
- Ok(())
- }
- fn finish(&self, _arg_input: Option<&[u8]>, _arg_signature: Option<&[u8]>, _arg_entropy: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_finish, 0, |_aidl_data| {
- _aidl_data.write(&_arg_input)?;
- _aidl_data.write(&_arg_signature)?;
- _aidl_data.write(&_arg_entropy)?;
- _aidl_data.write_slice_size(_arg_output.as_deref())?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeystoreOperation>::getDefaultImpl() {
- return _aidl_default_impl.finish(_arg_input, _arg_signature, _arg_entropy, _arg_output);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- *_arg_output = _aidl_reply.read()?;
- Ok(())
- }
- fn abort(&self) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_abort, 0, |_aidl_data| {
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeystoreOperation>::getDefaultImpl() {
- return _aidl_default_impl.abort();
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- Ok(())
- }
- }
- impl IKeystoreOperation for binder::Binder<BnKeystoreOperation> {
- fn update(&self, _arg_input: Option<&[u8]>, _arg_aadInput: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<()> { self.0.update(_arg_input, _arg_aadInput, _arg_output) }
- fn finish(&self, _arg_input: Option<&[u8]>, _arg_signature: Option<&[u8]>, _arg_entropy: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<()> { self.0.finish(_arg_input, _arg_signature, _arg_entropy, _arg_output) }
- fn abort(&self) -> binder::public_api::Result<()> { self.0.abort() }
- }
- fn on_transact(_aidl_service: &dyn IKeystoreOperation, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
- match _aidl_code {
- TRANSACTION_update => {
- let _arg_input: Option<Vec<u8>> = _aidl_data.read()?;
- let _arg_aadInput: Option<Vec<u8>> = _aidl_data.read()?;
- let mut _arg_output: Option<Vec<u8>> = Default::default();
- _aidl_data.resize_nullable_out_vec(&mut _arg_output)?;
- let _aidl_return = _aidl_service.update(_arg_input.as_deref(), _arg_aadInput.as_deref(), &mut _arg_output);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(&_arg_output)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_finish => {
- let _arg_input: Option<Vec<u8>> = _aidl_data.read()?;
- let _arg_signature: Option<Vec<u8>> = _aidl_data.read()?;
- let _arg_entropy: Option<Vec<u8>> = _aidl_data.read()?;
- let mut _arg_output: Option<Vec<u8>> = Default::default();
- _aidl_data.resize_nullable_out_vec(&mut _arg_output)?;
- let _aidl_return = _aidl_service.finish(_arg_input.as_deref(), _arg_signature.as_deref(), _arg_entropy.as_deref(), &mut _arg_output);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(&_arg_output)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_abort => {
- let _aidl_return = _aidl_service.abort();
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
- }
- }
- }
- pub mod IKeystoreSecurityLevel {
- #![allow(non_upper_case_globals)]
- #![allow(non_snake_case)]
- #[allow(unused_imports)] use binder::IBinder;
- use binder::declare_binder_interface;
- declare_binder_interface! {
- IKeystoreSecurityLevel["android.security.keystore2.IKeystoreSecurityLevel"] {
- native: BnKeystoreSecurityLevel(on_transact),
- proxy: BpKeystoreSecurityLevel {
- },
- }
- }
- pub trait IKeystoreSecurityLevel: binder::Interface + Send {
- fn get_descriptor() -> &'static str where Self: Sized { "android.security.keystore2.IKeystoreSecurityLevel" }
- fn create(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_operationParameters: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_forced: bool, _arg_challenge: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge>) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_18_IKeystoreOperation>> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn updateSubcomponent(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: Option<&crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: Option<&crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn generateKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_entropy: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn importKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_keyData: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn importWrappedKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_wrappingKey: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_maskingKey: &[u8], _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_authenticators: &[crate::mangled::_7_android_8_security_9_keystore2_17_AuthenticatorSpec], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn getDefaultImpl() -> DefaultImpl where Self: Sized {
- DEFAULT_IMPL.lock().unwrap().clone()
- }
- fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
- std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
- }
- }
- pub const TRANSACTION_create: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
- pub const TRANSACTION_updateSubcomponent: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
- pub const TRANSACTION_generateKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
- pub const TRANSACTION_importKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 3;
- pub const TRANSACTION_importWrappedKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 4;
- pub type DefaultImpl = Option<std::sync::Arc<dyn IKeystoreSecurityLevel + Sync>>;
- use lazy_static::lazy_static;
- lazy_static! {
- static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
- }
- pub(crate) mod mangled { pub use super::IKeystoreSecurityLevel as _7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel; }
- impl IKeystoreSecurityLevel for BpKeystoreSecurityLevel {
- fn create(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_operationParameters: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_forced: bool, _arg_challenge: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge>) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_18_IKeystoreOperation>> {
- let _aidl_reply = self.binder.transact(TRANSACTION_create, 0, |_aidl_data| {
- _aidl_data.write(_arg_key)?;
- _aidl_data.write(_arg_operationParameters)?;
- _aidl_data.write(&_arg_forced)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
- return _aidl_default_impl.create(_arg_key, _arg_operationParameters, _arg_forced, _arg_challenge);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- let _aidl_return: Box<dyn crate::mangled::_7_android_8_security_9_keystore2_18_IKeystoreOperation> = _aidl_reply.read()?;
- *_arg_challenge = _aidl_reply.read()?;
- Ok(_aidl_return)
- }
- fn updateSubcomponent(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: Option<&crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: Option<&crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_updateSubcomponent, 0, |_aidl_data| {
- _aidl_data.write(_arg_key)?;
- _aidl_data.write(&_arg_publicCert)?;
- _aidl_data.write(&_arg_certificateChain)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
- return _aidl_default_impl.updateSubcomponent(_arg_key, _arg_publicCert, _arg_certificateChain);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- Ok(())
- }
- fn generateKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_entropy: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_generateKey, 0, |_aidl_data| {
- _aidl_data.write(_arg_key)?;
- _aidl_data.write(_arg_params)?;
- _aidl_data.write(_arg_entropy)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
- return _aidl_default_impl.generateKey(_arg_key, _arg_params, _arg_entropy, _arg_resultKey, _arg_publicCert, _arg_certificateChain);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- *_arg_resultKey = _aidl_reply.read()?;
- *_arg_publicCert = _aidl_reply.read()?;
- *_arg_certificateChain = _aidl_reply.read()?;
- Ok(())
- }
- fn importKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_keyData: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_importKey, 0, |_aidl_data| {
- _aidl_data.write(_arg_key)?;
- _aidl_data.write(_arg_params)?;
- _aidl_data.write(_arg_keyData)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
- return _aidl_default_impl.importKey(_arg_key, _arg_params, _arg_keyData, _arg_resultKey, _arg_publicCert, _arg_certificateChain);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- *_arg_resultKey = _aidl_reply.read()?;
- *_arg_publicCert = _aidl_reply.read()?;
- *_arg_certificateChain = _aidl_reply.read()?;
- Ok(())
- }
- fn importWrappedKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_wrappingKey: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_maskingKey: &[u8], _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_authenticators: &[crate::mangled::_7_android_8_security_9_keystore2_17_AuthenticatorSpec], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_importWrappedKey, 0, |_aidl_data| {
- _aidl_data.write(_arg_key)?;
- _aidl_data.write(_arg_wrappingKey)?;
- _aidl_data.write(_arg_maskingKey)?;
- _aidl_data.write(_arg_params)?;
- _aidl_data.write(_arg_authenticators)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
- return _aidl_default_impl.importWrappedKey(_arg_key, _arg_wrappingKey, _arg_maskingKey, _arg_params, _arg_authenticators, _arg_resultKey, _arg_publicCert, _arg_certificateChain);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- *_arg_resultKey = _aidl_reply.read()?;
- *_arg_publicCert = _aidl_reply.read()?;
- *_arg_certificateChain = _aidl_reply.read()?;
- Ok(())
- }
- }
- impl IKeystoreSecurityLevel for binder::Binder<BnKeystoreSecurityLevel> {
- fn create(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_operationParameters: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_forced: bool, _arg_challenge: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge>) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_18_IKeystoreOperation>> { self.0.create(_arg_key, _arg_operationParameters, _arg_forced, _arg_challenge) }
- fn updateSubcomponent(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: Option<&crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: Option<&crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> { self.0.updateSubcomponent(_arg_key, _arg_publicCert, _arg_certificateChain) }
- fn generateKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_entropy: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> { self.0.generateKey(_arg_key, _arg_params, _arg_entropy, _arg_resultKey, _arg_publicCert, _arg_certificateChain) }
- fn importKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_keyData: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> { self.0.importKey(_arg_key, _arg_params, _arg_keyData, _arg_resultKey, _arg_publicCert, _arg_certificateChain) }
- fn importWrappedKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_wrappingKey: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_maskingKey: &[u8], _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_authenticators: &[crate::mangled::_7_android_8_security_9_keystore2_17_AuthenticatorSpec], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> { self.0.importWrappedKey(_arg_key, _arg_wrappingKey, _arg_maskingKey, _arg_params, _arg_authenticators, _arg_resultKey, _arg_publicCert, _arg_certificateChain) }
- }
- fn on_transact(_aidl_service: &dyn IKeystoreSecurityLevel, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
- match _aidl_code {
- TRANSACTION_create => {
- let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
- let _arg_operationParameters: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
- let _arg_forced: bool = _aidl_data.read()?;
- let mut _arg_challenge: Option<crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge> = Default::default();
- let _aidl_return = _aidl_service.create(&_arg_key, &_arg_operationParameters, _arg_forced, &mut _arg_challenge);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(_aidl_return)?;
- _aidl_reply.write(&_arg_challenge)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_updateSubcomponent => {
- let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
- let _arg_publicCert: Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate> = _aidl_data.read()?;
- let _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = _aidl_data.read()?;
- let _aidl_return = _aidl_service.updateSubcomponent(&_arg_key, _arg_publicCert.as_ref(), _arg_certificateChain.as_ref());
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_generateKey => {
- let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
- let _arg_params: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
- let _arg_entropy: Vec<u8> = _aidl_data.read()?;
- let mut _arg_resultKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = Default::default();
- let mut _arg_publicCert: Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate> = Default::default();
- let mut _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = Default::default();
- let _aidl_return = _aidl_service.generateKey(&_arg_key, &_arg_params, &_arg_entropy, &mut _arg_resultKey, &mut _arg_publicCert, &mut _arg_certificateChain);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(&_arg_resultKey)?;
- _aidl_reply.write(&_arg_publicCert)?;
- _aidl_reply.write(&_arg_certificateChain)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_importKey => {
- let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
- let _arg_params: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
- let _arg_keyData: Vec<u8> = _aidl_data.read()?;
- let mut _arg_resultKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = Default::default();
- let mut _arg_publicCert: Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate> = Default::default();
- let mut _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = Default::default();
- let _aidl_return = _aidl_service.importKey(&_arg_key, &_arg_params, &_arg_keyData, &mut _arg_resultKey, &mut _arg_publicCert, &mut _arg_certificateChain);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(&_arg_resultKey)?;
- _aidl_reply.write(&_arg_publicCert)?;
- _aidl_reply.write(&_arg_certificateChain)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_importWrappedKey => {
- let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
- let _arg_wrappingKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
- let _arg_maskingKey: Vec<u8> = _aidl_data.read()?;
- let _arg_params: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
- let _arg_authenticators: Vec<crate::mangled::_7_android_8_security_9_keystore2_17_AuthenticatorSpec> = _aidl_data.read()?;
- let mut _arg_resultKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = Default::default();
- let mut _arg_publicCert: Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate> = Default::default();
- let mut _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = Default::default();
- let _aidl_return = _aidl_service.importWrappedKey(&_arg_key, &_arg_wrappingKey, &_arg_maskingKey, &_arg_params, &_arg_authenticators, &mut _arg_resultKey, &mut _arg_publicCert, &mut _arg_certificateChain);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(&_arg_resultKey)?;
- _aidl_reply.write(&_arg_publicCert)?;
- _aidl_reply.write(&_arg_certificateChain)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
- }
- }
- }
- pub mod IKeystoreService {
- #![allow(non_upper_case_globals)]
- #![allow(non_snake_case)]
- #[allow(unused_imports)] use binder::IBinder;
- use binder::declare_binder_interface;
- declare_binder_interface! {
- IKeystoreService["android.security.keystore2.IKeystoreService"] {
- native: BnKeystoreService(on_transact),
- proxy: BpKeystoreService {
- },
- }
- }
- pub trait IKeystoreService: binder::Interface + Send {
- fn get_descriptor() -> &'static str where Self: Sized { "android.security.keystore2.IKeystoreService" }
- fn getSecurityLevel(&self, _arg_securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn getKeyEntry(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_metadata: &mut crate::mangled::_7_android_8_security_9_keystore2_11_KeyMetadata, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn listEntries(&self, _arg_domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain, _arg_namespace_: i64) -> binder::public_api::Result<Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor>> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn deleteKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn grant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32, _arg_accessVector: i32, _arg_grantKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn ungrant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32) -> binder::public_api::Result<()> {
- Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
- }
- fn getDefaultImpl() -> DefaultImpl where Self: Sized {
- DEFAULT_IMPL.lock().unwrap().clone()
- }
- fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
- std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
- }
- }
- pub const TRANSACTION_getSecurityLevel: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
- pub const TRANSACTION_getKeyEntry: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
- pub const TRANSACTION_listEntries: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
- pub const TRANSACTION_deleteKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 3;
- pub const TRANSACTION_grant: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 4;
- pub const TRANSACTION_ungrant: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 5;
- pub type DefaultImpl = Option<std::sync::Arc<dyn IKeystoreService + Sync>>;
- use lazy_static::lazy_static;
- lazy_static! {
- static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
- }
- pub(crate) mod mangled { pub use super::IKeystoreService as _7_android_8_security_9_keystore2_16_IKeystoreService; }
- impl IKeystoreService for BpKeystoreService {
- fn getSecurityLevel(&self, _arg_securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> {
- let _aidl_reply = self.binder.transact(TRANSACTION_getSecurityLevel, 0, |_aidl_data| {
- _aidl_data.write(&_arg_securityLevel)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
- return _aidl_default_impl.getSecurityLevel(_arg_securityLevel);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- let _aidl_return: Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel> = _aidl_reply.read()?;
- Ok(_aidl_return)
- }
- fn getKeyEntry(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_metadata: &mut crate::mangled::_7_android_8_security_9_keystore2_11_KeyMetadata, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> {
- let _aidl_reply = self.binder.transact(TRANSACTION_getKeyEntry, 0, |_aidl_data| {
- _aidl_data.write(_arg_key)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
- return _aidl_default_impl.getKeyEntry(_arg_key, _arg_metadata, _arg_publicCert, _arg_certificateChain);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- let _aidl_return: Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel> = _aidl_reply.read()?;
- *_arg_metadata = _aidl_reply.read()?;
- *_arg_publicCert = _aidl_reply.read()?;
- *_arg_certificateChain = _aidl_reply.read()?;
- Ok(_aidl_return)
- }
- fn listEntries(&self, _arg_domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain, _arg_namespace_: i64) -> binder::public_api::Result<Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor>> {
- let _aidl_reply = self.binder.transact(TRANSACTION_listEntries, 0, |_aidl_data| {
- _aidl_data.write(&_arg_domain)?;
- _aidl_data.write(&_arg_namespace_)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
- return _aidl_default_impl.listEntries(_arg_domain, _arg_namespace_);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- let _aidl_return: Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor> = _aidl_reply.read()?;
- Ok(_aidl_return)
- }
- fn deleteKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_deleteKey, 0, |_aidl_data| {
- _aidl_data.write(_arg_key)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
- return _aidl_default_impl.deleteKey(_arg_key);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- Ok(())
- }
- fn grant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32, _arg_accessVector: i32, _arg_grantKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_grant, 0, |_aidl_data| {
- _aidl_data.write(_arg_key)?;
- _aidl_data.write(&_arg_granteeUid)?;
- _aidl_data.write(&_arg_accessVector)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
- return _aidl_default_impl.grant(_arg_key, _arg_granteeUid, _arg_accessVector, _arg_grantKey);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- *_arg_grantKey = _aidl_reply.read()?;
- Ok(())
- }
- fn ungrant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32) -> binder::public_api::Result<()> {
- let _aidl_reply = self.binder.transact(TRANSACTION_ungrant, 0, |_aidl_data| {
- _aidl_data.write(_arg_key)?;
- _aidl_data.write(&_arg_granteeUid)?;
- Ok(())
- });
- if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
- if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
- return _aidl_default_impl.ungrant(_arg_key, _arg_granteeUid);
- }
- }
- let _aidl_reply = _aidl_reply?;
- let _aidl_status: binder::Status = _aidl_reply.read()?;
- if !_aidl_status.is_ok() { return Err(_aidl_status); }
- Ok(())
- }
- }
- impl IKeystoreService for binder::Binder<BnKeystoreService> {
- fn getSecurityLevel(&self, _arg_securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> { self.0.getSecurityLevel(_arg_securityLevel) }
- fn getKeyEntry(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_metadata: &mut crate::mangled::_7_android_8_security_9_keystore2_11_KeyMetadata, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> { self.0.getKeyEntry(_arg_key, _arg_metadata, _arg_publicCert, _arg_certificateChain) }
- fn listEntries(&self, _arg_domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain, _arg_namespace_: i64) -> binder::public_api::Result<Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor>> { self.0.listEntries(_arg_domain, _arg_namespace_) }
- fn deleteKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<()> { self.0.deleteKey(_arg_key) }
- fn grant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32, _arg_accessVector: i32, _arg_grantKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<()> { self.0.grant(_arg_key, _arg_granteeUid, _arg_accessVector, _arg_grantKey) }
- fn ungrant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32) -> binder::public_api::Result<()> { self.0.ungrant(_arg_key, _arg_granteeUid) }
- }
- fn on_transact(_aidl_service: &dyn IKeystoreService, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
- match _aidl_code {
- TRANSACTION_getSecurityLevel => {
- let _arg_securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel = _aidl_data.read()?;
- let _aidl_return = _aidl_service.getSecurityLevel(_arg_securityLevel);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(_aidl_return)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_getKeyEntry => {
- let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
- let mut _arg_metadata: crate::mangled::_7_android_8_security_9_keystore2_11_KeyMetadata = Default::default();
- let mut _arg_publicCert: Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate> = Default::default();
- let mut _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = Default::default();
- let _aidl_return = _aidl_service.getKeyEntry(&_arg_key, &mut _arg_metadata, &mut _arg_publicCert, &mut _arg_certificateChain);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(_aidl_return)?;
- _aidl_reply.write(&_arg_metadata)?;
- _aidl_reply.write(&_arg_publicCert)?;
- _aidl_reply.write(&_arg_certificateChain)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_listEntries => {
- let _arg_domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain = _aidl_data.read()?;
- let _arg_namespace_: i64 = _aidl_data.read()?;
- let _aidl_return = _aidl_service.listEntries(_arg_domain, _arg_namespace_);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(_aidl_return)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_deleteKey => {
- let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
- let _aidl_return = _aidl_service.deleteKey(&_arg_key);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_grant => {
- let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
- let _arg_granteeUid: i32 = _aidl_data.read()?;
- let _arg_accessVector: i32 = _aidl_data.read()?;
- let mut _arg_grantKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = Default::default();
- let _aidl_return = _aidl_service.grant(&_arg_key, _arg_granteeUid, _arg_accessVector, &mut _arg_grantKey);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- _aidl_reply.write(&_arg_grantKey)?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- TRANSACTION_ungrant => {
- let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
- let _arg_granteeUid: i32 = _aidl_data.read()?;
- let _aidl_return = _aidl_service.ungrant(&_arg_key, _arg_granteeUid);
- match &_aidl_return {
- Ok(_aidl_return) => {
- _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
- }
- Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
- }
- Ok(())
- }
- _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
- }
- }
- }
- pub mod KeyDescriptor {
- #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
- pub struct KeyDescriptor {
- pub domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain,
- pub namespace_: i64,
- pub alias: Option<String>,
- pub blob: Option<Vec<u8>>,
- }
- pub(crate) mod mangled { pub use super::KeyDescriptor as _7_android_8_security_9_keystore2_13_KeyDescriptor; }
- impl Default for KeyDescriptor {
- fn default() -> Self {
- Self {
- domain: Default::default(),
- namespace_: 0,
- alias: Default::default(),
- blob: Default::default(),
- }
- }
- }
- impl binder::parcel::Serialize for KeyDescriptor {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for KeyDescriptor {}
- impl binder::parcel::SerializeOption for KeyDescriptor {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.domain)?;
- parcel.write(&this.namespace_)?;
- parcel.write(&this.alias)?;
- parcel.write(&this.blob)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for KeyDescriptor {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for KeyDescriptor {}
- impl binder::parcel::DeserializeOption for KeyDescriptor {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.domain = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.namespace_ = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.alias = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.blob = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- pub mod KeyMetadata {
- pub struct KeyMetadata {
- pub key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor,
- pub securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel,
- pub hardwareEnforced: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>,
- pub softwareEnforced: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>,
- }
- pub(crate) mod mangled { pub use super::KeyMetadata as _7_android_8_security_9_keystore2_11_KeyMetadata; }
- impl Default for KeyMetadata {
- fn default() -> Self {
- Self {
- key: Default::default(),
- securityLevel: Default::default(),
- hardwareEnforced: Default::default(),
- softwareEnforced: Default::default(),
- }
- }
- }
- impl binder::parcel::Serialize for KeyMetadata {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for KeyMetadata {}
- impl binder::parcel::SerializeOption for KeyMetadata {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.key)?;
- parcel.write(&this.securityLevel)?;
- parcel.write(&this.hardwareEnforced)?;
- parcel.write(&this.softwareEnforced)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for KeyMetadata {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for KeyMetadata {}
- impl binder::parcel::DeserializeOption for KeyMetadata {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.key = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.securityLevel = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.hardwareEnforced = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- result.softwareEnforced = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- pub mod KeyPermission {
- #![allow(non_upper_case_globals)]
- pub type KeyPermission = i32;
- pub const None: KeyPermission = 0;
- pub const Delete: KeyPermission = 1;
- pub const GenUniqueId: KeyPermission = 2;
- pub const GetInfo: KeyPermission = 4;
- pub const Grant: KeyPermission = 8;
- pub const ManageBlob: KeyPermission = 16;
- pub const Rebind: KeyPermission = 32;
- pub const ReqForcedOp: KeyPermission = 64;
- pub const Update: KeyPermission = 128;
- pub const Use: KeyPermission = 256;
- pub const UseDevId: KeyPermission = 512;
- pub(crate) mod mangled { pub use super::KeyPermission as _7_android_8_security_9_keystore2_13_KeyPermission; }
- }
- pub mod OperationChallenge {
- pub struct OperationChallenge {
- pub challenge: i64,
- }
- pub(crate) mod mangled { pub use super::OperationChallenge as _7_android_8_security_9_keystore2_18_OperationChallenge; }
- impl Default for OperationChallenge {
- fn default() -> Self {
- Self {
- challenge: 0,
- }
- }
- }
- impl binder::parcel::Serialize for OperationChallenge {
- fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
- }
- }
- impl binder::parcel::SerializeArray for OperationChallenge {}
- impl binder::parcel::SerializeOption for OperationChallenge {
- fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
- let this = if let Some(this) = this {
- parcel.write(&1i32)?;
- this
- } else {
- return parcel.write(&0i32);
- };
- let start_pos = parcel.get_data_position();
- parcel.write(&0i32)?;
- parcel.write(&this.challenge)?;
- let end_pos = parcel.get_data_position();
- let parcelable_size = (end_pos - start_pos) as i32;
- unsafe { parcel.set_data_position(start_pos)?; }
- parcel.write(&parcelable_size)?;
- unsafe { parcel.set_data_position(end_pos)?; }
- Ok(())
- }
- }
- impl binder::parcel::Deserialize for OperationChallenge {
- fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
- <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
- .transpose()
- .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
- }
- }
- impl binder::parcel::DeserializeArray for OperationChallenge {}
- impl binder::parcel::DeserializeOption for OperationChallenge {
- fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
- let status: i32 = parcel.read()?;
- if status == 0 { return Ok(None); }
- let start_pos = parcel.get_data_position();
- let parcelable_size: i32 = parcel.read()?;
- if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
- let mut result = Self::default();
- result.challenge = parcel.read()?;
- if (parcel.get_data_position() - start_pos) >= parcelable_size {
- unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
- return Ok(Some(result));
- }
- Ok(Some(result))
- }
- }
- }
- pub mod ResponseCode {
- #![allow(non_upper_case_globals)]
- pub type ResponseCode = i32;
- pub const Ok: ResponseCode = 0;
- pub const Locked: ResponseCode = 2;
- pub const Uninitialized: ResponseCode = 3;
- pub const SystemError: ResponseCode = 4;
- pub const PermissionDenied: ResponseCode = 6;
- pub const KeyNotFound: ResponseCode = 7;
- pub const ValueCorrupted: ResponseCode = 8;
- pub const WrongPassword: ResponseCode = 10;
- pub const OpAuthNeeded: ResponseCode = 15;
- pub const KeyPermanentlyInvalidated: ResponseCode = 17;
- pub const NoSuchSecurityLevel: ResponseCode = 18;
- pub const KeymintErrorCode: ResponseCode = 19;
- pub const BackendBusy: ResponseCode = 20;
- pub(crate) mod mangled { pub use super::ResponseCode as _7_android_8_security_9_keystore2_12_ResponseCode; }
- }
- }
- }
- }
-}
-pub mod mangled {
- pub use super::aidl::android::security::keystore2::AuthenticatorSpec::mangled::*;
- pub use super::aidl::android::security::keystore2::Certificate::mangled::*;
- pub use super::aidl::android::security::keystore2::CertificateChain::mangled::*;
- pub use super::aidl::android::security::keystore2::Domain::mangled::*;
- pub use super::aidl::android::security::keystore2::IKeystoreOperation::mangled::*;
- pub use super::aidl::android::security::keystore2::IKeystoreSecurityLevel::mangled::*;
- pub use super::aidl::android::security::keystore2::IKeystoreService::mangled::*;
- pub use super::aidl::android::security::keystore2::KeyDescriptor::mangled::*;
- pub use super::aidl::android::security::keystore2::KeyMetadata::mangled::*;
- pub use super::aidl::android::security::keystore2::KeyPermission::mangled::*;
- pub use super::aidl::android::security::keystore2::OperationChallenge::mangled::*;
- pub use super::aidl::android::security::keystore2::ResponseCode::mangled::*;
- pub(crate) use android_hardware_keymint::mangled::*;
-}
diff --git a/keystore2/src/certificate_utils.cpp b/keystore2/src/certificate_utils.cpp
new file mode 100644
index 0000000..56dd3f4
--- /dev/null
+++ b/keystore2/src/certificate_utils.cpp
@@ -0,0 +1,558 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <certificate_utils.h>
+
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/x509v3.h>
+
+#include <functional>
+#include <limits>
+#include <string>
+#include <variant>
+#include <vector>
+
+namespace keystore {
+
+namespace {
+
+constexpr int kDigitalSignatureKeyUsageBit = 0;
+constexpr int kKeyEnciphermentKeyUsageBit = 2;
+constexpr int kDataEnciphermentKeyUsageBit = 3;
+constexpr int kKeyCertSignBit = 5;
+constexpr int kMaxKeyUsageBit = 8;
+
+DEFINE_OPENSSL_OBJECT_POINTER(ASN1_STRING);
+DEFINE_OPENSSL_OBJECT_POINTER(RSA_PSS_PARAMS);
+DEFINE_OPENSSL_OBJECT_POINTER(AUTHORITY_KEYID);
+DEFINE_OPENSSL_OBJECT_POINTER(BASIC_CONSTRAINTS);
+DEFINE_OPENSSL_OBJECT_POINTER(X509_ALGOR);
+
+} // namespace
+
+std::variant<CertUtilsError, X509_NAME_Ptr> makeCommonName(const std::string& name) {
+ X509_NAME_Ptr x509_name(X509_NAME_new());
+ if (!x509_name) {
+ return CertUtilsError::BoringSsl;
+ }
+ if (!X509_NAME_add_entry_by_txt(x509_name.get(), "CN", MBSTRING_ASC,
+ reinterpret_cast<const uint8_t*>(name.c_str()), name.length(),
+ -1 /* loc */, 0 /* set */)) {
+ return CertUtilsError::BoringSsl;
+ }
+ return x509_name;
+}
+
+std::variant<CertUtilsError, std::vector<uint8_t>> makeKeyId(const X509* cert) {
+ std::vector<uint8_t> keyid(20);
+ unsigned int len;
+ if (!X509_pubkey_digest(cert, EVP_sha1(), keyid.data(), &len)) {
+ return CertUtilsError::Encoding;
+ }
+ return keyid;
+}
+
+std::variant<CertUtilsError, AUTHORITY_KEYID_Ptr>
+makeAuthorityKeyExtension(const std::vector<uint8_t>& keyid) {
+ AUTHORITY_KEYID_Ptr auth_key(AUTHORITY_KEYID_new());
+ if (!auth_key) {
+ return CertUtilsError::MemoryAllocation;
+ }
+
+ auth_key->keyid = ASN1_OCTET_STRING_new();
+ if (auth_key->keyid == nullptr) {
+ return CertUtilsError::MemoryAllocation;
+ }
+
+ if (!ASN1_OCTET_STRING_set(auth_key->keyid, keyid.data(), keyid.size())) {
+ return CertUtilsError::BoringSsl;
+ }
+
+ return auth_key;
+}
+
+std::variant<CertUtilsError, ASN1_OCTET_STRING_Ptr>
+makeSubjectKeyExtension(const std::vector<uint8_t>& keyid) {
+
+ // Build OCTET_STRING
+ ASN1_OCTET_STRING_Ptr keyid_str(ASN1_OCTET_STRING_new());
+ if (!keyid_str || !ASN1_OCTET_STRING_set(keyid_str.get(), keyid.data(), keyid.size())) {
+ return CertUtilsError::BoringSsl;
+ }
+
+ return keyid_str;
+}
+
+std::variant<CertUtilsError, BASIC_CONSTRAINTS_Ptr>
+makeBasicConstraintsExtension(bool is_ca, std::optional<int> path_length) {
+
+ BASIC_CONSTRAINTS_Ptr bcons(BASIC_CONSTRAINTS_new());
+ if (!bcons) {
+ return CertUtilsError::MemoryAllocation;
+ }
+
+ bcons->ca = is_ca;
+ bcons->pathlen = nullptr;
+ if (path_length) {
+ bcons->pathlen = ASN1_INTEGER_new();
+ if (bcons->pathlen == nullptr || !ASN1_INTEGER_set(bcons->pathlen, *path_length)) {
+ return CertUtilsError::BoringSsl;
+ }
+ }
+
+ return bcons;
+}
+
+std::variant<CertUtilsError, ASN1_BIT_STRING_Ptr>
+makeKeyUsageExtension(bool is_signing_key, bool is_encryption_key, bool is_cert_key) {
+ // Build BIT_STRING with correct contents.
+ ASN1_BIT_STRING_Ptr key_usage(ASN1_BIT_STRING_new());
+ if (!key_usage) {
+ return CertUtilsError::BoringSsl;
+ }
+
+ for (size_t i = 0; i <= kMaxKeyUsageBit; ++i) {
+ if (!ASN1_BIT_STRING_set_bit(key_usage.get(), i, 0)) {
+ return CertUtilsError::BoringSsl;
+ }
+ }
+
+ if (is_signing_key) {
+ if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kDigitalSignatureKeyUsageBit, 1)) {
+ return CertUtilsError::BoringSsl;
+ }
+ }
+
+ if (is_encryption_key) {
+ if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyEnciphermentKeyUsageBit, 1) ||
+ !ASN1_BIT_STRING_set_bit(key_usage.get(), kDataEnciphermentKeyUsageBit, 1)) {
+ return CertUtilsError::BoringSsl;
+ }
+ }
+
+ if (is_cert_key) {
+ if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyCertSignBit, 1)) {
+ return CertUtilsError::BoringSsl;
+ }
+ }
+
+ return key_usage;
+}
+
+// Creates a rump certificate structure with serial, subject and issuer names, as well as
+// activation and expiry date.
+// Callers should pass an empty X509_Ptr and check the return value for CertUtilsError::Ok (0)
+// before accessing the result.
+std::variant<CertUtilsError, X509_Ptr>
+makeCertRump(const uint32_t serial, const char subject[], const uint64_t activeDateTimeMilliSeconds,
+ const uint64_t usageExpireDateTimeMilliSeconds) {
+
+ // Sanitize pointer arguments.
+ if (!subject || strlen(subject) == 0) {
+ return CertUtilsError::InvalidArgument;
+ }
+
+ // Create certificate structure.
+ X509_Ptr certificate(X509_new());
+ if (!certificate) {
+ return CertUtilsError::BoringSsl;
+ }
+
+ // Set the X509 version.
+ if (!X509_set_version(certificate.get(), 2 /* version 3, but zero-based */)) {
+ return CertUtilsError::BoringSsl;
+ }
+
+ // Set the certificate serialNumber
+ ASN1_INTEGER_Ptr serialNumber(ASN1_INTEGER_new());
+ if (!serialNumber || !ASN1_INTEGER_set(serialNumber.get(), serial) ||
+ !X509_set_serialNumber(certificate.get(), serialNumber.get() /* Don't release; copied */))
+ return CertUtilsError::BoringSsl;
+
+ // Set Subject Name
+ auto subjectName = makeCommonName(subject);
+ if (auto x509_subject = std::get_if<X509_NAME_Ptr>(&subjectName)) {
+ if (!X509_set_subject_name(certificate.get(), x509_subject->get() /* copied */)) {
+ return CertUtilsError::BoringSsl;
+ }
+ } else {
+ return std::get<CertUtilsError>(subjectName);
+ }
+
+ // Set activation date.
+ ASN1_TIME_Ptr notBefore(ASN1_TIME_new());
+ if (!notBefore || !ASN1_TIME_set(notBefore.get(), activeDateTimeMilliSeconds / 1000) ||
+ !X509_set_notBefore(certificate.get(), notBefore.get() /* Don't release; copied */))
+ return CertUtilsError::BoringSsl;
+
+ // Set expiration date.
+ time_t notAfterTime;
+ notAfterTime = (time_t)std::min((uint64_t)std::numeric_limits<time_t>::max(),
+ usageExpireDateTimeMilliSeconds / 1000);
+
+ ASN1_TIME_Ptr notAfter(ASN1_TIME_new());
+ if (!notAfter || !ASN1_TIME_set(notAfter.get(), notAfterTime) ||
+ !X509_set_notAfter(certificate.get(), notAfter.get() /* Don't release; copied */)) {
+ return CertUtilsError::BoringSsl;
+ }
+
+ return certificate;
+}
+
+std::variant<CertUtilsError, X509_Ptr>
+makeCert(const EVP_PKEY* evp_pkey, const uint32_t serial, const char subject[],
+ const uint64_t activeDateTimeMilliSeconds, const uint64_t usageExpireDateTimeMilliSeconds,
+ bool addSubjectKeyIdEx, std::optional<KeyUsageExtension> keyUsageEx,
+ std::optional<BasicConstraintsExtension> basicConstraints) {
+
+ // Make the rump certificate with serial, subject, not before and not after dates.
+ auto certificateV =
+ makeCertRump(serial, subject, activeDateTimeMilliSeconds, usageExpireDateTimeMilliSeconds);
+ if (auto error = std::get_if<CertUtilsError>(&certificateV)) {
+ return *error;
+ }
+ auto certificate = std::move(std::get<X509_Ptr>(certificateV));
+
+ // Set the public key.
+ if (!X509_set_pubkey(certificate.get(), const_cast<EVP_PKEY*>(evp_pkey))) {
+ return CertUtilsError::BoringSsl;
+ }
+
+ if (keyUsageEx) {
+ // Make and add the key usage extension.
+ auto key_usage_extensionV = makeKeyUsageExtension(
+ keyUsageEx->isSigningKey, keyUsageEx->isEncryptionKey, keyUsageEx->isCertificationKey);
+ if (auto error = std::get_if<CertUtilsError>(&key_usage_extensionV)) {
+ return *error;
+ }
+ auto key_usage_extension = std::move(std::get<ASN1_BIT_STRING_Ptr>(key_usage_extensionV));
+ if (!X509_add1_ext_i2d(certificate.get(), NID_key_usage,
+ key_usage_extension.get() /* Don't release; copied */,
+ true /* critical */, 0 /* flags */)) {
+ return CertUtilsError::BoringSsl;
+ }
+ }
+
+ if (basicConstraints) {
+ // Make and add basic constraints
+ auto basic_constraints_extensionV =
+ makeBasicConstraintsExtension(basicConstraints->isCa, basicConstraints->pathLength);
+ if (auto error = std::get_if<CertUtilsError>(&basic_constraints_extensionV)) {
+ return *error;
+ }
+ auto basic_constraints_extension =
+ std::move(std::get<BASIC_CONSTRAINTS_Ptr>(basic_constraints_extensionV));
+ if (!X509_add1_ext_i2d(certificate.get(), NID_basic_constraints,
+ basic_constraints_extension.get() /* Don't release; copied */,
+ true /* critical */, 0 /* flags */)) {
+ return CertUtilsError::BoringSsl;
+ }
+ }
+
+ if (addSubjectKeyIdEx) {
+ // Make and add subject key id extension.
+ auto keyidV = makeKeyId(certificate.get());
+ if (auto error = std::get_if<CertUtilsError>(&keyidV)) {
+ return *error;
+ }
+ auto& keyid = std::get<std::vector<uint8_t>>(keyidV);
+
+ auto subject_key_extensionV = makeSubjectKeyExtension(keyid);
+ if (auto error = std::get_if<CertUtilsError>(&subject_key_extensionV)) {
+ return *error;
+ }
+ auto subject_key_extension =
+ std::move(std::get<ASN1_OCTET_STRING_Ptr>(subject_key_extensionV));
+ if (!X509_add1_ext_i2d(certificate.get(), NID_subject_key_identifier,
+ subject_key_extension.get() /* Don't release; copied */,
+ false /* critical */, 0 /* flags */)) {
+ return CertUtilsError::BoringSsl;
+ }
+ }
+
+ return certificate;
+}
+
+CertUtilsError setIssuer(X509* cert, const X509* signingCert, bool addAuthKeyExt) {
+
+ X509_NAME* issuerName(X509_get_subject_name(signingCert));
+
+ // Set Issuer Name
+ if (issuerName) {
+ if (!X509_set_issuer_name(cert, issuerName /* copied */)) {
+ return CertUtilsError::BoringSsl;
+ }
+ } else {
+ return CertUtilsError::Encoding;
+ }
+
+ if (addAuthKeyExt) {
+ // Make and add authority key extension - self signed.
+ auto keyidV = makeKeyId(signingCert);
+ if (auto error = std::get_if<CertUtilsError>(&keyidV)) {
+ return *error;
+ }
+ auto& keyid = std::get<std::vector<uint8_t>>(keyidV);
+
+ auto auth_key_extensionV = makeAuthorityKeyExtension(keyid);
+ if (auto error = std::get_if<CertUtilsError>(&auth_key_extensionV)) {
+ return *error;
+ }
+ auto auth_key_extension = std::move(std::get<AUTHORITY_KEYID_Ptr>(auth_key_extensionV));
+ if (!X509_add1_ext_i2d(cert, NID_authority_key_identifier, auth_key_extension.get(), false,
+ 0)) {
+ return CertUtilsError::BoringSsl;
+ }
+ }
+ return CertUtilsError::Ok;
+}
+
+// Takes a certificate a signing certificate and the raw private signing_key. And signs
+// the certificate with the latter.
+CertUtilsError signCert(X509* certificate, EVP_PKEY* signing_key) {
+
+ if (certificate == nullptr) {
+ return CertUtilsError::UnexpectedNullPointer;
+ }
+
+ if (!X509_sign(certificate, signing_key, EVP_sha256())) {
+ return CertUtilsError::BoringSsl;
+ }
+
+ return CertUtilsError::Ok;
+}
+
+std::variant<CertUtilsError, std::vector<uint8_t>> encodeCert(X509* certificate) {
+ int len = i2d_X509(certificate, nullptr);
+ if (len < 0) {
+ return CertUtilsError::BoringSsl;
+ }
+
+ auto result = std::vector<uint8_t>(len);
+ uint8_t* p = result.data();
+
+ if (i2d_X509(certificate, &p) < 0) {
+ return CertUtilsError::BoringSsl;
+ }
+ return result;
+}
+
+CertUtilsError setRsaDigestAlgorField(X509_ALGOR** alg_ptr, const EVP_MD* digest) {
+ if (alg_ptr == nullptr || digest == nullptr) {
+ return CertUtilsError::UnexpectedNullPointer;
+ }
+ *alg_ptr = X509_ALGOR_new();
+ if (*alg_ptr == nullptr) {
+ return CertUtilsError::MemoryAllocation;
+ }
+ X509_ALGOR_set_md(*alg_ptr, digest);
+ return CertUtilsError::Ok;
+}
+
+CertUtilsError setPssMaskGeneratorField(X509_ALGOR** alg_ptr, const EVP_MD* digest) {
+ X509_ALGOR* mgf1_digest = nullptr;
+ if (auto error = setRsaDigestAlgorField(&mgf1_digest, digest)) {
+ return error;
+ }
+ X509_ALGOR_Ptr mgf1_digest_ptr(mgf1_digest);
+
+ ASN1_OCTET_STRING* mgf1_digest_algor_str = nullptr;
+ if (!ASN1_item_pack(mgf1_digest, ASN1_ITEM_rptr(X509_ALGOR), &mgf1_digest_algor_str)) {
+ return CertUtilsError::Encoding;
+ }
+ ASN1_OCTET_STRING_Ptr mgf1_digest_algor_str_ptr(mgf1_digest_algor_str);
+
+ *alg_ptr = X509_ALGOR_new();
+ if (*alg_ptr == nullptr) {
+ return CertUtilsError::MemoryAllocation;
+ }
+ X509_ALGOR_set0(*alg_ptr, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, mgf1_digest_algor_str);
+ // *alg_ptr took ownership of the octet string
+ mgf1_digest_algor_str_ptr.release();
+ return CertUtilsError::Ok;
+}
+
+static CertUtilsError setSaltLength(RSA_PSS_PARAMS* pss_params, unsigned length) {
+ pss_params->saltLength = ASN1_INTEGER_new();
+ if (pss_params->saltLength == nullptr) {
+ return CertUtilsError::MemoryAllocation;
+ }
+ if (!ASN1_INTEGER_set(pss_params->saltLength, length)) {
+ return CertUtilsError::Encoding;
+ };
+ return CertUtilsError::Ok;
+}
+
+std::variant<CertUtilsError, ASN1_STRING_Ptr> buildRsaPssParameter(Digest digest) {
+ RSA_PSS_PARAMS_Ptr pss(RSA_PSS_PARAMS_new());
+ if (!pss) {
+ return CertUtilsError::MemoryAllocation;
+ }
+
+ const EVP_MD* md = nullptr;
+
+ switch (digest) {
+ case Digest::SHA1:
+ break;
+ case Digest::SHA224:
+ md = EVP_sha224();
+ break;
+ case Digest::SHA256:
+ md = EVP_sha256();
+ break;
+ case Digest::SHA384:
+ md = EVP_sha384();
+ break;
+ case Digest::SHA512:
+ md = EVP_sha512();
+ break;
+ default:
+ return CertUtilsError::InvalidArgument;
+ }
+
+ if (md != nullptr) {
+ if (auto error = setSaltLength(pss.get(), EVP_MD_size(md))) {
+ return error;
+ }
+ if (auto error = setRsaDigestAlgorField(&pss->hashAlgorithm, md)) {
+ return error;
+ }
+ if (auto error = setPssMaskGeneratorField(&pss->maskGenAlgorithm, md)) {
+ return error;
+ }
+ }
+
+ ASN1_STRING* algo_str = nullptr;
+ if (!ASN1_item_pack(pss.get(), ASN1_ITEM_rptr(RSA_PSS_PARAMS), &algo_str)) {
+ return CertUtilsError::BoringSsl;
+ }
+
+ return ASN1_STRING_Ptr(algo_str);
+}
+
+CertUtilsError makeAndSetAlgo(X509_ALGOR* algo_field, Algo algo, Padding padding, Digest digest) {
+ if (algo_field == nullptr) {
+ return CertUtilsError::UnexpectedNullPointer;
+ }
+ ASN1_STRING_Ptr param;
+ int param_type = V_ASN1_UNDEF;
+ int nid = 0;
+ switch (algo) {
+ case Algo::ECDSA:
+ switch (digest) {
+ case Digest::SHA1:
+ nid = NID_ecdsa_with_SHA1;
+ break;
+ case Digest::SHA224:
+ nid = NID_ecdsa_with_SHA224;
+ break;
+ case Digest::SHA256:
+ nid = NID_ecdsa_with_SHA256;
+ break;
+ case Digest::SHA384:
+ nid = NID_ecdsa_with_SHA384;
+ break;
+ case Digest::SHA512:
+ nid = NID_ecdsa_with_SHA512;
+ break;
+ default:
+ return CertUtilsError::InvalidArgument;
+ }
+ break;
+ case Algo::RSA:
+ switch (padding) {
+ case Padding::PKCS1_5:
+ param_type = V_ASN1_NULL;
+ switch (digest) {
+ case Digest::SHA1:
+ nid = NID_sha1WithRSAEncryption;
+ break;
+ case Digest::SHA224:
+ nid = NID_sha224WithRSAEncryption;
+ break;
+ case Digest::SHA256:
+ nid = NID_sha256WithRSAEncryption;
+ break;
+ case Digest::SHA384:
+ nid = NID_sha384WithRSAEncryption;
+ break;
+ case Digest::SHA512:
+ nid = NID_sha512WithRSAEncryption;
+ break;
+ default:
+ return CertUtilsError::InvalidArgument;
+ }
+ break;
+ case Padding::PSS: {
+ auto v = buildRsaPssParameter(digest);
+ if (auto param_str = std::get_if<ASN1_STRING_Ptr>(&v)) {
+ param = std::move(*param_str);
+ param_type = V_ASN1_SEQUENCE;
+ nid = NID_rsassaPss;
+ } else {
+ return std::get<CertUtilsError>(v);
+ }
+ break;
+ }
+ default:
+ return CertUtilsError::InvalidArgument;
+ }
+ break;
+ default:
+ return CertUtilsError::InvalidArgument;
+ }
+
+ if (!X509_ALGOR_set0(algo_field, OBJ_nid2obj(nid), param_type, param.get())) {
+ return CertUtilsError::Encoding;
+ }
+ // The X509 struct took ownership.
+ param.release();
+ return CertUtilsError::Ok;
+}
+
+// This function allows for signing a
+CertUtilsError signCertWith(X509* certificate,
+ std::function<std::vector<uint8_t>(const uint8_t*, size_t)> sign,
+ Algo algo, Padding padding, Digest digest) {
+ if (auto error = makeAndSetAlgo(certificate->sig_alg, algo, padding, digest)) {
+ return error;
+ }
+ if (auto error = makeAndSetAlgo(certificate->cert_info->signature, algo, padding, digest)) {
+ return error;
+ }
+
+ uint8_t* cert_buf = nullptr;
+ size_t buf_len = i2d_re_X509_tbs(certificate, &cert_buf);
+ if (buf_len < 0) {
+ return CertUtilsError::Encoding;
+ }
+
+ bssl::UniquePtr<uint8_t> free_cert_buf(cert_buf);
+ auto signature = sign(cert_buf, buf_len);
+
+ if (!ASN1_STRING_set(certificate->signature, signature.data(), signature.size())) {
+ return CertUtilsError::BoringSsl;
+ }
+
+ certificate->signature->flags &= ~(0x07);
+ certificate->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+
+ return CertUtilsError::Ok;
+}
+
+} // namespace keystore
diff --git a/keystore2/src/crypto.cpp b/keystore2/src/crypto.cpp
new file mode 100644
index 0000000..8c52e4c
--- /dev/null
+++ b/keystore2/src/crypto.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "keystore2"
+
+#include "crypto.hpp"
+
+#include <log/log.h>
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+
+#include <vector>
+
+// Copied from system/security/keystore/blob.h.
+
+constexpr size_t kGcmTagLength = 128 / 8;
+constexpr size_t kAes128KeySizeBytes = 128 / 8;
+
+// Copied from system/security/keystore/blob.cpp.
+
+#if defined(__clang__)
+#define OPTNONE __attribute__((optnone))
+#elif defined(__GNUC__)
+#define OPTNONE __attribute__((optimize("O0")))
+#else
+#error Need a definition for OPTNONE
+#endif
+
+class ArrayEraser {
+ public:
+ ArrayEraser(uint8_t* arr, size_t size) : mArr(arr), mSize(size) {}
+ OPTNONE ~ArrayEraser() { std::fill(mArr, mArr + mSize, 0); }
+
+ private:
+ volatile uint8_t* mArr;
+ size_t mSize;
+};
+
+/**
+ * Returns a EVP_CIPHER appropriate for the given key size.
+ */
+const EVP_CIPHER* getAesCipherForKey(size_t key_size) {
+ const EVP_CIPHER* cipher = EVP_aes_256_gcm();
+ if (key_size == kAes128KeySizeBytes) {
+ cipher = EVP_aes_128_gcm();
+ }
+ return cipher;
+}
+
+/*
+ * Encrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
+ * 'iv' and write output to 'out' (which may be the same location as 'in') and 128-bit tag to
+ * 'tag'.
+ */
+bool AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
+ size_t key_size, const uint8_t* iv, uint8_t* tag) {
+
+ // There can be 128-bit and 256-bit keys
+ const EVP_CIPHER* cipher = getAesCipherForKey(key_size);
+
+ bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
+
+ EVP_EncryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
+ EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
+
+ std::vector<uint8_t> out_tmp(len);
+ uint8_t* out_pos = out_tmp.data();
+ int out_len;
+
+ EVP_EncryptUpdate(ctx.get(), out_pos, &out_len, in, len);
+ out_pos += out_len;
+ EVP_EncryptFinal_ex(ctx.get(), out_pos, &out_len);
+ out_pos += out_len;
+ if (out_pos - out_tmp.data() != static_cast<ssize_t>(len)) {
+ ALOGD("Encrypted ciphertext is the wrong size, expected %zu, got %zd", len,
+ out_pos - out_tmp.data());
+ return false;
+ }
+
+ std::copy(out_tmp.data(), out_pos, out);
+ EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kGcmTagLength, tag);
+
+ return true;
+}
+
+/*
+ * Decrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
+ * 'iv', checking 128-bit tag at 'tag' and writing plaintext to 'out'(which may be the same
+ * location as 'in').
+ */
+bool AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
+ size_t key_size, const uint8_t* iv, const uint8_t* tag) {
+
+ // There can be 128-bit and 256-bit keys
+ const EVP_CIPHER* cipher = getAesCipherForKey(key_size);
+
+ bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
+
+ EVP_DecryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
+ EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
+ EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kGcmTagLength, const_cast<uint8_t*>(tag));
+
+ std::vector<uint8_t> out_tmp(len);
+ ArrayEraser out_eraser(out_tmp.data(), len);
+ uint8_t* out_pos = out_tmp.data();
+ int out_len;
+
+ EVP_DecryptUpdate(ctx.get(), out_pos, &out_len, in, len);
+ out_pos += out_len;
+ if (!EVP_DecryptFinal_ex(ctx.get(), out_pos, &out_len)) {
+ ALOGE("Failed to decrypt blob; ciphertext or tag is likely corrupted");
+ return false;
+ }
+ out_pos += out_len;
+ if (out_pos - out_tmp.data() != static_cast<ssize_t>(len)) {
+ ALOGE("Encrypted plaintext is the wrong size, expected %zu, got %zd", len,
+ out_pos - out_tmp.data());
+ return false;
+ }
+
+ std::copy(out_tmp.data(), out_pos, out);
+
+ return true;
+}
+
+// Copied from system/security/keystore/keymaster_enforcement.cpp.
+
+class EvpMdCtx {
+ public:
+ EvpMdCtx() { EVP_MD_CTX_init(&ctx_); }
+ ~EvpMdCtx() { EVP_MD_CTX_cleanup(&ctx_); }
+
+ EVP_MD_CTX* get() { return &ctx_; }
+
+ private:
+ EVP_MD_CTX ctx_;
+};
+
+bool CreateKeyId(const uint8_t* key_blob, size_t len, km_id_t* out_id) {
+ EvpMdCtx ctx;
+
+ uint8_t hash[EVP_MAX_MD_SIZE];
+ unsigned int hash_len;
+ if (EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr /* ENGINE */) &&
+ EVP_DigestUpdate(ctx.get(), key_blob, len) &&
+ EVP_DigestFinal_ex(ctx.get(), hash, &hash_len)) {
+ assert(hash_len >= sizeof(*out_id));
+ memcpy(out_id, hash, sizeof(*out_id));
+ return true;
+ }
+
+ return false;
+}
+
+// Copied from system/security/keystore/user_state.h
+
+static constexpr size_t SALT_SIZE = 16;
+
+// Copied from system/security/keystore/user_state.cpp.
+
+void generateKeyFromPassword(uint8_t* key, size_t key_len, const char* pw, size_t pw_len,
+ uint8_t* salt) {
+ size_t saltSize;
+ if (salt != nullptr) {
+ saltSize = SALT_SIZE;
+ } else {
+ // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
+ salt = (uint8_t*)"keystore";
+ // sizeof = 9, not strlen = 8
+ saltSize = sizeof("keystore");
+ }
+
+ const EVP_MD* digest = EVP_sha256();
+
+ // SHA1 was used prior to increasing the key size
+ if (key_len == kAes128KeySizeBytes) {
+ digest = EVP_sha1();
+ }
+
+ PKCS5_PBKDF2_HMAC(pw, pw_len, salt, saltSize, 8192, digest, key_len, key);
+}
diff --git a/keystore2/src/crypto.hpp b/keystore2/src/crypto.hpp
new file mode 100644
index 0000000..9a9bb2e
--- /dev/null
+++ b/keystore2/src/crypto.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CRYPTO_H__
+#define __CRYPTO_H__
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+
+extern "C" {
+ bool AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len,
+ const uint8_t* key, size_t key_size, const uint8_t* iv, uint8_t* tag);
+ bool AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len,
+ const uint8_t* key, size_t key_size, const uint8_t* iv,
+ const uint8_t* tag);
+
+ // Copied from system/security/keystore/keymaster_enforcement.h.
+ typedef uint64_t km_id_t;
+
+ bool CreateKeyId(const uint8_t* key_blob, size_t len, km_id_t* out_id);
+
+ void generateKeyFromPassword(uint8_t* key, size_t key_len, const char* pw,
+ size_t pw_len, uint8_t* salt);
+}
+
+#endif // __CRYPTO_H__
diff --git a/keystore2/src/crypto.rs b/keystore2/src/crypto.rs
new file mode 100644
index 0000000..b25b648
--- /dev/null
+++ b/keystore2/src/crypto.rs
@@ -0,0 +1,78 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#[cfg(test)]
+mod tests {
+
+ use keystore2_crypto_bindgen::{
+ generateKeyFromPassword, AES_gcm_decrypt, AES_gcm_encrypt, CreateKeyId,
+ };
+
+ #[test]
+ fn test_encrypt_decrypt() {
+ let input = vec![0; 16];
+ let mut out = vec![0; 16];
+ let mut out2 = vec![0; 16];
+ let key = vec![0; 16];
+ let iv = vec![0; 12];
+ let mut tag = vec![0; 16];
+ unsafe {
+ let res = AES_gcm_encrypt(
+ input.as_ptr(),
+ out.as_mut_ptr(),
+ 16,
+ key.as_ptr(),
+ 16,
+ iv.as_ptr(),
+ tag.as_mut_ptr(),
+ );
+ assert!(res);
+ assert_ne!(out, input);
+ assert_ne!(tag, input);
+ let res = AES_gcm_decrypt(
+ out.as_ptr(),
+ out2.as_mut_ptr(),
+ 16,
+ key.as_ptr(),
+ 16,
+ iv.as_ptr(),
+ tag.as_ptr(),
+ );
+ assert!(res);
+ assert_eq!(out2, input);
+ }
+ }
+
+ #[test]
+ fn test_create_key_id() {
+ let blob = vec![0; 16];
+ let mut out: u64 = 0;
+ unsafe {
+ let res = CreateKeyId(blob.as_ptr(), 16, &mut out);
+ assert!(res);
+ assert_ne!(out, 0);
+ }
+ }
+
+ #[test]
+ fn test_generate_key_from_password() {
+ let mut key = vec![0; 16];
+ let pw = vec![0; 16];
+ let mut salt = vec![0; 16];
+ unsafe {
+ generateKeyFromPassword(key.as_mut_ptr(), 16, pw.as_ptr(), 16, salt.as_mut_ptr());
+ }
+ assert_ne!(key, vec![0; 16]);
+ }
+}
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index ea70195..0ce4ad6 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -41,23 +41,27 @@
//! from the database module these functions take permission check
//! callbacks.
-use crate::error::Error as KsError;
-use crate::key_parameter::{KeyParameter, SqlField, TagType};
-use crate::{error, permission::KeyPermSet};
+use crate::error::{Error as KsError, ResponseCode};
+use crate::key_parameter::{KeyParameter, SqlField, Tag};
+use crate::permission::KeyPermSet;
use anyhow::{anyhow, Context, Result};
-use android_hardware_keymint::aidl::android::hardware::keymint::SecurityLevel::SecurityLevel as SecurityLevelType;
-use android_security_keystore2::aidl::android::security::keystore2::{
- Domain, Domain::Domain as DomainType, KeyDescriptor::KeyDescriptor,
+use android_hardware_keymint::aidl::android::hardware::keymint::SecurityLevel::SecurityLevel;
+use android_system_keystore2::aidl::android::system::keystore2::{
+ Domain::Domain, KeyDescriptor::KeyDescriptor,
};
+use lazy_static::lazy_static;
#[cfg(not(test))]
use rand::prelude::random;
use rusqlite::{
params, types::FromSql, types::FromSqlResult, types::ToSqlOutput, types::ValueRef, Connection,
OptionalExtension, Row, Rows, ToSql, Transaction, TransactionBehavior, NO_PARAMS,
};
-use std::sync::Once;
+use std::{
+ collections::HashSet,
+ sync::{Condvar, Mutex, Once},
+};
#[cfg(test)]
use tests::random;
@@ -89,17 +93,78 @@
}
}
+lazy_static! {
+ static ref KEY_ID_LOCK: KeyIdLockDb = KeyIdLockDb::new();
+}
+
+struct KeyIdLockDb {
+ locked_keys: Mutex<HashSet<i64>>,
+ cond_var: Condvar,
+}
+
+/// A locked key. While a guard exists for a given key id, the same key cannot be loaded
+/// from the database a second time. Most functions manipulating the key blob database
+/// require a KeyIdGuard.
+#[derive(Debug)]
+pub struct KeyIdGuard(i64);
+
+impl KeyIdLockDb {
+ fn new() -> Self {
+ Self { locked_keys: Mutex::new(HashSet::new()), cond_var: Condvar::new() }
+ }
+
+ /// This function blocks until an exclusive lock for the given key entry id can
+ /// be acquired. It returns a guard object, that represents the lifecycle of the
+ /// acquired lock.
+ pub fn get(&self, key_id: i64) -> KeyIdGuard {
+ let mut locked_keys = self.locked_keys.lock().unwrap();
+ while locked_keys.contains(&key_id) {
+ locked_keys = self.cond_var.wait(locked_keys).unwrap();
+ }
+ locked_keys.insert(key_id);
+ KeyIdGuard(key_id)
+ }
+
+ /// This function attempts to acquire an exclusive lock on a given key id. If the
+ /// given key id is already taken the function returns None immediately. If a lock
+ /// can be acquired this function returns a guard object, that represents the
+ /// lifecycle of the acquired lock.
+ pub fn try_get(&self, key_id: i64) -> Option<KeyIdGuard> {
+ let mut locked_keys = self.locked_keys.lock().unwrap();
+ if locked_keys.insert(key_id) {
+ Some(KeyIdGuard(key_id))
+ } else {
+ None
+ }
+ }
+}
+
+impl KeyIdGuard {
+ /// Get the numeric key id of the locked key.
+ pub fn id(&self) -> i64 {
+ self.0
+ }
+}
+
+impl Drop for KeyIdGuard {
+ fn drop(&mut self) {
+ let mut locked_keys = KEY_ID_LOCK.locked_keys.lock().unwrap();
+ locked_keys.remove(&self.0);
+ KEY_ID_LOCK.cond_var.notify_all();
+ }
+}
+
/// This type represents a Keystore 2.0 key entry.
/// An entry has a unique `id` by which it can be found in the database.
/// It has a security level field, key parameters, and three optional fields
/// for the KeyMint blob, public certificate and a public certificate chain.
-#[derive(Debug, Default, Clone, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
pub struct KeyEntry {
id: i64,
km_blob: Option<Vec<u8>>,
cert: Option<Vec<u8>>,
cert_chain: Option<Vec<u8>>,
- sec_level: SecurityLevelType,
+ sec_level: SecurityLevel,
parameters: Vec<KeyParameter>,
}
@@ -133,9 +198,17 @@
self.cert_chain.take()
}
/// Returns the security level of the key entry.
- pub fn sec_level(&self) -> SecurityLevelType {
+ pub fn sec_level(&self) -> SecurityLevel {
self.sec_level
}
+ /// Exposes the key parameters of this key entry.
+ pub fn key_parameters(&self) -> &Vec<KeyParameter> {
+ &self.parameters
+ }
+ /// Consumes this key entry and extracts the keyparameters from it.
+ pub fn into_key_parameters(self) -> Vec<KeyParameter> {
+ self.parameters
+ }
}
/// Indicates the sub component of a key entry for persistent storage.
@@ -261,22 +334,24 @@
/// key artifacts, i.e., blobs and parameters have been associated with the new
/// key id. Finalizing with `rebind_alias` makes the creation of a new key entry
/// atomic even if key generation is not.
- pub fn create_key_entry(&self, domain: DomainType, namespace: i64) -> Result<i64> {
+ pub fn create_key_entry(&self, domain: Domain, namespace: i64) -> Result<KeyIdGuard> {
match domain {
- Domain::App | Domain::SELinux => {}
+ Domain::APP | Domain::SELINUX => {}
_ => {
return Err(KsError::sys())
.context(format!("Domain {:?} must be either App or SELinux.", domain));
}
}
- Self::insert_with_retry(|id| {
- self.conn.execute(
- "INSERT into persistent.keyentry (id, creation_date, domain, namespace, alias)
+ Ok(KEY_ID_LOCK.get(
+ Self::insert_with_retry(|id| {
+ self.conn.execute(
+ "INSERT into persistent.keyentry (id, creation_date, domain, namespace, alias)
VALUES(?, datetime('now'), ?, ?, NULL);",
- params![id, domain as i64, namespace],
- )
- })
- .context("In create_key_entry")
+ params![id, domain.0 as u32, namespace],
+ )
+ })
+ .context("In create_key_entry")?,
+ ))
}
/// Inserts a new blob and associates it with the given key id. Each blob
@@ -287,16 +362,16 @@
/// other than `SubComponentType::KM_BLOB` are ignored.
pub fn insert_blob(
&mut self,
- key_id: i64,
+ key_id: &KeyIdGuard,
sc_type: SubComponentType,
blob: &[u8],
- sec_level: SecurityLevelType,
+ sec_level: SecurityLevel,
) -> Result<()> {
self.conn
.execute(
"INSERT into persistent.blobentry (subcomponent_type, keyentryid, blob, sec_level)
VALUES (?, ?, ?, ?);",
- params![sc_type, key_id, blob, sec_level],
+ params![sc_type, key_id.0, blob, sec_level.0],
)
.context("Failed to insert blob.")?;
Ok(())
@@ -306,7 +381,7 @@
/// and associates them with the given `key_id`.
pub fn insert_keyparameter<'a>(
&mut self,
- key_id: i64,
+ key_id: &KeyIdGuard,
params: impl IntoIterator<Item = &'a KeyParameter>,
) -> Result<()> {
let mut stmt = self
@@ -319,8 +394,13 @@
let iter = params.into_iter();
for p in iter {
- stmt.insert(params![key_id, p.get_tag(), p.key_parameter_value(), p.security_level()])
- .with_context(|| format!("In insert_keyparameter: Failed to insert {:?}", p))?;
+ stmt.insert(params![
+ key_id.0,
+ p.get_tag().0,
+ p.key_parameter_value(),
+ p.security_level().0
+ ])
+ .with_context(|| format!("In insert_keyparameter: Failed to insert {:?}", p))?;
}
Ok(())
}
@@ -330,13 +410,13 @@
/// with the same alias-domain-namespace tuple if such row exits.
pub fn rebind_alias(
&mut self,
- newid: i64,
+ newid: &KeyIdGuard,
alias: &str,
- domain: DomainType,
+ domain: Domain,
namespace: i64,
) -> Result<()> {
match domain {
- Domain::App | Domain::SELinux => {}
+ Domain::APP | Domain::SELINUX => {}
_ => {
return Err(KsError::sys()).context(format!(
"In rebind_alias: Domain {:?} must be either App or SELinux.",
@@ -352,7 +432,7 @@
"UPDATE persistent.keyentry
SET alias = NULL, domain = NULL, namespace = NULL
WHERE alias = ? AND domain = ? AND namespace = ?;",
- params![alias, domain as i64, namespace],
+ params![alias, domain.0 as u32, namespace],
)
.context("In rebind_alias: Failed to rebind existing entry.")?;
let result = tx
@@ -360,7 +440,7 @@
"UPDATE persistent.keyentry
SET alias = ?
WHERE id = ? AND domain = ? AND namespace = ?;",
- params![alias, newid, domain as i64, namespace],
+ params![alias, newid.0, domain.0 as u32, namespace],
)
.context("In rebind_alias: Failed to set alias.")?;
if result != 1 {
@@ -395,10 +475,10 @@
)
.context("In load_key_entry_id: Failed to select from keyentry table.")?;
let mut rows = stmt
- .query(params![key.domain, key.namespace_, alias])
+ .query(params![key.domain.0 as u32, key.nspace, alias])
.context("In load_key_entry_id: Failed to read from keyentry table.")?;
Self::with_rows_extract_one(&mut rows, |row| {
- row.map_or_else(|| Err(KsError::Rc(error::Rc::KeyNotFound)), Ok)?
+ row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?
.get(0)
.context("Failed to unpack id.")
})
@@ -408,13 +488,13 @@
/// This helper function completes the access tuple of a key, which is required
/// to perform access control. The strategy depends on the `domain` field in the
/// key descriptor.
- /// * Domain::SELinux: The access tuple is complete and this function only loads
+ /// * Domain::SELINUX: The access tuple is complete and this function only loads
/// the key_id for further processing.
- /// * Domain::App: Like Domain::SELinux, but the tuple is completed by `caller_uid`
+ /// * Domain::APP: Like Domain::SELINUX, but the tuple is completed by `caller_uid`
/// which serves as the namespace.
- /// * Domain::Grant: The grant table is queried for the `key_id` and the
+ /// * Domain::GRANT: The grant table is queried for the `key_id` and the
/// `access_vector`.
- /// * Domain::KeyId: The keyentry table is queried for the owning `domain` and
+ /// * Domain::KEY_ID: The keyentry table is queried for the owning `domain` and
/// `namespace`.
/// In each case the information returned is sufficient to perform the access
/// check and the key id can be used to load further key artifacts.
@@ -429,67 +509,69 @@
// We already have the full access tuple to perform access control.
// The only distinction is that we use the caller_uid instead
// of the caller supplied namespace if the domain field is
- // Domain::App.
- Domain::App | Domain::SELinux => {
+ // Domain::APP.
+ Domain::APP | Domain::SELINUX => {
let mut access_key = key;
- if access_key.domain == Domain::App {
- access_key.namespace_ = caller_uid as i64;
+ if access_key.domain == Domain::APP {
+ access_key.nspace = caller_uid as i64;
}
let key_id = Self::load_key_entry_id(&access_key, &tx)
- .with_context(|| format!("With key.domain = {}.", access_key.domain))?;
+ .with_context(|| format!("With key.domain = {:?}.", access_key.domain))?;
Ok((key_id, access_key, None))
}
- // Domain::Grant. In this case we load the key_id and the access_vector
+ // Domain::GRANT. In this case we load the key_id and the access_vector
// from the grant table.
- Domain::Grant => {
+ Domain::GRANT => {
let mut stmt = tx
.prepare(
"SELECT keyentryid, access_vector FROM perboot.grant
WHERE grantee = ? AND id = ?;",
)
- .context("Domain::Grant prepare statement failed")?;
+ .context("Domain::GRANT prepare statement failed")?;
let mut rows = stmt
- .query(params![caller_uid as i64, key.namespace_])
+ .query(params![caller_uid as i64, key.nspace])
.context("Domain:Grant: query failed.")?;
let (key_id, access_vector): (i64, i32) =
Self::with_rows_extract_one(&mut rows, |row| {
- let r = row.map_or_else(|| Err(KsError::Rc(error::Rc::KeyNotFound)), Ok)?;
+ let r =
+ row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Ok((
r.get(0).context("Failed to unpack key_id.")?,
r.get(1).context("Failed to unpack access_vector.")?,
))
})
- .context("Domain::Grant.")?;
+ .context("Domain::GRANT.")?;
Ok((key_id, key, Some(access_vector.into())))
}
- // Domain::KeyId. In this case we load the domain and namespace from the
+ // Domain::KEY_ID. In this case we load the domain and namespace from the
// keyentry database because we need them for access control.
- Domain::KeyId => {
+ Domain::KEY_ID => {
let mut stmt = tx
.prepare(
"SELECT domain, namespace FROM persistent.keyentry
WHERE
id = ?;",
)
- .context("Domain::KeyId: prepare statement failed")?;
+ .context("Domain::KEY_ID: prepare statement failed")?;
let mut rows =
- stmt.query(params![key.namespace_]).context("Domain::KeyId: query failed.")?;
- let (domain, namespace): (DomainType, i64) =
+ stmt.query(params![key.nspace]).context("Domain::KEY_ID: query failed.")?;
+ let (domain, namespace): (Domain, i64) =
Self::with_rows_extract_one(&mut rows, |row| {
- let r = row.map_or_else(|| Err(KsError::Rc(error::Rc::KeyNotFound)), Ok)?;
+ let r =
+ row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Ok((
- r.get(0).context("Failed to unpack domain.")?,
+ Domain(r.get(0).context("Failed to unpack domain.")?),
r.get(1).context("Failed to unpack namespace.")?,
))
})
- .context("Domain::KeyId.")?;
- let key_id = key.namespace_;
+ .context("Domain::KEY_ID.")?;
+ let key_id = key.nspace;
let mut access_key = key;
access_key.domain = domain;
- access_key.namespace_ = namespace;
+ access_key.nspace = namespace;
Ok((key_id, access_key, None))
}
@@ -501,7 +583,7 @@
key_id: i64,
load_bits: KeyEntryLoadBits,
tx: &Transaction,
- ) -> Result<(SecurityLevelType, Option<Vec<u8>>, Option<Vec<u8>>, Option<Vec<u8>>)> {
+ ) -> Result<(SecurityLevel, Option<Vec<u8>>, Option<Vec<u8>>, Option<Vec<u8>>)> {
let mut stmt = tx
.prepare(
"SELECT MAX(id), sec_level, subcomponent_type, blob FROM persistent.blobentry
@@ -512,7 +594,7 @@
let mut rows =
stmt.query(params![key_id]).context("In load_blob_components: query failed.")?;
- let mut sec_level: SecurityLevelType = Default::default();
+ let mut sec_level: SecurityLevel = Default::default();
let mut km_blob: Option<Vec<u8>> = None;
let mut cert_blob: Option<Vec<u8>> = None;
let mut cert_chain_blob: Option<Vec<u8>> = None;
@@ -521,7 +603,8 @@
row.get(2).context("Failed to extract subcomponent_type.")?;
match (sub_type, load_bits.load_public()) {
(SubComponentType::KM_BLOB, _) => {
- sec_level = row.get(1).context("Failed to extract security level.")?;
+ sec_level =
+ SecurityLevel(row.get(1).context("Failed to extract security level.")?);
if load_bits.load_km() {
km_blob = Some(row.get(3).context("Failed to extract KM blob.")?);
}
@@ -557,8 +640,8 @@
let mut rows =
stmt.query(params![key_id]).context("In load_key_parameters: query failed.")?;
Self::with_rows_extract_all(&mut rows, |row| {
- let tag: TagType = row.get(0).context("Failed to read tag.")?;
- let sec_level: SecurityLevelType = row.get(2).context("Failed to read sec_level.")?;
+ let tag = Tag(row.get(0).context("Failed to read tag.")?);
+ let sec_level = SecurityLevel(row.get(2).context("Failed to read sec_level.")?);
parameters.push(
KeyParameter::new_from_sql(tag, &SqlField::new(1, &row), sec_level)
.context("Failed to read KeyParameter.")?,
@@ -581,10 +664,18 @@
load_bits: KeyEntryLoadBits,
caller_uid: u32,
check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
- ) -> Result<KeyEntry> {
+ ) -> Result<(KeyIdGuard, KeyEntry)> {
+ // KEY ID LOCK 1/2
+ // If we got a key descriptor with a key id we can get the lock right away.
+ // Otherwise we have to defer it until we know the key id.
+ let key_id_guard = match key.domain {
+ Domain::KEY_ID => Some(KEY_ID_LOCK.get(key.nspace)),
+ _ => None,
+ };
+
let tx = self
.conn
- .transaction_with_behavior(TransactionBehavior::Deferred)
+ .unchecked_transaction()
.context("In load_key_entry: Failed to initialize transaction.")?;
// Load the key_id and complete the access control tuple.
@@ -595,21 +686,71 @@
// So do not touch that '?' at the end.
check_permission(&access_key_descriptor, access_vector).context("In load_key_entry.")?;
- let (sec_level, km_blob, cert_blob, cert_chain_blob) =
- Self::load_blob_components(key_id, load_bits, &tx).context("In load_key_entry.")?;
+ // KEY ID LOCK 2/2
+ // If we did not get a key id lock by now, it was because we got a key descriptor
+ // without a key id. At this point we got the key id, so we can try and get a lock.
+ // However, we cannot block here, because we are in the middle of the transaction.
+ // So first we try to get the lock non blocking. If that fails, we roll back the
+ // transaction and block until we get the lock. After we successfully got the lock,
+ // we start a new transaction and load the access tuple again.
+ //
+ // We don't need to perform access control again, because we already established
+ // that the caller had access to the given key. But we need to make sure that the
+ // key id still exists. So we have to load the key entry by key id this time.
+ let (key_id_guard, tx) = match key_id_guard {
+ None => match KEY_ID_LOCK.try_get(key_id) {
+ None => {
+ // Roll back the transaction.
+ tx.rollback().context("In load_key_entry: Failed to roll back transaction.")?;
- let parameters = Self::load_key_parameters(key_id, &tx).context("In load_key_entry.")?;
+ // Block until we have a key id lock.
+ let key_id_guard = KEY_ID_LOCK.get(key_id);
+
+ // Create a new transaction.
+ let tx = self.conn.unchecked_transaction().context(
+ "In load_key_entry: Failed to initialize transaction. (deferred key lock)",
+ )?;
+
+ Self::load_access_tuple(
+ &tx,
+ // This time we have to load the key by the retrieved key id, because the
+ // alias may have been rebound after we rolled back the transaction.
+ KeyDescriptor {
+ domain: Domain::KEY_ID,
+ nspace: key_id,
+ ..Default::default()
+ },
+ caller_uid,
+ )
+ .context("In load_key_entry. (deferred key lock)")?;
+ (key_id_guard, tx)
+ }
+ Some(l) => (l, tx),
+ },
+ Some(key_id_guard) => (key_id_guard, tx),
+ };
+
+ let (sec_level, km_blob, cert_blob, cert_chain_blob) =
+ Self::load_blob_components(key_id_guard.id(), load_bits, &tx)
+ .context("In load_key_entry.")?;
+
+ let parameters =
+ Self::load_key_parameters(key_id_guard.id(), &tx).context("In load_key_entry.")?;
tx.commit().context("In load_key_entry: Failed to commit transaction.")?;
- Ok(KeyEntry {
- id: key_id,
- km_blob,
- cert: cert_blob,
- cert_chain: cert_chain_blob,
- sec_level,
- parameters,
- })
+ let key_id = key_id_guard.id();
+ Ok((
+ key_id_guard,
+ KeyEntry {
+ id: key_id,
+ km_blob,
+ cert: cert_blob,
+ cert_chain: cert_chain_blob,
+ sec_level,
+ parameters,
+ },
+ ))
}
/// Adds a grant to the grant table.
@@ -634,10 +775,10 @@
// Load the key_id and complete the access control tuple.
// We ignore the access vector here because grants cannot be granted.
// The access vector returned here expresses the permissions the
- // grantee has if key.domain == Domain::Grant. But this vector
+ // grantee has if key.domain == Domain::GRANT. But this vector
// cannot include the grant permission by design, so there is no way the
// subsequent permission check can pass.
- // We could check key.domain == Domain::Grant and fail early.
+ // We could check key.domain == Domain::GRANT and fail early.
// But even if we load the access tuple by grant here, the permission
// check denies the attempt to create a grant by grant descriptor.
let (key_id, access_key_descriptor, _) =
@@ -681,7 +822,7 @@
};
tx.commit().context("In grant: failed to commit transaction.")?;
- Ok(KeyDescriptor { domain: Domain::Grant, namespace_: grant_id, alias: None, blob: None })
+ Ok(KeyDescriptor { domain: Domain::GRANT, nspace: grant_id, alias: None, blob: None })
}
/// This function checks permissions like `grant` and `load_key_entry`
@@ -790,6 +931,9 @@
use crate::permission::{KeyPerm, KeyPermSet};
use rusqlite::NO_PARAMS;
use std::cell::RefCell;
+ use std::sync::atomic::{AtomicU8, Ordering};
+ use std::sync::Arc;
+ use std::thread;
static PERSISTENT_TEST_SQL: &str = "/data/local/tmp/persistent.sqlite";
static PERBOOT_TEST_SQL: &str = "/data/local/tmp/perboot.sqlite";
@@ -849,7 +993,7 @@
fn test_no_persistence_for_tests() -> Result<()> {
let db = new_test_db()?;
- db.create_key_entry(Domain::App, 100)?;
+ db.create_key_entry(Domain::APP, 100)?;
let entries = get_keyentry(&db)?;
assert_eq!(entries.len(), 1);
let db = new_test_db()?;
@@ -865,7 +1009,7 @@
let _file_guard_perboot = TempFile { filename: PERBOOT_TEST_SQL };
let db = new_test_db_with_persistent_file()?;
- db.create_key_entry(Domain::App, 100)?;
+ db.create_key_entry(Domain::APP, 100)?;
let entries = get_keyentry(&db)?;
assert_eq!(entries.len(), 1);
let db = new_test_db_with_persistent_file()?;
@@ -877,32 +1021,32 @@
#[test]
fn test_create_key_entry() -> Result<()> {
- fn extractor(ke: &KeyEntryRow) -> (DomainType, i64, Option<&str>) {
+ fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>) {
(ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
}
let db = new_test_db()?;
- db.create_key_entry(Domain::App, 100)?;
- db.create_key_entry(Domain::SELinux, 101)?;
+ db.create_key_entry(Domain::APP, 100)?;
+ db.create_key_entry(Domain::SELINUX, 101)?;
let entries = get_keyentry(&db)?;
assert_eq!(entries.len(), 2);
- assert_eq!(extractor(&entries[0]), (Domain::App, 100, None));
- assert_eq!(extractor(&entries[1]), (Domain::SELinux, 101, None));
+ assert_eq!(extractor(&entries[0]), (Domain::APP, 100, None));
+ assert_eq!(extractor(&entries[1]), (Domain::SELINUX, 101, None));
// Test that we must pass in a valid Domain.
check_result_is_error_containing_string(
- db.create_key_entry(Domain::Grant, 102),
- "Domain 1 must be either App or SELinux.",
+ db.create_key_entry(Domain::GRANT, 102),
+ "Domain Domain(1) must be either App or SELinux.",
);
check_result_is_error_containing_string(
- db.create_key_entry(Domain::Blob, 103),
- "Domain 3 must be either App or SELinux.",
+ db.create_key_entry(Domain::BLOB, 103),
+ "Domain Domain(3) must be either App or SELinux.",
);
check_result_is_error_containing_string(
- db.create_key_entry(Domain::KeyId, 104),
- "Domain 4 must be either App or SELinux.",
+ db.create_key_entry(Domain::KEY_ID, 104),
+ "Domain Domain(4) must be either App or SELinux.",
);
Ok(())
@@ -910,56 +1054,56 @@
#[test]
fn test_rebind_alias() -> Result<()> {
- fn extractor(ke: &KeyEntryRow) -> (Option<DomainType>, Option<i64>, Option<&str>) {
+ fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>) {
(ke.domain, ke.namespace, ke.alias.as_deref())
}
let mut db = new_test_db()?;
- db.create_key_entry(Domain::App, 42)?;
- db.create_key_entry(Domain::App, 42)?;
+ db.create_key_entry(Domain::APP, 42)?;
+ db.create_key_entry(Domain::APP, 42)?;
let entries = get_keyentry(&db)?;
assert_eq!(entries.len(), 2);
- assert_eq!(extractor(&entries[0]), (Some(Domain::App), Some(42), None));
- assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), None));
+ assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), None));
+ assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
// Test that the first call to rebind_alias sets the alias.
- db.rebind_alias(entries[0].id, "foo", Domain::App, 42)?;
+ db.rebind_alias(&KEY_ID_LOCK.get(entries[0].id), "foo", Domain::APP, 42)?;
let entries = get_keyentry(&db)?;
assert_eq!(entries.len(), 2);
- assert_eq!(extractor(&entries[0]), (Some(Domain::App), Some(42), Some("foo")));
- assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), None));
+ assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), Some("foo")));
+ assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
// Test that the second call to rebind_alias also empties the old one.
- db.rebind_alias(entries[1].id, "foo", Domain::App, 42)?;
+ db.rebind_alias(&KEY_ID_LOCK.get(entries[1].id), "foo", Domain::APP, 42)?;
let entries = get_keyentry(&db)?;
assert_eq!(entries.len(), 2);
assert_eq!(extractor(&entries[0]), (None, None, None));
- assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), Some("foo")));
+ assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
// Test that we must pass in a valid Domain.
check_result_is_error_containing_string(
- db.rebind_alias(0, "foo", Domain::Grant, 42),
- "Domain 1 must be either App or SELinux.",
+ db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::GRANT, 42),
+ "Domain Domain(1) must be either App or SELinux.",
);
check_result_is_error_containing_string(
- db.rebind_alias(0, "foo", Domain::Blob, 42),
- "Domain 3 must be either App or SELinux.",
+ db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::BLOB, 42),
+ "Domain Domain(3) must be either App or SELinux.",
);
check_result_is_error_containing_string(
- db.rebind_alias(0, "foo", Domain::KeyId, 42),
- "Domain 4 must be either App or SELinux.",
+ db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::KEY_ID, 42),
+ "Domain Domain(4) must be either App or SELinux.",
);
// Test that we correctly handle setting an alias for something that does not exist.
check_result_is_error_containing_string(
- db.rebind_alias(0, "foo", Domain::SELinux, 42),
+ db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::SELINUX, 42),
"Expected to update a single entry but instead updated 0",
);
// Test that we correctly abort the transaction in this case.
let entries = get_keyentry(&db)?;
assert_eq!(entries.len(), 2);
assert_eq!(extractor(&entries[0]), (None, None, None));
- assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), Some("foo")));
+ assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Ok(())
}
@@ -977,8 +1121,8 @@
NO_PARAMS,
)?;
let app_key = KeyDescriptor {
- domain: super::Domain::App,
- namespace_: 0,
+ domain: super::Domain::APP,
+ nspace: 0,
alias: Some("key".to_string()),
blob: None,
};
@@ -996,9 +1140,9 @@
assert_eq!(
*k,
KeyDescriptor {
- domain: super::Domain::App,
+ domain: super::Domain::APP,
// namespace must be set to the caller_uid.
- namespace_: CALLER_UID as i64,
+ nspace: CALLER_UID as i64,
alias: Some("key".to_string()),
blob: None,
}
@@ -1009,17 +1153,17 @@
assert_eq!(
app_granted_key,
KeyDescriptor {
- domain: super::Domain::Grant,
+ domain: super::Domain::GRANT,
// The grantid is next_random due to the mock random number generator.
- namespace_: next_random,
+ nspace: next_random,
alias: None,
blob: None,
}
);
let selinux_key = KeyDescriptor {
- domain: super::Domain::SELinux,
- namespace_: SELINUX_NAMESPACE,
+ domain: super::Domain::SELINUX,
+ nspace: SELINUX_NAMESPACE,
alias: Some("yek".to_string()),
blob: None,
};
@@ -1030,10 +1174,10 @@
assert_eq!(
*k,
KeyDescriptor {
- domain: super::Domain::SELinux,
+ domain: super::Domain::SELINUX,
// namespace must be the supplied SELinux
// namespace.
- namespace_: SELINUX_NAMESPACE,
+ nspace: SELINUX_NAMESPACE,
alias: Some("yek".to_string()),
blob: None,
}
@@ -1044,9 +1188,9 @@
assert_eq!(
selinux_granted_key,
KeyDescriptor {
- domain: super::Domain::Grant,
+ domain: super::Domain::GRANT,
// The grantid is next_random + 1 due to the mock random number generator.
- namespace_: next_random + 1,
+ nspace: next_random + 1,
alias: None,
blob: None,
}
@@ -1059,10 +1203,10 @@
assert_eq!(
*k,
KeyDescriptor {
- domain: super::Domain::SELinux,
+ domain: super::Domain::SELINUX,
// namespace must be the supplied SELinux
// namespace.
- namespace_: SELINUX_NAMESPACE,
+ nspace: SELINUX_NAMESPACE,
alias: Some("yek".to_string()),
blob: None,
}
@@ -1073,9 +1217,9 @@
assert_eq!(
selinux_granted_key,
KeyDescriptor {
- domain: super::Domain::Grant,
+ domain: super::Domain::GRANT,
// Same grant id as before. The entry was only updated.
- namespace_: next_random + 1,
+ nspace: next_random + 1,
alias: None,
blob: None,
}
@@ -1120,9 +1264,24 @@
#[test]
fn test_insert_blob() -> Result<()> {
let mut db = new_test_db()?;
- db.insert_blob(1, SubComponentType::KM_BLOB, TEST_KM_BLOB, 1)?;
- db.insert_blob(1, SubComponentType::CERT, TEST_CERT_BLOB, 2)?;
- db.insert_blob(1, SubComponentType::CERT_CHAIN, TEST_CERT_CHAIN_BLOB, 3)?;
+ db.insert_blob(
+ &KEY_ID_LOCK.get(1),
+ SubComponentType::KM_BLOB,
+ TEST_KM_BLOB,
+ SecurityLevel::SOFTWARE,
+ )?;
+ db.insert_blob(
+ &KEY_ID_LOCK.get(1),
+ SubComponentType::CERT,
+ TEST_CERT_BLOB,
+ SecurityLevel::TRUSTED_ENVIRONMENT,
+ )?;
+ db.insert_blob(
+ &KEY_ID_LOCK.get(1),
+ SubComponentType::CERT_CHAIN,
+ TEST_CERT_CHAIN_BLOB,
+ SecurityLevel::STRONGBOX,
+ )?;
let mut stmt = db.conn.prepare(
"SELECT subcomponent_type, keyentryid, blob, sec_level FROM persistent.blobentry
@@ -1133,11 +1292,11 @@
Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
})?;
let r = rows.next().unwrap().unwrap();
- assert_eq!(r, (SubComponentType::KM_BLOB, 1, TEST_KM_BLOB.to_vec(), 1));
+ assert_eq!(r, (SubComponentType::KM_BLOB, 1, TEST_KM_BLOB.to_vec(), 0));
let r = rows.next().unwrap().unwrap();
- assert_eq!(r, (SubComponentType::CERT, 1, TEST_CERT_BLOB.to_vec(), 2));
+ assert_eq!(r, (SubComponentType::CERT, 1, TEST_CERT_BLOB.to_vec(), 1));
let r = rows.next().unwrap().unwrap();
- assert_eq!(r, (SubComponentType::CERT_CHAIN, 1, TEST_CERT_CHAIN_BLOB.to_vec(), 3));
+ assert_eq!(r, (SubComponentType::CERT_CHAIN, 1, TEST_CERT_CHAIN_BLOB.to_vec(), 2));
Ok(())
}
@@ -1147,12 +1306,13 @@
#[test]
fn test_insert_and_load_full_keyentry_domain_app() -> Result<()> {
let mut db = new_test_db()?;
- let key_id = make_test_key_entry(&mut db, Domain::App, 1, TEST_ALIAS)
- .context("test_insert_and_load_full_keyentry_domain_app")?;
- let key_entry = db.load_key_entry(
+ let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
+ .context("test_insert_and_load_full_keyentry_domain_app")?
+ .0;
+ let (_key_guard, key_entry) = db.load_key_entry(
KeyDescriptor {
- domain: Domain::App,
- namespace_: 0,
+ domain: Domain::APP,
+ nspace: 0,
alias: Some(TEST_ALIAS.to_string()),
blob: None,
},
@@ -1167,8 +1327,8 @@
km_blob: Some(TEST_KM_BLOB.to_vec()),
cert: Some(TEST_CERT_BLOB.to_vec()),
cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
- sec_level: 1,
- parameters: make_test_params()
+ sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+ parameters: make_test_params(),
}
);
Ok(())
@@ -1177,12 +1337,13 @@
#[test]
fn test_insert_and_load_full_keyentry_domain_selinux() -> Result<()> {
let mut db = new_test_db()?;
- let key_id = make_test_key_entry(&mut db, Domain::SELinux, 1, TEST_ALIAS)
- .context("test_insert_and_load_full_keyentry_domain_selinux")?;
- let key_entry = db.load_key_entry(
+ let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
+ .context("test_insert_and_load_full_keyentry_domain_selinux")?
+ .0;
+ let (_key_guard, key_entry) = db.load_key_entry(
KeyDescriptor {
- domain: Domain::SELinux,
- namespace_: 1,
+ domain: Domain::SELINUX,
+ nspace: 1,
alias: Some(TEST_ALIAS.to_string()),
blob: None,
},
@@ -1197,8 +1358,8 @@
km_blob: Some(TEST_KM_BLOB.to_vec()),
cert: Some(TEST_CERT_BLOB.to_vec()),
cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
- sec_level: 1,
- parameters: make_test_params()
+ sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+ parameters: make_test_params(),
}
);
Ok(())
@@ -1207,10 +1368,11 @@
#[test]
fn test_insert_and_load_full_keyentry_domain_key_id() -> Result<()> {
let mut db = new_test_db()?;
- let key_id = make_test_key_entry(&mut db, Domain::SELinux, 1, TEST_ALIAS)
- .context("test_insert_and_load_full_keyentry_domain_key_id")?;
- let key_entry = db.load_key_entry(
- KeyDescriptor { domain: Domain::KeyId, namespace_: key_id, alias: None, blob: None },
+ let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
+ .context("test_insert_and_load_full_keyentry_domain_key_id")?
+ .0;
+ let (_key_guard, key_entry) = db.load_key_entry(
+ KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
KeyEntryLoadBits::BOTH,
1,
|_k, _av| Ok(()),
@@ -1222,8 +1384,8 @@
km_blob: Some(TEST_KM_BLOB.to_vec()),
cert: Some(TEST_CERT_BLOB.to_vec()),
cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
- sec_level: 1,
- parameters: make_test_params()
+ sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+ parameters: make_test_params(),
}
);
@@ -1233,13 +1395,14 @@
#[test]
fn test_insert_and_load_full_keyentry_from_grant() -> Result<()> {
let mut db = new_test_db()?;
- let key_id = make_test_key_entry(&mut db, Domain::App, 1, TEST_ALIAS)
- .context("test_insert_and_load_full_keyentry_from_grant")?;
+ let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
+ .context("test_insert_and_load_full_keyentry_from_grant")?
+ .0;
let granted_key = db.grant(
KeyDescriptor {
- domain: Domain::App,
- namespace_: 0,
+ domain: Domain::APP,
+ nspace: 0,
alias: Some(TEST_ALIAS.to_string()),
blob: None,
},
@@ -1251,11 +1414,12 @@
debug_dump_grant_table(&mut db)?;
- let key_entry = db.load_key_entry(granted_key, KeyEntryLoadBits::BOTH, 2, |k, av| {
- assert_eq!(Domain::Grant, k.domain);
- assert!(av.unwrap().includes(KeyPerm::use_()));
- Ok(())
- })?;
+ let (_key_guard, key_entry) =
+ db.load_key_entry(granted_key, KeyEntryLoadBits::BOTH, 2, |k, av| {
+ assert_eq!(Domain::GRANT, k.domain);
+ assert!(av.unwrap().includes(KeyPerm::use_()));
+ Ok(())
+ })?;
assert_eq!(
key_entry,
@@ -1264,13 +1428,106 @@
km_blob: Some(TEST_KM_BLOB.to_vec()),
cert: Some(TEST_CERT_BLOB.to_vec()),
cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
- sec_level: 1,
- parameters: make_test_params()
+ sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+ parameters: make_test_params(),
}
);
Ok(())
}
+ static KEY_LOCK_TEST_ALIAS: &str = "my super duper locked key";
+
+ static KEY_LOCK_TEST_SQL: &str = "/data/local/tmp/persistent_key_lock.sqlite";
+ static KEY_LOCK_PERBOOT_TEST_SQL: &str = "/data/local/tmp/perboot_key_lock.sqlite";
+
+ fn new_test_db_with_persistent_file_key_lock() -> Result<KeystoreDB> {
+ let conn = KeystoreDB::make_connection(KEY_LOCK_TEST_SQL, KEY_LOCK_PERBOOT_TEST_SQL)?;
+
+ KeystoreDB::init_tables(&conn).context("Failed to initialize tables.")?;
+ Ok(KeystoreDB { conn })
+ }
+
+ #[test]
+ fn test_insert_and_load_full_keyentry_domain_app_concurrently() -> Result<()> {
+ let handle = {
+ let _file_guard_persistent = Arc::new(TempFile { filename: KEY_LOCK_TEST_SQL });
+ let _file_guard_perboot = Arc::new(TempFile { filename: KEY_LOCK_PERBOOT_TEST_SQL });
+ let mut db = new_test_db_with_persistent_file_key_lock()?;
+ let key_id = make_test_key_entry(&mut db, Domain::APP, 33, KEY_LOCK_TEST_ALIAS)
+ .context("test_insert_and_load_full_keyentry_domain_app")?
+ .0;
+ let (_key_guard, key_entry) = db.load_key_entry(
+ KeyDescriptor {
+ domain: Domain::APP,
+ nspace: 0,
+ alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
+ blob: None,
+ },
+ KeyEntryLoadBits::BOTH,
+ 33,
+ |_k, _av| Ok(()),
+ )?;
+ assert_eq!(
+ key_entry,
+ KeyEntry {
+ id: key_id,
+ km_blob: Some(TEST_KM_BLOB.to_vec()),
+ cert: Some(TEST_CERT_BLOB.to_vec()),
+ cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
+ sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+ parameters: make_test_params(),
+ }
+ );
+ let state = Arc::new(AtomicU8::new(1));
+ let state2 = state.clone();
+
+ // Spawning a second thread that attempts to acquire the key id lock
+ // for the same key as the primary thread. The primary thread then
+ // waits, thereby forcing the secondary thread into the second stage
+ // of acquiring the lock (see KEY ID LOCK 2/2 above).
+ // The test succeeds if the secondary thread observes the transition
+ // of `state` from 1 to 2, despite having a whole second to overtake
+ // the primary thread.
+ let handle = thread::spawn(move || {
+ let _file_a = _file_guard_persistent;
+ let _file_b = _file_guard_perboot;
+ let mut db = new_test_db_with_persistent_file_key_lock().unwrap();
+ assert!(db
+ .load_key_entry(
+ KeyDescriptor {
+ domain: Domain::APP,
+ nspace: 0,
+ alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
+ blob: None,
+ },
+ KeyEntryLoadBits::BOTH,
+ 33,
+ |_k, _av| Ok(()),
+ )
+ .is_ok());
+ // We should only see a 2 here because we can only return
+ // from load_key_entry when the `_key_guard` expires,
+ // which happens at the end of the scope.
+ assert_eq!(2, state2.load(Ordering::Relaxed));
+ });
+
+ thread::sleep(std::time::Duration::from_millis(1000));
+
+ assert_eq!(Ok(1), state.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed));
+
+ // Return the handle from this scope so we can join with the
+ // secondary thread after the key id lock has expired.
+ handle
+ // This is where the `_key_guard` goes out of scope,
+ // which is the reason for concurrent load_key_entry on the same key
+ // to unblock.
+ };
+ // Join with the secondary thread and unwrap, to propagate failing asserts to the
+ // main test thread. We will not see failing asserts in secondary threads otherwise.
+ handle.join().unwrap();
+ Ok(())
+ }
+
// Helpers
// Checks that the given result is an error containing the given string.
@@ -1292,7 +1549,7 @@
struct KeyEntryRow {
id: i64,
creation_date: String,
- domain: Option<DomainType>,
+ domain: Option<Domain>,
namespace: Option<i64>,
alias: Option<String>,
}
@@ -1304,7 +1561,10 @@
Ok(KeyEntryRow {
id: row.get(0)?,
creation_date: row.get(1)?,
- domain: row.get(2)?,
+ domain: match row.get(2)? {
+ Some(i) => Some(Domain(i)),
+ None => None,
+ },
namespace: row.get(3)?,
alias: row.get(4)?,
})
@@ -1537,16 +1797,31 @@
fn make_test_key_entry(
db: &mut KeystoreDB,
- domain: DomainType,
+ domain: Domain,
namespace: i64,
alias: &str,
- ) -> Result<i64> {
+ ) -> Result<KeyIdGuard> {
let key_id = db.create_key_entry(domain, namespace)?;
- db.insert_blob(key_id, SubComponentType::KM_BLOB, TEST_KM_BLOB, 1)?;
- db.insert_blob(key_id, SubComponentType::CERT, TEST_CERT_BLOB, 1)?;
- db.insert_blob(key_id, SubComponentType::CERT_CHAIN, TEST_CERT_CHAIN_BLOB, 1)?;
- db.insert_keyparameter(key_id, &make_test_params())?;
- db.rebind_alias(key_id, alias, domain, namespace)?;
+ db.insert_blob(
+ &key_id,
+ SubComponentType::KM_BLOB,
+ TEST_KM_BLOB,
+ SecurityLevel::TRUSTED_ENVIRONMENT,
+ )?;
+ db.insert_blob(
+ &key_id,
+ SubComponentType::CERT,
+ TEST_CERT_BLOB,
+ SecurityLevel::TRUSTED_ENVIRONMENT,
+ )?;
+ db.insert_blob(
+ &key_id,
+ SubComponentType::CERT_CHAIN,
+ TEST_CERT_CHAIN_BLOB,
+ SecurityLevel::TRUSTED_ENVIRONMENT,
+ )?;
+ db.insert_keyparameter(&key_id, &make_test_params())?;
+ db.rebind_alias(&key_id, alias, domain, namespace)?;
Ok(key_id)
}
diff --git a/keystore2/src/error.rs b/keystore2/src/error.rs
index 0326610..63ebe62 100644
--- a/keystore2/src/error.rs
+++ b/keystore2/src/error.rs
@@ -25,22 +25,19 @@
//! This crate provides the convenience method `map_or_log_err` to convert `anyhow::Error`
//! into this wire type. In addition to handling the conversion of `Error`
//! to the `Result` wire type it handles any other error by mapping it to
-//! `ResponseCode::SystemError` and logs any error condition.
+//! `ResponseCode::SYSTEM_ERROR` and logs any error condition.
//!
//! Keystore functions should use `anyhow::Result` to return error conditions, and
//! context should be added every time an error is forwarded.
use std::cmp::PartialEq;
-pub use android_hardware_keymint::aidl::android::hardware::keymint::ErrorCode as Ec;
-pub use android_security_keystore2::aidl::android::security::keystore2::ResponseCode as Rc;
-
-use android_hardware_keymint::aidl::android::hardware::keymint::ErrorCode::ErrorCode;
-use android_security_keystore2::aidl::android::security::keystore2::ResponseCode::ResponseCode;
+pub use android_hardware_keymint::aidl::android::hardware::keymint::ErrorCode::ErrorCode;
+pub use android_system_keystore2::aidl::android::system::keystore2::ResponseCode::ResponseCode;
use keystore2_selinux as selinux;
-use android_security_keystore2::binder::{
+use android_system_keystore2::binder::{
ExceptionCode, Result as BinderResult, Status as BinderStatus,
};
@@ -60,14 +57,14 @@
}
impl Error {
- /// Short hand for `Error::Rc(ResponseCode::SystemError)`
+ /// Short hand for `Error::Rc(ResponseCode::SYSTEM_ERROR)`
pub fn sys() -> Self {
- Error::Rc(Rc::SystemError)
+ Error::Rc(ResponseCode::SYSTEM_ERROR)
}
- /// Short hand for `Error::Rc(ResponseCode::PermissionDenied`
+ /// Short hand for `Error::Rc(ResponseCode::PERMISSION_DENIED`
pub fn perm() -> Self {
- Error::Rc(Rc::PermissionDenied)
+ Error::Rc(ResponseCode::PERMISSION_DENIED)
}
}
@@ -83,7 +80,7 @@
let se = s.service_specific_error();
if se < 0 {
// Negative service specific errors are KM error codes.
- Error::Km(s.service_specific_error())
+ Error::Km(ErrorCode(s.service_specific_error()))
} else {
// Non negative error codes cannot be KM error codes.
// So we create an `Error::Binder` variant to preserve
@@ -102,16 +99,16 @@
}
/// This function should be used by Keystore service calls to translate error conditions
-/// into `android.security.keystore2.Result` which is imported here as `aidl::Result`
+/// into `android.system.keystore2.Result` which is imported here as `aidl::Result`
/// and newtyped as AidlResult.
/// All error conditions get logged by this function.
/// All `Error::Rc(x)` variants get mapped onto `aidl::Result{x, 0}`.
/// All `Error::Km(x)` variants get mapped onto
/// `aidl::Result{aidl::ResponseCode::KeymintErrorCode, x}`.
-/// `selinux::Error::perm()` is mapped on `aidl::Result{aidl::ResponseCode::PermissionDenied, 0}`.
+/// `selinux::Error::perm()` is mapped on `aidl::Result{aidl::ResponseCode::PERMISSION_DENIED, 0}`.
///
/// All non `Error` error conditions get mapped onto
-/// `aidl::Result{aidl::ResponseCode::SystemError}`.
+/// `aidl::Result{aidl::ResponseCode::SYSTEM_ERROR}`.
///
/// `handle_ok` will be called if `result` is `Ok(value)` where `value` will be passed
/// as argument to `handle_ok`. `handle_ok` must generate an `AidlResult`, typically
@@ -125,7 +122,7 @@
/// if (good_but_auth_required) {
/// Ok(aidl::ResponseCode::OpAuthRequired)
/// } else {
-/// Err(anyhow!(Error::Rc(aidl::ResponseCode::KeyNotFound)))
+/// Err(anyhow!(Error::Rc(aidl::ResponseCode::KEY_NOT_FOUND)))
/// }
/// }
///
@@ -140,15 +137,15 @@
log::error!("{:?}", e);
let root_cause = e.root_cause();
let rc = match root_cause.downcast_ref::<Error>() {
- Some(Error::Rc(rcode)) => *rcode,
- Some(Error::Km(ec)) => *ec,
+ Some(Error::Rc(rcode)) => rcode.0,
+ Some(Error::Km(ec)) => ec.0,
// If an Error::Binder reaches this stage we report a system error.
// The exception code and possible service specific error will be
// printed in the error log above.
- Some(Error::Binder(_, _)) => Rc::SystemError,
+ Some(Error::Binder(_, _)) => ResponseCode::SYSTEM_ERROR.0,
None => match root_cause.downcast_ref::<selinux::Error>() {
- Some(selinux::Error::PermissionDenied) => Rc::PermissionDenied,
- _ => Rc::SystemError,
+ Some(selinux::Error::PermissionDenied) => ResponseCode::PERMISSION_DENIED.0,
+ _ => ResponseCode::SYSTEM_ERROR.0,
},
};
Err(BinderStatus::new_service_specific_error(rc, None))
@@ -161,7 +158,7 @@
pub mod tests {
use super::*;
- use android_security_keystore2::binder::{
+ use android_system_keystore2::binder::{
ExceptionCode, Result as BinderResult, Status as BinderStatus,
};
use anyhow::{anyhow, Context};
@@ -229,27 +226,27 @@
);
// All Error::Rc(x) get mapped on a service specific error
// code of x.
- for rc in Rc::Ok..Rc::BackendBusy {
+ for rc in ResponseCode::LOCKED.0..ResponseCode::BACKEND_BUSY.0 {
assert_eq!(
Result::<(), i32>::Err(rc),
- map_or_log_err(nested_rc(rc), |_| Err(BinderStatus::ok()))
+ map_or_log_err(nested_rc(ResponseCode(rc)), |_| Err(BinderStatus::ok()))
.map_err(|s| s.service_specific_error())
);
}
// All Keystore Error::Km(x) get mapped on a service
// specific error of x.
- for ec in Ec::UNKNOWN_ERROR..Ec::ROOT_OF_TRUST_ALREADY_SET {
+ for ec in ErrorCode::UNKNOWN_ERROR.0..ErrorCode::ROOT_OF_TRUST_ALREADY_SET.0 {
assert_eq!(
Result::<(), i32>::Err(ec),
- map_or_log_err(nested_ec(ec), |_| Err(BinderStatus::ok()))
+ map_or_log_err(nested_ec(ErrorCode(ec)), |_| Err(BinderStatus::ok()))
.map_err(|s| s.service_specific_error())
);
}
// All Keymint errors x received through a Binder Result get mapped on
// a service specific error of x.
- for ec in Ec::UNKNOWN_ERROR..Ec::ROOT_OF_TRUST_ALREADY_SET {
+ for ec in ErrorCode::UNKNOWN_ERROR.0..ErrorCode::ROOT_OF_TRUST_ALREADY_SET.0 {
assert_eq!(
Result::<(), i32>::Err(ec),
map_or_log_err(
@@ -266,44 +263,47 @@
// service specific error.
let sse = map_km_error(binder_sse_error(1));
assert_eq!(Err(Error::Binder(ExceptionCode::SERVICE_SPECIFIC, 1)), sse);
- // map_or_log_err then maps it on a service specific error of Rc::SystemError.
+ // map_or_log_err then maps it on a service specific error of ResponseCode::SYSTEM_ERROR.
assert_eq!(
- Result::<(), i32>::Err(Rc::SystemError),
+ Result::<(), ResponseCode>::Err(ResponseCode::SYSTEM_ERROR),
map_or_log_err(sse.context("Non negative service specific error."), |_| Err(
BinderStatus::ok()
))
- .map_err(|s| s.service_specific_error())
+ .map_err(|s| ResponseCode(s.service_specific_error()))
);
// map_km_error creates a Error::Binder variant storing the given exception code.
let binder_exception = map_km_error(binder_exception(ExceptionCode::TRANSACTION_FAILED));
assert_eq!(Err(Error::Binder(ExceptionCode::TRANSACTION_FAILED, 0)), binder_exception);
- // map_or_log_err then maps it on a service specific error of Rc::SystemError.
+ // map_or_log_err then maps it on a service specific error of ResponseCode::SYSTEM_ERROR.
assert_eq!(
- Result::<(), i32>::Err(Rc::SystemError),
+ Result::<(), ResponseCode>::Err(ResponseCode::SYSTEM_ERROR),
map_or_log_err(binder_exception.context("Binder Exception."), |_| Err(
BinderStatus::ok()
))
- .map_err(|s| s.service_specific_error())
+ .map_err(|s| ResponseCode(s.service_specific_error()))
);
- // selinux::Error::Perm() needs to be mapped to Rc::PermissionDenied
+ // selinux::Error::Perm() needs to be mapped to ResponseCode::PERMISSION_DENIED
assert_eq!(
- Result::<(), i32>::Err(Rc::PermissionDenied),
+ Result::<(), ResponseCode>::Err(ResponseCode::PERMISSION_DENIED),
map_or_log_err(nested_selinux_perm(), |_| Err(BinderStatus::ok()))
- .map_err(|s| s.service_specific_error())
+ .map_err(|s| ResponseCode(s.service_specific_error()))
);
// All other errors get mapped on System Error.
assert_eq!(
- Result::<(), i32>::Err(Rc::SystemError),
+ Result::<(), ResponseCode>::Err(ResponseCode::SYSTEM_ERROR),
map_or_log_err(nested_other_error(), |_| Err(BinderStatus::ok()))
- .map_err(|s| s.service_specific_error())
+ .map_err(|s| ResponseCode(s.service_specific_error()))
);
// Result::Ok variants get passed to the ok handler.
- assert_eq!(Ok(Rc::OpAuthNeeded), map_or_log_err(nested_ok(Rc::OpAuthNeeded), Ok));
- assert_eq!(Ok(Rc::Ok), map_or_log_err(nested_ok(Rc::Ok), Ok));
+ assert_eq!(Ok(ResponseCode::LOCKED), map_or_log_err(nested_ok(ResponseCode::LOCKED), Ok));
+ assert_eq!(
+ Ok(ResponseCode::SYSTEM_ERROR),
+ map_or_log_err(nested_ok(ResponseCode::SYSTEM_ERROR), Ok)
+ );
Ok(())
}
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
new file mode 100644
index 0000000..0654b29
--- /dev/null
+++ b/keystore2/src/globals.rs
@@ -0,0 +1,29 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This module holds global state of Keystore such as the thread local
+//! database connections and connections to services that Keystore needs
+//! to talk to.
+
+use crate::database::KeystoreDB;
+use std::cell::RefCell;
+
+thread_local! {
+ /// Database connections are not thread safe, but connecting to the
+ /// same database multiple times is safe as long as each connection is
+ /// used by only one thread. So we store one database connection per
+ /// thread in this thread local key.
+ pub static DB: RefCell<KeystoreDB> =
+ RefCell::new(KeystoreDB::new().expect("Failed to open database."));
+}
diff --git a/keystore2/src/key_parameter.rs b/keystore2/src/key_parameter.rs
index f08031e..5698c96 100644
--- a/keystore2/src/key_parameter.rs
+++ b/keystore2/src/key_parameter.rs
@@ -17,18 +17,15 @@
//! and the methods to work with KeyParameter.
use crate::error::Error as KeystoreError;
-use crate::error::Rc;
+use crate::error::ResponseCode;
+
pub use android_hardware_keymint::aidl::android::hardware::keymint::{
- Algorithm, Algorithm::Algorithm as AlgorithmType, BlockMode,
- BlockMode::BlockMode as BlockModeType, Digest, Digest::Digest as DigestType, EcCurve,
- EcCurve::EcCurve as EcCurveType, HardwareAuthenticatorType,
- HardwareAuthenticatorType::HardwareAuthenticatorType as HardwareAuthenticatorTypeType,
- KeyOrigin, KeyOrigin::KeyOrigin as KeyOriginType,
- KeyParameter::KeyParameter as AidlKeyParameter, KeyPurpose,
- KeyPurpose::KeyPurpose as KeyPurposeType, PaddingMode,
- PaddingMode::PaddingMode as PaddingModeType, SecurityLevel,
- SecurityLevel::SecurityLevel as SecurityLevelType, Tag, Tag::Tag as TagType,
+ Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
+ HardwareAuthenticatorType::HardwareAuthenticatorType, KeyOrigin::KeyOrigin,
+ KeyParameter::KeyParameter as KmKeyParameter, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
+ SecurityLevel::SecurityLevel, Tag::Tag,
};
+use android_system_keystore2::aidl::android::system::keystore2::Authorization::Authorization;
use anyhow::{Context, Result};
use rusqlite::types::{FromSql, Null, ToSql, ToSqlOutput};
use rusqlite::{Result as SqlResult, Row};
@@ -37,7 +34,7 @@
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct KeyParameter {
key_parameter_value: KeyParameterValue,
- security_level: SecurityLevelType,
+ security_level: SecurityLevel,
}
/// KeyParameterValue holds a value corresponding to one of the Tags defined in
@@ -47,23 +44,23 @@
/// Associated with Tag:INVALID
Invalid,
/// Set of purposes for which the key may be used
- KeyPurpose(KeyPurposeType),
+ KeyPurpose(KeyPurpose),
/// Cryptographic algorithm with which the key is used
- Algorithm(AlgorithmType),
+ Algorithm(Algorithm),
/// Size of the key , in bits
KeySize(i32),
/// Block cipher mode(s) with which the key may be used
- BlockMode(BlockModeType),
+ BlockMode(BlockMode),
/// Digest algorithms that may be used with the key to perform signing and verification
- Digest(DigestType),
+ Digest(Digest),
/// Padding modes that may be used with the key. Relevant to RSA, AES and 3DES keys.
- PaddingMode(PaddingModeType),
+ PaddingMode(PaddingMode),
/// Can the caller provide a nonce for nonce-requiring operations
CallerNonce,
/// Minimum length of MAC for HMAC keys and AES keys that support GCM mode
MinMacLength(i32),
/// The elliptic curve
- EcCurve(EcCurveType),
+ EcCurve(EcCurve),
/// Value of the public exponent for an RSA key pair
RSAPublicExponent(i64),
/// An attestation certificate for the generated key should contain an application-scoped
@@ -93,7 +90,7 @@
/// No authentication is required to use this key
NoAuthRequired,
/// The types of user authenticators that may be used to authorize this key
- HardwareAuthenticatorType(HardwareAuthenticatorTypeType),
+ HardwareAuthenticatorType(HardwareAuthenticatorType),
/// The time in seconds for which the key is authorized for use, after user authentication
AuthTimeout(i32),
/// The key may be used after authentication timeout if device is still on-body
@@ -114,7 +111,7 @@
/// Specifies the date and time the key was created
CreationDateTime(i64),
/// Specifies where the key was created, if known
- KeyOrigin(KeyOriginType),
+ KeyOrigin(KeyOrigin),
/// The key used by verified boot to validate the operating system booted
RootOfTrust(Vec<u8>),
/// System OS version with which the key may be used
@@ -164,12 +161,12 @@
impl KeyParameter {
/// Create an instance of KeyParameter, given the value and the security level.
- pub fn new(key_parameter_value: KeyParameterValue, security_level: SecurityLevelType) -> Self {
+ pub fn new(key_parameter_value: KeyParameterValue, security_level: SecurityLevel) -> Self {
KeyParameter { key_parameter_value, security_level }
}
/// Returns the tag given the KeyParameter instance.
- pub fn get_tag(&self) -> TagType {
+ pub fn get_tag(&self) -> Tag {
match self.key_parameter_value {
KeyParameterValue::Invalid => Tag::INVALID,
KeyParameterValue::KeyPurpose(_) => Tag::PURPOSE,
@@ -233,9 +230,19 @@
}
/// Returns the security level of a KeyParameter.
- pub fn security_level(&self) -> &SecurityLevelType {
+ pub fn security_level(&self) -> &SecurityLevel {
&self.security_level
}
+
+ /// An authorization is a KeyParameter with an associated security level that is used
+ /// to convey the key characteristics to keystore clients. This function consumes
+ /// an internal KeyParameter representation to produce the Authorization wire type.
+ pub fn into_authorization(self) -> Authorization {
+ Authorization {
+ securityLevel: self.security_level,
+ keyParameter: self.key_parameter_value.convert_to_wire(),
+ }
+ }
}
/// This struct is defined to postpone converting rusqlite column value to the
@@ -264,15 +271,15 @@
fn to_sql(&self) -> SqlResult<ToSqlOutput> {
match self {
KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
- KeyParameterValue::KeyPurpose(k) => Ok(ToSqlOutput::from(*k as u32)),
- KeyParameterValue::Algorithm(a) => Ok(ToSqlOutput::from(*a as u32)),
+ KeyParameterValue::KeyPurpose(k) => Ok(ToSqlOutput::from(k.0 as u32)),
+ KeyParameterValue::Algorithm(a) => Ok(ToSqlOutput::from(a.0 as u32)),
KeyParameterValue::KeySize(k) => Ok(ToSqlOutput::from(*k)),
- KeyParameterValue::BlockMode(b) => Ok(ToSqlOutput::from(*b as u32)),
- KeyParameterValue::Digest(d) => Ok(ToSqlOutput::from(*d as u32)),
- KeyParameterValue::PaddingMode(p) => Ok(ToSqlOutput::from(*p as u32)),
+ KeyParameterValue::BlockMode(b) => Ok(ToSqlOutput::from(b.0 as u32)),
+ KeyParameterValue::Digest(d) => Ok(ToSqlOutput::from(d.0 as u32)),
+ KeyParameterValue::PaddingMode(p) => Ok(ToSqlOutput::from(p.0 as u32)),
KeyParameterValue::CallerNonce => Ok(ToSqlOutput::from(Null)),
KeyParameterValue::MinMacLength(m) => Ok(ToSqlOutput::from(*m)),
- KeyParameterValue::EcCurve(e) => Ok(ToSqlOutput::from(*e as u32)),
+ KeyParameterValue::EcCurve(e) => Ok(ToSqlOutput::from(e.0 as u32)),
KeyParameterValue::RSAPublicExponent(r) => Ok(ToSqlOutput::from(*r as i64)),
KeyParameterValue::IncludeUniqueID => Ok(ToSqlOutput::from(Null)),
KeyParameterValue::BootLoaderOnly => Ok(ToSqlOutput::from(Null)),
@@ -285,7 +292,7 @@
KeyParameterValue::UserID(u) => Ok(ToSqlOutput::from(*u)),
KeyParameterValue::UserSecureID(u) => Ok(ToSqlOutput::from(*u as i64)),
KeyParameterValue::NoAuthRequired => Ok(ToSqlOutput::from(Null)),
- KeyParameterValue::HardwareAuthenticatorType(h) => Ok(ToSqlOutput::from(*h as u32)),
+ KeyParameterValue::HardwareAuthenticatorType(h) => Ok(ToSqlOutput::from(h.0 as u32)),
KeyParameterValue::AuthTimeout(m) => Ok(ToSqlOutput::from(*m)),
KeyParameterValue::AllowWhileOnBody => Ok(ToSqlOutput::from(Null)),
KeyParameterValue::TrustedUserPresenceRequired => Ok(ToSqlOutput::from(Null)),
@@ -294,7 +301,7 @@
KeyParameterValue::ApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
KeyParameterValue::ApplicationData(a) => Ok(ToSqlOutput::from(a.to_vec())),
KeyParameterValue::CreationDateTime(c) => Ok(ToSqlOutput::from(*c as i64)),
- KeyParameterValue::KeyOrigin(k) => Ok(ToSqlOutput::from(*k as u32)),
+ KeyParameterValue::KeyOrigin(k) => Ok(ToSqlOutput::from(k.0 as u32)),
KeyParameterValue::RootOfTrust(r) => Ok(ToSqlOutput::from(r.to_vec())),
KeyParameterValue::OSVersion(o) => Ok(ToSqlOutput::from(*o)),
KeyParameterValue::OSPatchLevel(o) => Ok(ToSqlOutput::from(*o)),
@@ -328,25 +335,25 @@
/// This filtering is enforced at a higher level and here we support conversion for all the
/// variants.
pub fn new_from_sql(
- tag_val: TagType,
+ tag_val: Tag,
data: &SqlField,
- security_level_val: SecurityLevelType,
+ security_level_val: SecurityLevel,
) -> Result<Self> {
let key_param_value = match tag_val {
Tag::INVALID => KeyParameterValue::Invalid,
Tag::PURPOSE => {
- let key_purpose: KeyPurposeType = data
+ let key_purpose: i32 = data
.get()
- .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
.context("Failed to read sql data for tag: PURPOSE.")?;
- KeyParameterValue::KeyPurpose(key_purpose)
+ KeyParameterValue::KeyPurpose(KeyPurpose(key_purpose))
}
Tag::ALGORITHM => {
- let algorithm: AlgorithmType = data
+ let algorithm: i32 = data
.get()
- .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
.context("Failed to read sql data for tag: ALGORITHM.")?;
- KeyParameterValue::Algorithm(algorithm)
+ KeyParameterValue::Algorithm(Algorithm(algorithm))
}
Tag::KEY_SIZE => {
let key_size: i32 =
@@ -354,25 +361,25 @@
KeyParameterValue::KeySize(key_size)
}
Tag::BLOCK_MODE => {
- let block_mode: BlockModeType = data
+ let block_mode: i32 = data
.get()
- .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
.context("Failed to read sql data for tag: BLOCK_MODE.")?;
- KeyParameterValue::BlockMode(block_mode)
+ KeyParameterValue::BlockMode(BlockMode(block_mode))
}
Tag::DIGEST => {
- let digest: DigestType = data
+ let digest: i32 = data
.get()
- .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
.context("Failed to read sql data for tag: DIGEST.")?;
- KeyParameterValue::Digest(digest)
+ KeyParameterValue::Digest(Digest(digest))
}
Tag::PADDING => {
- let padding: PaddingModeType = data
+ let padding: i32 = data
.get()
- .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
.context("Failed to read sql data for tag: PADDING.")?;
- KeyParameterValue::PaddingMode(padding)
+ KeyParameterValue::PaddingMode(PaddingMode(padding))
}
Tag::CALLER_NONCE => KeyParameterValue::CallerNonce,
Tag::MIN_MAC_LENGTH => {
@@ -381,11 +388,11 @@
KeyParameterValue::MinMacLength(min_mac_length)
}
Tag::EC_CURVE => {
- let ec_curve: EcCurveType = data
+ let ec_curve: i32 = data
.get()
- .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
.context("Failed to read sql data for tag: EC_CURVE.")?;
- KeyParameterValue::EcCurve(ec_curve)
+ KeyParameterValue::EcCurve(EcCurve(ec_curve))
}
Tag::RSA_PUBLIC_EXPONENT => {
let rsa_pub_exponent: i64 =
@@ -436,11 +443,13 @@
}
Tag::NO_AUTH_REQUIRED => KeyParameterValue::NoAuthRequired,
Tag::USER_AUTH_TYPE => {
- let user_auth_type: HardwareAuthenticatorTypeType = data
+ let user_auth_type: i32 = data
.get()
- .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
.context("Failed to read sql data for tag: USER_AUTH_TYPE.")?;
- KeyParameterValue::HardwareAuthenticatorType(user_auth_type)
+ KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType(
+ user_auth_type,
+ ))
}
Tag::AUTH_TIMEOUT => {
let auth_timeout: i32 =
@@ -467,11 +476,11 @@
KeyParameterValue::CreationDateTime(creation_datetime)
}
Tag::ORIGIN => {
- let origin: KeyOriginType = data
+ let origin: i32 = data
.get()
- .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
.context("Failed to read sql data for tag: ORIGIN.")?;
- KeyParameterValue::KeyOrigin(origin)
+ KeyParameterValue::KeyOrigin(KeyOrigin(origin))
}
Tag::ROOT_OF_TRUST => {
let root_of_trust: Vec<u8> =
@@ -581,7 +590,7 @@
KeyParameterValue::ConfirmationToken(confirmation_token)
}
_ => {
- return Err(KeystoreError::Rc(Rc::ValueCorrupted))
+ return Err(KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
.context("Failed to decode Tag enum from value.")?
}
};
@@ -590,296 +599,323 @@
}
/// Macro rules for converting key parameter to/from wire type.
-/// This macro takes three different pieces of information about each of the KeyParameterValue
-/// variants.
-/// 1. variant name
-/// 2. tag name corresponding to the variant
-/// 3. the field name in the AidlKeyParameter struct, in which information about this variant is
-/// stored when converted
+/// This macro takes between three and four different pieces of information about each
+/// of the KeyParameterValue variants:
+/// 1. The KeyParameterValue variant name,
+/// 2. the tag name corresponding to the variant,
+/// 3. the field name in the KmKeyParameter struct, in which information about this variant is
+/// stored when converted, and
+/// 4. an optional enum type name when the nested value is of enum type.
/// The macro takes a set of lines corresponding to each KeyParameterValue variant and generates
/// the two conversion methods: convert_to_wire() and convert_from_wire().
/// ## Example
/// ```
/// implement_key_parameter_conversion_to_from_wire! {
/// Invalid, INVALID, na;
-/// KeyPurpose, PURPOSE, integer;
+/// KeyPurpose, PURPOSE, integer, KeyPurpose;
/// CallerNonce, CALLER_NONCE, boolValue;
/// UserSecureID, USER_SECURE_ID, longInteger;
/// ApplicationID, APPLICATION_ID, blob;
-/// ActiveDateTime, ACTIVE_DATETIME, dateTime;
/// }
/// ```
/// expands to:
/// ```
-/// pub fn convert_to_wire(self) -> AidlKeyParameter {
+/// pub fn convert_to_wire(self) -> KmKeyParameter {
/// match self {
-/// KeyParameterValue::Invalid => AidlKeyParameter {
+/// KeyParameterValue::Invalid => KmKeyParameter {
/// tag: Tag::INVALID,
/// ..Default::default()
/// },
-/// KeyParameterValue::KeyPurpose(v) => AidlKeyParameter {
+/// KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
/// tag: Tag::PURPOSE,
-/// integer: v,
+/// integer: v.0,
/// ..Default::default()
/// },
-/// KeyParameterValue::CallerNonce => AidlKeyParameter {
+/// KeyParameterValue::CallerNonce => KmKeyParameter {
/// tag: Tag::CALLER_NONCE,
/// boolValue: true,
/// ..Default::default()
/// },
-/// KeyParameterValue::UserSecureID(v) => AidlKeyParameter {
+/// KeyParameterValue::UserSecureID(v) => KmKeyParameter {
/// tag: Tag::USER_SECURE_ID,
/// longInteger: v,
/// ..Default::default()
/// },
-/// KeyParameterValue::ApplicationID(v) => AidlKeyParameter {
+/// KeyParameterValue::ApplicationID(v) => KmKeyParameter {
/// tag: Tag::APPLICATION_ID,
/// blob: v,
/// ..Default::default()
/// },
-/// KeyParameterValue::ActiveDateTime(v) => AidlKeyParameter {
-/// tag: Tag::ACTIVE_DATETIME,
-/// dateTime: v,
-/// ..Default::default()
-/// },
/// }
/// }
/// ```
/// and
/// ```
-/// pub fn convert_from_wire(aidl_kp: AidlKeyParameter) -> KeyParameterValue {
+/// pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
/// match aidl_kp {
-/// AidlKeyParameter {
+/// KmKeyParameter {
/// tag: Tag::INVALID,
/// ..
/// } => KeyParameterValue::Invalid,
-/// AidlKeyParameter {
+/// KmKeyParameter {
/// tag: Tag::PURPOSE,
/// integer: v,
/// ..
-/// } => KeyParameterValue::KeyPurpose(v),
-/// AidlKeyParameter {
+/// } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
+/// KmKeyParameter {
/// tag: Tag::CALLER_NONCE,
/// boolValue: true,
/// ..
/// } => KeyParameterValue::CallerNonce,
-/// AidlKeyParameter {
+/// KmKeyParameter {
/// tag: Tag::USER_SECURE_ID,
/// longInteger: v,
/// ..
/// } => KeyParameterValue::UserSecureID(v),
-/// AidlKeyParameter {
+/// KmKeyParameter {
/// tag: Tag::APPLICATION_ID,
/// blob: v,
/// ..
/// } => KeyParameterValue::ApplicationID(v),
-/// AidlKeyParameter {
-/// tag: Tag::ACTIVE_DATETIME,
-/// dateTime: v,
-/// ..
-/// } => KeyParameterValue::ActiveDateTime(v),
/// _ => KeyParameterValue::Invalid,
/// }
/// }
///
macro_rules! implement_key_parameter_conversion_to_from_wire {
- // There are three groups of rules in this macro.
- // 1. The first group contains the rule which acts as the public interface. It takes the input
- // given to this macro and prepares it to be given as input to the two groups of rules
- // mentioned below.
- // 2. The second group starts with the prefix @to and generates convert_to_wire() method.
- // 3. The third group starts with the prefix @from and generates convert_from_wire() method.
- //
- // Input to this macro is first handled by the first macro rule (belonging to the first
- // group above), which pre-processes the input such that rules in the other two groups
- // generate the code for the two methods, when called recursively.
- // Each of convert_to_wire() and convert_from_wire() methods are generated using a set of
- // four macro rules in the second two groups. These four rules intend to do the following
- // tasks respectively:
- // i) generates match arms related to Invalid KeyParameterValue variant.
- // ii) generates match arms related to boolValue field in AidlKeyParameter struct.
- // iii) generates match arms related to all the other fields in AidlKeyParameter struct.
- // iv) generates the method definition including the match arms generated from the above
- // three recursive macro rules.
+ // There are three groups of rules in this macro.
+ // 1. The first group contains the rule which acts as the public interface. It takes the input
+ // given to this macro and prepares it to be given as input to the two groups of rules
+ // mentioned below.
+ // 2. The second group starts with the prefix @to and generates convert_to_wire() method.
+ // 3. The third group starts with the prefix @from and generates convert_from_wire() method.
+ //
+ // Input to this macro is first handled by the first macro rule (belonging to the first
+ // group above), which pre-processes the input such that rules in the other two groups
+ // generate the code for the two methods, when called recursively.
+ // Each of convert_to_wire() and convert_from_wire() methods are generated using a set of
+ // four macro rules in the second two groups. These four rules intend to do the following
+ // tasks respectively:
+ // i) generates match arms related to Invalid KeyParameterValue variant.
+ // ii) generates match arms related to boolValue field in KmKeyParameter struct.
+ // iii) generates match arms related to all the other fields in KmKeyParameter struct.
+ // iv) generates the method definition including the match arms generated from the above
+ // three recursive macro rules.
- // This rule is applied on the input given to the macro invocations from outside the macro.
- ($($variant:ident, $tag_name:ident, $field_name:ident;)*) => {
- // pre-processes input to target the rules that generate convert_to_wire() method.
- implement_key_parameter_conversion_to_from_wire! {@to
- [], $($variant, $tag_name, $field_name;)*
- }
- // pre-processes input to target the rules that generate convert_from_wire() method.
- implement_key_parameter_conversion_to_from_wire! {@from
- [], $($variant, $tag_name, $field_name;)*
- }
- };
+ // This rule is applied on the input given to the macro invocations from outside the macro.
+ ($($variant:ident, $tag_name:ident, $field_name:ident $(,$enum_type:ident)?;)*) => {
+ // pre-processes input to target the rules that generate convert_to_wire() method.
+ implement_key_parameter_conversion_to_from_wire! {@to
+ [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
+ }
+ // pre-processes input to target the rules that generate convert_from_wire() method.
+ implement_key_parameter_conversion_to_from_wire! {@from
+ [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
+ }
+ };
- // Following four rules (belonging to the aforementioned second group) generate
- // convert_to_wire() conversion method.
- // -----------------------------------------------------------------------
- // This rule handles Invalid variant.
- // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
- // KeyParameterValue::Invalid => AidlKeyParameter {
- // tag: Tag::INVALID,
- // ..Default::default()
- // },
- (@to [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
- implement_key_parameter_conversion_to_from_wire! {@to
- [$($out)*
- KeyParameterValue::Invalid => AidlKeyParameter {
- tag: Tag::INVALID,
- ..Default::default()
- },
- ], $($in)*
- }
- };
- // This rule handles all variants that correspond to bool values.
- // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates
- // a match arm like:
- // KeyParameterValue::CallerNonce => AidlKeyParameter {
- // tag: Tag::CALLER_NONCE,
- // boolValue: true,
- // ..Default::default()
- // },
- (@to [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
- implement_key_parameter_conversion_to_from_wire! {@to
- [$($out)*
- KeyParameterValue::$variant => AidlKeyParameter {
- tag: Tag::$tag_val,
- boolValue: true,
- ..Default::default()
- },
- ], $($in)*
- }
- };
- // This rule handles all variants that are neither invalid nor bool values
- // (i.e. all variants which correspond to integer, longInteger, dateTime and blob fields in
- // AidlKeyParameter).
- // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
- // like: KeyParameterValue::ConfirmationToken(v) => AidlKeyParameter {
- // tag: Tag::CONFIRMATION_TOKEN,
- // blob: v,
- // ..Default::default(),
- // }
- (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
- implement_key_parameter_conversion_to_from_wire! {@to
- [$($out)*
- KeyParameterValue::$variant(v) => AidlKeyParameter {
- tag: Tag::$tag_val,
- $field: v,
- ..Default::default()
- },
- ], $($in)*
- }
- };
- // After all the match arms are generated by the above three rules, this rule combines them
- // into the convert_to_wire() method.
- (@to [$($out:tt)*], ) => {
- /// Conversion of key parameter to wire type
- pub fn convert_to_wire(self) -> AidlKeyParameter {
- match self {
- $($out)*
- }
- }
- };
+ // Following four rules (belonging to the aforementioned second group) generate
+ // convert_to_wire() conversion method.
+ // -----------------------------------------------------------------------
+ // This rule handles Invalid variant.
+ // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
+ // KeyParameterValue::Invalid => KmKeyParameter {
+ // tag: Tag::INVALID,
+ // ..Default::default()
+ // },
+ (@to [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
+ implement_key_parameter_conversion_to_from_wire! {@to
+ [$($out)*
+ KeyParameterValue::Invalid => KmKeyParameter {
+ tag: Tag::INVALID,
+ ..Default::default()
+ },
+ ], $($in)*
+ }
+ };
+ // This rule handles all variants that correspond to bool values.
+ // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates
+ // a match arm like:
+ // KeyParameterValue::CallerNonce => KmKeyParameter {
+ // tag: Tag::CALLER_NONCE,
+ // boolValue: true,
+ // ..Default::default()
+ // },
+ (@to [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
+ implement_key_parameter_conversion_to_from_wire! {@to
+ [$($out)*
+ KeyParameterValue::$variant => KmKeyParameter {
+ tag: Tag::$tag_val,
+ boolValue: true,
+ ..Default::default()
+ },
+ ], $($in)*
+ }
+ };
+ // This rule handles all enum variants.
+ // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
+ // like: KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
+ // tag: Tag::PURPOSE,
+ // integer: v.0,
+ // ..Default::default(),
+ // },
+ (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
+ implement_key_parameter_conversion_to_from_wire! {@to
+ [$($out)*
+ KeyParameterValue::$variant(v) => KmKeyParameter {
+ tag: Tag::$tag_val,
+ $field: v.0,
+ ..Default::default()
+ },
+ ], $($in)*
+ }
+ };
+ // This rule handles all variants that are neither invalid nor bool values nor enums
+ // (i.e. all variants which correspond to integer, longInteger, and blob fields in
+ // KmKeyParameter).
+ // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
+ // like: KeyParameterValue::ConfirmationToken(v) => KmKeyParameter {
+ // tag: Tag::CONFIRMATION_TOKEN,
+ // blob: v,
+ // ..Default::default(),
+ // },
+ (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
+ implement_key_parameter_conversion_to_from_wire! {@to
+ [$($out)*
+ KeyParameterValue::$variant(v) => KmKeyParameter {
+ tag: Tag::$tag_val,
+ $field: v,
+ ..Default::default()
+ },
+ ], $($in)*
+ }
+ };
+ // After all the match arms are generated by the above three rules, this rule combines them
+ // into the convert_to_wire() method.
+ (@to [$($out:tt)*], ) => {
+ /// Conversion of key parameter to wire type
+ pub fn convert_to_wire(self) -> KmKeyParameter {
+ match self {
+ $($out)*
+ }
+ }
+ };
- // Following four rules (belonging to the aforementioned third group) generate
- // convert_from_wire() conversion method.
- // ------------------------------------------------------------------------
- // This rule handles Invalid variant.
- // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
- // AidlKeyParameter { tag: Tag::INVALID, .. } => KeyParameterValue::Invalid,
- (@from [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
- implement_key_parameter_conversion_to_from_wire! {@from
- [$($out)*
- AidlKeyParameter {
- tag: Tag::INVALID,
- ..
- } => KeyParameterValue::Invalid,
- ], $($in)*
- }
- };
- // This rule handles all variants that correspond to bool values.
- // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates a match arm like:
- // AidlKeyParameter {
- // tag: Tag::CALLER_NONCE,
- // boolValue: true,
- // ..
- // } => KeyParameterValue::CallerNonce,
- (@from [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
- implement_key_parameter_conversion_to_from_wire! {@from
- [$($out)*
- AidlKeyParameter {
- tag: Tag::$tag_val,
- boolValue: true,
- ..
- } => KeyParameterValue::$variant,
- ], $($in)*
- }
- };
- // This rule handles all variants that are neither invalid nor bool values
- // (i.e. all variants which correspond to integer, longInteger, dateTime and blob fields in
- // AidlKeyParameter).
- // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
- // like:
- // AidlKeyParameter {
- // tag: Tag::CONFIRMATION_TOKEN,
- // blob: v,
- // ..,
- // } => KeyParameterValue::ConfirmationToken(v),
- (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
- implement_key_parameter_conversion_to_from_wire! {@from
- [$($out)*
- AidlKeyParameter {
- tag: Tag::$tag_val,
- $field: v,
- ..
- } => KeyParameterValue::$variant(v),
- ], $($in)*
- }
- };
- // After all the match arms are generated by the above three rules, this rule combines them
- // into the convert_from_wire() method.
- (@from [$($out:tt)*], ) => {
- /// Conversion of key parameter from wire type
- pub fn convert_from_wire(aidl_kp: AidlKeyParameter) -> KeyParameterValue {
- match aidl_kp {
- $($out)*
- _ => KeyParameterValue::Invalid,
- }
- }
- };
+ // Following four rules (belonging to the aforementioned third group) generate
+ // convert_from_wire() conversion method.
+ // ------------------------------------------------------------------------
+ // This rule handles Invalid variant.
+ // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
+ // KmKeyParameter { tag: Tag::INVALID, .. } => KeyParameterValue::Invalid,
+ (@from [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
+ implement_key_parameter_conversion_to_from_wire! {@from
+ [$($out)*
+ KmKeyParameter {
+ tag: Tag::INVALID,
+ ..
+ } => KeyParameterValue::Invalid,
+ ], $($in)*
+ }
+ };
+ // This rule handles all variants that correspond to bool values.
+ // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates a match arm like:
+ // KmKeyParameter {
+ // tag: Tag::CALLER_NONCE,
+ // boolValue: true,
+ // ..
+ // } => KeyParameterValue::CallerNonce,
+ (@from [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
+ implement_key_parameter_conversion_to_from_wire! {@from
+ [$($out)*
+ KmKeyParameter {
+ tag: Tag::$tag_val,
+ boolValue: true,
+ ..
+ } => KeyParameterValue::$variant,
+ ], $($in)*
+ }
+ };
+ // This rule handles all enum variants.
+ // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
+ // like:
+ // KmKeyParameter {
+ // tag: Tag::PURPOSE,
+ // integer: v,
+ // ..,
+ // } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
+ (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
+ implement_key_parameter_conversion_to_from_wire! {@from
+ [$($out)*
+ KmKeyParameter {
+ tag: Tag::$tag_val,
+ $field: v,
+ ..
+ } => KeyParameterValue::$variant($enum_type(v)),
+ ], $($in)*
+ }
+ };
+ // This rule handles all variants that are neither invalid nor bool values nor enums
+ // (i.e. all variants which correspond to integer, longInteger, and blob fields in
+ // KmKeyParameter).
+ // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
+ // like:
+ // KmKeyParameter {
+ // tag: Tag::CONFIRMATION_TOKEN,
+ // blob: v,
+ // ..,
+ // } => KeyParameterValue::ConfirmationToken(v),
+ (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
+ implement_key_parameter_conversion_to_from_wire! {@from
+ [$($out)*
+ KmKeyParameter {
+ tag: Tag::$tag_val,
+ $field: v,
+ ..
+ } => KeyParameterValue::$variant(v),
+ ], $($in)*
+ }
+ };
+ // After all the match arms are generated by the above three rules, this rule combines them
+ // into the convert_from_wire() method.
+ (@from [$($out:tt)*], ) => {
+ /// Conversion of key parameter from wire type
+ pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
+ match aidl_kp {
+ $($out)*
+ _ => KeyParameterValue::Invalid,
+ }
+ }
+ };
}
impl KeyParameterValue {
// Invoke the macro that generates the code for key parameter conversion to/from wire type
// with all possible variants of KeyParameterValue. Each line corresponding to a variant
// contains: variant identifier, tag value, and the related field name (i.e.
- // boolValue/integer/longInteger/dateTime/blob) in the AidlKeyParameter.
+ // boolValue/integer/longInteger/blob) in the KmKeyParameter.
implement_key_parameter_conversion_to_from_wire! {
Invalid, INVALID, na;
- KeyPurpose, PURPOSE, integer;
- Algorithm, ALGORITHM, integer;
+ KeyPurpose, PURPOSE, integer, KeyPurpose;
+ Algorithm, ALGORITHM, integer, Algorithm;
KeySize, KEY_SIZE, integer;
- BlockMode, BLOCK_MODE, integer;
- Digest, DIGEST, integer;
- PaddingMode, PADDING, integer;
+ BlockMode, BLOCK_MODE, integer, BlockMode;
+ Digest, DIGEST, integer, Digest;
+ PaddingMode, PADDING, integer, PaddingMode;
CallerNonce, CALLER_NONCE, boolValue;
MinMacLength, MIN_MAC_LENGTH, integer;
- EcCurve, EC_CURVE, integer;
+ EcCurve, EC_CURVE, integer, EcCurve;
RSAPublicExponent, RSA_PUBLIC_EXPONENT, longInteger;
IncludeUniqueID, INCLUDE_UNIQUE_ID, boolValue;
BootLoaderOnly, BOOTLOADER_ONLY, boolValue;
RollbackResistance, ROLLBACK_RESISTANCE, boolValue;
- ActiveDateTime, ACTIVE_DATETIME, dateTime;
- OriginationExpireDateTime, ORIGINATION_EXPIRE_DATETIME, dateTime;
- UsageExpireDateTime, USAGE_EXPIRE_DATETIME, dateTime;
+ ActiveDateTime, ACTIVE_DATETIME, longInteger;
+ OriginationExpireDateTime, ORIGINATION_EXPIRE_DATETIME, longInteger;
+ UsageExpireDateTime, USAGE_EXPIRE_DATETIME, longInteger;
MinSecondsBetweenOps, MIN_SECONDS_BETWEEN_OPS, integer;
MaxUsesPerBoot, MAX_USES_PER_BOOT, integer;
UserID, USER_ID, integer;
UserSecureID, USER_SECURE_ID, longInteger;
NoAuthRequired, NO_AUTH_REQUIRED, boolValue;
- HardwareAuthenticatorType, USER_AUTH_TYPE, integer;
+ HardwareAuthenticatorType, USER_AUTH_TYPE, integer, HardwareAuthenticatorType;
AuthTimeout, AUTH_TIMEOUT, integer;
AllowWhileOnBody, ALLOW_WHILE_ON_BODY, boolValue;
TrustedUserPresenceRequired, TRUSTED_USER_PRESENCE_REQUIRED, boolValue;
@@ -887,8 +923,8 @@
UnlockedDeviceRequired, UNLOCKED_DEVICE_REQUIRED, boolValue;
ApplicationID, APPLICATION_ID, blob;
ApplicationData, APPLICATION_DATA, blob;
- CreationDateTime, CREATION_DATETIME, dateTime;
- KeyOrigin, ORIGIN, integer;
+ CreationDateTime, CREATION_DATETIME, longInteger;
+ KeyOrigin, ORIGIN, integer, KeyOrigin;
RootOfTrust, ROOT_OF_TRUST, blob;
OSVersion, OS_VERSION, integer;
OSPatchLevel, OS_PATCHLEVEL, integer;
@@ -960,9 +996,9 @@
insert_into_keyparameter(
&db,
1,
- Tag::ALGORITHM,
- &Algorithm::RSA,
- SecurityLevel::STRONGBOX,
+ Tag::ALGORITHM.0,
+ &Algorithm::RSA.0,
+ SecurityLevel::STRONGBOX.0,
)?;
let key_param = query_from_keyparameter(&db)?;
assert_eq!(Tag::ALGORITHM, key_param.get_tag());
@@ -976,7 +1012,7 @@
#[test]
fn test_new_from_sql_i32() -> Result<()> {
let db = init_db()?;
- insert_into_keyparameter(&db, 1, Tag::KEY_SIZE, &1024, SecurityLevel::STRONGBOX)?;
+ insert_into_keyparameter(&db, 1, Tag::KEY_SIZE.0, &1024, SecurityLevel::STRONGBOX.0)?;
let key_param = query_from_keyparameter(&db)?;
assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
@@ -992,9 +1028,9 @@
insert_into_keyparameter(
&db,
1,
- Tag::RSA_PUBLIC_EXPONENT,
+ Tag::RSA_PUBLIC_EXPONENT.0,
&(i64::MAX),
- SecurityLevel::STRONGBOX,
+ SecurityLevel::STRONGBOX.0,
)?;
let key_param = query_from_keyparameter(&db)?;
assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
@@ -1010,7 +1046,7 @@
#[test]
fn test_new_from_sql_bool() -> Result<()> {
let db = init_db()?;
- insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE, &Null, SecurityLevel::STRONGBOX)?;
+ insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE.0, &Null, SecurityLevel::STRONGBOX.0)?;
let key_param = query_from_keyparameter(&db)?;
assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
@@ -1027,9 +1063,9 @@
insert_into_keyparameter(
&db,
1,
- Tag::APPLICATION_ID,
+ Tag::APPLICATION_ID.0,
&app_id_bytes,
- SecurityLevel::STRONGBOX,
+ SecurityLevel::STRONGBOX.0,
)?;
let key_param = query_from_keyparameter(&db)?;
assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
@@ -1140,7 +1176,7 @@
#[test]
fn test_invalid_conversion_from_sql() -> Result<()> {
let db = init_db()?;
- insert_into_keyparameter(&db, 1, Tag::ALGORITHM, &Null, 1)?;
+ insert_into_keyparameter(&db, 1, Tag::ALGORITHM.0, &Null, 1)?;
tests::check_result_contains_error_string(
query_from_keyparameter(&db),
"Failed to read sql data for tag: ALGORITHM.",
@@ -1175,7 +1211,7 @@
) -> Result<()> {
db.execute(
"INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
-VALUES(?, ?, ?, ?);",
+ VALUES(?, ?, ?, ?);",
params![key_id, tag, *value, security_level],
)?;
Ok(())
@@ -1185,32 +1221,33 @@
fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
db.execute(
"INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
-VALUES(?, ?, ?, ?);",
- params![key_id, kp.get_tag(), kp.key_parameter_value(), kp.security_level()],
+ VALUES(?, ?, ?, ?);",
+ params![key_id, kp.get_tag().0, kp.key_parameter_value(), kp.security_level().0],
)?;
Ok(())
}
/// Helper method to query a row from keyparameter table
fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
- let mut stmt = db.prepare(
- "SELECT tag, data, security_level FROM
-persistent.keyparameter",
- )?;
+ let mut stmt =
+ db.prepare("SELECT tag, data, security_level FROM persistent.keyparameter")?;
let mut rows = stmt.query(NO_PARAMS)?;
let row = rows.next()?.unwrap();
- Ok(KeyParameter::new_from_sql(row.get(0)?, &SqlField(1, row), row.get(2)?)?)
+ Ok(KeyParameter::new_from_sql(
+ Tag(row.get(0)?),
+ &SqlField(1, row),
+ SecurityLevel(row.get(2)?),
+ )?)
}
}
/// The wire_tests module tests the 'convert_to_wire' and 'convert_from_wire' methods for
-/// KeyParameter, for the five different types used in AidlKeyParameter, in addition to Invalid
+/// KeyParameter, for the four different types used in KmKeyParameter, in addition to Invalid
/// key parameter.
/// i) bool
/// ii) integer
/// iii) longInteger
-/// iv) dateTime
-/// v) blob
+/// iv) blob
#[cfg(test)]
mod wire_tests {
use crate::key_parameter::*;
@@ -1236,7 +1273,7 @@
);
let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
assert_eq!(Tag::PURPOSE, actual.tag);
- assert_eq!(KeyPurpose::ENCRYPT, actual.integer);
+ assert_eq!(KeyPurpose::ENCRYPT.0, actual.integer);
}
#[test]
fn test_convert_to_wire_long_integer() {
@@ -1247,16 +1284,6 @@
assert_eq!(i64::MAX, actual.longInteger);
}
#[test]
- fn test_convert_to_wire_date_time() {
- let kp = KeyParameter::new(
- KeyParameterValue::ActiveDateTime(i64::MAX),
- SecurityLevel::STRONGBOX,
- );
- let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
- assert_eq!(Tag::ACTIVE_DATETIME, actual.tag);
- assert_eq!(i64::MAX, actual.dateTime);
- }
- #[test]
fn test_convert_to_wire_blob() {
let kp = KeyParameter::new(
KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
@@ -1270,22 +1297,22 @@
/// unit tests for from conversion
#[test]
fn test_convert_from_wire_invalid() {
- let aidl_kp = AidlKeyParameter { tag: Tag::INVALID, ..Default::default() };
+ let aidl_kp = KmKeyParameter { tag: Tag::INVALID, ..Default::default() };
let actual = KeyParameterValue::convert_from_wire(aidl_kp);
assert_eq!(KeyParameterValue::Invalid, actual);
}
#[test]
fn test_convert_from_wire_bool() {
let aidl_kp =
- AidlKeyParameter { tag: Tag::CALLER_NONCE, boolValue: true, ..Default::default() };
+ KmKeyParameter { tag: Tag::CALLER_NONCE, boolValue: true, ..Default::default() };
let actual = KeyParameterValue::convert_from_wire(aidl_kp);
assert_eq!(KeyParameterValue::CallerNonce, actual);
}
#[test]
fn test_convert_from_wire_integer() {
- let aidl_kp = AidlKeyParameter {
+ let aidl_kp = KmKeyParameter {
tag: Tag::PURPOSE,
- integer: KeyPurpose::ENCRYPT,
+ integer: KeyPurpose::ENCRYPT.0,
..Default::default()
};
let actual = KeyParameterValue::convert_from_wire(aidl_kp);
@@ -1293,7 +1320,7 @@
}
#[test]
fn test_convert_from_wire_long_integer() {
- let aidl_kp = AidlKeyParameter {
+ let aidl_kp = KmKeyParameter {
tag: Tag::USER_SECURE_ID,
longInteger: i64::MAX,
..Default::default()
@@ -1302,18 +1329,8 @@
assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), actual);
}
#[test]
- fn test_convert_from_wire_date_time() {
- let aidl_kp = AidlKeyParameter {
- tag: Tag::ACTIVE_DATETIME,
- dateTime: i64::MAX,
- ..Default::default()
- };
- let actual = KeyParameterValue::convert_from_wire(aidl_kp);
- assert_eq!(KeyParameterValue::ActiveDateTime(i64::MAX), actual);
- }
- #[test]
fn test_convert_from_wire_blob() {
- let aidl_kp = AidlKeyParameter {
+ let aidl_kp = KmKeyParameter {
tag: Tag::CONFIRMATION_TOKEN,
blob: String::from("ConfirmationToken").into_bytes(),
..Default::default()
diff --git a/keystore2/src/keystore2_main.rs b/keystore2/src/keystore2_main.rs
new file mode 100644
index 0000000..dea0a93
--- /dev/null
+++ b/keystore2/src/keystore2_main.rs
@@ -0,0 +1,59 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This crate implements Keystore 2.0.
+
+use binder::Interface;
+use keystore2::service::KeystoreService;
+use log::{error, info};
+use std::panic;
+
+static KS2_SERVICE_NAME: &str = "android.system.keystore2";
+
+/// Keystore 2.0 takes one argument which is a path indicating its designated working directory.
+fn main() {
+ // Initialize android logging.
+ android_logger::init_once(
+ android_logger::Config::default().with_tag("keystore2").with_min_level(log::Level::Debug),
+ );
+ // Redirect panic messages to logcat.
+ panic::set_hook(Box::new(|panic_info| {
+ error!("{}", panic_info);
+ }));
+
+ // Saying hi.
+ info!("Keystore2 is starting.");
+
+ let mut args = std::env::args();
+ args.next().expect("That's odd. How is there not even a first argument?");
+ if let Some(dir) = args.next() {
+ if std::env::set_current_dir(dir.clone()).is_err() {
+ panic!("Failed to set working directory {}.", dir)
+ }
+ } else {
+ panic!("Must specify a working directory.");
+ }
+
+ let ks_service = KeystoreService::new_native_binder().unwrap_or_else(|e| {
+ panic!("Failed to create service {} because of {:?}.", KS2_SERVICE_NAME, e);
+ });
+ binder::add_service(KS2_SERVICE_NAME, ks_service.as_binder()).unwrap_or_else(|e| {
+ panic!("Failed to register service {} because of {:?}.", KS2_SERVICE_NAME, e);
+ });
+
+ info!("Successfully registered Keystore 2.0 service.");
+ info!("Joining threadpool now.");
+
+ binder::ProcessState::join_thread_pool();
+}
diff --git a/keystore2/src/lib.rs b/keystore2/src/lib.rs
index b5fef3e..3e13c5f 100644
--- a/keystore2/src/lib.rs
+++ b/keystore2/src/lib.rs
@@ -14,8 +14,14 @@
//! This crate implements the Android Keystore 2.0 service.
+mod crypto;
pub mod database;
pub mod error;
+pub mod globals;
/// Internal Representation of Key Parameter and convenience functions.
pub mod key_parameter;
+pub mod operation;
pub mod permission;
+pub mod security_level;
+pub mod service;
+pub mod utils;
diff --git a/keystore2/src/operation.rs b/keystore2/src/operation.rs
new file mode 100644
index 0000000..14edc6c
--- /dev/null
+++ b/keystore2/src/operation.rs
@@ -0,0 +1,815 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This crate implements the `IKeystoreOperation` AIDL interface, which represents
+//! an ongoing key operation, as well as the operation database, which is mainly
+//! required for tracking operations for the purpose of pruning.
+//! This crate also implements an operation pruning strategy.
+//!
+//! Operations implement the API calls update, finish, and abort.
+//! Additionally, an operation can be dropped and pruned. The former
+//! happens if the client deletes a binder to the operation object.
+//! An existing operation may get pruned when running out of operation
+//! slots and a new operation takes precedence.
+//!
+//! ## Operation Lifecycle
+//! An operation gets created when the client calls `IKeystoreSecurityLevel::create`.
+//! It may receive zero or more update request. The lifecycle ends when:
+//! * `update` yields an error.
+//! * `finish` is called.
+//! * `abort` is called.
+//! * The operation gets dropped.
+//! * The operation gets pruned.
+//! `Operation` has an `Outcome` member. While the outcome is `Outcome::Unknown`,
+//! the operation is active and in a good state. Any of the above conditions may
+//! change the outcome to one of the defined outcomes Success, Abort, Dropped,
+//! Pruned, or ErrorCode. The latter is chosen in the case of an unexpected error, during
+//! `update` or `finish`. `Success` is chosen iff `finish` completes without error.
+//! Note that all operations get dropped eventually in the sense that they lose
+//! their last reference and get destroyed. At that point, the fate of the operation
+//! gets logged. However, an operation will transition to `Outcome::Dropped` iff
+//! the operation was still active (`Outcome::Unknown`) at that time.
+//!
+//! ## Operation Dropping
+//! To observe the dropping of an operation, we have to make sure that there
+//! are no strong references to the IBinder representing this operation.
+//! This would be simple enough if the operation object would need to be accessed
+//! only by transactions. But to perform pruning, we have to retain a reference to the
+//! original operation object.
+//!
+//! ## Operation Pruning
+//! Pruning an operation happens during the creation of a new operation.
+//! We have to iterate through the operation database to find a suitable
+//! candidate. Then we abort and finalize this operation setting its outcome to
+//! `Outcome::Pruned`. The corresponding KeyMint operation slot will have been freed
+//! up at this point, but the `Operation` object lingers. When the client
+//! attempts to use the operation again they will receive
+//! ErrorCode::INVALID_OPERATION_HANDLE indicating that the operation no longer
+//! exits. This should be the cue for the client to destroy its binder.
+//! At that point the operation gets dropped.
+//!
+//! ## Architecture
+//! The `IKeystoreOperation` trait is implemented by `KeystoreOperation`.
+//! This acts as a proxy object holding a strong reference to actual operation
+//! implementation `Operation`.
+//!
+//! ```
+//! struct KeystoreOperation {
+//! operation: Mutex<Option<Arc<Operation>>>,
+//! }
+//! ```
+//!
+//! The `Mutex` serves two purposes. It provides interior mutability allowing
+//! us to set the Option to None. We do this when the life cycle ends during
+//! a call to `update`, `finish`, or `abort`. As a result most of the Operation
+//! related resources are freed. The `KeystoreOperation` proxy object still
+//! lingers until dropped by the client.
+//! The second purpose is to protect operations against concurrent usage.
+//! Failing to lock this mutex yields `ResponseCode::OPERATION_BUSY` and indicates
+//! a programming error in the client.
+//!
+//! Note that the Mutex only protects the operation against concurrent client calls.
+//! We still retain weak references to the operation in the operation database:
+//!
+//! ```
+//! struct OperationDb {
+//! operations: Mutex<Vec<Weak<Operation>>>
+//! }
+//! ```
+//!
+//! This allows us to access the operations for the purpose of pruning.
+//! We do this in three phases.
+//! 1. We gather the pruning information. Besides non mutable information,
+//! we access `last_usage` which is protected by a mutex.
+//! We only lock this mutex for single statements at a time. During
+//! this phase we hold the operation db lock.
+//! 2. We choose a pruning candidate by computing the pruning resistance
+//! of each operation. We do this entirely with information we now
+//! have on the stack without holding any locks.
+//! (See `OperationDb::prune` for more details on the pruning strategy.)
+//! 3. During pruning we briefly lock the operation database again to get the
+//! the pruning candidate by index. We then attempt to abort the candidate.
+//! If the candidate was touched in the meantime or is currently fulfilling
+//! a request (i.e., the client calls update, finish, or abort),
+//! we go back to 1 and try again.
+//!
+//! So the outer Mutex in `KeystoreOperation::operation` only protects
+//! operations against concurrent client calls but not against concurrent
+//! pruning attempts. This is what the `Operation::outcome` mutex is used for.
+//!
+//! ```
+//! struct Operation {
+//! ...
+//! outcome: Mutex<Outcome>,
+//! ...
+//! }
+//! ```
+//!
+//! Any request that can change the outcome, i.e., `update`, `finish`, `abort`,
+//! `drop`, and `prune` has to take the outcome lock and check if the outcome
+//! is still `Outcome::Unknown` before entering. `prune` is special in that
+//! it will `try_lock`, because we don't want to be blocked on a potentially
+//! long running request at another operation. If it fails to get the lock
+//! the operation is either being touched, which changes its pruning resistance,
+//! or it transitions to its end-of-life, which means we may get a free slot.
+//! Either way, we have to revaluate the pruning scores.
+
+use std::{
+ collections::HashMap,
+ sync::{Arc, Mutex, MutexGuard, Weak},
+ time::Duration,
+ time::Instant,
+};
+
+use crate::error::{map_km_error, map_or_log_err, Error, ErrorCode, ResponseCode};
+use crate::utils::Asp;
+use android_hardware_keymint::aidl::android::hardware::keymint::{
+ ByteArray::ByteArray, IKeyMintOperation::IKeyMintOperation,
+ KeyParameter::KeyParameter as KmParam, KeyParameterArray::KeyParameterArray, Tag::Tag,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+ IKeystoreOperation::BnKeystoreOperation, IKeystoreOperation::IKeystoreOperation,
+};
+use anyhow::{anyhow, Context, Result};
+use binder::{IBinder, Interface};
+
+/// Operations have `Outcome::Unknown` as long as they are active. They transition
+/// to one of the other variants exactly once. The distinction in outcome is mainly
+/// for the statistic.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
+enum Outcome {
+ Unknown,
+ Success,
+ Abort,
+ Dropped,
+ Pruned,
+ ErrorCode(ErrorCode),
+}
+
+/// Operation bundles all of the operation related resources and tracks the operation's
+/// outcome.
+#[derive(Debug)]
+pub struct Operation {
+ // The index of this operation in the OperationDb.
+ index: usize,
+ km_op: Asp,
+ last_usage: Mutex<Instant>,
+ outcome: Mutex<Outcome>,
+ owner: u32, // Uid of the operation's owner.
+}
+
+struct PruningInfo {
+ last_usage: Instant,
+ owner: u32,
+ index: usize,
+}
+
+// We don't except more than 32KiB of data in `update`, `updateAad`, and `finish`.
+const MAX_RECEIVE_DATA: usize = 0x8000;
+
+impl Operation {
+ /// Constructor
+ pub fn new(index: usize, km_op: Box<dyn IKeyMintOperation>, owner: u32) -> Self {
+ Self {
+ index,
+ km_op: Asp::new(km_op.as_binder()),
+ last_usage: Mutex::new(Instant::now()),
+ outcome: Mutex::new(Outcome::Unknown),
+ owner,
+ }
+ }
+
+ fn get_pruning_info(&self) -> Option<PruningInfo> {
+ // An operation may be finalized.
+ if let Ok(guard) = self.outcome.try_lock() {
+ match *guard {
+ Outcome::Unknown => {}
+ // If the outcome is any other than unknown, it has been finalized,
+ // and we can no longer consider it for pruning.
+ _ => return None,
+ }
+ }
+ // Else: If we could not grab the lock, this means that the operation is currently
+ // being used and it may be transitioning to finalized or it was simply updated.
+ // In any case it is fair game to consider it for pruning. If the operation
+ // transitioned to a final state, we will notice when we attempt to prune, and
+ // a subsequent attempt to create a new operation will succeed.
+ Some(PruningInfo {
+ // Expect safety:
+ // `last_usage` is locked only for primitive single line statements.
+ // There is no chance to panic and poison the mutex.
+ last_usage: *self.last_usage.lock().expect("In get_pruning_info."),
+ owner: self.owner,
+ index: self.index,
+ })
+ }
+
+ fn prune(&self, last_usage: Instant) -> Result<(), Error> {
+ let mut locked_outcome = match self.outcome.try_lock() {
+ Ok(guard) => match *guard {
+ Outcome::Unknown => guard,
+ _ => return Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)),
+ },
+ Err(_) => return Err(Error::Rc(ResponseCode::OPERATION_BUSY)),
+ };
+
+ // In `OperationDb::prune`, which is our caller, we first gather the pruning
+ // information including the last usage. When we select a candidate
+ // we call `prune` on that candidate passing the last_usage
+ // that we gathered earlier. If the actual last usage
+ // has changed since than, it means the operation was busy in the
+ // meantime, which means that we have to reevaluate the pruning score.
+ //
+ // Expect safety:
+ // `last_usage` is locked only for primitive single line statements.
+ // There is no chance to panic and poison the mutex.
+ if *self.last_usage.lock().expect("In Operation::prune()") != last_usage {
+ return Err(Error::Rc(ResponseCode::OPERATION_BUSY));
+ }
+ *locked_outcome = Outcome::Pruned;
+
+ let km_op: Box<dyn IKeyMintOperation> = match self.km_op.get_interface() {
+ Ok(km_op) => km_op,
+ Err(e) => {
+ log::error!("In prune: Failed to get KeyMintOperation interface.\n {:?}", e);
+ return Err(Error::sys());
+ }
+ };
+
+ // We abort the operation. If there was an error we log it but ignore it.
+ if let Err(e) = map_km_error(km_op.abort()) {
+ log::error!("In prune: KeyMint::abort failed with {:?}.", e);
+ }
+
+ Ok(())
+ }
+
+ // This function takes a Result from a KeyMint call and inspects it for errors.
+ // If an error was found it updates the given `locked_outcome` accordingly.
+ // It forwards the Result unmodified.
+ // The precondition to this call must be *locked_outcome == Outcome::Unknown.
+ // Ideally the `locked_outcome` came from a successful call to `check_active`
+ // see below.
+ fn update_outcome<T>(
+ &self,
+ locked_outcome: &mut Outcome,
+ err: Result<T, Error>,
+ ) -> Result<T, Error> {
+ match &err {
+ Err(Error::Km(e)) => *locked_outcome = Outcome::ErrorCode(*e),
+ Err(_) => *locked_outcome = Outcome::ErrorCode(ErrorCode::UNKNOWN_ERROR),
+ Ok(_) => (),
+ }
+ err
+ }
+
+ // This function grabs the outcome lock and checks the current outcome state.
+ // If the outcome is still `Outcome::Unknown`, this function returns
+ // the locked outcome for further updates. In any other case it returns
+ // ErrorCode::INVALID_OPERATION_HANDLE indicating that this operation has
+ // been finalized and is no longer active.
+ fn check_active(&self) -> Result<MutexGuard<Outcome>> {
+ let guard = self.outcome.lock().expect("In check_active.");
+ match *guard {
+ Outcome::Unknown => Ok(guard),
+ _ => Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)).context(format!(
+ "In check_active: Call on finalized operation with outcome: {:?}.",
+ *guard
+ )),
+ }
+ }
+
+ // This function checks the amount of input data sent to us. We reject any buffer
+ // exceeding MAX_RECEIVE_DATA bytes as input to `update`, `update_aad`, and `finish`
+ // in order to force clients into using reasonable limits.
+ fn check_input_length(data: &[u8]) -> Result<()> {
+ if data.len() > MAX_RECEIVE_DATA {
+ // This error code is unique, no context required here.
+ return Err(anyhow!(Error::Rc(ResponseCode::TOO_MUCH_DATA)));
+ }
+ Ok(())
+ }
+
+ // Update the last usage to now.
+ fn touch(&self) {
+ // Expect safety:
+ // `last_usage` is locked only for primitive single line statements.
+ // There is no chance to panic and poison the mutex.
+ *self.last_usage.lock().expect("In touch.") = Instant::now();
+ }
+
+ /// Implementation of `IKeystoreOperation::updateAad`.
+ /// Refer to the AIDL spec at system/hardware/interfaces/keystore2 for details.
+ fn update_aad(&self, aad_input: &[u8]) -> Result<()> {
+ let mut outcome = self.check_active().context("In update_aad")?;
+ Self::check_input_length(aad_input).context("In update_aad")?;
+ self.touch();
+
+ let params = KeyParameterArray {
+ params: vec![KmParam {
+ tag: Tag::ASSOCIATED_DATA,
+ blob: aad_input.into(),
+ ..Default::default()
+ }],
+ };
+
+ let mut out_params: Option<KeyParameterArray> = None;
+ let mut output: Option<ByteArray> = None;
+
+ let km_op: Box<dyn IKeyMintOperation> =
+ self.km_op.get_interface().context("In update: Failed to get KeyMintOperation.")?;
+
+ self.update_outcome(
+ &mut *outcome,
+ map_km_error(km_op.update(
+ Some(¶ms),
+ None,
+ // TODO Get auth token from enforcement module if required.
+ None,
+ // TODO Get verification token from enforcement module if required.
+ None,
+ &mut out_params,
+ &mut output,
+ )),
+ )
+ .context("In update_aad: KeyMint::update failed.")?;
+
+ Ok(())
+ }
+
+ /// Implementation of `IKeystoreOperation::update`.
+ /// Refer to the AIDL spec at system/hardware/interfaces/keystore2 for details.
+ fn update(&self, input: &[u8]) -> Result<Option<Vec<u8>>> {
+ let mut outcome = self.check_active().context("In update")?;
+ Self::check_input_length(input).context("In update")?;
+ self.touch();
+
+ let mut out_params: Option<KeyParameterArray> = None;
+ let mut output: Option<ByteArray> = None;
+
+ let km_op: Box<dyn IKeyMintOperation> =
+ self.km_op.get_interface().context("In update: Failed to get KeyMintOperation.")?;
+
+ self.update_outcome(
+ &mut *outcome,
+ map_km_error(km_op.update(
+ None,
+ Some(input),
+ // TODO Get auth token from enforcement module if required.
+ None,
+ // TODO Get verification token from enforcement module if required.
+ None,
+ &mut out_params,
+ &mut output,
+ )),
+ )
+ .context("In update: KeyMint::update failed.")?;
+
+ match output {
+ Some(blob) => Ok(Some(blob.data)),
+ None => Ok(None),
+ }
+ }
+
+ /// Implementation of `IKeystoreOperation::finish`.
+ /// Refer to the AIDL spec at system/hardware/interfaces/keystore2 for details.
+ fn finish(&self, input: Option<&[u8]>, signature: Option<&[u8]>) -> Result<Option<Vec<u8>>> {
+ let mut outcome = self.check_active().context("In finish")?;
+ if let Some(input) = input {
+ Self::check_input_length(input).context("In finish")?;
+ }
+ self.touch();
+
+ let mut out_params: Option<KeyParameterArray> = None;
+
+ let km_op: Box<dyn IKeyMintOperation> =
+ self.km_op.get_interface().context("In finish: Failed to get KeyMintOperation.")?;
+
+ let output = self
+ .update_outcome(
+ &mut *outcome,
+ map_km_error(km_op.finish(
+ None,
+ input,
+ signature,
+ // TODO Get auth token from enforcement module if required.
+ None,
+ // TODO Get verification token from enforcement module if required.
+ None,
+ &mut out_params,
+ )),
+ )
+ .context("In finish: KeyMint::finish failed.")?;
+
+ // At this point the operation concluded successfully.
+ *outcome = Outcome::Success;
+
+ if output.is_empty() {
+ Ok(None)
+ } else {
+ Ok(Some(output))
+ }
+ }
+
+ /// Aborts the operation if it is active. IFF the operation is aborted the outcome is
+ /// set to `outcome`. `outcome` must reflect the reason for the abort. Since the operation
+ /// gets aborted `outcome` must not be `Operation::Success` or `Operation::Unknown`.
+ fn abort(&self, outcome: Outcome) -> Result<()> {
+ let mut locked_outcome = self.check_active().context("In abort")?;
+ *locked_outcome = outcome;
+ let km_op: Box<dyn IKeyMintOperation> =
+ self.km_op.get_interface().context("In abort: Failed to get KeyMintOperation.")?;
+
+ map_km_error(km_op.abort()).context("In abort: KeyMint::abort failed.")
+ }
+}
+
+impl Drop for Operation {
+ fn drop(&mut self) {
+ if let Ok(Outcome::Unknown) = self.outcome.get_mut() {
+ // If the operation was still active we call abort, setting
+ // the outcome to `Outcome::Dropped`
+ if let Err(e) = self.abort(Outcome::Dropped) {
+ log::error!("While dropping Operation: abort failed:\n {:?}", e);
+ }
+ }
+ }
+}
+
+/// The OperationDb holds weak references to all ongoing operations.
+/// Its main purpose is to facilitate operation pruning.
+#[derive(Debug, Default)]
+pub struct OperationDb {
+ // TODO replace Vec with WeakTable when the weak_table crate becomes
+ // available.
+ operations: Mutex<Vec<Weak<Operation>>>,
+}
+
+impl OperationDb {
+ /// Creates a new OperationDb.
+ pub fn new() -> Self {
+ Self { operations: Mutex::new(Vec::new()) }
+ }
+
+ /// Creates a new operation.
+ /// This function takes a KeyMint operation and an associated
+ /// owner uid and returns a new Operation wrapped in a `std::sync::Arc`.
+ pub fn create_operation(
+ &self,
+ km_op: Box<dyn IKeyMintOperation>,
+ owner: u32,
+ ) -> Arc<Operation> {
+ // We use unwrap because we don't allow code that can panic while locked.
+ let mut operations = self.operations.lock().expect("In create_operation.");
+
+ let mut index: usize = 0;
+ // First we iterate through the operation slots to try and find an unused
+ // slot. If we don't find one, we append the new entry instead.
+ match (*operations).iter_mut().find(|s| {
+ index += 1;
+ s.upgrade().is_none()
+ }) {
+ Some(free_slot) => {
+ let new_op = Arc::new(Operation::new(index - 1, km_op, owner));
+ *free_slot = Arc::downgrade(&new_op);
+ new_op
+ }
+ None => {
+ let new_op = Arc::new(Operation::new(operations.len(), km_op, owner));
+ operations.push(Arc::downgrade(&new_op));
+ new_op
+ }
+ }
+ }
+
+ fn get(&self, index: usize) -> Option<Arc<Operation>> {
+ self.operations.lock().expect("In OperationDb::get.").get(index).and_then(|op| op.upgrade())
+ }
+
+ /// Attempts to prune an operation.
+ ///
+ /// This function is used during operation creation, i.e., by
+ /// `KeystoreSecurityLevel::create_operation`, to try and free up an operation slot
+ /// if it got `ErrorCode::TOO_MANY_OPERATIONS` from the KeyMint backend. It is not
+ /// guaranteed that an operation slot is available after this call successfully
+ /// returned for various reasons. E.g., another thread may have snatched up the newly
+ /// available slot. Callers may have to call prune multiple times before they get a
+ /// free operation slot. Prune may also return `Err(Error::Rc(ResponseCode::BACKEND_BUSY))`
+ /// which indicates that no prunable operation was found.
+ ///
+ /// To find a suitable candidate we compute the malus for the caller and each existing
+ /// operation. The malus is the inverse of the pruning power (caller) or pruning
+ /// resistance (existing operation).
+ ///
+ /// The malus is based on the number of sibling operations and age. Sibling
+ /// operations are operations that have the same owner (UID).
+ ///
+ /// Every operation, existing or new, starts with a malus of 1. Every sibling
+ /// increases the malus by one. The age is the time since an operation was last touched.
+ /// It increases the malus by log6(<age in seconds> + 1) rounded down to the next
+ /// integer. So the malus increases stepwise after 5s, 35s, 215s, ...
+ /// Of two operations with the same malus the least recently used one is considered
+ /// weaker.
+ ///
+ /// For the caller to be able to prune an operation it must find an operation
+ /// with a malus higher than its own.
+ ///
+ /// The malus can be expressed as
+ /// ```
+ /// malus = 1 + no_of_siblings + floor(log6(age_in_seconds + 1))
+ /// ```
+ /// where the constant `1` accounts for the operation under consideration.
+ /// In reality we compute it as
+ /// ```
+ /// caller_malus = 1 + running_siblings
+ /// ```
+ /// because the new operation has no age and is not included in the `running_siblings`,
+ /// and
+ /// ```
+ /// running_malus = running_siblings + floor(log6(age_in_seconds + 1))
+ /// ```
+ /// because a running operation is included in the `running_siblings` and it has
+ /// an age.
+ ///
+ /// ## Example
+ /// A caller with no running operations has a malus of 1. Young (age < 5s) operations
+ /// also with no siblings have a malus of one and cannot be pruned by the caller.
+ /// We have to find an operation that has at least one sibling or is older than 5s.
+ ///
+ /// A caller with one running operation has a malus of 2. Now even young siblings
+ /// or single child aging (5s <= age < 35s) operations are off limit. An aging
+ /// sibling of two, however, would have a malus of 3 and would be fair game.
+ ///
+ /// ## Rationale
+ /// Due to the limitation of KeyMint operation slots, we cannot get around pruning or
+ /// a single app could easily DoS KeyMint.
+ /// Keystore 1.0 used to always prune the least recently used operation. This at least
+ /// guaranteed that new operations can always be started. With the increased usage
+ /// of Keystore we saw increased pruning activity which can lead to a livelock
+ /// situation in the worst case.
+ ///
+ /// With the new pruning strategy we want to provide well behaved clients with
+ /// progress assurances while punishing DoS attempts. As a result of this
+ /// strategy we can be in the situation where no operation can be pruned and the
+ /// creation of a new operation fails. This allows single child operations which
+ /// are frequently updated to complete, thereby breaking up livelock situations
+ /// and facilitating system wide progress.
+ ///
+ /// ## Update
+ /// We also allow callers to cannibalize their own sibling operations if no other
+ /// slot can be found. In this case the least recently used sibling is pruned.
+ pub fn prune(&self, caller: u32) -> Result<(), Error> {
+ loop {
+ // Maps the uid of the owner to the number of operations that owner has
+ // (running_siblings). More operations per owner lowers the pruning
+ // resistance of the operations of that owner. Whereas the number of
+ // ongoing operations of the caller lowers the pruning power of the caller.
+ let mut owners: HashMap<u32, u64> = HashMap::new();
+ let mut pruning_info: Vec<PruningInfo> = Vec::new();
+
+ let now = Instant::now();
+ self.operations
+ .lock()
+ .expect("In OperationDb::prune: Trying to lock self.operations.")
+ .iter()
+ .for_each(|op| {
+ if let Some(op) = op.upgrade() {
+ if let Some(p_info) = op.get_pruning_info() {
+ let owner = p_info.owner;
+ pruning_info.push(p_info);
+ // Count operations per owner.
+ *owners.entry(owner).or_insert(0) += 1;
+ }
+ }
+ });
+
+ let caller_malus = 1u64 + *owners.entry(caller).or_default();
+
+ // We iterate through all operations computing the malus and finding
+ // the candidate with the highest malus which must also be higher
+ // than the caller_malus.
+ struct CandidateInfo {
+ index: usize,
+ malus: u64,
+ last_usage: Instant,
+ age: Duration,
+ }
+ let mut oldest_caller_op: Option<CandidateInfo> = None;
+ let candidate = pruning_info.iter().fold(
+ None,
+ |acc: Option<CandidateInfo>, &PruningInfo { last_usage, owner, index }| {
+ // Compute the age of the current operation.
+ let age = now
+ .checked_duration_since(last_usage)
+ .unwrap_or_else(|| Duration::new(0, 0));
+
+ // Find the least recently used sibling as an alternative pruning candidate.
+ if owner == caller {
+ if let Some(CandidateInfo { age: a, .. }) = oldest_caller_op {
+ if age > a {
+ oldest_caller_op =
+ Some(CandidateInfo { index, malus: 0, last_usage, age });
+ }
+ } else {
+ oldest_caller_op =
+ Some(CandidateInfo { index, malus: 0, last_usage, age });
+ }
+ }
+
+ // Compute the malus of the current operation.
+ // Expect safety: Every owner in pruning_info was counted in
+ // the owners map. So this unwrap cannot panic.
+ let malus = *owners
+ .get(&owner)
+ .expect("This is odd. We should have counted every owner in pruning_info.")
+ + ((age.as_secs() + 1) as f64).log(6.0).floor() as u64;
+
+ // Now check if the current operation is a viable/better candidate
+ // the one currently stored in the accumulator.
+ match acc {
+ // First we have to find any operation that is prunable by the caller.
+ None => {
+ if caller_malus < malus {
+ Some(CandidateInfo { index, malus, last_usage, age })
+ } else {
+ None
+ }
+ }
+ // If we have found one we look for the operation with the worst score.
+ // If there is a tie, the older operation is considered weaker.
+ Some(CandidateInfo { index: i, malus: m, last_usage: l, age: a }) => {
+ if malus > m || (malus == m && age > a) {
+ Some(CandidateInfo { index, malus, last_usage, age })
+ } else {
+ Some(CandidateInfo { index: i, malus: m, last_usage: l, age: a })
+ }
+ }
+ }
+ },
+ );
+
+ // If we did not find a suitable candidate we may cannibalize our oldest sibling.
+ let candidate = candidate.or(oldest_caller_op);
+
+ match candidate {
+ Some(CandidateInfo { index, malus: _, last_usage, age: _ }) => {
+ match self.get(index) {
+ Some(op) => {
+ match op.prune(last_usage) {
+ // We successfully freed up a slot.
+ Ok(()) => break Ok(()),
+ // This means the operation we tried to prune was on its way
+ // out. It also means that the slot it had occupied was freed up.
+ Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)) => break Ok(()),
+ // This means the operation we tried to prune was currently
+ // servicing a request. There are two options.
+ // * Assume that it was touched, which means that its
+ // pruning resistance increased. In that case we have
+ // to start over and find another candidate.
+ // * Assume that the operation is transitioning to end-of-life.
+ // which means that we got a free slot for free.
+ // If we assume the first but the second is true, we prune
+ // a good operation without need (aggressive approach).
+ // If we assume the second but the first is true, our
+ // caller will attempt to create a new KeyMint operation,
+ // fail with `ErrorCode::TOO_MANY_OPERATIONS`, and call
+ // us again (conservative approach).
+ Err(Error::Rc(ResponseCode::OPERATION_BUSY)) => {
+ // We choose the conservative approach, because
+ // every needlessly pruned operation can impact
+ // the user experience.
+ // To switch to the aggressive approach replace
+ // the following line with `continue`.
+ break Ok(());
+ }
+
+ // The candidate may have been touched so the score
+ // has changed since our evaluation.
+ _ => continue,
+ }
+ }
+ // This index does not exist any more. The operation
+ // in this slot was dropped. Good news, a slot
+ // has freed up.
+ None => break Ok(()),
+ }
+ }
+ // We did not get a pruning candidate.
+ None => break Err(Error::Rc(ResponseCode::BACKEND_BUSY)),
+ }
+ }
+ }
+}
+
+/// Implementation of IKeystoreOperation.
+pub struct KeystoreOperation {
+ operation: Mutex<Option<Arc<Operation>>>,
+}
+
+impl KeystoreOperation {
+ /// Creates a new operation instance wrapped in a
+ /// BnKeystoreOperation proxy object. It also
+ /// calls `IBinder::set_requesting_sid` on the new interface, because
+ /// we need it for checking Keystore permissions.
+ pub fn new_native_binder(operation: Arc<Operation>) -> impl IKeystoreOperation + Send {
+ let result =
+ BnKeystoreOperation::new_binder(Self { operation: Mutex::new(Some(operation)) });
+ result.as_binder().set_requesting_sid(true);
+ result
+ }
+
+ /// Grabs the outer operation mutex and calls `f` on the locked operation.
+ /// The function also deletes the operation if it returns with an error or if
+ /// `delete_op` is true.
+ fn with_locked_operation<T, F>(&self, f: F, delete_op: bool) -> Result<T>
+ where
+ for<'a> F: FnOnce(&'a Operation) -> Result<T>,
+ {
+ let mut delete_op: bool = delete_op;
+ match self.operation.try_lock() {
+ Ok(mut mutex_guard) => {
+ let result = match &*mutex_guard {
+ Some(op) => {
+ let result = f(&*op);
+ // Any error here means we can discard the operation.
+ if result.is_err() {
+ delete_op = true;
+ }
+ result
+ }
+ None => Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE))
+ .context("In KeystoreOperation::with_locked_operation"),
+ };
+
+ if delete_op {
+ // We give up our reference to the Operation, thereby freeing up our
+ // internal resources and ending the wrapped KeyMint operation.
+ // This KeystoreOperation object will still be owned by an SpIBinder
+ // until the client drops its remote reference.
+ *mutex_guard = None;
+ }
+ result
+ }
+ Err(_) => Err(Error::Rc(ResponseCode::OPERATION_BUSY))
+ .context("In KeystoreOperation::with_locked_operation"),
+ }
+ }
+}
+
+impl binder::Interface for KeystoreOperation {}
+
+impl IKeystoreOperation for KeystoreOperation {
+ fn updateAad(&self, aad_input: &[u8]) -> binder::public_api::Result<()> {
+ map_or_log_err(
+ self.with_locked_operation(
+ |op| op.update_aad(aad_input).context("In KeystoreOperation::updateAad"),
+ false,
+ ),
+ Ok,
+ )
+ }
+
+ fn update(&self, input: &[u8]) -> binder::public_api::Result<Option<Vec<u8>>> {
+ map_or_log_err(
+ self.with_locked_operation(
+ |op| op.update(input).context("In KeystoreOperation::update"),
+ false,
+ ),
+ Ok,
+ )
+ }
+ fn finish(
+ &self,
+ input: Option<&[u8]>,
+ signature: Option<&[u8]>,
+ ) -> binder::public_api::Result<Option<Vec<u8>>> {
+ map_or_log_err(
+ self.with_locked_operation(
+ |op| op.finish(input, signature).context("In KeystoreOperation::finish"),
+ true,
+ ),
+ Ok,
+ )
+ }
+
+ fn abort(&self) -> binder::public_api::Result<()> {
+ map_or_log_err(
+ self.with_locked_operation(
+ |op| op.abort(Outcome::Abort).context("In KeystoreOperation::abort"),
+ true,
+ ),
+ Ok,
+ )
+ }
+}
diff --git a/keystore2/src/permission.rs b/keystore2/src/permission.rs
index 1880623..0917256 100644
--- a/keystore2/src/permission.rs
+++ b/keystore2/src/permission.rs
@@ -18,9 +18,9 @@
//! It also provides KeystorePerm and KeyPerm as convenience wrappers for the SELinux permission
//! defined by keystore2 and keystore2_key respectively.
-use android_security_keystore2::aidl::android::security::keystore2::KeyPermission;
-
-use android_security_keystore2::aidl::android::security::keystore2::KeyDescriptor::KeyDescriptor;
+use android_system_keystore2::aidl::android::system::keystore2::{
+ Domain::Domain, KeyDescriptor::KeyDescriptor, KeyPermission::KeyPermission,
+};
use std::cmp::PartialEq;
use std::convert::From;
@@ -137,10 +137,10 @@
=>
{
$(#[$m])*
- pub struct $name(pub $aidl_name::$aidl_name);
+ pub struct $name(pub $aidl_name);
- impl From<$aidl_name::$aidl_name> for $name {
- fn from (p: $aidl_name::$aidl_name) -> Self {
+ impl From<$aidl_name> for $name {
+ fn from (p: $aidl_name) -> Self {
match p {
$aidl_name::$def_name => Self($aidl_name::$def_name),
$($aidl_name::$element_name => Self($aidl_name::$element_name),)*
@@ -149,8 +149,8 @@
}
}
- impl Into<$aidl_name::$aidl_name> for $name {
- fn into(self) -> $aidl_name::$aidl_name {
+ impl Into<$aidl_name> for $name {
+ fn into(self) -> $aidl_name {
self.0
}
}
@@ -192,17 +192,17 @@
/// KeyPerm::get_info().to_selinux());
/// ```
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
- KeyPerm from KeyPermission with default (None, none) {
- Delete, selinux name: delete;
- GenUniqueId, selinux name: gen_unique_id;
- GetInfo, selinux name: get_info;
- Grant, selinux name: grant;
- ManageBlob, selinux name: manage_blob;
- Rebind, selinux name: rebind;
- ReqForcedOp, selinux name: req_forced_op;
- Update, selinux name: update;
- Use, selinux name: use;
- UseDevId, selinux name: use_dev_id;
+ KeyPerm from KeyPermission with default (NONE, none) {
+ DELETE, selinux name: delete;
+ GEN_UNIQUE_ID, selinux name: gen_unique_id;
+ GET_INFO, selinux name: get_info;
+ GRANT, selinux name: grant;
+ MANAGE_BLOB, selinux name: manage_blob;
+ REBIND, selinux name: rebind;
+ REQ_FORCED_OP, selinux name: req_forced_op;
+ UPDATE, selinux name: update;
+ USE, selinux name: use;
+ USE_DEV_ID, selinux name: use_dev_id;
}
);
@@ -356,7 +356,7 @@
let p = self.vec.0 & (1 << self.pos);
self.pos += 1;
if p != 0 {
- return Some(KeyPerm::from(p));
+ return Some(KeyPerm::from(KeyPermission(p)));
}
}
}
@@ -365,7 +365,7 @@
impl From<KeyPerm> for KeyPermSet {
fn from(p: KeyPerm) -> Self {
- Self(p.0 as i32)
+ Self((p.0).0 as i32)
}
}
@@ -400,7 +400,7 @@
macro_rules! key_perm_set {
() => { KeyPermSet(0) };
($head:expr $(, $tail:expr)* $(,)?) => {
- KeyPermSet($head.0 as i32 $(| $tail.0 as i32)*)
+ KeyPermSet(($head.0).0 $(| ($tail.0).0)*)
};
}
@@ -429,8 +429,8 @@
/// Attempts to grant the grant permission are always denied.
///
/// The only viable target domains are
-/// * `Domain::App` in which case u:r:keystore:s0 is used as target context and
-/// * `Domain::SELinux` in which case the `key.namespace_` parameter is looked up in
+/// * `Domain::APP` in which case u:r:keystore:s0 is used as target context and
+/// * `Domain::SELINUX` in which case the `key.nspace` parameter is looked up in
/// SELinux keystore key backend, and the result is used
/// as target context.
pub fn check_grant_permission(
@@ -438,12 +438,10 @@
access_vec: KeyPermSet,
key: &KeyDescriptor,
) -> anyhow::Result<()> {
- use android_security_keystore2::aidl::android::security::keystore2::Domain;
-
let target_context = match key.domain {
- Domain::App => getcon().context("check_grant_permission: getcon failed.")?,
- Domain::SELinux => lookup_keystore2_key_context(key.namespace_)
- .context("check_grant_permission: Domain::SELinux: Failed to lookup namespace.")?,
+ Domain::APP => getcon().context("check_grant_permission: getcon failed.")?,
+ Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
+ .context("check_grant_permission: Domain::SELINUX: Failed to lookup namespace.")?,
_ => return Err(KsError::sys()).context(format!("Cannot grant {:?}.", key.domain)),
};
@@ -469,19 +467,19 @@
/// descriptor `key` in the security class `keystore2_key`.
///
/// The behavior differs slightly depending on the selected target domain:
-/// * `Domain::App` u:r:keystore:s0 is used as target context.
-/// * `Domain::SELinux` `key.namespace_` parameter is looked up in the SELinux keystore key
+/// * `Domain::APP` u:r:keystore:s0 is used as target context.
+/// * `Domain::SELINUX` `key.nspace` parameter is looked up in the SELinux keystore key
/// backend, and the result is used as target context.
-/// * `Domain::Blob` Same as SELinux but the "manage_blob" permission is always checked additionally
+/// * `Domain::BLOB` Same as SELinux but the "manage_blob" permission is always checked additionally
/// to the one supplied in `perm`.
-/// * `Domain::Grant` Does not use selinux::check_access. Instead the `access_vector`
+/// * `Domain::GRANT` Does not use selinux::check_access. Instead the `access_vector`
/// parameter is queried for permission, which must be supplied in this case.
///
/// ## Return values.
/// * Ok(()) If the requested permissions were granted.
/// * Err(selinux::Error::perm()) If the requested permissions were denied.
-/// * Err(KsError::sys()) This error is produced if `Domain::Grant` is selected but no `access_vec`
-/// was supplied. It is also produced if `Domain::KeyId` was selected, and
+/// * Err(KsError::sys()) This error is produced if `Domain::GRANT` is selected but no `access_vec`
+/// was supplied. It is also produced if `Domain::KEY_ID` was selected, and
/// on various unexpected backend failures.
pub fn check_key_permission(
caller_ctx: &CStr,
@@ -489,14 +487,12 @@
key: &KeyDescriptor,
access_vector: &Option<KeyPermSet>,
) -> anyhow::Result<()> {
- use android_security_keystore2::aidl::android::security::keystore2::Domain;
-
let target_context = match key.domain {
// apps get the default keystore context
- Domain::App => getcon().context("check_key_permission: getcon failed.")?,
- Domain::SELinux => lookup_keystore2_key_context(key.namespace_)
- .context("check_key_permission: Domain::SELinux: Failed to lookup namespace.")?,
- Domain::Grant => {
+ Domain::APP => getcon().context("check_key_permission: getcon failed.")?,
+ Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
+ .context("check_key_permission: Domain::SELINUX: Failed to lookup namespace.")?,
+ Domain::GRANT => {
match access_vector {
Some(pv) => {
if pv.includes(perm) {
@@ -509,20 +505,20 @@
None => {
// If DOMAIN_GRANT was selected an access vector must be supplied.
return Err(KsError::sys()).context(
- "Cannot check permission for Domain::Grant without access vector.",
+ "Cannot check permission for Domain::GRANT without access vector.",
);
}
}
}
- Domain::KeyId => {
- // We should never be called with `Domain::KeyId. The database
- // lookup should have converted this into one of `Domain::App`
- // or `Domain::SELinux`.
- return Err(KsError::sys()).context("Cannot check permission for Domain::KeyId.");
+ Domain::KEY_ID => {
+ // We should never be called with `Domain::KEY_ID. The database
+ // lookup should have converted this into one of `Domain::APP`
+ // or `Domain::SELINUX`.
+ return Err(KsError::sys()).context("Cannot check permission for Domain::KEY_ID.");
}
- Domain::Blob => {
- let tctx = lookup_keystore2_key_context(key.namespace_)
- .context("Domain::Blob: Failed to lookup namespace.")?;
+ Domain::BLOB => {
+ let tctx = lookup_keystore2_key_context(key.nspace)
+ .context("Domain::BLOB: Failed to lookup namespace.")?;
// If DOMAIN_KEY_BLOB was specified, we check for the "manage_blob"
// permission in addition to the requested permission.
selinux::check_access(
@@ -536,7 +532,7 @@
}
_ => {
return Err(KsError::sys())
- .context(format!("Unknown domain value: \"{}\".", key.domain))
+ .context(format!("Unknown domain value: \"{:?}\".", key.domain))
}
};
@@ -650,8 +646,7 @@
fn check_grant_permission_app() -> Result<()> {
let system_server_ctx = Context::new("u:r:system_server:s0")?;
let shell_ctx = Context::new("u:r:shell:s0")?;
- use android_security_keystore2::aidl::android::security::keystore2::Domain;
- let key = KeyDescriptor { domain: Domain::App, namespace_: 0, alias: None, blob: None };
+ let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
assert!(check_grant_permission(&system_server_ctx, NOT_GRANT_PERMS, &key).is_ok());
// attempts to grant the grant permission must always fail even when privileged.
@@ -667,11 +662,10 @@
#[test]
fn check_grant_permission_selinux() -> Result<()> {
- use android_security_keystore2::aidl::android::security::keystore2::Domain;
let (sctx, namespace, is_su) = check_context()?;
let key = KeyDescriptor {
- domain: Domain::SELinux,
- namespace_: namespace as i64,
+ domain: Domain::SELINUX,
+ nspace: namespace as i64,
alias: None,
blob: None,
};
@@ -688,8 +682,7 @@
#[test]
fn check_key_permission_domain_grant() -> Result<()> {
- use android_security_keystore2::aidl::android::security::keystore2::Domain;
- let key = KeyDescriptor { domain: Domain::Grant, namespace_: 0, alias: None, blob: None };
+ let key = KeyDescriptor { domain: Domain::GRANT, nspace: 0, alias: None, blob: None };
assert_perm_failed!(check_key_permission(
&selinux::Context::new("ignored").unwrap(),
@@ -711,9 +704,8 @@
let system_server_ctx = Context::new("u:r:system_server:s0")?;
let shell_ctx = Context::new("u:r:shell:s0")?;
let gmscore_app = Context::new("u:r:gmscore_app:s0")?;
- use android_security_keystore2::aidl::android::security::keystore2::Domain;
- let key = KeyDescriptor { domain: Domain::App, namespace_: 0, alias: None, blob: None };
+ let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
assert!(check_key_permission(&system_server_ctx, KeyPerm::use_(), &key, &None).is_ok());
assert!(check_key_permission(&system_server_ctx, KeyPerm::delete(), &key, &None).is_ok());
@@ -752,11 +744,10 @@
#[test]
fn check_key_permission_domain_selinux() -> Result<()> {
- use android_security_keystore2::aidl::android::security::keystore2::Domain;
let (sctx, namespace, is_su) = check_context()?;
let key = KeyDescriptor {
- domain: Domain::SELinux,
- namespace_: namespace as i64,
+ domain: Domain::SELINUX,
+ nspace: namespace as i64,
alias: None,
blob: None,
};
@@ -789,11 +780,10 @@
#[test]
fn check_key_permission_domain_blob() -> Result<()> {
- use android_security_keystore2::aidl::android::security::keystore2::Domain;
let (sctx, namespace, is_su) = check_context()?;
let key = KeyDescriptor {
- domain: Domain::Blob,
- namespace_: namespace as i64,
+ domain: Domain::BLOB,
+ nspace: namespace as i64,
alias: None,
blob: None,
};
@@ -808,8 +798,7 @@
#[test]
fn check_key_permission_domain_key_id() -> Result<()> {
- use android_security_keystore2::aidl::android::security::keystore2::Domain;
- let key = KeyDescriptor { domain: Domain::KeyId, namespace_: 0, alias: None, blob: None };
+ let key = KeyDescriptor { domain: Domain::KEY_ID, nspace: 0, alias: None, blob: None };
assert_eq!(
Some(&KsError::sys()),
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
new file mode 100644
index 0000000..24a2e99
--- /dev/null
+++ b/keystore2/src/security_level.rs
@@ -0,0 +1,590 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#![allow(unused_variables)]
+
+//! This crate implements the IKeystoreSecurityLevel interface.
+
+use android_hardware_keymint::aidl::android::hardware::keymint::{
+ Algorithm::Algorithm, ByteArray::ByteArray, Certificate::Certificate as KmCertificate,
+ HardwareAuthenticatorType::HardwareAuthenticatorType, IKeyMintDevice::IKeyMintDevice,
+ KeyCharacteristics::KeyCharacteristics, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
+ KeyPurpose::KeyPurpose, SecurityLevel::SecurityLevel, Tag::Tag,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+ AuthenticatorSpec::AuthenticatorSpec, CreateOperationResponse::CreateOperationResponse,
+ Domain::Domain, IKeystoreOperation::IKeystoreOperation,
+ IKeystoreSecurityLevel::BnKeystoreSecurityLevel,
+ IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
+ KeyMetadata::KeyMetadata, KeyParameters::KeyParameters,
+};
+
+use crate::permission::KeyPerm;
+use crate::utils::{check_key_permission, Asp};
+use crate::{database::KeyIdGuard, globals::DB};
+use crate::{
+ database::{KeyEntry, KeyEntryLoadBits, SubComponentType},
+ operation::KeystoreOperation,
+ operation::OperationDb,
+};
+use crate::{
+ error::{self, map_km_error, map_or_log_err, Error, ErrorCode},
+ utils::key_characteristics_to_internal,
+};
+use anyhow::{anyhow, Context, Result};
+use binder::{IBinder, Interface, ThreadState};
+
+/// Implementation of the IKeystoreSecurityLevel Interface.
+pub struct KeystoreSecurityLevel {
+ security_level: SecurityLevel,
+ keymint: Asp,
+ operation_db: OperationDb,
+}
+
+static KEYMINT_SERVICE_NAME: &str = "android.hardware.keymint.IKeyMintDevice";
+
+// Blob of 32 zeroes used as empty masking key.
+static ZERO_BLOB_32: &[u8] = &[0; 32];
+
+impl KeystoreSecurityLevel {
+ /// Creates a new security level instance wrapped in a
+ /// BnKeystoreSecurityLevel proxy object. It also
+ /// calls `IBinder::set_requesting_sid` on the new interface, because
+ /// we need it for checking keystore permissions.
+ pub fn new_native_binder(
+ security_level: SecurityLevel,
+ ) -> Result<impl IKeystoreSecurityLevel + Send> {
+ let service_name = format!("{}/default", KEYMINT_SERVICE_NAME);
+ let keymint: Box<dyn IKeyMintDevice> =
+ binder::get_interface(&service_name).map_err(|e| {
+ anyhow!(format!(
+ "Could not get KeyMint instance: {} failed with error code {:?}",
+ service_name, e
+ ))
+ })?;
+
+ let result = BnKeystoreSecurityLevel::new_binder(Self {
+ security_level,
+ keymint: Asp::new(keymint.as_binder()),
+ operation_db: OperationDb::new(),
+ });
+ result.as_binder().set_requesting_sid(true);
+ Ok(result)
+ }
+
+ fn store_new_key(
+ &self,
+ key: KeyDescriptor,
+ key_characteristics: KeyCharacteristics,
+ km_cert_chain: Option<Vec<KmCertificate>>,
+ blob: ByteArray,
+ ) -> Result<KeyMetadata> {
+ let (cert, cert_chain): (Option<Vec<u8>>, Option<Vec<u8>>) = match km_cert_chain {
+ Some(mut chain) => (
+ match chain.len() {
+ 0 => None,
+ _ => Some(chain.remove(0).encodedCertificate),
+ },
+ match chain.len() {
+ 0 => None,
+ _ => Some(
+ chain
+ .iter()
+ .map(|c| c.encodedCertificate.iter())
+ .flatten()
+ .copied()
+ .collect(),
+ ),
+ },
+ ),
+ None => (None, None),
+ };
+
+ let key_parameters =
+ key_characteristics_to_internal(key_characteristics, self.security_level);
+
+ let key = match key.domain {
+ Domain::BLOB => {
+ KeyDescriptor { domain: Domain::BLOB, blob: Some(blob.data), ..Default::default() }
+ }
+ _ => DB
+ .with(|db| {
+ let mut db = db.borrow_mut();
+ let key_id = db
+ .create_key_entry(key.domain, key.nspace)
+ .context("Trying to create a key entry.")?;
+ db.insert_blob(
+ &key_id,
+ SubComponentType::KM_BLOB,
+ &blob.data,
+ self.security_level,
+ )
+ .context("Trying to insert km blob.")?;
+ if let Some(c) = &cert {
+ db.insert_blob(&key_id, SubComponentType::CERT, c, self.security_level)
+ .context("Trying to insert cert blob.")?;
+ }
+ if let Some(c) = &cert_chain {
+ db.insert_blob(
+ &key_id,
+ SubComponentType::CERT_CHAIN,
+ c,
+ self.security_level,
+ )
+ .context("Trying to insert cert chain blob.")?;
+ }
+ db.insert_keyparameter(&key_id, &key_parameters)
+ .context("Trying to insert key parameters.")?;
+ match &key.alias {
+ Some(alias) => db
+ .rebind_alias(&key_id, alias, key.domain, key.nspace)
+ .context("Failed to rebind alias.")?,
+ None => {
+ return Err(error::Error::sys()).context(
+ "Alias must be specified. (This should have been checked earlier.)",
+ )
+ }
+ }
+ Ok(KeyDescriptor {
+ domain: Domain::KEY_ID,
+ nspace: key_id.id(),
+ ..Default::default()
+ })
+ })
+ .context("In store_new_key.")?,
+ };
+
+ Ok(KeyMetadata {
+ key,
+ keySecurityLevel: self.security_level,
+ certificate: cert,
+ certificateChain: cert_chain,
+ authorizations: crate::utils::key_parameters_to_authorizations(key_parameters),
+ ..Default::default()
+ })
+ }
+
+ fn create_operation(
+ &self,
+ key: &KeyDescriptor,
+ operation_parameters: &[KeyParameter],
+ forced: bool,
+ ) -> Result<CreateOperationResponse> {
+ let caller_uid = ThreadState::get_calling_uid();
+ // We use `scoping_blob` to extend the life cycle of the blob loaded from the database,
+ // so that we can use it by reference like the blob provided by the key descriptor.
+ // Otherwise, we would have to clone the blob from the key descriptor.
+ let scoping_blob: Vec<u8>;
+ let (km_blob, key_id_guard) = match key.domain {
+ Domain::BLOB => {
+ check_key_permission(KeyPerm::use_(), key, &None)
+ .context("In create_operation: checking use permission for Domain::BLOB.")?;
+ (
+ match &key.blob {
+ Some(blob) => blob,
+ None => {
+ return Err(Error::sys()).context(concat!(
+ "In create_operation: Key blob must be specified when",
+ " using Domain::BLOB."
+ ))
+ }
+ },
+ None,
+ )
+ }
+ _ => {
+ let (key_id_guard, mut key_entry) = DB
+ .with::<_, Result<(KeyIdGuard, KeyEntry)>>(|db| {
+ db.borrow_mut().load_key_entry(
+ key.clone(),
+ KeyEntryLoadBits::KM,
+ caller_uid,
+ |k, av| check_key_permission(KeyPerm::use_(), k, &av),
+ )
+ })
+ .context("In create_operation: Failed to load key blob.")?;
+ scoping_blob = match key_entry.take_km_blob() {
+ Some(blob) => blob,
+ None => {
+ return Err(Error::sys()).context(concat!(
+ "In create_operation: Successfully loaded key entry,",
+ " but KM blob was missing."
+ ))
+ }
+ };
+ (&scoping_blob, Some(key_id_guard))
+ }
+ };
+
+ // TODO Authorize begin operation.
+ // Check if we need an authorization token.
+ // Lookup authorization token and request VerificationToken if required.
+
+ let purpose = operation_parameters.iter().find(|p| p.tag == Tag::PURPOSE).map_or(
+ Err(Error::Km(ErrorCode::INVALID_ARGUMENT))
+ .context("In create_operation: No operation purpose specified."),
+ |kp| Ok(KeyPurpose(kp.integer)),
+ )?;
+
+ let km_dev: Box<dyn IKeyMintDevice> = self
+ .keymint
+ .get_interface()
+ .context("In create_operation: Failed to get KeyMint device")?;
+
+ let (begin_result, upgraded_blob) = self
+ .upgrade_keyblob_if_required_with(
+ &*km_dev,
+ key_id_guard,
+ &km_blob,
+ &operation_parameters,
+ |blob| loop {
+ match map_km_error(km_dev.begin(
+ purpose,
+ blob,
+ &operation_parameters,
+ &Default::default(),
+ )) {
+ Err(Error::Km(ErrorCode::TOO_MANY_OPERATIONS)) => {
+ self.operation_db.prune(caller_uid)?;
+ continue;
+ }
+ v => return v,
+ }
+ },
+ )
+ .context("In create_operation: Failed to begin operation.")?;
+
+ let operation = match begin_result.operation {
+ Some(km_op) => self.operation_db.create_operation(km_op, caller_uid),
+ None => return Err(Error::sys()).context("In create_operation: Begin operation returned successfully, but did not return a valid operation."),
+ };
+
+ let op_binder: Box<dyn IKeystoreOperation> =
+ KeystoreOperation::new_native_binder(operation)
+ .as_binder()
+ .into_interface()
+ .context("In create_operation: Failed to create IKeystoreOperation.")?;
+
+ // TODO we need to the enforcement module to determine if we need to return the challenge.
+ // We return None for now because we don't support auth bound keys yet.
+ Ok(CreateOperationResponse {
+ iOperation: Some(op_binder),
+ operationChallenge: None,
+ parameters: match begin_result.params.len() {
+ 0 => None,
+ _ => Some(KeyParameters { keyParameter: begin_result.params }),
+ },
+ })
+ }
+
+ fn generate_key(
+ &self,
+ key: &KeyDescriptor,
+ attestation_key: Option<&KeyDescriptor>,
+ params: &[KeyParameter],
+ flags: i32,
+ entropy: &[u8],
+ ) -> Result<KeyMetadata> {
+ if key.domain != Domain::BLOB && key.alias.is_none() {
+ return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+ .context("In generate_key: Alias must be specified");
+ }
+
+ let key = match key.domain {
+ Domain::APP => KeyDescriptor {
+ domain: key.domain,
+ nspace: ThreadState::get_calling_uid() as i64,
+ alias: key.alias.clone(),
+ blob: None,
+ },
+ _ => key.clone(),
+ };
+
+ // generate_key requires the rebind permission.
+ check_key_permission(KeyPerm::rebind(), &key, &None).context("In generate_key.")?;
+
+ let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
+ map_km_error(km_dev.addRngEntropy(entropy))?;
+ let mut blob: ByteArray = Default::default();
+ let mut key_characteristics: KeyCharacteristics = Default::default();
+ let mut certificate_chain: Vec<KmCertificate> = Default::default();
+ map_km_error(km_dev.generateKey(
+ ¶ms,
+ &mut blob,
+ &mut key_characteristics,
+ &mut certificate_chain,
+ ))?;
+
+ self.store_new_key(key, key_characteristics, Some(certificate_chain), blob)
+ .context("In generate_key.")
+ }
+
+ fn import_key(
+ &self,
+ key: &KeyDescriptor,
+ attestation_key: Option<&KeyDescriptor>,
+ params: &[KeyParameter],
+ flags: i32,
+ key_data: &[u8],
+ ) -> Result<KeyMetadata> {
+ if key.domain != Domain::BLOB && key.alias.is_none() {
+ return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+ .context("In import_key: Alias must be specified");
+ }
+
+ let key = match key.domain {
+ Domain::APP => KeyDescriptor {
+ domain: key.domain,
+ nspace: ThreadState::get_calling_uid() as i64,
+ alias: key.alias.clone(),
+ blob: None,
+ },
+ _ => key.clone(),
+ };
+
+ // import_key requires the rebind permission.
+ check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_key.")?;
+
+ let mut blob: ByteArray = Default::default();
+ let mut key_characteristics: KeyCharacteristics = Default::default();
+ let mut certificate_chain: Vec<KmCertificate> = Default::default();
+
+ let format = params
+ .iter()
+ .find(|p| p.tag == Tag::ALGORITHM)
+ .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+ .context("No KeyParameter 'Algorithm'.")
+ .and_then(|p| match Algorithm(p.integer) {
+ Algorithm::AES | Algorithm::HMAC | Algorithm::TRIPLE_DES => Ok(KeyFormat::RAW),
+ Algorithm::RSA | Algorithm::EC => Ok(KeyFormat::PKCS8),
+ algorithm => Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+ .context(format!("Unknown Algorithm {:?}.", algorithm)),
+ })
+ .context("In import_key.")?;
+
+ let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
+ map_km_error(km_dev.importKey(
+ ¶ms,
+ format,
+ key_data,
+ &mut blob,
+ &mut key_characteristics,
+ &mut certificate_chain,
+ ))?;
+
+ self.store_new_key(key, key_characteristics, Some(certificate_chain), blob)
+ .context("In import_key.")
+ }
+
+ fn import_wrapped_key(
+ &self,
+ key: &KeyDescriptor,
+ wrapping_key: &KeyDescriptor,
+ masking_key: Option<&[u8]>,
+ params: &[KeyParameter],
+ authenticators: &[AuthenticatorSpec],
+ ) -> Result<KeyMetadata> {
+ if key.domain != Domain::BLOB && key.alias.is_none() {
+ return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+ .context("In import_wrapped_key: Alias must be specified.");
+ }
+
+ if wrapping_key.domain == Domain::BLOB {
+ return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT)).context(
+ "In import_wrapped_key: Import wrapped key not supported for self managed blobs.",
+ );
+ }
+
+ let wrapped_data = match &key.blob {
+ Some(d) => d,
+ None => {
+ return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT)).context(
+ "In import_wrapped_key: Blob must be specified and hold wrapped key data.",
+ )
+ }
+ };
+
+ let key = match key.domain {
+ Domain::APP => KeyDescriptor {
+ domain: key.domain,
+ nspace: ThreadState::get_calling_uid() as i64,
+ alias: key.alias.clone(),
+ blob: None,
+ },
+ _ => key.clone(),
+ };
+
+ // import_wrapped_key requires the rebind permission for the new key.
+ check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_wrapped_key.")?;
+
+ let (wrapping_key_id_guard, wrapping_key_entry) = DB
+ .with(|db| {
+ db.borrow_mut().load_key_entry(
+ wrapping_key.clone(),
+ KeyEntryLoadBits::KM,
+ ThreadState::get_calling_uid(),
+ |k, av| check_key_permission(KeyPerm::use_(), k, &av),
+ )
+ })
+ .context("Failed to load wrapping key.")?;
+ let wrapping_key_blob = match wrapping_key_entry.km_blob() {
+ Some(blob) => blob,
+ None => {
+ return Err(error::Error::sys()).context(concat!(
+ "No km_blob after successfully loading key.",
+ " This should never happen."
+ ))
+ }
+ };
+
+ // km_dev.importWrappedKey does not return a certificate chain.
+ // TODO Do we assume that all wrapped keys are symmetric?
+ // let certificate_chain: Vec<KmCertificate> = Default::default();
+
+ let pw_sid = authenticators
+ .iter()
+ .find_map(|a| match a.authenticatorType {
+ HardwareAuthenticatorType::PASSWORD => Some(a.authenticatorId),
+ _ => None,
+ })
+ .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+ .context("A password authenticator SID must be specified.")?;
+
+ let fp_sid = authenticators
+ .iter()
+ .find_map(|a| match a.authenticatorType {
+ HardwareAuthenticatorType::FINGERPRINT => Some(a.authenticatorId),
+ _ => None,
+ })
+ .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+ .context("A fingerprint authenticator SID must be specified.")?;
+
+ let masking_key = masking_key.unwrap_or(ZERO_BLOB_32);
+
+ let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
+ let ((blob, key_characteristics), _) = self.upgrade_keyblob_if_required_with(
+ &*km_dev,
+ Some(wrapping_key_id_guard),
+ wrapping_key_blob,
+ &[],
+ |wrapping_blob| {
+ let mut blob: ByteArray = Default::default();
+ let mut key_characteristics: KeyCharacteristics = Default::default();
+ map_km_error(km_dev.importWrappedKey(
+ wrapped_data,
+ wrapping_key_blob,
+ masking_key,
+ ¶ms,
+ pw_sid,
+ fp_sid,
+ &mut blob,
+ &mut key_characteristics,
+ ))?;
+ Ok((blob, key_characteristics))
+ },
+ )?;
+
+ self.store_new_key(key, key_characteristics, None, blob).context("In import_wrapped_key.")
+ }
+
+ fn upgrade_keyblob_if_required_with<T, F>(
+ &self,
+ km_dev: &dyn IKeyMintDevice,
+ key_id_guard: Option<KeyIdGuard>,
+ blob: &[u8],
+ params: &[KeyParameter],
+ f: F,
+ ) -> Result<(T, Option<Vec<u8>>)>
+ where
+ F: Fn(&[u8]) -> Result<T, Error>,
+ {
+ match f(blob) {
+ Err(Error::Km(ErrorCode::KEY_REQUIRES_UPGRADE)) => {
+ let upgraded_blob = map_km_error(km_dev.upgradeKey(blob, params))
+ .context("In upgrade_keyblob_if_required_with: Upgrade failed.")?;
+ key_id_guard.map_or(Ok(()), |key_id_guard| {
+ DB.with(|db| {
+ db.borrow_mut().insert_blob(
+ &key_id_guard,
+ SubComponentType::KM_BLOB,
+ &upgraded_blob,
+ self.security_level,
+ )
+ })
+ .context(concat!(
+ "In upgrade_keyblob_if_required_with: ",
+ "Failed to insert upgraded blob into the database.",
+ ))
+ })?;
+ match f(&upgraded_blob) {
+ Ok(v) => Ok((v, Some(upgraded_blob))),
+ Err(e) => Err(e).context(concat!(
+ "In upgrade_keyblob_if_required_with: ",
+ "Failed to perform operation on second try."
+ )),
+ }
+ }
+ Err(e) => {
+ Err(e).context("In upgrade_keyblob_if_required_with: Failed perform operation.")
+ }
+ Ok(v) => Ok((v, None)),
+ }
+ }
+}
+
+impl binder::Interface for KeystoreSecurityLevel {}
+
+impl IKeystoreSecurityLevel for KeystoreSecurityLevel {
+ fn createOperation(
+ &self,
+ key: &KeyDescriptor,
+ operation_parameters: &[KeyParameter],
+ forced: bool,
+ ) -> binder::public_api::Result<CreateOperationResponse> {
+ map_or_log_err(self.create_operation(key, operation_parameters, forced), Ok)
+ }
+ fn generateKey(
+ &self,
+ key: &KeyDescriptor,
+ attestation_key: Option<&KeyDescriptor>,
+ params: &[KeyParameter],
+ flags: i32,
+ entropy: &[u8],
+ ) -> binder::public_api::Result<KeyMetadata> {
+ map_or_log_err(self.generate_key(key, attestation_key, params, flags, entropy), Ok)
+ }
+ fn importKey(
+ &self,
+ key: &KeyDescriptor,
+ attestation_key: Option<&KeyDescriptor>,
+ params: &[KeyParameter],
+ flags: i32,
+ key_data: &[u8],
+ ) -> binder::public_api::Result<KeyMetadata> {
+ map_or_log_err(self.import_key(key, attestation_key, params, flags, key_data), Ok)
+ }
+ fn importWrappedKey(
+ &self,
+ key: &KeyDescriptor,
+ wrapping_key: &KeyDescriptor,
+ masking_key: Option<&[u8]>,
+ params: &[KeyParameter],
+ authenticators: &[AuthenticatorSpec],
+ ) -> binder::public_api::Result<KeyMetadata> {
+ map_or_log_err(
+ self.import_wrapped_key(key, wrapping_key, masking_key, params, authenticators),
+ Ok,
+ )
+ }
+}
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
new file mode 100644
index 0000000..71aecbd
--- /dev/null
+++ b/keystore2/src/service.rs
@@ -0,0 +1,232 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// TODO remove when fully implemented.
+#![allow(unused_variables)]
+
+//! This crate implement the core Keystore 2.0 service API as defined by the Keystore 2.0
+//! AIDL spec.
+
+use crate::database::{KeyEntryLoadBits, SubComponentType};
+use crate::error::{self, map_or_log_err, ErrorCode};
+use crate::globals::DB;
+use crate::permission;
+use crate::permission::KeyPerm;
+use crate::security_level::KeystoreSecurityLevel;
+use crate::utils::{
+ check_grant_permission, check_key_permission, key_parameters_to_authorizations, Asp,
+};
+use android_hardware_keymint::aidl::android::hardware::keymint::SecurityLevel::SecurityLevel;
+use android_system_keystore2::aidl::android::system::keystore2::{
+ Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel,
+ IKeystoreService::BnKeystoreService, IKeystoreService::IKeystoreService,
+ KeyDescriptor::KeyDescriptor, KeyEntryResponse::KeyEntryResponse, KeyMetadata::KeyMetadata,
+};
+use anyhow::{anyhow, Context, Result};
+use binder::{IBinder, Interface, ThreadState};
+
+/// Implementation of the IKeystoreService.
+pub struct KeystoreService {
+ sec_level: Asp,
+}
+
+impl KeystoreService {
+ /// Create a new instance of the Keystore 2.0 service.
+ pub fn new_native_binder() -> Result<impl IKeystoreService> {
+ let result = BnKeystoreService::new_binder(Self {
+ sec_level: Asp::new({
+ let sec_level =
+ KeystoreSecurityLevel::new_native_binder(SecurityLevel::TRUSTED_ENVIRONMENT)
+ .context("While trying to create IKeystoreSecurityLevel")?;
+ sec_level.as_binder()
+ }),
+ });
+ result.as_binder().set_requesting_sid(true);
+ Ok(result)
+ }
+
+ fn get_security_level(
+ &self,
+ security_level: SecurityLevel,
+ ) -> Result<Box<dyn IKeystoreSecurityLevel>> {
+ match security_level {
+ SecurityLevel::TRUSTED_ENVIRONMENT => self
+ .sec_level
+ .get_interface()
+ .context("In get_security_level: Failed to get IKeystoreSecurityLevel."),
+ _ => Err(anyhow!(error::Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))),
+ }
+ }
+
+ fn get_key_entry(&self, key: &KeyDescriptor) -> Result<KeyEntryResponse> {
+ let (key_id_guard, mut key_entry) = DB
+ .with(|db| {
+ db.borrow_mut().load_key_entry(
+ key.clone(),
+ KeyEntryLoadBits::PUBLIC,
+ ThreadState::get_calling_uid(),
+ |k, av| check_key_permission(KeyPerm::get_info(), k, &av),
+ )
+ })
+ .context("In get_key_entry, while trying to load key info.")?;
+
+ let i_sec_level = match key_entry.sec_level() {
+ SecurityLevel::TRUSTED_ENVIRONMENT => self
+ .sec_level
+ .get_interface()
+ .context("In get_key_entry: Failed to get IKeystoreSecurityLevel.")?,
+ _ => return Err(anyhow!(error::Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))),
+ };
+
+ Ok(KeyEntryResponse {
+ iSecurityLevel: Some(i_sec_level),
+ metadata: KeyMetadata {
+ key: KeyDescriptor {
+ domain: Domain::KEY_ID,
+ nspace: key_id_guard.id(),
+ ..Default::default()
+ },
+ keySecurityLevel: key_entry.sec_level(),
+ certificate: key_entry.take_cert(),
+ certificateChain: key_entry.take_cert_chain(),
+ authorizations: key_parameters_to_authorizations(key_entry.into_key_parameters()),
+ ..Default::default()
+ },
+ })
+ }
+
+ fn update_subcomponent(
+ &self,
+ key: &KeyDescriptor,
+ public_cert: Option<&[u8]>,
+ certificate_chain: Option<&[u8]>,
+ ) -> Result<()> {
+ DB.with::<_, Result<()>>(|db| {
+ let mut db = db.borrow_mut();
+ let (key_id_guard, key_entry) = db
+ .load_key_entry(
+ key.clone(),
+ KeyEntryLoadBits::NONE,
+ ThreadState::get_calling_uid(),
+ |k, av| {
+ check_key_permission(KeyPerm::update(), k, &av)
+ .context("In update_subcomponent.")
+ },
+ )
+ .context("Failed to load key_entry.")?;
+
+ if let Some(cert) = public_cert {
+ db.insert_blob(&key_id_guard, SubComponentType::CERT, cert, key_entry.sec_level())
+ .context("Failed to update cert subcomponent.")?;
+ }
+
+ if let Some(cert_chain) = certificate_chain {
+ db.insert_blob(
+ &key_id_guard,
+ SubComponentType::CERT_CHAIN,
+ cert_chain,
+ key_entry.sec_level(),
+ )
+ .context("Failed to update cert chain subcomponent.")?;
+ }
+ Ok(())
+ })
+ .context("In update_subcomponent.")
+ }
+
+ fn list_entries(&self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
+ // TODO implement.
+ Err(anyhow!(error::Error::sys()))
+ }
+
+ fn delete_key(&self, key: &KeyDescriptor) -> Result<()> {
+ // TODO implement.
+ Err(anyhow!(error::Error::sys()))
+ }
+
+ fn grant(
+ &self,
+ key: &KeyDescriptor,
+ grantee_uid: i32,
+ access_vector: permission::KeyPermSet,
+ ) -> Result<KeyDescriptor> {
+ DB.with(|db| {
+ db.borrow_mut().grant(
+ key.clone(),
+ ThreadState::get_calling_uid(),
+ grantee_uid as u32,
+ access_vector,
+ |k, av| check_grant_permission(*av, k).context("During grant."),
+ )
+ })
+ .context("In KeystoreService::grant.")
+ }
+
+ fn ungrant(&self, key: &KeyDescriptor, grantee_uid: i32) -> Result<()> {
+ DB.with(|db| {
+ db.borrow_mut().ungrant(
+ key.clone(),
+ ThreadState::get_calling_uid(),
+ grantee_uid as u32,
+ |k| check_key_permission(KeyPerm::grant(), k, &None),
+ )
+ })
+ .context("In KeystoreService::ungrant.")
+ }
+}
+
+impl binder::Interface for KeystoreService {}
+
+// Implementation of IKeystoreService. See AIDL spec at
+// system/security/keystore2/binder/android/security/keystore2/IKeystoreService.aidl
+impl IKeystoreService for KeystoreService {
+ fn getSecurityLevel(
+ &self,
+ security_level: SecurityLevel,
+ ) -> binder::public_api::Result<Box<dyn IKeystoreSecurityLevel>> {
+ map_or_log_err(self.get_security_level(SecurityLevel(security_level.0)), Ok)
+ }
+ fn getKeyEntry(&self, key: &KeyDescriptor) -> binder::public_api::Result<KeyEntryResponse> {
+ map_or_log_err(self.get_key_entry(key), Ok)
+ }
+ fn updateSubcomponent(
+ &self,
+ key: &KeyDescriptor,
+ public_cert: Option<&[u8]>,
+ certificate_chain: Option<&[u8]>,
+ ) -> binder::public_api::Result<()> {
+ map_or_log_err(self.update_subcomponent(key, public_cert, certificate_chain), Ok)
+ }
+ fn listEntries(
+ &self,
+ domain: Domain,
+ namespace: i64,
+ ) -> binder::public_api::Result<Vec<KeyDescriptor>> {
+ map_or_log_err(self.list_entries(domain, namespace), Ok)
+ }
+ fn deleteKey(&self, key: &KeyDescriptor) -> binder::public_api::Result<()> {
+ map_or_log_err(self.delete_key(key), Ok)
+ }
+ fn grant(
+ &self,
+ key: &KeyDescriptor,
+ grantee_uid: i32,
+ access_vector: i32,
+ ) -> binder::public_api::Result<KeyDescriptor> {
+ map_or_log_err(self.grant(key, grantee_uid, access_vector.into()), Ok)
+ }
+ fn ungrant(&self, key: &KeyDescriptor, grantee_uid: i32) -> binder::public_api::Result<()> {
+ map_or_log_err(self.ungrant(key, grantee_uid), Ok)
+ }
+}
diff --git a/keystore2/src/tests/certificate_utils_test.cpp b/keystore2/src/tests/certificate_utils_test.cpp
new file mode 100644
index 0000000..2df9ce5
--- /dev/null
+++ b/keystore2/src/tests/certificate_utils_test.cpp
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "certificate_utils.h"
+
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <variant>
+
+#include "test_keys.h"
+
+using namespace keystore;
+
+// I leave these here in case they are needed for debugging.
+namespace debug_utils {
+
+void log_ssl_error() {
+ unsigned long error = ERR_peek_last_error();
+
+ char buf[128];
+ ERR_error_string_n(error, buf, sizeof(buf));
+ std::cout << "BoringSslError: " << buf << std::endl;
+}
+
+std::string hexdump(const std::vector<uint8_t>& data) {
+ std::stringstream s;
+ size_t column_count = 0;
+ for (auto& c : data) {
+ s << std::setw(2) << std::setfill('0') << std::hex << (unsigned int)c;
+ if (++column_count % 40 == 0) s << "\n";
+ }
+ return s.str();
+}
+
+} // namespace debug_utils
+
+constexpr uint64_t kValidity = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
+
+const EVP_MD* getMD(Digest digest) {
+ switch (digest) {
+ case Digest::SHA1:
+ return EVP_sha1();
+ case Digest::SHA224:
+ return EVP_sha224();
+ case Digest::SHA256:
+ return EVP_sha256();
+ case Digest::SHA384:
+ return EVP_sha384();
+ case Digest::SHA512:
+ return EVP_sha512();
+ }
+}
+
+std::array<Digest, 5> digests = {
+ Digest::SHA1, Digest::SHA224, Digest::SHA256, Digest::SHA384, Digest::SHA512,
+};
+
+static const char* toString(Digest d) {
+ switch (d) {
+ case Digest::SHA1:
+ return "SHA1";
+ case Digest::SHA224:
+ return "SHA224";
+ case Digest::SHA256:
+ return "SHA256";
+ case Digest::SHA384:
+ return "SHA384";
+ case Digest::SHA512:
+ return "SHA512";
+ }
+}
+
+std::array<Padding, 2> rsa_paddings = {
+ Padding::PSS,
+ Padding::PKCS1_5,
+};
+
+enum class EcCurve {
+ P224,
+ P256,
+ P384,
+ P521,
+};
+
+std::array<int, 4> ec_curves = {
+ NID_secp224r1,
+ NID_X9_62_prime256v1,
+ NID_secp384r1,
+ NID_secp521r1,
+};
+
+static const char* curveNidToString(int nid) {
+ switch (nid) {
+ case NID_secp224r1:
+ return "P224";
+ case NID_X9_62_prime256v1:
+ return "P256";
+ case NID_secp384r1:
+ return "P384";
+ case NID_secp521r1:
+ return "P521";
+ default:
+ return "Unknown";
+ }
+}
+
+std::array<long, 2> rsa_key_sizes = {
+ 2048,
+ 4096,
+};
+
+using EcParam = std::tuple<int /* EC curve NID */, Digest>;
+
+class CertificateUtilsWithEcCurve : public testing::TestWithParam<EcParam> {};
+
+static std::string paramToStringEc(testing::TestParamInfo<EcParam> param) {
+ std::stringstream s;
+ auto [curve_nid, digest] = param.param;
+ s << param.index << "_" << curveNidToString(curve_nid) << "_" << toString(digest);
+ return s.str();
+}
+
+INSTANTIATE_TEST_SUITE_P(CertSigningWithCallbackEC, CertificateUtilsWithEcCurve,
+ testing::Combine(testing::ValuesIn(ec_curves), testing::ValuesIn(digests)),
+ paramToStringEc);
+
+TEST_P(CertificateUtilsWithEcCurve, CertSigningWithCallbackEC) {
+ // Structured decomposition (e.g.: auto [a, b, c] = ...) does not work here because
+ // names bound this way cannot be captured in lambda expressions so we use std::tie instead.
+ int curve_nid;
+ Digest digest;
+ std::tie(curve_nid, digest) = GetParam();
+ EVP_PKEY_CTX_Ptr pkey_ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL));
+ ASSERT_TRUE((bool)pkey_ctx);
+ ASSERT_TRUE(EVP_PKEY_keygen_init(pkey_ctx.get()));
+ ASSERT_TRUE(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pkey_ctx.get(), curve_nid));
+
+ EVP_PKEY* pkey_ptr = nullptr;
+ ASSERT_TRUE(EVP_PKEY_keygen(pkey_ctx.get(), &pkey_ptr));
+ EVP_PKEY_Ptr pkey(pkey_ptr);
+ ASSERT_TRUE(pkey);
+
+ uint64_t now_ms = (uint64_t)time(nullptr) * 1000;
+
+ BasicConstraintsExtension bcons{
+ .isCa = true,
+ .pathLength = {},
+ };
+
+ KeyUsageExtension keyUsage{
+ .isSigningKey = true,
+ .isEncryptionKey = false,
+ .isCertificationKey = true,
+ };
+
+ auto certV = makeCert(pkey.get(), 1, "Me", now_ms - kValidity, now_ms + kValidity,
+ true /* subject key id extension */, keyUsage, bcons);
+ ASSERT_TRUE(std::holds_alternative<X509_Ptr>(certV));
+ auto& cert = std::get<X509_Ptr>(certV);
+ ASSERT_TRUE(!setIssuer(cert.get(), cert.get(), true));
+
+ ASSERT_TRUE(!signCertWith(
+ cert.get(),
+ [&](const uint8_t* data, size_t len) {
+ bssl::ScopedEVP_MD_CTX sign_ctx;
+ EXPECT_TRUE(
+ EVP_DigestSignInit(sign_ctx.get(), nullptr, getMD(digest), nullptr, pkey.get()));
+
+ std::vector<uint8_t> sig_buf(512);
+ size_t sig_len = 512;
+ EVP_DigestSign(sign_ctx.get(), sig_buf.data(), &sig_len, data, len);
+ sig_buf.resize(sig_len);
+ return sig_buf;
+ },
+ Algo::ECDSA, Padding::Ignored, digest));
+
+ auto encCertV = encodeCert(cert.get());
+ ASSERT_TRUE(std::holds_alternative<std::vector<uint8_t>>(encCertV));
+
+ auto& encCert = std::get<1>(encCertV);
+ // Uncomment the next line to dump the DER encoded signed certificate as hex string.
+ // You can pipe this dump into "xxd -r -p | openssl x509 -inform der -text -noout"
+ // to inspect the certificate.
+ // std::cout << "DER encoded cert:\n" << debug_utils::hexdump(encCert) << std::endl;
+
+ const uint8_t* p = encCert.data();
+ X509_Ptr decoded_cert(d2i_X509(nullptr, &p, (long)encCert.size()));
+ EVP_PKEY_Ptr decoded_pkey(X509_get_pubkey(decoded_cert.get()));
+ ASSERT_TRUE(X509_verify(decoded_cert.get(), decoded_pkey.get()));
+}
+
+using RsaParams = std::tuple<long /* key size */, Padding, Digest>;
+
+class CertificateUtilsWithRsa : public testing::TestWithParam<RsaParams> {};
+
+static std::string paramsToStringRsa(testing::TestParamInfo<RsaParams> param) {
+ std::stringstream s;
+ auto [key_size, padding, digest] = param.param;
+ s << param.index << "_" << key_size << "_";
+ switch (padding) {
+ case Padding::PSS:
+ s << "PSS";
+ break;
+ case Padding::PKCS1_5:
+ s << "PKCS1_5";
+ break;
+ case Padding::Ignored:
+ s << "Ignored";
+ }
+ s << "_" << toString(digest);
+ return s.str();
+}
+
+INSTANTIATE_TEST_SUITE_P(CertSigningWithCallbackRsa, CertificateUtilsWithRsa,
+ testing::Combine(testing::ValuesIn(rsa_key_sizes),
+ testing::ValuesIn(rsa_paddings),
+ testing::ValuesIn(digests)),
+ paramsToStringRsa);
+
+TEST_P(CertificateUtilsWithRsa, CertSigningWithCallbackRsa) {
+ // Structured decomposition (e.g.: auto [a, b, c] = ...) does not work here because
+ // names bound this way cannot be captured in lambda expressions so we use std::tie instead.
+ long key_size;
+ Padding padding;
+ Digest digest;
+ std::tie(key_size, padding, digest) = GetParam();
+
+ CBS cbs;
+ switch (key_size) {
+ case 2048:
+ CBS_init(&cbs, rsa_key_2k, rsa_key_2k_len);
+ break;
+ case 4096:
+ CBS_init(&cbs, rsa_key_4k, rsa_key_4k_len);
+ break;
+ default:
+ FAIL();
+ }
+ EVP_PKEY_Ptr pkey(EVP_parse_private_key(&cbs));
+ ASSERT_TRUE(pkey);
+
+ uint64_t now_ms = (uint64_t)time(nullptr) * 1000;
+
+ BasicConstraintsExtension bcons{
+ .isCa = true,
+ .pathLength = 0,
+ };
+
+ KeyUsageExtension keyUsage{
+ .isSigningKey = true,
+ .isEncryptionKey = false,
+ .isCertificationKey = true,
+ };
+
+ auto certV = makeCert(pkey.get(), 1, "Me", now_ms - kValidity, now_ms + kValidity,
+ true /* subject key id extension */, keyUsage, bcons);
+ ASSERT_TRUE(std::holds_alternative<X509_Ptr>(certV));
+ auto& cert = std::get<X509_Ptr>(certV);
+ ASSERT_TRUE(!setIssuer(cert.get(), cert.get(), true));
+
+ ASSERT_TRUE(!signCertWith(
+ cert.get(),
+ [&](const uint8_t* data, size_t len) {
+ bssl::ScopedEVP_MD_CTX sign_ctx;
+ EVP_PKEY_CTX* pkey_sign_ctx_ptr;
+ EXPECT_TRUE(EVP_DigestSignInit(sign_ctx.get(), &pkey_sign_ctx_ptr, getMD(digest),
+ nullptr, pkey.get()));
+
+ if (padding == Padding::PSS) {
+ EXPECT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pkey_sign_ctx_ptr, RSA_PKCS1_PSS_PADDING));
+ EXPECT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_sign_ctx_ptr, -1));
+ } else {
+ EXPECT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pkey_sign_ctx_ptr, RSA_PKCS1_PADDING));
+ }
+
+ std::vector<uint8_t> sig_buf(1024);
+ size_t sig_len = 1024;
+ EVP_DigestSign(sign_ctx.get(), sig_buf.data(), &sig_len, data, len);
+ sig_buf.resize(sig_len);
+ return sig_buf;
+ },
+ Algo::RSA, padding, digest));
+
+ auto encCertV = encodeCert(cert.get());
+ ASSERT_TRUE(std::holds_alternative<std::vector<uint8_t>>(encCertV));
+
+ auto& encCert = std::get<1>(encCertV);
+ // Uncomment the next line to dump the DER encoded signed certificate as hex string.
+ // You can pipe this dump into "xxd -r -p | openssl x509 -inform der -text -noout"
+ // to inspect the certificate.
+ // std::cout << "DER encoded cert:\n" << debug_utils::hexdump(encCert) << std::endl;
+
+ const uint8_t* p = encCert.data();
+ X509_Ptr decoded_cert(d2i_X509(nullptr, &p, (long)encCert.size()));
+ EVP_PKEY_Ptr decoded_pkey(X509_get_pubkey(decoded_cert.get()));
+ ASSERT_TRUE(X509_verify(decoded_cert.get(), decoded_pkey.get()));
+}
diff --git a/keystore2/src/tests/gtest_main.cpp b/keystore2/src/tests/gtest_main.cpp
new file mode 100644
index 0000000..149cbbc
--- /dev/null
+++ b/keystore2/src/tests/gtest_main.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/keystore2/src/tests/test_keys.h b/keystore2/src/tests/test_keys.h
new file mode 100644
index 0000000..d3b1175
--- /dev/null
+++ b/keystore2/src/tests/test_keys.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+constexpr const unsigned char rsa_key_4k[] = {
+ 0x30, 0x82, 0x09, 0x41, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x09, 0x2b, 0x30, 0x82, 0x09, 0x27, 0x02, 0x01,
+ 0x00, 0x02, 0x82, 0x02, 0x01, 0x00, 0xac, 0x07, 0x4e, 0xc6, 0x20, 0xb9, 0x78, 0x03, 0xd0, 0x53,
+ 0x22, 0xa4, 0xef, 0x6d, 0xd1, 0x7a, 0x7e, 0x5e, 0x5e, 0x1d, 0xe7, 0x9b, 0x30, 0x31, 0x99, 0xe8,
+ 0x1c, 0xdf, 0x32, 0x0c, 0xdb, 0xdb, 0xc2, 0x4c, 0x22, 0x10, 0x71, 0xd0, 0x76, 0x83, 0xb0, 0x50,
+ 0x66, 0xa4, 0x43, 0x75, 0xe8, 0x46, 0xde, 0x58, 0x9e, 0x31, 0x82, 0x81, 0x8c, 0x36, 0x20, 0xbb,
+ 0x42, 0xcd, 0xb9, 0x21, 0x29, 0x67, 0x39, 0x4d, 0x2a, 0x1c, 0xc2, 0x89, 0x48, 0x23, 0x5f, 0xdd,
+ 0x60, 0xc4, 0x04, 0x42, 0xbe, 0x6f, 0x01, 0xa5, 0xf8, 0xac, 0xba, 0x27, 0xd1, 0x87, 0x08, 0x6b,
+ 0xe6, 0x1b, 0xfc, 0xba, 0xff, 0x7e, 0xc9, 0xaf, 0x76, 0x28, 0xe8, 0x93, 0x2c, 0xbf, 0x6f, 0xed,
+ 0xf3, 0x6f, 0x21, 0xc1, 0xe7, 0x56, 0xf5, 0x15, 0x56, 0xa8, 0xa1, 0xfd, 0xb7, 0xb3, 0x8c, 0x3d,
+ 0x1f, 0xf3, 0x80, 0xea, 0x79, 0xff, 0x0c, 0xc6, 0xb6, 0x59, 0xa0, 0x3f, 0x13, 0xb0, 0x4f, 0xb3,
+ 0x1c, 0xe1, 0x2a, 0xa5, 0x45, 0x02, 0x51, 0xa3, 0x74, 0x15, 0xee, 0xf0, 0xca, 0xba, 0x7d, 0xca,
+ 0xc6, 0x87, 0xd6, 0x12, 0x9b, 0xbb, 0x4b, 0x86, 0xc7, 0xcb, 0x88, 0xc6, 0x10, 0xee, 0x34, 0x51,
+ 0x4b, 0xe9, 0x9d, 0xbb, 0x59, 0x03, 0xff, 0xbf, 0x98, 0x0a, 0xfd, 0xf2, 0xd0, 0x06, 0x0e, 0x51,
+ 0xd1, 0xbb, 0x8b, 0xbd, 0xca, 0x26, 0x4d, 0x05, 0x0e, 0xee, 0x82, 0x0f, 0xf6, 0x38, 0x46, 0x2a,
+ 0x7f, 0xfd, 0x37, 0xe6, 0xcf, 0xaa, 0x6a, 0x84, 0xbc, 0xa7, 0xd2, 0x06, 0x29, 0x49, 0x4c, 0xd2,
+ 0x28, 0xd4, 0x48, 0x09, 0xfc, 0x91, 0x1e, 0xb0, 0x06, 0xf9, 0x5b, 0xbe, 0xd9, 0xb8, 0x01, 0xec,
+ 0x3a, 0xc3, 0xa2, 0x1d, 0x89, 0x0b, 0x22, 0xf8, 0xf0, 0x8e, 0x95, 0xe0, 0x3d, 0x5b, 0x80, 0x38,
+ 0x21, 0x80, 0x10, 0x04, 0x54, 0xaa, 0xa5, 0x81, 0x8b, 0x47, 0x73, 0x54, 0xcb, 0x06, 0xa9, 0x01,
+ 0xf5, 0x57, 0x72, 0xdd, 0x5f, 0x9f, 0xe1, 0x14, 0x1f, 0xc1, 0x3b, 0xda, 0xd1, 0xad, 0xc7, 0x9c,
+ 0x70, 0x18, 0xfd, 0x07, 0x7e, 0x37, 0x0d, 0xb4, 0x30, 0xff, 0x6d, 0x4b, 0x99, 0xdb, 0x3f, 0x23,
+ 0xd7, 0x15, 0x3d, 0x4c, 0x14, 0x63, 0x98, 0xf5, 0x03, 0x63, 0x4e, 0x63, 0x15, 0x6a, 0xce, 0x7f,
+ 0xfc, 0x4f, 0xa0, 0x72, 0x49, 0x3f, 0xd9, 0xa2, 0xde, 0x65, 0xac, 0x35, 0x88, 0x03, 0x55, 0xf5,
+ 0x27, 0x57, 0x4e, 0x4b, 0xef, 0x44, 0x1d, 0xd1, 0xe9, 0xaf, 0x89, 0x7e, 0x19, 0x2a, 0xc4, 0x48,
+ 0x80, 0x8d, 0x22, 0xd6, 0x4f, 0x79, 0x39, 0x15, 0x00, 0xc0, 0xa8, 0x93, 0x5a, 0x05, 0xce, 0xc8,
+ 0x3f, 0x27, 0x40, 0x09, 0x1f, 0x2a, 0x0c, 0x32, 0x6a, 0x2d, 0xef, 0x51, 0x79, 0x51, 0xf1, 0xfe,
+ 0xdb, 0x2c, 0xb5, 0x2f, 0x4d, 0x94, 0x1d, 0xd2, 0xb8, 0xed, 0x53, 0x58, 0x3e, 0xb4, 0x65, 0xfb,
+ 0xca, 0x9f, 0xfe, 0x5c, 0x68, 0x20, 0x58, 0xd9, 0xfd, 0xc7, 0x4d, 0x0f, 0x03, 0x37, 0x61, 0xaf,
+ 0x2b, 0x90, 0xe1, 0xfc, 0x15, 0xa6, 0xf1, 0xac, 0x5d, 0xad, 0xb4, 0xbe, 0xf6, 0xb4, 0x7b, 0x42,
+ 0xe6, 0x17, 0xe9, 0x79, 0xde, 0x65, 0x50, 0x70, 0x6b, 0x46, 0x24, 0x73, 0x4d, 0xa3, 0x54, 0x3a,
+ 0x21, 0xc2, 0x1c, 0x80, 0x1d, 0xf6, 0xd4, 0x0e, 0x7a, 0xa5, 0x4e, 0x97, 0xc1, 0x15, 0x37, 0x02,
+ 0xea, 0x55, 0xff, 0xad, 0x59, 0x95, 0xa0, 0x24, 0xd0, 0x58, 0x59, 0xf7, 0x9a, 0x4e, 0x2b, 0x78,
+ 0x89, 0x91, 0x9c, 0x67, 0x14, 0xe4, 0x24, 0xc3, 0xb8, 0xd3, 0x7d, 0x06, 0xaf, 0x46, 0x8f, 0xe7,
+ 0x07, 0x88, 0xf0, 0x4c, 0xf4, 0xb8, 0x3a, 0x2a, 0x9c, 0x89, 0x2f, 0x7c, 0x32, 0xfd, 0x52, 0x55,
+ 0xd8, 0xe1, 0x58, 0x46, 0xe5, 0xc3, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x02, 0x00, 0x08,
+ 0x79, 0xcf, 0xb2, 0xc9, 0x57, 0xfa, 0x06, 0xce, 0x13, 0xda, 0x88, 0x1f, 0xd7, 0xdc, 0x53, 0x59,
+ 0xb8, 0x92, 0x90, 0x8c, 0xa1, 0xc3, 0xcd, 0x1d, 0xd5, 0x26, 0xdf, 0x04, 0x5b, 0x47, 0xd5, 0xdb,
+ 0x0b, 0xdf, 0x3d, 0xca, 0x2d, 0xc8, 0x39, 0x12, 0xcd, 0xd3, 0x50, 0xd2, 0x96, 0x13, 0x9c, 0xb2,
+ 0x45, 0xd1, 0x7d, 0x84, 0xfd, 0x97, 0x07, 0xef, 0xb2, 0xea, 0x46, 0xb2, 0x91, 0x64, 0xb5, 0xd6,
+ 0x47, 0xec, 0x04, 0x40, 0xbd, 0x7c, 0xd5, 0x69, 0x5a, 0xc1, 0xf2, 0xc6, 0x76, 0xf7, 0x65, 0x06,
+ 0xc2, 0xc3, 0xae, 0xd6, 0xf9, 0x31, 0x44, 0xa2, 0xf0, 0x96, 0x04, 0xd8, 0xfd, 0xe9, 0xaa, 0xb8,
+ 0x8b, 0x31, 0x9a, 0x30, 0x63, 0x57, 0xf8, 0x12, 0xae, 0xb9, 0xa8, 0xc7, 0x14, 0x03, 0xae, 0xf0,
+ 0x22, 0x5e, 0x03, 0xae, 0xff, 0x8e, 0x36, 0x85, 0x79, 0x59, 0x82, 0xa8, 0xde, 0x64, 0xa6, 0x61,
+ 0x5d, 0xc5, 0x0c, 0x43, 0x6d, 0xf8, 0x2d, 0x5e, 0xaf, 0xe7, 0x83, 0x5c, 0x93, 0x8a, 0x03, 0xe4,
+ 0x3b, 0xd6, 0x73, 0x62, 0x33, 0x70, 0xf9, 0xa1, 0x4b, 0x05, 0x5f, 0x19, 0xf8, 0x0e, 0xbe, 0x3a,
+ 0xa9, 0x68, 0x5c, 0xa9, 0xdf, 0x80, 0x64, 0x0c, 0x25, 0xd9, 0x44, 0xa8, 0x65, 0xdb, 0xab, 0xeb,
+ 0xc4, 0xe7, 0xdb, 0xda, 0xc9, 0x44, 0xe0, 0x97, 0x82, 0x06, 0x80, 0x64, 0x11, 0x34, 0xcd, 0x90,
+ 0x4b, 0xe8, 0x81, 0x6d, 0xdd, 0x15, 0x77, 0x8e, 0x55, 0x77, 0xba, 0xe5, 0x2f, 0x35, 0x1a, 0x23,
+ 0x67, 0x68, 0xd8, 0x27, 0xeb, 0xef, 0xca, 0xd1, 0xc3, 0x25, 0x09, 0xd8, 0x86, 0xcd, 0x6f, 0xe5,
+ 0x00, 0x2d, 0x47, 0xc9, 0xf2, 0x6c, 0x4d, 0xb9, 0xa2, 0x86, 0xfe, 0xae, 0x95, 0x1f, 0xf4, 0x71,
+ 0x83, 0xac, 0x6e, 0x8a, 0x09, 0xe3, 0x5c, 0x07, 0xc4, 0x3c, 0x3a, 0x50, 0x0f, 0xb6, 0x90, 0x21,
+ 0x25, 0xdf, 0x2d, 0x61, 0x89, 0xb6, 0x3c, 0xb3, 0xc3, 0xc0, 0xd9, 0x2e, 0x73, 0x76, 0xf6, 0x46,
+ 0x46, 0xf8, 0x01, 0xbd, 0x0b, 0x94, 0x80, 0xf6, 0x94, 0x5b, 0x17, 0x9e, 0xbc, 0xdb, 0x9d, 0xfd,
+ 0xc2, 0x3e, 0x56, 0xa1, 0xa0, 0x1a, 0xed, 0x82, 0xcb, 0xb0, 0xb3, 0xd4, 0x58, 0xb4, 0x91, 0x8e,
+ 0xd9, 0x84, 0xb8, 0x94, 0xc2, 0x86, 0x42, 0xa6, 0x86, 0xf2, 0x9c, 0x1d, 0xc7, 0xc9, 0xed, 0x6d,
+ 0x0d, 0x8d, 0x98, 0x08, 0xf3, 0x52, 0xe7, 0x7f, 0xfe, 0xe0, 0x9f, 0xdf, 0x43, 0x8e, 0xbc, 0x3f,
+ 0x93, 0x41, 0x44, 0x7b, 0x26, 0x0e, 0x2e, 0xc1, 0xc2, 0x4e, 0xc7, 0xb4, 0x5c, 0xc5, 0x55, 0xae,
+ 0xbb, 0xb4, 0x2f, 0xd5, 0x1f, 0x34, 0xce, 0x94, 0x66, 0x12, 0x41, 0x8a, 0x15, 0x8b, 0xcb, 0xdd,
+ 0x00, 0xf9, 0xa0, 0x55, 0xa6, 0x8b, 0xe9, 0x13, 0x14, 0xc6, 0x0b, 0x98, 0x8f, 0xff, 0x2f, 0x9a,
+ 0xe8, 0x78, 0x68, 0x94, 0xeb, 0x53, 0xeb, 0x4b, 0xed, 0x5a, 0x6d, 0x1c, 0xe2, 0xe5, 0xc7, 0xde,
+ 0x13, 0xa9, 0xaf, 0xa3, 0xc7, 0x54, 0x26, 0xa0, 0x3f, 0x44, 0xdd, 0x9f, 0x14, 0xe2, 0xc4, 0x9a,
+ 0xf5, 0x30, 0xea, 0x2e, 0x75, 0xc6, 0xd3, 0xf8, 0x5e, 0x9b, 0x02, 0x0d, 0xc8, 0x81, 0x6c, 0x13,
+ 0x3b, 0x9c, 0x89, 0x54, 0x52, 0x41, 0x62, 0xad, 0xa0, 0x52, 0xaa, 0x2c, 0xc4, 0x2c, 0x63, 0x58,
+ 0xf6, 0xb1, 0xfa, 0xdc, 0x77, 0xed, 0x3e, 0x8c, 0x12, 0x94, 0x09, 0x57, 0x18, 0xb3, 0x04, 0x53,
+ 0x3c, 0xad, 0xa8, 0x45, 0x4b, 0x19, 0xa0, 0xcb, 0x8f, 0x6f, 0x5d, 0x2d, 0xcc, 0xe1, 0xfe, 0x4a,
+ 0xe6, 0x20, 0xed, 0x9a, 0x76, 0x4f, 0x17, 0xfd, 0xed, 0x1e, 0x6e, 0x41, 0x21, 0x43, 0xe4, 0xe9,
+ 0x47, 0x01, 0x1f, 0x76, 0x68, 0x4d, 0xbb, 0xd3, 0xba, 0x68, 0x34, 0x06, 0x6a, 0xf5, 0xe9, 0x02,
+ 0x82, 0x01, 0x01, 0x00, 0xdb, 0xc5, 0x0d, 0x95, 0x88, 0x5f, 0x2c, 0xa9, 0x7c, 0xb7, 0x06, 0xd8,
+ 0x20, 0x60, 0x72, 0x80, 0xec, 0xae, 0xf4, 0xdc, 0x48, 0x5d, 0x9d, 0x6d, 0x2a, 0x54, 0x36, 0xe1,
+ 0x32, 0x25, 0x10, 0x4d, 0x56, 0x0f, 0x51, 0xe9, 0xbc, 0x95, 0x3f, 0x38, 0x43, 0xed, 0xc6, 0x6a,
+ 0x16, 0xb0, 0x06, 0x90, 0x85, 0x51, 0x07, 0xea, 0x7b, 0x1d, 0x64, 0x12, 0x39, 0x7e, 0x32, 0x92,
+ 0x3e, 0xcc, 0x97, 0x91, 0x02, 0x6c, 0xf8, 0x95, 0xc7, 0x39, 0xa1, 0x5c, 0xd3, 0x62, 0xcc, 0x29,
+ 0x83, 0x27, 0xe6, 0x36, 0xba, 0xf6, 0x62, 0x80, 0xf6, 0x15, 0xda, 0x0f, 0xc4, 0x47, 0x81, 0x44,
+ 0x96, 0xba, 0xec, 0x37, 0x8c, 0x95, 0xb2, 0x30, 0x12, 0xc0, 0x4d, 0x62, 0x88, 0x5e, 0x7d, 0x13,
+ 0x6d, 0x83, 0x14, 0x1e, 0xd7, 0xc2, 0xeb, 0x9d, 0xbd, 0xa4, 0x70, 0x78, 0xf3, 0xb1, 0x6b, 0x6c,
+ 0xe9, 0x37, 0x63, 0x47, 0x6f, 0xed, 0xea, 0xd6, 0x32, 0x80, 0x71, 0xa2, 0x7f, 0x38, 0x67, 0xb4,
+ 0x1f, 0xf0, 0x7f, 0xb6, 0xb7, 0x56, 0xe7, 0x24, 0xaa, 0x2f, 0xb9, 0x93, 0xb8, 0xab, 0x2a, 0xec,
+ 0xc4, 0x19, 0x9a, 0xea, 0x5d, 0x01, 0x1e, 0xdd, 0x5c, 0x05, 0x37, 0x12, 0x04, 0x32, 0xb2, 0x5d,
+ 0x16, 0xdc, 0x88, 0x0c, 0xfe, 0x1e, 0xf6, 0x9f, 0x63, 0xbf, 0xb2, 0x00, 0x6b, 0x99, 0xbe, 0x42,
+ 0x96, 0x41, 0xe0, 0x3d, 0xd1, 0x35, 0x6a, 0xf1, 0x81, 0x09, 0xd6, 0x4c, 0xdd, 0xc0, 0x20, 0x6e,
+ 0x0d, 0xcb, 0x30, 0x11, 0x73, 0x11, 0x82, 0x5e, 0x1b, 0x9a, 0xa0, 0x57, 0xcd, 0xd7, 0xab, 0xa2,
+ 0xe9, 0xed, 0xe7, 0x26, 0x8d, 0x30, 0x09, 0xe7, 0x5a, 0xa1, 0xd0, 0x62, 0xac, 0x7f, 0x15, 0xd1,
+ 0x9a, 0x0a, 0x97, 0x5d, 0x8a, 0xc0, 0x47, 0xa4, 0xa8, 0x8b, 0x26, 0x75, 0x35, 0x5d, 0xa9, 0xf1,
+ 0x1a, 0x61, 0xdc, 0xbf, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc8, 0x63, 0x6e, 0x9c, 0x88, 0xcd, 0x33,
+ 0xef, 0x72, 0x80, 0x00, 0x6b, 0x8e, 0xb0, 0xd2, 0xa9, 0x5c, 0x78, 0xf7, 0x25, 0x8f, 0xba, 0x49,
+ 0x60, 0xa3, 0x33, 0xf4, 0x16, 0x1c, 0x81, 0xad, 0x82, 0x39, 0xa5, 0xa8, 0x12, 0xc2, 0x7e, 0x05,
+ 0x33, 0x9c, 0xd9, 0xa9, 0xa4, 0x02, 0xf8, 0x43, 0xdf, 0xa6, 0x39, 0xdb, 0xc0, 0x60, 0xdc, 0x53,
+ 0x76, 0x7c, 0xef, 0xf0, 0x58, 0x44, 0x3d, 0xc7, 0x77, 0xe6, 0x6f, 0x2a, 0xbd, 0x89, 0x8b, 0x40,
+ 0xe3, 0x02, 0x80, 0x8c, 0x46, 0x24, 0x4c, 0x63, 0xc4, 0x06, 0xb1, 0x48, 0x92, 0x0a, 0x86, 0x58,
+ 0xe3, 0x08, 0x2a, 0x2e, 0x4b, 0xdd, 0xa6, 0x64, 0x68, 0xe9, 0xac, 0x07, 0x2b, 0x3d, 0x2f, 0x42,
+ 0x68, 0x5a, 0x42, 0xdb, 0xb7, 0x5a, 0x67, 0xc4, 0x5f, 0x19, 0xba, 0xff, 0xed, 0x17, 0x0b, 0xf8,
+ 0x26, 0x36, 0xd7, 0x9d, 0x3a, 0x3d, 0x0e, 0x5f, 0x31, 0x29, 0x3f, 0xf4, 0x24, 0x2f, 0x0a, 0xa2,
+ 0x21, 0x0e, 0x6e, 0x86, 0xf5, 0x1e, 0xb7, 0xce, 0x81, 0x95, 0xd0, 0xcd, 0x97, 0xd1, 0x2c, 0xd4,
+ 0x9f, 0x95, 0xd6, 0x7c, 0x68, 0x80, 0x4f, 0xe6, 0x5c, 0xab, 0xfe, 0x6b, 0xf9, 0x8b, 0x12, 0x99,
+ 0xad, 0xc9, 0x64, 0x21, 0x99, 0xef, 0xfb, 0xd3, 0x16, 0x8b, 0x95, 0x93, 0xa7, 0xb7, 0x24, 0x36,
+ 0x00, 0xb2, 0xa2, 0xbe, 0x79, 0x4e, 0x66, 0xbd, 0xe1, 0x2d, 0xd0, 0xa9, 0x76, 0xe1, 0x13, 0x0d,
+ 0xb5, 0x4b, 0xc5, 0xe9, 0x63, 0x23, 0x45, 0xcf, 0x5f, 0x0d, 0x5c, 0xce, 0x93, 0x7f, 0xa9, 0x68,
+ 0xf6, 0xfc, 0x2c, 0x54, 0x40, 0x43, 0xca, 0x9d, 0xfd, 0x43, 0x81, 0x4d, 0xbe, 0x98, 0x87, 0xca,
+ 0x2c, 0x82, 0x32, 0xb7, 0xcf, 0xa1, 0xc5, 0xf8, 0x55, 0xea, 0x2b, 0x6d, 0xfc, 0xe7, 0x5d, 0xcf,
+ 0xde, 0xf8, 0x15, 0xc2, 0xc3, 0xa2, 0xe6, 0x83, 0xfd, 0x02, 0x82, 0x01, 0x00, 0x2c, 0x83, 0x3a,
+ 0xff, 0x20, 0x81, 0xf6, 0x6f, 0xd5, 0xbc, 0xd4, 0x7c, 0x0e, 0x02, 0xba, 0xee, 0x76, 0x01, 0xf1,
+ 0xc2, 0x74, 0x3d, 0xd1, 0xd6, 0xfc, 0x8d, 0xd6, 0x17, 0xc2, 0xaa, 0x53, 0x24, 0xf6, 0xdb, 0x5f,
+ 0x81, 0xf2, 0x1a, 0x60, 0x95, 0xaa, 0xdc, 0x8c, 0x25, 0x8c, 0xb6, 0xd6, 0x7d, 0x8b, 0x23, 0x20,
+ 0x71, 0x53, 0xc2, 0x5e, 0x34, 0x7a, 0xc4, 0x9e, 0xc5, 0x94, 0x46, 0xa8, 0x24, 0x4c, 0xd3, 0x79,
+ 0x7e, 0x0c, 0xbe, 0x15, 0x7a, 0xd1, 0xad, 0xdf, 0x20, 0x41, 0x5a, 0x61, 0x7c, 0x90, 0x5d, 0xbb,
+ 0x11, 0xd7, 0xc6, 0x11, 0x46, 0xc4, 0x40, 0x9f, 0x64, 0x1f, 0x0b, 0x79, 0x30, 0xbf, 0x1e, 0xca,
+ 0xda, 0x85, 0xd1, 0xc1, 0x5a, 0xc5, 0xb8, 0x2d, 0xa9, 0x33, 0xb3, 0x2a, 0xee, 0x1c, 0x51, 0x74,
+ 0x9b, 0x9c, 0x7f, 0xa3, 0xf0, 0x3b, 0x9b, 0xa1, 0xe0, 0x8b, 0x54, 0x16, 0x9d, 0xaf, 0x84, 0x06,
+ 0xde, 0x9f, 0x97, 0xf8, 0x6c, 0x2b, 0x4c, 0x67, 0x64, 0xca, 0x5b, 0x51, 0xe2, 0xd6, 0x3b, 0x99,
+ 0xd1, 0x89, 0x4e, 0xe5, 0x4d, 0x90, 0x47, 0xcb, 0x07, 0xed, 0xa8, 0x2a, 0x02, 0x72, 0x17, 0xfa,
+ 0x02, 0x67, 0xd2, 0xfe, 0x96, 0x7d, 0x97, 0x2f, 0x1d, 0x3f, 0xb6, 0x27, 0x30, 0x4a, 0x80, 0x46,
+ 0xff, 0x7d, 0x9a, 0xa4, 0x19, 0x05, 0xb2, 0x3c, 0x21, 0x0c, 0x82, 0x07, 0x43, 0x3e, 0x0e, 0x8d,
+ 0xbc, 0xa0, 0xa0, 0x37, 0x71, 0x96, 0x30, 0x85, 0xe1, 0x04, 0x96, 0x35, 0x04, 0x33, 0xc4, 0x46,
+ 0x1d, 0x7d, 0x85, 0xd2, 0x18, 0x36, 0xaf, 0x0a, 0x2a, 0x93, 0x2b, 0x06, 0x78, 0x7e, 0x7c, 0x4e,
+ 0x65, 0x37, 0xac, 0x32, 0xa2, 0xe9, 0xc1, 0x4b, 0xd0, 0x0a, 0x5d, 0x3e, 0xcf, 0x49, 0x7d, 0x2c,
+ 0x85, 0xa3, 0x45, 0x9b, 0xe2, 0x7d, 0x8e, 0x9d, 0x0f, 0x22, 0x82, 0xd3, 0xcd, 0x02, 0x82, 0x01,
+ 0x00, 0x46, 0xe8, 0x18, 0x3d, 0xbf, 0x92, 0x8c, 0xec, 0x0f, 0xa2, 0x07, 0x84, 0x07, 0xab, 0xbd,
+ 0xff, 0x3b, 0xbf, 0x7a, 0x04, 0x8a, 0x85, 0x2a, 0x6d, 0xcd, 0x92, 0x16, 0xae, 0xb4, 0x4b, 0x96,
+ 0xaf, 0xdb, 0xe2, 0x28, 0x44, 0xeb, 0x19, 0x58, 0x91, 0xd8, 0xd0, 0x94, 0x5c, 0x7a, 0xc8, 0x8a,
+ 0x8b, 0xda, 0xef, 0xe2, 0x38, 0x82, 0x8d, 0xb3, 0xe2, 0xdb, 0x76, 0xb3, 0x9f, 0x28, 0x16, 0x8c,
+ 0x3c, 0x7b, 0x07, 0x9f, 0x22, 0x0e, 0x47, 0x7e, 0x20, 0x55, 0xc4, 0x52, 0xde, 0x86, 0xfd, 0x98,
+ 0xd7, 0xc6, 0x5e, 0x79, 0x05, 0x64, 0x40, 0x01, 0xb7, 0xe4, 0x2d, 0xb8, 0xd0, 0x13, 0x90, 0x4b,
+ 0x3b, 0x6c, 0x63, 0xf8, 0xed, 0x6d, 0xeb, 0x09, 0x1e, 0x8f, 0xc1, 0xd4, 0xa9, 0x5e, 0x8e, 0x15,
+ 0x48, 0x69, 0x7c, 0x68, 0x0e, 0xe6, 0xf6, 0xcf, 0x4a, 0x06, 0x61, 0xe9, 0x3a, 0xb0, 0x5c, 0x23,
+ 0x86, 0xeb, 0xc7, 0xbb, 0x86, 0x0a, 0x37, 0x43, 0x03, 0x5b, 0x6d, 0xf4, 0xc7, 0x4b, 0xa5, 0x52,
+ 0xa7, 0x3b, 0xf1, 0xf4, 0xad, 0xe1, 0xd0, 0x71, 0x34, 0x3e, 0xfa, 0xf4, 0x6e, 0xad, 0xe8, 0x97,
+ 0xe4, 0xf6, 0xdf, 0x42, 0x29, 0xbc, 0xf2, 0x49, 0xfa, 0xda, 0xa6, 0x59, 0xd5, 0x74, 0xbb, 0xb1,
+ 0x07, 0xeb, 0x40, 0x74, 0x4d, 0x06, 0x5b, 0x03, 0xd8, 0xdf, 0x5d, 0x02, 0xf5, 0x3d, 0xae, 0xd1,
+ 0x45, 0x9a, 0xc6, 0x99, 0x10, 0x7d, 0xb8, 0x16, 0x43, 0xae, 0x9a, 0x4b, 0x69, 0x4f, 0x13, 0xe6,
+ 0xbb, 0x05, 0xa9, 0x6f, 0x57, 0x75, 0xf6, 0xe6, 0x33, 0x6f, 0x2b, 0xe8, 0x6c, 0x0d, 0x10, 0xe7,
+ 0x32, 0xb4, 0xee, 0x4e, 0x2a, 0x41, 0x22, 0xdb, 0x81, 0x40, 0x58, 0xdd, 0xfd, 0xd4, 0x8a, 0x8e,
+ 0xc3, 0x27, 0xe7, 0x52, 0x36, 0x09, 0x50, 0x82, 0xbb, 0xad, 0x21, 0x56, 0x17, 0x8f, 0xce, 0xed,
+ 0xa9, 0x02, 0x82, 0x01, 0x00, 0x78, 0x0c, 0x4f, 0x07, 0x4a, 0x2d, 0x91, 0xa3, 0xfd, 0x1c, 0xb3,
+ 0xb5, 0xcb, 0x11, 0x1c, 0x04, 0xc9, 0x7f, 0xbf, 0x86, 0x7d, 0x5e, 0x2e, 0xf4, 0x2c, 0xad, 0x9e,
+ 0x35, 0x74, 0x2e, 0x55, 0xc6, 0xaf, 0x1c, 0x76, 0xb9, 0x3d, 0x44, 0xe7, 0xdd, 0x5f, 0x32, 0x0e,
+ 0xce, 0x4b, 0x43, 0x6d, 0x7c, 0x10, 0xd3, 0x01, 0x6f, 0x22, 0xa5, 0xb3, 0xaf, 0x40, 0x80, 0x57,
+ 0xf0, 0x96, 0x7c, 0xb8, 0xae, 0xbc, 0x35, 0x8b, 0xa1, 0x59, 0xdc, 0xc4, 0xf7, 0x8b, 0xda, 0xe7,
+ 0x91, 0x9b, 0xa7, 0x54, 0x61, 0xad, 0x9d, 0x0a, 0x68, 0xc3, 0xc5, 0x10, 0x9e, 0x39, 0x16, 0x9c,
+ 0x3b, 0xf3, 0x3a, 0xdf, 0xb9, 0x72, 0xed, 0x4f, 0x56, 0x1e, 0x5c, 0x8b, 0x35, 0x0b, 0xa6, 0x08,
+ 0x83, 0x96, 0xd4, 0x6d, 0x3f, 0xe3, 0x6a, 0x25, 0xa2, 0xe8, 0x0f, 0xce, 0x0c, 0x26, 0x85, 0x02,
+ 0xba, 0xe1, 0xfc, 0xdc, 0xa0, 0x18, 0xfc, 0x7c, 0x87, 0xa6, 0x6b, 0xf5, 0x92, 0xa8, 0x83, 0x5f,
+ 0xbf, 0xa5, 0xe3, 0x0e, 0x21, 0x10, 0xbf, 0x44, 0x49, 0xc7, 0x62, 0x36, 0x46, 0x0b, 0x97, 0xdc,
+ 0xd4, 0x30, 0x02, 0xd4, 0x04, 0xcb, 0x8f, 0xfe, 0xde, 0x76, 0x44, 0x9f, 0xd6, 0x55, 0x8e, 0x45,
+ 0xaa, 0x10, 0xd4, 0xa0, 0x2c, 0x49, 0x72, 0x6e, 0x5f, 0xf1, 0xd5, 0x0a, 0x1e, 0xba, 0xc6, 0xb4,
+ 0xb6, 0x93, 0x9d, 0x6a, 0xe4, 0xaa, 0x61, 0x3a, 0xca, 0x77, 0xa4, 0x16, 0xa2, 0x4f, 0x2f, 0xad,
+ 0xe6, 0xb5, 0x64, 0x93, 0x37, 0xf9, 0xdc, 0x28, 0x70, 0x54, 0x0b, 0xb2, 0x15, 0x96, 0x60, 0xbc,
+ 0x86, 0x16, 0xfc, 0x5c, 0xf0, 0x75, 0xc2, 0x6f, 0x51, 0x4f, 0x71, 0xbb, 0x77, 0xed, 0xe8, 0x2b,
+ 0xf2, 0xe3, 0x7d, 0x02, 0xa8, 0xfe, 0x26, 0x8a, 0x40, 0x63, 0x8f, 0x14, 0x84, 0xd2, 0x00, 0x70,
+ 0x6a, 0xf3, 0xde, 0xf8, 0x66};
+constexpr const unsigned int rsa_key_4k_len = sizeof(rsa_key_4k);
+
+constexpr const unsigned char rsa_key_2k[] = {
+ 0x30, 0x82, 0x04, 0xbd, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x04, 0xa7, 0x30, 0x82, 0x04, 0xa3, 0x02, 0x01,
+ 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9d, 0xd0, 0xca, 0x63, 0xaa, 0x59, 0x73, 0x13, 0x55, 0x53,
+ 0xdc, 0x5d, 0x4d, 0xf9, 0x5c, 0x4f, 0x31, 0xe3, 0x34, 0x45, 0xbf, 0xc5, 0x8b, 0x43, 0x8f, 0x10,
+ 0xb6, 0x22, 0xaf, 0xe0, 0x12, 0xff, 0xf5, 0xa8, 0x71, 0x0a, 0xe9, 0x67, 0x8d, 0x05, 0xd2, 0x69,
+ 0x35, 0x32, 0x8d, 0x94, 0x9f, 0x52, 0x63, 0x4e, 0x54, 0x0b, 0x29, 0x3d, 0x7b, 0x5e, 0xc0, 0x98,
+ 0x94, 0x23, 0x43, 0x46, 0x39, 0xce, 0xc2, 0xe1, 0x2b, 0xcd, 0x00, 0x6c, 0x9d, 0xe7, 0x81, 0xb9,
+ 0x6b, 0x97, 0xea, 0x3a, 0xe7, 0x09, 0x06, 0x6b, 0xf3, 0xe1, 0x7a, 0x03, 0xcd, 0x51, 0x2c, 0x16,
+ 0x19, 0x6c, 0xdf, 0x2c, 0xd5, 0x96, 0x92, 0x19, 0xaa, 0x91, 0xe3, 0xa5, 0xc7, 0xe1, 0x0b, 0x07,
+ 0xb6, 0x84, 0xd3, 0xa7, 0x1f, 0x0d, 0x22, 0xb9, 0xc1, 0x76, 0x16, 0x81, 0x53, 0x50, 0x7d, 0x54,
+ 0x2a, 0x26, 0x9e, 0xfa, 0xb1, 0xb7, 0x83, 0x05, 0x24, 0x81, 0xea, 0x5a, 0x6c, 0xb5, 0x92, 0x69,
+ 0x63, 0x35, 0xfa, 0x04, 0xae, 0xee, 0xc5, 0xdb, 0xf0, 0x9b, 0xfe, 0xe6, 0xc4, 0x73, 0x18, 0x3d,
+ 0xd3, 0x01, 0xaf, 0x03, 0x43, 0x95, 0xca, 0xab, 0x43, 0x04, 0x64, 0x49, 0xe7, 0x47, 0xf8, 0x97,
+ 0xe5, 0x63, 0xd1, 0x3d, 0x21, 0x9b, 0xd5, 0x13, 0x2a, 0xb0, 0xf1, 0xf9, 0xff, 0xd2, 0xb7, 0x12,
+ 0xa8, 0xa0, 0x20, 0x38, 0xde, 0x41, 0x8e, 0xa3, 0xc7, 0xce, 0x5b, 0x9c, 0x30, 0x1a, 0xaf, 0x13,
+ 0x11, 0xd1, 0xd0, 0x71, 0x7f, 0x1e, 0x47, 0xa8, 0x32, 0x3b, 0x4a, 0x36, 0xa8, 0x6d, 0x8c, 0xd7,
+ 0x5f, 0x93, 0x95, 0xa8, 0xe0, 0xfa, 0x59, 0xb5, 0x6c, 0x1f, 0xfb, 0x01, 0x64, 0xf5, 0x5d, 0xf5,
+ 0x17, 0x75, 0x53, 0xfb, 0xc3, 0x3f, 0xd7, 0xc5, 0x45, 0x53, 0xb4, 0xa2, 0xcf, 0xa5, 0x71, 0xf0,
+ 0x7a, 0x8b, 0x66, 0x09, 0xfa, 0x4d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x03,
+ 0xe9, 0x06, 0x4d, 0x6a, 0xe2, 0xa0, 0x2b, 0x24, 0xa1, 0x99, 0x23, 0xb2, 0x08, 0xbc, 0x2f, 0x4a,
+ 0xd2, 0xa6, 0x30, 0x6b, 0x91, 0xd6, 0xf8, 0xb1, 0x0f, 0x9e, 0x71, 0x04, 0x94, 0xe8, 0xe8, 0xf1,
+ 0x00, 0x1f, 0xf0, 0xea, 0x70, 0x97, 0x8f, 0x6d, 0xde, 0x65, 0x24, 0x35, 0x5a, 0xd9, 0xdf, 0x13,
+ 0x8e, 0x7f, 0x74, 0x44, 0x02, 0x28, 0x7a, 0x39, 0x61, 0x19, 0x1b, 0xe3, 0x3b, 0xac, 0x62, 0x01,
+ 0x9f, 0xcc, 0xfd, 0xdd, 0x85, 0x53, 0x72, 0x46, 0xdb, 0x69, 0x1d, 0x90, 0xa9, 0xad, 0xf6, 0x22,
+ 0x1e, 0x6e, 0xf8, 0x06, 0xc0, 0x6d, 0x08, 0x16, 0x5a, 0x0e, 0x7e, 0x37, 0xec, 0xbc, 0xa1, 0x68,
+ 0x49, 0xa7, 0x84, 0x1e, 0xdf, 0xb4, 0x30, 0xa6, 0x1d, 0x26, 0x4f, 0x6b, 0x39, 0x1d, 0xad, 0x58,
+ 0x7a, 0x16, 0xca, 0x38, 0xc0, 0xdd, 0x3c, 0xc6, 0x26, 0x32, 0xe1, 0xd5, 0xc2, 0xeb, 0x6a, 0xa6,
+ 0x70, 0x1f, 0x50, 0x82, 0x2d, 0xf6, 0x09, 0x27, 0x56, 0x4f, 0xf1, 0xed, 0x62, 0x60, 0xe5, 0x55,
+ 0x0f, 0x8d, 0xbe, 0xd7, 0x5a, 0xb7, 0x7c, 0x57, 0x25, 0xe5, 0xa3, 0x46, 0xb6, 0x97, 0xe0, 0x87,
+ 0x43, 0x04, 0x46, 0xd8, 0x4f, 0xbe, 0x80, 0x75, 0x40, 0x48, 0x2d, 0xc0, 0x57, 0xf8, 0x76, 0xbd,
+ 0xd8, 0x14, 0xa0, 0x7b, 0x39, 0x4f, 0xcf, 0xdc, 0x34, 0x5b, 0x1e, 0x91, 0xef, 0xa7, 0xc8, 0x82,
+ 0x2c, 0xe8, 0xe4, 0x01, 0x2b, 0xa6, 0x92, 0x4e, 0x0b, 0xd1, 0x98, 0xdc, 0x45, 0x46, 0x3f, 0x89,
+ 0xb1, 0x01, 0xb5, 0xa7, 0xeb, 0x71, 0x2f, 0x09, 0x10, 0x3c, 0x71, 0x14, 0xf3, 0x86, 0x18, 0xa8,
+ 0x5a, 0x30, 0xef, 0xfe, 0x87, 0x65, 0xb1, 0xaf, 0x9c, 0x8d, 0x3e, 0xc8, 0x8d, 0x72, 0xf5, 0x16,
+ 0xcb, 0x3a, 0xb8, 0xb1, 0x18, 0xa5, 0x43, 0x1d, 0x24, 0xa1, 0x1c, 0x2d, 0x2d, 0x87, 0xc1, 0x02,
+ 0x81, 0x81, 0x00, 0xde, 0x87, 0xff, 0x74, 0x9d, 0x86, 0x9b, 0x0b, 0x18, 0xb7, 0xa4, 0x50, 0xda,
+ 0x2d, 0x27, 0xff, 0x0e, 0x4d, 0xae, 0x40, 0x21, 0x92, 0x0b, 0x1d, 0x8b, 0xdd, 0x81, 0xdc, 0x40,
+ 0x1c, 0xed, 0x7d, 0x39, 0xd6, 0x1d, 0xdd, 0x88, 0xd0, 0x92, 0xee, 0x74, 0xca, 0x96, 0xa7, 0x6a,
+ 0x58, 0xd3, 0xc6, 0xf4, 0x3e, 0x93, 0x43, 0x54, 0x07, 0x72, 0x3a, 0x8d, 0x3b, 0x09, 0xe0, 0x16,
+ 0x16, 0x71, 0xf1, 0xae, 0xc4, 0xc0, 0x46, 0xce, 0x40, 0x6d, 0xba, 0xf0, 0x4d, 0x1d, 0x04, 0x9a,
+ 0x32, 0x31, 0xe1, 0x07, 0x9b, 0x90, 0x7c, 0xc2, 0xb2, 0xfc, 0x4e, 0xb9, 0x61, 0xd4, 0xdb, 0x4a,
+ 0xa1, 0xb9, 0x78, 0x46, 0x98, 0xa9, 0xfb, 0x21, 0x60, 0xb8, 0x07, 0x6b, 0x24, 0x4d, 0x4d, 0x35,
+ 0x83, 0x0b, 0x21, 0xac, 0xdf, 0x93, 0x2f, 0xb5, 0xec, 0xe5, 0x99, 0x1a, 0x59, 0xaa, 0xd3, 0xbb,
+ 0x8f, 0xe9, 0xad, 0x02, 0x81, 0x81, 0x00, 0xb5, 0x8d, 0x14, 0x8e, 0x85, 0xd9, 0x7c, 0x9e, 0xfc,
+ 0xa1, 0x1f, 0x1a, 0x84, 0x31, 0x07, 0x71, 0x1a, 0x72, 0x91, 0xc0, 0xc5, 0xac, 0x8f, 0xa7, 0x0f,
+ 0x37, 0x48, 0x51, 0x12, 0xda, 0x0d, 0x30, 0x6d, 0x97, 0x21, 0x20, 0x90, 0x49, 0x4d, 0x2b, 0xc1,
+ 0x89, 0x8e, 0x00, 0x66, 0x18, 0x47, 0xd5, 0x68, 0x62, 0xe7, 0x29, 0xf4, 0x95, 0x59, 0x5b, 0xba,
+ 0x4b, 0xc2, 0x20, 0xda, 0xef, 0x4f, 0x33, 0x0e, 0x99, 0xfe, 0x6c, 0xec, 0xf9, 0xd8, 0x81, 0x3a,
+ 0x46, 0x1a, 0xbd, 0xba, 0xf7, 0xfc, 0xd7, 0x19, 0xf8, 0x2d, 0xd1, 0x81, 0x88, 0xce, 0x55, 0x98,
+ 0xe6, 0xbc, 0x25, 0x67, 0xa6, 0xbe, 0x2b, 0x0f, 0x1d, 0xb6, 0x0d, 0xea, 0xc6, 0xb6, 0x95, 0xee,
+ 0x42, 0x3e, 0x1b, 0xf5, 0x8c, 0xf3, 0x19, 0x8e, 0x59, 0xfc, 0xe1, 0x42, 0x1b, 0x26, 0x20, 0x09,
+ 0x8a, 0x1b, 0x57, 0x8e, 0xe1, 0xa7, 0x21, 0x02, 0x81, 0x80, 0x78, 0xc7, 0x33, 0x7d, 0x25, 0xaa,
+ 0x53, 0x28, 0x38, 0xa8, 0x23, 0x84, 0xc6, 0x85, 0xcf, 0xb9, 0x7d, 0x17, 0xe8, 0x45, 0x62, 0x73,
+ 0x13, 0x99, 0x5b, 0xba, 0x43, 0xab, 0x39, 0x18, 0xfa, 0x45, 0x07, 0x49, 0x11, 0x38, 0x95, 0xf3,
+ 0x2e, 0x6c, 0x41, 0xf3, 0x5a, 0xc5, 0x4e, 0xd1, 0x1b, 0x50, 0x56, 0x6c, 0x48, 0x1d, 0x38, 0xd4,
+ 0x39, 0xc9, 0x51, 0xb2, 0x03, 0x70, 0x1e, 0x4c, 0xdc, 0x57, 0x22, 0x56, 0x23, 0x4d, 0xca, 0xcf,
+ 0xe9, 0x3e, 0x97, 0x02, 0x23, 0x87, 0xc5, 0xf1, 0x0c, 0x65, 0x68, 0x6d, 0xa4, 0x84, 0x32, 0x60,
+ 0x56, 0xd4, 0x9b, 0x85, 0x5f, 0xb4, 0x0d, 0xd3, 0xad, 0x08, 0x7c, 0xb8, 0x8b, 0x39, 0x84, 0x2a,
+ 0x2c, 0x77, 0xca, 0x4d, 0x0f, 0xaf, 0xa2, 0x25, 0x97, 0xbb, 0x15, 0x4a, 0xdb, 0x65, 0xff, 0xc5,
+ 0xad, 0xef, 0xe4, 0xff, 0x59, 0xda, 0x45, 0x68, 0x9c, 0x99, 0x02, 0x81, 0x80, 0x16, 0x45, 0x0a,
+ 0xfb, 0x7c, 0x91, 0xb4, 0x06, 0xb0, 0x88, 0x77, 0x0f, 0x42, 0x9d, 0xdd, 0x02, 0xd3, 0xb2, 0xb0,
+ 0x0c, 0x4c, 0x73, 0x21, 0x5f, 0xe5, 0xae, 0xeb, 0x50, 0xfe, 0x95, 0xfe, 0xbe, 0x2d, 0x03, 0x37,
+ 0xce, 0x0d, 0xc4, 0xe0, 0x11, 0x78, 0xf9, 0x0d, 0x91, 0x20, 0xf4, 0xe3, 0x82, 0xda, 0xfe, 0x1e,
+ 0xca, 0xf7, 0xb4, 0x86, 0x34, 0x89, 0x42, 0x97, 0xba, 0x7e, 0x00, 0x92, 0xdf, 0x79, 0x70, 0x0c,
+ 0x54, 0x82, 0x31, 0x17, 0x8c, 0xaa, 0x80, 0x44, 0xf1, 0x77, 0x08, 0xca, 0x5b, 0xfc, 0x54, 0x84,
+ 0x12, 0x49, 0xe8, 0x65, 0x1e, 0xfc, 0xd5, 0x78, 0xc8, 0xc1, 0xd1, 0x23, 0x4c, 0x96, 0xdb, 0x17,
+ 0x24, 0xd7, 0xe2, 0xae, 0x2c, 0xef, 0xff, 0xf2, 0x2c, 0x6d, 0xcf, 0x6f, 0x56, 0x78, 0x2e, 0xb3,
+ 0xa5, 0x51, 0xfd, 0x90, 0x8c, 0xa7, 0x7e, 0xe8, 0x61, 0xb2, 0x26, 0x1d, 0xe1, 0x02, 0x81, 0x81,
+ 0x00, 0x88, 0xf6, 0x9a, 0xec, 0xab, 0xb6, 0x25, 0x2c, 0x12, 0x4e, 0x90, 0x8f, 0xea, 0xa2, 0x7e,
+ 0x62, 0x41, 0xd7, 0xfd, 0x7c, 0x5d, 0xaa, 0x83, 0xfa, 0xc7, 0x48, 0x51, 0x54, 0xed, 0x72, 0x59,
+ 0x95, 0xc0, 0x61, 0xdc, 0xfa, 0xc6, 0xb8, 0xd5, 0x5f, 0x9a, 0xd0, 0x7e, 0xcb, 0x3f, 0xc4, 0xfd,
+ 0xb4, 0x4d, 0x46, 0x74, 0xc4, 0xf0, 0x45, 0xd4, 0x62, 0xdc, 0x27, 0x37, 0x4a, 0x8a, 0xcf, 0x27,
+ 0x1a, 0x6f, 0x00, 0x50, 0x12, 0x99, 0x8d, 0xd7, 0xa8, 0xdf, 0xf3, 0xa4, 0x61, 0x18, 0x4f, 0xed,
+ 0x1d, 0xac, 0x51, 0xd4, 0x44, 0x2f, 0x73, 0xea, 0xe7, 0xd7, 0xd2, 0x81, 0xe1, 0xe8, 0x4e, 0x0a,
+ 0xeb, 0xbd, 0x40, 0x2b, 0x62, 0xb3, 0x43, 0x60, 0x72, 0x73, 0x31, 0xc0, 0x7a, 0x16, 0x15, 0x83,
+ 0x71, 0x2f, 0x2e, 0xb4, 0x17, 0x43, 0x12, 0x30, 0x08, 0xef, 0x72, 0xdb, 0xc9, 0x50, 0x28, 0x5a,
+ 0xda};
+constexpr const unsigned int rsa_key_2k_len = sizeof(rsa_key_2k);
\ No newline at end of file
diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs
new file mode 100644
index 0000000..1c678c3
--- /dev/null
+++ b/keystore2/src/utils.rs
@@ -0,0 +1,138 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This module implements utility functions used by the Keystore 2.0 service
+//! implementation.
+
+use crate::permission;
+use crate::permission::{KeyPerm, KeyPermSet, KeystorePerm};
+use crate::{error::Error, key_parameter::KeyParameterValue};
+use android_hardware_keymint::aidl::android::hardware::keymint::{
+ KeyCharacteristics::KeyCharacteristics, SecurityLevel::SecurityLevel,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+ Authorization::Authorization, KeyDescriptor::KeyDescriptor,
+};
+use anyhow::{anyhow, Context};
+use binder::{FromIBinder, SpIBinder, ThreadState};
+use std::sync::Mutex;
+
+/// This function uses its namesake in the permission module and in
+/// combination with with_calling_sid from the binder crate to check
+/// if the caller has the given keystore permission.
+pub fn check_keystore_permission(perm: KeystorePerm) -> anyhow::Result<()> {
+ ThreadState::with_calling_sid(|calling_sid| {
+ permission::check_keystore_permission(
+ &calling_sid.ok_or_else(Error::sys).context(
+ "In check_keystore_permission: Cannot check permission without calling_sid.",
+ )?,
+ perm,
+ )
+ })
+}
+
+/// This function uses its namesake in the permission module and in
+/// combination with with_calling_sid from the binder crate to check
+/// if the caller has the given grant permission.
+pub fn check_grant_permission(access_vec: KeyPermSet, key: &KeyDescriptor) -> anyhow::Result<()> {
+ ThreadState::with_calling_sid(|calling_sid| {
+ permission::check_grant_permission(
+ &calling_sid.ok_or_else(Error::sys).context(
+ "In check_grant_permission: Cannot check permission without calling_sid.",
+ )?,
+ access_vec,
+ key,
+ )
+ })
+}
+
+/// This function uses its namesake in the permission module and in
+/// combination with with_calling_sid from the binder crate to check
+/// if the caller has the given key permission.
+pub fn check_key_permission(
+ perm: KeyPerm,
+ key: &KeyDescriptor,
+ access_vector: &Option<KeyPermSet>,
+) -> anyhow::Result<()> {
+ ThreadState::with_calling_sid(|calling_sid| {
+ permission::check_key_permission(
+ &calling_sid
+ .ok_or_else(Error::sys)
+ .context("In check_key_permission: Cannot check permission without calling_sid.")?,
+ perm,
+ key,
+ access_vector,
+ )
+ })
+}
+
+/// Thread safe wrapper around SpIBinder. It is safe to have SpIBinder smart pointers to the
+/// same object in multiple threads, but cloning a SpIBinder is not thread safe.
+/// Keystore frequently hands out binder tokens to the security level interface. If this
+/// is to happen from a multi threaded thread pool, the SpIBinder needs to be protected by a
+/// Mutex.
+#[derive(Debug)]
+pub struct Asp(Mutex<SpIBinder>);
+
+impl Asp {
+ /// Creates a new instance owning a SpIBinder wrapped in a Mutex.
+ pub fn new(i: SpIBinder) -> Self {
+ Self(Mutex::new(i))
+ }
+
+ /// Clones the owned SpIBinder and attempts to convert it into the requested interface.
+ pub fn get_interface<T: FromIBinder + ?Sized>(&self) -> anyhow::Result<Box<T>> {
+ // We can use unwrap here because we never panic when locked, so the mutex
+ // can never be poisoned.
+ let lock = self.0.lock().unwrap();
+ (*lock)
+ .clone()
+ .into_interface()
+ .map_err(|e| anyhow!(format!("get_interface failed with error code {:?}", e)))
+ }
+}
+
+/// Converts a set of key characteristics as returned from KeyMint into the internal
+/// representation of the keystore service.
+/// The parameter `hw_security_level` indicates which security level shall be used for
+/// parameters found in the hardware enforced parameter list.
+pub fn key_characteristics_to_internal(
+ key_characteristics: KeyCharacteristics,
+ hw_security_level: SecurityLevel,
+) -> Vec<crate::key_parameter::KeyParameter> {
+ key_characteristics
+ .hardwareEnforced
+ .into_iter()
+ .map(|aidl_kp| {
+ crate::key_parameter::KeyParameter::new(
+ KeyParameterValue::convert_from_wire(aidl_kp),
+ hw_security_level,
+ )
+ })
+ .chain(key_characteristics.softwareEnforced.into_iter().map(|aidl_kp| {
+ crate::key_parameter::KeyParameter::new(
+ KeyParameterValue::convert_from_wire(aidl_kp),
+ SecurityLevel::SOFTWARE,
+ )
+ }))
+ .collect()
+}
+
+/// Converts a set of key characteristics from the internal representation into a set of
+/// Authorizations as they are used to convey key characteristics to the clients of keystore.
+pub fn key_parameters_to_authorizations(
+ parameters: Vec<crate::key_parameter::KeyParameter>,
+) -> Vec<Authorization> {
+ parameters.into_iter().map(|p| p.into_authorization()).collect()
+}
diff --git a/provisioner/Android.bp b/provisioner/Android.bp
new file mode 100644
index 0000000..c1c8d15
--- /dev/null
+++ b/provisioner/Android.bp
@@ -0,0 +1,44 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+aidl_interface {
+ name: "android.security.provisioner",
+ unstable: true,
+ local_include_dir: "binder",
+ srcs: [
+ "binder/android/security/provisioner/*.aidl",
+ ],
+ backend: {
+ java: {
+ platform_apis: true,
+ },
+ cpp: {
+ enabled: false,
+ },
+ ndk: {
+ enabled: false,
+ },
+ },
+}
+
+java_binary {
+ name: "provisioner_cli",
+ wrapper: "provisioner_cli",
+ srcs: ["src/com/android/commands/provisioner/**/*.java"],
+ static_libs: [
+ "android.security.provisioner-java",
+ ],
+}
diff --git a/provisioner/binder/android/security/provisioner/IProvisionerService.aidl b/provisioner/binder/android/security/provisioner/IProvisionerService.aidl
new file mode 100644
index 0000000..f81e9ab
--- /dev/null
+++ b/provisioner/binder/android/security/provisioner/IProvisionerService.aidl
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.provisioner;
+
+/**
+ * @hide
+ */
+interface IProvisionerService {
+ byte[] getCertificateRequest(in boolean testMode,
+ in int keyCount,
+ in byte[] endpointEncryptionKey,
+ in byte[] challenge) = 0;
+}
diff --git a/provisioner/provisioner_cli b/provisioner/provisioner_cli
new file mode 100755
index 0000000..7b53d6e
--- /dev/null
+++ b/provisioner/provisioner_cli
@@ -0,0 +1,21 @@
+#!/system/bin/sh
+#
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Script to start "provisioner_cli" on the device.
+#
+base=/system
+export CLASSPATH=$base/framework/provisioner_cli.jar
+exec app_process $base/bin com.android.commands.provisioner.Cli "$@"
diff --git a/provisioner/src/com/android/commands/provisioner/Cli.java b/provisioner/src/com/android/commands/provisioner/Cli.java
new file mode 100644
index 0000000..62afdac
--- /dev/null
+++ b/provisioner/src/com/android/commands/provisioner/Cli.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.provisioner;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.security.provisioner.IProvisionerService;
+
+import com.android.internal.os.BaseCommand;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.IllegalArgumentException;
+
+/**
+ * Contains the implementation of the remote provisioning command-line interface.
+ */
+public class Cli extends BaseCommand {
+ /**
+ * Creates an instance of the command-line interface and runs it. This is the entry point of
+ * the tool.
+ */
+ public static void main(String[] args) {
+ new Cli().run(args);
+ }
+
+ /**
+ * Runs the command requested by the invoker. It parses the very first required argument, which
+ * is the command, and calls the appropriate handler.
+ */
+ @Override
+ public void onRun() throws Exception {
+ String cmd = nextArgRequired();
+ switch (cmd) {
+ case "get-req":
+ getRequest();
+ break;
+
+ case "help":
+ onShowUsage(System.out);
+ break;
+
+ default:
+ throw new IllegalArgumentException("unknown command: " + cmd);
+ }
+ }
+
+ /**
+ * Retrieves a 'certificate request' from the provisioning service. The COSE-encoded
+ * 'certificate chain' describing the endpoint encryption key (EEK) to use for encryption is
+ * read from the standard input. The retrieved request is written to the standard output.
+ */
+ private void getRequest() throws Exception {
+ // Process options.
+ boolean test = false;
+ byte[] challenge = null;
+ int count = 0;
+ String arg;
+ while ((arg = nextArg()) != null) {
+ switch (arg) {
+ case "--test":
+ test = true;
+ break;
+
+ case "--challenge":
+ // TODO: We may need a different encoding of the challenge.
+ challenge = nextArgRequired().getBytes();
+ break;
+
+ case "--count":
+ count = Integer.parseInt(nextArgRequired());
+ if (count < 0) {
+ throw new IllegalArgumentException(
+ "--count must be followed by non-negative number");
+ }
+ break;
+
+ default:
+ throw new IllegalArgumentException("unknown argument: " + arg);
+ }
+ }
+
+ // Send the request over to the provisioning service and write the result to stdout.
+ byte[] res = getService().getCertificateRequest(test, count, readAll(System.in), challenge);
+ if (res != null) {
+ System.out.write(res);
+ }
+ }
+
+ /**
+ * Retrieves an implementation of the IProvisionerService interface. It allows the caller to
+ * call into the service via binder.
+ */
+ private static IProvisionerService getService() throws RemoteException {
+ IBinder binder = ServiceManager.getService("remote-provisioner");
+ if (binder == null) {
+ throw new RemoteException("Provisioning service is inaccessible");
+ }
+ return IProvisionerService.Stub.asInterface(binder);
+ }
+
+ /** Reads all data from the provided input stream and returns it as a byte array. */
+ private static byte[] readAll(InputStream in) throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ byte[] buf = new byte[1024];
+ int read;
+ while ((read = in.read(buf)) != -1) {
+ out.write(buf, 0, read);
+ }
+ return out.toByteArray();
+ }
+
+ /**
+ * Writes the usage information to the given stream. This is displayed to users of the tool when
+ * they ask for help or when they pass incorrect arguments to the tool.
+ */
+ @Override
+ public void onShowUsage(PrintStream out) {
+ out.println(
+ "Usage: provisioner_cli <command> [options]\n" +
+ "Commands: help\n" +
+ " get-req [--count <n>] [--test] [--challenge <v>]");
+ }
+}