Merge "Adding TEST_MAPPING to system/security/keystore"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 68df61f..9b96f36 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -4,7 +4,7 @@
[Builtin Hooks Options]
clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
-rustfmt = --check --config-path=rustfmt.toml ${PREUPLOAD_FILES}
+rustfmt = --config-path=rustfmt.toml
[Hook Scripts]
aosp_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "."
diff --git a/keystore/Android.bp b/keystore/Android.bp
index b881757..45b721b 100644
--- a/keystore/Android.bp
+++ b/keystore/Android.bp
@@ -34,8 +34,9 @@
"blob.cpp",
"confirmation_manager.cpp",
"grant_store.cpp",
- "key_config.proto",
- "key_proto_handler.cpp",
+ "key_creation_log_handler.cpp",
+ "key_operation_log_handler.cpp",
+ "key_attestation_log_handler.cpp",
"key_store_service.cpp",
"keyblob_utils.cpp",
"keymaster_enforcement.cpp",
@@ -44,8 +45,6 @@
"keystore_utils.cpp",
"legacy_keymaster_device_wrapper.cpp",
"operation.cpp",
- "operation_config.proto",
- "operation_proto_handler.cpp",
"permissions.cpp",
"user_state.cpp",
],
@@ -74,6 +73,7 @@
"libservices",
"libsoftkeymasterdevice",
"libutils",
+ "libstatslog",
],
init_rc: ["keystore.rc"],
aidl: {
diff --git a/keystore/KeyStore.h b/keystore/KeyStore.h
index 0027ec8..7841a80 100644
--- a/keystore/KeyStore.h
+++ b/keystore/KeyStore.h
@@ -62,9 +62,9 @@
} // namespace keystore
namespace std {
-template <typename T, size_t count> struct tuple_size<keystore::Devices<T, count>> {
+template <typename T, size_t N> struct tuple_size<keystore::Devices<T, N>> {
public:
- static constexpr size_t value = std::tuple_size<std::array<T, count>>::value;
+ static constexpr size_t value = std::tuple_size<std::array<T, N>>::value;
};
} // namespace std
diff --git a/keystore/include/keystore/keystore.h b/keystore/include/keystore/keystore.h
index 3aed8c2..f840eb7 100644
--- a/keystore/include/keystore/keystore.h
+++ b/keystore/include/keystore/keystore.h
@@ -45,6 +45,21 @@
OP_AUTH_NEEDED = 15, // Auth is needed for this operation before it can be used.
KEY_ALREADY_EXISTS = 16,
KEY_PERMANENTLY_INVALIDATED = 17,
+
+ /**
+ * Following three response codes are for logging purposes only.
+ * The operations are logged at the end of the life cycle of an operation handle,
+ * along with the reason for the end of the operation handle. For the operations
+ * that fail in update and finish, the reason for failure is available with
+ * the above response codes.
+ * For the operations that are aborted in three different ways, the reason
+ * for aborting is not available. The following enum values define the
+ * three ways an operation can get aborted.
+ */
+ ABORT_CALLED = 18,
+ PRUNED = 19,
+ BINDER_DIED = 20,
+
};
/*
diff --git a/keystore/key_proto_handler.h b/keystore/key_attestation_log_handler.cpp
similarity index 66%
copy from keystore/key_proto_handler.h
copy to keystore/key_attestation_log_handler.cpp
index a2f6a24..34c76a3 100644
--- a/keystore/key_proto_handler.h
+++ b/keystore/key_attestation_log_handler.cpp
@@ -13,17 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#ifndef KEYSTORE_KEY_PROTO_HANDLER_H_
-#define KEYSTORE_KEY_PROTO_HANDLER_H_
-
-#include <keystore/keystore_hidl_support.h>
-
+#include <statslog.h>
namespace keystore {
-void uploadKeyCharacteristicsAsProto(const hidl_vec<KeyParameter>& keyParams,
- bool wasCreationSuccessful);
+void logKeystoreKeyAttestationEvent(bool wasSuccessful, int32_t errorCode) {
+ android::util::stats_write(android::util::KEYSTORE_KEY_EVENT_REPORTED,
+ android::util::KEYSTORE_KEY_EVENT_REPORTED__TYPE__KEY_ATTESTATION,
+ wasSuccessful, errorCode);
+}
-} // namespace keystore
-
-#endif // KEYSTORE_KEY_PROTO_HANDLER_H_
+} // namespace keystore
\ No newline at end of file
diff --git a/keystore/key_proto_handler.h b/keystore/key_attestation_log_handler.h
similarity index 66%
copy from keystore/key_proto_handler.h
copy to keystore/key_attestation_log_handler.h
index a2f6a24..e69e667 100644
--- a/keystore/key_proto_handler.h
+++ b/keystore/key_attestation_log_handler.h
@@ -14,16 +14,13 @@
* limitations under the License.
*/
-#ifndef KEYSTORE_KEY_PROTO_HANDLER_H_
-#define KEYSTORE_KEY_PROTO_HANDLER_H_
-
-#include <keystore/keystore_hidl_support.h>
+#ifndef _KEY_ATTESTATION_LOG_HANDLER_H_
+#define _KEY_ATTESTATION_LOG_HANDLER_H_
namespace keystore {
-void uploadKeyCharacteristicsAsProto(const hidl_vec<KeyParameter>& keyParams,
- bool wasCreationSuccessful);
+void logKeystoreKeyAttestationEvent(bool wasSuccessful, int32_t errorCode);
-} // namespace keystore
+}
-#endif // KEYSTORE_KEY_PROTO_HANDLER_H_
+#endif //_KEY_ATTESTATION_LOG_HANDLER_H_
\ No newline at end of file
diff --git a/keystore/key_config.proto b/keystore/key_config.proto
deleted file mode 100644
index 0b1a398..0000000
--- a/keystore/key_config.proto
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-syntax = "proto2";
-
-package keystore;
-
-option optimize_for = LITE_RUNTIME;
-
-message KeyConfig {
- // What type of encryption algorithm is this key being generated/imported for
- // e.g. AES, RSA, etc
- optional string algorithm = 1;
-
- // Size of the key being generated/imported
- optional int32 key_size = 2;
-
- // Log whether the key was generated, imported, securely imported, or derived.
- optional string origin = 3;
-
- // What auth types does this key require? If none, then no auth required.
- optional string user_auth_type = 4;
-
- // If user authentication is required, is the requirement time based? If it
- // is not time based then this field will not be used and the key is per
- // operation. Per operation keys must be user authenticated on each usage.
- optional int32 user_auth_key_timeout = 5;
-
- // Track which padding modes this key supports.
- repeated string padding = 6;
-
- // Track which digests this key supports
- repeated string digest = 7;
-
- // Check what block mode is being used depending on the mode of encryption
- repeated string block_mode = 8;
-
- // Was the key generated/imported successfully?
- optional bool was_creation_successful = 9;
-
- // What purposes can this key be used for?
- repeated string purpose = 10;
-
- // Which ec curve was selected if elliptic curve cryptography is in use
- optional string ec_curve = 11;
-
- // Standalone or is a file system required
- optional string key_blob_usage_reqs = 12;
-}
diff --git a/keystore/key_creation_log_handler.cpp b/keystore/key_creation_log_handler.cpp
new file mode 100644
index 0000000..d846257
--- /dev/null
+++ b/keystore/key_creation_log_handler.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2018 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 "KeystoreOperation"
+
+#include "key_creation_log_handler.h"
+#include <statslog.h>
+
+namespace keystore {
+
+template <typename Tag>
+int32_t getEnumTagValue(const AuthorizationSet& authorization_set, Tag tag) {
+ auto tagValue = authorization_set.GetTagValue(tag);
+ if (tagValue.isOk()) {
+ static_assert(sizeof(decltype(tagValue.value())) <= sizeof(int32_t),
+ "Tag type value will be truncated, if cast to int32_t");
+ return static_cast<int32_t>(tagValue.value());
+ }
+ // Usually, if the value is not present, 0 is set. However, since 0 is a valid
+ // enum value, -1 is set for single enum fields.
+ return -1;
+}
+
+int32_t generateBitMapForPaddingModeValues(const AuthorizationSet& authorization_set) {
+ int32_t bitMap = 0;
+ int32_t tagValueCount = authorization_set.GetTagCount(TAG_PADDING);
+ if (tagValueCount == 0) {
+ // unlike in the single enum fields, if no value is provided,
+ // 0 is set for the bitmap
+ return bitMap;
+ }
+ int current_offset = -1;
+ while (tagValueCount > 0) {
+ current_offset = authorization_set.find(TAG_PADDING, current_offset);
+ KeyParameter keyParam = authorization_set[current_offset];
+ auto tagValue = accessTagValue(TAG_PADDING, keyParam);
+ switch (tagValue) {
+ case PaddingMode::NONE:
+ bitMap |= (1 << NONE_BIT_POS);
+ break;
+ case PaddingMode::RSA_OAEP:
+ bitMap |= (1 << PaddingModeBitPosition::RSA_OAEP_BIT_POS);
+ break;
+ case PaddingMode::RSA_PSS:
+ bitMap |= (1 << PaddingModeBitPosition::RSA_PSS_BIT_POS);
+ break;
+ case PaddingMode::RSA_PKCS1_1_5_ENCRYPT:
+ bitMap |= (1 << PaddingModeBitPosition::RSA_PKCS1_1_5_ENCRYPT_BIT_POS);
+ break;
+ case PaddingMode::RSA_PKCS1_1_5_SIGN:
+ bitMap |= (1 << PaddingModeBitPosition::RSA_PKCS1_1_5_SIGN_BIT_POS);
+ break;
+ case PaddingMode::PKCS7:
+ bitMap |= (1 << PaddingModeBitPosition::PKCS7_BIT_POS);
+ break;
+ default:
+ break;
+ }
+ tagValueCount -= 1;
+ }
+ return bitMap;
+}
+
+int32_t generateBitMapForDigestValues(const AuthorizationSet& authorization_set) {
+ int32_t bitMap = 0;
+ int32_t tagValueCount = authorization_set.GetTagCount(TAG_DIGEST);
+ if (tagValueCount == 0) {
+ // unlike in the single enum fields, if no value is provided,
+ // 0 is set for the bitmap
+ return bitMap;
+ }
+ int current_offset = -1;
+ while (tagValueCount > 0) {
+ current_offset = authorization_set.find(TAG_DIGEST, current_offset);
+ KeyParameter keyParam = authorization_set[current_offset];
+ auto tagValue = accessTagValue(TAG_DIGEST, keyParam);
+ switch (tagValue) {
+ case Digest::NONE:
+ bitMap |= (1 << NONE_BIT_POS);
+ break;
+ case Digest::MD5:
+ bitMap |= (1 << DigestBitPosition::MD5_BIT_POS);
+ break;
+ case Digest::SHA1:
+ bitMap |= (1 << DigestBitPosition::SHA1_BIT_POS);
+ break;
+ case Digest::SHA_2_224:
+ bitMap |= (1 << DigestBitPosition::SHA_2_224_BIT_POS);
+ break;
+ case Digest::SHA_2_256:
+ bitMap |= (1 << DigestBitPosition::SHA_2_256_BIT_POS);
+ break;
+ case Digest::SHA_2_384:
+ bitMap |= (1 << DigestBitPosition::SHA_2_384_BIT_POS);
+ break;
+ case Digest::SHA_2_512:
+ bitMap |= (1 << DigestBitPosition::SHA_2_512_BIT_POS);
+ break;
+ default:
+ break;
+ }
+ tagValueCount -= 1;
+ }
+ return bitMap;
+}
+
+int32_t generateBitMapForBlockModeValues(const AuthorizationSet& authorization_set) {
+ int32_t bitMap = 0;
+ int32_t tagValueCount = authorization_set.GetTagCount(TAG_BLOCK_MODE);
+ if (tagValueCount == 0) {
+ // unlike in the single enum fields, if no value is provided,
+ // 0 is set for the bitmap
+ return bitMap;
+ }
+ int current_offset = -1;
+ while (tagValueCount > 0) {
+ current_offset = authorization_set.find(TAG_BLOCK_MODE, current_offset);
+ KeyParameter keyParam = authorization_set[current_offset];
+ auto tagValue = accessTagValue(TAG_BLOCK_MODE, keyParam);
+ switch (tagValue) {
+ case BlockMode::ECB:
+ bitMap |= (1 << BlockModeBitPosition::ECB_BIT_POS);
+ break;
+ case BlockMode::CBC:
+ bitMap |= (1 << BlockModeBitPosition::CBC_BIT_POS);
+ break;
+ case BlockMode::CTR:
+ bitMap |= (1 << BlockModeBitPosition::CTR_BIT_POS);
+ break;
+ case BlockMode::GCM:
+ bitMap |= (1 << BlockModeBitPosition::GCM_BIT_POS);
+ break;
+ default:
+ break;
+ }
+ tagValueCount -= 1;
+ }
+ return bitMap;
+}
+
+int32_t generateBitMapForKeyPurposeValues(const AuthorizationSet& authorization_set) {
+ int32_t bitMap = 0;
+ int32_t tagValueCount = authorization_set.GetTagCount(TAG_PURPOSE);
+ if (tagValueCount == 0) {
+ // unlike in the single enum fields, if no value is provided,
+ // 0 is set for the bitmap
+ return bitMap;
+ }
+ int current_offset = -1;
+ while (tagValueCount > 0) {
+ current_offset = authorization_set.find(TAG_PURPOSE, current_offset);
+ KeyParameter keyParam = authorization_set[current_offset];
+ auto tagValue = accessTagValue(TAG_PURPOSE, keyParam);
+ switch (tagValue) {
+ case KeyPurpose::ENCRYPT:
+ bitMap |= (1 << KeyPurposeBitPosition::ENCRYPT_BIT_POS);
+ break;
+ case KeyPurpose::DECRYPT:
+ bitMap |= (1 << KeyPurposeBitPosition::DECRYPT_BIT_POS);
+ break;
+ case KeyPurpose::SIGN:
+ bitMap |= (1 << KeyPurposeBitPosition::SIGN_BIT_POS);
+ break;
+ case KeyPurpose::VERIFY:
+ bitMap |= (1 << KeyPurposeBitPosition::VERIFY_BIT_POS);
+ break;
+ case KeyPurpose::WRAP_KEY:
+ bitMap |= (1 << KeyPurposeBitPosition::WRAP_KEY_BIT_POS);
+ break;
+ default:
+ break;
+ }
+ tagValueCount -= 1;
+ }
+ return bitMap;
+}
+
+void logKeystoreKeyCreationEvent(const hidl_vec<KeyParameter>& keyParams,
+ bool wasCreationSuccessful, int32_t errorCode) {
+ AuthorizationSet authorization_set(keyParams);
+ authorization_set.Deduplicate();
+
+ android::util::stats_write(android::util::KEYSTORE_KEY_EVENT_REPORTED,
+ getEnumTagValue(authorization_set, TAG_ALGORITHM),
+ getEnumTagValue(authorization_set, TAG_KEY_SIZE),
+ getEnumTagValue(authorization_set, TAG_ORIGIN),
+ getEnumTagValue(authorization_set, TAG_USER_AUTH_TYPE),
+ getEnumTagValue(authorization_set, TAG_AUTH_TIMEOUT),
+ generateBitMapForPaddingModeValues(authorization_set),
+ generateBitMapForDigestValues(authorization_set),
+ generateBitMapForBlockModeValues(authorization_set),
+ generateBitMapForKeyPurposeValues(authorization_set),
+ getEnumTagValue(authorization_set, TAG_EC_CURVE),
+ getEnumTagValue(authorization_set, TAG_BLOB_USAGE_REQUIREMENTS),
+ android::util::KEYSTORE_KEY_EVENT_REPORTED__TYPE__KEY_CREATION,
+ wasCreationSuccessful, errorCode);
+}
+
+} // namespace keystore
diff --git a/keystore/key_creation_log_handler.h b/keystore/key_creation_log_handler.h
new file mode 100644
index 0000000..a314eb1
--- /dev/null
+++ b/keystore/key_creation_log_handler.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 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 KEY_CREATION_LOG_HANDLER_H_
+#define KEY_CREATION_LOG_HANDLER_H_
+
+#include <keystore/keystore_hidl_support.h>
+
+namespace keystore {
+
+/**
+ * Following enums are defined as a part of the workaround to log the repeated
+ * values of ENUM_REP type. The workaround is to represent the repeated values
+ * of ENUM_REP type as a bitmap and the following enums define their positions
+ * in the bitmap.
+ */
+
+enum PaddingModeBitPosition : int32_t {
+ RSA_OAEP_BIT_POS = 1,
+ RSA_PSS_BIT_POS = 2,
+ RSA_PKCS1_1_5_ENCRYPT_BIT_POS = 3,
+ RSA_PKCS1_1_5_SIGN_BIT_POS = 4,
+ PKCS7_BIT_POS = 5,
+};
+
+enum DigestBitPosition : int32_t {
+ MD5_BIT_POS = 1,
+ SHA1_BIT_POS = 2,
+ SHA_2_224_BIT_POS = 3,
+ SHA_2_256_BIT_POS = 4,
+ SHA_2_384_BIT_POS = 5,
+ SHA_2_512_BIT_POS = 6,
+};
+
+enum BlockModeBitPosition : int32_t {
+ ECB_BIT_POS = 1,
+ CBC_BIT_POS = 2,
+ CTR_BIT_POS = 3,
+ GCM_BIT_POS = 4,
+};
+
+enum KeyPurposeBitPosition : int32_t {
+ ENCRYPT_BIT_POS = 1,
+ DECRYPT_BIT_POS = 2,
+ SIGN_BIT_POS = 3,
+ VERIFY_BIT_POS = 4,
+ WRAP_KEY_BIT_POS = 5,
+};
+
+// None is an enum value for digest and a deprecated value for padding mode
+const int32_t NONE_BIT_POS = 0;
+
+void logKeystoreKeyCreationEvent(const hidl_vec<KeyParameter>& keyParams,
+ bool wasCreationSuccessful, int32_t errorCode);
+
+} // namespace keystore
+
+#endif // KEY_CREATION_LOG_HANDLER_H_
diff --git a/keystore/key_operation_log_handler.cpp b/keystore/key_operation_log_handler.cpp
new file mode 100644
index 0000000..140d5a7
--- /dev/null
+++ b/keystore/key_operation_log_handler.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2018 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 "KeystoreOperation"
+
+#include "key_operation_log_handler.h"
+#include "key_creation_log_handler.h"
+
+#include <keystore/keystore_hidl_support.h>
+#include <statslog.h>
+
+namespace keystore {
+
+template <typename Tag>
+int32_t getOptionalEnumTagValue(const AuthorizationSet& authorization_set, Tag tag) {
+ auto tagValue = authorization_set.GetTagValue(tag);
+ if (tagValue.isOk()) {
+ static_assert(sizeof(decltype(tagValue.value())) <= sizeof(int32_t),
+ "Tag type value will be truncated, if cast to int32_t");
+ return static_cast<int32_t>(tagValue.value());
+ }
+ //-1 is an invalid value for all enum types.
+ return -1;
+}
+
+int32_t generateBitMapForPaddingModeValue(const AuthorizationSet& authorization_set) {
+ auto tagValue = authorization_set.GetTagValue(TAG_PADDING);
+ if (tagValue.isOk()) {
+ auto value = tagValue.value();
+ switch (value) {
+ case PaddingMode::NONE:
+ return (1 << NONE_BIT_POS);
+ case PaddingMode::RSA_OAEP:
+ return (1 << PaddingModeBitPosition::RSA_OAEP_BIT_POS);
+ case PaddingMode::RSA_PSS:
+ return (1 << PaddingModeBitPosition::RSA_PSS_BIT_POS);
+ case PaddingMode::RSA_PKCS1_1_5_ENCRYPT:
+ return (1 << PaddingModeBitPosition::RSA_PKCS1_1_5_ENCRYPT_BIT_POS);
+ case PaddingMode::RSA_PKCS1_1_5_SIGN:
+ return (1 << PaddingModeBitPosition::RSA_PKCS1_1_5_SIGN_BIT_POS);
+ case PaddingMode::PKCS7:
+ return (1 << PaddingModeBitPosition::PKCS7_BIT_POS);
+ default:
+ break;
+ }
+ }
+ // unlike in the single enum fields, if no value is provided,
+ // 0 is set for the bitmap
+ return 0;
+}
+
+int32_t generateBitMapForDigestValue(const AuthorizationSet& authorization_set) {
+ auto tagValue = authorization_set.GetTagValue(TAG_DIGEST);
+ if (tagValue.isOk()) {
+ auto value = tagValue.value();
+ switch (value) {
+ case Digest::NONE:
+ return (1 << NONE_BIT_POS);
+ case Digest::MD5:
+ return (1 << DigestBitPosition::MD5_BIT_POS);
+ case Digest::SHA1:
+ return (1 << DigestBitPosition::SHA1_BIT_POS);
+ case Digest::SHA_2_224:
+ return (1 << DigestBitPosition::SHA_2_224_BIT_POS);
+ case Digest::SHA_2_256:
+ return (1 << DigestBitPosition::SHA_2_256_BIT_POS);
+ case Digest::SHA_2_384:
+ return (1 << DigestBitPosition::SHA_2_384_BIT_POS);
+ case Digest::SHA_2_512:
+ return (1 << DigestBitPosition::SHA_2_512_BIT_POS);
+ default:
+ break;
+ }
+ }
+ // unlike in the single enum fields, if no value is provided,
+ // 0 is set for the bitmap
+ return 0;
+}
+
+int32_t generateBitMapForBlockModeValue(const AuthorizationSet& authorization_set) {
+ auto tagValue = authorization_set.GetTagValue(TAG_BLOCK_MODE);
+ if (tagValue.isOk()) {
+ auto value = tagValue.value();
+ switch (value) {
+ case BlockMode::ECB:
+ return (1 << BlockModeBitPosition::ECB_BIT_POS);
+ case BlockMode::CBC:
+ return (1 << BlockModeBitPosition::CBC_BIT_POS);
+ case BlockMode::CTR:
+ return (1 << BlockModeBitPosition::CTR_BIT_POS);
+ case BlockMode::GCM:
+ return (1 << BlockModeBitPosition::GCM_BIT_POS);
+ default:
+ break;
+ }
+ }
+ // unlike in the single enum fields, if no value is provided,
+ // 0 is set for the bitmap
+ return 0;
+}
+
+void logKeystoreKeyOperationEvent(const Operation& op, bool wasOperationSuccessful,
+ int32_t responseCode) {
+ AuthorizationSet authorization_set(op.characteristics.softwareEnforced);
+ authorization_set.Union(op.characteristics.hardwareEnforced);
+ AuthorizationSet operation_params(op.params);
+
+ android::util::stats_write(
+ android::util::KEYSTORE_KEY_EVENT_REPORTED,
+ getOptionalEnumTagValue(authorization_set, TAG_ALGORITHM),
+ getOptionalEnumTagValue(authorization_set, TAG_KEY_SIZE),
+ getOptionalEnumTagValue(authorization_set, TAG_ORIGIN),
+ getOptionalEnumTagValue(authorization_set, TAG_USER_AUTH_TYPE),
+ getOptionalEnumTagValue(authorization_set, TAG_AUTH_TIMEOUT),
+ generateBitMapForPaddingModeValue(operation_params),
+ generateBitMapForDigestValue(operation_params),
+ generateBitMapForBlockModeValue(operation_params), static_cast<int32_t>(op.purpose),
+ getOptionalEnumTagValue(authorization_set, TAG_EC_CURVE),
+ getOptionalEnumTagValue(authorization_set, TAG_BLOB_USAGE_REQUIREMENTS),
+ android::util::KEYSTORE_KEY_EVENT_REPORTED__TYPE__KEY_OPERATION, wasOperationSuccessful,
+ responseCode);
+}
+
+} // namespace keystore
diff --git a/keystore/key_proto_handler.h b/keystore/key_operation_log_handler.h
similarity index 68%
rename from keystore/key_proto_handler.h
rename to keystore/key_operation_log_handler.h
index a2f6a24..efd3f00 100644
--- a/keystore/key_proto_handler.h
+++ b/keystore/key_operation_log_handler.h
@@ -14,16 +14,15 @@
* limitations under the License.
*/
-#ifndef KEYSTORE_KEY_PROTO_HANDLER_H_
-#define KEYSTORE_KEY_PROTO_HANDLER_H_
+#ifndef KEY_OPERATION_LOG_HANDLER_H_
+#define KEY_OPERATION_LOG_HANDLER_H_
-#include <keystore/keystore_hidl_support.h>
+#include "operation_struct.h"
namespace keystore {
-void uploadKeyCharacteristicsAsProto(const hidl_vec<KeyParameter>& keyParams,
- bool wasCreationSuccessful);
+void logKeystoreKeyOperationEvent(const Operation& op, bool wasSuccessful, int32_t errorCode);
} // namespace keystore
-#endif // KEYSTORE_KEY_PROTO_HANDLER_H_
+#endif // KEY_OPERATION_LOG_HANDLER_H_
diff --git a/keystore/key_proto_handler.cpp b/keystore/key_proto_handler.cpp
deleted file mode 100644
index f8400af..0000000
--- a/keystore/key_proto_handler.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2018 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 "KeystoreOperation"
-
-#include "key_proto_handler.h"
-
-#include <android/os/DropBoxManager.h>
-#include <google/protobuf/message_lite.h>
-#include <keymasterV4_1/Keymaster.h>
-#include <keystore/keymaster_types.h>
-#include <utils/String16.h>
-#include <utils/StrongPointer.h>
-
-#include "key_config.pb.h"
-
-namespace keystore {
-
-void checkEnforcedCharacteristics(const hidl_vec<KeyParameter>& keyParams, KeyConfig* keyConfig) {
- for (auto& keyParam : keyParams) {
- switch (keyParam.tag) {
- case Tag::PURPOSE:
- keyConfig->add_purpose(toString(accessTagValue(TAG_PURPOSE, keyParam)));
- break;
- case Tag::ALGORITHM:
- keyConfig->set_algorithm(toString(accessTagValue(TAG_ALGORITHM, keyParam)));
- break;
- case Tag::KEY_SIZE:
- keyConfig->set_key_size(accessTagValue(TAG_KEY_SIZE, keyParam));
- break;
- case Tag::BLOCK_MODE:
- keyConfig->add_block_mode(toString(accessTagValue(TAG_BLOCK_MODE, keyParam)));
- break;
- case Tag::PADDING:
- keyConfig->add_padding(toString(accessTagValue(TAG_PADDING, keyParam)));
- break;
- case Tag::DIGEST:
- keyConfig->add_digest(toString(accessTagValue(TAG_DIGEST, keyParam)));
- break;
- case Tag::EC_CURVE:
- keyConfig->set_ec_curve(toString(accessTagValue(TAG_EC_CURVE, keyParam)));
- break;
- case Tag::AUTH_TIMEOUT:
- keyConfig->set_user_auth_key_timeout(accessTagValue(TAG_AUTH_TIMEOUT, keyParam));
- break;
- case Tag::ORIGIN:
- keyConfig->set_origin(toString(accessTagValue(TAG_ORIGIN, keyParam)));
- break;
- case Tag::BLOB_USAGE_REQUIREMENTS:
- keyConfig->set_key_blob_usage_reqs(
- toString(accessTagValue(TAG_BLOB_USAGE_REQUIREMENTS, keyParam)));
- break;
- case Tag::USER_AUTH_TYPE:
- keyConfig->set_user_auth_type(toString(accessTagValue(TAG_USER_AUTH_TYPE, keyParam)));
- break;
- default:
- break;
- }
- }
-}
-
-void uploadKeyCharacteristicsAsProto(const hidl_vec<KeyParameter>& keyParams,
- bool wasCreationSuccessful) {
- KeyConfig keyConfig;
- checkEnforcedCharacteristics(keyParams, &keyConfig);
- android::sp<android::os::DropBoxManager> dropbox(new android::os::DropBoxManager());
- keyConfig.set_was_creation_successful(wasCreationSuccessful);
-
- size_t size = keyConfig.ByteSize();
- auto data = std::make_unique<uint8_t[]>(size);
- keyConfig.SerializeWithCachedSizesToArray(data.get());
- dropbox->addData(android::String16("keymaster"), data.get(), size, 0);
-}
-
-} // namespace keystore
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
index 583f5b6..4e5bc48 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -41,7 +41,7 @@
#include <keymasterV4_0/keymaster_utils.h>
#include "defaults.h"
-#include "key_proto_handler.h"
+#include "key_attestation_log_handler.h"
#include "keystore_keymaster_enforcement.h"
#include "keystore_utils.h"
#include <keystore/keystore_attestation_id.h>
@@ -1118,6 +1118,10 @@
AuthorizationSet mutableParams = params.getParameters();
KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams);
+
+ auto logErrorOnReturn = android::base::make_scope_guard(
+ [&] { logKeystoreKeyAttestationEvent(false /*wasSuccessful*/, rc.getErrorCode()); });
+
if (!rc.isOk()) {
return AIDL_RETURN(rc);
}
@@ -1134,6 +1138,8 @@
return AIDL_RETURN(rc);
}
+ logErrorOnReturn.Disable();
+
auto dev = mKeyStore->getDevice(keyBlob);
auto hidlKey = blob2hidlVec(keyBlob);
dev->attestKey(
@@ -1142,13 +1148,18 @@
std::tuple<ErrorCode, hidl_vec<hidl_vec<uint8_t>>>&& hidlResult) {
auto& [ret, certChain] = hidlResult;
if (!rc.isOk()) {
+ logKeystoreKeyAttestationEvent(false /*wasSuccessful*/,
+ static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {});
} else if (ret != ErrorCode::OK) {
+ KeyStoreServiceReturnCode ksrc(ret);
+ logKeystoreKeyAttestationEvent(false /*wasSuccessful*/, ksrc.getErrorCode());
dev->logIfKeymasterVendorError(ret);
- cb->onFinished(KeyStoreServiceReturnCode(ret), {});
+ cb->onFinished(ksrc, {});
} else {
- cb->onFinished(KeyStoreServiceReturnCode(ret),
- KeymasterCertificateChain(std::move(certChain)));
+ KeyStoreServiceReturnCode ksrc(ret);
+ logKeystoreKeyAttestationEvent(true /*wasSuccessful*/, ksrc.getErrorCode());
+ cb->onFinished(ksrc, KeymasterCertificateChain(std::move(certChain)));
}
});
diff --git a/keystore/keymaster_worker.cpp b/keystore/keymaster_worker.cpp
index 911815e..7481a1e 100644
--- a/keystore/keymaster_worker.cpp
+++ b/keystore/keymaster_worker.cpp
@@ -29,7 +29,7 @@
#include "KeyStore.h"
#include "keymaster_enforcement.h"
-#include "key_proto_handler.h"
+#include "key_creation_log_handler.h"
#include "keystore_utils.h"
#include <chrono>
@@ -336,8 +336,10 @@
return {rc, std::move(authToken)};
}
-KeyStoreServiceReturnCode KeymasterWorker::abort(const sp<IBinder>& token) {
- auto op = operationMap_.removeOperation(token, false /* wasOpSuccessful */);
+KeyStoreServiceReturnCode KeymasterWorker::abort(const sp<IBinder>& token,
+ ResponseCode reason_for_abort) {
+ auto op = operationMap_.removeOperation(token, false /* wasOpSuccessful */,
+ static_cast<int32_t>(reason_for_abort));
if (op) {
keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
return KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle));
@@ -355,7 +357,7 @@
size_t op_count_before_abort = operationMap_.getOperationCount();
// We mostly ignore errors from abort() because all we care about is whether at least
// one operation has been removed.
- auto rc = abort(oldest);
+ auto rc = abort(oldest, ResponseCode::PRUNED);
keyStore_->removeOperationDevice(oldest);
if (operationMap_.getOperationCount() >= op_count_before_abort) {
ALOGE("Failed to abort pruneable operation %p, error: %d", oldest.get(), rc.getErrorCode());
@@ -598,7 +600,7 @@
}
Finalize abort_operation_in_case_of_error([&] {
- operationMap_.removeOperation(token, false);
+ operationMap_.removeOperation(token, false, rc.getErrorCode());
keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle));
});
@@ -677,7 +679,7 @@
bool finished = false;
Finalize abort_operation_in_case_of_error([&] {
- operationMap_.removeOperation(token, finished && rc.isOk());
+ operationMap_.removeOperation(token, finished && rc.isOk(), rc.getErrorCode());
keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
if (!finished)
KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle));
@@ -745,8 +747,9 @@
}
void KeymasterWorker::abort(sp<IBinder> token, abort_cb worker_cb) {
- Worker::addRequest(
- [this, CAPTURE_MOVE(token), CAPTURE_MOVE(worker_cb)]() { return worker_cb(abort(token)); });
+ Worker::addRequest([this, CAPTURE_MOVE(token), CAPTURE_MOVE(worker_cb)]() {
+ return worker_cb(abort(token, ResponseCode::ABORT_CALLED));
+ });
}
void KeymasterWorker::verifyAuthorization(uint64_t challenge, hidl_vec<KeyParameter> params,
@@ -800,8 +803,10 @@
// by KeyStore::getFallbackDevice()
bool consider_fallback = securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT;
- Finalize logOnFail(
- [&] { uploadKeyCharacteristicsAsProto(keyParams, false /* wasCreationSuccessful */); });
+ Finalize logOnFail([&] {
+ logKeystoreKeyCreationEvent(keyParams, false /*wasCreationSuccessful*/,
+ rc.getErrorCode());
+ });
KeyCharacteristics outCharacteristics;
KeyStoreServiceReturnCode error;
@@ -870,7 +875,8 @@
// log on success
logOnFail.release();
- uploadKeyCharacteristicsAsProto(keyParams, true /* wasCreationSuccessful */);
+ logKeystoreKeyCreationEvent(keyParams, true /*wasCreationSuccessful*/,
+ error.getErrorCode());
return worker_cb(error, std::move(outCharacteristics));
});
@@ -904,11 +910,13 @@
// by KeyStore::getFallbackDevice()
bool consider_fallback = securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT;
- Finalize logOnFail(
- [&] { uploadKeyCharacteristicsAsProto(keyParams, false /* wasCreationSuccessful */); });
+ KeyStoreServiceReturnCode error;
+ Finalize logOnFail([&] {
+ logKeystoreKeyCreationEvent(keyParams, false /*wasCreationSuccessful*/,
+ error.getErrorCode());
+ });
KeyCharacteristics outCharacteristics;
- KeyStoreServiceReturnCode error;
auto hidl_cb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
const KeyCharacteristics& keyCharacteristics) {
keymasterDevice_->logIfKeymasterVendorError(ret);
@@ -975,7 +983,8 @@
// log on success
logOnFail.release();
- uploadKeyCharacteristicsAsProto(keyParams, true /* wasCreationSuccessful */);
+ logKeystoreKeyCreationEvent(keyParams, true /*wasCreationSuccessful*/,
+ error.getErrorCode());
return worker_cb(error, std::move(outCharacteristics));
});
@@ -1126,7 +1135,7 @@
Worker::addRequest([this, who]() {
auto operations = operationMap_.getOperationsForToken(who.unsafe_get());
for (const auto& token : operations) {
- abort(token);
+ abort(token, ResponseCode::BINDER_DIED);
keyStore_->removeOperationDevice(token);
}
});
diff --git a/keystore/keymaster_worker.h b/keystore/keymaster_worker.h
index 8e35c16..f11af29 100644
--- a/keystore/keymaster_worker.h
+++ b/keystore/keymaster_worker.h
@@ -190,7 +190,7 @@
getAuthToken(const KeyCharacteristics& characteristics, uint64_t handle, KeyPurpose purpose,
bool failOnTokenMissing = true);
- KeyStoreServiceReturnCode abort(const sp<IBinder>& token);
+ KeyStoreServiceReturnCode abort(const sp<IBinder>& token, ResponseCode reason_for_abort);
bool pruneOperation();
diff --git a/keystore/operation.cpp b/keystore/operation.cpp
index 71ab340..bd4bd5e 100644
--- a/keystore/operation.cpp
+++ b/keystore/operation.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "KeystoreOperation"
#include "operation.h"
+#include "key_operation_log_handler.h"
#include <algorithm>
#include <android-base/logging.h>
@@ -58,12 +59,12 @@
}
std::shared_ptr<Operation> OperationMap::removeOperation(const sp<IBinder>& token,
- bool wasSuccessful) {
+ bool wasSuccessful, int32_t responseCode) {
auto entry = mMap.find(token);
if (entry == mMap.end()) return {};
auto op = entry->second;
- operationUploader.uploadOpAsProto(*op, wasSuccessful);
+ logKeystoreKeyOperationEvent(*op, wasSuccessful, responseCode);
mMap.erase(entry);
auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
diff --git a/keystore/operation.h b/keystore/operation.h
index ef880a7..8423db5 100644
--- a/keystore/operation.h
+++ b/keystore/operation.h
@@ -33,7 +33,6 @@
#include <keystore/keystore_concurrency.h>
#include <keystore/keystore_hidl_support.h>
-#include "operation_proto_handler.h"
#include "operation_struct.h"
namespace keystore {
@@ -57,7 +56,8 @@
KeyCharacteristics&& characteristics,
const hidl_vec<KeyParameter>& params, bool pruneable);
std::shared_ptr<Operation> getOperation(const sp<IBinder>& token);
- std::shared_ptr<Operation> removeOperation(const sp<IBinder>& token, bool wasSuccessful);
+ std::shared_ptr<Operation> removeOperation(const sp<IBinder>& token, bool wasSuccessful,
+ int32_t responseCode);
size_t getOperationCount() const { return mMap.size(); }
sp<IBinder> getOldestPruneableOperation();
std::vector<sp<IBinder>> getOperationsForToken(const sp<IBinder>& appToken);
@@ -70,7 +70,6 @@
std::list<sp<IBinder>> mLru;
std::map<sp<IBinder>, std::vector<sp<IBinder>>> mAppTokenMap;
IBinder::DeathRecipient* mDeathRecipient;
- OperationProtoHandler operationUploader;
};
} // namespace keystore
diff --git a/keystore/operation_config.proto b/keystore/operation_config.proto
deleted file mode 100644
index efbb4fe..0000000
--- a/keystore/operation_config.proto
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-syntax = "proto2";
-
-package keystore;
-
-option optimize_for = LITE_RUNTIME;
-
-// A single operation config
-message OperationConfig {
- // What type of encryption algorithm is the key being used in the op for.
- optional string algorithm = 1;
-
- // Size of the key being used in this op
- optional int32 key_size = 2;
-
- // Log whether the key in this op was generated, imported,
- // securely imported, or derived.
- optional string origin = 3;
-
- // What auth types does this op require? If none, then no auth required.
- optional string user_auth_type = 4;
-
- // If user authentication is required, is the requirement time based? If it
- // is not time based then this field will not be used and the key is per
- // operation. Per operation keys must be user authenticated on each usage.
- optional int32 user_auth_key_timeout = 5;
-
- // Track which padding mode was used for this operation.
- optional string padding = 6;
-
- // Keep track of the digest algorithm being used.
- optional string digest = 7;
-
- // Check what block mode is being used depending on the mode of encryption
- optional string block_mode = 8;
-
- // Did the operation succeed? If it didn't, this represents bugs or
- // error cases occurring.
- optional bool was_op_successful = 9;
-
- // What purpose is this operation serving? Encrypt, decrypt, sign verify?
- optional string purpose = 10;
-
- // Which ec curve was selected if elliptic curve cryptography is in use
- optional string ec_curve = 11;
-
- // Standalone or is a file system required
- optional string key_blob_usage_reqs = 12;
-}
-
-message OperationConfigEvent {
- optional OperationConfig op_config = 1;
-
- // counts corresponds to the number of times each op_config in the above array
- // was recorded during the collection period.
- optional uint32 count = 2;
-}
-
-message OperationConfigEvents {
- repeated OperationConfigEvent op_config_events = 1;
-}
-
diff --git a/keystore/operation_proto_handler.cpp b/keystore/operation_proto_handler.cpp
deleted file mode 100644
index 3b3d3fc..0000000
--- a/keystore/operation_proto_handler.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2018 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 "KeystoreOperation"
-
-#include "operation_proto_handler.h"
-
-#include <android/os/DropBoxManager.h>
-#include <google/protobuf/message_lite.h>
-#include <keymasterV4_1/Keymaster.h>
-#include <keystore/keymaster_types.h>
-#include <keystore/keystore_hidl_support.h>
-#include <utils/String16.h>
-#include <utils/StrongPointer.h>
-
-using namespace std::chrono;
-
-namespace keystore {
-
-constexpr auto kCollectionTime = 1h;
-
-void determinePurpose(KeyPurpose purpose, OperationConfig* operationConfig) {
- switch (purpose) {
- case KeyPurpose::VERIFY:
- operationConfig->set_purpose("verify");
- break;
- case KeyPurpose::ENCRYPT:
- operationConfig->set_purpose("encrypt");
- break;
- case KeyPurpose::SIGN:
- operationConfig->set_purpose("sign");
- break;
- case KeyPurpose::DECRYPT:
- operationConfig->set_purpose("decrypt");
- break;
- case KeyPurpose::WRAP_KEY:
- operationConfig->set_purpose("wrap");
- break;
- default:
- break;
- }
-}
-
-void checkKeyCharacteristics(const hidl_vec<KeyParameter>& characteristics,
- OperationConfig* operationConfig) {
- for (auto& opParam : characteristics) {
- switch (opParam.tag) {
- case Tag::ALGORITHM:
- operationConfig->set_algorithm(toString(accessTagValue(TAG_ALGORITHM, opParam)));
- break;
- case Tag::KEY_SIZE:
- operationConfig->set_key_size(accessTagValue(TAG_KEY_SIZE, opParam));
- break;
- case Tag::EC_CURVE:
- operationConfig->set_ec_curve(toString(accessTagValue(TAG_EC_CURVE, opParam)));
- break;
- case Tag::AUTH_TIMEOUT:
- operationConfig->set_user_auth_key_timeout(accessTagValue(TAG_AUTH_TIMEOUT, opParam));
- break;
- case Tag::ORIGIN:
- operationConfig->set_origin(toString(accessTagValue(TAG_ORIGIN, opParam)));
- break;
- case Tag::BLOB_USAGE_REQUIREMENTS:
- operationConfig->set_key_blob_usage_reqs(
- toString(accessTagValue(TAG_BLOB_USAGE_REQUIREMENTS, opParam)));
- break;
- case Tag::USER_AUTH_TYPE:
- operationConfig->set_user_auth_type(
- toString(accessTagValue(TAG_USER_AUTH_TYPE, opParam)));
- break;
- default:
- break;
- }
- }
-}
-
-void checkOpCharacteristics(const hidl_vec<KeyParameter>& characteristics,
- OperationConfig* operationConfig) {
- for (auto& opParam : characteristics) {
- switch (opParam.tag) {
- case Tag::BLOCK_MODE:
- operationConfig->set_block_mode(toString(accessTagValue(TAG_BLOCK_MODE, opParam)));
- break;
- case Tag::PADDING:
- operationConfig->set_padding(toString(accessTagValue(TAG_PADDING, opParam)));
- break;
- case Tag::DIGEST:
- operationConfig->set_digest(toString(accessTagValue(TAG_DIGEST, opParam)));
- break;
- default:
- break;
- }
- }
-}
-
-void OperationProtoHandler::uploadOpAsProto(Operation& op, bool wasOpSuccessful) {
- std::lock_guard<std::mutex> lock(op_upload_mutex);
- OperationConfig operationConfig;
- determinePurpose(op.purpose, &operationConfig);
- checkKeyCharacteristics(op.characteristics.softwareEnforced, &operationConfig);
- checkKeyCharacteristics(op.characteristics.hardwareEnforced, &operationConfig);
- checkOpCharacteristics(op.params, &operationConfig);
- operationConfig.set_was_op_successful(wasOpSuccessful);
- // Only bother with counting an hour out when an operation entry is actually
- // added
- if (protoMap.empty()) {
- start_time = std::chrono::steady_clock::now();
- }
- auto cur_time = std::chrono::steady_clock::now();
-
- // Add operations to a map within the time duration of an hour. Deduplicate
- // repeated ops by incrementing the counter of the original one stored and
- // discarding the new one.
- protoMap[operationConfig.SerializeAsString()]++;
-
- if (cur_time - start_time >= kCollectionTime) {
- // Iterate through the unordered map and dump all the operation protos
- // accumulated over the hour into the holding list proto after setting
- // their counts.
- OperationConfigEvents opConfigEvents;
- for (auto elem : protoMap) {
- OperationConfigEvent* event = opConfigEvents.add_op_config_events();
- event->mutable_op_config()->ParseFromString(elem.first);
- event->set_count(elem.second);
- }
- android::sp<android::os::DropBoxManager> dropbox(new android::os::DropBoxManager);
- size_t size = opConfigEvents.ByteSize();
- auto data = std::make_unique<uint8_t[]>(size);
- opConfigEvents.SerializeWithCachedSizesToArray(data.get());
- dropbox->addData(android::String16("keymaster"), data.get(), size, 0);
- protoMap.clear();
- }
-}
-
-} // namespace keystore
diff --git a/keystore/operation_proto_handler.h b/keystore/operation_proto_handler.h
deleted file mode 100644
index 64d0a59..0000000
--- a/keystore/operation_proto_handler.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef KEYSTORE_OPERATION_PROTO_HANDLER_H_
-#define KEYSTORE_OPERATION_PROTO_HANDLER_H_
-
-#include "operation_config.pb.h"
-#include "operation_struct.h"
-#include <chrono>
-#include <mutex>
-#include <unordered_map>
-#include <vector>
-
-namespace keystore {
-
-using ::android::IBinder;
-using keymaster::support::Keymaster;
-
-class OperationProtoHandler {
- public:
- void uploadOpAsProto(Operation& op, bool wasOpSuccessful);
-
- private:
- std::unordered_map<std::string, int> protoMap;
- std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now();
- std::mutex op_upload_mutex;
-};
-
-} // namespace keystore
-
-#endif // KEYSTORE_OPERATION_PROTO_HANDLER_H_
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
new file mode 100644
index 0000000..154b675
--- /dev/null
+++ b/keystore2/Android.bp
@@ -0,0 +1,88 @@
+// 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.
+
+rust_library {
+ name: "libkeystore2",
+ crate_name: "keystore2",
+ srcs: ["src/lib.rs"],
+
+ rustlibs: [
+ "libanyhow",
+ "libkeystore_aidl_generated",
+ "libkeystore2_selinux",
+ "liblazy_static",
+ "liblibsqlite3_sys",
+ "liblog_rust",
+ "librand",
+ "librusqlite",
+ "libthiserror",
+ ],
+}
+
+rust_test {
+ name: "keystore2_test",
+ crate_name: "keystore2",
+ srcs: ["src/lib.rs"],
+ test_suites: ["general-tests"],
+ auto_gen_config: true,
+ rustlibs: [
+ "libandroid_logger",
+ "libanyhow",
+ "libkeystore_aidl_generated",
+ "libkeystore2_selinux",
+ "liblazy_static",
+ "liblibsqlite3_sys",
+ "liblog_rust",
+ "librusqlite",
+ "libthiserror",
+ ],
+}
+
+// This is a placeholder for the libraries that will be generated from the AIDL specs
+// eventually.
+rust_library {
+ name: "libkeystore_aidl_generated",
+ crate_name: "keystore_aidl_generated",
+
+ srcs: ["src/aidl_generated.rs"],
+}
+
+// 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",
+ ],
+}
+
+// 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",
+
+ srcs: ["src/android_security_keystore2.rs"],
+
+ rustlibs: [
+ "libandroid_hardware_keymint",
+ "libbinder_rs",
+ "liblazy_static",
+ ],
+}
diff --git a/keystore2/TEST_MAPPING b/keystore2/TEST_MAPPING
new file mode 100644
index 0000000..70e3175
--- /dev/null
+++ b/keystore2/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "keystore2_test"
+ }
+ ]
+}
diff --git a/keystore2/selinux/Android.bp b/keystore2/selinux/Android.bp
new file mode 100644
index 0000000..acbf5ef
--- /dev/null
+++ b/keystore2/selinux/Android.bp
@@ -0,0 +1,54 @@
+// 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.
+
+rust_library {
+ name: "libkeystore2_selinux",
+ crate_name: "keystore2_selinux",
+ srcs: [
+ "src/lib.rs",
+ ],
+
+ shared_libs: [
+ "libselinux",
+ ],
+
+ rustlibs: [
+ "libanyhow",
+ "liblog_rust",
+ "libselinux_bindgen",
+ "libthiserror",
+ ],
+}
+
+rust_test {
+ name: "keystore2_selinux_test",
+ srcs: [
+ "src/lib.rs",
+ ],
+ crate_name: "keystore2_selinux_test",
+ test_suites: ["general-tests"],
+ auto_gen_config: true,
+
+ shared_libs: [
+ "libselinux",
+ ],
+
+ rustlibs: [
+ "libandroid_logger",
+ "libanyhow",
+ "liblog_rust",
+ "libselinux_bindgen",
+ "libthiserror",
+ ],
+}
diff --git a/keystore2/selinux/TEST_MAPPING b/keystore2/selinux/TEST_MAPPING
new file mode 100644
index 0000000..0e68257
--- /dev/null
+++ b/keystore2/selinux/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "keystore2_selinux_test"
+ }
+ ]
+}
diff --git a/keystore2/selinux/src/lib.rs b/keystore2/selinux/src/lib.rs
new file mode 100644
index 0000000..05f9db8
--- /dev/null
+++ b/keystore2/selinux/src/lib.rs
@@ -0,0 +1,427 @@
+// 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(missing_docs)]
+
+//! This crate provides some safe wrappers around the libselinux API. It is currently limited
+//! to the API surface that Keystore 2.0 requires to perform permission checks against
+//! the SEPolicy. Notably, it provides wrappers for:
+//! * getcon
+//! * selinux_check_access
+//! * selabel_lookup for the keystore2_key backend.
+//! And it provides an owning wrapper around context strings `Context`.
+
+use std::ffi::{CStr, CString};
+use std::fmt;
+use std::io;
+use std::marker::{Send, Sync};
+pub use std::ops::Deref;
+use std::os::raw::c_char;
+use std::ptr;
+use std::sync;
+
+use selinux_bindgen as selinux;
+
+use anyhow::Context as AnyhowContext;
+use anyhow::{anyhow, Result};
+
+use selinux::SELABEL_CTX_ANDROID_KEYSTORE2_KEY;
+use selinux::SELINUX_CB_LOG;
+
+static SELINUX_LOG_INIT: sync::Once = sync::Once::new();
+
+fn redirect_selinux_logs_to_logcat() {
+ // `selinux_set_callback` assigned the static lifetime function pointer
+ // `selinux_log_callback` to a static lifetime variable.
+ let cb = selinux::selinux_callback { func_log: Some(selinux::selinux_log_callback) };
+ unsafe {
+ selinux::selinux_set_callback(SELINUX_CB_LOG as i32, cb);
+ }
+}
+
+// This function must be called before any entrypoint into lib selinux.
+// Or leave a comment reasoning why calling this macro is not necessary
+// for a given entry point.
+fn init_logger_once() {
+ SELINUX_LOG_INIT.call_once(redirect_selinux_logs_to_logcat)
+}
+
+/// Selinux Error code.
+#[derive(thiserror::Error, Debug, PartialEq)]
+pub enum Error {
+ /// Indicates that an access check yielded no access.
+ #[error("Permission Denied")]
+ PermissionDenied,
+ /// Indicates an unexpected system error. Nested string provides some details.
+ #[error("Selinux SystemError: {0}")]
+ SystemError(String),
+}
+
+impl Error {
+ /// Constructs a `PermissionDenied` error.
+ pub fn perm() -> Self {
+ Error::PermissionDenied
+ }
+ fn sys<T: Into<String>>(s: T) -> Self {
+ Error::SystemError(s.into())
+ }
+}
+
+/// Context represents an SELinux context string. It can take ownership of a raw
+/// s-string as allocated by `getcon` or `selabel_lookup`. In this case it uses
+/// `freecon` to free the resources when dropped. In its second variant it stores
+/// an `std::ffi::CString` that can be initialized from a Rust string slice.
+pub enum Context {
+ /// Wraps a raw context c-string as returned by libselinux.
+ Raw(*mut ::std::os::raw::c_char),
+ /// Stores a context string as `std::ffi::CString`.
+ CString(CString),
+}
+
+impl fmt::Display for Context {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}", (**self).to_str().unwrap_or("Invalid context"))
+ }
+}
+
+impl Drop for Context {
+ fn drop(&mut self) {
+ if let Self::Raw(p) = self {
+ // No need to initialize the logger here, because
+ // `freecon` cannot run unless `Backend::lookup` or `getcon`
+ // has run.
+ unsafe { selinux::freecon(*p) };
+ }
+ }
+}
+
+impl Deref for Context {
+ type Target = CStr;
+
+ fn deref(&self) -> &Self::Target {
+ match self {
+ Self::Raw(p) => unsafe { CStr::from_ptr(*p) },
+ Self::CString(cstr) => &cstr,
+ }
+ }
+}
+
+impl Context {
+ /// Initializes the `Context::CString` variant from a Rust string slice.
+ pub fn new(con: &str) -> Result<Self> {
+ Ok(Self::CString(
+ CString::new(con)
+ .with_context(|| format!("Failed to create Context with \"{}\"", con))?,
+ ))
+ }
+}
+
+/// The backend trait provides a uniform interface to all libselinux context backends.
+/// Currently, we only implement the KeystoreKeyBackend though.
+pub trait Backend {
+ /// Implementers use libselinux `selabel_lookup` to lookup the context for the given `key`.
+ fn lookup(&self, key: &str) -> Result<Context>;
+}
+
+/// Keystore key backend takes onwnership of the SELinux context handle returned by
+/// `selinux_android_keystore2_key_context_handle` and uses `selabel_close` to free
+/// the handle when dropped.
+/// It implements `Backend` to provide keystore_key label lookup functionality.
+pub struct KeystoreKeyBackend {
+ handle: *mut selinux::selabel_handle,
+}
+
+// KeystoreKeyBackend is Sync because selabel_lookup is thread safe.
+unsafe impl Sync for KeystoreKeyBackend {}
+unsafe impl Send for KeystoreKeyBackend {}
+
+impl KeystoreKeyBackend {
+ const BACKEND_TYPE: i32 = SELABEL_CTX_ANDROID_KEYSTORE2_KEY as i32;
+
+ /// Creates a new instance representing an SELinux context handle as returned by
+ /// `selinux_android_keystore2_key_context_handle`.
+ pub fn new() -> Result<Self> {
+ init_logger_once();
+ let handle = unsafe { selinux::selinux_android_keystore2_key_context_handle() };
+ if handle.is_null() {
+ return Err(anyhow!(Error::sys("Failed to open KeystoreKeyBackend")));
+ }
+ Ok(KeystoreKeyBackend { handle })
+ }
+}
+
+impl Drop for KeystoreKeyBackend {
+ fn drop(&mut self) {
+ // No need to initialize the logger here because it cannot be called unless
+ // KeystoreKeyBackend::new has run.
+ unsafe { selinux::selabel_close(self.handle) };
+ }
+}
+
+// Because KeystoreKeyBackend is Sync and Send, member function must never call
+// non thread safe libselinux functions. As of this writing no non thread safe
+// functions exist that could be called on a label backend handle.
+impl Backend for KeystoreKeyBackend {
+ fn lookup(&self, key: &str) -> Result<Context> {
+ let mut con: *mut c_char = ptr::null_mut();
+ let c_key = CString::new(key).with_context(|| {
+ format!("selabel_lookup: Failed to convert key \"{}\" to CString.", key)
+ })?;
+ match unsafe {
+ // No need to initialize the logger here because it cannot run unless
+ // KeystoreKeyBackend::new has run.
+ selinux::selabel_lookup(self.handle, &mut con, c_key.as_ptr(), Self::BACKEND_TYPE)
+ } {
+ 0 => {
+ if !con.is_null() {
+ Ok(Context::Raw(con))
+ } else {
+ Err(anyhow!(Error::sys(format!(
+ "selabel_lookup returned a NULL context for key \"{}\"",
+ key
+ ))))
+ }
+ }
+ _ => Err(anyhow!(io::Error::last_os_error()))
+ .with_context(|| format!("selabel_lookup failed for key \"{}\"", key)),
+ }
+ }
+}
+
+/// Safe wrapper around libselinux `getcon`. It initializes the `Context::Raw` variant of the
+/// returned `Context`.
+///
+/// ## Return
+/// * Ok(Context::Raw()) if successful.
+/// * Err(Error::sys()) if getcon succeeded but returned a NULL pointer.
+/// * Err(io::Error::last_os_error()) if getcon failed.
+pub fn getcon() -> Result<Context> {
+ init_logger_once();
+ let mut con: *mut c_char = ptr::null_mut();
+ match unsafe { selinux::getcon(&mut con) } {
+ 0 => {
+ if !con.is_null() {
+ Ok(Context::Raw(con))
+ } else {
+ Err(anyhow!(Error::sys("getcon returned a NULL context")))
+ }
+ }
+ _ => Err(anyhow!(io::Error::last_os_error())).context("getcon failed"),
+ }
+}
+
+/// Safe wrapper around selinux_check_access.
+///
+/// ## Return
+/// * Ok(()) iff the requested access was granted.
+/// * Err(anyhow!(Error::perm()))) if the permission was denied.
+/// * Err(anyhow!(ioError::last_os_error())) if any other error occurred while performing
+/// the access check.
+pub fn check_access(source: &Context, target: &Context, tclass: &str, perm: &str) -> Result<()> {
+ init_logger_once();
+ let c_tclass = CString::new(tclass).with_context(|| {
+ format!("check_access: Failed to convert tclass \"{}\" to CString.", tclass)
+ })?;
+ let c_perm = CString::new(perm).with_context(|| {
+ format!("check_access: Failed to convert perm \"{}\" to CString.", perm)
+ })?;
+
+ match unsafe {
+ selinux::selinux_check_access(
+ source.as_ptr(),
+ target.as_ptr(),
+ c_tclass.as_ptr(),
+ c_perm.as_ptr(),
+ ptr::null_mut(),
+ )
+ } {
+ 0 => Ok(()),
+ _ => {
+ let e = io::Error::last_os_error();
+ match e.kind() {
+ io::ErrorKind::PermissionDenied => Err(anyhow!(Error::perm())),
+ _ => Err(anyhow!(e)),
+ }
+ .with_context(|| {
+ format!(
+ concat!(
+ "check_access: Failed with sctx: {} tctx: {}",
+ " with target class: \"{}\" perm: \"{}\""
+ ),
+ source, target, tclass, perm
+ )
+ })
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use anyhow::Result;
+
+ /// The su_key namespace as defined in su.te and keystore_key_contexts of the
+ /// SePolicy (system/sepolicy).
+ static SU_KEY_NAMESPACE: &str = "0";
+ /// The shell_key namespace as defined in shell.te and keystore_key_contexts of the
+ /// SePolicy (system/sepolicy).
+ static SHELL_KEY_NAMESPACE: &str = "1";
+
+ fn check_context() -> Result<(Context, &'static str, bool)> {
+ let context = getcon()?;
+ match context.to_str().unwrap() {
+ "u:r:su:s0" => Ok((context, SU_KEY_NAMESPACE, true)),
+ "u:r:shell:s0" => Ok((context, SHELL_KEY_NAMESPACE, false)),
+ c => Err(anyhow!(format!(
+ "This test must be run as \"su\" or \"shell\". Current context: \"{}\"",
+ c
+ ))),
+ }
+ }
+
+ #[test]
+ fn test_getcon() -> Result<()> {
+ check_context()?;
+ Ok(())
+ }
+
+ #[test]
+ fn test_label_lookup() -> Result<()> {
+ let (_context, namespace, is_su) = check_context()?;
+ let backend = crate::KeystoreKeyBackend::new()?;
+ let context = backend.lookup(namespace)?;
+ if is_su {
+ assert_eq!(context.to_str(), Ok("u:object_r:su_key:s0"));
+ } else {
+ assert_eq!(context.to_str(), Ok("u:object_r:shell_key:s0"));
+ }
+ Ok(())
+ }
+
+ #[test]
+ fn context_from_string() -> Result<()> {
+ let tctx = Context::new("u:object_r:keystore:s0").unwrap();
+ let sctx = Context::new("u:r:system_server:s0").unwrap();
+ check_access(&sctx, &tctx, "keystore2_key", "use")?;
+ Ok(())
+ }
+
+ mod perm {
+ use super::super::*;
+ use super::*;
+ use anyhow::Result;
+
+ /// check_key_perm(perm, privileged, priv_domain)
+ /// `perm` is a permission of the keystore2_key class and `privileged` is a boolean
+ /// indicating whether the permission is considered privileged.
+ /// Privileged permissions are expeced to be denied to `shell` users but granted
+ /// to the given priv_domain.
+ macro_rules! check_key_perm {
+ // "use" is a keyword and cannot be used as an identifier, but we must keep
+ // the permission string intact. So we map the identifier name on use_ while using
+ // the permission string "use". In all other cases we can simply use the stringified
+ // identifier as permission string.
+ (use, $privileged:expr) => {
+ check_key_perm!(use_, $privileged, "use");
+ };
+ ($perm:ident, $privileged:expr) => {
+ check_key_perm!($perm, $privileged, stringify!($perm));
+ };
+ ($perm:ident, $privileged:expr, $p_str:expr) => {
+ #[test]
+ fn $perm() -> Result<()> {
+ android_logger::init_once(
+ android_logger::Config::default()
+ .with_tag("keystore_selinux_tests")
+ .with_min_level(log::Level::Debug),
+ );
+ let scontext = Context::new("u:r:shell:s0")?;
+ let backend = KeystoreKeyBackend::new()?;
+ let tcontext = backend.lookup(SHELL_KEY_NAMESPACE)?;
+
+ if $privileged {
+ assert_eq!(
+ Some(&Error::perm()),
+ check_access(
+ &scontext,
+ &tcontext,
+ "keystore2_key",
+ $p_str
+ )
+ .err()
+ .unwrap()
+ .root_cause()
+ .downcast_ref::<Error>()
+ );
+ } else {
+ assert!(check_access(
+ &scontext,
+ &tcontext,
+ "keystore2_key",
+ $p_str
+ )
+ .is_ok());
+ }
+ Ok(())
+ }
+ };
+ }
+
+ check_key_perm!(manage_blob, true);
+ check_key_perm!(delete, false);
+ check_key_perm!(use_dev_id, true);
+ check_key_perm!(req_forced_op, true);
+ check_key_perm!(gen_unique_id, true);
+ check_key_perm!(grant, true);
+ check_key_perm!(get_info, false);
+ check_key_perm!(list, false);
+ check_key_perm!(rebind, false);
+ check_key_perm!(update, false);
+ check_key_perm!(use, false);
+
+ macro_rules! check_keystore_perm {
+ ($perm:ident) => {
+ #[test]
+ fn $perm() -> Result<()> {
+ let ks_context = Context::new("u:object_r:keystore:s0")?;
+ let priv_context = Context::new("u:r:system_server:s0")?;
+ let unpriv_context = Context::new("u:r:shell:s0")?;
+ assert!(check_access(
+ &priv_context,
+ &ks_context,
+ "keystore2",
+ stringify!($perm)
+ )
+ .is_ok());
+ assert_eq!(
+ Some(&Error::perm()),
+ check_access(&unpriv_context, &ks_context, "keystore2", stringify!($perm))
+ .err()
+ .unwrap()
+ .root_cause()
+ .downcast_ref::<Error>()
+ );
+ Ok(())
+ }
+ };
+ }
+
+ check_keystore_perm!(add_auth);
+ check_keystore_perm!(clear_ns);
+ check_keystore_perm!(get_state);
+ check_keystore_perm!(lock);
+ check_keystore_perm!(reset);
+ check_keystore_perm!(unlock);
+ }
+}
diff --git a/keystore2/src/aidl_generated.rs b/keystore2/src/aidl_generated.rs
new file mode 100644
index 0000000..4b6a844
--- /dev/null
+++ b/keystore2/src/aidl_generated.rs
@@ -0,0 +1,99 @@
+// 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(missing_docs)]
+
+//! This crate holds types that we are depending on and will be generated by the AIDL
+//! compiler.
+
+use std::cmp::PartialEq;
+use std::fmt;
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct Result {
+ pub rc: ResponseCode,
+ pub km_error_code: i32,
+}
+
+impl fmt::Display for Result {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{:?}", self)
+ }
+}
+
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum ResponseCode {
+ Ok = 0,
+ // 1 Reserved - formerly NO_ERROR
+ Locked = 2,
+ Uninitialized = 3,
+ SystemError = 4,
+ // 5 Reserved - formerly "protocol error" was never used
+ PermissionDenied = 6,
+ KeyNotFound = 7,
+ ValueCorrupted = 8,
+ // 9 Reserved - formerly "undefined action" was never used
+ WrongPassword = 10,
+ // 11 - 13 Reserved - formerly password retry count indicators: obsolete
+ //
+ // 14 Reserved - formerly SIGNATURE_INVALID: Keystore does not perform public key
+ // operations any more.
+
+ // Indicates to the caller that user authorization is required before the operation may
+ // commence.
+ OpAuthNeeded = 15,
+ // 16 Reserved
+ KeyPermanentlyInvalidated = 17,
+ NoSuchSecurityLevel = 18,
+ KeymintErrorCode = 19,
+ BackendBusy = 20,
+}
+
+pub type ErrorCode = i32;
+
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum KeyPermission {
+ None = 0,
+ Delete = 1,
+ GenUniqueId = 2,
+ GetInfo = 4,
+ Grant = 8,
+ List = 0x10,
+ ManageBlob = 0x20,
+ Rebind = 0x40,
+ ReqForcedOp = 0x80,
+ Update = 0x100,
+ Use = 0x200,
+ UseDevId = 0x400,
+}
+
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum Domain {
+ App = 0,
+ Grant = 1,
+ SELinux = 2,
+ Blob = 3,
+ KeyId = 4,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct KeyDescriptor {
+ pub domain: Domain,
+ pub namespace_: i64,
+ pub alias: Option<String>,
+ pub blob: Option<Vec<u8>>,
+}
diff --git a/keystore2/src/android_hardware_keymint.rs b/keystore2/src/android_hardware_keymint.rs
new file mode 100644
index 0000000..dcdf87f
--- /dev/null
+++ b/keystore2/src/android_hardware_keymint.rs
@@ -0,0 +1,1639 @@
+#![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 KEYMASTER_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 {
+ 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 + Send + 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 {
+ 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 + Send + 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 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::*;
+}
\ No newline at end of file
diff --git a/keystore2/src/android_security_keystore2.rs b/keystore2/src/android_security_keystore2.rs
new file mode 100644
index 0000000..421885f
--- /dev/null
+++ b/keystore2/src/android_security_keystore2.rs
@@ -0,0 +1,1312 @@
+#![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 certificates: Vec<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>,
+ }
+ 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 {
+ certificates: 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.certificates)?;
+ 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.certificates = 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 {
+ 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<crate::mangled::_7_android_8_security_9_keystore2_6_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<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+ Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+ }
+ fn abort(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_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 + Send + 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<crate::mangled::_7_android_8_security_9_keystore2_6_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); }
+ let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+ *_arg_output = _aidl_reply.read()?;
+ Ok(_aidl_return)
+ }
+ 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<crate::mangled::_7_android_8_security_9_keystore2_6_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); }
+ let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+ *_arg_output = _aidl_reply.read()?;
+ Ok(_aidl_return)
+ }
+ fn abort(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_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); }
+ let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+ Ok(_aidl_return)
+ }
+ }
+ 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<crate::mangled::_7_android_8_security_9_keystore2_6_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<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.finish(_arg_input, _arg_signature, _arg_entropy, _arg_output) }
+ fn abort(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_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(_aidl_return)?;
+ _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(_aidl_return)?;
+ _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))?;
+ _aidl_reply.write(_aidl_return)?;
+ }
+ 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 {
+ 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 crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> 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_publicKey: Option<&crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: Option<&crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_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_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_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_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_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_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_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 + Send + 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 crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> 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, _arg_rc);
+ }
+ }
+ 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()?;
+ *_arg_rc = _aidl_reply.read()?;
+ Ok(_aidl_return)
+ }
+ fn updateSubcomponent(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicKey: Option<&crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: Option<&crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+ let _aidl_reply = self.binder.transact(TRANSACTION_updateSubcomponent, 0, |_aidl_data| {
+ _aidl_data.write(_arg_key)?;
+ _aidl_data.write(&_arg_publicKey)?;
+ _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_publicKey, _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: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+ Ok(_aidl_return)
+ }
+ 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_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_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_publicKey, _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: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+ *_arg_resultKey = _aidl_reply.read()?;
+ *_arg_publicKey = _aidl_reply.read()?;
+ *_arg_certificateChain = _aidl_reply.read()?;
+ Ok(_aidl_return)
+ }
+ 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_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_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_publicKey, _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: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+ *_arg_resultKey = _aidl_reply.read()?;
+ *_arg_publicKey = _aidl_reply.read()?;
+ *_arg_certificateChain = _aidl_reply.read()?;
+ Ok(_aidl_return)
+ }
+ 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_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_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_publicKey, _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: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+ *_arg_resultKey = _aidl_reply.read()?;
+ *_arg_publicKey = _aidl_reply.read()?;
+ *_arg_certificateChain = _aidl_reply.read()?;
+ Ok(_aidl_return)
+ }
+ }
+ 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 crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> 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, _arg_rc) }
+ fn updateSubcomponent(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicKey: Option<&crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: Option<&crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.updateSubcomponent(_arg_key, _arg_publicKey, _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_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.generateKey(_arg_key, _arg_params, _arg_entropy, _arg_resultKey, _arg_publicKey, _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_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.importKey(_arg_key, _arg_params, _arg_keyData, _arg_resultKey, _arg_publicKey, _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_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.importWrappedKey(_arg_key, _arg_wrappingKey, _arg_maskingKey, _arg_params, _arg_authenticators, _arg_resultKey, _arg_publicKey, _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: crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge = Default::default();
+ let mut _arg_rc: crate::mangled::_7_android_8_security_9_keystore2_6_Result = Default::default();
+ let _aidl_return = _aidl_service.create(&_arg_key, &_arg_operationParameters, _arg_forced, &mut _arg_challenge, &mut _arg_rc);
+ 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)?;
+ _aidl_reply.write(&_arg_rc)?;
+ }
+ 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_publicKey: Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey> = _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_publicKey.as_ref(), _arg_certificateChain.as_ref());
+ 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_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_publicKey: Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey> = 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_publicKey, &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_resultKey)?;
+ _aidl_reply.write(&_arg_publicKey)?;
+ _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_publicKey: Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey> = 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_publicKey, &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_resultKey)?;
+ _aidl_reply.write(&_arg_publicKey)?;
+ _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_publicKey: Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey> = 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_publicKey, &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_resultKey)?;
+ _aidl_reply.write(&_arg_publicKey)?;
+ _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 {
+ 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, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> 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_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> 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, _arg_list: &mut Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+ 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<crate::mangled::_7_android_8_security_9_keystore2_6_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<crate::mangled::_7_android_8_security_9_keystore2_6_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<crate::mangled::_7_android_8_security_9_keystore2_6_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 + Send + 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, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> 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, _arg_rc);
+ }
+ }
+ 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_rc = _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_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> 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_publicKey, _arg_certificateChain, _arg_rc);
+ }
+ }
+ 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_publicKey = _aidl_reply.read()?;
+ *_arg_certificateChain = _aidl_reply.read()?;
+ *_arg_rc = _aidl_reply.read()?;
+ Ok(_aidl_return)
+ }
+ fn listEntries(&self, _arg_domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain, _arg_nameSpace: i64, _arg_list: &mut Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> {
+ let _aidl_reply = self.binder.transact(TRANSACTION_listEntries, 0, |_aidl_data| {
+ _aidl_data.write(&_arg_domain)?;
+ _aidl_data.write(&_arg_nameSpace)?;
+ _aidl_data.write_slice_size(Some(_arg_list))?;
+ 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, _arg_list);
+ }
+ }
+ 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_security_9_keystore2_6_Result = _aidl_reply.read()?;
+ *_arg_list = _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<crate::mangled::_7_android_8_security_9_keystore2_6_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); }
+ let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+ Ok(_aidl_return)
+ }
+ 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<crate::mangled::_7_android_8_security_9_keystore2_6_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); }
+ let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+ *_arg_grantKey = _aidl_reply.read()?;
+ Ok(_aidl_return)
+ }
+ fn ungrant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_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); }
+ let _aidl_return: crate::mangled::_7_android_8_security_9_keystore2_6_Result = _aidl_reply.read()?;
+ Ok(_aidl_return)
+ }
+ }
+ impl IKeystoreService for binder::Binder<BnKeystoreService> {
+ fn getSecurityLevel(&self, _arg_securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> { self.0.getSecurityLevel(_arg_securityLevel, _arg_rc) }
+ 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_publicKey: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>, _arg_rc: &mut crate::mangled::_7_android_8_security_9_keystore2_6_Result) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> { self.0.getKeyEntry(_arg_key, _arg_metadata, _arg_publicKey, _arg_certificateChain, _arg_rc) }
+ fn listEntries(&self, _arg_domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain, _arg_nameSpace: i64, _arg_list: &mut Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor>) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_Result> { self.0.listEntries(_arg_domain, _arg_nameSpace, _arg_list) }
+ fn deleteKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<crate::mangled::_7_android_8_security_9_keystore2_6_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<crate::mangled::_7_android_8_security_9_keystore2_6_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<crate::mangled::_7_android_8_security_9_keystore2_6_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 mut _arg_rc: crate::mangled::_7_android_8_security_9_keystore2_6_Result = Default::default();
+ let _aidl_return = _aidl_service.getSecurityLevel(_arg_securityLevel, &mut _arg_rc);
+ match &_aidl_return {
+ Ok(_aidl_return) => {
+ _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+ _aidl_reply.write(_aidl_return)?;
+ _aidl_reply.write(&_arg_rc)?;
+ }
+ 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_publicKey: Option<crate::mangled::_7_android_8_security_9_keystore2_9_PublicKey> = Default::default();
+ let mut _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = Default::default();
+ let mut _arg_rc: crate::mangled::_7_android_8_security_9_keystore2_6_Result = Default::default();
+ let _aidl_return = _aidl_service.getKeyEntry(&_arg_key, &mut _arg_metadata, &mut _arg_publicKey, &mut _arg_certificateChain, &mut _arg_rc);
+ 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_publicKey)?;
+ _aidl_reply.write(&_arg_certificateChain)?;
+ _aidl_reply.write(&_arg_rc)?;
+ }
+ 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 mut _arg_list: Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor> = Default::default();
+ _aidl_data.resize_out_vec(&mut _arg_list)?;
+ let _aidl_return = _aidl_service.listEntries(_arg_domain, _arg_nameSpace, &mut _arg_list);
+ match &_aidl_return {
+ Ok(_aidl_return) => {
+ _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+ _aidl_reply.write(_aidl_return)?;
+ _aidl_reply.write(&_arg_list)?;
+ }
+ 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))?;
+ _aidl_reply.write(_aidl_return)?;
+ }
+ 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(_aidl_return)?;
+ _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))?;
+ _aidl_reply.write(_aidl_return)?;
+ }
+ Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+ }
+ Ok(())
+ }
+ _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+ }
+ }
+ }
+ pub mod KeyDescriptor {
+ 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 List: KeyPermission = 16;
+ pub const ManageBlob: KeyPermission = 32;
+ pub const Rebind: KeyPermission = 64;
+ pub const ReqForcedOp: KeyPermission = 128;
+ pub const Update: KeyPermission = 256;
+ pub const Use: KeyPermission = 512;
+ pub const UseDevId: KeyPermission = 1024;
+ 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 PublicKey {
+ pub struct PublicKey {
+ pub keyMaterial: Vec<u8>,
+ }
+ pub(crate) mod mangled { pub use super::PublicKey as _7_android_8_security_9_keystore2_9_PublicKey; }
+ impl Default for PublicKey {
+ fn default() -> Self {
+ Self {
+ keyMaterial: Default::default(),
+ }
+ }
+ }
+ impl binder::parcel::Serialize for PublicKey {
+ 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 PublicKey {}
+ impl binder::parcel::SerializeOption for PublicKey {
+ 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.keyMaterial)?;
+ 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 PublicKey {
+ 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 PublicKey {}
+ impl binder::parcel::DeserializeOption for PublicKey {
+ 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.keyMaterial = 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 Result {
+ #[derive(Debug, Copy, Clone, Eq, PartialEq)]
+ pub struct Result {
+ pub rc: crate::mangled::_7_android_8_security_9_keystore2_12_ResponseCode,
+ pub errorCode: crate::mangled::_7_android_8_hardware_7_keymint_9_ErrorCode,
+ }
+ pub(crate) mod mangled { pub use super::Result as _7_android_8_security_9_keystore2_6_Result; }
+ impl Default for Result {
+ fn default() -> Self {
+ Self {
+ rc: Default::default(),
+ errorCode: Default::default(),
+ }
+ }
+ }
+ impl binder::parcel::Serialize for Result {
+ 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 Result {}
+ impl binder::parcel::SerializeOption for Result {
+ 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.rc)?;
+ parcel.write(&this.errorCode)?;
+ 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 Result {
+ 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 Result {}
+ impl binder::parcel::DeserializeOption for Result {
+ 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.rc = 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.errorCode = 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::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::PublicKey::mangled::*;
+ pub use super::aidl::android::security::keystore2::ResponseCode::mangled::*;
+ pub use super::aidl::android::security::keystore2::Result::mangled::*;
+ pub(crate) use android_hardware_keymint::mangled::*;
+}
\ No newline at end of file
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
new file mode 100644
index 0000000..394b7be
--- /dev/null
+++ b/keystore2/src/database.rs
@@ -0,0 +1,397 @@
+// 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: Once this is stable, remove this and document everything public.
+#![allow(missing_docs)]
+
+use crate::error::Error as KsError;
+use anyhow::{Context, Result};
+use keystore_aidl_generated as aidl;
+#[cfg(not(test))]
+use rand::prelude::random;
+use rusqlite::{params, Connection, TransactionBehavior, NO_PARAMS};
+#[cfg(test)]
+use tests::random;
+
+pub struct KeystoreDB {
+ conn: Connection,
+}
+
+impl KeystoreDB {
+ // TODO(b/160882985): Figure out the location for this file.
+ #[cfg(not(test))]
+ pub fn new() -> Result<KeystoreDB> {
+ KeystoreDB::new_with_filename("persistent.sql")
+ }
+
+ #[cfg(test)]
+ pub fn new() -> Result<KeystoreDB> {
+ KeystoreDB::new_with_filename("")
+ }
+
+ fn new_with_filename(persistent_file: &str) -> Result<KeystoreDB> {
+ let db = KeystoreDB {
+ conn: Connection::open_in_memory()
+ .context("Failed to initialize sqlite connection.")?,
+ };
+ db.attach_databases(persistent_file).context("Failed to create KeystoreDB.")?;
+ db.init_tables().context("Failed to create KeystoreDB.")?;
+ Ok(db)
+ }
+
+ fn attach_databases(&self, persistent_file: &str) -> Result<()> {
+ self.conn
+ .execute("ATTACH DATABASE ? as 'persistent';", params![persistent_file])
+ .context("Failed to attach databases.")?;
+ Ok(())
+ }
+
+ fn init_tables(&self) -> Result<()> {
+ self.conn
+ .execute(
+ "CREATE TABLE IF NOT EXISTS persistent.keyentry (
+ id INTEGER UNIQUE,
+ creation_date DATETIME,
+ domain INTEGER,
+ namespace INTEGER,
+ alias TEXT);",
+ NO_PARAMS,
+ )
+ .context("Failed to initialize \"keyentry\" table.")?;
+ Ok(())
+ }
+
+ pub fn create_key_entry(&self, domain: aidl::Domain, namespace: i64) -> Result<i64> {
+ match domain {
+ aidl::Domain::App | aidl::Domain::SELinux => {}
+ _ => {
+ return Err(KsError::sys())
+ .context(format!("Domain {:?} must be either App or SELinux.", domain));
+ }
+ }
+ // Loop until we get a unique id.
+ loop {
+ let newid: i64 = random();
+ let ret = self.conn.execute(
+ "INSERT into persistent.keyentry (id, creation_date, domain, namespace, alias)
+ VALUES(?, datetime('now'), ?, ?, NULL);",
+ params![newid, domain as i64, namespace],
+ );
+ match ret {
+ // If the id already existed, try again.
+ Err(rusqlite::Error::SqliteFailure(
+ libsqlite3_sys::Error {
+ code: libsqlite3_sys::ErrorCode::ConstraintViolation,
+ extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE,
+ },
+ _,
+ )) => (),
+ _ => return Ok(newid),
+ }
+ }
+ }
+
+ pub fn rebind_alias(
+ &mut self,
+ newid: u32,
+ alias: &str,
+ domain: aidl::Domain,
+ namespace: i64,
+ ) -> Result<()> {
+ match domain {
+ aidl::Domain::App | aidl::Domain::SELinux => {}
+ _ => {
+ return Err(KsError::sys())
+ .context(format!("Domain {:?} must be either App or SELinux.", domain));
+ }
+ }
+ let tx = self
+ .conn
+ .transaction_with_behavior(TransactionBehavior::Immediate)
+ .context("Failed to initialize transaction.")?;
+ tx.execute(
+ "UPDATE persistent.keyentry
+ SET alias = NULL, domain = NULL, namespace = NULL
+ WHERE alias = ? AND domain = ? AND namespace = ?;",
+ params![alias, domain as i64, namespace],
+ )
+ .context("Failed to rebind existing entry.")?;
+ let result = tx
+ .execute(
+ "UPDATE persistent.keyentry
+ SET alias = ?
+ WHERE id = ? AND domain = ? AND namespace = ?;",
+ params![alias, newid, domain as i64, namespace],
+ )
+ .context("Failed to set alias.")?;
+ if result != 1 {
+ // Note that this explicit rollback is not required, as
+ // the transaction should rollback if we do not commit it.
+ // We leave it here for readability.
+ tx.rollback().context("Failed to rollback a failed transaction.")?;
+ return Err(KsError::sys()).context(format!(
+ "Expected to update a single entry but instead updated {}.",
+ result
+ ));
+ }
+ tx.commit().context("Failed to commit transaction.")
+ }
+}
+
+#[cfg(test)]
+mod tests {
+
+ use super::*;
+ use std::cell::RefCell;
+
+ // Ensure that we're using the "injected" random function, not the real one.
+ #[test]
+ fn test_mocked_random() {
+ let rand1 = random();
+ let rand2 = random();
+ let rand3 = random();
+ if rand1 == rand2 {
+ assert_eq!(rand2 + 1, rand3);
+ } else {
+ assert_eq!(rand1 + 1, rand2);
+ assert_eq!(rand2, rand3);
+ }
+ }
+
+ // Ensure we can initialize the database.
+ #[test]
+ fn test_new() -> Result<()> {
+ KeystoreDB::new()?;
+ Ok(())
+ }
+
+ // Test that we have the correct tables.
+ #[test]
+ fn test_tables() -> Result<()> {
+ let db = KeystoreDB::new()?;
+ let tables = db
+ .conn
+ .prepare("SELECT name from persistent.sqlite_master WHERE type='table' ORDER BY name;")?
+ .query_map(params![], |row| row.get(0))?
+ .collect::<rusqlite::Result<Vec<String>>>()?;
+ assert_eq!(tables.len(), 1);
+ assert_eq!(tables[0], "keyentry");
+ Ok(())
+ }
+
+ #[test]
+ fn test_no_persistence_for_tests() -> Result<()> {
+ let db = KeystoreDB::new()?;
+
+ db.create_key_entry(aidl::Domain::App, 100)?;
+ let entries = get_keyentry(&db)?;
+ assert_eq!(entries.len(), 1);
+ let db = KeystoreDB::new()?;
+
+ let entries = get_keyentry(&db)?;
+ assert_eq!(entries.len(), 0);
+ Ok(())
+ }
+
+ #[test]
+ fn test_persistence_for_files() -> Result<()> {
+ let persistent = TempFile { filename: "/data/local/tmp/persistent.sql" };
+ let db = KeystoreDB::new_with_filename(persistent.filename)?;
+
+ db.create_key_entry(aidl::Domain::App, 100)?;
+ let entries = get_keyentry(&db)?;
+ assert_eq!(entries.len(), 1);
+ let db = KeystoreDB::new_with_filename(persistent.filename)?;
+
+ let entries_new = get_keyentry(&db)?;
+ assert_eq!(entries, entries_new);
+ Ok(())
+ }
+
+ #[test]
+ fn test_create_key_entry() -> Result<()> {
+ use aidl::Domain;
+
+ fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>) {
+ (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
+ }
+
+ let db = KeystoreDB::new()?;
+
+ 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));
+
+ // Test that we must pass in a valid Domain.
+ check_result_is_error_containing_string(
+ db.create_key_entry(Domain::Grant, 102),
+ "Domain Grant must be either App or SELinux.",
+ );
+ check_result_is_error_containing_string(
+ db.create_key_entry(Domain::Blob, 103),
+ "Domain Blob must be either App or SELinux.",
+ );
+ check_result_is_error_containing_string(
+ db.create_key_entry(Domain::KeyId, 104),
+ "Domain KeyId must be either App or SELinux.",
+ );
+
+ Ok(())
+ }
+
+ #[test]
+ fn test_rebind_alias() -> Result<()> {
+ use aidl::Domain;
+
+ fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>) {
+ (ke.domain, ke.namespace, ke.alias.as_deref())
+ }
+
+ let mut db = KeystoreDB::new()?;
+ 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));
+
+ // Test that the first call to rebind_alias sets the alias.
+ db.rebind_alias(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));
+
+ // Test that the second call to rebind_alias also empties the old one.
+ db.rebind_alias(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")));
+
+ // Test that we must pass in a valid Domain.
+ check_result_is_error_containing_string(
+ db.rebind_alias(0, "foo", Domain::Grant, 42),
+ "Domain Grant must be either App or SELinux.",
+ );
+ check_result_is_error_containing_string(
+ db.rebind_alias(0, "foo", Domain::Blob, 42),
+ "Domain Blob must be either App or SELinux.",
+ );
+ check_result_is_error_containing_string(
+ db.rebind_alias(0, "foo", Domain::KeyId, 42),
+ "Domain KeyId 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),
+ "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")));
+
+ Ok(())
+ }
+
+ // Helpers
+
+ // Checks that the given result is an error containing the given string.
+ fn check_result_is_error_containing_string<T>(result: Result<T>, target: &str) {
+ let error_str = format!(
+ "{:#?}",
+ result.err().unwrap_or_else(|| panic!("Expected the error: {}", target))
+ );
+ assert!(
+ error_str.contains(target),
+ "The string \"{}\" should contain \"{}\"",
+ error_str,
+ target
+ );
+ }
+
+ #[derive(Debug, PartialEq)]
+ #[allow(dead_code)]
+ struct KeyEntryRow {
+ id: u32,
+ creation_date: String,
+ domain: Option<aidl::Domain>,
+ namespace: Option<i64>,
+ alias: Option<String>,
+ }
+
+ fn get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>> {
+ db.conn
+ .prepare("SELECT * FROM persistent.keyentry;")?
+ .query_map(NO_PARAMS, |row| {
+ let domain: Option<i32> = row.get(2)?;
+ Ok(KeyEntryRow {
+ id: row.get(0)?,
+ creation_date: row.get(1)?,
+ domain: domain.map(domain_from_integer),
+ namespace: row.get(3)?,
+ alias: row.get(4)?,
+ })
+ })?
+ .map(|r| r.context("Could not read keyentry row."))
+ .collect::<Result<Vec<_>>>()
+ }
+
+ // TODO: Replace this with num_derive.
+ fn domain_from_integer(value: i32) -> aidl::Domain {
+ use aidl::Domain;
+ match value {
+ x if Domain::App as i32 == x => Domain::App,
+ x if Domain::Grant as i32 == x => Domain::Grant,
+ x if Domain::SELinux as i32 == x => Domain::SELinux,
+ x if Domain::Blob as i32 == x => Domain::Blob,
+ x if Domain::KeyId as i32 == x => Domain::KeyId,
+ _ => panic!("Unexpected domain: {}", value),
+ }
+ }
+
+ // A class that deletes a file when it is dropped.
+ // TODO: If we ever add a crate that does this, we can use it instead.
+ struct TempFile {
+ filename: &'static str,
+ }
+
+ impl Drop for TempFile {
+ fn drop(&mut self) {
+ std::fs::remove_file(self.filename).expect("Cannot delete temporary file");
+ }
+ }
+
+ // Use a custom random number generator that repeats each number once.
+ // This allows us to test repeated elements.
+
+ thread_local! {
+ static RANDOM_COUNTER: RefCell<i64> = RefCell::new(0);
+ }
+
+ pub fn random() -> i64 {
+ RANDOM_COUNTER.with(|counter| {
+ let result = *counter.borrow() / 2;
+ *counter.borrow_mut() += 1;
+ result
+ })
+ }
+}
diff --git a/keystore2/src/error.rs b/keystore2/src/error.rs
new file mode 100644
index 0000000..e6443b7
--- /dev/null
+++ b/keystore2/src/error.rs
@@ -0,0 +1,287 @@
+// 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.
+
+//! Keystore error provides convenience methods and types for Keystore error handling.
+//! Clients of Keystore expect one of two error codes, i.e., a Keystore ResponseCode as
+//! defined by the Keystore AIDL interface, or a Keymint ErrorCode as defined by
+//! the Keymint HAL specification.
+//! This crate provides `Error` which can wrap both. It is to be used
+//! internally by Keystore to diagnose error conditions that need to be reported to
+//! the client. To report the error condition to the client the Keystore AIDL
+//! interface defines a wire type `Result` which is distinctly different from Rust's
+//! `enum Result<T,E>`.
+//!
+//! 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.
+//!
+//! 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;
+use std::convert::From;
+
+use keystore_aidl_generated as aidl;
+use keystore_aidl_generated::ResponseCode as AidlRc;
+
+use keystore2_selinux as selinux;
+
+pub use aidl::ResponseCode;
+
+/// AidlResult wraps the `android.security.keystore2.Result` generated from AIDL
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct AidlResult(aidl::Result);
+
+impl AidlResult {
+ /// Creates an instance of AidlResult indicating no error has occurred.
+ pub fn ok() -> Self {
+ Self(aidl::Result { rc: AidlRc::Ok, km_error_code: 0 })
+ }
+
+ /// Creates an instance of AidlResult indicating the given ResponseCode.
+ pub fn rc(rc: AidlRc) -> Self {
+ Self(aidl::Result { rc, km_error_code: 0 })
+ }
+
+ /// Creates an instance of AidlResult indicating the given KM ErrorCode.
+ pub fn ec(ec: aidl::ErrorCode) -> Self {
+ Self(aidl::Result { rc: AidlRc::KeymintErrorCode, km_error_code: ec })
+ }
+}
+
+/// This is the main Keystore error type. It wraps the Keystore `ResponseCode` generated
+/// from AIDL in the `Rc` variant and Keymint `ErrorCode` in the Km variant.
+#[derive(Debug, thiserror::Error, PartialEq)]
+pub enum Error {
+ /// Wraps a Keystore `ResponseCode` as defined by the Keystore AIDL interface specification.
+ #[error("Error::Rc({0:?})")]
+ Rc(AidlRc),
+ /// Wraps a Keymint `ErrorCode` as defined by the Keymint AIDL interface specification.
+ #[error("Error::Km({0:?})")]
+ Km(aidl::ErrorCode), // TODO Keymint ErrorCode is a generated AIDL type.
+}
+
+impl Error {
+ /// Short hand for `Error::Rc(ResponseCode::SystemError)`
+ pub fn sys() -> Self {
+ Error::Rc(AidlRc::SystemError)
+ }
+
+ /// Short hand for `Error::Rc(ResponseCode::PermissionDenied`
+ pub fn perm() -> Self {
+ Error::Rc(AidlRc::PermissionDenied)
+ }
+}
+
+impl From<anyhow::Error> for AidlResult {
+ fn from(error: anyhow::Error) -> Self {
+ let root_cause = error.root_cause();
+ match root_cause.downcast_ref::<Error>() {
+ Some(Error::Rc(rcode)) => AidlResult::rc(*rcode),
+ Some(Error::Km(ec)) => AidlResult::ec(*ec),
+ None => match root_cause.downcast_ref::<selinux::Error>() {
+ Some(selinux::Error::PermissionDenied) => AidlResult::rc(AidlRc::PermissionDenied),
+ _ => AidlResult::rc(AidlRc::SystemError),
+ },
+ }
+ }
+}
+
+/// 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`
+/// 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}`.
+///
+/// All non `Error` error conditions get mapped onto
+/// `aidl::Result{aidl::ResponseCode::SystemError}`.
+///
+/// `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
+/// `AidlResult::ok()`, but other response codes may be used, e.g.,
+/// `aidl::ResponseCode::OpAuthNeeded` which does not required logging.
+///
+/// # Examples
+///
+/// ```
+/// fn loadKey() -> anyhow::Result<aidl::ResponseCode> {
+/// if (good_but_auth_required) {
+/// Ok(aidl::ResponseCode::OpAuthRequired)
+/// } else {
+/// Err(anyhow!(Error::Rc(aidl::ResponseCode::KeyNotFound)))
+/// }
+/// }
+///
+/// aidl_result_ = map_or_log_err(loadKey(), |r| { some_side_effect(); AidlResult::rc(r) });
+/// ```
+pub fn map_or_log_err<T>(
+ result: anyhow::Result<T>,
+ handle_ok: impl FnOnce(T) -> AidlResult,
+) -> AidlResult {
+ result.map_or_else(
+ |e| {
+ log::error!("{:?}", e);
+ e.into()
+ },
+ handle_ok,
+ )
+}
+
+#[cfg(test)]
+mod tests {
+
+ use anyhow::{anyhow, Context};
+
+ use super::aidl::ErrorCode;
+ use super::*;
+
+ fn nested_nested_rc(rc: AidlRc) -> anyhow::Result<()> {
+ Err(anyhow!(Error::Rc(rc))).context("nested nested rc")
+ }
+
+ fn nested_rc(rc: AidlRc) -> anyhow::Result<()> {
+ nested_nested_rc(rc).context("nested rc")
+ }
+
+ fn nested_nested_ec(ec: ErrorCode) -> anyhow::Result<()> {
+ Err(anyhow!(Error::Km(ec))).context("nested nested ec")
+ }
+
+ fn nested_ec(ec: ErrorCode) -> anyhow::Result<()> {
+ nested_nested_ec(ec).context("nested ec")
+ }
+
+ fn nested_nested_ok(rc: AidlRc) -> anyhow::Result<AidlRc> {
+ Ok(rc)
+ }
+
+ fn nested_ok(rc: AidlRc) -> anyhow::Result<AidlRc> {
+ nested_nested_ok(rc).context("nested ok")
+ }
+
+ fn nested_nested_selinux_perm() -> anyhow::Result<()> {
+ Err(anyhow!(selinux::Error::perm())).context("nested nexted selinux permission denied")
+ }
+
+ fn nested_selinux_perm() -> anyhow::Result<()> {
+ nested_nested_selinux_perm().context("nested selinux permission denied")
+ }
+
+ #[derive(Debug, thiserror::Error)]
+ enum TestError {
+ #[error("TestError::Fail")]
+ Fail = 0,
+ }
+
+ fn nested_nested_other_error() -> anyhow::Result<()> {
+ Err(anyhow!(TestError::Fail)).context("nested nested other error")
+ }
+
+ fn nested_other_error() -> anyhow::Result<()> {
+ nested_nested_other_error().context("nested other error")
+ }
+
+ #[test]
+ fn keystore_error_test() -> anyhow::Result<(), String> {
+ android_logger::init_once(
+ android_logger::Config::default()
+ .with_tag("keystore_error_tests")
+ .with_min_level(log::Level::Debug),
+ );
+ // All Error::Rc(x) get mapped on aidl::Result{x, 0}
+ assert_eq!(
+ AidlResult::rc(AidlRc::Ok),
+ map_or_log_err(nested_rc(AidlRc::Ok), |_| AidlResult::ec(0))
+ );
+ assert_eq!(
+ AidlResult::rc(AidlRc::Locked),
+ map_or_log_err(nested_rc(AidlRc::Locked), |_| AidlResult::ec(0))
+ );
+ assert_eq!(
+ AidlResult::rc(AidlRc::Uninitialized),
+ map_or_log_err(nested_rc(AidlRc::Uninitialized), |_| AidlResult::ec(0))
+ );
+ assert_eq!(
+ AidlResult::rc(AidlRc::SystemError),
+ map_or_log_err(nested_rc(AidlRc::SystemError), |_| AidlResult::ec(0))
+ );
+ assert_eq!(
+ AidlResult::rc(AidlRc::PermissionDenied),
+ map_or_log_err(nested_rc(AidlRc::PermissionDenied), |_| AidlResult::ec(0))
+ );
+ assert_eq!(
+ AidlResult::rc(AidlRc::KeyNotFound),
+ map_or_log_err(nested_rc(AidlRc::KeyNotFound), |_| AidlResult::ec(0))
+ );
+ assert_eq!(
+ AidlResult::rc(AidlRc::ValueCorrupted),
+ map_or_log_err(nested_rc(AidlRc::ValueCorrupted), |_| AidlResult::ec(0))
+ );
+ assert_eq!(
+ AidlResult::rc(AidlRc::WrongPassword),
+ map_or_log_err(nested_rc(AidlRc::WrongPassword), |_| AidlResult::ec(0))
+ );
+ assert_eq!(
+ AidlResult::rc(AidlRc::OpAuthNeeded),
+ map_or_log_err(nested_rc(AidlRc::OpAuthNeeded), |_| AidlResult::ec(0))
+ );
+ assert_eq!(
+ AidlResult::rc(AidlRc::KeyPermanentlyInvalidated),
+ map_or_log_err(nested_rc(AidlRc::KeyPermanentlyInvalidated), |_| AidlResult::ec(0))
+ );
+ assert_eq!(
+ AidlResult::rc(AidlRc::NoSuchSecurityLevel),
+ map_or_log_err(nested_rc(AidlRc::NoSuchSecurityLevel), |_| AidlResult::ec(0))
+ );
+ assert_eq!(
+ AidlResult::rc(AidlRc::KeymintErrorCode),
+ map_or_log_err(nested_rc(AidlRc::KeymintErrorCode), |_| AidlResult::ec(0))
+ );
+ assert_eq!(
+ AidlResult::rc(AidlRc::BackendBusy),
+ map_or_log_err(nested_rc(AidlRc::BackendBusy), |_| AidlResult::ec(0))
+ );
+
+ // All KeystoreKerror::Km(x) get mapped on
+ // aidl::Result{AidlRc::KeymintErrorCode, x}
+ assert_eq!(
+ AidlResult::ec(-7),
+ map_or_log_err(nested_ec(-7), |_| AidlResult::rc(AidlRc::SystemError))
+ );
+
+ // All other get mapped on System Error.
+ assert_eq!(
+ AidlResult::rc(AidlRc::SystemError),
+ map_or_log_err(nested_other_error(), |_| AidlResult::ec(0))
+ );
+
+ // Result::Ok variants get passed to the ok handler.
+ assert_eq!(
+ AidlResult::rc(AidlRc::OpAuthNeeded),
+ map_or_log_err(nested_ok(AidlRc::OpAuthNeeded), AidlResult::rc)
+ );
+ assert_eq!(AidlResult::ok(), map_or_log_err(nested_ok(AidlRc::Ok), AidlResult::rc));
+
+ // selinux::Error::Perm() needs to be mapped to AidlRc::PermissionDenied
+ assert_eq!(
+ AidlResult::rc(AidlRc::PermissionDenied),
+ map_or_log_err(nested_selinux_perm(), |_| AidlResult::ec(0))
+ );
+ Ok(())
+ }
+} // mod tests
diff --git a/keystore2/src/key_parameter.rs b/keystore2/src/key_parameter.rs
new file mode 100644
index 0000000..d9ec7f3
--- /dev/null
+++ b/keystore2/src/key_parameter.rs
@@ -0,0 +1,251 @@
+// 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.
+
+//! KeyParameter is used to express different characteristics of a key requested by the user
+//! and enforced by the OEMs. This module implements the internal representation of KeyParameter
+//! and the methods to work with KeyParameter.
+
+use crate::keymint_definitions::{
+ Algorithm, BlockMode, Digest, EcCurve, HardwareAuthenticatorType, KeyBlobUsageRequirements,
+ KeyOrigin, KeyPurpose, PaddingMode, SecurityLevel, Tag,
+};
+
+/// KeyParameter wraps the KeyParameterValue and the security level at which it is enforced.
+pub struct KeyParameter {
+ key_parameter_value: KeyParameterValue,
+ security_level: SecurityLevel,
+}
+
+/// KeyParameterValue holds a value corresponding to one of the Tags defined in
+/// the AIDL spec at hardware/interfaces/keymint
+#[derive(PartialEq, Debug)]
+pub enum KeyParameterValue {
+ /// Associated with Tag:INVALID
+ Invalid,
+ /// Set of purposes for which the key may be used
+ KeyPurpose(KeyPurpose),
+ /// Cryptographic algorithm with which the key is used
+ Algorithm(Algorithm),
+ /// Size of the key , in bits
+ KeySize(u32),
+ /// Block cipher mode(s) with which the key may be used
+ BlockMode(BlockMode),
+ /// Digest algorithms that may be used with the key to perform signing and verification
+ Digest(Digest),
+ /// Padding modes that may be used with the key. Relevant to RSA, AES and 3DES keys.
+ 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(u32),
+ /// The elliptic curve
+ EcCurve(EcCurve),
+ /// Value of the public exponent for an RSA key pair
+ RSAPublicExponent(u64),
+ /// An attestation certificate for the generated key should contain an application-scoped
+ /// and time-bounded device-unique ID
+ IncludeUniqueID,
+ /// Necessary system environment conditions for the generated key to be used
+ KeyBlobUsageRequirements(KeyBlobUsageRequirements),
+ /// Only the boot loader can use the key
+ BootLoaderOnly,
+ /// When deleted, the key is guaranteed to be permanently deleted and unusable
+ RollbackResistance,
+ //TODO: HARDWARE_TYPE reserved for future use
+ /// The date and time at which the key becomes active
+ ActiveDateTime(u64),
+ /// The date and time at which the key expires for signing and encryption
+ OriginationExpireDateTime(u64),
+ /// The date and time at which the key expires for verification and decryption
+ UsageExpireDateTime(u64),
+ /// Minimum amount of time that elapses between allowed operations
+ MinSecondsBetweenOps(u32),
+ /// Maximum number of times that a key may be used between system reboots
+ MaxUsesPerBoot(u32),
+ /// ID of the Android user that is permitted to use the key
+ UserID(u32),
+ /// A key may only be used under a particular secure user authentication state
+ UserSecureID(u64),
+ /// No authentication is required to use this key
+ NoAuthRequired,
+ /// The types of user authenticators that may be used to authorize this key
+ HardwareAuthenticatorType(HardwareAuthenticatorType),
+ /// The time in seconds for which the key is authorized for use, after user authentication
+ AuthTimeout(u32),
+ /// The key may be used after authentication timeout if device is still on-body
+ AllowWhileOnBody,
+ /// The key must be unusable except when the user has provided proof of physical presence
+ TrustedUserPresenceRequired,
+ /// Applicable to keys with KeyPurpose SIGN, and specifies that this key must not be usable
+ /// unless the user provides confirmation of the data to be signed
+ TrustedConfirmationRequired,
+ /// The key may only be used when the device is unlocked
+ UnlockedDeviceRequired,
+ /// When provided to generateKey or importKey, this tag specifies data
+ /// that is necessary during all uses of the key
+ ApplicationID(Vec<u8>),
+ /// When provided to generateKey or importKey, this tag specifies data
+ /// that is necessary during all uses of the key
+ ApplicationData(Vec<u8>),
+ /// Specifies the date and time the key was created
+ CreationDateTime(u64),
+ /// Specifies where the key was created, if known
+ 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
+ OSVersion(u32),
+ /// Specifies the system security patch level with which the key may be used
+ OSPatchLevel(u32),
+ /// Specifies a unique, time-based identifier
+ UniqueID(Vec<u8>),
+ /// Used to deliver a "challenge" value to the attestKey() method
+ AttestationChallenge(Vec<u8>),
+ /// The set of applications which may use a key, used only with attestKey()
+ AttestationApplicationID(Vec<u8>),
+ /// Provides the device's brand name, to attestKey()
+ AttestationIdBrand(Vec<u8>),
+ /// Provides the device's device name, to attestKey()
+ AttestationIdDevice(Vec<u8>),
+ /// Provides the device's product name, to attestKey()
+ AttestationIdProduct(Vec<u8>),
+ /// Provides the device's serial number, to attestKey()
+ AttestationIdSerial(Vec<u8>),
+ /// Provides the IMEIs for all radios on the device, to attestKey()
+ AttestationIdIMEI(Vec<u8>),
+ /// Provides the MEIDs for all radios on the device, to attestKey()
+ AttestationIdMEID(Vec<u8>),
+ /// Provides the device's manufacturer name, to attestKey()
+ AttestationIdManufacturer(Vec<u8>),
+ /// Provides the device's model name, to attestKey()
+ AttestationIdModel(Vec<u8>),
+ /// Specifies the vendor image security patch level with which the key may be used
+ VendorPatchLevel(u32),
+ /// Specifies the boot image (kernel) security patch level with which the key may be used
+ BootPatchLevel(u32),
+ /// Provides "associated data" for AES-GCM encryption or decryption
+ AssociatedData(Vec<u8>),
+ /// Provides or returns a nonce or Initialization Vector (IV) for AES-GCM,
+ /// AES-CBC, AES-CTR, or 3DES-CBC encryption or decryption
+ Nonce(Vec<u8>),
+ /// Provides the requested length of a MAC or GCM authentication tag, in bits
+ MacLength(u32),
+ /// Specifies whether the device has been factory reset since the
+ /// last unique ID rotation. Used for key attestation
+ ResetSinceIdRotation,
+ /// Used to deliver a cryptographic token proving that the user
+ /// confirmed a signing request
+ ConfirmationToken(Vec<u8>),
+}
+
+impl KeyParameter {
+ /// Create an instance of KeyParameter, given the value and the security level.
+ 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) -> Tag {
+ match self.key_parameter_value {
+ KeyParameterValue::Invalid => Tag::INVALID,
+ KeyParameterValue::KeyPurpose(_) => Tag::PURPOSE,
+ KeyParameterValue::Algorithm(_) => Tag::ALGORITHM,
+ KeyParameterValue::KeySize(_) => Tag::KEY_SIZE,
+ KeyParameterValue::BlockMode(_) => Tag::BLOCK_MODE,
+ KeyParameterValue::Digest(_) => Tag::DIGEST,
+ KeyParameterValue::PaddingMode(_) => Tag::PADDING,
+ KeyParameterValue::CallerNonce => Tag::CALLER_NONCE,
+ KeyParameterValue::MinMacLength(_) => Tag::MIN_MAC_LENGTH,
+ KeyParameterValue::EcCurve(_) => Tag::EC_CURVE,
+ KeyParameterValue::RSAPublicExponent(_) => Tag::RSA_PUBLIC_EXPONENT,
+ KeyParameterValue::IncludeUniqueID => Tag::INCLUDE_UNIQUE_ID,
+ KeyParameterValue::KeyBlobUsageRequirements(_) => Tag::BLOB_USAGE_REQUIREMENTS,
+ KeyParameterValue::BootLoaderOnly => Tag::BOOTLOADER_ONLY,
+ KeyParameterValue::RollbackResistance => Tag::ROLLBACK_RESISTANCE,
+ KeyParameterValue::ActiveDateTime(_) => Tag::ACTIVE_DATETIME,
+ KeyParameterValue::OriginationExpireDateTime(_) => Tag::ORIGINATION_EXPIRE_DATETIME,
+ KeyParameterValue::UsageExpireDateTime(_) => Tag::USAGE_EXPIRE_DATETIME,
+ KeyParameterValue::MinSecondsBetweenOps(_) => Tag::MIN_SECONDS_BETWEEN_OPS,
+ KeyParameterValue::MaxUsesPerBoot(_) => Tag::MAX_USES_PER_BOOT,
+ KeyParameterValue::UserID(_) => Tag::USER_ID,
+ KeyParameterValue::UserSecureID(_) => Tag::USER_SECURE_ID,
+ KeyParameterValue::NoAuthRequired => Tag::NO_AUTH_REQUIRED,
+ KeyParameterValue::HardwareAuthenticatorType(_) => Tag::USER_AUTH_TYPE,
+ KeyParameterValue::AuthTimeout(_) => Tag::AUTH_TIMEOUT,
+ KeyParameterValue::AllowWhileOnBody => Tag::ALLOW_WHILE_ON_BODY,
+ KeyParameterValue::TrustedUserPresenceRequired => Tag::TRUSTED_USER_PRESENCE_REQUIRED,
+ KeyParameterValue::TrustedConfirmationRequired => Tag::TRUSTED_CONFIRMATION_REQUIRED,
+ KeyParameterValue::UnlockedDeviceRequired => Tag::UNLOCKED_DEVICE_REQUIRED,
+ KeyParameterValue::ApplicationID(_) => Tag::APPLICATION_ID,
+ KeyParameterValue::ApplicationData(_) => Tag::APPLICATION_DATA,
+ KeyParameterValue::CreationDateTime(_) => Tag::CREATION_DATETIME,
+ KeyParameterValue::KeyOrigin(_) => Tag::ORIGIN,
+ KeyParameterValue::RootOfTrust(_) => Tag::ROOT_OF_TRUST,
+ KeyParameterValue::OSVersion(_) => Tag::OS_VERSION,
+ KeyParameterValue::OSPatchLevel(_) => Tag::OS_PATCHLEVEL,
+ KeyParameterValue::UniqueID(_) => Tag::UNIQUE_ID,
+ KeyParameterValue::AttestationChallenge(_) => Tag::ATTESTATION_CHALLENGE,
+ KeyParameterValue::AttestationApplicationID(_) => Tag::ATTESTATION_APPLICATION_ID,
+ KeyParameterValue::AttestationIdBrand(_) => Tag::ATTESTATION_ID_BRAND,
+ KeyParameterValue::AttestationIdDevice(_) => Tag::ATTESTATION_ID_DEVICE,
+ KeyParameterValue::AttestationIdProduct(_) => Tag::ATTESTATION_ID_PRODUCT,
+ KeyParameterValue::AttestationIdSerial(_) => Tag::ATTESTATION_ID_SERIAL,
+ KeyParameterValue::AttestationIdIMEI(_) => Tag::ATTESTATION_ID_IMEI,
+ KeyParameterValue::AttestationIdMEID(_) => Tag::ATTESTATION_ID_MEID,
+ KeyParameterValue::AttestationIdManufacturer(_) => Tag::ATTESTATION_ID_MANUFACTURER,
+ KeyParameterValue::AttestationIdModel(_) => Tag::ATTESTATION_ID_MODEL,
+ KeyParameterValue::VendorPatchLevel(_) => Tag::VENDOR_PATCHLEVEL,
+ KeyParameterValue::BootPatchLevel(_) => Tag::BOOT_PATCHLEVEL,
+ KeyParameterValue::AssociatedData(_) => Tag::ASSOCIATED_DATA,
+ KeyParameterValue::Nonce(_) => Tag::NONCE,
+ KeyParameterValue::MacLength(_) => Tag::MAC_LENGTH,
+ KeyParameterValue::ResetSinceIdRotation => Tag::RESET_SINCE_ID_ROTATION,
+ KeyParameterValue::ConfirmationToken(_) => Tag::CONFIRMATION_TOKEN,
+ }
+ }
+
+ /// Returns key parameter value.
+ pub fn key_parameter_value(&self) -> &KeyParameterValue {
+ &self.key_parameter_value
+ }
+
+ /// Returns the security level of a KeyParameter.
+ pub fn security_level(&self) -> &SecurityLevel {
+ &self.security_level
+ }
+}
+
+#[cfg(test)]
+mod basic_tests {
+ use crate::key_parameter::*;
+ use crate::keymint_definitions::{SecurityLevel, Tag};
+
+ // Test basic functionality of KeyParameter.
+ #[test]
+ fn test_key_parameter() {
+ let key_parameter = KeyParameter::new(
+ KeyParameterValue::Algorithm(Algorithm::RSA),
+ SecurityLevel::STRONGBOX,
+ );
+
+ assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
+
+ assert_eq!(
+ *key_parameter.key_parameter_value(),
+ KeyParameterValue::Algorithm(Algorithm::RSA)
+ );
+
+ assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
+ }
+}
diff --git a/keystore2/src/keymint_definitions.rs b/keystore2/src/keymint_definitions.rs
new file mode 100644
index 0000000..2658a01
--- /dev/null
+++ b/keystore2/src/keymint_definitions.rs
@@ -0,0 +1,177 @@
+// 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(non_camel_case_types)]
+#![allow(missing_docs)]
+
+/// This is the current interface for the code to-be-generated from the keymint AIDL.
+/// The AIDL spec is at" hardware/interfaces/keymint
+#[repr(u32)]
+#[derive(PartialEq, Debug)]
+pub enum TagType {
+ INVALID = 0 << 28,
+ ENUM = 1 << 28,
+ ENUM_REP = 2 << 28,
+ UINT = 3 << 28,
+ UINT_REP = 4 << 28,
+ ULONG = 5 << 28,
+ DATE = 6 << 28,
+ BOOL = 7 << 28,
+ BIGNUM = 8 << 28,
+ BYTES = 9 << 28,
+ ULONG_REP = 10 << 28,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum Tag {
+ INVALID = TagType::INVALID as u32,
+ PURPOSE = TagType::ENUM_REP as u32 | 1,
+ ALGORITHM = TagType::ENUM as u32 | 2,
+ KEY_SIZE = TagType::UINT as u32 | 3,
+ BLOCK_MODE = TagType::ENUM_REP as u32 | 4,
+ DIGEST = TagType::ENUM_REP as u32 | 5,
+ PADDING = TagType::ENUM_REP as u32 | 6,
+ CALLER_NONCE = TagType::BOOL as u32 | 7,
+ MIN_MAC_LENGTH = TagType::UINT as u32 | 8,
+ EC_CURVE = TagType::ENUM as u32 | 10,
+ RSA_PUBLIC_EXPONENT = TagType::ULONG as u32 | 200,
+ INCLUDE_UNIQUE_ID = TagType::BOOL as u32 | 202,
+ BLOB_USAGE_REQUIREMENTS = TagType::ENUM as u32 | 301,
+ BOOTLOADER_ONLY = TagType::BOOL as u32 | 302,
+ ROLLBACK_RESISTANCE = TagType::BOOL as u32 | 303,
+ ACTIVE_DATETIME = TagType::DATE as u32 | 400,
+ ORIGINATION_EXPIRE_DATETIME = TagType::DATE as u32 | 401,
+ USAGE_EXPIRE_DATETIME = TagType::DATE as u32 | 402,
+ MIN_SECONDS_BETWEEN_OPS = TagType::UINT as u32 | 403,
+ MAX_USES_PER_BOOT = TagType::UINT as u32 | 404,
+ USER_ID = TagType::UINT as u32 | 501,
+ USER_SECURE_ID = TagType::ULONG_REP as u32 | 502,
+ NO_AUTH_REQUIRED = TagType::BOOL as u32 | 503,
+ USER_AUTH_TYPE = TagType::ENUM as u32 | 504,
+ AUTH_TIMEOUT = TagType::UINT as u32 | 505,
+ ALLOW_WHILE_ON_BODY = TagType::BOOL as u32 | 506,
+ TRUSTED_USER_PRESENCE_REQUIRED = TagType::BOOL as u32 | 507,
+ TRUSTED_CONFIRMATION_REQUIRED = TagType::BOOL as u32 | 508,
+ UNLOCKED_DEVICE_REQUIRED = TagType::BOOL as u32 | 509,
+ APPLICATION_ID = TagType::BYTES as u32 | 601,
+ APPLICATION_DATA = TagType::BYTES as u32 | 700,
+ CREATION_DATETIME = TagType::DATE as u32 | 701,
+ ORIGIN = TagType::ENUM as u32 | 702,
+ ROOT_OF_TRUST = TagType::BYTES as u32 | 704,
+ OS_VERSION = TagType::UINT as u32 | 705,
+ OS_PATCHLEVEL = TagType::UINT as u32 | 706,
+ UNIQUE_ID = TagType::BYTES as u32 | 707,
+ ATTESTATION_CHALLENGE = TagType::BYTES as u32 | 708,
+ ATTESTATION_APPLICATION_ID = TagType::BYTES as u32 | 709,
+ ATTESTATION_ID_BRAND = TagType::BYTES as u32 | 710,
+ ATTESTATION_ID_DEVICE = TagType::BYTES as u32 | 711,
+ ATTESTATION_ID_PRODUCT = TagType::BYTES as u32 | 712,
+ ATTESTATION_ID_SERIAL = TagType::BYTES as u32 | 713,
+ ATTESTATION_ID_IMEI = TagType::BYTES as u32 | 714,
+ ATTESTATION_ID_MEID = TagType::BYTES as u32 | 715,
+ ATTESTATION_ID_MANUFACTURER = TagType::BYTES as u32 | 716,
+ ATTESTATION_ID_MODEL = TagType::BYTES as u32 | 717,
+ VENDOR_PATCHLEVEL = TagType::UINT as u32 | 718,
+ BOOT_PATCHLEVEL = TagType::UINT as u32 | 719,
+ ASSOCIATED_DATA = TagType::BYTES as u32 | 1000,
+ NONCE = TagType::BYTES as u32 | 1001,
+ MAC_LENGTH = TagType::UINT as u32 | 1003,
+ RESET_SINCE_ID_ROTATION = TagType::BOOL as u32 | 1004,
+ CONFIRMATION_TOKEN = TagType::BYTES as u32 | 1005,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum Algorithm {
+ RSA = 1,
+ EC = 3,
+ AES = 32,
+ TRIPLE_DES = 33,
+ HMAC = 128,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum BlockMode {
+ ECB = 1,
+ CBC = 2,
+ CTR = 3,
+ GCM = 32,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum PaddingMode {
+ NONE = 1,
+ RSA_OAEP = 2,
+ RSA_PSS = 3,
+ RSA_PKCS1_1_5_ENCRYPT = 4,
+ RSA_PKCS1_1_5_SIGN = 5,
+ PKCS7 = 64,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum Digest {
+ NONE = 0,
+ MD5 = 1,
+ SHA1 = 2,
+ SHA_2_224 = 3,
+ SHA_2_256 = 4,
+ SHA_2_384 = 5,
+ SHA_2_512 = 6,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum EcCurve {
+ P_224 = 0,
+ P_256 = 1,
+ P_384 = 2,
+ P_521 = 3,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum KeyOrigin {
+ GENERATED = 0,
+ DERIVED = 1,
+ IMPORTED = 2,
+ UNKNOWN = 3,
+ SECURELY_IMPORTED = 4,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum KeyBlobUsageRequirements {
+ STANDALONE = 0,
+ REQUIRES_FILE_SYSTEM = 1,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum KeyPurpose {
+ ENCRYPT = 0,
+ DECRYPT = 1,
+ SIGN = 2,
+ VERIFY = 3,
+ WRAP_KEY = 5,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum HardwareAuthenticatorType {
+ NONE = 0,
+ PASSWORD = 1,
+ FINGERPRINT = 1 << 1,
+ ANY = (0xFFFFFFFF as u32) as u32,
+}
+#[repr(u32)]
+#[derive(PartialEq, Debug, Copy, Clone)]
+pub enum SecurityLevel {
+ SOFTWARE = 0,
+ TRUSTED_ENVIRONMENT = 1,
+ STRONGBOX = 2,
+}
diff --git a/keystore2/src/lib.rs b/keystore2/src/lib.rs
new file mode 100644
index 0000000..13ef87d
--- /dev/null
+++ b/keystore2/src/lib.rs
@@ -0,0 +1,23 @@
+// 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 Android Keystore 2.0 service.
+
+pub mod database;
+pub mod error;
+/// Internal Representation of Key Parameter and convenience functions.
+pub mod key_parameter;
+/// Internal interface for the code to-be-generated from the keymint AIDL
+pub mod keymint_definitions;
+pub mod permission;
diff --git a/keystore2/src/permission.rs b/keystore2/src/permission.rs
new file mode 100644
index 0000000..0db56dd
--- /dev/null
+++ b/keystore2/src/permission.rs
@@ -0,0 +1,916 @@
+// 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 provides access control primitives for Keystore 2.0.
+//! It provides high level functions for checking permissions in the keystore2 and keystore2_key
+//! SELinux classes based on the keystore2_selinux backend.
+//! It also provides KeystorePerm and KeyPerm as convenience wrappers for the SELinux permission
+//! defined by keystore2 and keystore2_key respectively.
+
+use keystore_aidl_generated as aidl;
+
+use std::cmp::PartialEq;
+use std::convert::From;
+
+use crate::error::Error as KsError;
+use keystore2_selinux as selinux;
+
+use anyhow::Context as AnyhowContext;
+
+use selinux::Backend;
+
+use lazy_static::lazy_static;
+
+// Replace getcon with a mock in the test situation
+#[cfg(not(test))]
+use selinux::getcon;
+#[cfg(test)]
+use tests::test_getcon as getcon;
+
+lazy_static! {
+ // Panicking here is allowed because keystore cannot function without this backend
+ // and it would happen early and indicate a gross misconfiguration of the device.
+ static ref KEYSTORE2_KEY_LABEL_BACKEND: selinux::KeystoreKeyBackend =
+ selinux::KeystoreKeyBackend::new().unwrap();
+}
+
+fn lookup_keystore2_key_context(namespace: i64) -> anyhow::Result<selinux::Context> {
+ KEYSTORE2_KEY_LABEL_BACKEND.lookup(&namespace.to_string())
+}
+
+/// The below example wraps the enum MyPermission in the tuple struct `MyPerm` and implements
+/// * `From<i32> for `MyPerm`, where each unknown numeric value is mapped to the given default,
+/// here `None`
+/// * `Into<MyPermission> for `MyPerm`
+/// * `MyPerm::foo()` and `MyPerm::bar()` which construct MyPerm instances representing
+/// `MyPermission::Foo` and `MyPermission::Bar` respectively.
+/// * `MyPerm.to_selinux(&self)`, which returns the selinux string representation of the
+/// represented permission.
+/// * Tests in the given test namespace for each permision that check that the numeric
+/// representations of MyPermission and MyPerm match. (TODO replace with static assert if
+/// they become available.)
+///
+/// ## Special behavior
+/// If the keyword `use` appears as an selinux name `use_` is used as identifier for the
+/// constructor function (e.g. `MePerm::use_()`) but the string returned by `to_selinux` will
+/// still be `"use"`.
+///
+/// ## Example
+/// ```
+/// #[i32]
+/// enum MyPermission {
+/// None = 0,
+/// Foo = 1,
+/// Bar = 2,
+/// }
+///
+/// implement_permission!(
+/// /// MyPerm documentation.
+/// #[derive(Clone, Copy, Debug, PartialEq)]
+/// MyPermission as MyPerm with default (None = 0, none)
+/// and test namespace my_perm_tests {
+/// Foo = 1, selinux name: foo;
+/// Bar = 2, selinux name: bar;
+/// }
+/// );
+/// ```
+macro_rules! implement_permission {
+ // This rule provides the public interface of the macro. And starts the preprocessing
+ // recursion (see below).
+ ($(#[$m:meta])* $t:ty as $name:ident with default ($($def:tt)*)
+ and test namespace $tn:ident { $($element:tt)* })
+ => {
+ implement_permission!(@replace_use $($m)*, $t, $name, $tn, ($($def)*), [] , $($element)*);
+ };
+
+
+ // The following three rules recurse through the elements of the form
+ // `<enum variant> = <integer_literal>, selinux name: <selinux_name>;`
+ // preprocessing the input.
+
+ // The first rule terminates the recursion and passes the processed arguments to the final
+ // rule that spills out the implementation.
+ (@replace_use $($m:meta)*, $t:ty, $name:ident, $tn:ident, ($($def:tt)*), [$($out:tt)*], ) => {
+ implement_permission!(@end $($m)*, $t, $name, $tn, ($($def)*) { $($out)* } );
+ };
+
+ // The second rule is triggered if the selinux name of an element is literally `use`.
+ // It produces the tuple `<enum variant> = <integer_literal>, use_, use;`
+ // and appends it to the out list.
+ (@replace_use $($m:meta)*, $t:ty, $name:ident, $tn:ident, ($($def:tt)*), [$($out:tt)*],
+ $e_name:ident = $e_val:expr, selinux name: use; $($element:tt)*)
+ => {
+ implement_permission!(@replace_use $($m)*, $t, $name, $tn, ($($def)*),
+ [$($out)* $e_name = $e_val, use_, use;], $($element)*);
+ };
+
+ // The third rule is the default rule which replaces every input tuple with
+ // `<enum variant> = <integer_literal>, <selinux_name>, <selinux_name>;`
+ // and appends the result to the out list.
+ (@replace_use $($m:meta)*, $t:ty, $name:ident, $tn:ident, ($($def:tt)*), [$($out:tt)*],
+ $e_name:ident = $e_val:expr, selinux name: $e_str:ident; $($element:tt)*)
+ => {
+ implement_permission!(@replace_use $($m)*, $t, $name, $tn, ($($def)*),
+ [$($out)* $e_name = $e_val, $e_str, $e_str;], $($element)*);
+ };
+
+ (@end $($m:meta)*, $t:ty, $name:ident, $tn:ident,
+ ($def_name:ident = $def:expr, $def_selinux_name:ident) {
+ $($element_name:ident = $element_val:expr, $element_identifier:ident,
+ $selinux_name:ident;)*
+ })
+ =>
+ {
+ $(#[$m])*
+ pub struct $name($t);
+
+ impl From<i32> for $name {
+ fn from (p: i32) -> Self {
+ match p {
+ $def => Self(<$t>::$def_name),
+ $($element_val => Self(<$t>::$element_name),)*
+ _ => Self(<$t>::$def_name),
+ }
+ }
+ }
+
+ impl Into<$t> for $name {
+ fn into(self) -> $t {
+ self.0
+ }
+ }
+
+ impl $name {
+ /// Returns a string representation of the permission as required by
+ /// `selinux::check_access`.
+ pub fn to_selinux(&self) -> &'static str {
+ match self {
+ Self(<$t>::$def_name) => stringify!($def_selinux_name),
+ $(Self(<$t>::$element_name) => stringify!($selinux_name),)*
+ }
+ }
+
+ /// Creates an instance representing a permission with the same name.
+ pub const fn $def_selinux_name() -> Self { Self(<$t>::$def_name) }
+ $(
+ /// Creates an instance representing a permission with the same name.
+ pub const fn $element_identifier() -> Self { Self(<$t>::$element_name) }
+ )*
+ }
+ #[cfg(test)]
+ mod $tn {
+ use super::*;
+
+ #[test]
+ fn $def_selinux_name() {
+ assert_eq!($name::$def_selinux_name(), (<$t>::$def_name as i32).into());
+ }
+ $(
+ #[test]
+ fn $element_identifier() {
+ assert_eq!($name::$element_identifier(), (<$t>::$element_name as i32).into());
+ }
+ )*
+ }
+ };
+
+
+}
+
+implement_permission!(
+ /// KeyPerm provides a convenient abstraction from the SELinux class `keystore2_key`.
+ /// At the same time it maps `KeyPermissions` from the Keystore 2.0 AIDL Grant interface to
+ /// the SELinux permissions. With the implement_permission macro, we conveniently
+ /// provide mappings between the wire type bit field values, the rust enum and the SELinux
+ /// string representation.
+ ///
+ /// ## Example
+ ///
+ /// In this access check `KeyPerm::get_info().to_selinux()` would return the SELinux representation
+ /// "info".
+ /// ```
+ /// selinux::check_access(source_context, target_context, "keystore2_key",
+ /// KeyPerm::get_info().to_selinux());
+ /// ```
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+ aidl::KeyPermission as KeyPerm with default (None = 0, none)
+ and test namespace key_perm_tests {
+ Delete = 1, selinux name: delete;
+ GenUniqueId = 2, selinux name: gen_unique_id;
+ GetInfo = 4, selinux name: get_info;
+ Grant = 8, selinux name: grant;
+ List = 0x10, selinux name: list;
+ ManageBlob = 0x20, selinux name: manage_blob;
+ Rebind = 0x40, selinux name: rebind;
+ ReqForcedOp = 0x80, selinux name: req_forced_op;
+ Update = 0x100, selinux name: update;
+ Use = 0x200, selinux name: use;
+ UseDevId = 0x400, selinux name: use_dev_id;
+ }
+);
+
+/// KeystorePermission defines values for the SELinux `keystore2` security class.
+/// Countrary to `KeyPermission`, this enum is not generated by AIDL and need not be
+/// wrapped by newtype pattern. But we conveniently use the implement_permission macro
+/// to provide the same feature that we did for `KeyPermission` to this set of permissions.
+#[repr(i32)]
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub enum KeystorePermission {
+ /// `None` is not a permission that can ever be granted. It is not known to the SEPolicy.
+ None = 0,
+ /// Checked when a new auth token is installed.
+ AddAuth = 1,
+ /// Checked when an app is uninstalled or wiped.
+ ClearNs = 2,
+ /// Checked when the locked state of Keystore 2.0 is queried.
+ GetState = 4,
+ /// Checked when Keystore 2.0 gets locked.
+ Lock = 8,
+ /// Checked when Keystore 2.0 shall be reset.
+ Reset = 0x10,
+ /// Checked when Keystore 2.0 shall be unlocked.
+ Unlock = 0x20,
+}
+
+implement_permission!(
+ /// KeystorePerm provides a convenient abstraction from the SELinux class `keystore2`.
+ /// Using the implement_permission macro we get the same features as `KeyPerm`.
+ #[derive(Clone, Copy, Debug, PartialEq)]
+ KeystorePermission as KeystorePerm with default (None = 0, none)
+ and test namespace keystore_perm_tests {
+ AddAuth = 1, selinux name: add_auth;
+ ClearNs = 2, selinux name: clear_ns;
+ GetState = 4, selinux name: get_state;
+ Lock = 8, selinux name: lock;
+ Reset = 0x10, selinux name: reset;
+ Unlock = 0x20, selinux name: unlock;
+ }
+);
+
+/// Represents a set of `KeyPerm` permissions.
+/// `IntoIterator` is implemented for this struct allowing the iteration through all the
+/// permissions in the set.
+/// It also implements a function `includes(self, other)` that checks if the permissions
+/// in `other` are included in `self`.
+///
+/// KeyPermSet can be created with the macro `key_perm_set![]`.
+///
+/// ## Example
+/// ```
+/// let perms1 = key_perm_set![KeyPerm::use_(), KeyPerm::manage_blob(), KeyPerm::grant()];
+/// let perms2 = key_perm_set![KeyPerm::use_(), KeyPerm::manage_blob()];
+///
+/// assert!(perms1.includes(perms2))
+/// assert!(!perms2.includes(perms1))
+///
+/// let i = perms1.into_iter();
+/// // iteration in ascending order of the permission's numeric representation.
+/// assert_eq(Some(KeyPerm::manage_blob()), i.next());
+/// assert_eq(Some(KeyPerm::grant()), i.next());
+/// assert_eq(Some(KeyPerm::use_()), i.next());
+/// assert_eq(None, i.next());
+/// ```
+#[derive(Copy, Clone)]
+pub struct KeyPermSet(i32);
+
+mod perm {
+ use super::*;
+
+ pub struct IntoIter {
+ vec: KeyPermSet,
+ pos: u8,
+ }
+
+ impl IntoIter {
+ pub fn new(v: KeyPermSet) -> Self {
+ Self { vec: v, pos: 0 }
+ }
+ }
+
+ impl std::iter::Iterator for IntoIter {
+ type Item = KeyPerm;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ loop {
+ if self.pos == 32 {
+ return None;
+ }
+ let p = self.vec.0 & (1 << self.pos);
+ self.pos += 1;
+ if p != 0 {
+ return Some(KeyPerm::from(p));
+ }
+ }
+ }
+ }
+}
+
+impl From<KeyPerm> for KeyPermSet {
+ fn from(p: KeyPerm) -> Self {
+ Self(p.0 as i32)
+ }
+}
+
+impl KeyPermSet {
+ /// Returns true iff this permission set has all of the permissions that are in `other`.
+ fn includes<T: Into<KeyPermSet>>(&self, other: T) -> bool {
+ let o: KeyPermSet = other.into();
+ (self.0 & o.0) == o.0
+ }
+}
+
+/// This macro can be used to create a `KeyPermSet` from a list of `KeyPerm` values.
+///
+/// ## Example
+/// ```
+/// let v = key_perm_set![Perm::delete(), Perm::manage_blob()];
+/// ```
+#[macro_export]
+macro_rules! key_perm_set {
+ () => { KeyPermSet(0) };
+ ($head:expr $(, $tail:expr)* $(,)?) => {
+ KeyPermSet($head.0 as i32 $(| $tail.0 as i32)*)
+ };
+}
+
+impl IntoIterator for KeyPermSet {
+ type Item = KeyPerm;
+ type IntoIter = perm::IntoIter;
+
+ fn into_iter(self) -> Self::IntoIter {
+ Self::IntoIter::new(self)
+ }
+}
+
+/// Uses `selinux::check_access` to check if the given caller context `caller_cxt` may access
+/// the given permision `perm` of the `keystore2` security class.
+pub fn check_keystore_permission(
+ caller_ctx: &selinux::Context,
+ perm: KeystorePerm,
+) -> anyhow::Result<()> {
+ let target_context = getcon().context("check_keystore_permission: getcon failed.")?;
+ selinux::check_access(caller_ctx, &target_context, "keystore2", perm.to_selinux())
+}
+
+/// Uses `selinux::check_access` to check if the given caller context `caller_cxt` has
+/// all the permissions indicated in `access_vec` for the target domain indicated by the key
+/// descriptor `key` in the security class `keystore2_key`.
+///
+/// Also checks if the caller has the grant permission for the given target domain.
+///
+/// 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
+/// SELinux keystore key backend, and the result is used
+/// as target context.
+pub fn check_grant_permission(
+ caller_ctx: &selinux::Context,
+ access_vec: KeyPermSet,
+ key: &aidl::KeyDescriptor,
+) -> anyhow::Result<()> {
+ use aidl::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.")?,
+ _ => return Err(KsError::sys()).context(format!("Cannot grant {:?}.", key.domain)),
+ };
+
+ selinux::check_access(caller_ctx, &target_context, "keystore2_key", "grant")
+ .context("Grant permission is required when granting.")?;
+
+ if access_vec.includes(KeyPerm::grant()) {
+ return Err(selinux::Error::perm()).context("Grant permission cannot be granted.");
+ }
+
+ for p in access_vec.into_iter() {
+ selinux::check_access(caller_ctx, &target_context, "keystore2_key", p.to_selinux())
+ .context(concat!(
+ "check_grant_permission: check_access failed. ",
+ "The caller may have tried to grant a permission that they don't possess."
+ ))?
+ }
+ Ok(())
+}
+
+/// Uses `selinux::check_access` to check if the given caller context `caller_cxt`
+/// has the permissions indicated by `perm` for the target domain indicated by the key
+/// 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
+/// backend, and the result is used as target context.
+/// * `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`
+/// 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
+/// on various unexpected backend failures.
+pub fn check_key_permission(
+ caller_ctx: &selinux::Context,
+ perm: KeyPerm,
+ key: &aidl::KeyDescriptor,
+ access_vector: &Option<KeyPermSet>,
+) -> anyhow::Result<()> {
+ use aidl::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 => {
+ match access_vector {
+ Some(pv) => {
+ if pv.includes(perm) {
+ return Ok(());
+ } else {
+ return Err(selinux::Error::perm())
+ .context(format!("\"{}\" not granted", perm.to_selinux()));
+ }
+ }
+ 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.",
+ );
+ }
+ }
+ }
+ 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::Blob => {
+ let tctx = lookup_keystore2_key_context(key.namespace_)
+ .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(
+ caller_ctx,
+ &tctx,
+ "keystore2_key",
+ KeyPerm::manage_blob().to_selinux(),
+ )?;
+
+ tctx
+ }
+ };
+
+ selinux::check_access(caller_ctx, &target_context, "keystore2_key", perm.to_selinux())
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use anyhow::anyhow;
+ use anyhow::Result;
+ use keystore2_selinux::*;
+ use keystore_aidl_generated as aidl;
+
+ const ALL_PERMS: KeyPermSet = key_perm_set![
+ KeyPerm::manage_blob(),
+ KeyPerm::delete(),
+ KeyPerm::use_dev_id(),
+ KeyPerm::req_forced_op(),
+ KeyPerm::gen_unique_id(),
+ KeyPerm::grant(),
+ KeyPerm::get_info(),
+ KeyPerm::list(),
+ KeyPerm::rebind(),
+ KeyPerm::update(),
+ KeyPerm::use_(),
+ ];
+
+ const NOT_GRANT_PERMS: KeyPermSet = key_perm_set![
+ KeyPerm::manage_blob(),
+ KeyPerm::delete(),
+ KeyPerm::use_dev_id(),
+ KeyPerm::req_forced_op(),
+ KeyPerm::gen_unique_id(),
+ // No KeyPerm::grant()
+ KeyPerm::get_info(),
+ KeyPerm::list(),
+ KeyPerm::rebind(),
+ KeyPerm::update(),
+ KeyPerm::use_(),
+ ];
+
+ const UNPRIV_PERMS: KeyPermSet = key_perm_set![
+ KeyPerm::delete(),
+ KeyPerm::get_info(),
+ KeyPerm::list(),
+ KeyPerm::rebind(),
+ KeyPerm::update(),
+ KeyPerm::use_(),
+ ];
+
+ /// The su_key namespace as defined in su.te and keystore_key_contexts of the
+ /// SePolicy (system/sepolicy).
+ const SU_KEY_NAMESPACE: i32 = 0;
+ /// The shell_key namespace as defined in shell.te and keystore_key_contexts of the
+ /// SePolicy (system/sepolicy).
+ const SHELL_KEY_NAMESPACE: i32 = 1;
+
+ pub fn test_getcon() -> Result<Context> {
+ Context::new("u:object_r:keystore:s0")
+ }
+
+ // This macro evaluates the given expression and checks that
+ // a) evaluated to Result::Err() and that
+ // b) the wrapped error is selinux::Error::perm() (permission denied).
+ // We use a macro here because a function would mask which invocation caused the failure.
+ //
+ // TODO b/164121720 Replace this macro with a function when `track_caller` is available.
+ macro_rules! assert_perm_failed {
+ ($test_function:expr) => {
+ let result = $test_function;
+ assert!(result.is_err(), "Permission check should have failed.");
+ assert_eq!(
+ Some(&selinux::Error::perm()),
+ result.err().unwrap().root_cause().downcast_ref::<selinux::Error>()
+ );
+ };
+ }
+
+ fn check_context() -> Result<(selinux::Context, i32, bool)> {
+ // Calling the non mocked selinux::getcon here intended.
+ let context = selinux::getcon()?;
+ match context.to_str().unwrap() {
+ "u:r:su:s0" => Ok((context, SU_KEY_NAMESPACE, true)),
+ "u:r:shell:s0" => Ok((context, SHELL_KEY_NAMESPACE, false)),
+ c => Err(anyhow!(format!(
+ "This test must be run as \"su\" or \"shell\". Current context: \"{}\"",
+ c
+ ))),
+ }
+ }
+
+ #[test]
+ fn check_keystore_permission_test() -> Result<()> {
+ let system_server_ctx = Context::new("u:r:system_server:s0")?;
+ assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::add_auth()).is_ok());
+ assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::clear_ns()).is_ok());
+ assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::get_state()).is_ok());
+ assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::lock()).is_ok());
+ assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::reset()).is_ok());
+ assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::unlock()).is_ok());
+ let shell_ctx = Context::new("u:r:shell:s0")?;
+ assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::add_auth()));
+ assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::clear_ns()));
+ assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::get_state()));
+ assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::lock()));
+ assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::reset()));
+ assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::unlock()));
+ Ok(())
+ }
+
+ #[test]
+ 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 aidl::Domain;
+ let key =
+ aidl::KeyDescriptor { domain: Domain::App, namespace_: 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.
+
+ assert_perm_failed!(check_grant_permission(
+ &system_server_ctx,
+ KeyPerm::grant().into(),
+ &key
+ ));
+ // unprivileged grant attempts always fail. shell does not have the grant permission.
+ assert_perm_failed!(check_grant_permission(&shell_ctx, UNPRIV_PERMS, &key));
+ Ok(())
+ }
+
+ #[test]
+ fn check_grant_permission_selinux() -> Result<()> {
+ use aidl::Domain;
+ let (sctx, namespace, is_su) = check_context()?;
+ let key = aidl::KeyDescriptor {
+ domain: Domain::SELinux,
+ namespace_: namespace as i64,
+ alias: None,
+ blob: None,
+ };
+ if is_su {
+ assert!(check_grant_permission(&sctx, NOT_GRANT_PERMS, &key).is_ok());
+ // attempts to grant the grant permission must always fail even when privileged.
+ assert_perm_failed!(check_grant_permission(&sctx, KeyPerm::grant().into(), &key));
+ } else {
+ // unprivileged grant attempts always fail. shell does not have the grant permission.
+ assert_perm_failed!(check_grant_permission(&sctx, UNPRIV_PERMS, &key));
+ }
+ Ok(())
+ }
+
+ #[test]
+ fn check_key_permission_domain_grant() -> Result<()> {
+ use aidl::Domain;
+ let key =
+ aidl::KeyDescriptor { domain: Domain::Grant, namespace_: 0, alias: None, blob: None };
+
+ assert_perm_failed!(check_key_permission(
+ &selinux::Context::new("ignored").unwrap(),
+ KeyPerm::grant(),
+ &key,
+ &Some(UNPRIV_PERMS)
+ ));
+
+ check_key_permission(
+ &selinux::Context::new("ignored").unwrap(),
+ KeyPerm::use_(),
+ &key,
+ &Some(ALL_PERMS),
+ )
+ }
+
+ #[test]
+ fn check_key_permission_domain_app() -> Result<()> {
+ 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 aidl::Domain;
+
+ let key =
+ aidl::KeyDescriptor { domain: Domain::App, namespace_: 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());
+ assert!(check_key_permission(&system_server_ctx, KeyPerm::get_info(), &key, &None).is_ok());
+ assert!(check_key_permission(&system_server_ctx, KeyPerm::rebind(), &key, &None).is_ok());
+ assert!(check_key_permission(&system_server_ctx, KeyPerm::list(), &key, &None).is_ok());
+ assert!(check_key_permission(&system_server_ctx, KeyPerm::update(), &key, &None).is_ok());
+ assert!(check_key_permission(&system_server_ctx, KeyPerm::grant(), &key, &None).is_ok());
+ assert!(
+ check_key_permission(&system_server_ctx, KeyPerm::use_dev_id(), &key, &None).is_ok()
+ );
+ assert!(check_key_permission(&gmscore_app, KeyPerm::gen_unique_id(), &key, &None).is_ok());
+
+ assert!(check_key_permission(&shell_ctx, KeyPerm::use_(), &key, &None).is_ok());
+ assert!(check_key_permission(&shell_ctx, KeyPerm::delete(), &key, &None).is_ok());
+ assert!(check_key_permission(&shell_ctx, KeyPerm::get_info(), &key, &None).is_ok());
+ assert!(check_key_permission(&shell_ctx, KeyPerm::rebind(), &key, &None).is_ok());
+ assert!(check_key_permission(&shell_ctx, KeyPerm::list(), &key, &None).is_ok());
+ assert!(check_key_permission(&shell_ctx, KeyPerm::update(), &key, &None).is_ok());
+ assert_perm_failed!(check_key_permission(&shell_ctx, KeyPerm::grant(), &key, &None));
+ assert_perm_failed!(check_key_permission(
+ &shell_ctx,
+ KeyPerm::req_forced_op(),
+ &key,
+ &None
+ ));
+ assert_perm_failed!(check_key_permission(&shell_ctx, KeyPerm::manage_blob(), &key, &None));
+ assert_perm_failed!(check_key_permission(&shell_ctx, KeyPerm::use_dev_id(), &key, &None));
+ assert_perm_failed!(check_key_permission(
+ &shell_ctx,
+ KeyPerm::gen_unique_id(),
+ &key,
+ &None
+ ));
+
+ Ok(())
+ }
+
+ #[test]
+ fn check_key_permission_domain_selinux() -> Result<()> {
+ use aidl::Domain;
+ let (sctx, namespace, is_su) = check_context()?;
+ let key = aidl::KeyDescriptor {
+ domain: Domain::SELinux,
+ namespace_: namespace as i64,
+ alias: None,
+ blob: None,
+ };
+
+ if is_su {
+ assert!(check_key_permission(&sctx, KeyPerm::use_(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::delete(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::get_info(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::rebind(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::list(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::update(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::grant(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::manage_blob(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::use_dev_id(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::gen_unique_id(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::req_forced_op(), &key, &None).is_ok());
+ } else {
+ assert!(check_key_permission(&sctx, KeyPerm::use_(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::delete(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::get_info(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::rebind(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::list(), &key, &None).is_ok());
+ assert!(check_key_permission(&sctx, KeyPerm::update(), &key, &None).is_ok());
+ assert_perm_failed!(check_key_permission(&sctx, KeyPerm::grant(), &key, &None));
+ assert_perm_failed!(check_key_permission(&sctx, KeyPerm::req_forced_op(), &key, &None));
+ assert_perm_failed!(check_key_permission(&sctx, KeyPerm::manage_blob(), &key, &None));
+ assert_perm_failed!(check_key_permission(&sctx, KeyPerm::use_dev_id(), &key, &None));
+ assert_perm_failed!(check_key_permission(&sctx, KeyPerm::gen_unique_id(), &key, &None));
+ }
+ Ok(())
+ }
+
+ #[test]
+ fn check_key_permission_domain_blob() -> Result<()> {
+ use aidl::Domain;
+ let (sctx, namespace, is_su) = check_context()?;
+ let key = aidl::KeyDescriptor {
+ domain: Domain::Blob,
+ namespace_: namespace as i64,
+ alias: None,
+ blob: None,
+ };
+
+ if is_su {
+ check_key_permission(&sctx, KeyPerm::use_(), &key, &None)
+ } else {
+ assert_perm_failed!(check_key_permission(&sctx, KeyPerm::use_(), &key, &None));
+ Ok(())
+ }
+ }
+
+ #[test]
+ fn check_key_permission_domain_key_id() -> Result<()> {
+ use aidl::Domain;
+ let key =
+ aidl::KeyDescriptor { domain: Domain::KeyId, namespace_: 0, alias: None, blob: None };
+
+ assert_eq!(
+ Some(&KsError::sys()),
+ check_key_permission(
+ &selinux::Context::new("ignored").unwrap(),
+ KeyPerm::use_(),
+ &key,
+ &None
+ )
+ .err()
+ .unwrap()
+ .root_cause()
+ .downcast_ref::<KsError>()
+ );
+ Ok(())
+ }
+
+ #[test]
+ fn key_perm_set_all_test() {
+ let v = key_perm_set![
+ KeyPerm::manage_blob(),
+ KeyPerm::delete(),
+ KeyPerm::use_dev_id(),
+ KeyPerm::req_forced_op(),
+ KeyPerm::gen_unique_id(),
+ KeyPerm::grant(),
+ KeyPerm::get_info(),
+ KeyPerm::list(),
+ KeyPerm::rebind(),
+ KeyPerm::update(),
+ KeyPerm::use_() // Test if the macro accepts missing comma at the end of the list.
+ ];
+ let mut i = v.into_iter();
+ assert_eq!(i.next().unwrap().to_selinux(), "delete");
+ assert_eq!(i.next().unwrap().to_selinux(), "gen_unique_id");
+ assert_eq!(i.next().unwrap().to_selinux(), "get_info");
+ assert_eq!(i.next().unwrap().to_selinux(), "grant");
+ assert_eq!(i.next().unwrap().to_selinux(), "list");
+ assert_eq!(i.next().unwrap().to_selinux(), "manage_blob");
+ assert_eq!(i.next().unwrap().to_selinux(), "rebind");
+ assert_eq!(i.next().unwrap().to_selinux(), "req_forced_op");
+ assert_eq!(i.next().unwrap().to_selinux(), "update");
+ assert_eq!(i.next().unwrap().to_selinux(), "use");
+ assert_eq!(i.next().unwrap().to_selinux(), "use_dev_id");
+ assert_eq!(None, i.next());
+ }
+ #[test]
+ fn key_perm_set_sparse_test() {
+ let v = key_perm_set![
+ KeyPerm::manage_blob(),
+ KeyPerm::req_forced_op(),
+ KeyPerm::gen_unique_id(),
+ KeyPerm::list(),
+ KeyPerm::update(),
+ KeyPerm::use_(), // Test if macro accepts the comma at the end of the list.
+ ];
+ let mut i = v.into_iter();
+ assert_eq!(i.next().unwrap().to_selinux(), "gen_unique_id");
+ assert_eq!(i.next().unwrap().to_selinux(), "list");
+ assert_eq!(i.next().unwrap().to_selinux(), "manage_blob");
+ assert_eq!(i.next().unwrap().to_selinux(), "req_forced_op");
+ assert_eq!(i.next().unwrap().to_selinux(), "update");
+ assert_eq!(i.next().unwrap().to_selinux(), "use");
+ assert_eq!(None, i.next());
+ }
+ #[test]
+ fn key_perm_set_empty_test() {
+ let v = key_perm_set![];
+ let mut i = v.into_iter();
+ assert_eq!(None, i.next());
+ }
+ #[test]
+ fn key_perm_set_include_subset_test() {
+ let v1 = key_perm_set![
+ KeyPerm::manage_blob(),
+ KeyPerm::delete(),
+ KeyPerm::use_dev_id(),
+ KeyPerm::req_forced_op(),
+ KeyPerm::gen_unique_id(),
+ KeyPerm::grant(),
+ KeyPerm::get_info(),
+ KeyPerm::list(),
+ KeyPerm::rebind(),
+ KeyPerm::update(),
+ KeyPerm::use_(),
+ ];
+ let v2 = key_perm_set![
+ KeyPerm::manage_blob(),
+ KeyPerm::delete(),
+ KeyPerm::list(),
+ KeyPerm::rebind(),
+ KeyPerm::update(),
+ KeyPerm::use_(),
+ ];
+ assert!(v1.includes(v2));
+ assert!(!v2.includes(v1));
+ }
+ #[test]
+ fn key_perm_set_include_equal_test() {
+ let v1 = key_perm_set![
+ KeyPerm::manage_blob(),
+ KeyPerm::delete(),
+ KeyPerm::list(),
+ KeyPerm::rebind(),
+ KeyPerm::update(),
+ KeyPerm::use_(),
+ ];
+ let v2 = key_perm_set![
+ KeyPerm::manage_blob(),
+ KeyPerm::delete(),
+ KeyPerm::list(),
+ KeyPerm::rebind(),
+ KeyPerm::update(),
+ KeyPerm::use_(),
+ ];
+ assert!(v1.includes(v2));
+ assert!(v2.includes(v1));
+ }
+ #[test]
+ fn key_perm_set_include_overlap_test() {
+ let v1 = key_perm_set![
+ KeyPerm::manage_blob(),
+ KeyPerm::delete(),
+ KeyPerm::grant(), // only in v1
+ KeyPerm::list(),
+ KeyPerm::rebind(),
+ KeyPerm::update(),
+ KeyPerm::use_(),
+ ];
+ let v2 = key_perm_set![
+ KeyPerm::manage_blob(),
+ KeyPerm::delete(),
+ KeyPerm::req_forced_op(), // only in v2
+ KeyPerm::list(),
+ KeyPerm::rebind(),
+ KeyPerm::update(),
+ KeyPerm::use_(),
+ ];
+ assert!(!v1.includes(v2));
+ assert!(!v2.includes(v1));
+ }
+ #[test]
+ fn key_perm_set_include_no_overlap_test() {
+ let v1 = key_perm_set![KeyPerm::manage_blob(), KeyPerm::delete(), KeyPerm::grant(),];
+ let v2 = key_perm_set![
+ KeyPerm::req_forced_op(),
+ KeyPerm::list(),
+ KeyPerm::rebind(),
+ KeyPerm::update(),
+ KeyPerm::use_(),
+ ];
+ assert!(!v1.includes(v2));
+ assert!(!v2.includes(v1));
+ }
+}