Merge "Updating CDDL schemas to match the finalized spec."
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/bluetooth/audio/2.1/default/Android.bp b/bluetooth/audio/2.1/default/Android.bp
index 5c30f79..3000223 100644
--- a/bluetooth/audio/2.1/default/Android.bp
+++ b/bluetooth/audio/2.1/default/Android.bp
@@ -19,6 +19,7 @@
"A2dpSoftwareAudioProvider.cpp",
"HearingAidAudioProvider.cpp",
"LeAudioAudioProvider.cpp",
+ "LeAudioOffloadAudioProvider.cpp",
],
header_libs: ["libhardware_headers"],
shared_libs: [
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
index e1b1ac6..b0d171a 100644
--- a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
@@ -41,8 +41,12 @@
BluetoothAudioProvidersFactory::hearing_aid_provider_instance_;
LeAudioOutputAudioProvider
BluetoothAudioProvidersFactory::leaudio_output_provider_instance_;
+LeAudioOffloadOutputAudioProvider
+ BluetoothAudioProvidersFactory::leaudio_offload_output_provider_instance_;
LeAudioInputAudioProvider
BluetoothAudioProvidersFactory::leaudio_input_provider_instance_;
+LeAudioOffloadInputAudioProvider
+ BluetoothAudioProvidersFactory::leaudio_offload_input_provider_instance_;
Return<void> BluetoothAudioProvidersFactory::openProvider(
const V2_0::SessionType sessionType, openProvider_cb _hidl_cb) {
@@ -90,9 +94,15 @@
case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
provider = &leaudio_output_provider_instance_;
break;
+ case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+ provider = &leaudio_offload_output_provider_instance_;
+ break;
case SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
provider = &leaudio_input_provider_instance_;
break;
+ case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+ provider = &leaudio_offload_input_provider_instance_;
+ break;
default:
status = BluetoothAudioStatus::FAILURE;
}
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
index fd83694..f8f557e 100644
--- a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
@@ -23,6 +23,7 @@
#include "BluetoothAudioProvider.h"
#include "HearingAidAudioProvider.h"
#include "LeAudioAudioProvider.h"
+#include "LeAudioOffloadAudioProvider.h"
namespace android {
namespace hardware {
@@ -55,6 +56,8 @@
static HearingAidAudioProvider hearing_aid_provider_instance_;
static LeAudioOutputAudioProvider leaudio_output_provider_instance_;
static LeAudioInputAudioProvider leaudio_input_provider_instance_;
+ static LeAudioOffloadOutputAudioProvider leaudio_offload_output_provider_instance_;
+ static LeAudioOffloadInputAudioProvider leaudio_offload_input_provider_instance_;
};
extern "C" IBluetoothAudioProvidersFactory*
diff --git a/bluetooth/audio/2.1/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/2.1/default/LeAudioOffloadAudioProvider.cpp
new file mode 100644
index 0000000..c11bdad
--- /dev/null
+++ b/bluetooth/audio/2.1/default/LeAudioOffloadAudioProvider.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BTAudioProviderLeAudioOffload"
+
+#include "LeAudioOffloadAudioProvider.h"
+
+#include <android-base/logging.h>
+
+#include "BluetoothAudioSessionReport_2_1.h"
+#include "BluetoothAudioSupportedCodecsDB_2_1.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::bluetooth::audio::BluetoothAudioSessionReport_2_1;
+using ::android::hardware::Void;
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+LeAudioOffloadOutputAudioProvider::LeAudioOffloadOutputAudioProvider()
+ : LeAudioOffloadAudioProvider() {
+ session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+LeAudioOffloadInputAudioProvider::LeAudioOffloadInputAudioProvider()
+ : LeAudioOffloadAudioProvider() {
+ session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
+}
+
+LeAudioOffloadAudioProvider::LeAudioOffloadAudioProvider()
+ : BluetoothAudioProvider() {}
+
+bool LeAudioOffloadAudioProvider::isValid(const V2_0::SessionType& sessionType) {
+ LOG(ERROR) << __func__ << ", invalid session type for Offloaded Le Audio provider: "
+ << toString(sessionType);
+
+ return false;
+}
+
+bool LeAudioOffloadAudioProvider::isValid(const SessionType& sessionType) {
+ return (sessionType == session_type_);
+}
+
+Return<void> LeAudioOffloadAudioProvider::startSession_2_1(
+ const sp<V2_0::IBluetoothAudioPort>& hostIf,
+ const AudioConfiguration& audioConfig, startSession_cb _hidl_cb) {
+ /**
+ * Initialize the audio platform if audioConfiguration is supported.
+ * Save the IBluetoothAudioPort interface, so that it can be used
+ * later to send stream control commands to the HAL client, based on
+ * interaction with Audio framework.
+ */
+ if (audioConfig.getDiscriminator() !=
+ AudioConfiguration::hidl_discriminator::leAudioCodecConfig) {
+ LOG(WARNING) << __func__
+ << " - Invalid Audio Configuration=" << toString(audioConfig);
+ _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+ DataMQ::Descriptor());
+ return Void();
+ }
+
+ if (!android::bluetooth::audio::IsOffloadLeAudioConfigurationValid(session_type_,
+ audioConfig.leAudioCodecConfig())) {
+ LOG(WARNING) << __func__ << " - Unsupported LC3 Offloaded Configuration="
+ << toString(audioConfig.leAudioCodecConfig());
+ _hidl_cb(BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION,
+ DataMQ::Descriptor());
+ return Void();
+ }
+
+ return BluetoothAudioProvider::startSession_2_1(hostIf, audioConfig,
+ _hidl_cb);
+}
+
+Return<void> LeAudioOffloadAudioProvider::onSessionReady(startSession_cb _hidl_cb) {
+ BluetoothAudioSessionReport_2_1::OnSessionStarted(session_type_, stack_iface_,
+ nullptr, audio_config_);
+ _hidl_cb(BluetoothAudioStatus::SUCCESS, DataMQ::Descriptor());
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/audio/2.1/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/2.1/default/LeAudioOffloadAudioProvider.h
new file mode 100644
index 0000000..564e9a3
--- /dev/null
+++ b/bluetooth/audio/2.1/default/LeAudioOffloadAudioProvider.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/bluetooth/audio/2.1/types.h>
+
+#include "BluetoothAudioProvider.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+namespace V2_1 {
+namespace implementation {
+
+class LeAudioOffloadAudioProvider : public BluetoothAudioProvider {
+ public:
+ LeAudioOffloadAudioProvider();
+
+ bool isValid(const SessionType& sessionType) override;
+ bool isValid(const V2_0::SessionType& sessionType) override;
+
+ Return<void> startSession_2_1(const sp<V2_0::IBluetoothAudioPort>& hostIf,
+ const AudioConfiguration& audioConfig,
+ startSession_cb _hidl_cb) override;
+
+ private:
+ Return<void> onSessionReady(startSession_cb _hidl_cb) override;
+};
+
+class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {
+ public:
+ LeAudioOffloadOutputAudioProvider();
+};
+
+class LeAudioOffloadInputAudioProvider : public LeAudioOffloadAudioProvider {
+ public:
+ LeAudioOffloadInputAudioProvider();
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace audio
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h
index 4d7be21..95f7408 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h
@@ -35,7 +35,7 @@
std::shared_ptr<BluetoothAudioSession_2_1> session_ptr =
BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type);
if (session_ptr != nullptr) {
- return session_ptr->GetAudioSession()->IsSessionReady();
+ return session_ptr->IsSessionReady();
}
return false;
}
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
index 9d91196..c250ef1 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
@@ -60,6 +60,16 @@
}
}
+bool BluetoothAudioSession_2_1::IsSessionReady() {
+ if (session_type_2_1_ !=
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+ return audio_session->IsSessionReady();
+ }
+
+ std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
+ return audio_session->stack_iface_ != nullptr;
+}
+
std::shared_ptr<BluetoothAudioSession>
BluetoothAudioSession_2_1::GetAudioSession() {
return audio_session;
@@ -70,7 +80,7 @@
const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration
BluetoothAudioSession_2_1::GetAudioConfig() {
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
- if (audio_session->IsSessionReady()) {
+ if (IsSessionReady()) {
// If session is unknown it means it should be 2.0 type
if (session_type_2_1_ != SessionType_2_1::UNKNOWN)
return audio_config_2_1_;
@@ -110,20 +120,29 @@
SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
session_type_2_1_ ==
SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
- bool is_offload_session =
+ bool is_offload_a2dp_session =
(session_type_2_1_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+ bool is_offload_le_audio_session =
+ (session_type_2_1_ == SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ session_type_2_1_ == SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
auto audio_config_discriminator = audio_config.getDiscriminator();
bool is_software_audio_config =
(is_software_session &&
audio_config_discriminator ==
::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
hidl_discriminator::pcmConfig);
- bool is_offload_audio_config =
- (is_offload_session &&
+ bool is_a2dp_offload_audio_config =
+ (is_offload_a2dp_session &&
audio_config_discriminator ==
::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
hidl_discriminator::codecConfig);
- if (!is_software_audio_config && !is_offload_audio_config) {
+ bool is_le_audio_offload_audio_config =
+ (is_offload_le_audio_session &&
+ audio_config_discriminator ==
+ ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
+ hidl_discriminator::leAudioCodecConfig);
+ if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
+ !is_le_audio_offload_audio_config) {
return false;
}
audio_config_2_1_ = audio_config;
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
index 5a35153..db82c73 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
@@ -50,6 +50,10 @@
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
session_type);
+ // The function helps to check if this session is ready or not
+ // @return: true if the Bluetooth stack has started the specified session
+ bool IsSessionReady();
+
std::shared_ptr<BluetoothAudioSession> GetAudioSession();
// The report function is used to report that the Bluetooth stack has started
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.cpp b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.cpp
index 8b0b0f7..c90ce6d 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.cpp
@@ -122,6 +122,21 @@
return false;
}
+bool IsOffloadLeAudioConfigurationValid(
+ const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+ session_type,
+ const ::android::hardware::bluetooth::audio::V2_1::Lc3CodecConfiguration&) {
+
+ if (session_type != SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+ session_type != SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ return false;
+ }
+
+ //TODO: perform checks on le_audio_codec_config once we know supported parameters
+
+ return true;
+}
+
} // namespace audio
} // namespace bluetooth
} // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.h
index 746d9c0..a52636c 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_1.h
@@ -41,6 +41,11 @@
const ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration&
codec_config);
+bool IsOffloadLeAudioConfigurationValid(
+ const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+ session_type,
+ const ::android::hardware::bluetooth::audio::V2_1::Lc3CodecConfiguration&
+ le_audio_codec_config);
} // namespace audio
} // namespace bluetooth
} // namespace android
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index 362ab41..615fde0 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -496,10 +496,26 @@
* - program changes exactly to what was requested.
*/
TEST_P(BroadcastRadioHalTest, DabTune) {
+ Result halResult;
+ hidl_vec<DabTableEntry> config;
+ auto cb = [&](Result result, hidl_vec<DabTableEntry> configCb) {
+ halResult = result;
+ config = configCb;
+ };
+ auto hidlResult = mModule->getDabRegionConfig(cb);
+ ASSERT_TRUE(hidlResult.isOk());
+
+ if (halResult == Result::NOT_SUPPORTED) {
+ printSkipped("DAB not supported");
+ return;
+ }
+ ASSERT_EQ(Result::OK, halResult);
+ ASSERT_NE(config.size(), 0U);
+
ASSERT_TRUE(openSession());
ProgramSelector sel = {};
- uint64_t freq = 178352;
+ uint64_t freq = config[config.size() / 2].frequency;
sel.primaryId = make_identifier(IdentifierType::DAB_FREQUENCY,freq);
std::this_thread::sleep_for(gTuneWorkaround);
diff --git a/current.txt b/current.txt
index cd1446d..88b067d 100644
--- a/current.txt
+++ b/current.txt
@@ -836,4 +836,7 @@
ead4ec8713a2cb40906fe31ba793d21a6b1190143c446690d16a6ea686aa2fea android.hardware.tetheroffload.control@1.1::ITetheringOffloadCallback
e34b4c7bec5e032c14804707ca924dd6b99ed5ba139da7505fe7d698d0fe178f android.hardware.tetheroffload.control@1.1::types
+# ABI preserving changes to HALs during Android T
+62ace52d9c3ff1f60f94118557a2aaf0b953513e59dcd34d5f94ae28d4c7e780 android.hardware.fastboot@1.0::IFastboot
+
# There should be no more HIDL HALs - please use AIDL instead.
diff --git a/fastboot/1.0/IFastboot.hal b/fastboot/1.0/IFastboot.hal
index dce3ad7..b39061c 100644
--- a/fastboot/1.0/IFastboot.hal
+++ b/fastboot/1.0/IFastboot.hal
@@ -33,7 +33,7 @@
/**
* Executes a fastboot OEM command.
*
- * @param oemCmdArgs The oem command that is passed to the fastboot HAL.
+ * @param oemCmd The oem command that is passed to the fastboot HAL.
* @return result Returns the status SUCCESS if the operation is successful,
* INVALID_ARGUMENT for bad arguments,
* FAILURE_UNKNOWN for an invalid/unsupported command.
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/identity/aidl/default/common/WritableIdentityCredential.cpp b/identity/aidl/default/common/WritableIdentityCredential.cpp
index 25f129b..200ee61 100644
--- a/identity/aidl/default/common/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/common/WritableIdentityCredential.cpp
@@ -210,6 +210,15 @@
"numAccessControlProfileRemaining_ is not zero"));
}
+ // Ensure passed-in profile ids reference valid access control profiles
+ for (const int32_t id : accessControlProfileIds) {
+ if (accessControlProfileIds_.find(id) == accessControlProfileIds_.end()) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_INVALID_DATA,
+ "An id in accessControlProfileIds references non-existing ACP"));
+ }
+ }
+
if (remainingEntryCounts_.size() == 0) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_INVALID_DATA, "No more namespaces to add to"));
diff --git a/identity/aidl/vts/DeleteCredentialTests.cpp b/identity/aidl/vts/DeleteCredentialTests.cpp
index d3addf4..7627c9c 100644
--- a/identity/aidl/vts/DeleteCredentialTests.cpp
+++ b/identity/aidl/vts/DeleteCredentialTests.cpp
@@ -102,7 +102,7 @@
ASSERT_TRUE(wc->addAccessControlProfile(1, {}, false, 0, 0, &sacp).isOk());
// Single entry - don't care about the returned encrypted data
- ASSERT_TRUE(wc->beginAddEntry({0}, "ns", "Some Data", 1).isOk());
+ ASSERT_TRUE(wc->beginAddEntry({1}, "ns", "Some Data", 1).isOk());
vector<uint8_t> encryptedData;
ASSERT_TRUE(wc->addEntryValue({9}, &encryptedData).isOk());
diff --git a/identity/aidl/vts/ProveOwnershipTests.cpp b/identity/aidl/vts/ProveOwnershipTests.cpp
index fa0e293..c622193 100644
--- a/identity/aidl/vts/ProveOwnershipTests.cpp
+++ b/identity/aidl/vts/ProveOwnershipTests.cpp
@@ -102,7 +102,7 @@
ASSERT_TRUE(wc->addAccessControlProfile(1, {}, false, 0, 0, &sacp).isOk());
// Single entry - don't care about the returned encrypted data
- ASSERT_TRUE(wc->beginAddEntry({0}, "ns", "Some Data", 1).isOk());
+ ASSERT_TRUE(wc->beginAddEntry({1}, "ns", "Some Data", 1).isOk());
vector<uint8_t> encryptedData;
ASSERT_TRUE(wc->addEntryValue({9}, &encryptedData).isOk());
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index 4547624..7f4674d 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -644,7 +644,7 @@
// the VTS tests. Of course, this is a pretend-only game since hopefully no
// relying party is ever going to trust our batch key and those keys above
// it.
- ::keymaster::PureSoftKeymasterContext context(::keymaster::KmVersion::KEYMASTER_4_1,
+ ::keymaster::PureSoftKeymasterContext context(::keymaster::KmVersion::KEYMINT_1,
KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
keymaster_error_t error;
@@ -682,10 +682,9 @@
i2d_X509_NAME(subjectName.get(), &subjectPtr);
- uint64_t nowMilliSeconds = time(nullptr) * 1000;
::keymaster::AuthorizationSet auth_set(
::keymaster::AuthorizationSetBuilder()
- .Authorization(::keymaster::TAG_CERTIFICATE_NOT_BEFORE, nowMilliSeconds)
+ .Authorization(::keymaster::TAG_CERTIFICATE_NOT_BEFORE, activeTimeMilliSeconds)
.Authorization(::keymaster::TAG_CERTIFICATE_NOT_AFTER, expireTimeMilliSeconds)
.Authorization(::keymaster::TAG_ATTESTATION_CHALLENGE, challenge.data(),
challenge.size())
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/Burst.cpp b/neuralnetworks/aidl/utils/src/Burst.cpp
index 87cd0e4..800ac32 100644
--- a/neuralnetworks/aidl/utils/src/Burst.cpp
+++ b/neuralnetworks/aidl/utils/src/Burst.cpp
@@ -62,7 +62,7 @@
private:
const std::shared_ptr<const Burst> kBurst;
const Request kRequest;
- const std::vector<int64_t>& kMemoryIdentifierTokens;
+ const std::vector<int64_t> kMemoryIdentifierTokens;
const bool kMeasure;
const int64_t kLoopTimeoutDuration;
const hal::utils::RequestRelocation kRelocation;
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/aidl/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
index e0b529f..94ce5c1 100644
--- a/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/CompilationCachingTests.cpp
@@ -357,16 +357,40 @@
return false;
}
+ // If fallbackModel is not provided, call prepareModelFromCache.
+ // If fallbackModel is provided, and prepareModelFromCache returns GENERAL_FAILURE,
+ // then prepareModel(fallbackModel) will be called.
+ // This replicates the behaviour of the runtime when loading a model from cache.
+ // NNAPI Shim depends on this behaviour and may try to load the model from cache in
+ // prepareModel (shim needs model information when loading from cache).
void prepareModelFromCache(const std::vector<ndk::ScopedFileDescriptor>& modelCache,
const std::vector<ndk::ScopedFileDescriptor>& dataCache,
- std::shared_ptr<IPreparedModel>* preparedModel,
- ErrorStatus* status) {
+ std::shared_ptr<IPreparedModel>* preparedModel, ErrorStatus* status,
+ const Model* fallbackModel = nullptr) {
// Launch prepare model from cache.
std::shared_ptr<PreparedModelCallback> preparedModelCallback =
ndk::SharedRefBase::make<PreparedModelCallback>();
std::vector<uint8_t> cacheToken(std::begin(mToken), std::end(mToken));
- const auto prepareLaunchStatus = kDevice->prepareModelFromCache(
+ auto prepareLaunchStatus = kDevice->prepareModelFromCache(
kNoDeadline, modelCache, dataCache, cacheToken, preparedModelCallback);
+
+ // The shim does not support prepareModelFromCache() properly, but it
+ // will still attempt to create a model from cache when modelCache or
+ // dataCache is provided in prepareModel(). Instead of failing straight
+ // away, we try to utilize that other code path when fallbackModel is
+ // set. Note that we cannot verify whether the returned model was
+ // actually prepared from cache in that case.
+ if (!prepareLaunchStatus.isOk() &&
+ prepareLaunchStatus.getExceptionCode() == EX_SERVICE_SPECIFIC &&
+ static_cast<ErrorStatus>(prepareLaunchStatus.getServiceSpecificError()) ==
+ ErrorStatus::GENERAL_FAILURE &&
+ mIsCachingSupported && fallbackModel != nullptr) {
+ preparedModelCallback = ndk::SharedRefBase::make<PreparedModelCallback>();
+ prepareLaunchStatus = kDevice->prepareModel(
+ *fallbackModel, ExecutionPreference::FAST_SINGLE_ANSWER, kDefaultPriority,
+ kNoDeadline, modelCache, dataCache, cacheToken, preparedModelCallback);
+ }
+
ASSERT_TRUE(prepareLaunchStatus.isOk() ||
prepareLaunchStatus.getExceptionCode() == EX_SERVICE_SPECIFIC)
<< "prepareLaunchStatus: " << prepareLaunchStatus.getDescription();
@@ -382,6 +406,42 @@
*preparedModel = preparedModelCallback->getPreparedModel();
}
+ // Replicate behaviour of runtime when loading model from cache.
+ // Test if prepareModelFromCache behaves correctly when faced with bad
+ // arguments. If prepareModelFromCache is not supported (GENERAL_FAILURE),
+ // it attempts to call prepareModel with same arguments, which is expected either
+ // to not support the model (GENERAL_FAILURE) or return a valid model.
+ void verifyModelPreparationBehaviour(const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+ const std::vector<ndk::ScopedFileDescriptor>& dataCache,
+ const Model* model, const TestModel& testModel) {
+ std::shared_ptr<IPreparedModel> preparedModel;
+ ErrorStatus status;
+
+ // Verify that prepareModelFromCache fails either due to bad
+ // arguments (INVALID_ARGUMENT) or GENERAL_FAILURE if not supported.
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status,
+ /*fallbackModel=*/nullptr);
+ if (status != ErrorStatus::INVALID_ARGUMENT) {
+ ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+ }
+ ASSERT_EQ(preparedModel, nullptr);
+
+ // If caching is not supported, attempt calling prepareModel.
+ if (status == ErrorStatus::GENERAL_FAILURE) {
+ // Fallback with prepareModel should succeed regardless of cache files
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status,
+ /*fallbackModel=*/model);
+ // Unless caching is not supported?
+ if (status != ErrorStatus::GENERAL_FAILURE) {
+ // But if it is, we should see a valid model.
+ ASSERT_EQ(status, ErrorStatus::NONE);
+ ASSERT_NE(preparedModel, nullptr);
+ EvaluatePreparedModel(kDevice, preparedModel, testModel,
+ /*testKind=*/TestKind::GENERAL);
+ }
+ }
+ }
+
// Absolute path to the temporary cache directory.
std::string mCacheDir;
@@ -397,7 +457,7 @@
uint8_t mToken[static_cast<uint32_t>(IDevice::BYTE_SIZE_OF_CACHE_TOKEN)] = {};
uint32_t mNumModelCache;
uint32_t mNumDataCache;
- uint32_t mIsCachingSupported;
+ bool mIsCachingSupported;
const std::shared_ptr<IDevice> kDevice;
// The primary data type of the testModel.
@@ -438,7 +498,8 @@
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
createCacheFds(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheFds(mDataCache, AccessMode::READ_WRITE, &dataCache);
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status,
+ /*fallbackModel=*/&model);
if (!mIsCachingSupported) {
ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
ASSERT_EQ(preparedModel, nullptr);
@@ -498,7 +559,8 @@
for (uint32_t i = 0; i < dataCache.size(); i++) {
ASSERT_GE(read(dataCache[i].get(), &placeholderByte, 1), 0);
}
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status,
+ /*fallbackModel=*/&model);
if (!mIsCachingSupported) {
ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
ASSERT_EQ(preparedModel, nullptr);
@@ -536,13 +598,7 @@
// Execute and verify results.
EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
// Check if prepareModelFromCache fails.
- preparedModel = nullptr;
- ErrorStatus status;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::INVALID_ARGUMENT) {
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
- ASSERT_EQ(preparedModel, nullptr);
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Test with number of model cache files smaller than mNumModelCache.
@@ -560,13 +616,7 @@
// Execute and verify results.
EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
// Check if prepareModelFromCache fails.
- preparedModel = nullptr;
- ErrorStatus status;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::INVALID_ARGUMENT) {
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
- ASSERT_EQ(preparedModel, nullptr);
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Test with number of data cache files greater than mNumDataCache.
@@ -583,13 +633,7 @@
// Execute and verify results.
EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
// Check if prepareModelFromCache fails.
- preparedModel = nullptr;
- ErrorStatus status;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::INVALID_ARGUMENT) {
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
- ASSERT_EQ(preparedModel, nullptr);
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Test with number of data cache files smaller than mNumDataCache.
@@ -607,13 +651,7 @@
// Execute and verify results.
EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
// Check if prepareModelFromCache fails.
- preparedModel = nullptr;
- ErrorStatus status;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::INVALID_ARGUMENT) {
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
- ASSERT_EQ(preparedModel, nullptr);
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
}
@@ -633,68 +671,48 @@
// Test with number of model cache files greater than mNumModelCache.
{
- std::shared_ptr<IPreparedModel> preparedModel = nullptr;
- ErrorStatus status;
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
mModelCache.push_back({mTmpCache});
createCacheFds(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheFds(mDataCache, AccessMode::READ_WRITE, &dataCache);
mModelCache.pop_back();
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::GENERAL_FAILURE) {
- ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
- }
- ASSERT_EQ(preparedModel, nullptr);
+
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Test with number of model cache files smaller than mNumModelCache.
if (mModelCache.size() > 0) {
- std::shared_ptr<IPreparedModel> preparedModel = nullptr;
- ErrorStatus status;
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
auto tmp = mModelCache.back();
mModelCache.pop_back();
createCacheFds(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheFds(mDataCache, AccessMode::READ_WRITE, &dataCache);
mModelCache.push_back(tmp);
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::GENERAL_FAILURE) {
- ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
- }
- ASSERT_EQ(preparedModel, nullptr);
+
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Test with number of data cache files greater than mNumDataCache.
{
- std::shared_ptr<IPreparedModel> preparedModel = nullptr;
- ErrorStatus status;
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
mDataCache.push_back({mTmpCache});
createCacheFds(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheFds(mDataCache, AccessMode::READ_WRITE, &dataCache);
mDataCache.pop_back();
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::GENERAL_FAILURE) {
- ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
- }
- ASSERT_EQ(preparedModel, nullptr);
+
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Test with number of data cache files smaller than mNumDataCache.
if (mDataCache.size() > 0) {
- std::shared_ptr<IPreparedModel> preparedModel = nullptr;
- ErrorStatus status;
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
auto tmp = mDataCache.back();
mDataCache.pop_back();
createCacheFds(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheFds(mDataCache, AccessMode::READ_WRITE, &dataCache);
mDataCache.push_back(tmp);
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::GENERAL_FAILURE) {
- ASSERT_EQ(status, ErrorStatus::INVALID_ARGUMENT);
- }
- ASSERT_EQ(preparedModel, nullptr);
+
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
}
@@ -719,13 +737,7 @@
// Execute and verify results.
EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
// Check if prepareModelFromCache fails.
- preparedModel = nullptr;
- ErrorStatus status;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::INVALID_ARGUMENT) {
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
- ASSERT_EQ(preparedModel, nullptr);
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Go through each handle in data cache, test with invalid access mode.
@@ -741,13 +753,7 @@
// Execute and verify results.
EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
// Check if prepareModelFromCache fails.
- preparedModel = nullptr;
- ErrorStatus status;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- if (status != ErrorStatus::INVALID_ARGUMENT) {
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- }
- ASSERT_EQ(preparedModel, nullptr);
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
}
@@ -769,30 +775,23 @@
// Go through each handle in model cache, test with invalid access mode.
for (uint32_t i = 0; i < mNumModelCache; i++) {
- std::shared_ptr<IPreparedModel> preparedModel = nullptr;
- ErrorStatus status;
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
modelCacheMode[i] = AccessMode::WRITE_ONLY;
createCacheFds(mModelCache, modelCacheMode, &modelCache);
createCacheFds(mDataCache, dataCacheMode, &dataCache);
modelCacheMode[i] = AccessMode::READ_WRITE;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- ASSERT_EQ(preparedModel, nullptr);
+
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
// Go through each handle in data cache, test with invalid access mode.
for (uint32_t i = 0; i < mNumDataCache; i++) {
- std::shared_ptr<IPreparedModel> preparedModel = nullptr;
- ErrorStatus status;
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
dataCacheMode[i] = AccessMode::WRITE_ONLY;
createCacheFds(mModelCache, modelCacheMode, &modelCache);
createCacheFds(mDataCache, dataCacheMode, &dataCache);
dataCacheMode[i] = AccessMode::READ_WRITE;
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
- ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
- ASSERT_EQ(preparedModel, nullptr);
+ verifyModelPreparationBehaviour(modelCache, dataCache, &model, testModel);
}
}
@@ -872,7 +871,8 @@
std::vector<ndk::ScopedFileDescriptor> modelCache, dataCache;
createCacheFds(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheFds(mDataCache, AccessMode::READ_WRITE, &dataCache);
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status,
+ /*fallbackModel=*/nullptr);
// The preparation may fail or succeed, but must not crash. If the preparation succeeds,
// the prepared model must be executed with the correct result and not crash.
@@ -933,7 +933,8 @@
// Spawn a thread to copy the cache content concurrently while preparing from cache.
std::thread thread(copyCacheFiles, std::cref(modelCacheMul), std::cref(mModelCache));
- prepareModelFromCache(modelCache, dataCache, &preparedModel, &status);
+ prepareModelFromCache(modelCache, dataCache, &preparedModel, &status,
+ /*fallbackModel=*/nullptr);
thread.join();
// The preparation may fail or succeed, but must not crash. If the preparation succeeds,
diff --git a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
index d3b041d..2356ff0 100644
--- a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
@@ -435,8 +435,8 @@
mInputMemory = TestBlobAHWB::create(std::max<size_t>(inputSize, 1));
mOutputMemory = TestBlobAHWB::create(std::max<size_t>(outputSize, 1));
} else {
- mInputMemory = TestAshmem::create(std::max<size_t>(inputSize, 1));
- mOutputMemory = TestAshmem::create(std::max<size_t>(outputSize, 1));
+ mInputMemory = TestAshmem::create(std::max<size_t>(inputSize, 1), /*aidlReadonly=*/true);
+ mOutputMemory = TestAshmem::create(std::max<size_t>(outputSize, 1), /*aidlReadonly=*/false);
}
CHECK_NE(mInputMemory, nullptr);
CHECK_NE(mOutputMemory, nullptr);
diff --git a/neuralnetworks/aidl/vts/functional/Utils.cpp b/neuralnetworks/aidl/vts/functional/Utils.cpp
index 3c7f5f7..9af362e 100644
--- a/neuralnetworks/aidl/vts/functional/Utils.cpp
+++ b/neuralnetworks/aidl/vts/functional/Utils.cpp
@@ -23,6 +23,7 @@
#include <android/binder_status.h>
#include <android/hardware_buffer.h>
+#include <sys/mman.h>
#include <iostream>
#include <limits>
#include <numeric>
@@ -98,19 +99,39 @@
std::multiplies<>{});
}
-std::unique_ptr<TestAshmem> TestAshmem::create(uint32_t size) {
- auto ashmem = std::make_unique<TestAshmem>(size);
+std::unique_ptr<TestAshmem> TestAshmem::create(uint32_t size, bool aidlReadonly) {
+ auto ashmem = std::make_unique<TestAshmem>(size, aidlReadonly);
return ashmem->mIsValid ? std::move(ashmem) : nullptr;
}
-void TestAshmem::initialize(uint32_t size) {
+// This function will create a readonly shared memory with PROT_READ only.
+// The input shared memory must be either Ashmem or mapped-FD.
+static nn::SharedMemory convertSharedMemoryToReadonly(const nn::SharedMemory& sharedMemory) {
+ if (std::holds_alternative<nn::Memory::Ashmem>(sharedMemory->handle)) {
+ const auto& memory = std::get<nn::Memory::Ashmem>(sharedMemory->handle);
+ return nn::createSharedMemoryFromFd(memory.size, PROT_READ, memory.fd.get(), /*offset=*/0)
+ .value();
+ } else if (std::holds_alternative<nn::Memory::Fd>(sharedMemory->handle)) {
+ const auto& memory = std::get<nn::Memory::Fd>(sharedMemory->handle);
+ return nn::createSharedMemoryFromFd(memory.size, PROT_READ, memory.fd.get(), memory.offset)
+ .value();
+ }
+ CHECK(false) << "Unexpected shared memory type";
+ return sharedMemory;
+}
+
+void TestAshmem::initialize(uint32_t size, bool aidlReadonly) {
mIsValid = false;
ASSERT_GT(size, 0);
const auto sharedMemory = nn::createSharedMemory(size).value();
mMappedMemory = nn::map(sharedMemory).value();
mPtr = static_cast<uint8_t*>(std::get<void*>(mMappedMemory.pointer));
CHECK_NE(mPtr, nullptr);
- mAidlMemory = utils::convert(sharedMemory).value();
+ if (aidlReadonly) {
+ mAidlMemory = utils::convert(convertSharedMemoryToReadonly(sharedMemory)).value();
+ } else {
+ mAidlMemory = utils::convert(sharedMemory).value();
+ }
mIsValid = true;
}
diff --git a/neuralnetworks/aidl/vts/functional/Utils.h b/neuralnetworks/aidl/vts/functional/Utils.h
index 77085a7..9dd7359 100644
--- a/neuralnetworks/aidl/vts/functional/Utils.h
+++ b/neuralnetworks/aidl/vts/functional/Utils.h
@@ -79,15 +79,18 @@
class TestAshmem : public TestMemoryBase {
public:
- static std::unique_ptr<TestAshmem> create(uint32_t size);
+ // If aidlReadonly is true, getAidlMemory will return a sAIDL memory with readonly access;
+ // otherwise, the sAIDL memory has read-write access. This only affects the sAIDL memory.
+ // getPointer will always return a valid address with read-write access.
+ static std::unique_ptr<TestAshmem> create(uint32_t size, bool aidlReadonly = false);
// Prefer TestAshmem::create.
// The constructor calls initialize, which constructs the memory resources. This is a workaround
// that gtest macros cannot be used directly in a constructor.
- TestAshmem(uint32_t size) { initialize(size); }
+ TestAshmem(uint32_t size, bool aidlReadonly) { initialize(size, aidlReadonly); }
private:
- void initialize(uint32_t size);
+ void initialize(uint32_t size, bool aidlReadonly);
nn::Mapping mMappedMemory;
};
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 422e91c..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
@@ -821,7 +897,7 @@
/*
* Test IRadio.updateSimPhonebookRecords() for the response returned.
*/
-TEST_F(RadioHidlTest_v1_6, updateSimPhonebookRecords) {
+TEST_P(RadioHidlTest_v1_6, updateSimPhonebookRecords) {
serial = GetRandomSerialNumber();
radio_v1_6->getSimPhonebookCapacity(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
@@ -851,7 +927,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);
- EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED},
+ CHECK_GENERAL_ERROR));
if(pbCapacity.maxAdnRecords > 0
&& pbCapacity.usedAdnRecords < pbCapacity.maxAdnRecords) {
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/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 9cc795d..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.
*
@@ -805,9 +803,10 @@
byte[] convertStorageKeyToEphemeral(in byte[] storageKeyBlob);
/**
- * Returns parameters associated with the provided key. This should match the
- * KeyCharacteristics present in the KeyCreationResult returned by generateKey(),
- * importKey(), or importWrappedKey().
+ * Returns KeyMint-enforced parameters associated with the provided key. The returned tags are
+ * a subset of KeyCharacteristics found in the KeyCreationResult returned by generateKey(),
+ * importKey(), or importWrappedKey(). The returned value is a subset, as it does not include
+ * any Keystore-enforced parameters.
*
* @param keyBlob The opaque descriptor returned by generateKey, importKey or importWrappedKey.
*
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/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
index f93dbba..fd6bf65 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -159,18 +159,17 @@
* purpose [1] EXPLICIT SET OF INTEGER OPTIONAL,
* algorithm [2] EXPLICIT INTEGER OPTIONAL,
* keySize [3] EXPLICIT INTEGER OPTIONAL,
- * blockMode [4] EXPLICIT SET OF INTEGER OPTIONAL,
* digest [5] EXPLICIT SET OF INTEGER OPTIONAL,
* padding [6] EXPLICIT SET OF INTEGER OPTIONAL,
- * callerNonce [7] EXPLICIT NULL OPTIONAL,
- * minMacLength [8] EXPLICIT INTEGER OPTIONAL,
* ecCurve [10] EXPLICIT INTEGER OPTIONAL,
* rsaPublicExponent [200] EXPLICIT INTEGER OPTIONAL,
+ * mgfDigest [203] EXPLICIT SET OF INTEGER OPTIONAL,
* rollbackResistance [303] EXPLICIT NULL OPTIONAL,
+ * earlyBootOnly [305] EXPLICIT NULL OPTIONAL,
* activeDateTime [400] EXPLICIT INTEGER OPTIONAL,
* originationExpireDateTime [401] EXPLICIT INTEGER OPTIONAL,
* usageExpireDateTime [402] EXPLICIT INTEGER OPTIONAL,
- * userSecureId [502] EXPLICIT INTEGER OPTIONAL,
+ * usageCountLimit [405] EXPLICIT INTEGER OPTIONAL,
* noAuthRequired [503] EXPLICIT NULL OPTIONAL,
* userAuthType [504] EXPLICIT INTEGER OPTIONAL,
* authTimeout [505] EXPLICIT INTEGER OPTIONAL,
@@ -194,6 +193,7 @@
* attestationIdModel [717] EXPLICIT OCTET_STRING OPTIONAL,
* vendorPatchLevel [718] EXPLICIT INTEGER OPTIONAL,
* bootPatchLevel [719] EXPLICIT INTEGER OPTIONAL,
+ * deviceUniqueAttestation [720] EXPLICIT NULL OPTIONAL,
* }
*/
Certificate[] certificateChain;
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/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index 4ff4574..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,23 +820,33 @@
*
* 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
* operations. It indicates that attestation using a device-unique key is requested, rather
- * than a batch key. When a device-unique key is used, only the attestation certificate is
- * returned; no additional chained certificates are provided. It's up to the caller to
- * recognize the device-unique signing key. Only SecurityLevel::STRONGBOX IKeyMintDevices may
- * support device-unique attestations. SecurityLevel::TRUSTED_ENVIRONMENT IKeyMintDevices must
- * return ErrorCode::INVALID_ARGUMENT if they receive DEVICE_UNIQUE_ATTESTATION.
+ * than a batch key. When a device-unique key is used, the returned chain should contain two
+ * certificates:
+ * * The attestation certificate, containing the attestation extension, as described in
+ KeyCreationResult.aidl.
+ * * A self-signed root certificate, signed by the device-unique key.
+ * No additional chained certificates are provided. Only SecurityLevel::STRONGBOX
+ * IKeyMintDevices may support device-unique attestations. SecurityLevel::TRUSTED_ENVIRONMENT
+ * IKeyMintDevices must return ErrorCode::INVALID_ARGUMENT if they receive
+ * DEVICE_UNIQUE_ATTESTATION.
* SecurityLevel::STRONGBOX IKeyMintDevices need not support DEVICE_UNIQUE_ATTESTATION, and
* return ErrorCode::CANNOT_ATTEST_IDS if they do not support it.
*
+ * The caller needs to obtain the device-unique keys out-of-band and compare them against the
+ * key used to sign the self-signed root certificate.
+ * To ease this process, the IKeyMintDevice implementation should include, both in the subject
+ * and issuer fields of the self-signed root, the unique identifier of the device. Using the
+ * unique identifier will make it straightforward for the caller to link a device to its key.
+ *
* 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
@@ -850,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
@@ -867,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,
@@ -887,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.
@@ -898,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
@@ -906,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
@@ -915,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
@@ -923,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.
@@ -931,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
@@ -939,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
@@ -947,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.
@@ -958,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 b8699e9..a312723 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -141,11 +141,18 @@
attest_key, &attested_key_blob, &attested_key_characteristics,
&attested_key_cert_chain));
+ // The returned key characteristics will include CREATION_DATETIME (checked below)
+ // in SecurityLevel::KEYSTORE; this will be stripped out in the CheckCharacteristics()
+ // call below, to match what getKeyCharacteristics() returns (which doesn't include
+ // any SecurityLevel::KEYSTORE characteristics).
+ CheckCharacteristics(attested_key_blob, attested_key_characteristics);
+
CheckedDeleteKey(&attested_key_blob);
CheckedDeleteKey(&attest_key.keyBlob);
hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
+
// The client-specified CREATION_DATETIME should be in sw_enforced.
// Its presence will also trigger verify_attestation_record() to check that it
// is in the attestation extension with a matching value.
@@ -549,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);
@@ -633,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);
@@ -655,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 b0f056a..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,10 +40,11 @@
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.
+ ASSERT_EQ(cert_chain_.size(), 2);
EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
- ASSERT_GT(cert_chain_.size(), 0);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
EXPECT_TRUE(verify_attestation_record("challenge", "foo", sw_enforced, hw_enforced,
@@ -133,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);
}
/*
@@ -157,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")
@@ -173,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 a9a67bc..44b8274 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -142,6 +142,15 @@
return filtered;
}
+// Remove any SecurityLevel::KEYSTORE entries from a list of key characteristics.
+void strip_keystore_tags(vector<KeyCharacteristics>* characteristics) {
+ characteristics->erase(std::remove_if(characteristics->begin(), characteristics->end(),
+ [](const auto& entry) {
+ return entry.securityLevel == SecurityLevel::KEYSTORE;
+ }),
+ characteristics->end());
+}
+
string x509NameToStr(X509_NAME* name) {
char* s = X509_NAME_oneline(name, nullptr, 0);
string retval(s);
@@ -320,6 +329,65 @@
return GetReturnErrorCode(result);
}
+ErrorCode KeyMintAidlTestBase::GetCharacteristics(const vector<uint8_t>& key_blob,
+ const vector<uint8_t>& app_id,
+ const vector<uint8_t>& app_data,
+ vector<KeyCharacteristics>* key_characteristics) {
+ Status result =
+ keymint_->getKeyCharacteristics(key_blob, app_id, app_data, key_characteristics);
+ return GetReturnErrorCode(result);
+}
+
+ErrorCode KeyMintAidlTestBase::GetCharacteristics(const vector<uint8_t>& key_blob,
+ vector<KeyCharacteristics>* key_characteristics) {
+ vector<uint8_t> empty_app_id, empty_app_data;
+ return GetCharacteristics(key_blob, empty_app_id, empty_app_data, key_characteristics);
+}
+
+void KeyMintAidlTestBase::CheckCharacteristics(
+ const vector<uint8_t>& key_blob,
+ const vector<KeyCharacteristics>& generate_characteristics) {
+ // Any key characteristics that were in SecurityLevel::KEYSTORE when returned from
+ // generateKey() should be excluded, as KeyMint will have no record of them.
+ // This applies to CREATION_DATETIME in particular.
+ vector<KeyCharacteristics> expected_characteristics(generate_characteristics);
+ strip_keystore_tags(&expected_characteristics);
+
+ vector<KeyCharacteristics> retrieved;
+ ASSERT_EQ(ErrorCode::OK, GetCharacteristics(key_blob, &retrieved));
+ EXPECT_EQ(expected_characteristics, retrieved);
+}
+
+void KeyMintAidlTestBase::CheckAppIdCharacteristics(
+ const vector<uint8_t>& key_blob, std::string_view app_id_string,
+ std::string_view app_data_string,
+ const vector<KeyCharacteristics>& generate_characteristics) {
+ // Exclude any SecurityLevel::KEYSTORE characteristics for comparisons.
+ vector<KeyCharacteristics> expected_characteristics(generate_characteristics);
+ strip_keystore_tags(&expected_characteristics);
+
+ vector<uint8_t> app_id(app_id_string.begin(), app_id_string.end());
+ vector<uint8_t> app_data(app_data_string.begin(), app_data_string.end());
+ vector<KeyCharacteristics> retrieved;
+ ASSERT_EQ(ErrorCode::OK, GetCharacteristics(key_blob, app_id, app_data, &retrieved));
+ EXPECT_EQ(expected_characteristics, retrieved);
+
+ // Check that key characteristics can't be retrieved if the app ID or app data is missing.
+ vector<uint8_t> empty;
+ vector<KeyCharacteristics> not_retrieved;
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ GetCharacteristics(key_blob, empty, app_data, ¬_retrieved));
+ EXPECT_EQ(not_retrieved.size(), 0);
+
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ GetCharacteristics(key_blob, app_id, empty, ¬_retrieved));
+ EXPECT_EQ(not_retrieved.size(), 0);
+
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ GetCharacteristics(key_blob, empty, empty, ¬_retrieved));
+ EXPECT_EQ(not_retrieved.size(), 0);
+}
+
ErrorCode KeyMintAidlTestBase::DeleteKey(vector<uint8_t>* key_blob, bool keep_key_blob) {
Status result = keymint_->deleteKey(*key_blob);
if (!keep_key_blob) {
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index d8f1bb3..82f192a 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -16,8 +16,12 @@
#pragma once
+#include <functional>
+#include <string_view>
+
#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>
@@ -104,6 +108,18 @@
unwrapping_params, 0 /* password_sid */, 0 /* biometric_sid */);
}
+ ErrorCode GetCharacteristics(const vector<uint8_t>& key_blob, const vector<uint8_t>& app_id,
+ const vector<uint8_t>& app_data,
+ vector<KeyCharacteristics>* key_characteristics);
+ ErrorCode GetCharacteristics(const vector<uint8_t>& key_blob,
+ vector<KeyCharacteristics>* key_characteristics);
+
+ void CheckCharacteristics(const vector<uint8_t>& key_blob,
+ const vector<KeyCharacteristics>& generate_characteristics);
+ void CheckAppIdCharacteristics(const vector<uint8_t>& key_blob, std::string_view app_id_string,
+ std::string_view app_data_string,
+ const vector<KeyCharacteristics>& generate_characteristics);
+
ErrorCode DeleteKey(vector<uint8_t>* key_blob, bool keep_key_blob = false);
ErrorCode DeleteKey(bool keep_key_blob = false);
@@ -192,50 +208,58 @@
template <typename TagType>
std::tuple<KeyData /* aesKey */, KeyData /* hmacKey */, KeyData /* rsaKey */,
KeyData /* ecdsaKey */>
- CreateTestKeys(TagType tagToTest, ErrorCode expectedReturn) {
+ CreateTestKeys(
+ TagType tagToTest, ErrorCode expectedReturn,
+ std::function<void(AuthorizationSetBuilder*)> tagModifier =
+ [](AuthorizationSetBuilder*) {}) {
/* AES */
KeyData aesKeyData;
- ErrorCode errorCode = GenerateKey(AuthorizationSetBuilder()
- .AesEncryptionKey(128)
- .Authorization(tagToTest)
- .BlockMode(BlockMode::ECB)
- .Padding(PaddingMode::NONE)
- .Authorization(TAG_NO_AUTH_REQUIRED),
- &aesKeyData.blob, &aesKeyData.characteristics);
+ AuthorizationSetBuilder aesBuilder = AuthorizationSetBuilder()
+ .AesEncryptionKey(128)
+ .Authorization(tagToTest)
+ .BlockMode(BlockMode::ECB)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED);
+ tagModifier(&aesBuilder);
+ ErrorCode errorCode =
+ GenerateKey(aesBuilder, &aesKeyData.blob, &aesKeyData.characteristics);
EXPECT_EQ(expectedReturn, errorCode);
/* HMAC */
KeyData hmacKeyData;
- errorCode = GenerateKey(AuthorizationSetBuilder()
- .HmacKey(128)
- .Authorization(tagToTest)
- .Digest(Digest::SHA_2_256)
- .Authorization(TAG_MIN_MAC_LENGTH, 128)
- .Authorization(TAG_NO_AUTH_REQUIRED),
- &hmacKeyData.blob, &hmacKeyData.characteristics);
+ AuthorizationSetBuilder hmacBuilder = AuthorizationSetBuilder()
+ .HmacKey(128)
+ .Authorization(tagToTest)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)
+ .Authorization(TAG_NO_AUTH_REQUIRED);
+ tagModifier(&hmacBuilder);
+ errorCode = GenerateKey(hmacBuilder, &hmacKeyData.blob, &hmacKeyData.characteristics);
EXPECT_EQ(expectedReturn, errorCode);
/* RSA */
KeyData rsaKeyData;
- errorCode = GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(2048, 65537)
- .Authorization(tagToTest)
- .Digest(Digest::NONE)
- .Padding(PaddingMode::NONE)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .SetDefaultValidity(),
- &rsaKeyData.blob, &rsaKeyData.characteristics);
+ AuthorizationSetBuilder rsaBuilder = AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Authorization(tagToTest)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity();
+ tagModifier(&rsaBuilder);
+ errorCode = GenerateKey(rsaBuilder, &rsaKeyData.blob, &rsaKeyData.characteristics);
EXPECT_EQ(expectedReturn, errorCode);
/* ECDSA */
KeyData ecdsaKeyData;
- errorCode = GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(256)
- .Authorization(tagToTest)
- .Digest(Digest::SHA_2_256)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .SetDefaultValidity(),
- &ecdsaKeyData.blob, &ecdsaKeyData.characteristics);
+ AuthorizationSetBuilder ecdsaBuilder = AuthorizationSetBuilder()
+ .EcdsaSigningKey(256)
+ .Authorization(tagToTest)
+ .Digest(Digest::SHA_2_256)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity();
+ tagModifier(&ecdsaBuilder);
+ errorCode = GenerateKey(ecdsaBuilder, &ecdsaKeyData.blob, &ecdsaKeyData.characteristics);
EXPECT_EQ(expectedReturn, errorCode);
return {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData};
}
@@ -290,6 +314,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 8b1eb30..295be1a 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -560,6 +560,7 @@
EXPECT_GT(key_blob.size(), 0U);
CheckSymmetricParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -742,6 +743,7 @@
EXPECT_GT(key_blob.size(), 0U);
CheckSymmetricParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -788,6 +790,7 @@
EXPECT_GT(key_blob.size(), 0U);
CheckSymmetricParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -865,6 +868,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -911,6 +915,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -978,6 +983,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1108,6 +1114,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1176,6 +1183,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1211,6 +1219,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1266,6 +1275,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1362,6 +1372,7 @@
&key_blob, &key_characteristics));
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1405,6 +1416,7 @@
&key_blob, &key_characteristics));
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1452,6 +1464,7 @@
&key_blob, &key_characteristics));
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1511,6 +1524,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1555,6 +1569,7 @@
&key_blob, &key_characteristics));
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1594,6 +1609,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
@@ -1726,6 +1742,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::HMAC));
@@ -1761,6 +1778,7 @@
ASSERT_GT(key_blob.size(), 0U);
ASSERT_EQ(cert_chain_.size(), 0);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::HMAC));
@@ -1791,6 +1809,7 @@
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
+ CheckCharacteristics(key_blob, key_characteristics);
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::HMAC));
@@ -2044,6 +2063,9 @@
.Authorization(TAG_APPLICATION_ID, "clientid")
.Authorization(TAG_APPLICATION_DATA, "appdata")
.SetDefaultValidity()));
+
+ CheckAppIdCharacteristics(key_blob_, "clientid", "appdata", key_characteristics_);
+
EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
Begin(KeyPurpose::SIGN,
AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)));
@@ -2558,6 +2580,9 @@
.Authorization(TAG_APPLICATION_ID, "clientid")
.Authorization(TAG_APPLICATION_DATA, "appdata")
.SetDefaultValidity()));
+
+ CheckAppIdCharacteristics(key_blob_, "clientid", "appdata", key_characteristics_);
+
EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
Begin(KeyPurpose::SIGN, AuthorizationSetBuilder().Digest(Digest::NONE)));
AbortIfNeeded();
@@ -6330,6 +6355,11 @@
auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] =
CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::OK);
+ for (const auto& keyData : {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}) {
+ ASSERT_GT(keyData.blob.size(), 0U);
+ AuthorizationSet crypto_params = SecLevelAuthorizations(keyData.characteristics);
+ EXPECT_TRUE(crypto_params.Contains(TAG_EARLY_BOOT_ONLY)) << crypto_params;
+ }
CheckedDeleteKey(&aesKeyData.blob);
CheckedDeleteKey(&hmacKeyData.blob);
CheckedDeleteKey(&rsaKeyData.blob);
@@ -6337,7 +6367,30 @@
}
/*
- * EarlyBootKeyTest.UsetEarlyBootKeyFailure
+ * EarlyBootKeyTest.CreateAttestedEarlyBootKey
+ *
+ * Verifies that creating an early boot key with attestation succeeds.
+ */
+TEST_P(EarlyBootKeyTest, CreateAttestedEarlyBootKey) {
+ auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] = CreateTestKeys(
+ TAG_EARLY_BOOT_ONLY, ErrorCode::OK, [](AuthorizationSetBuilder* builder) {
+ builder->AttestationChallenge("challenge");
+ builder->AttestationApplicationId("app_id");
+ });
+
+ for (const auto& keyData : {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}) {
+ ASSERT_GT(keyData.blob.size(), 0U);
+ AuthorizationSet crypto_params = SecLevelAuthorizations(keyData.characteristics);
+ EXPECT_TRUE(crypto_params.Contains(TAG_EARLY_BOOT_ONLY)) << crypto_params;
+ }
+ CheckedDeleteKey(&aesKeyData.blob);
+ CheckedDeleteKey(&hmacKeyData.blob);
+ CheckedDeleteKey(&rsaKeyData.blob);
+ CheckedDeleteKey(&ecdsaKeyData.blob);
+}
+
+/*
+ * EarlyBootKeyTest.UseEarlyBootKeyFailure
*
* Verifies that using early boot keys at a later stage fails.
*/
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index a2071c2..a177317 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -340,6 +340,7 @@
cppbor::Array() // SignedMacAad
.add(challenge_)
.add(std::move(deviceInfoMap))
+ .add(keysToSignMac)
.encode());
ASSERT_TRUE(macKey) << macKey.message();
diff --git a/security/keymint/support/attestation_record.cpp b/security/keymint/support/attestation_record.cpp
index a48f770..2462228 100644
--- a/security/keymint/support/attestation_record.cpp
+++ b/security/keymint/support/attestation_record.cpp
@@ -64,6 +64,7 @@
} ASN1_SEQUENCE_END(KM_ROOT_OF_TRUST);
IMPLEMENT_ASN1_FUNCTIONS(KM_ROOT_OF_TRUST);
+// Fields ordered in tag order.
typedef struct km_auth_list {
ASN1_INTEGER_SET* purpose;
ASN1_INTEGER* algorithm;
@@ -72,32 +73,38 @@
ASN1_INTEGER_SET* padding;
ASN1_INTEGER* ec_curve;
ASN1_INTEGER* rsa_public_exponent;
+ ASN1_INTEGER_SET* mgf_digest;
+ 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;
+ ASN1_INTEGER* usage_count_limit;
ASN1_NULL* no_auth_required;
ASN1_INTEGER* user_auth_type;
ASN1_INTEGER* auth_timeout;
ASN1_NULL* allow_while_on_body;
- ASN1_NULL* all_applications;
- ASN1_OCTET_STRING* application_id;
+ ASN1_NULL* trusted_user_presence_required;
+ ASN1_NULL* trusted_confirmation_required;
+ ASN1_NULL* unlocked_device_required;
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* storage_key;
ASN1_NULL* identity_credential;
- ASN1_INTEGER* usage_count_limit;
} KM_AUTH_LIST;
ASN1_SEQUENCE(KM_AUTH_LIST) = {
@@ -109,13 +116,18 @@
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_SET_OF_OPT(KM_AUTH_LIST, mgf_digest, ASN1_INTEGER,
+ TAG_RSA_OAEP_MGF_DIGEST.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()),
ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, usage_count_limit, ASN1_INTEGER,
+ TAG_USAGE_COUNT_LIMIT.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()),
@@ -133,19 +145,31 @@
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, storage_key, ASN1_NULL, TAG_STORAGE_KEY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential, ASN1_NULL,
TAG_IDENTITY_CREDENTIAL_KEY.maskedTag()),
- ASN1_EXP_OPT(KM_AUTH_LIST, usage_count_limit, ASN1_INTEGER,
- TAG_USAGE_COUNT_LIMIT.maskedTag()),
} ASN1_SEQUENCE_END(KM_AUTH_LIST);
IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
@@ -155,9 +179,9 @@
ASN1_INTEGER* keymint_version;
ASN1_ENUMERATED* keymint_security_level;
ASN1_OCTET_STRING* attestation_challenge;
+ ASN1_INTEGER* unique_id;
KM_AUTH_LIST* software_enforced;
KM_AUTH_LIST* tee_enforced;
- ASN1_INTEGER* unique_id;
} KM_KEY_DESCRIPTION;
ASN1_SEQUENCE(KM_KEY_DESCRIPTION) = {
@@ -253,41 +277,52 @@
}
// Extract the values from the specified ASN.1 record and place them in auth_list.
+// Does nothing with root-of-trust field.
static ErrorCode extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet* auth_list) {
if (!record) return ErrorCode::OK;
- copyAuthTag(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list);
- copyAuthTag(record->algorithm, TAG_ALGORITHM, auth_list);
- copyAuthTag(record->application_id, TAG_APPLICATION_ID, auth_list);
- copyAuthTag(record->auth_timeout, TAG_AUTH_TIMEOUT, auth_list);
- copyAuthTag(record->creation_date_time, TAG_CREATION_DATETIME, auth_list);
- copyAuthTag(record->digest, TAG_DIGEST, auth_list);
- copyAuthTag(record->ec_curve, TAG_EC_CURVE, auth_list);
- copyAuthTag(record->key_size, TAG_KEY_SIZE, auth_list);
- copyAuthTag(record->no_auth_required, TAG_NO_AUTH_REQUIRED, auth_list);
- copyAuthTag(record->origin, TAG_ORIGIN, auth_list);
- copyAuthTag(record->origination_expire_date_time, TAG_ORIGINATION_EXPIRE_DATETIME, auth_list);
- copyAuthTag(record->os_patchlevel, TAG_OS_PATCHLEVEL, auth_list);
- copyAuthTag(record->os_version, TAG_OS_VERSION, auth_list);
- copyAuthTag(record->padding, TAG_PADDING, auth_list);
+ // Fields ordered in tag order.
copyAuthTag(record->purpose, TAG_PURPOSE, auth_list);
- copyAuthTag(record->rollback_resistance, TAG_ROLLBACK_RESISTANCE, auth_list);
+ copyAuthTag(record->algorithm, TAG_ALGORITHM, auth_list);
+ copyAuthTag(record->key_size, TAG_KEY_SIZE, auth_list);
+ copyAuthTag(record->digest, TAG_DIGEST, auth_list);
+ copyAuthTag(record->padding, TAG_PADDING, auth_list);
+ copyAuthTag(record->ec_curve, TAG_EC_CURVE, auth_list);
copyAuthTag(record->rsa_public_exponent, TAG_RSA_PUBLIC_EXPONENT, auth_list);
+ copyAuthTag(record->mgf_digest, TAG_RSA_OAEP_MGF_DIGEST, auth_list);
+ copyAuthTag(record->rollback_resistance, TAG_ROLLBACK_RESISTANCE, auth_list);
+ copyAuthTag(record->early_boot_only, TAG_EARLY_BOOT_ONLY, auth_list);
+ copyAuthTag(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list);
+ copyAuthTag(record->origination_expire_date_time, TAG_ORIGINATION_EXPIRE_DATETIME, auth_list);
copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
+ copyAuthTag(record->usage_count_limit, TAG_USAGE_COUNT_LIMIT, auth_list);
+ copyAuthTag(record->no_auth_required, TAG_NO_AUTH_REQUIRED, 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->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
- copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
+ copyAuthTag(record->auth_timeout, TAG_AUTH_TIMEOUT, auth_list);
+ copyAuthTag(record->allow_while_on_body, TAG_ALLOW_WHILE_ON_BODY, auth_list);
copyAuthTag(record->trusted_user_presence_required, TAG_TRUSTED_USER_PRESENCE_REQUIRED,
auth_list);
copyAuthTag(record->trusted_confirmation_required, TAG_TRUSTED_CONFIRMATION_REQUIRED,
auth_list);
copyAuthTag(record->unlocked_device_required, TAG_UNLOCKED_DEVICE_REQUIRED, auth_list);
- copyAuthTag(record->early_boot_only, TAG_EARLY_BOOT_ONLY, auth_list);
+ copyAuthTag(record->creation_date_time, TAG_CREATION_DATETIME, auth_list);
+ copyAuthTag(record->origin, TAG_ORIGIN, auth_list);
+ // root_of_trust dealt with separately
+ copyAuthTag(record->os_version, TAG_OS_VERSION, auth_list);
+ copyAuthTag(record->os_patchlevel, TAG_OS_PATCHLEVEL, 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->device_unique_attestation, TAG_DEVICE_UNIQUE_ATTESTATION, auth_list);
- copyAuthTag(record->storage_key, TAG_STORAGE_KEY, auth_list);
copyAuthTag(record->identity_credential, TAG_IDENTITY_CREDENTIAL_KEY, auth_list);
- copyAuthTag(record->usage_count_limit, TAG_USAGE_COUNT_LIMIT, auth_list);
return ErrorCode::OK;
}
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/android/hardware/security/secureclock/TimeStampToken.aidl b/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
index 2fbd29a..fcf2ee8 100644
--- a/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
+++ b/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
@@ -39,7 +39,7 @@
* 32-byte HMAC-SHA256 of the above values, computed as:
*
* HMAC(H,
- * ISecureClock.TIME_STAMP_MAC_LABEL || challenge || timestamp || securityLevel )
+ * ISecureClock.TIME_STAMP_MAC_LABEL || challenge || timestamp || 1 )
*
* where:
*
@@ -50,9 +50,7 @@
* ``||'' represents concatenation
*
* The representation of challenge and timestamp is as 64-bit unsigned integers in big-endian
- * order. SecurityLevel is represented as a 32-bit unsigned integer in big-endian order as
- * described in android.hardware.security.keymint.SecurityLevel. It represents the security
- * level of the secure clock environment.
+ * order. 1, above, is a 32-bit unsigned integer, also big-endian.
*/
byte[] mac;
}
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) {