Merge "Add attestation application id for key attestation"
diff --git a/keystore/.clang-format b/keystore/.clang-format
index 5747e19..b0dc94c 100644
--- a/keystore/.clang-format
+++ b/keystore/.clang-format
@@ -3,7 +3,7 @@
UseTab: Never
BreakBeforeBraces: Attach
AllowShortFunctionsOnASingleLine: Inline
-AllowShortIfStatementsOnASingleLine: false
+AllowShortIfStatementsOnASingleLine: true
IndentCaseLabels: false
ColumnLimit: 100
PointerBindsToType: true
diff --git a/keystore/Android.mk b/keystore/Android.mk
index f17d5eb..1af8b75 100644
--- a/keystore/Android.mk
+++ b/keystore/Android.mk
@@ -32,13 +32,15 @@
blob.cpp \
entropy.cpp \
key_store_service.cpp \
+ keystore_attestation_id.cpp \
keyblob_utils.cpp \
keystore.cpp \
keystore_main.cpp \
keystore_utils.cpp \
operation.cpp \
permissions.cpp \
- user_state.cpp
+ user_state.cpp \
+ ../../../frameworks/base/core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl
LOCAL_SHARED_LIBRARIES := \
libbinder \
libcutils \
@@ -59,6 +61,7 @@
LOCAL_CLANG := true
LOCAL_SANITIZE := integer
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_AIDL_INCLUDES := frameworks/base/core/java/
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
@@ -97,6 +100,9 @@
LOCAL_CFLAGS := -Wall -Wextra -Werror
LOCAL_SRC_FILES := \
IKeystoreService.cpp \
+ KeyAttestationApplicationId.cpp \
+ KeyAttestationPackageInfo.cpp \
+ Signature.cpp \
keyblob_utils.cpp \
keystore_client.proto \
keystore_client_impl.cpp \
diff --git a/keystore/KeyAttestationApplicationId.cpp b/keystore/KeyAttestationApplicationId.cpp
new file mode 100644
index 0000000..1352124
--- /dev/null
+++ b/keystore/KeyAttestationApplicationId.cpp
@@ -0,0 +1,40 @@
+/*
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "include/keystore/KeyAttestationApplicationId.h"
+
+#include <binder/Parcel.h>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+status_t KeyAttestationApplicationId::writeToParcel(Parcel* parcel) const {
+ return parcel->writeParcelableVector(packageInfos_);
+}
+
+status_t KeyAttestationApplicationId::readFromParcel(const Parcel* parcel) {
+ std::unique_ptr<std::vector<std::unique_ptr<KeyAttestationPackageInfo>>> temp_vector;
+ auto rc = parcel->readParcelableVector(&temp_vector);
+ if (rc != NO_ERROR) return rc;
+ packageInfos_.reset(temp_vector.release());
+ return NO_ERROR;
+}
+
+} // namespace keymaster
+} // namespace security
+} // namespace android
diff --git a/keystore/KeyAttestationPackageInfo.cpp b/keystore/KeyAttestationPackageInfo.cpp
new file mode 100644
index 0000000..a84c246
--- /dev/null
+++ b/keystore/KeyAttestationPackageInfo.cpp
@@ -0,0 +1,49 @@
+/*
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "include/keystore/KeyAttestationPackageInfo.h"
+
+#include <binder/Parcel.h>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+status_t KeyAttestationPackageInfo::writeToParcel(Parcel* parcel) const {
+ auto rc = parcel->writeString16(packageName_);
+ if (rc != NO_ERROR) return rc;
+ rc = parcel->writeInt32(versionCode_);
+ if (rc != NO_ERROR) return rc;
+ return parcel->writeParcelableVector(signatures_);
+}
+
+status_t KeyAttestationPackageInfo::readFromParcel(const Parcel* parcel) {
+ auto rc = parcel->readString16(&packageName_);
+ if (rc != NO_ERROR) return rc;
+ rc = parcel->readInt32(&versionCode_);
+ if (rc != NO_ERROR) return rc;
+
+ std::unique_ptr<std::vector<std::unique_ptr<content::pm::Signature>>> temp_vector;
+ rc = parcel->readParcelableVector(&temp_vector);
+ if (rc != NO_ERROR) return rc;
+ signatures_.reset(temp_vector.release());
+ return NO_ERROR;
+}
+
+} // namespace keymaster
+} // namespace security
+} // namespace android
diff --git a/keystore/Signature.cpp b/keystore/Signature.cpp
new file mode 100644
index 0000000..1566df9
--- /dev/null
+++ b/keystore/Signature.cpp
@@ -0,0 +1,36 @@
+/*
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "include/keystore/Signature.h"
+
+#include <binder/Parcel.h>
+
+namespace android {
+namespace content {
+namespace pm {
+
+status_t Signature::writeToParcel(Parcel* parcel) const {
+ return parcel->writeByteVector(sig_data_);
+}
+
+status_t Signature::readFromParcel(const Parcel* parcel) {
+ return parcel->readByteVector(&sig_data_);
+}
+
+} // namespace pm
+} // namespace content
+} // namespace android
diff --git a/keystore/include/keystore/KeyAttestationApplicationId.h b/keystore/include/keystore/KeyAttestationApplicationId.h
new file mode 100644
index 0000000..a7ce210
--- /dev/null
+++ b/keystore/include/keystore/KeyAttestationApplicationId.h
@@ -0,0 +1,51 @@
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
+
+#include "KeyAttestationPackageInfo.h"
+#include "utils.h"
+#include <binder/Parcelable.h>
+#include <memory>
+#include <vector>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+class KeyAttestationApplicationId : public Parcelable {
+ public:
+ typedef SharedNullableIterator<const KeyAttestationPackageInfo, std::vector>
+ ConstKeyAttestationPackageInfoIterator;
+
+ status_t writeToParcel(Parcel*) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
+ ConstKeyAttestationPackageInfoIterator pinfos_begin() const {
+ return ConstKeyAttestationPackageInfoIterator(packageInfos_);
+ }
+ ConstKeyAttestationPackageInfoIterator pinfos_end() const {
+ return ConstKeyAttestationPackageInfoIterator();
+ }
+
+ private:
+ std::shared_ptr<std::vector<std::unique_ptr<KeyAttestationPackageInfo>>> packageInfos_;
+};
+
+} // namespace keymaster
+} // namespace security
+} // namsepace android
+
+#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
diff --git a/keystore/include/keystore/KeyAttestationPackageInfo.h b/keystore/include/keystore/KeyAttestationPackageInfo.h
new file mode 100644
index 0000000..b938e83
--- /dev/null
+++ b/keystore/include/keystore/KeyAttestationPackageInfo.h
@@ -0,0 +1,53 @@
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
+
+#include "Signature.h"
+#include "utils.h"
+#include <binder/Parcelable.h>
+#include <memory>
+#include <stdint.h>
+#include <vector>
+
+namespace android {
+namespace security {
+namespace keymaster {
+
+class KeyAttestationPackageInfo : public Parcelable {
+ public:
+ typedef SharedNullableIterator<const content::pm::Signature, std::vector>
+ ConstSignatureIterator;
+
+ status_t writeToParcel(Parcel*) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
+ const std::unique_ptr<String16>& package_name() const { return packageName_; }
+ int32_t version_code() const { return versionCode_; }
+
+ ConstSignatureIterator sigs_begin() const { return ConstSignatureIterator(signatures_); }
+ ConstSignatureIterator sigs_end() const { return ConstSignatureIterator(); }
+
+ private:
+ std::unique_ptr<String16> packageName_;
+ int32_t versionCode_;
+ std::shared_ptr<std::vector<std::unique_ptr<content::pm::Signature>>> signatures_;
+};
+
+} // namespace keymaster
+} // namespace security
+} // namespace android
+
+#endif // KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONPACKAGEINFO_H_
diff --git a/keystore/include/keystore/Signature.h b/keystore/include/keystore/Signature.h
new file mode 100644
index 0000000..59b77bf
--- /dev/null
+++ b/keystore/include/keystore/Signature.h
@@ -0,0 +1,43 @@
+// Copyright 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_SIGNATURE_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_SIGNATURE_H_
+
+#include <binder/Parcelable.h>
+#include <stdint.h>
+#include <vector>
+
+namespace android {
+namespace content {
+namespace pm {
+
+class Signature : public Parcelable {
+ public:
+ status_t writeToParcel(Parcel*) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
+ const std::vector<uint8_t>& data() const & { return sig_data_; }
+ std::vector<uint8_t>& data() & { return sig_data_; }
+ std::vector<uint8_t>&& data() && { return std::move(sig_data_); }
+
+ private:
+ std::vector<uint8_t> sig_data_;
+};
+
+} // namespace pm
+} // namespace content
+} // namespace android
+
+#endif // KEYSTORE_INCLUDE_KEYSTORE_SIGNATURE_H_
diff --git a/keystore/include/keystore/utils.h b/keystore/include/keystore/utils.h
new file mode 100644
index 0000000..f95ae71
--- /dev/null
+++ b/keystore/include/keystore/utils.h
@@ -0,0 +1,96 @@
+// TODO: Insert description here. (generated by jdanis)
+
+#ifndef KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_
+#define KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_
+
+#include <iterator>
+#include <memory>
+#include <vector>
+
+namespace android {
+namespace security {
+
+/*
+ * This iterator abstracts from a collection of the form
+ * std::shared_ptr<COLLECTION_TYPE<std::unique_ptr<T>>>
+ * such that it is defined both for nulled outer pointer and
+ * nulled entries. If shared_ptr(nullptr) is passed in, the iterator behaves
+ * like the end iterator yielding an empty collection. Nulled
+ * entries are skipped so that the iterator is always dereferencable unless
+ * it is equal to end.
+ * The default constructor always yields an iterator equal to end.
+ * The same iterator invalidation rules apply as they do for the iterators
+ * of the corresponding collection.
+ */
+template <typename T, template <typename...> class Coll = std::vector>
+class SharedNullableIterator {
+ public:
+ typedef Coll<std::unique_ptr<typename std::remove_const<T>::type>> CollectionType;
+ typedef std::shared_ptr<CollectionType> CollectionPtr;
+
+ SharedNullableIterator() {}
+ SharedNullableIterator(const std::shared_ptr<CollectionType>& coll) : coll_(coll) { init(); }
+ SharedNullableIterator(std::shared_ptr<CollectionType>&& coll) : coll_(coll) { init(); }
+
+ SharedNullableIterator(const SharedNullableIterator& other)
+ : coll_(other.coll_), cur_(other.cur_) {}
+ SharedNullableIterator(SharedNullableIterator&& other)
+ : coll_(std::move(other.coll_)), cur_(std::move(other.cur_)) {}
+
+ SharedNullableIterator& operator++() {
+ inc();
+ return *this;
+ }
+ SharedNullableIterator operator++(int) {
+ SharedNullableIterator retval(*this);
+ ++(*this);
+ return retval;
+ }
+ T& operator*() const { return **cur_; }
+
+ T* operator->() const { return &**cur_; }
+
+ bool operator==(const SharedNullableIterator& other) const {
+ return cur_ == other.cur_ || (is_end() && other.is_end());
+ }
+ bool operator!=(const SharedNullableIterator& other) const { return !(*this == other); }
+
+ SharedNullableIterator& operator=(const SharedNullableIterator&) = default;
+ SharedNullableIterator& operator=(SharedNullableIterator&&) = default;
+
+ private:
+ inline bool is_end() const { return !coll_ || cur_ == coll_->end(); }
+ inline void inc() {
+ if (!is_end()) {
+ do {
+ ++cur_;
+ // move forward to the next non null member or stay at end
+ } while (cur_ != coll_->end() && !(*cur_));
+ }
+ }
+ void init() {
+ if (coll_) {
+ // move forward to the first non null member
+ for (cur_ = coll_->begin(); cur_ != coll_->end() && !(*cur_); ++cur_) {
+ }
+ }
+ }
+
+ CollectionPtr coll_;
+ typename CollectionType::iterator cur_;
+};
+
+} // namespace security
+} // namespace android
+
+namespace std {
+template <typename T, template <typename...> class COLL>
+struct iterator_traits<android::security::SharedNullableIterator<T, COLL>> {
+ typedef T& reference;
+ typedef T value_type;
+ typedef T* pointer;
+ typedef forward_iterator_tag iterator_category;
+};
+}
+
+#endif // KEYSTORE_INCLUDE_KEYSTORE_UTILS_H_
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
index 329898b..bd7fd18 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -28,6 +28,7 @@
#include <hardware/keymaster_defs.h>
#include "defaults.h"
+#include "keystore_attestation_id.h"
#include "keystore_utils.h"
using keymaster::AuthorizationSet;
@@ -1129,8 +1130,7 @@
int32_t KeyStoreService::attestKey(const String16& name, const KeymasterArguments& params,
KeymasterCertificateChain* outChain) {
- if (!outChain)
- return KM_ERROR_OUTPUT_PARAMETER_NULL;
+ if (!outChain) return KM_ERROR_OUTPUT_PARAMETER_NULL;
if (!checkAllowedOperationParams(params.params)) {
return KM_ERROR_INVALID_ARGUMENT;
@@ -1149,15 +1149,33 @@
keymaster_key_blob_t key = {keyBlob.getValue(),
static_cast<size_t>(std::max(0, keyBlob.getLength()))};
auto* dev = mKeyStore->getDeviceForBlob(keyBlob);
- if (!dev->attest_key)
- return KM_ERROR_UNIMPLEMENTED;
+ if (!dev->attest_key) return KM_ERROR_UNIMPLEMENTED;
+
+ /* get the attestation application id
+ * the result is actually a pair: .second contains the error code and if this is NO_ERROR
+ * .first contains the requested attestation id
+ */
+ auto asn1_attestation_id_result = security::gather_attestation_application_id(callingUid);
+ if (asn1_attestation_id_result.second != android::NO_ERROR) {
+ ALOGE("failed to gather attestation_id");
+ return KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING;
+ }
+
+ /*
+ * Make a mutable copy of the params vector which to append the attestation id to.
+ * The copy is shallow, and the lifetime of the inner objects is the calling scope.
+ */
+ auto mutable_params = params.params;
+
+ mutable_params.push_back({.tag = KM_TAG_ATTESTATION_APPLICATION_ID,
+ .blob = {asn1_attestation_id_result.first.data(),
+ asn1_attestation_id_result.first.size()}});
const keymaster_key_param_set_t in_params = {
- const_cast<keymaster_key_param_t*>(params.params.data()), params.params.size()};
+ const_cast<keymaster_key_param_t*>(mutable_params.data()), mutable_params.size()};
outChain->chain = {nullptr, 0};
int32_t rc = dev->attest_key(dev, &key, &in_params, &outChain->chain);
- if (rc)
- return rc;
+ if (rc) return rc;
return ::NO_ERROR;
}
@@ -1306,6 +1324,8 @@
for (auto param : params) {
switch (param.tag) {
case KM_TAG_AUTH_TOKEN:
+ // fall through intended
+ case KM_TAG_ATTESTATION_APPLICATION_ID:
return false;
default:
break;
diff --git a/keystore/keystore_attestation_id.cpp b/keystore/keystore_attestation_id.cpp
new file mode 100644
index 0000000..36c692f
--- /dev/null
+++ b/keystore/keystore_attestation_id.cpp
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "keystore_attestation_id.h"
+
+#define LOG_TAG "keystore_att_id"
+
+#include <cutils/log.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <binder/PersistableBundle.h>
+
+#include <android/security/keymaster/BpKeyAttestationApplicationIdProvider.h>
+#include <android/security/keymaster/IKeyAttestationApplicationIdProvider.h>
+#include <keystore/KeyAttestationApplicationId.h>
+#include <keystore/KeyAttestationPackageInfo.h>
+#include <keystore/Signature.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/sha.h>
+
+#include <utils/String8.h>
+
+namespace android {
+
+namespace {
+
+static std::vector<uint8_t> signature2SHA256(const content::pm::Signature& sig) {
+ std::vector<uint8_t> digest_buffer(SHA256_DIGEST_LENGTH);
+ SHA256(sig.data().data(), sig.data().size(), digest_buffer.data());
+ return digest_buffer;
+}
+
+using ::android::security::keymaster::BpKeyAttestationApplicationIdProvider;
+
+class KeyAttestationApplicationIdProvider : public BpKeyAttestationApplicationIdProvider {
+ public:
+ KeyAttestationApplicationIdProvider();
+
+ static KeyAttestationApplicationIdProvider& get();
+
+ private:
+ android::sp<android::IServiceManager> service_manager_;
+};
+
+KeyAttestationApplicationIdProvider& KeyAttestationApplicationIdProvider::get() {
+ static KeyAttestationApplicationIdProvider mpm;
+ return mpm;
+}
+
+KeyAttestationApplicationIdProvider::KeyAttestationApplicationIdProvider()
+ : BpKeyAttestationApplicationIdProvider(
+ android::defaultServiceManager()->getService(String16("sec_key_att_app_id_provider"))) {}
+
+DECLARE_STACK_OF(ASN1_OCTET_STRING);
+
+typedef struct km_attestation_package_info {
+ ASN1_OCTET_STRING* package_name;
+ ASN1_INTEGER* version;
+ STACK_OF(ASN1_OCTET_STRING) * signature_digests;
+} KM_ATTESTATION_PACKAGE_INFO;
+
+ASN1_SEQUENCE(KM_ATTESTATION_PACKAGE_INFO) = {
+ ASN1_SIMPLE(KM_ATTESTATION_PACKAGE_INFO, package_name, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(KM_ATTESTATION_PACKAGE_INFO, version, ASN1_INTEGER),
+ ASN1_SET_OF(KM_ATTESTATION_PACKAGE_INFO, signature_digests, ASN1_OCTET_STRING),
+} ASN1_SEQUENCE_END(KM_ATTESTATION_PACKAGE_INFO);
+IMPLEMENT_ASN1_FUNCTIONS(KM_ATTESTATION_PACKAGE_INFO);
+
+DECLARE_STACK_OF(KM_ATTESTATION_PACKAGE_INFO);
+
+typedef struct km_attestation_application_id {
+ STACK_OF(KM_ATTESTATION_PACKAGE_INFO) * package_infos;
+} KM_ATTESTATION_APPLICATION_ID;
+
+ASN1_SEQUENCE(KM_ATTESTATION_APPLICATION_ID) = {
+ ASN1_SET_OF(KM_ATTESTATION_APPLICATION_ID, package_infos, KM_ATTESTATION_PACKAGE_INFO),
+} ASN1_SEQUENCE_END(KM_ATTESTATION_APPLICATION_ID);
+IMPLEMENT_ASN1_FUNCTIONS(KM_ATTESTATION_APPLICATION_ID);
+}
+
+} // namespace android
+
+namespace std {
+template <> struct default_delete<android::KM_ATTESTATION_PACKAGE_INFO> {
+ void operator()(android::KM_ATTESTATION_PACKAGE_INFO* p) {
+ android::KM_ATTESTATION_PACKAGE_INFO_free(p);
+ }
+};
+template <> struct default_delete<ASN1_OCTET_STRING> {
+ void operator()(ASN1_OCTET_STRING* p) { ASN1_OCTET_STRING_free(p); }
+};
+template <> struct default_delete<android::KM_ATTESTATION_APPLICATION_ID> {
+ void operator()(android::KM_ATTESTATION_APPLICATION_ID* p) {
+ android::KM_ATTESTATION_APPLICATION_ID_free(p);
+ }
+};
+} // namespace std
+
+namespace android {
+namespace security {
+namespace {
+
+using ::android::security::keymaster::KeyAttestationApplicationId;
+using ::android::security::keymaster::KeyAttestationPackageInfo;
+
+status_t build_attestation_package_info(
+ const std::string& pkg_name, const uint32_t pkg_version,
+ const std::vector<std::vector<uint8_t>>& signature_digests,
+ std::unique_ptr<KM_ATTESTATION_PACKAGE_INFO>* attestation_package_info_ptr) {
+
+ if (!attestation_package_info_ptr) return BAD_VALUE;
+ auto& attestation_package_info = *attestation_package_info_ptr;
+
+ attestation_package_info.reset(KM_ATTESTATION_PACKAGE_INFO_new());
+ if (!attestation_package_info.get()) return NO_MEMORY;
+
+ if (!ASN1_OCTET_STRING_set(attestation_package_info->package_name,
+ reinterpret_cast<const unsigned char*>(pkg_name.data()),
+ pkg_name.size())) {
+ return UNKNOWN_ERROR;
+ }
+
+ auto signature_digest_stack =
+ reinterpret_cast<_STACK*>(attestation_package_info->signature_digests);
+
+ assert(signature_digest_stack != nullptr);
+
+ for (auto si : signature_digests) {
+ auto asn1_item = std::unique_ptr<ASN1_OCTET_STRING>(ASN1_OCTET_STRING_new());
+ if (!asn1_item) return NO_MEMORY;
+ if (!ASN1_OCTET_STRING_set(asn1_item.get(), si.data(), si.size())) {
+ return UNKNOWN_ERROR;
+ }
+ if (!sk_push(signature_digest_stack, asn1_item.get())) {
+ return NO_MEMORY;
+ }
+ asn1_item.release(); // if push succeeded, the stack takes ownership
+ }
+
+ if (!ASN1_INTEGER_set(attestation_package_info->version, pkg_version)) {
+ return UNKNOWN_ERROR;
+ }
+
+ return NO_ERROR;
+}
+
+inline std::pair<std::vector<uint8_t>, status_t> wraperror(const status_t status) {
+ return std::pair<std::vector<uint8_t>, status_t>(std::vector<uint8_t>(), status);
+}
+
+std::pair<std::vector<uint8_t>, status_t>
+build_attestation_application_id(const KeyAttestationApplicationId& key_attestation_id) {
+ auto attestation_id =
+ std::unique_ptr<KM_ATTESTATION_APPLICATION_ID>(KM_ATTESTATION_APPLICATION_ID_new());
+
+ auto attestation_pinfo_stack = reinterpret_cast<_STACK*>(attestation_id->package_infos);
+
+ for (auto pinfo = key_attestation_id.pinfos_begin(); pinfo != key_attestation_id.pinfos_end();
+ ++pinfo) {
+ std::vector<std::vector<uint8_t>> signature_digests;
+
+ for (auto sig = pinfo->sigs_begin(); sig != pinfo->sigs_end(); ++sig) {
+ signature_digests.push_back(signature2SHA256(*sig));
+ }
+
+ if (!pinfo->package_name()) {
+ ALOGE("Key attestation package info lacks package name");
+ return wraperror(BAD_VALUE);
+ }
+ std::string package_name(String8(*pinfo->package_name()).string());
+ std::unique_ptr<KM_ATTESTATION_PACKAGE_INFO> attestation_package_info;
+ auto rc = build_attestation_package_info(package_name, pinfo->version_code(),
+ signature_digests, &attestation_package_info);
+ if (rc != NO_ERROR) {
+ ALOGE("Building DER attestation package info failed %d", rc);
+ return wraperror(rc);
+ }
+ if (!sk_push(attestation_pinfo_stack, attestation_package_info.get())) {
+ return wraperror(NO_MEMORY);
+ }
+ // if push succeeded, the stack takes ownership
+ attestation_package_info.release();
+ }
+
+ int len = i2d_KM_ATTESTATION_APPLICATION_ID(attestation_id.get(), nullptr);
+ if (len < 0) return wraperror(UNKNOWN_ERROR);
+ auto result = std::make_pair(std::vector<uint8_t>(len), NO_ERROR);
+ uint8_t* p = result.first.data();
+ len = i2d_KM_ATTESTATION_APPLICATION_ID(attestation_id.get(), &p);
+ if (len < 0) return wraperror(UNKNOWN_ERROR);
+
+ return result;
+}
+
+/* The following function are not used. They are mentioned here to silence
+ * warnings about them not being used.
+ */
+void unused_functions_silencer() __attribute__((unused));
+void unused_functions_silencer() {
+ i2d_KM_ATTESTATION_PACKAGE_INFO(nullptr, nullptr);
+ d2i_KM_ATTESTATION_APPLICATION_ID(nullptr, nullptr, 0);
+ d2i_KM_ATTESTATION_PACKAGE_INFO(nullptr, nullptr, 0);
+}
+
+} // namespace
+
+std::pair<std::vector<uint8_t>, status_t> gather_attestation_application_id(uid_t uid) {
+ auto& pm = KeyAttestationApplicationIdProvider::get();
+
+ /* Get the attestation application ID from package manager */
+ KeyAttestationApplicationId key_attestation_id;
+ auto status = pm.getKeyAttestationApplicationId(uid, &key_attestation_id);
+ if (!status.isOk()) {
+ ALOGE("package manager request for key attestation ID failed with: %s",
+ status.exceptionMessage().string());
+ return wraperror(FAILED_TRANSACTION);
+ }
+
+ /* DER encode the attestation application ID */
+ return build_attestation_application_id(key_attestation_id);
+}
+
+} // namespace security
+} // namespace android
diff --git a/keystore/keystore_attestation_id.h b/keystore/keystore_attestation_id.h
new file mode 100644
index 0000000..55d2c94
--- /dev/null
+++ b/keystore/keystore_attestation_id.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef KEYSTORE_KEYSTORE_ATTESTATION_ID_H_
+#define KEYSTORE_KEYSTORE_ATTESTATION_ID_H_
+
+#include <utils/Errors.h>
+#include <vector>
+
+namespace android {
+namespace security {
+
+/**
+ * Gathers the attestation id for the application determined by uid by querying the package manager
+ * As of this writing uids can be shared in android, which is why the asn.1 encoded result may
+ * contain more than one application attestation id.
+ *
+ * @returns .first the asn.1 encoded attestation application id if .second is NO_ERROR. If .second
+ * is not NO_ERROR the content of .first is undefined.
+ */
+std::pair<std::vector<uint8_t>, status_t> gather_attestation_application_id(uid_t uid);
+
+} // namespace security
+} // namespace android
+#endif // KEYSTORE_KEYSTORE_ATTESTATION_ID_H_