Merge "identity: fix access control checks in libeic."
diff --git a/audio/7.0/config/update_audio_policy_config.sh b/audio/7.0/config/update_audio_policy_config.sh
index 159fa35..c475dd1 100755
--- a/audio/7.0/config/update_audio_policy_config.sh
+++ b/audio/7.0/config/update_audio_policy_config.sh
@@ -41,7 +41,7 @@
set -euo pipefail
-if (echo "$@" | grep -qe -h); then
+if (echo "$@" | grep -qe "^-h"); then
echo "This script will update Audio Policy Manager config file"
echo "to the format required by V7.0 XSD schema from a previous"
echo "version."
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index bbc14ad..898c22d 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "audiohalservice"
+#include <signal.h>
#include <string>
#include <vector>
@@ -45,6 +46,8 @@
}
int main(int /* argc */, char* /* argv */ []) {
+ signal(SIGPIPE, SIG_IGN);
+
::android::ProcessState::initWithDriver("/dev/vndbinder");
// start a threadpool for vndbinder interactions
::android::ProcessState::self()->startThreadPool();
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp
index 548285a..9be9ea7 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp
@@ -31,6 +31,14 @@
GeneratorHub::GeneratorHub(const OnHalEvent& onHalEvent)
: mOnHalEvent(onHalEvent), mThread(&GeneratorHub::run, this) {}
+GeneratorHub::~GeneratorHub() {
+ mShuttingDownFlag.store(true);
+ mCond.notify_all();
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
void GeneratorHub::registerGenerator(int32_t cookie, FakeValueGeneratorPtr generator) {
{
std::lock_guard<std::mutex> g(mLock);
@@ -58,15 +66,18 @@
}
void GeneratorHub::run() {
- while (true) {
+ while (!mShuttingDownFlag.load()) {
std::unique_lock<std::mutex> g(mLock);
// Pop events whose generator does not exist (may be already unregistered)
while (!mEventQueue.empty()
&& mGenerators.find(mEventQueue.top().cookie) == mGenerators.end()) {
mEventQueue.pop();
}
- // Wait until event queue is not empty
- mCond.wait(g, [this] { return !mEventQueue.empty(); });
+ // Wait until event queue is not empty or shutting down flag is set
+ mCond.wait(g, [this] { return !mEventQueue.empty() || mShuttingDownFlag.load(); });
+ if (mShuttingDownFlag.load()) {
+ break;
+ }
const VhalEvent& curEvent = mEventQueue.top();
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h
index dcf6a4f..b25dbf1 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h
@@ -58,7 +58,7 @@
public:
GeneratorHub(const OnHalEvent& onHalEvent);
- ~GeneratorHub() = default;
+ ~GeneratorHub();
/**
* Register a new generator. The generator will be discarded if it could not produce next event.
@@ -84,6 +84,7 @@
mutable std::mutex mLock;
std::condition_variable mCond;
std::thread mThread;
+ std::atomic<bool> mShuttingDownFlag{false};
};
} // namespace impl
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
index 77f7c3b..c250ef1 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
@@ -61,8 +61,6 @@
}
bool BluetoothAudioSession_2_1::IsSessionReady() {
- LOG(WARNING) << __func__ << " session_type: " << toString(session_type_2_1_);
-
if (session_type_2_1_ !=
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
return audio_session->IsSessionReady();
diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp
index 27e74f1..16fb85c 100644
--- a/camera/common/1.0/default/CameraModule.cpp
+++ b/camera/common/1.0/default/CameraModule.cpp
@@ -549,7 +549,6 @@
}
}
}
- free_camera_metadata(metadata);
}
mCameraInfoMap.removeItem(cameraId);
diff --git a/drm/1.0/default/Android.bp b/drm/1.0/default/Android.bp
index af1c076..a5cba5c 100644
--- a/drm/1.0/default/Android.bp
+++ b/drm/1.0/default/Android.bp
@@ -32,6 +32,7 @@
"-Werror",
"-Wextra",
"-Wall",
+ "-Wthread-safety",
],
shared_libs: [
"liblog",
@@ -42,7 +43,7 @@
export_header_lib_headers: [
"libutils_headers",
],
- export_include_dirs : ["include"]
+ export_include_dirs: ["include"],
}
soong_config_module_type {
diff --git a/drm/1.0/default/CryptoPlugin.cpp b/drm/1.0/default/CryptoPlugin.cpp
index e6d4e84..8dea7e9 100644
--- a/drm/1.0/default/CryptoPlugin.cpp
+++ b/drm/1.0/default/CryptoPlugin.cpp
@@ -53,6 +53,8 @@
uint32_t bufferId) {
sp<IMemory> hidlMemory = mapMemory(base);
+ std::lock_guard<std::mutex> shared_buffer_lock(mSharedBufferLock);
+
// allow mapMemory to return nullptr
mSharedBufferMap[bufferId] = hidlMemory;
return Void();
@@ -65,7 +67,7 @@
const SharedBuffer& source, uint64_t offset,
const DestinationBuffer& destination,
decrypt_cb _hidl_cb) {
-
+ std::unique_lock<std::mutex> shared_buffer_lock(mSharedBufferLock);
if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) {
_hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source decrypt buffer base not set");
return Void();
@@ -79,7 +81,7 @@
}
}
- android::CryptoPlugin::Mode legacyMode;
+ android::CryptoPlugin::Mode legacyMode = android::CryptoPlugin::kMode_Unencrypted;
switch(mode) {
case Mode::UNENCRYPTED:
legacyMode = android::CryptoPlugin::kMode_Unencrypted;
@@ -146,7 +148,10 @@
return Void();
}
- if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
+ size_t totalSize = 0;
+ if (__builtin_add_overflow(destBuffer.offset, destBuffer.size, &totalSize) ||
+ totalSize > destBase->getSize()) {
+ android_errorWriteLog(0x534e4554, "176496353");
_hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
return Void();
}
@@ -157,7 +162,7 @@
}
base = static_cast<uint8_t *>(static_cast<void *>(destBase->getPointer()));
- destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
+ destPtr = static_cast<void*>(base + destination.nonsecureMemory.offset);
} else if (destination.type == BufferType::NATIVE_HANDLE) {
if (!secure) {
_hidl_cb(Status::BAD_VALUE, 0, "native handle destination must be secure");
@@ -170,6 +175,10 @@
_hidl_cb(Status::BAD_VALUE, 0, "invalid destination type");
return Void();
}
+
+ // release mSharedBufferLock
+ shared_buffer_lock.unlock();
+
ssize_t result = mLegacyPlugin->decrypt(secure, keyId.data(), iv.data(),
legacyMode, legacyPattern, srcPtr, legacySubSamples.get(),
subSamples.size(), destPtr, &detailMessage);
diff --git a/drm/1.0/default/CryptoPlugin.h b/drm/1.0/default/CryptoPlugin.h
index 11cc2aa..0d091fa 100644
--- a/drm/1.0/default/CryptoPlugin.h
+++ b/drm/1.0/default/CryptoPlugin.h
@@ -17,11 +17,14 @@
#ifndef ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
#define ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
-#include <android/hidl/memory/1.0/IMemory.h>
+#include <android-base/thread_annotations.h>
#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <android/hidl/memory/1.0/IMemory.h>
#include <hidl/Status.h>
#include <media/hardware/CryptoAPI.h>
+#include <mutex>
+
namespace android {
namespace hardware {
namespace drm {
@@ -60,19 +63,21 @@
Return<void> setSharedBufferBase(const ::android::hardware::hidl_memory& base,
uint32_t bufferId) override;
- Return<void> decrypt(bool secure, const hidl_array<uint8_t, 16>& keyId,
- const hidl_array<uint8_t, 16>& iv, Mode mode, const Pattern& pattern,
- const hidl_vec<SubSample>& subSamples, const SharedBuffer& source,
- uint64_t offset, const DestinationBuffer& destination,
- decrypt_cb _hidl_cb) override;
+ Return<void> decrypt(
+ bool secure, const hidl_array<uint8_t, 16>& keyId, const hidl_array<uint8_t, 16>& iv,
+ Mode mode, const Pattern& pattern, const hidl_vec<SubSample>& subSamples,
+ const SharedBuffer& source, uint64_t offset, const DestinationBuffer& destination,
+ decrypt_cb _hidl_cb) override NO_THREAD_SAFETY_ANALYSIS; // use unique_lock
-private:
+ private:
android::CryptoPlugin *mLegacyPlugin;
- std::map<uint32_t, sp<IMemory> > mSharedBufferMap;
+ std::map<uint32_t, sp<IMemory>> mSharedBufferMap GUARDED_BY(mSharedBufferLock);
CryptoPlugin() = delete;
CryptoPlugin(const CryptoPlugin &) = delete;
void operator=(const CryptoPlugin &) = delete;
+
+ std::mutex mSharedBufferLock;
};
} // namespace implementation
diff --git a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
index 7d32ced..618624e 100644
--- a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
+++ b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
@@ -236,6 +236,10 @@
generatePassword(password, 0);
enrollNewPassword(password, enrollRsp, true);
verifyPassword(password, enrollRsp.data, 1, verifyRsp, true);
+
+ ALOGI("Testing unenrolled password doesn't verify");
+ generatePassword(password, 1);
+ verifyPassword(password, enrollRsp.data, 1, verifyRsp, false);
ALOGI("Testing Enroll+Verify done");
}
diff --git a/keymaster/4.0/support/attestation_record.cpp b/keymaster/4.0/support/attestation_record.cpp
index bc294bd..342b3e2 100644
--- a/keymaster/4.0/support/attestation_record.cpp
+++ b/keymaster/4.0/support/attestation_record.cpp
@@ -71,6 +71,7 @@
ASN1_INTEGER_SET* padding;
ASN1_INTEGER* ec_curve;
ASN1_INTEGER* rsa_public_exponent;
+ ASN1_NULL* rollback_resistance;
ASN1_INTEGER* active_date_time;
ASN1_INTEGER* origination_expire_date_time;
ASN1_INTEGER* usage_expire_date_time;
@@ -78,56 +79,84 @@
ASN1_INTEGER* user_auth_type;
ASN1_INTEGER* auth_timeout;
ASN1_NULL* allow_while_on_body;
+ ASN1_NULL* trusted_user_presence_required;
+ ASN1_NULL* trusted_confirmation_required;
+ ASN1_NULL* unlocked_device_required;
ASN1_NULL* all_applications;
ASN1_OCTET_STRING* application_id;
ASN1_INTEGER* creation_date_time;
ASN1_INTEGER* origin;
- ASN1_NULL* rollback_resistance;
KM_ROOT_OF_TRUST* root_of_trust;
ASN1_INTEGER* os_version;
ASN1_INTEGER* os_patchlevel;
ASN1_OCTET_STRING* attestation_application_id;
- ASN1_NULL* trusted_user_presence_required;
- ASN1_NULL* trusted_confirmation_required;
- ASN1_NULL* unlocked_device_required;
+ ASN1_OCTET_STRING* attestation_id_brand;
+ ASN1_OCTET_STRING* attestation_id_device;
+ ASN1_OCTET_STRING* attestation_id_product;
+ ASN1_OCTET_STRING* attestation_id_serial;
+ ASN1_OCTET_STRING* attestation_id_imei;
+ ASN1_OCTET_STRING* attestation_id_meid;
+ ASN1_OCTET_STRING* attestation_id_manufacturer;
+ ASN1_OCTET_STRING* attestation_id_model;
ASN1_INTEGER* vendor_patchlevel;
ASN1_INTEGER* boot_patchlevel;
} KM_AUTH_LIST;
ASN1_SEQUENCE(KM_AUTH_LIST) = {
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.maskedTag()),
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.maskedTag()),
- ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
- TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL, TAG_ROLLBACK_RESISTANCE.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
- TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
- TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL, TAG_ALLOW_WHILE_ON_BODY.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, trusted_user_presence_required, ASN1_NULL,
- TAG_TRUSTED_USER_PRESENCE_REQUIRED.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, trusted_confirmation_required, ASN1_NULL,
- TAG_TRUSTED_CONFIRMATION_REQUIRED.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, unlocked_device_required, ASN1_NULL,
- TAG_UNLOCKED_DEVICE_REQUIRED.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER, TAG_CREATION_DATETIME.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER, TAG_VENDOR_PATCHLEVEL.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
- TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.maskedTag()),
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.maskedTag()),
+ ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
+ TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
+ TAG_ROLLBACK_RESISTANCE.maskedTag()),
+
+ ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
+ TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
+ TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL,
+ TAG_ALLOW_WHILE_ON_BODY.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, trusted_user_presence_required, ASN1_NULL,
+ TAG_TRUSTED_USER_PRESENCE_REQUIRED.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, trusted_confirmation_required, ASN1_NULL,
+ TAG_TRUSTED_CONFIRMATION_REQUIRED.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, unlocked_device_required, ASN1_NULL,
+ TAG_UNLOCKED_DEVICE_REQUIRED.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER,
+ TAG_CREATION_DATETIME.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_brand, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_BRAND.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_device, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_DEVICE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_product, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_PRODUCT.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_serial, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_SERIAL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_imei, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_IMEI.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_meid, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MEID.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_manufacturer, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MANUFACTURER.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_model, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MODEL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER,
+ TAG_VENDOR_PATCHLEVEL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
} ASN1_SEQUENCE_END(KM_AUTH_LIST);
IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
@@ -259,6 +288,14 @@
copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
+ copyAuthTag(record->attestation_id_brand, TAG_ATTESTATION_ID_BRAND, auth_list);
+ copyAuthTag(record->attestation_id_device, TAG_ATTESTATION_ID_DEVICE, auth_list);
+ copyAuthTag(record->attestation_id_product, TAG_ATTESTATION_ID_PRODUCT, auth_list);
+ copyAuthTag(record->attestation_id_serial, TAG_ATTESTATION_ID_SERIAL, auth_list);
+ copyAuthTag(record->attestation_id_imei, TAG_ATTESTATION_ID_IMEI, auth_list);
+ copyAuthTag(record->attestation_id_meid, TAG_ATTESTATION_ID_MEID, auth_list);
+ copyAuthTag(record->attestation_id_manufacturer, TAG_ATTESTATION_ID_MANUFACTURER, auth_list);
+ copyAuthTag(record->attestation_id_model, TAG_ATTESTATION_ID_MODEL, auth_list);
copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
copyAuthTag(record->trusted_user_presence_required, TAG_TRUSTED_USER_PRESENCE_REQUIRED,
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 9e37ed0..01c502c 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -96,6 +96,18 @@
return count > 0;
}
+// If the given property is available, add it to the tag set under the given tag ID.
+template <Tag tag>
+void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
+ const char* prop) {
+ char value[PROPERTY_VALUE_MAX];
+ int len = property_get(prop, value, /* default = */ "");
+ if (len > 0) {
+ tags->Authorization(ttag, reinterpret_cast<const uint8_t*>(value),
+ static_cast<size_t>(len));
+ }
+}
+
constexpr char hex_value[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
@@ -4409,6 +4421,95 @@
}
/*
+ * AttestationTest.EcAttestationID
+ *
+ * Verifies that attesting to EC keys with correct attestation ID fields works and generates the
+ * expected output.
+ */
+TEST_P(AttestationTest, EcAttestationID) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)));
+
+ // Collection of valid attestation ID tags.
+ auto attestation_id_tags = AuthorizationSetBuilder();
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
+ "ro.product.manufacturer");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
+
+ for (const KeyParameter& tag : attestation_id_tags) {
+ AuthorizationSetBuilder builder =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
+ .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo"));
+ // Include one of the (valid) attestation ID tags.
+ builder.push_back(tag);
+ hidl_vec<hidl_vec<uint8_t>> cert_chain;
+ auto result = AttestKey(builder, &cert_chain);
+ if (result == ErrorCode::CANNOT_ATTEST_IDS) {
+ continue;
+ }
+
+ ASSERT_EQ(ErrorCode::OK, result);
+ EXPECT_GE(cert_chain.size(), 2U);
+
+ std::vector<KeyParameter> expected_hw_enforced = key_characteristics_.hardwareEnforced;
+ expected_hw_enforced.push_back(tag);
+
+ EXPECT_TRUE(verify_attestation_record(
+ "challenge", "foo", key_characteristics_.softwareEnforced,
+ hidl_vec<KeyParameter>(expected_hw_enforced), SecLevel(), cert_chain[0]));
+ }
+}
+
+/*
+ * AttestationTest.EcAttestationMismatchID
+ *
+ * Verifies that attesting to EC keys with incorrect attestation ID fields fails.
+ */
+TEST_P(AttestationTest, EcAttestationMismatchID) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)));
+
+ // Collection of invalid attestation ID tags.
+ std::string invalid = "completely-invalid";
+ auto invalid_tags =
+ AuthorizationSetBuilder()
+ .Authorization(V4_0::TAG_ATTESTATION_ID_BRAND, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_DEVICE, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_PRODUCT, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_SERIAL, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_IMEI, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_MEID, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_MANUFACTURER, invalid.data(),
+ invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_MODEL, invalid.data(), invalid.size());
+
+ for (const KeyParameter& invalid_tag : invalid_tags) {
+ AuthorizationSetBuilder builder =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
+ .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo"));
+ // Include one of the invalid attestation ID tags.
+ builder.push_back(invalid_tag);
+ hidl_vec<hidl_vec<uint8_t>> cert_chain;
+ auto result = AttestKey(builder, &cert_chain);
+
+ EXPECT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG)
+ << "result: " << static_cast<int32_t>(result);
+ }
+}
+
+/*
* AttestationTest.EcAttestationRequiresAttestationAppId
*
* Verifies that attesting to EC keys requires app ID
diff --git a/keymaster/4.1/support/attestation_record.cpp b/keymaster/4.1/support/attestation_record.cpp
index 207a7e8..15230d5 100644
--- a/keymaster/4.1/support/attestation_record.cpp
+++ b/keymaster/4.1/support/attestation_record.cpp
@@ -79,6 +79,8 @@
ASN1_INTEGER_SET* padding;
ASN1_INTEGER* ec_curve;
ASN1_INTEGER* rsa_public_exponent;
+ ASN1_NULL* rollback_resistance;
+ ASN1_NULL* early_boot_only;
ASN1_INTEGER* active_date_time;
ASN1_INTEGER* origination_expire_date_time;
ASN1_INTEGER* usage_expire_date_time;
@@ -86,21 +88,27 @@
ASN1_INTEGER* user_auth_type;
ASN1_INTEGER* auth_timeout;
ASN1_NULL* allow_while_on_body;
+ ASN1_NULL* trusted_user_presence_required;
+ ASN1_NULL* trusted_confirmation_required;
+ ASN1_NULL* unlocked_device_required;
ASN1_NULL* all_applications;
ASN1_OCTET_STRING* application_id;
ASN1_INTEGER* creation_date_time;
ASN1_INTEGER* origin;
- ASN1_NULL* rollback_resistance;
KM_ROOT_OF_TRUST* root_of_trust;
ASN1_INTEGER* os_version;
ASN1_INTEGER* os_patchlevel;
ASN1_OCTET_STRING* attestation_application_id;
- ASN1_NULL* trusted_user_presence_required;
- ASN1_NULL* trusted_confirmation_required;
- ASN1_NULL* unlocked_device_required;
+ ASN1_OCTET_STRING* attestation_id_brand;
+ ASN1_OCTET_STRING* attestation_id_device;
+ ASN1_OCTET_STRING* attestation_id_product;
+ ASN1_OCTET_STRING* attestation_id_serial;
+ ASN1_OCTET_STRING* attestation_id_imei;
+ ASN1_OCTET_STRING* attestation_id_meid;
+ ASN1_OCTET_STRING* attestation_id_manufacturer;
+ ASN1_OCTET_STRING* attestation_id_model;
ASN1_INTEGER* vendor_patchlevel;
ASN1_INTEGER* boot_patchlevel;
- ASN1_NULL* early_boot_only;
ASN1_NULL* device_unique_attestation;
ASN1_NULL* identity_credential_key;
} KM_AUTH_LIST;
@@ -116,6 +124,7 @@
TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
TAG_ROLLBACK_RESISTANCE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
@@ -138,12 +147,27 @@
ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_brand, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_BRAND.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_device, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_DEVICE.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_product, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_PRODUCT.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_serial, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_SERIAL.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_imei, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_IMEI.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_meid, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MEID.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_manufacturer, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MANUFACTURER.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_model, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_MODEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER,
TAG_VENDOR_PATCHLEVEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
- TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, device_unique_attestation, ASN1_NULL,
TAG_DEVICE_UNIQUE_ATTESTATION.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential_key, ASN1_NULL,
@@ -279,6 +303,14 @@
copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
+ copyAuthTag(record->attestation_id_brand, TAG_ATTESTATION_ID_BRAND, auth_list);
+ copyAuthTag(record->attestation_id_device, TAG_ATTESTATION_ID_DEVICE, auth_list);
+ copyAuthTag(record->attestation_id_product, TAG_ATTESTATION_ID_PRODUCT, auth_list);
+ copyAuthTag(record->attestation_id_serial, TAG_ATTESTATION_ID_SERIAL, auth_list);
+ copyAuthTag(record->attestation_id_imei, TAG_ATTESTATION_ID_IMEI, auth_list);
+ copyAuthTag(record->attestation_id_meid, TAG_ATTESTATION_ID_MEID, auth_list);
+ copyAuthTag(record->attestation_id_manufacturer, TAG_ATTESTATION_ID_MANUFACTURER, auth_list);
+ copyAuthTag(record->attestation_id_model, TAG_ATTESTATION_ID_MODEL, auth_list);
copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
copyAuthTag(record->trusted_user_presence_required, TAG_TRUSTED_USER_PRESENCE_REQUIRED,
diff --git a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
index 40eb142..e8db56a 100644
--- a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
@@ -53,6 +53,14 @@
using V4_0::TAG_ASSOCIATED_DATA;
using V4_0::TAG_ATTESTATION_APPLICATION_ID;
using V4_0::TAG_ATTESTATION_CHALLENGE;
+using V4_0::TAG_ATTESTATION_ID_BRAND;
+using V4_0::TAG_ATTESTATION_ID_DEVICE;
+using V4_0::TAG_ATTESTATION_ID_IMEI;
+using V4_0::TAG_ATTESTATION_ID_MANUFACTURER;
+using V4_0::TAG_ATTESTATION_ID_MEID;
+using V4_0::TAG_ATTESTATION_ID_MODEL;
+using V4_0::TAG_ATTESTATION_ID_PRODUCT;
+using V4_0::TAG_ATTESTATION_ID_SERIAL;
using V4_0::TAG_AUTH_TIMEOUT;
using V4_0::TAG_BLOB_USAGE_REQUIREMENTS;
using V4_0::TAG_BLOCK_MODE;
diff --git a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
index 0639da8..4a57f44 100644
--- a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "keymaster_hidl_hal_test"
#include <cutils/log.h>
+#include <vector>
#include "Keymaster4_1HidlTest.h"
@@ -26,6 +27,8 @@
#include <keymasterV4_1/attestation_record.h>
#include <keymasterV4_1/authorization_set.h>
+using android::hardware::keymaster::V4_0::test::add_tag_from_prop;
+
// Not to dump the attestation by default. Can enable by specify the parameter
// "--dump_attestations" on lunching VTS
static bool dumpAttestations = false;
@@ -172,10 +175,42 @@
attestation.software_enforced.Sort();
attestation.hardware_enforced.Sort();
- EXPECT_EQ(filter_tags(expected_sw_enforced), filter_tags(attestation.software_enforced))
- << DIFFERENCE(expected_sw_enforced, attestation.software_enforced);
- EXPECT_EQ(filter_tags(expected_hw_enforced), filter_tags(attestation.hardware_enforced))
- << DIFFERENCE(expected_hw_enforced, attestation.hardware_enforced);
+ expected_sw_enforced = filter_tags(expected_sw_enforced);
+ expected_hw_enforced = filter_tags(expected_hw_enforced);
+ AuthorizationSet attestation_sw_enforced = filter_tags(attestation.software_enforced);
+ AuthorizationSet attestation_hw_enforced = filter_tags(attestation.hardware_enforced);
+
+ EXPECT_EQ(expected_sw_enforced, attestation_sw_enforced)
+ << DIFFERENCE(expected_sw_enforced, attestation_sw_enforced);
+ EXPECT_EQ(expected_hw_enforced, attestation_hw_enforced)
+ << DIFFERENCE(expected_hw_enforced, attestation_hw_enforced);
+}
+
+X509_Ptr parse_cert_blob(const std::vector<uint8_t>& blob) {
+ const uint8_t* p = blob.data();
+ return X509_Ptr(d2i_X509(nullptr /* allocate new */, &p, blob.size()));
+}
+
+bool check_certificate_chain_signatures(const hidl_vec<hidl_vec<uint8_t>>& cert_chain) {
+ // TODO: Check that root is self-signed once b/187803288 is resolved.
+ for (size_t i = 0; i < cert_chain.size() - 1; ++i) {
+ X509_Ptr key_cert(parse_cert_blob(cert_chain[i]));
+ X509_Ptr signing_cert(parse_cert_blob(cert_chain[i + 1]));
+
+ if (!key_cert.get() || !signing_cert.get()) {
+ return false;
+ }
+
+ EVP_PKEY_Ptr signing_pubkey(X509_get_pubkey(signing_cert.get()));
+ if (!signing_pubkey.get()) {
+ return false;
+ }
+
+ if (!X509_verify(key_cert.get(), signing_pubkey.get())) {
+ return false;
+ }
+ }
+ return true;
}
} // namespace
@@ -243,6 +278,7 @@
EXPECT_EQ(ErrorCode::OK, result);
EXPECT_EQ(2U, cert_chain.size());
+ EXPECT_TRUE(check_certificate_chain_signatures(cert_chain));
if (dumpAttestations) {
for (auto cert_ : cert_chain) dumpContent(bin2hex(cert_));
}
@@ -289,6 +325,7 @@
EXPECT_EQ(ErrorCode::OK, result);
EXPECT_EQ(2U, cert_chain.size());
+ EXPECT_TRUE(check_certificate_chain_signatures(cert_chain));
if (dumpAttestations) {
for (auto cert_ : cert_chain) dumpContent(bin2hex(cert_));
}
@@ -312,6 +349,106 @@
SecLevel());
}
+TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationID) {
+ if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::OK, convert(GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID))));
+
+ // Collection of valid attestation ID tags.
+ auto attestation_id_tags = AuthorizationSetBuilder();
+ add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
+ add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
+ add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
+ add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+ add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_MANUFACTURER,
+ "ro.product.manufacturer");
+ add_tag_from_prop(&attestation_id_tags, V4_0::TAG_ATTESTATION_ID_MODEL, "ro.product.model");
+
+ for (const KeyParameter& tag : attestation_id_tags) {
+ hidl_vec<hidl_vec<uint8_t>> cert_chain;
+ HidlBuf challenge("challenge");
+ HidlBuf app_id("foo");
+ AuthorizationSetBuilder builder =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+ .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
+ .Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id);
+ builder.push_back(tag);
+ ErrorCode result = convert(AttestKey(builder, &cert_chain));
+
+ // It is optional for Strong box to support DeviceUniqueAttestation.
+ if (result == ErrorCode::CANNOT_ATTEST_IDS) return;
+
+ ASSERT_EQ(ErrorCode::OK, result);
+ EXPECT_EQ(2U, cert_chain.size());
+ if (dumpAttestations) {
+ for (auto cert_ : cert_chain) dumpContent(bin2hex(cert_));
+ }
+ auto [err, attestation] = parse_attestation_record(cert_chain[0]);
+ ASSERT_EQ(ErrorCode::OK, err);
+
+ AuthorizationSetBuilder hw_enforced =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
+ .Authorization(TAG_OS_VERSION, os_version())
+ .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+ hw_enforced.push_back(tag);
+ check_attestation_record(
+ attestation, challenge,
+ /* sw_enforced */
+ AuthorizationSetBuilder().Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id),
+ hw_enforced, SecLevel());
+ }
+}
+
+TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationMismatchID) {
+ if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::OK, convert(GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID))));
+
+ // Collection of invalid attestation ID tags.
+ std::string invalid = "completely-invalid";
+ auto attestation_id_tags =
+ AuthorizationSetBuilder()
+ .Authorization(V4_0::TAG_ATTESTATION_ID_BRAND, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_DEVICE, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_PRODUCT, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_SERIAL, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_IMEI, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_MEID, invalid.data(), invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_MANUFACTURER, invalid.data(),
+ invalid.size())
+ .Authorization(V4_0::TAG_ATTESTATION_ID_MODEL, invalid.data(), invalid.size());
+
+ for (const KeyParameter& invalid_tag : attestation_id_tags) {
+ hidl_vec<hidl_vec<uint8_t>> cert_chain;
+ HidlBuf challenge("challenge");
+ HidlBuf app_id("foo");
+ AuthorizationSetBuilder builder =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+ .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
+ .Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id);
+ builder.push_back(invalid_tag);
+ ErrorCode result = convert(AttestKey(builder, &cert_chain));
+
+ EXPECT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG)
+ << "result: " << static_cast<int32_t>(result);
+ }
+}
+
INSTANTIATE_KEYMASTER_4_1_HIDL_TEST(DeviceUniqueAttestationTest);
} // namespace test
diff --git a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
index f8c1fad..670ccfb 100644
--- a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
+++ b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
@@ -18,6 +18,8 @@
#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
+#include <android-base/properties.h>
+
#include <KeymasterHidlTest.h>
#include <keymasterV4_1/authorization_set.h>
@@ -159,3 +161,17 @@
android::hardware::PrintInstanceNameToString)
} // namespace android::hardware::keymaster::V4_1::test
+
+namespace android::hardware::keymaster::V4_0::test {
+
+// If the given property is available, add it to the tag set under the given tag ID.
+template <Tag tag>
+void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
+ const char* prop) {
+ std::string prop_value = ::android::base::GetProperty(prop, /* default= */ "");
+ if (!prop_value.empty()) {
+ tags->Authorization(ttag, prop_value.data(), prop_value.size());
+ }
+}
+
+} // namespace android::hardware::keymaster::V4_0::test
diff --git a/neuralnetworks/1.3/utils/src/Conversions.cpp b/neuralnetworks/1.3/utils/src/Conversions.cpp
index e8a4f55..11225cf 100644
--- a/neuralnetworks/1.3/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.3/utils/src/Conversions.cpp
@@ -239,7 +239,7 @@
using Discriminator = hal::V1_3::Request::MemoryPool::hidl_discriminator;
switch (memoryPool.getDiscriminator()) {
case Discriminator::hidlMemory:
- return hal::utils::createSharedMemoryFromHidlMemory(memoryPool.hidlMemory());
+ return unvalidatedConvert(memoryPool.hidlMemory());
case Discriminator::token:
return static_cast<Request::MemoryDomainToken>(memoryPool.token());
}
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h
index 5eab9ff..78433a7 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h
@@ -95,9 +95,7 @@
GeneralResult<Extension> unvalidatedConvert(const aidl_hal::Extension& extension);
GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
const aidl_hal::ExtensionOperandTypeInformation& operandTypeInformation);
-GeneralResult<SharedHandle> unvalidatedConvert(
- const ::aidl::android::hardware::common::NativeHandle& handle);
-GeneralResult<SyncFence> unvalidatedConvert(const ndk::ScopedFileDescriptor& syncFence);
+GeneralResult<SharedHandle> unvalidatedConvert(const ndk::ScopedFileDescriptor& handle);
GeneralResult<std::vector<Operation>> unvalidatedConvert(
const std::vector<aidl_hal::Operation>& operations);
@@ -113,7 +111,7 @@
GeneralResult<Priority> convert(const aidl_hal::Priority& priority);
GeneralResult<Request> convert(const aidl_hal::Request& request);
GeneralResult<Timing> convert(const aidl_hal::Timing& timing);
-GeneralResult<SyncFence> convert(const ndk::ScopedFileDescriptor& syncFence);
+GeneralResult<SharedHandle> convert(const ndk::ScopedFileDescriptor& handle);
GeneralResult<std::vector<Extension>> convert(const std::vector<aidl_hal::Extension>& extension);
GeneralResult<std::vector<SharedMemory>> convert(const std::vector<aidl_hal::Memory>& memories);
@@ -160,9 +158,7 @@
nn::GeneralResult<int64_t> unvalidatedConvert(const nn::OptionalDuration& optionalDuration);
nn::GeneralResult<int64_t> unvalidatedConvert(const nn::OptionalTimePoint& optionalTimePoint);
nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvert(const nn::SyncFence& syncFence);
-nn::GeneralResult<common::NativeHandle> unvalidatedConvert(const nn::SharedHandle& sharedHandle);
-nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvertCache(
- const nn::SharedHandle& handle);
+nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvert(const nn::SharedHandle& handle);
nn::GeneralResult<std::vector<uint8_t>> convert(const nn::CacheToken& cacheToken);
nn::GeneralResult<BufferDesc> convert(const nn::BufferDesc& bufferDesc);
diff --git a/neuralnetworks/aidl/utils/src/Conversions.cpp b/neuralnetworks/aidl/utils/src/Conversions.cpp
index 4b263ee..0517730 100644
--- a/neuralnetworks/aidl/utils/src/Conversions.cpp
+++ b/neuralnetworks/aidl/utils/src/Conversions.cpp
@@ -108,17 +108,6 @@
return canonical;
}
-GeneralResult<Handle> unvalidatedConvertHelper(const NativeHandle& aidlNativeHandle) {
- std::vector<base::unique_fd> fds;
- fds.reserve(aidlNativeHandle.fds.size());
- for (const auto& fd : aidlNativeHandle.fds) {
- auto duplicatedFd = NN_TRY(dupFd(fd.get()));
- fds.emplace_back(duplicatedFd.release());
- }
-
- return Handle{.fds = std::move(fds), .ints = aidlNativeHandle.ints};
-}
-
struct NativeHandleDeleter {
void operator()(native_handle_t* handle) const {
if (handle) {
@@ -498,18 +487,14 @@
return static_cast<ExecutionPreference>(executionPreference);
}
-GeneralResult<SharedHandle> unvalidatedConvert(const NativeHandle& aidlNativeHandle) {
- return std::make_shared<const Handle>(NN_TRY(unvalidatedConvertHelper(aidlNativeHandle)));
-}
-
GeneralResult<std::vector<Operation>> unvalidatedConvert(
const std::vector<aidl_hal::Operation>& operations) {
return unvalidatedConvertVec(operations);
}
-GeneralResult<SyncFence> unvalidatedConvert(const ndk::ScopedFileDescriptor& syncFence) {
- auto duplicatedFd = NN_TRY(dupFd(syncFence.get()));
- return SyncFence::create(std::move(duplicatedFd));
+GeneralResult<SharedHandle> unvalidatedConvert(const ndk::ScopedFileDescriptor& handle) {
+ auto duplicatedFd = NN_TRY(dupFd(handle.get()));
+ return std::make_shared<const Handle>(std::move(duplicatedFd));
}
GeneralResult<Capabilities> convert(const aidl_hal::Capabilities& capabilities) {
@@ -553,8 +538,8 @@
return validatedConvert(timing);
}
-GeneralResult<SyncFence> convert(const ndk::ScopedFileDescriptor& syncFence) {
- return validatedConvert(syncFence);
+GeneralResult<SharedHandle> convert(const ndk::ScopedFileDescriptor& handle) {
+ return validatedConvert(handle);
}
GeneralResult<std::vector<Extension>> convert(const std::vector<aidl_hal::Extension>& extension) {
@@ -619,17 +604,6 @@
return halObject;
}
-nn::GeneralResult<common::NativeHandle> unvalidatedConvert(const nn::Handle& handle) {
- common::NativeHandle aidlNativeHandle;
- aidlNativeHandle.fds.reserve(handle.fds.size());
- for (const auto& fd : handle.fds) {
- auto duplicatedFd = NN_TRY(nn::dupFd(fd.get()));
- aidlNativeHandle.fds.emplace_back(duplicatedFd.release());
- }
- aidlNativeHandle.ints = handle.ints;
- return aidlNativeHandle;
-}
-
// Helper template for std::visit
template <class... Ts>
struct overloaded : Ts... {
@@ -755,11 +729,6 @@
return measureTiming == nn::MeasureTiming::YES;
}
-nn::GeneralResult<common::NativeHandle> unvalidatedConvert(const nn::SharedHandle& sharedHandle) {
- CHECK(sharedHandle != nullptr);
- return unvalidatedConvert(*sharedHandle);
-}
-
nn::GeneralResult<Memory> unvalidatedConvert(const nn::SharedMemory& memory) {
if (memory == nullptr) {
return (NN_ERROR() << "Unable to convert nullptr memory")
@@ -997,16 +966,8 @@
return ndk::ScopedFileDescriptor(duplicatedFd.release());
}
-nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvertCache(
- const nn::SharedHandle& handle) {
- if (handle->ints.size() != 0) {
- NN_ERROR() << "Cache handle must not contain ints";
- }
- if (handle->fds.size() != 1) {
- NN_ERROR() << "Cache handle must contain exactly one fd but contains "
- << handle->fds.size();
- }
- auto duplicatedFd = NN_TRY(nn::dupFd(handle->fds.front().get()));
+nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvert(const nn::SharedHandle& handle) {
+ auto duplicatedFd = NN_TRY(nn::dupFd(handle->get()));
return ndk::ScopedFileDescriptor(duplicatedFd.release());
}
@@ -1069,16 +1030,7 @@
nn::GeneralResult<std::vector<ndk::ScopedFileDescriptor>> convert(
const std::vector<nn::SharedHandle>& cacheHandles) {
- const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(cacheHandles)));
- if (version > kVersion) {
- return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
- }
- std::vector<ndk::ScopedFileDescriptor> cacheFds;
- cacheFds.reserve(cacheHandles.size());
- for (const auto& cacheHandle : cacheHandles) {
- cacheFds.push_back(NN_TRY(unvalidatedConvertCache(cacheHandle)));
- }
- return cacheFds;
+ return validatedConvert(cacheHandles);
}
nn::GeneralResult<std::vector<ndk::ScopedFileDescriptor>> convert(
diff --git a/neuralnetworks/aidl/utils/src/PreparedModel.cpp b/neuralnetworks/aidl/utils/src/PreparedModel.cpp
index 18e7636..f861d74 100644
--- a/neuralnetworks/aidl/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/aidl/utils/src/PreparedModel.cpp
@@ -160,7 +160,7 @@
auto resultSyncFence = nn::SyncFence::createAsSignaled();
if (result.syncFence.get() != -1) {
- resultSyncFence = NN_TRY(nn::convert(result.syncFence));
+ resultSyncFence = nn::SyncFence::create(NN_TRY(nn::convert(result.syncFence))).value();
}
auto callback = result.callback;
diff --git a/neuralnetworks/utils/common/src/CommonUtils.cpp b/neuralnetworks/utils/common/src/CommonUtils.cpp
index 8e55bf0..906b0cf 100644
--- a/neuralnetworks/utils/common/src/CommonUtils.cpp
+++ b/neuralnetworks/utils/common/src/CommonUtils.cpp
@@ -89,23 +89,39 @@
});
}
-nn::GeneralResult<hidl_handle> createNativeHandleFrom(base::unique_fd fd,
+nn::GeneralResult<hidl_handle> createNativeHandleFrom(std::vector<base::unique_fd> fds,
const std::vector<int32_t>& ints) {
constexpr size_t kIntMax = std::numeric_limits<int>::max();
+ CHECK_LE(fds.size(), kIntMax);
CHECK_LE(ints.size(), kIntMax);
- native_handle_t* nativeHandle = native_handle_create(1, static_cast<int>(ints.size()));
+ native_handle_t* nativeHandle =
+ native_handle_create(static_cast<int>(fds.size()), static_cast<int>(ints.size()));
if (nativeHandle == nullptr) {
return NN_ERROR() << "Failed to create native_handle";
}
- nativeHandle->data[0] = fd.release();
- std::copy(ints.begin(), ints.end(), nativeHandle->data + 1);
+ for (size_t i = 0; i < fds.size(); ++i) {
+ nativeHandle->data[i] = fds[i].release();
+ }
+ std::copy(ints.begin(), ints.end(), nativeHandle->data + nativeHandle->numFds);
hidl_handle handle;
handle.setTo(nativeHandle, /*shouldOwn=*/true);
return handle;
}
+nn::GeneralResult<hidl_handle> createNativeHandleFrom(base::unique_fd fd,
+ const std::vector<int32_t>& ints) {
+ std::vector<base::unique_fd> fds;
+ fds.push_back(std::move(fd));
+ return createNativeHandleFrom(std::move(fds), ints);
+}
+
+nn::GeneralResult<hidl_handle> createNativeHandleFrom(const nn::Memory::Unknown::Handle& handle) {
+ std::vector<base::unique_fd> fds = NN_TRY(nn::dupFds(handle.fds.begin(), handle.fds.end()));
+ return createNativeHandleFrom(std::move(fds), handle.ints);
+}
+
nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Ashmem& memory) {
auto fd = NN_TRY(nn::dupFd(memory.fd));
auto handle = NN_TRY(createNativeHandleFrom(std::move(fd), {}));
@@ -139,7 +155,22 @@
}
nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Unknown& memory) {
- return hidl_memory(memory.name, NN_TRY(hidlHandleFromSharedHandle(memory.handle)), memory.size);
+ return hidl_memory(memory.name, NN_TRY(createNativeHandleFrom(memory.handle)), memory.size);
+}
+
+nn::GeneralResult<nn::Memory::Unknown::Handle> unknownHandleFromNativeHandle(
+ const native_handle_t* handle) {
+ if (handle == nullptr) {
+ return NN_ERROR() << "unknownHandleFromNativeHandle failed because handle is nullptr";
+ }
+
+ std::vector<base::unique_fd> fds =
+ NN_TRY(nn::dupFds(handle->data + 0, handle->data + handle->numFds));
+
+ std::vector<int> ints(handle->data + handle->numFds,
+ handle->data + handle->numFds + handle->numInts);
+
+ return nn::Memory::Unknown::Handle{.fds = std::move(fds), .ints = std::move(ints)};
}
} // anonymous namespace
@@ -349,7 +380,7 @@
if (memory.name() != "hardware_buffer_blob") {
auto handle = nn::Memory::Unknown{
- .handle = NN_TRY(sharedHandleFromNativeHandle(memory.handle())),
+ .handle = NN_TRY(unknownHandleFromNativeHandle(memory.handle())),
.size = static_cast<size_t>(memory.size()),
.name = memory.name(),
};
@@ -395,53 +426,19 @@
}
nn::GeneralResult<hidl_handle> hidlHandleFromSharedHandle(const nn::Handle& handle) {
- std::vector<base::unique_fd> fds;
- fds.reserve(handle.fds.size());
- for (const auto& fd : handle.fds) {
- const int dupFd = dup(fd);
- if (dupFd == -1) {
- return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Failed to dup the fd";
- }
- fds.emplace_back(dupFd);
- }
-
- constexpr size_t kIntMax = std::numeric_limits<int>::max();
- CHECK_LE(handle.fds.size(), kIntMax);
- CHECK_LE(handle.ints.size(), kIntMax);
- native_handle_t* nativeHandle = native_handle_create(static_cast<int>(handle.fds.size()),
- static_cast<int>(handle.ints.size()));
- if (nativeHandle == nullptr) {
- return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Failed to create native_handle";
- }
- for (size_t i = 0; i < fds.size(); ++i) {
- nativeHandle->data[i] = fds[i].release();
- }
- std::copy(handle.ints.begin(), handle.ints.end(), &nativeHandle->data[nativeHandle->numFds]);
-
- hidl_handle hidlHandle;
- hidlHandle.setTo(nativeHandle, /*shouldOwn=*/true);
- return hidlHandle;
+ base::unique_fd fd = NN_TRY(nn::dupFd(handle.get()));
+ return createNativeHandleFrom(std::move(fd), {});
}
nn::GeneralResult<nn::Handle> sharedHandleFromNativeHandle(const native_handle_t* handle) {
if (handle == nullptr) {
return NN_ERROR() << "sharedHandleFromNativeHandle failed because handle is nullptr";
}
-
- std::vector<base::unique_fd> fds;
- fds.reserve(handle->numFds);
- for (int i = 0; i < handle->numFds; ++i) {
- const int dupFd = dup(handle->data[i]);
- if (dupFd == -1) {
- return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Failed to dup the fd";
- }
- fds.emplace_back(dupFd);
+ if (handle->numFds != 1 || handle->numInts != 0) {
+ return NN_ERROR() << "sharedHandleFromNativeHandle failed because handle does not only "
+ "hold a single fd";
}
-
- std::vector<int> ints(&handle->data[handle->numFds],
- &handle->data[handle->numFds + handle->numInts]);
-
- return nn::Handle{.fds = std::move(fds), .ints = std::move(ints)};
+ return nn::dupFd(handle->data[0]);
}
nn::GeneralResult<hidl_vec<hidl_handle>> convertSyncFences(
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
index 34395ca..391166b 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -19,6 +19,82 @@
#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
/*
+ * Test IRadio.setAllowedNetworkTypesBitmap for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, setAllowedNetworkTypesBitmap) {
+ serial = GetRandomSerialNumber();
+ ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_4::RadioAccessFamily>
+ allowedNetworkTypesBitmap{};
+ allowedNetworkTypesBitmap |= ::android::hardware::radio::V1_4::RadioAccessFamily::LTE;
+
+ radio_v1_6->setAllowedNetworkTypesBitmap(serial, allowedNetworkTypesBitmap);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+
+ if (getRadioHalCapabilities()) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
+ ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
+ }
+}
+
+/*
+ * Test IRadio.getAllowedNetworkTypesBitmap for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, getAllowedNetworkTypesBitmap) {
+ serial = GetRandomSerialNumber();
+ ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_4::RadioAccessFamily>
+ allowedNetworkTypesBitmap{};
+ allowedNetworkTypesBitmap |= ::android::hardware::radio::V1_4::RadioAccessFamily::LTE;
+
+ radio_v1_6->setAllowedNetworkTypesBitmap(serial, allowedNetworkTypesBitmap);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+
+ if (radioRsp_v1_6->rspInfo.error == ::android::hardware::radio::V1_6::RadioError::NONE) {
+ sleep(3); // wait for modem
+ serial = GetRandomSerialNumber();
+ radio_v1_6->getAllowedNetworkTypesBitmap(serial);
+
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+
+ if (getRadioHalCapabilities()) {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
+ } else {
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
+ ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
+ }
+ }
+}
+
+/*
* Test IRadio.setupDataCall_1_6() for the response returned.
*/
TEST_P(RadioHidlTest_v1_6, setupDataCall_1_6) {
@@ -512,11 +588,11 @@
EXPECT_EQ(std::cv_status::no_timeout, wait());
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
- ASSERT_TRUE(
- CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::NONE,
- ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
- ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE}));
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::SIM_ERR}));
// setSimCardPower_1_6 does not return until the request is handled, and should not trigger
// CardState::ABSENT when turning off power
@@ -534,11 +610,11 @@
EXPECT_EQ(std::cv_status::no_timeout, wait());
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
- ASSERT_TRUE(
- CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::NONE,
- ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
- ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE}));
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::SIM_ERR}));
// setSimCardPower_1_6 does not return until the request is handled. Just verify that we still
// have CardState::PRESENT after turning the power back on
diff --git a/radio/1.6/vts/functional/radio_response.cpp b/radio/1.6/vts/functional/radio_response.cpp
index b1e679b..e1b9f56 100644
--- a/radio/1.6/vts/functional/radio_response.cpp
+++ b/radio/1.6/vts/functional/radio_response.cpp
@@ -1172,10 +1172,13 @@
}
Return<void> RadioResponse_v1_6::getAllowedNetworkTypesBitmapResponse(
- const ::android::hardware::radio::V1_6::RadioResponseInfo& /*info*/,
+ const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
const ::android::hardware::hidl_bitfield<
::android::hardware::radio::V1_4::RadioAccessFamily>
- /*networkTypeBitmap*/) {
+ networkTypeBitmap) {
+ rspInfo = info;
+ networkTypeBitmapResponse = networkTypeBitmap;
+ parent_v1_6.notify(info.serial);
return Void();
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
index 3ea14a1..32d69cd 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -37,10 +37,13 @@
* ? "board" : tstr,
* ? "vb_state" : "green" / "yellow" / "orange", // Taken from the AVB values
* ? "bootloader_state" : "locked" / "unlocked", // Taken from the AVB values
+ * ? "vbmeta_digest": bstr, // Taken from the AVB values
* ? "os_version" : tstr, // Same as android.os.Build.VERSION.release
* ? "system_patch_level" : uint, // YYYYMMDD
* ? "boot_patch_level" : uint, // YYYYMMDD
* ? "vendor_patch_level" : uint, // YYYYMMDD
+ * "version" : 1, // The CDDL schema version.
+ * "security_level" : "tee" / "strongbox"
* }
*/
byte[] deviceInfo;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 5b0b303..88b2a26 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -233,8 +233,6 @@
* indistinguishable from random. Thus, if the entropy from any source is good, the output
* must be good.
*
- * TODO(seleneh) specify what mixing functions and cprng we allow.
- *
* @param data Bytes to be mixed into the CRNG seed. The caller must not provide more than 2
* KiB of data per invocation.
*
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
index 04d91d0..a29fb08 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -33,8 +33,8 @@
*
* The root of trust for secure provisioning is something called the "Boot Certificate Chain", or
* BCC. The BCC is a chain of public key certificates, represented as COSE_Sign1 objects containing
- * COSE_Key representations of the public keys. The "root" of the BCC is a self-signed certificate
- * for a device-unique public key, denoted DK_pub. All public keys in the BCC are device-unique. The
+ * COSE_Key representations of the public keys. The "root" of the BCC is
+ * a device-unique public key, denoted DK_pub. All public keys in the BCC are device-unique. The
* public key from each certificate in the chain is used to sign the next certificate in the
* chain. The final, "leaf" certificate contains a public key, denoted KM_pub, whose corresponding
* private key, denoted KM_priv, is available for use by the IRemotelyProvisionedComponent.
@@ -58,12 +58,8 @@
* (given the necessary input), but no stage can compute the secret of any preceding stage. Updating
* the firmware or configuration of any stage changes the key pair of that stage, and of all
* subsequent stages, and no attacker who compromised the previous version of the updated firmware
- * can know or predict the post-update key pairs.
- *
- * The first BCC certificate is special because its contained public key, DK_pub, will never change,
- * making it a permanent, device-unique identifier. Although the remaining keys in the BCC are also
- * device-unique, they are not necessarily permanent, since they can change when the device software
- * is updated.
+ * can know or predict the post-update key pairs. It is recommended and expected that the BCC is
+ * constructed using the Open Profile for DICE.
*
* When the provisioning server receives a message signed by KM_priv and containing a BCC that
* chains from DK_pub to KM_pub, it can be certain that (barring vulnerabilities in some boot
@@ -78,7 +74,7 @@
* While a proper BCC, as described above, reflects the complete boot sequence from boot ROM to the
* secure area image of the IRemotelyProvisionedComponent, it's also possible to use a "degenerate"
* BCC which consists only of a single, self-signed certificate containing the public key of a
- * hardware-bound key pair. This is an appropriate solution for devices which haven't implemented
+ * hardware-bound key pair. This is an appopriate solution for devices which haven't implemented
* everything necessary to produce a proper BCC, but can derive a unique key pair in the secure
* area. In this degenerate case, DK_pub is the same as KM_pub.
*
@@ -141,7 +137,7 @@
* privateKeyHandle, that the contained public key is for remote certification.
*
* @return data representing a handle to the private key. The format is implementation-defined,
- * but note that specific services may define a required format.
+ * but note that specific services may define a required format. KeyMint does.
*/
byte[] generateEcdsaP256KeyPair(in boolean testMode, out MacedPublicKey macedPublicKey);
@@ -162,65 +158,90 @@
* If testMode is false, the keysToCertify array must not contain any keys flagged as
* test keys. Otherwise, the method must return STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
*
- * @param in endpointEncryptionKey contains an X25519 public key which will be used to encrypt
+ * @param in endpointEncryptionKey contains an X22519 public key which will be used to encrypt
* the BCC. For flexibility, this is represented as a certificate chain, represented as a
* CBOR array of COSE_Sign1 objects, ordered from root to leaf. The leaf contains the
* X25519 encryption key, each other element is an Ed25519 key signing the next in the
- * chain. The root is self-signed.
+ * chain. The root is self-signed. An implementor may also choose to use P256 as an
+ * alternative curve for signing and encryption instead of Curve 25519.
*
* EekChain = [ + SignedSignatureKey, SignedEek ]
*
* SignedSignatureKey = [ // COSE_Sign1
* protected: bstr .cbor {
- * 1 : -8, // Algorithm : EdDSA
+ * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm
* },
- * unprotected: { },
- * payload: bstr .cbor SignatureKey,
- * signature: bstr PureEd25519(.cbor SignatureKeySignatureInput)
+ * unprotected: {},
+ * payload: bstr .cbor SignatureKeyEd25519 /
+ * bstr .cbor SignatureKeyP256,
+ * signature: bstr PureEd25519(.cbor SignatureKeySignatureInput) /
+ * bstr ECDSA(.cbor SignatureKeySignatureInput)
* ]
*
- * SignatureKey = { // COSE_Key
+ * SignatureKeyEd25519 = { // COSE_Key
* 1 : 1, // Key type : Octet Key Pair
- * 3 : -8, // Algorithm : EdDSA
+ * 3 : AlgorithmEdDSA, // Algorithm
* -1 : 6, // Curve : Ed25519
* -2 : bstr // Ed25519 public key
* }
*
+ * SignatureKeyP256 = {
+ * 1 : 2, // Key type : EC2
+ * 3 : AlgorithmES256, // Algorithm
+ * -1 : 1, // Curve: P256
+ * -2 : bstr, // X coordinate
+ * -3 : bstr // Y coordinate
+ * }
+ *
* SignatureKeySignatureInput = [
* context: "Signature1",
* body_protected: bstr .cbor {
- * 1 : -8, // Algorithm : EdDSA
+ * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm
* },
* external_aad: bstr .size 0,
- * payload: bstr .cbor SignatureKey
+ * payload: bstr .cbor SignatureKeyEd25519 /
+ * bstr .cbor SignatureKeyP256
* ]
*
* SignedEek = [ // COSE_Sign1
* protected: bstr .cbor {
- * 1 : -8, // Algorithm : EdDSA
+ * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm
* },
- * unprotected: { },
- * payload: bstr .cbor Eek,
- * signature: bstr PureEd25519(.cbor EekSignatureInput)
+ * unprotected: {},
+ * payload: bstr .cbor EekX25519 / .cbor EekP256,
+ * signature: bstr PureEd25519(.cbor EekSignatureInput) /
+ * bstr ECDSA(.cbor EekSignatureInput)
* ]
*
- * Eek = { // COSE_Key
- * 1 : 1, // Key type : Octet Key Pair
- * 2 : bstr // KID : EEK ID
- * 3 : -25, // Algorithm : ECDH-ES + HKDF-256
- * -1 : 4, // Curve : X25519
- * -2 : bstr // X25519 public key
+ * EekX25519 = { // COSE_Key
+ * 1 : 1, // Key type : Octet Key Pair
+ * 2 : bstr // KID : EEK ID
+ * 3 : -25, // Algorithm : ECDH-ES + HKDF-256
+ * -1 : 4, // Curve : X25519
+ * -2 : bstr // Ed25519 public key
+ * }
+ *
+ * EekP256 = { // COSE_Key
+ * 1 : 2, // Key type : EC2
+ * 2 : bstr // KID : EEK ID
+ * 3 : -25, // Algorithm : ECDH-ES + HKDF-256
+ * -1 : 1, // Curve : P256
+ * -2 : bstr // Sender X coordinate
+ * -3 : bstr // Sender Y coordinate
* }
*
* EekSignatureInput = [
* context: "Signature1",
* body_protected: bstr .cbor {
- * 1 : -8, // Algorithm : EdDSA
+ * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm
* },
* external_aad: bstr .size 0,
- * payload: bstr .cbor Eek
+ * payload: bstr .cbor EekX25519 / .cbor EekP256
* ]
*
+ * AlgorithmES256 = -7
+ * AlgorithmEdDSA = -8
+ *
* If the contents of endpointEncryptionKey do not match the SignedEek structure above,
* the method must return STATUS_INVALID_EEK.
*
@@ -228,7 +249,7 @@
* in the chain, which implies that it must not attempt to validate the signature.
*
* If testMode is false, the method must validate the chain signatures, and must verify
- * that the public key in the root certificate is in its pre-configured set of
+ * that the public key in the root certifictate is in its pre-configured set of
* authorized EEK root keys. If the public key is not in the database, or if signature
* verification fails, the method must return STATUS_INVALID_EEK.
*
@@ -236,8 +257,13 @@
* by the secure area. See the description of the 'signature' output parameter for
* details.
*
- * @param out keysToSignMac contains the MAC of KeysToSign in the CertificateRequest
- * structure. Specifically, it contains:
+ * @param out DeviceInfo contains the VerifiedDeviceInfo portion of the DeviceInfo array in
+ * CertificateRequest. The structure is described within the DeviceInfo.aidl file.
+ *
+ * @param out ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
+ * authenticate the keysToSign (see keysToSignMac output argument).
+ *
+ * @return The of KeysToSign in the CertificateRequest structure. Specifically, it contains:
*
* HMAC-256(EK_mac, .cbor KeysToMacStructure)
*
@@ -248,11 +274,11 @@
* protected : bstr .cbor {
* 1 : 5, // Algorithm : HMAC-256
* },
- * unprotected : { },
+ * unprotected : {},
* // Payload is PublicKeys from keysToSign argument, in provided order.
* payload: bstr .cbor [ * PublicKey ],
* tag: bstr
- * ]
+ * ]
*
* KeysToMacStructure = [
* context : "MAC0",
@@ -261,9 +287,6 @@
* // Payload is PublicKeys from keysToSign argument, in provided order.
* payload : bstr .cbor [ * PublicKey ]
* ]
- *
- * @param out ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
- * authenticate the keysToSign (see keysToSignMac output argument).
*/
byte[] generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign,
in byte[] endpointEncryptionCertChain, in byte[] challenge, out DeviceInfo deviceInfo,
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
index 25fdee3..f0df048 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCharacteristics.aidl
@@ -32,6 +32,17 @@
*/
@VintfStability
parcelable KeyCharacteristics {
+ /**
+ * The security level enforcing this collection of key properties.
+ */
SecurityLevel securityLevel = SecurityLevel.SOFTWARE;
+
+ /**
+ * `authorizations` is a list of key properties that are enforced at this security level.
+ * A key can have different properties enforced by components of different security levels.
+ * For example, some properties are provided by the operating system, which has a
+ * different security level to the IKeyMintDevice.
+ * See the `keyCharacteristics` field in `KeyCreationResult` for more details.
+ */
KeyParameter[] authorizations;
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
index 8da7578..b82dee6 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyMintHardwareInfo.aidl
@@ -29,7 +29,6 @@
* Implementation version of the keymint hardware. The version number is implementation
* defined, and not necessarily globally meaningful. The version is used to distinguish
* between different versions of a given implementation.
- * TODO(seleneh) add the version related info to the code.
*/
int versionNumber;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl b/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
index fbb373b..e71a9c9 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/PaddingMode.aidl
@@ -17,8 +17,6 @@
package android.hardware.security.keymint;
/**
- * TODO(seleneh) update the description.
- *
* Padding modes that may be applied to plaintext for encryption operations. This list includes
* padding modes for both symmetric and asymmetric algorithms. Note that implementations should not
* provide all possible combinations of algorithm and padding, only the
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
index 5199062..31dbb28 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
@@ -40,11 +40,7 @@
* 1 : -25 // Algorithm : ECDH-ES + HKDF-256
* },
* unprotected : {
- * -1 : { // COSE_Key
- * 1 : 1, // Key type : Octet Key Pair
- * -1 : 4, // Curve : X25519
- * -2 : bstr // Sender X25519 public key
- * }
+ * -1 : PubKeyX25519 / PubKeyEcdhP256 // Of the sender
* 4 : bstr, // KID : EEK ID
* },
* ciphertext : nil
@@ -67,7 +63,7 @@
* other : bstr // EEK pubkey
* ],
* SuppPubInfo : [
- * 128, // Output key length
+ * 256, // Output key length
* protected : bstr .size 0
* ]
* ]
@@ -75,34 +71,51 @@
* ProtectedDataPayload [
* SignedMac,
* Bcc,
+ * ? AdditionalDKSignatures,
+ * ]
+ * AdditionalDKSignatures = {
+ * + SignerName => DKCertChain
+ * }
+ *
+ * SignerName = tstr
+ *
+ * DKCertChain = [
+ * 2* Certificate // Root -> Leaf. Root is the vendor
+ * // self-signed cert, leaf contains DK_pub
* ]
*
- * SignedMac = [ // COSE_Sign1
- * bstr .cbor { // Protected params
- * 1 : -8, // Algorithm : EdDSA
+ * Certificate = COSE_Sign1 of a public key
+ *
+ * SignedMac = [ // COSE_Sign1
+ * bstr .cbor { // Protected params
+ * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm
* },
- * { }, // Unprotected params
+ * {}, // Unprotected params
* bstr .size 32, // MAC key
- * bstr PureEd25519(DK_priv, .cbor SignedMac_structure)
+ * bstr PureEd25519(KM_priv, .cbor SignedMac_structure) /
+ * ECDSA(KM_priv, bstr .cbor SignedMac_structure)
* ]
*
* SignedMac_structure = [
* "Signature1",
- * bstr .cbor { // Protected params
- * 1 : -8, // Algorithm : EdDSA
+ * bstr .cbor { // Protected params
+ * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm
* },
* bstr .cbor SignedMacAad
- * bstr .size 32 // MAC key
+ * bstr .size 32 // MAC key
* ]
*
* SignedMacAad = [
* challenge : bstr,
- * DeviceInfo
+ * VerifiedDeviceInfo,
+ * tag: bstr // This is the tag from COSE_Mac0 of
+ * // KeysToCertify, to tie the key set to
+ * // the signature.
* ]
*
* Bcc = [
- * PubKey, // DK_pub
- * + BccEntry, // Root -> leaf (KM_pub)
+ * PubKeyEd25519 / PubKeyECDSA256, // DK_pub
+ * + BccEntry, // Root -> leaf (KM_pub)
* ]
*
* BccPayload = { // CWT
@@ -120,44 +133,38 @@
* ? -4670549 : bstr, // Authority Hash
* ? -4670550 : bstr, // Authority Descriptor
* ? -4670551 : bstr, // Mode
- * -4670552 : bstr .cbor PubKey // Subject Public Key
+ * -4670552 : bstr .cbor PubKeyEd25519 /
+ * bstr .cbor PubKeyECDSA256 // Subject Public Key
* -4670553 : bstr // Key Usage
* }
*
- * BccEntry = [ // COSE_Sign1
- * protected: bstr .cbor {
- * 1 : -8, // Algorithm : EdDSA
+ * BccEntry = [ // COSE_Sign1 (untagged)
+ * protected : bstr .cbor {
+ * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm
* },
- * unprotected: { },
+ * unprotected: {},
* payload: bstr .cbor BccPayload,
- * // First entry in the chain is signed by DK_pub, the others are each signed by their
- * // immediate predecessor. See RFC 8032 for signature representation.
- * signature: bstr .cbor PureEd25519(SigningKey, bstr .cbor BccEntryInput)
+ * signature: bstr .cbor PureEd25519(SigningKey, bstr .cbor BccEntryInput) /
+ * bstr .cbor ECDSA(SigningKey, bstr .cbor BccEntryInput)
+ * // See RFC 8032 for details of how to encode the signature value for Ed25519.
* ]
*
- * PubKey = { // COSE_Key
- * 1 : 1, // Key type : octet key pair
- * 3 : -8, // Algorithm : EdDSA
- * 4 : 2, // Ops: Verify
- * -1 : 6, // Curve : Ed25519
- * -2 : bstr // X coordinate, little-endian
- * }
- *
* BccEntryInput = [
* context: "Signature1",
* protected: bstr .cbor {
- * 1 : -8, // Algorithm : EdDSA
+ * 1 : AlgorithmEdDSA / AlgorithmES256, // Algorithm
* },
* external_aad: bstr .size 0,
* payload: bstr .cbor BccPayload
* ]
*
- * DeviceInfo = {
+ * VerifiedDeviceInfo = {
* ? "brand" : tstr,
* ? "manufacturer" : tstr,
* ? "product" : tstr,
* ? "model" : tstr,
* ? "board" : tstr,
+ * ? "device" : tstr,
* ? "vb_state" : "green" / "yellow" / "orange",
* ? "bootloader_state" : "locked" / "unlocked",
* ? "os_version" : tstr,
@@ -165,6 +172,39 @@
* ? "boot_patch_level" : uint, // YYYYMMDD
* ? "vendor_patch_level" : uint, // YYYYMMDD
* }
+ *
+ * PubKeyX25519 = { // COSE_Key
+ * 1 : 1, // Key type : Octet Key Pair
+ * -1 : 4, // Curve : X25519
+ * -2 : bstr // Sender X25519 public key
+ * }
+ *
+ * PubKeyEd25519 = { // COSE_Key
+ * 1 : 1, // Key type : octet key pair
+ * 3 : AlgorithmEdDSA, // Algorithm : EdDSA
+ * 4 : 2, // Ops: Verify
+ * -1 : 6, // Curve : Ed25519
+ * -2 : bstr // X coordinate, little-endian
+ * }
+ *
+ * PubKeyEcdhP256 = { // COSE_Key
+ * 1 : 2, // Key type : EC2
+ * -1 : 1, // Curve : P256
+ * -2 : bstr // Sender X coordinate
+ * -3 : bstr // Sender Y coordinate
+ * }
+ *
+ * PubKeyECDSA256 = { // COSE_Key
+ * 1 : 2, // Key type : EC2
+ * 3 : AlgorithmES256, // Algorithm : ECDSA w/ SHA-256
+ * 4 : 2, // Ops: Verify
+ * -1 : 1, // Curve: P256
+ * -2 : bstr, // X coordinate
+ * -3 : bstr // Y coordinate
+ * }
+ *
+ * AlgorithmES256 = -7
+ * AlgorithmEdDSA = -8
*/
byte[] protectedData;
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index 58e02b3..972ce2e 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -18,10 +18,6 @@
import android.hardware.security.keymint.TagType;
-// TODO(seleneh) : note aidl currently does not support double nested enum definitions such as
-// ROOT_OF_TRUST = TagType:BYTES | 704. So we are forced to write definitions as
-// ROOT_OF_TRUST = (9 << 28) for now. Will need to flip this back later when aidl support is added.
-
/**
* Tag specifies various kinds of tags that can be set in KeyParameter to identify what kind of
* data are stored in KeyParameter.
@@ -33,7 +29,7 @@
/**
* Tag::INVALID should never be set. It means you hit an error.
*/
- INVALID = (0 << 28) | 0,
+ INVALID = 0,
/**
* Tag::PURPOSE specifies the set of purposes for which the key may be used. Possible values
@@ -47,7 +43,7 @@
*
* Must be hardware-enforced.
*/
- PURPOSE = (2 << 28) /* TagType:ENUM_REP */ | 1,
+ PURPOSE = TagType.ENUM_REP | 1,
/**
* Tag::ALGORITHM specifies the cryptographic algorithm with which the key is used. This tag
@@ -56,7 +52,7 @@
*
* Must be hardware-enforced.
*/
- ALGORITHM = (1 << 28) /* TagType:ENUM */ | 2,
+ ALGORITHM = TagType.ENUM | 2,
/**
* Tag::KEY_SIZE specifies the size, in bits, of the key, measuring in the normal way for the
@@ -68,7 +64,7 @@
*
* Must be hardware-enforced.
*/
- KEY_SIZE = (3 << 28) /* TagType:UINT */ | 3,
+ KEY_SIZE = TagType.UINT | 3,
/**
* Tag::BLOCK_MODE specifies the block cipher mode(s) with which the key may be used. This tag
@@ -81,7 +77,7 @@
*
* Must be hardware-enforced.
*/
- BLOCK_MODE = (2 << 28) /* TagType:ENUM_REP */ | 4,
+ BLOCK_MODE = TagType.ENUM_REP | 4,
/**
* Tag::DIGEST specifies the digest algorithms that may be used with the key to perform signing
@@ -95,7 +91,7 @@
*
* Must be hardware-enforced.
*/
- DIGEST = (2 << 28) /* TagType:ENUM_REP */ | 5,
+ DIGEST = TagType.ENUM_REP | 5,
/**
* Tag::PADDING specifies the padding modes that may be used with the key. This tag is relevant
@@ -123,7 +119,7 @@
*
* Must be hardware-enforced.
*/
- PADDING = (2 << 28) /* TagType:ENUM_REP */ | 6,
+ PADDING = TagType.ENUM_REP | 6,
/**
* Tag::CALLER_NONCE specifies that the caller can provide a nonce for nonce-requiring
@@ -136,7 +132,7 @@
*
* Must be hardware-enforced.
*/
- CALLER_NONCE = (7 << 28) /* TagType:BOOL */ | 7,
+ CALLER_NONCE = TagType.BOOL | 7,
/**
* Tag::MIN_MAC_LENGTH specifies the minimum length of MAC that can be requested or verified
@@ -149,7 +145,7 @@
*
* Must be hardware-enforced.
*/
- MIN_MAC_LENGTH = (3 << 28) /* TagType:UINT */ | 8,
+ MIN_MAC_LENGTH = TagType.UINT | 8,
// Tag 9 reserved
@@ -159,7 +155,7 @@
*
* Must be hardware-enforced.
*/
- EC_CURVE = (1 << 28) /* TagType:ENUM */ | 10,
+ EC_CURVE = TagType.ENUM | 10,
/**
* Tag::RSA_PUBLIC_EXPONENT specifies the value of the public exponent for an RSA key pair.
@@ -173,7 +169,7 @@
*
* Must be hardware-enforced.
*/
- RSA_PUBLIC_EXPONENT = (5 << 28) /* TagType:ULONG */ | 200,
+ RSA_PUBLIC_EXPONENT = TagType.ULONG | 200,
// Tag 201 reserved
@@ -184,7 +180,7 @@
*
* Must be hardware-enforced.
*/
- INCLUDE_UNIQUE_ID = (7 << 28) /* TagType:BOOL */ | 202,
+ INCLUDE_UNIQUE_ID = TagType.BOOL | 202,
/**
* Tag::RSA_OAEP_MGF_DIGEST specifies the MGF1 digest algorithms that may be used with RSA
@@ -197,7 +193,7 @@
*
* Must be hardware-enforced.
*/
- RSA_OAEP_MGF_DIGEST = (2 << 28) /* TagType:ENUM_REP */ | 203,
+ RSA_OAEP_MGF_DIGEST = TagType.ENUM_REP | 203,
// Tag 301 reserved
@@ -209,7 +205,7 @@
*
* Must be hardware-enforced.
*/
- BOOTLOADER_ONLY = (7 << 28) /* TagType:BOOL */ | 302,
+ BOOTLOADER_ONLY = TagType.BOOL | 302,
/**
* Tag::ROLLBACK_RESISTANCE specifies that the key has rollback resistance, meaning that when
@@ -224,10 +220,10 @@
*
* Must be hardware-enforced.
*/
- ROLLBACK_RESISTANCE = (7 << 28) /* TagType:BOOL */ | 303,
+ ROLLBACK_RESISTANCE = TagType.BOOL | 303,
// Reserved for future use.
- HARDWARE_TYPE = (1 << 28) /* TagType:ENUM */ | 304,
+ HARDWARE_TYPE = TagType.ENUM | 304,
/**
* Keys tagged with EARLY_BOOT_ONLY may only be used during early boot, until
@@ -236,7 +232,7 @@
* provided to IKeyMintDevice::importKey, the import must fail with
* ErrorCode::EARLY_BOOT_ENDED.
*/
- EARLY_BOOT_ONLY = (7 << 28) /* TagType:BOOL */ | 305,
+ EARLY_BOOT_ONLY = TagType.BOOL | 305,
/**
* Tag::ACTIVE_DATETIME specifies the date and time at which the key becomes active, in
@@ -245,7 +241,7 @@
*
* Need not be hardware-enforced.
*/
- ACTIVE_DATETIME = (6 << 28) /* TagType:DATE */ | 400,
+ ACTIVE_DATETIME = TagType.DATE | 400,
/**
* Tag::ORIGINATION_EXPIRE_DATETIME specifies the date and time at which the key expires for
@@ -257,7 +253,7 @@
*
* Need not be hardware-enforced.
*/
- ORIGINATION_EXPIRE_DATETIME = (6 << 28) /* TagType:DATE */ | 401,
+ ORIGINATION_EXPIRE_DATETIME = TagType.DATE | 401,
/**
* Tag::USAGE_EXPIRE_DATETIME specifies the date and time at which the key expires for
@@ -269,13 +265,9 @@
*
* Need not be hardware-enforced.
*/
- USAGE_EXPIRE_DATETIME = (6 << 28) /* TagType:DATE */ | 402,
+ USAGE_EXPIRE_DATETIME = TagType.DATE | 402,
/**
- * TODO(seleneh) this tag need to be deleted.
- *
- * TODO(seleneh) this tag need to be deleted.
- *
* Tag::MIN_SECONDS_BETWEEN_OPS specifies the minimum amount of time that elapses between
* allowed operations using a key. This can be used to rate-limit uses of keys in contexts
* where unlimited use may enable brute force attacks.
@@ -293,8 +285,10 @@
* fails because the table is full, KeyMint returns ErrorCode::TOO_MANY_OPERATIONS.
*
* Must be hardware-enforced.
+ *
+ * TODO(b/191458710): find out if this tag is still supported.
*/
- MIN_SECONDS_BETWEEN_OPS = (3 << 28) /* TagType:UINT */ | 403,
+ MIN_SECONDS_BETWEEN_OPS = TagType.UINT | 403,
/**
* Tag::MAX_USES_PER_BOOT specifies the maximum number of times that a key may be used between
@@ -314,7 +308,7 @@
*
* Must be hardware-enforced.
*/
- MAX_USES_PER_BOOT = (3 << 28) /* TagType:UINT */ | 404,
+ MAX_USES_PER_BOOT = TagType.UINT | 404,
/**
* Tag::USAGE_COUNT_LIMIT specifies the number of times that a key may be used. This can be
@@ -343,14 +337,14 @@
* record. This tag must have the same SecurityLevel as the tag that is added to the key
* characteristics.
*/
- USAGE_COUNT_LIMIT = (3 << 28) | 405, /* TagType:UINT */
+ USAGE_COUNT_LIMIT = TagType.UINT | 405,
/**
* Tag::USER_ID specifies the ID of the Android user that is permitted to use the key.
*
* Must not be hardware-enforced.
*/
- USER_ID = (3 << 28) /* TagType:UINT */ | 501,
+ USER_ID = TagType.UINT | 501,
/**
* Tag::USER_SECURE_ID specifies that a key may only be used under a particular secure user
@@ -383,7 +377,7 @@
*
* Must be hardware-enforced.
*/
- USER_SECURE_ID = (10 << 28) /* TagType:ULONG_REP */ | 502,
+ USER_SECURE_ID = TagType.ULONG_REP | 502,
/**
* Tag::NO_AUTH_REQUIRED specifies that no authentication is required to use this key. This tag
@@ -391,7 +385,7 @@
*
* Must be hardware-enforced.
*/
- NO_AUTH_REQUIRED = (7 << 28) /* TagType:BOOL */ | 503,
+ NO_AUTH_REQUIRED = TagType.BOOL | 503,
/**
* Tag::USER_AUTH_TYPE specifies the types of user authenticators that may be used to authorize
@@ -410,7 +404,7 @@
*
* Must be hardware-enforced.
*/
- USER_AUTH_TYPE = (1 << 28) /* TagType:ENUM */ | 504,
+ USER_AUTH_TYPE = TagType.ENUM | 504,
/**
* Tag::AUTH_TIMEOUT specifies the time in seconds for which the key is authorized for use,
@@ -424,7 +418,7 @@
*
* Must be hardware-enforced.
*/
- AUTH_TIMEOUT = (3 << 28) /* TagType:UINT */ | 505,
+ AUTH_TIMEOUT = TagType.UINT | 505,
/**
* Tag::ALLOW_WHILE_ON_BODY specifies that the key may be used after authentication timeout if
@@ -432,7 +426,7 @@
*
* Cannot be hardware-enforced.
*/
- ALLOW_WHILE_ON_BODY = (7 << 28) /* TagType:BOOL */ | 506,
+ ALLOW_WHILE_ON_BODY = TagType.BOOL | 506,
/**
* TRUSTED_USER_PRESENCE_REQUIRED is an optional feature that specifies that this key must be
@@ -479,7 +473,7 @@
*
* Must be hardware-enforced.
*/
- TRUSTED_USER_PRESENCE_REQUIRED = (7 << 28) /* TagType:BOOL */ | 507,
+ TRUSTED_USER_PRESENCE_REQUIRED = TagType.BOOL | 507,
/**
* Tag::TRUSTED_CONFIRMATION_REQUIRED is only applicable to keys with KeyPurpose SIGN, and
@@ -493,7 +487,7 @@
*
* Must be hardware-enforced.
*/
- TRUSTED_CONFIRMATION_REQUIRED = (7 << 28) /* TagType:BOOL */ | 508,
+ TRUSTED_CONFIRMATION_REQUIRED = TagType.BOOL | 508,
/**
* Tag::UNLOCKED_DEVICE_REQUIRED specifies that the key may only be used when the device is
@@ -501,7 +495,7 @@
*
* Must be software-enforced.
*/
- UNLOCKED_DEVICE_REQUIRED = (7 << 28) /* TagType:BOOL */ | 509,
+ UNLOCKED_DEVICE_REQUIRED = TagType.BOOL | 509,
/**
* Tag::APPLICATION_ID. When provided to generateKey or importKey, this tag specifies data
@@ -517,7 +511,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- APPLICATION_ID = (9 << 28) /* TagType:BYTES */ | 601,
+ APPLICATION_ID = TagType.BYTES | 601,
/*
* Semantically unenforceable tags, either because they have no specific meaning or because
@@ -538,7 +532,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- APPLICATION_DATA = (9 << 28) /* TagType:BYTES */ | 700,
+ APPLICATION_DATA = TagType.BYTES | 700,
/**
* Tag::CREATION_DATETIME specifies the date and time the key was created, in milliseconds since
@@ -546,7 +540,7 @@
*
* Must be in the software-enforced list, if provided.
*/
- CREATION_DATETIME = (6 << 28) /* TagType:DATE */ | 701,
+ CREATION_DATETIME = TagType.DATE | 701,
/**
* Tag::ORIGIN specifies where the key was created, if known. This tag must not be specified
@@ -555,7 +549,7 @@
*
* Must be hardware-enforced.
*/
- ORIGIN = (1 << 28) /* TagType:ENUM */ | 702,
+ ORIGIN = TagType.ENUM | 702,
// 703 is unused.
@@ -567,7 +561,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ROOT_OF_TRUST = (9 << 28) /* TagType:BYTES */ | 704,
+ ROOT_OF_TRUST = TagType.BYTES | 704,
/**
* Tag::OS_VERSION specifies the system OS version with which the key may be used. This tag is
@@ -590,7 +584,7 @@
*
* Must be hardware-enforced.
*/
- OS_VERSION = (3 << 28) /* TagType:UINT */ | 705,
+ OS_VERSION = TagType.UINT | 705,
/**
* Tag::OS_PATCHLEVEL specifies the system security patch level with which the key may be used.
@@ -611,7 +605,7 @@
*
* Must be hardware-enforced.
*/
- OS_PATCHLEVEL = (3 << 28) /* TagType:UINT */ | 706,
+ OS_PATCHLEVEL = TagType.UINT | 706,
/**
* Tag::UNIQUE_ID specifies a unique, time-based identifier. This tag is never provided to or
@@ -646,7 +640,7 @@
*
* Must be hardware-enforced.
*/
- UNIQUE_ID = (9 << 28) /* TagType:BYTES */ | 707,
+ UNIQUE_ID = TagType.BYTES | 707,
/**
* Tag::ATTESTATION_CHALLENGE is used to deliver a "challenge" value to the attested key
@@ -655,7 +649,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_CHALLENGE = (9 << 28) /* TagType:BYTES */ | 708,
+ ATTESTATION_CHALLENGE = TagType.BYTES | 708,
/**
* Tag::ATTESTATION_APPLICATION_ID identifies the set of applications which may use a key, used
@@ -681,7 +675,7 @@
*
* Cannot be hardware-enforced.
*/
- ATTESTATION_APPLICATION_ID = (9 << 28) /* TagType:BYTES */ | 709,
+ ATTESTATION_APPLICATION_ID = TagType.BYTES | 709,
/**
* Tag::ATTESTATION_ID_BRAND provides the device's brand name, as returned by Build.BRAND in
@@ -694,7 +688,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_BRAND = (9 << 28) /* TagType:BYTES */ | 710,
+ ATTESTATION_ID_BRAND = TagType.BYTES | 710,
/**
* Tag::ATTESTATION_ID_DEVICE provides the device's device name, as returned by Build.DEVICE in
@@ -707,7 +701,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_DEVICE = (9 << 28) /* TagType:BYTES */ | 711,
+ ATTESTATION_ID_DEVICE = TagType.BYTES | 711,
/**
* Tag::ATTESTATION_ID_PRODUCT provides the device's product name, as returned by Build.PRODUCT
@@ -720,7 +714,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_PRODUCT = (9 << 28) /* TagType:BYTES */ | 712,
+ ATTESTATION_ID_PRODUCT = TagType.BYTES | 712,
/**
* Tag::ATTESTATION_ID_SERIAL the device's serial number. This field must be set only when
@@ -732,7 +726,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_SERIAL = (9 << 28) /* TagType:BYTES */ | 713,
+ ATTESTATION_ID_SERIAL = TagType.BYTES | 713,
/**
* Tag::ATTESTATION_ID_IMEI provides the IMEIs for all radios on the device to attested key
@@ -745,7 +739,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_IMEI = (9 << 28) /* TagType:BYTES */ | 714,
+ ATTESTATION_ID_IMEI = TagType.BYTES | 714,
/**
* Tag::ATTESTATION_ID_MEID provides the MEIDs for all radios on the device to attested key
@@ -758,7 +752,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_MEID = (9 << 28) /* TagType:BYTES */ | 715,
+ ATTESTATION_ID_MEID = TagType.BYTES | 715,
/**
* Tag::ATTESTATION_ID_MANUFACTURER provides the device's manufacturer name, as returned by
@@ -771,7 +765,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_MANUFACTURER = (9 << 28) /* TagType:BYTES */ | 716,
+ ATTESTATION_ID_MANUFACTURER = TagType.BYTES | 716,
/**
* Tag::ATTESTATION_ID_MODEL provides the device's model name, as returned by Build.MODEL in
@@ -784,7 +778,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- ATTESTATION_ID_MODEL = (9 << 28) /* TagType:BYTES */ | 717,
+ ATTESTATION_ID_MODEL = TagType.BYTES | 717,
/**
* Tag::VENDOR_PATCHLEVEL specifies the vendor image security patch level with which the key may
@@ -806,7 +800,7 @@
*
* Must be hardware-enforced.
*/
- VENDOR_PATCHLEVEL = (3 << 28) /* TagType:UINT */ | 718,
+ VENDOR_PATCHLEVEL = TagType.UINT | 718,
/**
* Tag::BOOT_PATCHLEVEL specifies the boot image (kernel) security patch level with which the
@@ -826,7 +820,7 @@
*
* Must be hardware-enforced.
*/
- BOOT_PATCHLEVEL = (3 << 28) /* TagType:UINT */ | 719,
+ BOOT_PATCHLEVEL = TagType.UINT | 719,
/**
* DEVICE_UNIQUE_ATTESTATION is an argument to IKeyMintDevice::attested key generation/import
@@ -852,7 +846,7 @@
* IKeyMintDevice implementations that support device-unique attestation MUST add the
* DEVICE_UNIQUE_ATTESTATION tag to device-unique attestations.
*/
- DEVICE_UNIQUE_ATTESTATION = (7 << 28) /* TagType:BOOL */ | 720,
+ DEVICE_UNIQUE_ATTESTATION = TagType.BOOL | 720,
/**
* IDENTITY_CREDENTIAL_KEY is never used by IKeyMintDevice, is not a valid argument to key
@@ -860,7 +854,7 @@
* attestation. It is used in attestations produced by the IIdentityCredential HAL when that
* HAL attests to Credential Keys. IIdentityCredential produces KeyMint-style attestations.
*/
- IDENTITY_CREDENTIAL_KEY = (7 << 28) /* TagType:BOOL */ | 721,
+ IDENTITY_CREDENTIAL_KEY = TagType.BOOL | 721,
/**
* To prevent keys from being compromised if an attacker acquires read access to system / kernel
@@ -877,12 +871,13 @@
* ErrorCode::INVALID_OPERATION is returned when a key with Tag::STORAGE_KEY is provided to
* begin().
*/
- STORAGE_KEY = (7 << 28) /* TagType:BOOL */ | 722,
+ STORAGE_KEY = TagType.BOOL | 722,
/**
+ * OBSOLETE: Do not use. See IKeyMintOperation.updateAad instead.
* TODO: Delete when keystore1 is deleted.
*/
- ASSOCIATED_DATA = (9 << 28) /* TagType:BYTES */ | 1000,
+ ASSOCIATED_DATA = TagType.BYTES | 1000,
/**
* Tag::NONCE is used to provide or return a nonce or Initialization Vector (IV) for AES-GCM,
@@ -897,7 +892,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- NONCE = (9 << 28) /* TagType:BYTES */ | 1001,
+ NONCE = TagType.BYTES | 1001,
/**
* Tag::MAC_LENGTH provides the requested length of a MAC or GCM authentication tag, in bits.
@@ -908,7 +903,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- MAC_LENGTH = (3 << 28) /* TagType:UINT */ | 1003,
+ MAC_LENGTH = TagType.UINT | 1003,
/**
* Tag::RESET_SINCE_ID_ROTATION specifies whether the device has been factory reset since the
@@ -916,7 +911,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- RESET_SINCE_ID_ROTATION = (7 << 28) /* TagType:BOOL */ | 1004,
+ RESET_SINCE_ID_ROTATION = TagType.BOOL | 1004,
/**
* Tag::CONFIRMATION_TOKEN is used to deliver a cryptographic token proving that the user
@@ -925,7 +920,7 @@
*
* Must never appear in KeyCharacteristics.
*/
- CONFIRMATION_TOKEN = (9 << 28) /* TagType:BYTES */ | 1005,
+ CONFIRMATION_TOKEN = TagType.BYTES | 1005,
/**
* Tag::CERTIFICATE_SERIAL specifies the serial number to be assigned to the attestation
@@ -933,7 +928,7 @@
* keyMint in the attestation parameters during generateKey() and importKey(). If not provided,
* the serial shall default to 1.
*/
- CERTIFICATE_SERIAL = (8 << 28) /* TagType:BIGNUM */ | 1006,
+ CERTIFICATE_SERIAL = TagType.BIGNUM | 1006,
/**
* Tag::CERTIFICATE_SUBJECT the certificate subject. The value is a DER encoded X509 NAME.
@@ -941,7 +936,7 @@
* during generateKey and importKey. If not provided the subject name shall default to
* CN="Android Keystore Key".
*/
- CERTIFICATE_SUBJECT = (9 << 28) /* TagType:BYTES */ | 1007,
+ CERTIFICATE_SUBJECT = TagType.BYTES | 1007,
/**
* Tag::CERTIFICATE_NOT_BEFORE the beginning of the validity of the certificate in UNIX epoch
@@ -949,7 +944,7 @@
* certificates. ErrorCode::MISSING_NOT_BEFORE must be returned if this tag is not provided if
* this tag is not provided to generateKey or importKey.
*/
- CERTIFICATE_NOT_BEFORE = (6 << 28) /* TagType:DATE */ | 1008,
+ CERTIFICATE_NOT_BEFORE = TagType.DATE | 1008,
/**
* Tag::CERTIFICATE_NOT_AFTER the end of the validity of the certificate in UNIX epoch time in
@@ -957,7 +952,7 @@
* ErrorCode::MISSING_NOT_AFTER must be returned if this tag is not provided to generateKey or
* importKey.
*/
- CERTIFICATE_NOT_AFTER = (6 << 28) /* TagType:DATE */ | 1009,
+ CERTIFICATE_NOT_AFTER = TagType.DATE | 1009,
/**
* Tag::MAX_BOOT_LEVEL specifies a maximum boot level at which a key should function.
@@ -968,5 +963,5 @@
*
* Cannot be hardware enforced in this version.
*/
- MAX_BOOT_LEVEL = (3 << 28) /* TagType:UINT */ | 1010,
+ MAX_BOOT_LEVEL = TagType.UINT | 1010,
}
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index ae2becd..a312723 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -556,7 +556,7 @@
.EcdsaSigningKey(curve)
.AttestKey()
.SetDefaultValidity(),
- {} /* attestation siging key */, &attest_key.keyBlob,
+ {} /* attestation signing key */, &attest_key.keyBlob,
&attest_key_characteristics, &attest_key_cert_chain));
ASSERT_GT(attest_key_cert_chain.size(), 0);
@@ -640,7 +640,7 @@
ErrorCode::OK,
GenerateKey(
AuthorizationSetBuilder().EcdsaSigningKey(EcCurve::P_256).SetDefaultValidity(),
- {} /* attestation siging key */, &non_attest_key.keyBlob,
+ {} /* attestation signing key */, &non_attest_key.keyBlob,
&non_attest_key_characteristics, &non_attest_key_cert_chain));
ASSERT_GT(non_attest_key_cert_chain.size(), 0);
@@ -662,6 +662,124 @@
&attested_key_cert_chain));
}
+TEST_P(AttestKeyTest, EcdsaAttestationID) {
+ // Create attestation key.
+ AttestationKey attest_key;
+ vector<KeyCharacteristics> attest_key_characteristics;
+ vector<Certificate> attest_key_cert_chain;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .AttestKey()
+ .SetDefaultValidity(),
+ {} /* attestation signing key */, &attest_key.keyBlob,
+ &attest_key_characteristics, &attest_key_cert_chain));
+ attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
+ ASSERT_GT(attest_key_cert_chain.size(), 0);
+ EXPECT_EQ(attest_key_cert_chain.size(), 1);
+ EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain));
+
+ // Collection of valid attestation ID tags.
+ auto attestation_id_tags = AuthorizationSetBuilder();
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
+ "ro.product.manufacturer");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
+
+ for (const KeyParameter& tag : attestation_id_tags) {
+ SCOPED_TRACE(testing::Message() << "+tag-" << tag);
+ // Use attestation key to sign an ECDSA key, but include an attestation ID field.
+ AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .SetDefaultValidity();
+ builder.push_back(tag);
+ vector<uint8_t> attested_key_blob;
+ vector<KeyCharacteristics> attested_key_characteristics;
+ vector<Certificate> attested_key_cert_chain;
+ auto result = GenerateKey(builder, attest_key, &attested_key_blob,
+ &attested_key_characteristics, &attested_key_cert_chain);
+ if (result == ErrorCode::CANNOT_ATTEST_IDS) {
+ continue;
+ }
+
+ ASSERT_EQ(result, ErrorCode::OK);
+
+ CheckedDeleteKey(&attested_key_blob);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
+
+ // The attested key characteristics will not contain APPLICATION_ID_* fields (their
+ // spec definitions all have "Must never appear in KeyCharacteristics"), but the
+ // attestation extension should contain them, so make sure the extra tag is added.
+ hw_enforced.push_back(tag);
+
+ EXPECT_TRUE(verify_attestation_record("challenge", "foo", sw_enforced, hw_enforced,
+ SecLevel(),
+ attested_key_cert_chain[0].encodedCertificate));
+ }
+ CheckedDeleteKey(&attest_key.keyBlob);
+}
+
+TEST_P(AttestKeyTest, EcdsaAttestationMismatchID) {
+ // Create attestation key.
+ AttestationKey attest_key;
+ vector<KeyCharacteristics> attest_key_characteristics;
+ vector<Certificate> attest_key_cert_chain;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .AttestKey()
+ .SetDefaultValidity(),
+ {} /* attestation signing key */, &attest_key.keyBlob,
+ &attest_key_characteristics, &attest_key_cert_chain));
+ attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
+ ASSERT_GT(attest_key_cert_chain.size(), 0);
+ EXPECT_EQ(attest_key_cert_chain.size(), 1);
+ EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain));
+
+ // Collection of invalid attestation ID tags.
+ auto attestation_id_tags =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_ATTESTATION_ID_BRAND, "bogus-brand")
+ .Authorization(TAG_ATTESTATION_ID_DEVICE, "devious-device")
+ .Authorization(TAG_ATTESTATION_ID_PRODUCT, "punctured-product")
+ .Authorization(TAG_ATTESTATION_ID_SERIAL, "suspicious-serial")
+ .Authorization(TAG_ATTESTATION_ID_IMEI, "invalid-imei")
+ .Authorization(TAG_ATTESTATION_ID_MEID, "mismatching-meid")
+ .Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "malformed-manufacturer")
+ .Authorization(TAG_ATTESTATION_ID_MODEL, "malicious-model");
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+
+ for (const KeyParameter& invalid_tag : attestation_id_tags) {
+ SCOPED_TRACE(testing::Message() << "+tag-" << invalid_tag);
+
+ // Use attestation key to sign an ECDSA key, but include an invalid
+ // attestation ID field.
+ AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .SetDefaultValidity();
+ builder.push_back(invalid_tag);
+ vector<uint8_t> attested_key_blob;
+ vector<KeyCharacteristics> attested_key_characteristics;
+ vector<Certificate> attested_key_cert_chain;
+ auto result = GenerateKey(builder, attest_key, &attested_key_blob,
+ &attested_key_characteristics, &attested_key_cert_chain);
+
+ ASSERT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG)
+ << "result = " << result;
+ }
+ CheckedDeleteKey(&attest_key.keyBlob);
+}
+
INSTANTIATE_KEYMINT_AIDL_TEST(AttestKeyTest);
} // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
index 732d9eb..a3ed3ad 100644
--- a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -29,7 +29,7 @@
protected:
void CheckUniqueAttestationResults(const vector<uint8_t>& key_blob,
const vector<KeyCharacteristics>& key_characteristics,
- const AuthorizationSet& hw_enforced, int key_size) {
+ const AuthorizationSet& hw_enforced) {
ASSERT_GT(cert_chain_.size(), 0);
if (KeyMintAidlTestBase::dump_Attestations) {
@@ -40,8 +40,6 @@
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
- EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size)) << "Key size missing";
-
// The device-unique attestation chain should contain exactly two certificates:
// * The leaf with the attestation extension.
// * A self-signed root, signed using the device-unique key.
@@ -136,17 +134,32 @@
ASSERT_EQ(ErrorCode::OK, result);
- AuthorizationSet hw_enforced = AuthorizationSetBuilder()
- .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .RsaSigningKey(2048, 65537)
- .Digest(Digest::SHA_2_256)
- .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
- .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
- .Authorization(TAG_OS_VERSION, os_version())
- .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+ AuthorizationSetBuilder hw_enforced =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::SHA_2_256)
+ .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
+ .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
+ .Authorization(TAG_OS_VERSION, os_version())
+ .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
- CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced, key_size);
+ // Any patchlevels attached to the key should also be present in the attestation extension.
+ AuthorizationSet auths;
+ for (const auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
+ if (vendor_pl) {
+ hw_enforced.Authorization(TAG_VENDOR_PATCHLEVEL, *vendor_pl);
+ }
+ auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
+ if (boot_pl) {
+ hw_enforced.Authorization(TAG_BOOT_PATCHLEVEL, *boot_pl);
+ }
+
+ CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced);
}
/*
@@ -160,11 +173,10 @@
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- int key_size = 256;
auto result = GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(256)
+ .EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_INCLUDE_UNIQUE_ID)
.AttestationChallenge("challenge")
@@ -176,17 +188,137 @@
if (result == ErrorCode::CANNOT_ATTEST_IDS) return;
ASSERT_EQ(ErrorCode::OK, result);
- AuthorizationSet hw_enforced = AuthorizationSetBuilder()
- .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(EcCurve::P_256)
- .Digest(Digest::SHA_2_256)
- .Authorization(TAG_EC_CURVE, EcCurve::P_256)
- .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
- .Authorization(TAG_OS_VERSION, os_version())
- .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+ AuthorizationSetBuilder hw_enforced =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+ .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
+ .Authorization(TAG_OS_VERSION, os_version())
+ .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+ // Any patchlevels attached to the key should also be present in the attestation extension.
+ AuthorizationSet auths;
+ for (const auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
+ if (vendor_pl) {
+ hw_enforced.Authorization(TAG_VENDOR_PATCHLEVEL, *vendor_pl);
+ }
+ auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
+ if (boot_pl) {
+ hw_enforced.Authorization(TAG_BOOT_PATCHLEVEL, *boot_pl);
+ }
- CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced, key_size);
+ CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced);
+}
+
+/*
+ * DeviceUniqueAttestationTest.EcdsaDeviceUniqueAttestationID
+ *
+ * Verifies that device unique attestation can include IDs that do match the
+ * local device.
+ */
+TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationID) {
+ if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+ // Collection of valid attestation ID tags.
+ auto attestation_id_tags = AuthorizationSetBuilder();
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
+ "ro.product.manufacturer");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+
+ for (const KeyParameter& tag : attestation_id_tags) {
+ SCOPED_TRACE(testing::Message() << "+tag-" << tag);
+ AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
+ builder.push_back(tag);
+ auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+
+ // It is optional for Strong box to support DeviceUniqueAttestation.
+ if (result == ErrorCode::CANNOT_ATTEST_IDS) return;
+ ASSERT_EQ(ErrorCode::OK, result);
+
+ AuthorizationSetBuilder hw_enforced =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+ .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
+ .Authorization(TAG_OS_VERSION, os_version())
+ .Authorization(TAG_OS_PATCHLEVEL, os_patch_level());
+ // Expect the specified tag to be present in the attestation extension.
+ hw_enforced.push_back(tag);
+ // Any patchlevels attached to the key should also be present in the attestation extension.
+ AuthorizationSet auths;
+ for (const auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ auto vendor_pl = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
+ if (vendor_pl) {
+ hw_enforced.Authorization(TAG_VENDOR_PATCHLEVEL, *vendor_pl);
+ }
+ auto boot_pl = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
+ if (boot_pl) {
+ hw_enforced.Authorization(TAG_BOOT_PATCHLEVEL, *boot_pl);
+ }
+ CheckUniqueAttestationResults(key_blob, key_characteristics, hw_enforced);
+ }
+}
+
+/*
+ * DeviceUniqueAttestationTest.EcdsaDeviceUniqueAttestationMismatchID
+ *
+ * Verifies that device unique attestation rejects attempts to attest to IDs that
+ * don't match the local device.
+ */
+TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationMismatchID) {
+ if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+ // Collection of invalid attestation ID tags.
+ auto attestation_id_tags =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_ATTESTATION_ID_BRAND, "bogus-brand")
+ .Authorization(TAG_ATTESTATION_ID_DEVICE, "devious-device")
+ .Authorization(TAG_ATTESTATION_ID_PRODUCT, "punctured-product")
+ .Authorization(TAG_ATTESTATION_ID_SERIAL, "suspicious-serial")
+ .Authorization(TAG_ATTESTATION_ID_IMEI, "invalid-imei")
+ .Authorization(TAG_ATTESTATION_ID_MEID, "mismatching-meid")
+ .Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "malformed-manufacturer")
+ .Authorization(TAG_ATTESTATION_ID_MODEL, "malicious-model");
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+
+ for (const KeyParameter& invalid_tag : attestation_id_tags) {
+ SCOPED_TRACE(testing::Message() << "+tag-" << invalid_tag);
+ AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_INCLUDE_UNIQUE_ID)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION);
+ // Add the tag that doesn't match the local device's real ID.
+ builder.push_back(invalid_tag);
+ auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+
+ ASSERT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG);
+ }
}
INSTANTIATE_KEYMINT_AIDL_TEST(DeviceUniqueAttestationTest);
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 44b8274..5359b3b 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -62,6 +62,9 @@
namespace {
+// Invalid value for a patchlevel (which is of form YYYYMMDD).
+const uint32_t kInvalidPatchlevel = 99998877;
+
// Overhead for PKCS#1 v1.5 signature padding of undigested messages. Digested messages have
// additional overhead, for the digest algorithmIdentifier required by PKCS#1.
const size_t kPkcs1UndigestedSignaturePaddingOverhead = 11;
@@ -126,10 +129,9 @@
// Attestations don't contain everything in key authorization lists, so we need to filter the key
// lists to produce the lists that we expect to match the attestations.
auto kTagsToFilter = {
- Tag::CREATION_DATETIME,
- Tag::EC_CURVE,
- Tag::HARDWARE_TYPE,
- Tag::INCLUDE_UNIQUE_ID,
+ Tag::CREATION_DATETIME,
+ Tag::HARDWARE_TYPE,
+ Tag::INCLUDE_UNIQUE_ID,
};
AuthorizationSet filtered_tags(const AuthorizationSet& set) {
@@ -163,6 +165,28 @@
bool KeyMintAidlTestBase::arm_deleteAllKeys = false;
bool KeyMintAidlTestBase::dump_Attestations = false;
+uint32_t KeyMintAidlTestBase::boot_patch_level(
+ const vector<KeyCharacteristics>& key_characteristics) {
+ // The boot patchlevel is not available as a property, but should be present
+ // in the key characteristics of any created key.
+ AuthorizationSet allAuths;
+ for (auto& entry : key_characteristics) {
+ allAuths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ auto patchlevel = allAuths.GetTagValue(TAG_BOOT_PATCHLEVEL);
+ if (patchlevel.has_value()) {
+ return patchlevel.value();
+ } else {
+ // No boot patchlevel is available. Return a value that won't match anything
+ // and so will trigger test failures.
+ return kInvalidPatchlevel;
+ }
+}
+
+uint32_t KeyMintAidlTestBase::boot_patch_level() {
+ return boot_patch_level(key_characteristics_);
+}
+
ErrorCode KeyMintAidlTestBase::GetReturnErrorCode(const Status& result) {
if (result.isOk()) return ErrorCode::OK;
@@ -998,16 +1022,7 @@
}
break;
case Algorithm::EC:
- switch (SecLevel()) {
- case SecurityLevel::SOFTWARE:
- case SecurityLevel::TRUSTED_ENVIRONMENT:
- return {224, 256, 384, 521};
- case SecurityLevel::STRONGBOX:
- return {256};
- default:
- ADD_FAILURE() << "Invalid security level " << uint32_t(SecLevel());
- break;
- }
+ ADD_FAILURE() << "EC keys must be specified by curve not size";
break;
case Algorithm::AES:
return {128, 256};
@@ -1123,9 +1138,11 @@
}
vector<EcCurve> KeyMintAidlTestBase::InvalidCurves() {
- if (SecLevel() == SecurityLevel::TRUSTED_ENVIRONMENT) return {};
- CHECK(SecLevel() == SecurityLevel::STRONGBOX);
- return {EcCurve::P_224, EcCurve::P_384, EcCurve::P_521};
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ return {EcCurve::P_224, EcCurve::P_384, EcCurve::P_521};
+ } else {
+ return {};
+ }
}
vector<Digest> KeyMintAidlTestBase::ValidDigests(bool withNone, bool withMD5) {
@@ -1293,9 +1310,9 @@
AuthorizationSet att_sw_enforced;
AuthorizationSet att_hw_enforced;
uint32_t att_attestation_version;
- uint32_t att_keymaster_version;
+ uint32_t att_keymint_version;
SecurityLevel att_attestation_security_level;
- SecurityLevel att_keymaster_security_level;
+ SecurityLevel att_keymint_security_level;
vector<uint8_t> att_challenge;
vector<uint8_t> att_unique_id;
vector<uint8_t> att_app_id;
@@ -1304,8 +1321,8 @@
attest_rec->length, //
&att_attestation_version, //
&att_attestation_security_level, //
- &att_keymaster_version, //
- &att_keymaster_security_level, //
+ &att_keymint_version, //
+ &att_keymint_security_level, //
&att_challenge, //
&att_sw_enforced, //
&att_hw_enforced, //
@@ -1324,14 +1341,14 @@
expected_sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, appId);
}
- EXPECT_EQ(att_keymaster_version, 100U);
- EXPECT_EQ(security_level, att_keymaster_security_level);
+ EXPECT_EQ(att_keymint_version, 100U);
+ EXPECT_EQ(security_level, att_keymint_security_level);
EXPECT_EQ(security_level, att_attestation_security_level);
char property_value[PROPERTY_VALUE_MAX] = {};
// TODO(b/136282179): When running under VTS-on-GSI the TEE-backed
- // keymaster implementation will report YYYYMM dates instead of YYYYMMDD
+ // keymint implementation will report YYYYMM dates instead of YYYYMMDD
// for the BOOT_PATCH_LEVEL.
if (avb_verification_enabled()) {
for (int i = 0; i < att_hw_enforced.size(); i++) {
@@ -1370,13 +1387,6 @@
EXPECT_TRUE(expected_hw_enforced.Contains(TAG_NO_AUTH_REQUIRED));
}
- // Alternatively this checks the opposite - a false boolean tag (one that isn't provided in
- // the authorization list during key generation) isn't being attested to in the certificate.
- EXPECT_FALSE(expected_sw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
- EXPECT_FALSE(att_sw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
- EXPECT_FALSE(expected_hw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
- EXPECT_FALSE(att_hw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
-
if (att_hw_enforced.Contains(TAG_ALGORITHM, Algorithm::EC)) {
// For ECDSA keys, either an EC_CURVE or a KEY_SIZE can be specified, but one must be.
EXPECT_TRUE(att_hw_enforced.Contains(TAG_EC_CURVE) ||
@@ -1442,9 +1452,7 @@
att_sw_enforced.Sort();
expected_sw_enforced.Sort();
- auto a = filtered_tags(expected_sw_enforced);
- auto b = filtered_tags(att_sw_enforced);
- EXPECT_EQ(a, b);
+ EXPECT_EQ(filtered_tags(expected_sw_enforced), filtered_tags(att_sw_enforced));
att_hw_enforced.Sort();
expected_hw_enforced.Sort();
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 4d31fa4..d592d36 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -21,6 +21,7 @@
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
+#include <android-base/properties.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <gtest/gtest.h>
@@ -75,6 +76,8 @@
uint32_t os_version() { return os_version_; }
uint32_t os_patch_level() { return os_patch_level_; }
uint32_t vendor_patch_level() { return vendor_patch_level_; }
+ uint32_t boot_patch_level(const vector<KeyCharacteristics>& key_characteristics);
+ uint32_t boot_patch_level();
ErrorCode GetReturnErrorCode(const Status& result);
@@ -252,7 +255,7 @@
/* ECDSA */
KeyData ecdsaKeyData;
AuthorizationSetBuilder ecdsaBuilder = AuthorizationSetBuilder()
- .EcdsaSigningKey(256)
+ .EcdsaSigningKey(EcCurve::P_256)
.Authorization(tagToTest)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -313,6 +316,16 @@
long challenge_;
};
+// If the given property is available, add it to the tag set under the given tag ID.
+template <Tag tag>
+void add_tag_from_prop(AuthorizationSetBuilder* tags, TypedTag<TagType::BYTES, tag> ttag,
+ const char* prop) {
+ std::string prop_value = ::android::base::GetProperty(prop, /* default= */ "");
+ if (!prop_value.empty()) {
+ tags->Authorization(ttag, prop_value.data(), prop_value.size());
+ }
+}
+
vector<uint8_t> build_serial_blob(const uint64_t serial_int);
void verify_subject(const X509* cert, const string& subject, bool self_signed);
void verify_serial(X509* cert, const uint64_t expected_serial);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 295be1a..d41d270 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -18,6 +18,8 @@
#include <cutils/log.h>
#include <signal.h>
+
+#include <algorithm>
#include <iostream>
#include <openssl/ec.h>
@@ -1362,11 +1364,11 @@
* have correct characteristics.
*/
TEST_P(NewKeyGenerationTest, Ecdsa) {
- for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+ for (auto curve : ValidCurves()) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(key_size)
+ .EcdsaSigningKey(curve)
.Digest(Digest::NONE)
.SetDefaultValidity(),
&key_blob, &key_characteristics));
@@ -1377,8 +1379,7 @@
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
- EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
- << "Key size " << key_size << "missing";
+ EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
CheckedDeleteKey(&key_blob);
}
@@ -1400,13 +1401,13 @@
uint64_t serial_int = 0xFFFFFFFFFFFFFFFF;
vector<uint8_t> serial_blob(build_serial_blob(serial_int));
- for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+ for (auto curve : ValidCurves()) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
ASSERT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(key_size)
+ .EcdsaSigningKey(curve)
.Digest(Digest::NONE)
.AttestationChallenge(challenge)
.AttestationApplicationId(app_id)
@@ -1421,8 +1422,7 @@
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
- EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
- << "Key size " << key_size << "missing";
+ EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
ASSERT_GT(cert_chain_.size(), 0);
@@ -1439,6 +1439,170 @@
}
/*
+ * NewKeyGenerationTest.EcdsaAttestationTags
+ *
+ * Verifies that creation of an attested ECDSA key includes various tags in the
+ * attestation extension.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAttestationTags) {
+ auto challenge = "hello";
+ auto app_id = "foo";
+ auto subject = "cert subj 2";
+ vector<uint8_t> subject_der(make_name_from_str(subject));
+ uint64_t serial_int = 0x1010;
+ vector<uint8_t> serial_blob(build_serial_blob(serial_int));
+ const AuthorizationSetBuilder base_builder =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity();
+
+ // Various tags that map to fields in the attestation extension ASN.1 schema.
+ auto extra_tags = AuthorizationSetBuilder()
+ .Authorization(TAG_ROLLBACK_RESISTANCE)
+ .Authorization(TAG_EARLY_BOOT_ONLY)
+ .Authorization(TAG_ACTIVE_DATETIME, 1619621648000)
+ .Authorization(TAG_ORIGINATION_EXPIRE_DATETIME, 1619621648000)
+ .Authorization(TAG_USAGE_EXPIRE_DATETIME, 1619621999000)
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 42)
+ .Authorization(TAG_AUTH_TIMEOUT, 100000)
+ .Authorization(TAG_ALLOW_WHILE_ON_BODY)
+ .Authorization(TAG_TRUSTED_USER_PRESENCE_REQUIRED)
+ .Authorization(TAG_TRUSTED_CONFIRMATION_REQUIRED)
+ .Authorization(TAG_UNLOCKED_DEVICE_REQUIRED)
+ .Authorization(TAG_CREATION_DATETIME, 1619621648000);
+ for (const KeyParameter& tag : extra_tags) {
+ SCOPED_TRACE(testing::Message() << "tag-" << tag);
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ AuthorizationSetBuilder builder = base_builder;
+ builder.push_back(tag);
+ auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+ if (result == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE &&
+ tag.tag == TAG_ROLLBACK_RESISTANCE) {
+ continue;
+ }
+ if (result == ErrorCode::UNSUPPORTED_TAG &&
+ (tag.tag == TAG_ALLOW_WHILE_ON_BODY || tag.tag == TAG_TRUSTED_USER_PRESENCE_REQUIRED)) {
+ // Optional tag not supported by this KeyMint implementation.
+ continue;
+ }
+ ASSERT_EQ(result, ErrorCode::OK);
+ ASSERT_GT(key_blob.size(), 0U);
+
+ EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+ ASSERT_GT(cert_chain_.size(), 0);
+ verify_subject_and_serial(cert_chain_[0], serial_int, subject, /* self_signed = */ false);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+ if (tag.tag != TAG_ATTESTATION_APPLICATION_ID) {
+ // Expect to find most of the extra tags in the key characteristics
+ // of the generated key (but not for ATTESTATION_APPLICATION_ID).
+ EXPECT_TRUE(hw_enforced.Contains(tag.tag) || sw_enforced.Contains(tag.tag))
+ << tag << " not in hw:" << hw_enforced << " nor sw:" << sw_enforced;
+ }
+
+ // Verifying the attestation record will check for the specific tag because
+ // it's included in the authorizations.
+ EXPECT_TRUE(verify_attestation_record(challenge, app_id, sw_enforced, hw_enforced,
+ SecLevel(), cert_chain_[0].encodedCertificate));
+
+ CheckedDeleteKey(&key_blob);
+ }
+
+ // Device attestation IDs should be rejected for normal attestation requests; these fields
+ // are only used for device unique attestation.
+ auto invalid_tags = AuthorizationSetBuilder()
+ .Authorization(TAG_ATTESTATION_ID_BRAND, "brand")
+ .Authorization(TAG_ATTESTATION_ID_DEVICE, "device")
+ .Authorization(TAG_ATTESTATION_ID_PRODUCT, "product")
+ .Authorization(TAG_ATTESTATION_ID_SERIAL, "serial")
+ .Authorization(TAG_ATTESTATION_ID_IMEI, "imei")
+ .Authorization(TAG_ATTESTATION_ID_MEID, "meid")
+ .Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "manufacturer")
+ .Authorization(TAG_ATTESTATION_ID_MODEL, "model");
+ for (const KeyParameter& tag : invalid_tags) {
+ SCOPED_TRACE(testing::Message() << "tag-" << tag);
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ AuthorizationSetBuilder builder =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity();
+ builder.push_back(tag);
+ ASSERT_EQ(ErrorCode::CANNOT_ATTEST_IDS,
+ GenerateKey(builder, &key_blob, &key_characteristics));
+ }
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaAttestationTagNoApplicationId
+ *
+ * Verifies that creation of an attested ECDSA key does not include APPLICATION_ID.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAttestationTagNoApplicationId) {
+ auto challenge = "hello";
+ auto attest_app_id = "foo";
+ auto subject = "cert subj 2";
+ vector<uint8_t> subject_der(make_name_from_str(subject));
+ uint64_t serial_int = 0x1010;
+ vector<uint8_t> serial_blob(build_serial_blob(serial_int));
+
+ // Earlier versions of the attestation extension schema included a slot:
+ // applicationId [601] EXPLICIT OCTET_STRING OPTIONAL,
+ // This should never have been included, and should never be filled in.
+ // Generate an attested key that include APPLICATION_ID and APPLICATION_DATA,
+ // to confirm that this field never makes it into the attestation extension.
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(attest_app_id)
+ .Authorization(TAG_APPLICATION_ID, "client_id")
+ .Authorization(TAG_APPLICATION_DATA, "appdata")
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ ASSERT_EQ(result, ErrorCode::OK);
+ ASSERT_GT(key_blob.size(), 0U);
+
+ EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+ ASSERT_GT(cert_chain_.size(), 0);
+ verify_subject_and_serial(cert_chain_[0], serial_int, subject, /* self_signed = */ false);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+ EXPECT_TRUE(verify_attestation_record(challenge, attest_app_id, sw_enforced, hw_enforced,
+ SecLevel(), cert_chain_[0].encodedCertificate));
+
+ // Check that the app id is not in the cert.
+ string app_id = "clientid";
+ std::vector<uint8_t> needle(reinterpret_cast<const uint8_t*>(app_id.data()),
+ reinterpret_cast<const uint8_t*>(app_id.data()) + app_id.size());
+ ASSERT_EQ(std::search(cert_chain_[0].encodedCertificate.begin(),
+ cert_chain_[0].encodedCertificate.end(), needle.begin(), needle.end()),
+ cert_chain_[0].encodedCertificate.end());
+
+ CheckedDeleteKey(&key_blob);
+}
+
+/*
* NewKeyGenerationTest.EcdsaSelfSignAttestation
*
* Verifies that if no challenge is provided to an Ecdsa key generation, then
@@ -1451,12 +1615,12 @@
uint64_t serial_int = 0x123456FFF1234;
vector<uint8_t> serial_blob(build_serial_blob(serial_int));
- for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+ for (auto curve : ValidCurves()) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
ASSERT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(key_size)
+ .EcdsaSigningKey(curve)
.Digest(Digest::NONE)
.Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
.Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
@@ -1469,8 +1633,7 @@
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
- EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
- << "Key size " << key_size << "missing";
+ EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
verify_subject_and_serial(cert_chain_[0], serial_int, subject, false);
@@ -1512,11 +1675,11 @@
TEST_P(NewKeyGenerationTest, EcdsaIgnoreAppId) {
auto app_id = "foo";
- for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+ for (auto curve : ValidCurves()) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(key_size)
+ .EcdsaSigningKey(curve)
.Digest(Digest::NONE)
.AttestationApplicationId(app_id)
.SetDefaultValidity(),
@@ -1529,8 +1692,7 @@
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
- EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
- << "Key size " << key_size << "missing";
+ EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
ASSERT_EQ(cert_chain_.size(), 1);
@@ -1552,7 +1714,6 @@
*/
TEST_P(NewKeyGenerationTest, AttestationApplicationIDLengthProperlyEncoded) {
auto challenge = "hello";
- auto key_size = 256;
std::vector<uint32_t> app_id_lengths{143, 258};
for (uint32_t length : app_id_lengths) {
@@ -1561,7 +1722,7 @@
vector<KeyCharacteristics> key_characteristics;
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(key_size)
+ .EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::NONE)
.AttestationChallenge(challenge)
.AttestationApplicationId(app_id)
@@ -1574,8 +1735,7 @@
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
- EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
- << "Key size " << key_size << "missing";
+ EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, EcCurve::P_256)) << "Curve P256 missing";
EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
ASSERT_GT(cert_chain_.size(), 0);
@@ -1597,11 +1757,11 @@
* resulting keys have correct characteristics.
*/
TEST_P(NewKeyGenerationTest, LimitedUsageEcdsa) {
- for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+ for (auto curve : ValidCurves()) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(key_size)
+ .EcdsaSigningKey(curve)
.Digest(Digest::NONE)
.Authorization(TAG_USAGE_COUNT_LIMIT, 1)
.SetDefaultValidity(),
@@ -1614,8 +1774,7 @@
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
- EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
- << "Key size " << key_size << "missing";
+ EXPECT_TRUE(crypto_params.Contains(TAG_EC_CURVE, curve)) << "Curve " << curve << "missing";
// Check the usage count limit tag appears in the authorizations.
AuthorizationSet auths;
@@ -1632,7 +1791,7 @@
/*
* NewKeyGenerationTest.EcdsaDefaultSize
*
- * Verifies that failing to specify a key size for EC key generation returns
+ * Verifies that failing to specify a curve for EC key generation returns
* UNSUPPORTED_KEY_SIZE.
*/
TEST_P(NewKeyGenerationTest, EcdsaDefaultSize) {
@@ -1651,20 +1810,23 @@
* UNSUPPORTED_KEY_SIZE.
*/
TEST_P(NewKeyGenerationTest, EcdsaInvalidSize) {
- for (auto key_size : InvalidKeySizes(Algorithm::EC)) {
+ for (auto curve : InvalidCurves()) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE, GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(key_size)
+ .EcdsaSigningKey(curve)
.Digest(Digest::NONE)
.SetDefaultValidity(),
&key_blob, &key_characteristics));
}
- ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE, GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(190)
- .Digest(Digest::NONE)
- .SetDefaultValidity()));
+ ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
+ GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_ALGORITHM, Algorithm::EC)
+ .Authorization(TAG_KEY_SIZE, 190)
+ .SigningKey()
+ .Digest(Digest::NONE)
+ .SetDefaultValidity()));
}
/*
@@ -1676,29 +1838,13 @@
TEST_P(NewKeyGenerationTest, EcdsaMismatchKeySize) {
if (SecLevel() == SecurityLevel::STRONGBOX) return;
- ASSERT_EQ(ErrorCode::INVALID_ARGUMENT,
- GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(224)
- .Authorization(TAG_EC_CURVE, EcCurve::P_256)
- .Digest(Digest::NONE)
- .SetDefaultValidity()));
-}
-
-/*
- * NewKeyGenerationTest.EcdsaAllValidSizes
- *
- * Verifies that keymint supports all required EC key sizes.
- */
-TEST_P(NewKeyGenerationTest, EcdsaAllValidSizes) {
- auto valid_sizes = ValidKeySizes(Algorithm::EC);
- for (size_t size : valid_sizes) {
- EXPECT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(size)
- .Digest(Digest::NONE)
- .SetDefaultValidity()))
- << "Failed to generate size: " << size;
- CheckedDeleteKey();
- }
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_KEY_SIZE, 224)
+ .Authorization(TAG_EC_CURVE, EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .SetDefaultValidity());
+ ASSERT_TRUE(result == ErrorCode::INVALID_ARGUMENT ||
+ result == ErrorCode::UNSUPPORTED_ALGORITHM);
}
/*
@@ -2471,31 +2617,6 @@
}
/*
- * SigningOperationsTest.EcdsaAllSizesAndHashes
- *
- * Verifies that ECDSA operations succeed with all possible key sizes and hashes.
- */
-TEST_P(SigningOperationsTest, EcdsaAllSizesAndHashes) {
- for (auto key_size : ValidKeySizes(Algorithm::EC)) {
- for (auto digest : ValidDigests(false /* withNone */, false /* withMD5 */)) {
- ErrorCode error = GenerateKey(AuthorizationSetBuilder()
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(key_size)
- .Digest(digest)
- .SetDefaultValidity());
- EXPECT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with size " << key_size
- << " and digest " << digest;
- if (error != ErrorCode::OK) continue;
-
- string message(1024, 'a');
- if (digest == Digest::NONE) message.resize(key_size / 8);
- SignMessage(message, AuthorizationSetBuilder().Digest(digest));
- CheckedDeleteKey();
- }
- }
-}
-
-/*
* SigningOperationsTest.EcdsaAllDigestsAndCurves
*
* Verifies ECDSA signature/verification for all digests and curves.
@@ -2560,7 +2681,7 @@
TEST_P(SigningOperationsTest, EcdsaNoDigestHugeData) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(256)
+ .EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::NONE)
.SetDefaultValidity()));
string message(1 * 1024, 'a');
@@ -2575,7 +2696,7 @@
TEST_P(SigningOperationsTest, EcUseRequiresCorrectAppIdAppData) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(256)
+ .EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::NONE)
.Authorization(TAG_APPLICATION_ID, "clientid")
.Authorization(TAG_APPLICATION_DATA, "appdata")
@@ -2612,7 +2733,7 @@
TEST_P(SigningOperationsTest, EcdsaIncompatibleDigest) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(256)
+ .EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::NONE)
.Digest(Digest::SHA1)
.SetDefaultValidity()));
@@ -3000,13 +3121,12 @@
TEST_P(ImportKeyTest, EcdsaSuccess) {
ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(256)
+ .EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::SHA_2_256)
.SetDefaultValidity(),
KeyFormat::PKCS8, ec_256_key));
CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
- CheckCryptoParam(TAG_KEY_SIZE, 256U);
CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256);
@@ -3027,13 +3147,12 @@
TEST_P(ImportKeyTest, EcdsaP256RFC5915Success) {
ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(256)
+ .EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::SHA_2_256)
.SetDefaultValidity(),
KeyFormat::PKCS8, ec_256_key_rfc5915));
CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
- CheckCryptoParam(TAG_KEY_SIZE, 256U);
CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256);
@@ -3053,13 +3172,12 @@
TEST_P(ImportKeyTest, EcdsaP256SEC1Success) {
ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(256)
+ .EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::SHA_2_256)
.SetDefaultValidity(),
KeyFormat::PKCS8, ec_256_key_sec1));
CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
- CheckCryptoParam(TAG_KEY_SIZE, 256U);
CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256);
@@ -3080,13 +3198,12 @@
if (SecLevel() == SecurityLevel::STRONGBOX) return;
ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(521)
+ .EcdsaSigningKey(EcCurve::P_521)
.Digest(Digest::SHA_2_256)
.SetDefaultValidity(),
KeyFormat::PKCS8, ec_521_key));
CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
- CheckCryptoParam(TAG_KEY_SIZE, 521U);
CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_521);
CheckOrigin();
@@ -3098,21 +3215,6 @@
}
/*
- * ImportKeyTest.EcdsaSizeMismatch
- *
- * Verifies that importing an ECDSA key pair with a size that doesn't match the key fails in the
- * correct way.
- */
-TEST_P(ImportKeyTest, EcdsaSizeMismatch) {
- ASSERT_EQ(ErrorCode::IMPORT_PARAMETER_MISMATCH,
- ImportKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(224 /* Doesn't match key */)
- .Digest(Digest::NONE)
- .SetDefaultValidity(),
- KeyFormat::PKCS8, ec_256_key));
-}
-
-/*
* ImportKeyTest.EcdsaCurveMismatch
*
* Verifies that importing an ECDSA key pair with a curve that doesn't match the key fails in
@@ -3975,7 +4077,7 @@
TEST_P(EncryptionOperationsTest, EcdsaEncrypt) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(256)
+ .EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::NONE)
.SetDefaultValidity()));
auto params = AuthorizationSetBuilder().Digest(Digest::NONE);
@@ -6418,7 +6520,7 @@
ASSERT_EQ(ErrorCode::EARLY_BOOT_ENDED, ImportKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.Authorization(TAG_EARLY_BOOT_ONLY)
- .EcdsaSigningKey(256)
+ .EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::SHA_2_256)
.SetDefaultValidity(),
KeyFormat::PKCS8, ec_256_key));
diff --git a/security/keymint/support/keymint_utils.cpp b/security/keymint/support/keymint_utils.cpp
index 2dbdfa8..1e0733f 100644
--- a/security/keymint/support/keymint_utils.cpp
+++ b/security/keymint/support/keymint_utils.cpp
@@ -32,10 +32,11 @@
constexpr char kPlatformPatchlevelProp[] = "ro.build.version.security_patch";
constexpr char kVendorPatchlevelProp[] = "ro.vendor.build.security_patch";
-constexpr char kPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-[0-9]{2}$";
+constexpr char kPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-([0-9]{2})$";
constexpr size_t kYearMatch = 1;
constexpr size_t kMonthMatch = 2;
-constexpr size_t kPatchlevelMatchCount = kMonthMatch + 1;
+constexpr size_t kDayMatch = 3;
+constexpr size_t kPatchlevelMatchCount = kDayMatch + 1;
uint32_t match_to_uint32(const char* expression, const regmatch_t& match) {
if (match.rm_so == -1) return 0;
@@ -53,8 +54,6 @@
return prop_value;
}
-} // anonymous namespace
-
uint32_t getOsVersion(const char* version_str) {
regex_t regex;
if (regcomp(®ex, kPlatformVersionRegex, REG_EXTENDED)) {
@@ -76,12 +75,9 @@
return (major * 100 + minor) * 100 + subminor;
}
-uint32_t getOsVersion() {
- std::string version = wait_and_get_property(kPlatformVersionProp);
- return getOsVersion(version.c_str());
-}
+enum class PatchlevelOutput { kYearMonthDay, kYearMonth };
-uint32_t getPatchlevel(const char* patchlevel_str) {
+uint32_t getPatchlevel(const char* patchlevel_str, PatchlevelOutput detail) {
regex_t regex;
if (regcomp(®ex, kPatchlevelRegex, REG_EXTENDED) != 0) {
return 0;
@@ -100,17 +96,35 @@
if (month < 1 || month > 12) {
return 0;
}
- return year * 100 + month;
+
+ switch (detail) {
+ case PatchlevelOutput::kYearMonthDay: {
+ uint32_t day = match_to_uint32(patchlevel_str, matches[kDayMatch]);
+ if (day < 1 || day > 31) {
+ return 0;
+ }
+ return year * 10000 + month * 100 + day;
+ }
+ case PatchlevelOutput::kYearMonth:
+ return year * 100 + month;
+ }
+}
+
+} // anonymous namespace
+
+uint32_t getOsVersion() {
+ std::string version = wait_and_get_property(kPlatformVersionProp);
+ return getOsVersion(version.c_str());
}
uint32_t getOsPatchlevel() {
std::string patchlevel = wait_and_get_property(kPlatformPatchlevelProp);
- return getPatchlevel(patchlevel.c_str());
+ return getPatchlevel(patchlevel.c_str(), PatchlevelOutput::kYearMonth);
}
uint32_t getVendorPatchlevel() {
std::string patchlevel = wait_and_get_property(kVendorPatchlevelProp);
- return getPatchlevel(patchlevel.c_str());
+ return getPatchlevel(patchlevel.c_str(), PatchlevelOutput::kYearMonthDay);
}
} // namespace aidl::android::hardware::security::keymint
diff --git a/security/secureclock/aidl/vts/functional/SecureClockAidlTest.cpp b/security/secureclock/aidl/vts/functional/SecureClockAidlTest.cpp
index 31f4854..bf332d5 100644
--- a/security/secureclock/aidl/vts/functional/SecureClockAidlTest.cpp
+++ b/security/secureclock/aidl/vts/functional/SecureClockAidlTest.cpp
@@ -114,6 +114,7 @@
EXPECT_EQ(ErrorCode::OK, result1.error);
EXPECT_EQ(1U, result1.token.challenge);
EXPECT_GT(result1.token.timestamp.milliSeconds, 0U);
+ EXPECT_EQ(32U, result1.token.mac.size());
unsigned long time_to_sleep = 200;
sleep_ms(time_to_sleep);
@@ -123,6 +124,7 @@
EXPECT_EQ(ErrorCode::OK, result2.error);
EXPECT_EQ(2U, result2.token.challenge);
EXPECT_GT(result2.token.timestamp.milliSeconds, 0U);
+ EXPECT_EQ(32U, result2.token.mac.size());
auto host_time_delta = result2_time - result1_time;
@@ -153,6 +155,7 @@
EXPECT_EQ(ErrorCode::OK, result1.error);
EXPECT_EQ(0U, result1.token.challenge);
EXPECT_GT(result1.token.timestamp.milliSeconds, 0U);
+ EXPECT_EQ(32U, result1.token.mac.size());
unsigned long time_to_sleep = 200;
sleep_ms(time_to_sleep);
@@ -162,6 +165,7 @@
EXPECT_EQ(ErrorCode::OK, result2.error);
EXPECT_EQ(1U, result2.token.challenge);
EXPECT_GT(result2.token.timestamp.milliSeconds, 0U);
+ EXPECT_EQ(32U, result2.token.mac.size());
auto host_time_delta = result2_time - result1_time;
diff --git a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
index 8426120..919f882 100644
--- a/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
+++ b/security/sharedsecret/aidl/vts/functional/SharedSecretAidlTest.cpp
@@ -48,6 +48,9 @@
SharedSecretParameters params;
auto error = GetReturnErrorCode(sharedSecret->getSharedSecretParameters(¶ms));
EXPECT_EQ(ErrorCode::OK, error);
+ EXPECT_TRUE(params.seed.size() == 0 || params.seed.size() == 32);
+ EXPECT_TRUE(params.nonce.size() == 32);
+
GetParamsResult result;
result.tie() = std::tie(error, params);
return result;
@@ -234,6 +237,45 @@
}
}
+TEST_F(SharedSecretAidlTest, ComputeSharedSecretShortNonce) {
+ auto sharedSecrets = allSharedSecrets();
+ if (sharedSecrets.empty()) {
+ GTEST_SKIP() << "Skipping the test as no shared secret service is found.";
+ }
+ auto fixup_hmac = finally([&]() { computeAllSharedSecrets(getAllSharedSecretParameters()); });
+
+ auto params = getAllSharedSecretParameters();
+ ASSERT_EQ(sharedSecrets.size(), params.size())
+ << "One or more shared secret services failed to provide parameters.";
+
+ // All should be well in the normal case
+ auto responses = computeAllSharedSecrets(params);
+
+ ASSERT_GT(responses.size(), 0U);
+ vector<uint8_t> correct_response = responses[0].sharing_check;
+ verifyResponses(correct_response, responses);
+
+ // Pick a random param and shorten that nonce by one.
+ size_t param_to_tweak = rand() % params.size();
+ auto& to_tweak = params[param_to_tweak].nonce;
+ ASSERT_TRUE(to_tweak.size() == 32);
+ to_tweak.resize(31);
+
+ responses = computeAllSharedSecrets(params);
+ for (size_t i = 0; i < responses.size(); ++i) {
+ if (i == param_to_tweak) {
+ EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
+ << "Shared secret service that provided tweaked param should fail to compute "
+ "shared secret";
+ } else {
+ EXPECT_EQ(ErrorCode::OK, responses[i].error) << "Others should succeed";
+ EXPECT_NE(correct_response, responses[i].sharing_check)
+ << "Others should calculate a different shared secret, due to the tweaked "
+ "nonce.";
+ }
+ }
+}
+
TEST_F(SharedSecretAidlTest, ComputeSharedSecretCorruptSeed) {
auto sharedSecrets = allSharedSecrets();
if (sharedSecrets.empty()) {
@@ -275,6 +317,45 @@
}
}
}
+
+TEST_F(SharedSecretAidlTest, ComputeSharedSecretShortSeed) {
+ auto sharedSecrets = allSharedSecrets();
+ if (sharedSecrets.empty()) {
+ GTEST_SKIP() << "Skipping the test as no shared secret service is found.";
+ }
+ auto fixup_hmac = finally([&]() { computeAllSharedSecrets(getAllSharedSecretParameters()); });
+ auto params = getAllSharedSecretParameters();
+ ASSERT_EQ(sharedSecrets.size(), params.size())
+ << "One or more shared secret service failed to provide parameters.";
+
+ // All should be well in the normal case
+ auto responses = computeAllSharedSecrets(params);
+
+ ASSERT_GT(responses.size(), 0U);
+ vector<uint8_t> correct_response = responses[0].sharing_check;
+ verifyResponses(correct_response, responses);
+
+ // Pick a random param and modify the seed to be of (invalid) length 31.
+ auto param_to_tweak = rand() % params.size();
+ auto& to_tweak = params[param_to_tweak].seed;
+ ASSERT_TRUE(to_tweak.size() == 32 || to_tweak.size() == 0);
+ to_tweak.resize(31);
+
+ responses = computeAllSharedSecrets(params);
+ for (size_t i = 0; i < responses.size(); ++i) {
+ if (i == param_to_tweak) {
+ EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
+ << "Shared secret service that provided tweaked param should fail to compute "
+ "shared secret";
+ } else {
+ EXPECT_EQ(ErrorCode::OK, responses[i].error) << "Others should succeed";
+ EXPECT_NE(correct_response, responses[i].sharing_check)
+ << "Others should calculate a different shared secret, due to the tweaked "
+ "nonce.";
+ }
+ }
+}
+
} // namespace aidl::android::hardware::security::sharedsecret::test
int main(int argc, char** argv) {