Merge changes from topic "sk_hal" into main
* changes:
VTS test for ISecretkeeper
Secretkeeper implementation: in-HAL/nonsecure impl
Introduce Secretkeeper HAL interface
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Spatializer.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Spatializer.aidl
index 9f97de0..98ecee0 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Spatializer.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Spatializer.aidl
@@ -35,12 +35,13 @@
@VintfStability
union Spatializer {
android.hardware.audio.effect.VendorExtension vendor;
- android.media.audio.common.Spatialization.Level spatializationLevel;
- android.media.audio.common.HeadTracking.Mode headTrackingMode;
android.media.audio.common.AudioChannelLayout[] supportedChannelLayout;
+ android.media.audio.common.Spatialization.Level spatializationLevel;
android.media.audio.common.Spatialization.Mode spatializationMode;
- float[6] headToStage;
- const int HEAD_TO_STAGE_VEC_SIZE = 6;
+ int headTrackingSensorId;
+ android.media.audio.common.HeadTracking.Mode headTrackingMode;
+ android.media.audio.common.HeadTracking.ConnectionMode headTrackingConnectionMode;
+ android.media.audio.common.HeadTracking.SensorData headTrackingSensorData;
@VintfStability
union Id {
android.hardware.audio.effect.VendorExtension vendorExtensionTag;
diff --git a/audio/aidl/android/hardware/audio/effect/Spatializer.aidl b/audio/aidl/android/hardware/audio/effect/Spatializer.aidl
index 4edb2e8..6ebe0d5 100644
--- a/audio/aidl/android/hardware/audio/effect/Spatializer.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Spatializer.aidl
@@ -52,29 +52,37 @@
VendorExtension vendor;
/**
- * Level of spatialization.
- */
- Spatialization.Level spatializationLevel;
-
- /**
- * Head tracking mode for spatialization.
- */
- HeadTracking.Mode headTrackingMode;
-
- /**
* List of supported input channel layouts.
*/
AudioChannelLayout[] supportedChannelLayout;
/**
+ * Level of spatialization.
+ */
+ Spatialization.Level spatializationLevel;
+
+ /**
* Spatialization mode, Binaural or Transaural for example.
*/
Spatialization.Mode spatializationMode;
/**
- * Vector representing of the head-to-stage pose with six floats: first three are a translation
- * vector, and the last three are a rotation vector.
+ * Head tracking sensor ID.
*/
- const int HEAD_TO_STAGE_VEC_SIZE = 6;
- float[HEAD_TO_STAGE_VEC_SIZE] headToStage;
+ int headTrackingSensorId;
+
+ /**
+ * Head tracking mode for spatialization.
+ */
+ HeadTracking.Mode headTrackingMode;
+
+ /**
+ * Head tracking sensor connection mode for spatialization.
+ */
+ HeadTracking.ConnectionMode headTrackingConnectionMode;
+
+ /**
+ * Headtracking sensor data.
+ */
+ HeadTracking.SensorData headTrackingSensorData;
}
diff --git a/audio/aidl/vts/ModuleConfig.cpp b/audio/aidl/vts/ModuleConfig.cpp
index a633d83..2b86271 100644
--- a/audio/aidl/vts/ModuleConfig.cpp
+++ b/audio/aidl/vts/ModuleConfig.cpp
@@ -17,6 +17,9 @@
#include <algorithm>
#include <chrono>
+#define LOG_TAG "VtsHalAudio.ModuleConfig"
+#include <android-base/logging.h>
+
#include <Utils.h>
#include <aidl/android/media/audio/common/AudioInputFlags.h>
#include <aidl/android/media/audio/common/AudioIoFlags.h>
diff --git a/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp b/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp
index 8a085e5..4d0995d 100644
--- a/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp
+++ b/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp
@@ -76,30 +76,20 @@
using ::android::hardware::automotive::vehicle::V2_0::vms::VmsLayerOffering;
using ::android::hardware::automotive::vehicle::V2_0::vms::VmsOffers;
-constexpr const char kCarMake[] = "Default Car";
-constexpr VehicleProperty kVehicleProp[] = {VehicleProperty::INVALID,
- VehicleProperty::HVAC_FAN_SPEED,
- VehicleProperty::INFO_MAKE,
- VehicleProperty::DISPLAY_BRIGHTNESS,
- VehicleProperty::INFO_FUEL_CAPACITY,
- VehicleProperty::HVAC_SEAT_TEMPERATURE};
-constexpr DiagnosticIntegerSensorIndex kDiagnosticIntIndex[] = {
- DiagnosticIntegerSensorIndex::FUEL_SYSTEM_STATUS,
- DiagnosticIntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON,
- DiagnosticIntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT,
- DiagnosticIntegerSensorIndex::FUEL_TYPE};
-constexpr DiagnosticFloatSensorIndex kDiagnosticFloatIndex[] = {
- DiagnosticFloatSensorIndex::CALCULATED_ENGINE_LOAD,
- DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1,
- DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1,
- DiagnosticFloatSensorIndex::THROTTLE_POSITION};
-constexpr size_t kVehiclePropArrayLength = std::size(kVehicleProp);
-constexpr size_t kIntSensorArrayLength = std::size(kDiagnosticIntIndex);
-constexpr size_t kFloatSensorArrayLength = std::size(kDiagnosticFloatIndex);
-constexpr VmsMessageType kAvailabilityMessageType[] = {VmsMessageType::AVAILABILITY_CHANGE,
- VmsMessageType::AVAILABILITY_RESPONSE};
-constexpr VmsMessageType kSubscriptionMessageType[] = {VmsMessageType::SUBSCRIPTIONS_CHANGE,
- VmsMessageType::SUBSCRIPTIONS_RESPONSE};
+std::string kCarMake;
+constexpr int32_t kMaxCaseMessage = 8;
+constexpr int32_t kMaxRuns = 20;
+constexpr int32_t kMaxSize = 1000;
+constexpr int32_t kMinSize = 0;
+constexpr int32_t kMaxFileSize = 100;
+float kFloatValue;
+std::vector<int32_t> kVec32;
+std::vector<int64_t> kVec64;
+std::vector<uint8_t> kVec8;
+std::vector<float> kVecFloat;
+static const std::vector<std::string> kSampleDtcs = {"P0070",
+ "P0102"
+ "P0123"};
MockedVehicleHal::VehiclePropValuePtr MockedVehicleHal::get(
const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
@@ -113,23 +103,23 @@
switch (property) {
case VehicleProperty::INFO_MAKE:
- pValue = getValuePool()->obtainString(kCarMake);
+ pValue = getValuePool()->obtainString(kCarMake.c_str());
break;
case VehicleProperty::INFO_FUEL_CAPACITY:
if (mFuelCapacityAttemptsLeft-- > 0) {
*outStatus = StatusCode::TRY_AGAIN;
} else {
- pValue = getValuePool()->obtainFloat(42.42);
+ pValue = getValuePool()->obtainFloat(kFloatValue);
}
break;
default:
if (requestedPropValue.prop == kCustomComplexProperty) {
pValue = getValuePool()->obtainComplex();
- pValue->value.int32Values = hidl_vec<int32_t>{10, 20};
- pValue->value.int64Values = hidl_vec<int64_t>{30, 40};
- pValue->value.floatValues = hidl_vec<float_t>{1.1, 2.2};
- pValue->value.bytes = hidl_vec<uint8_t>{1, 2, 3};
- pValue->value.stringValue = kCarMake;
+ pValue->value.int32Values = hidl_vec<int32_t>{kVec32};
+ pValue->value.int64Values = hidl_vec<int64_t>{kVec64};
+ pValue->value.floatValues = hidl_vec<float_t>{kVecFloat};
+ pValue->value.bytes = hidl_vec<uint8_t>{kVec8};
+ pValue->value.stringValue = kCarMake.c_str();
break;
}
auto key = makeKey(toInt(property), areaId);
@@ -145,28 +135,72 @@
return pValue;
}
+void VehicleHalManagerFuzzer::initValue() {
+ kCarMake = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxFileSize);
+ kFloatValue = mFuzzedDataProvider->ConsumeFloatingPoint<float>();
+ fillParameter<int32_t>(mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize),
+ kVec32);
+ fillParameter<int64_t>(mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize),
+ kVec64);
+ fillParameter<uint8_t>(mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize),
+ kVec8);
+ size_t size = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+ for (size_t i = 0; i < size; ++i) {
+ kVecFloat.push_back(mFuzzedDataProvider->ConsumeFloatingPoint<float>());
+ }
+}
+
void VehicleHalManagerFuzzer::process(const uint8_t* data, size_t size) {
mFuzzedDataProvider = new FuzzedDataProvider(data, size);
- invokeDebug();
- invokePropConfigs();
- invokeSubscribe();
- invokeSetAndGetValues();
- invokeObd2SensorStore();
- invokeVmsUtils();
- invokeVehiclePropStore();
- invokeWatchDogClient();
+ initValue();
+ /* Limited while loop runs to prevent timeouts caused
+ * by repeated calls to high-execution-time APIs.
+ */
+ size_t maxRuns = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinSize, kMaxRuns);
+ size_t itr = 0;
+ while (mFuzzedDataProvider->remaining_bytes() && ++itr <= maxRuns) {
+ auto invokeVehicleHalManagerFuzzer =
+ mFuzzedDataProvider->PickValueInArray<const std::function<void()>>({
+ [&]() { invokeDebug(); },
+ [&]() { invokePropConfigs(); },
+ [&]() { invokeSubscribe(); },
+ [&]() { invokeSetAndGetValues(); },
+ [&]() { invokeObd2SensorStore(); },
+ [&]() { invokeVmsUtils(); },
+ [&]() { invokeVehiclePropStore(); },
+ [&]() { invokeWatchDogClient(); },
+ });
+ invokeVehicleHalManagerFuzzer();
+ }
}
void VehicleHalManagerFuzzer::invokeDebug() {
- hidl_string debugOption = mFuzzedDataProvider->PickValueInArray(
- {"--help", "--list", "--get", "--set", "", "invalid"});
hidl_handle fd = {};
native_handle_t* rawHandle = native_handle_create(/*numFds=*/1, /*numInts=*/0);
fd.setTo(native_handle_clone(rawHandle), /*shouldOwn=*/true);
+ int32_t size = mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(kMinSize, kMaxFileSize);
+ hidl_vec<hidl_string> options(size);
- mManager->debug(fd, {});
- mManager->debug(fd, {debugOption});
+ for (int32_t idx = 0; idx < size; ++idx) {
+ if (idx == 0 && mFuzzedDataProvider->ConsumeBool()) {
+ options[idx] = mFuzzedDataProvider->PickValueInArray(
+ {"--help", "--list", "--get", "--set", "", "invalid"});
+ } else if (idx == 2 && mFuzzedDataProvider->ConsumeBool()) {
+ options[idx] =
+ mFuzzedDataProvider->PickValueInArray({"-i", "-i64", "-f", "-s", "-b", "-a"});
+ } else if (mFuzzedDataProvider->ConsumeBool()) {
+ options[idx] = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxSize);
+ } else {
+ options[idx] = std::to_string(mFuzzedDataProvider->ConsumeIntegral<int32_t>());
+ }
+ }
+
+ if (mFuzzedDataProvider->ConsumeBool()) {
+ mManager->debug(fd, {});
+ } else {
+ mManager->debug(fd, options);
+ }
native_handle_delete(rawHandle);
}
@@ -175,178 +209,245 @@
int32_t vehicleProp2 = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
hidl_vec<int32_t> properties = {vehicleProp1, vehicleProp2};
+ auto invokePropConfigsAPI = mFuzzedDataProvider->PickValueInArray<const std::function<void()>>({
+ [&]() {
+ mManager->getPropConfigs(
+ properties, []([[maybe_unused]] StatusCode status,
+ [[maybe_unused]] const hidl_vec<VehiclePropConfig>& c) {});
+ },
+ [&]() {
+ mManager->getPropConfigs(
+ {mFuzzedDataProvider->ConsumeIntegral<int32_t>()},
+ []([[maybe_unused]] StatusCode status,
+ [[maybe_unused]] const hidl_vec<VehiclePropConfig>& c) {});
+ },
+ [&]() {
+ mManager->getAllPropConfigs(
+ []([[maybe_unused]] const hidl_vec<VehiclePropConfig>& propConfigs) {});
+ },
- mManager->getPropConfigs(properties,
- []([[maybe_unused]] StatusCode status,
- [[maybe_unused]] const hidl_vec<VehiclePropConfig>& c) {});
-
- mManager->getPropConfigs({toInt(kVehicleProp[abs(vehicleProp1) % kVehiclePropArrayLength])},
- []([[maybe_unused]] StatusCode status,
- [[maybe_unused]] const hidl_vec<VehiclePropConfig>& c) {});
-
- mManager->getAllPropConfigs(
- []([[maybe_unused]] const hidl_vec<VehiclePropConfig>& propConfigs) {});
+ });
+ invokePropConfigsAPI();
}
void VehicleHalManagerFuzzer::invokeSubscribe() {
- int32_t vehicleProp1 = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
int32_t vehicleProp2 = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
int32_t vehicleProp3 = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
- const auto prop1 = toInt(kVehicleProp[abs(vehicleProp1) % kVehiclePropArrayLength]);
sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
+ VehiclePropertyType type =
+ static_cast<VehiclePropertyType>(mFuzzedDataProvider->ConsumeIntegral<int32_t>());
- hidl_vec<SubscribeOptions> options = {
- SubscribeOptions{.propId = prop1, .flags = SubscribeFlags::EVENTS_FROM_CAR}};
+ auto invokeSubscribeAPI = mFuzzedDataProvider->PickValueInArray<const std::function<void()>>({
+ [&]() {
+ size_t size =
+ mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+ hidl_vec<SubscribeOptions> options(size);
+ for (size_t idx = 0; idx < size; ++idx) {
+ options[idx] = {SubscribeOptions{
+ .propId = mFuzzedDataProvider->ConsumeIntegral<int32_t>(),
+ .flags = static_cast<SubscribeFlags>(
+ mFuzzedDataProvider->ConsumeIntegral<int32_t>())}};
+ }
+ mManager->subscribe(cb, options);
+ },
+ [&]() {
+ auto unsubscribedValue = mObjectPool->obtain(type);
+ if (!unsubscribedValue) {
+ return;
+ }
+ unsubscribedValue->prop = vehicleProp2;
+ unsubscribedValue->value.int32Values[0] = INT32_MAX;
+ mHal->sendPropEvent(std::move(unsubscribedValue));
+ cb->waitForExpectedEvents(mFuzzedDataProvider->ConsumeIntegral<size_t>());
+ },
+ [&]() {
+ const auto prop1 = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
+ mManager->unsubscribe(cb, prop1);
+ },
+ [&]() {
+ mHal->sendHalError(StatusCode::TRY_AGAIN, vehicleProp3,
+ mFuzzedDataProvider->ConsumeIntegral<int32_t>() /*areaId=*/);
+ },
- mManager->subscribe(cb, options);
-
- auto unsubscribedValue = mObjectPool->obtain(VehiclePropertyType::INT32);
- unsubscribedValue->prop = toInt(kVehicleProp[abs(vehicleProp2) % kVehiclePropArrayLength]);
-
- mHal->sendPropEvent(std::move(unsubscribedValue));
- cb->getReceivedEvents();
- cb->waitForExpectedEvents(0);
-
- auto subscribedValue = mObjectPool->obtain(VehiclePropertyType::INT32);
- subscribedValue->prop = toInt(kVehicleProp[abs(vehicleProp2) % kVehiclePropArrayLength]);
- subscribedValue->value.int32Values[0] = INT32_MAX;
-
- cb->reset();
- VehiclePropValue actualValue(*subscribedValue.get());
- mHal->sendPropEvent(std::move(subscribedValue));
- cb->waitForExpectedEvents(1);
- mManager->unsubscribe(cb, prop1);
-
- sp<MockedVehicleCallback> cb2 = new MockedVehicleCallback();
-
- hidl_vec<SubscribeOptions> options2 = {
- SubscribeOptions{
- .propId = toInt(kVehicleProp[abs(vehicleProp3) % kVehiclePropArrayLength]),
- .flags = SubscribeFlags::EVENTS_FROM_CAR},
- };
-
- mManager->subscribe(cb2, options2);
-
- mHal->sendHalError(StatusCode::TRY_AGAIN,
- toInt(kVehicleProp[abs(vehicleProp3) % kVehiclePropArrayLength]),
- /*areaId=*/0);
+ });
+ invokeSubscribeAPI();
}
void VehicleHalManagerFuzzer::invokeSetAndGetValues() {
- uint32_t vehicleProp1 =
- mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kVehiclePropArrayLength - 1);
- uint32_t vehicleProp2 =
- mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kVehiclePropArrayLength - 1);
- uint32_t vehicleProp3 =
- mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kVehiclePropArrayLength - 1);
-
- invokeGet(kCustomComplexProperty, 0);
- invokeGet(toInt(kVehicleProp[vehicleProp2]), 0);
- invokeGet(toInt(kVehicleProp[vehicleProp1]), 0);
-
- auto expectedValue = mObjectPool->obtainInt32(mFuzzedDataProvider->ConsumeIntegral<int32_t>());
- mObjectPool->obtainInt64(mFuzzedDataProvider->ConsumeIntegral<int64_t>());
- mObjectPool->obtainFloat(mFuzzedDataProvider->ConsumeFloatingPoint<float>());
- mObjectPool->obtainBoolean(mFuzzedDataProvider->ConsumeBool());
- expectedValue->prop = toInt(kVehicleProp[vehicleProp2]);
- expectedValue->areaId = 0;
-
- mManager->set(*expectedValue.get());
- invokeGet(toInt(kVehicleProp[vehicleProp2]), 0);
- expectedValue->prop = toInt(kVehicleProp[vehicleProp3]);
- mManager->set(*expectedValue.get());
- expectedValue->prop = toInt(VehicleProperty::INVALID);
- mManager->set(*expectedValue.get());
+ auto invokeSetAndGetAPI = mFuzzedDataProvider->PickValueInArray<const std::function<void()>>({
+ [&]() {
+ invokeGet(mFuzzedDataProvider->ConsumeIntegral<int32_t>(),
+ mFuzzedDataProvider->ConsumeIntegral<int32_t>());
+ },
+ [&]() { mObjectPool->obtainInt64(mFuzzedDataProvider->ConsumeIntegral<int64_t>()); },
+ [&]() { mObjectPool->obtainFloat(mFuzzedDataProvider->ConsumeFloatingPoint<float>()); },
+ [&]() { mObjectPool->obtainBoolean(mFuzzedDataProvider->ConsumeBool()); },
+ [&]() {
+ int32_t vehicleProp2 = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
+ auto expectedValue =
+ mObjectPool->obtainInt32(mFuzzedDataProvider->ConsumeIntegral<int32_t>());
+ expectedValue->prop = vehicleProp2;
+ expectedValue->areaId = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
+ mManager->set(*expectedValue.get());
+ },
+ });
+ invokeSetAndGetAPI();
}
void VehicleHalManagerFuzzer::invokeObd2SensorStore() {
- uint32_t diagnosticIntIndex =
- mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kIntSensorArrayLength - 1);
- int32_t diagnosticIntValue = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
- uint32_t diagnosticFloatIndex =
- mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kFloatSensorArrayLength - 1);
- float diagnosticFloatValue = mFuzzedDataProvider->ConsumeFloatingPoint<float>();
+ size_t diagnosticInt = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+ size_t diagnosticFloat =
+ mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
std::unique_ptr<Obd2SensorStore> sensorStore(
- new Obd2SensorStore(kIntSensorArrayLength, kFloatSensorArrayLength));
- if (sensorStore) {
- sensorStore->setIntegerSensor(kDiagnosticIntIndex[diagnosticIntIndex], diagnosticIntValue);
- sensorStore->setFloatSensor(kDiagnosticFloatIndex[diagnosticFloatIndex],
- diagnosticFloatValue);
- sensorStore->getIntegerSensors();
- sensorStore->getFloatSensors();
- sensorStore->getSensorsBitmask();
- static std::vector<std::string> sampleDtcs = {"P0070",
- "P0102"
- "P0123"};
- for (auto&& dtc : sampleDtcs) {
- auto freezeFrame = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
- sensorStore->fillPropValue(dtc, freezeFrame.get());
- freezeFrame->prop = static_cast<int>(VehicleProperty::OBD2_FREEZE_FRAME);
- }
+ new Obd2SensorStore(diagnosticInt, diagnosticFloat));
+
+ if (!sensorStore.get()) {
+ return;
}
+
+ auto invokeObd2SensorStoreAPI =
+ mFuzzedDataProvider->PickValueInArray<const std::function<void()>>({
+ [&]() {
+ int32_t diagnosticIntValue =
+ mFuzzedDataProvider->ConsumeIntegral<int32_t>();
+ int32_t diagnosticIntIndex =
+ mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(
+ kMinSize,
+ toInt(DiagnosticIntegerSensorIndex::LAST_SYSTEM_INDEX) +
+ diagnosticInt);
+ sensorStore->setIntegerSensor(
+ static_cast<DiagnosticIntegerSensorIndex>(diagnosticIntIndex),
+ diagnosticIntValue);
+ },
+ [&]() {
+ float diagnosticFloatValue =
+ mFuzzedDataProvider->ConsumeFloatingPoint<float>();
+ int32_t diagnosticFloatIndex =
+ mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(
+ kMinSize,
+ toInt(DiagnosticFloatSensorIndex::LAST_SYSTEM_INDEX) +
+ diagnosticFloat);
+ sensorStore->setFloatSensor(
+ static_cast<DiagnosticFloatSensorIndex>(diagnosticFloatIndex),
+ diagnosticFloatValue);
+ },
+ [&]() { sensorStore->getIntegerSensors(); },
+ [&]() { sensorStore->getFloatSensors(); },
+ [&]() { sensorStore->getSensorsBitmask(); },
+ [&]() {
+ for (auto&& dtc : kSampleDtcs) {
+ VehiclePropertyType type = static_cast<VehiclePropertyType>(
+ mFuzzedDataProvider->ConsumeIntegral<int32_t>());
+ auto freezeFrame = createVehiclePropValue(
+ type, mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(
+ kMinSize, kMaxSize));
+ if (!freezeFrame.get()) {
+ return;
+ }
+ freezeFrame->prop = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
+ sensorStore->fillPropValue(dtc, freezeFrame.get());
+ }
+ },
+ });
+ invokeObd2SensorStoreAPI();
}
void VehicleHalManagerFuzzer::invokeVmsUtils() {
- bool availabilityMsgType = mFuzzedDataProvider->ConsumeBool();
- bool subscriptionMsgType = mFuzzedDataProvider->ConsumeBool();
+ std::unique_ptr<VehiclePropValue> message;
int32_t intValue = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
+ VmsLayer layer(mFuzzedDataProvider->ConsumeIntegral<int32_t>(),
+ mFuzzedDataProvider->ConsumeIntegral<int32_t>(),
+ mFuzzedDataProvider->ConsumeIntegral<int32_t>());
+ VmsOffers offers = {
+ intValue,
+ {VmsLayerOffering(VmsLayer(mFuzzedDataProvider->ConsumeIntegral<int32_t>(),
+ mFuzzedDataProvider->ConsumeIntegral<int32_t>(),
+ mFuzzedDataProvider->ConsumeIntegral<int32_t>()))}};
+ const VmsLayerAndPublisher layer_and_publisher(
+ VmsLayer(mFuzzedDataProvider->ConsumeIntegral<int32_t>(),
+ mFuzzedDataProvider->ConsumeIntegral<int32_t>(),
+ mFuzzedDataProvider->ConsumeIntegral<int32_t>()),
+ intValue);
- VmsLayer layer(1, 0, 2);
- auto message = createSubscribeMessage(layer);
+ switch (mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(kMinSize, kMaxCaseMessage)) {
+ case 0: {
+ message = createSubscribeMessage(layer);
+ break;
+ }
+ case 1: {
+ message = createUnsubscribeMessage(layer);
+ break;
+ }
+ case 2: {
+ message = createSubscriptionsRequest();
+ break;
+ }
+ case 3: {
+ message = createOfferingMessage(offers);
+ break;
+ }
+ case 4: {
+ message = createAvailabilityRequest();
+ break;
+ }
+ case 5: {
+ std::string pub_bytes;
+ if (mFuzzedDataProvider->ConsumeBool()) {
+ pub_bytes = "pub_id";
+ } else {
+ pub_bytes = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxFileSize);
+ }
+ message = createPublisherIdRequest(pub_bytes);
+ break;
+ }
+ case 6: {
+ std::string bytes = "placeholder";
+ if (mFuzzedDataProvider->ConsumeBool()) {
+ bytes = "placeholder";
+ } else {
+ bytes = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxFileSize);
+ }
+ message = createDataMessageWithLayerPublisherInfo(layer_and_publisher, bytes);
+ break;
+ }
+ case 7: {
+ message = createBaseVmsMessage(
+ mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+ break;
+ }
+ case 8: {
+ message = createStartSessionMessage(intValue, intValue + 1);
+ break;
+ }
+ }
+
isValidVmsMessage(*message);
- message = createUnsubscribeMessage(layer);
-
- VmsOffers offers = {intValue, {VmsLayerOffering(VmsLayer(1, 0, 2))}};
- message = createOfferingMessage(offers);
- std::vector<VmsLayer> dependencies = {VmsLayer(2, 0, 2), VmsLayer(3, 0, 3)};
- std::vector<VmsLayerOffering> offering = {VmsLayerOffering(layer, dependencies)};
- offers = {intValue, offering};
- message = createOfferingMessage(offers);
-
- message = createAvailabilityRequest();
- message = createSubscriptionsRequest();
-
- std::string bytes = "placeholder";
- const VmsLayerAndPublisher layer_and_publisher(VmsLayer(2, 0, 1), intValue);
- message = createDataMessageWithLayerPublisherInfo(layer_and_publisher, bytes);
- parseData(*message);
- createSubscribeToPublisherMessage(layer_and_publisher);
- createUnsubscribeToPublisherMessage(layer_and_publisher);
-
- std::string pub_bytes = "pub_id";
- message = createPublisherIdRequest(pub_bytes);
- message = createBaseVmsMessage(2);
message->value.int32Values =
- hidl_vec<int32_t>{toInt(VmsMessageType::PUBLISHER_ID_RESPONSE), intValue};
- parsePublisherIdResponse(*message);
+ hidl_vec<int32_t>{mFuzzedDataProvider->ConsumeIntegral<int32_t>(), intValue};
- message->value.int32Values =
- hidl_vec<int32_t>{toInt(kSubscriptionMessageType[subscriptionMsgType]), intValue};
- getSequenceNumberForSubscriptionsState(*message);
-
- message->value.int32Values = hidl_vec<int32_t>{toInt(kSubscriptionMessageType[0]), intValue};
- isSequenceNumberNewer(*message, intValue + 1);
- invokeGetSubscribedLayers(kSubscriptionMessageType[subscriptionMsgType]);
-
- message->value.int32Values =
- hidl_vec<int32_t>{toInt(kAvailabilityMessageType[availabilityMsgType]), 0};
- hasServiceNewlyStarted(*message);
- message = createStartSessionMessage(intValue, intValue + 1);
- parseMessageType(*message);
-
- message->value.int32Values =
- hidl_vec<int32_t>{toInt(kAvailabilityMessageType[availabilityMsgType]), intValue};
- isAvailabilitySequenceNumberNewer(*message, intValue + 1);
-
- message->value.int32Values =
- hidl_vec<int32_t>{toInt(kAvailabilityMessageType[availabilityMsgType]), intValue};
- getSequenceNumberForAvailabilityState(*message);
- message = createBaseVmsMessage(3);
- int new_service_id;
- message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::START_SESSION), 0, -1};
- parseStartSessionMessage(*message, -1, 0, &new_service_id);
+ auto invokeVmsUtilsAPI = mFuzzedDataProvider->PickValueInArray<const std::function<void()>>({
+ [&]() { parseData(*message); },
+ [&]() { createSubscribeToPublisherMessage(layer_and_publisher); },
+ [&]() { createUnsubscribeToPublisherMessage(layer_and_publisher); },
+ [&]() { parsePublisherIdResponse(*message); },
+ [&]() { getSequenceNumberForSubscriptionsState(*message); },
+ [&]() { isSequenceNumberNewer(*message, intValue + 1); },
+ [&]() {
+ invokeGetSubscribedLayers(
+ (VmsMessageType)mFuzzedDataProvider->ConsumeIntegral<int32_t>());
+ },
+ [&]() { hasServiceNewlyStarted(*message); },
+ [&]() { parseMessageType(*message); },
+ [&]() { isAvailabilitySequenceNumberNewer(*message, intValue + 1); },
+ [&]() { getSequenceNumberForAvailabilityState(*message); },
+ [&]() {
+ int32_t new_service_id;
+ parseStartSessionMessage(*message, -1, 0, &new_service_id);
+ },
+ });
+ invokeVmsUtilsAPI();
}
void VehicleHalManagerFuzzer::invokeGet(int32_t property, int32_t areaId) {
@@ -367,27 +468,31 @@
mActualStatusCode = refStatus;
}
-void VehicleHalManagerFuzzer::invokeGetSubscribedLayers(VmsMessageType type) {
- VmsOffers offers = {123,
- {VmsLayerOffering(VmsLayer(1, 0, 1), {VmsLayer(4, 1, 1)}),
- VmsLayerOffering(VmsLayer(2, 0, 1))}};
- auto message = createBaseVmsMessage(16);
- message->value.int32Values = hidl_vec<int32_t>{toInt(type),
- 1234, // sequence number
- 2, // number of layers
- 1, // number of associated layers
- 1, // layer 1
- 0, 1,
- 4, // layer 2
- 1, 1,
- 2, // associated layer
- 0, 1,
- 2, // number of publisher IDs
- 111, // publisher IDs
- 123};
- isValidVmsMessage(*message);
- getSubscribedLayers(*message, offers);
- getAvailableLayers(*message);
+void VehicleHalManagerFuzzer::invokeGetSubscribedLayers(VmsMessageType /*type*/) {
+ int32_t intValue = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
+ VmsOffers offers = {
+ intValue,
+ {VmsLayerOffering(VmsLayer(mFuzzedDataProvider->ConsumeIntegral<int32_t>(),
+ mFuzzedDataProvider->ConsumeIntegral<int32_t>(),
+ mFuzzedDataProvider->ConsumeIntegral<int32_t>()))}};
+ auto message = createBaseVmsMessage(
+ mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinSize, kMaxFileSize));
+ std::vector<int32_t> v;
+ size_t size = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+ for (size_t i = 0; i < size; i++) {
+ v.push_back(mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize));
+ }
+
+ message->value.int32Values = hidl_vec<int32_t>(v);
+ if (!isValidVmsMessage(*message)) {
+ return;
+ }
+
+ if (mFuzzedDataProvider->ConsumeBool()) {
+ getSubscribedLayers(*message, offers);
+ } else {
+ getAvailableLayers(*message);
+ }
}
void VehicleHalManagerFuzzer::invokeVehiclePropStore() {
@@ -398,33 +503,49 @@
.prop = vehicleProp,
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::STATIC,
- .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ .areaConfigs = {VehicleAreaConfig{
+ .areaId = (mFuzzedDataProvider->ConsumeIntegral<int32_t>())}},
};
- store->registerProperty(config);
VehiclePropValue propValue{};
propValue.prop = vehicleProp;
- propValue.areaId = 0;
- store->writeValue(propValue, shouldWriteStatus);
- store->readAllValues();
- store->getAllConfigs();
- store->getConfigOrNull(vehicleProp);
- store->readValuesForProperty(vehicleProp);
- store->readValueOrNull(propValue);
- store->readValueOrNull(propValue.prop, propValue.areaId, 0);
- store->removeValuesForProperty(vehicleProp);
- store->removeValue(propValue);
- store->getConfigOrDie(vehicleProp);
+ propValue.areaId = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
+
+ auto invokeVehiclePropStoreAPI =
+ mFuzzedDataProvider->PickValueInArray<const std::function<void()>>({
+ [&]() { store->registerProperty(config); },
+ [&]() { store->writeValue(propValue, shouldWriteStatus); },
+ [&]() { store->readAllValues(); },
+ [&]() { store->getAllConfigs(); },
+ [&]() { store->getConfigOrNull(vehicleProp); },
+ [&]() { store->readValuesForProperty(vehicleProp); },
+ [&]() { store->readValueOrNull(propValue); },
+ [&]() {
+ store->readValueOrNull(propValue.prop, propValue.areaId,
+ mFuzzedDataProvider->ConsumeIntegralInRange<int64_t>(
+ kMinSize, kMaxFileSize));
+ },
+ [&]() { store->removeValuesForProperty(vehicleProp); },
+ [&]() { store->removeValue(propValue); },
+ [&]() {
+ if (store->getConfigOrNull(vehicleProp)) {
+ store->getConfigOrDie(vehicleProp);
+ }
+ },
+ });
+ invokeVehiclePropStoreAPI();
}
void VehicleHalManagerFuzzer::invokeWatchDogClient() {
- auto service = new VehicleHalManager(mHal.get());
sp<Looper> looper(Looper::prepare(/*opts=*/mFuzzedDataProvider->ConsumeBool()));
- if (auto watchdogClient = ndk::SharedRefBase::make<WatchdogClient>(looper, service);
+ if (auto watchdogClient = ndk::SharedRefBase::make<WatchdogClient>(looper, mManager.get());
watchdogClient->initialize()) {
- watchdogClient->checkIfAlive(-1, TimeoutLength::TIMEOUT_NORMAL);
+ if (mFuzzedDataProvider->ConsumeBool()) {
+ watchdogClient->checkIfAlive(
+ mFuzzedDataProvider->ConsumeIntegral<int32_t>(),
+ (TimeoutLength)mFuzzedDataProvider->ConsumeIntegral<int32_t>());
+ }
watchdogClient->prepareProcessTermination();
}
- delete service;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
diff --git a/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.h b/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.h
index e9335d3..26ac11e 100644
--- a/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.h
+++ b/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.h
@@ -98,6 +98,13 @@
}
void process(const uint8_t* data, size_t size);
+ template <typename T>
+ void fillParameter(size_t size, std::vector<T>& data) {
+ for (size_t i = 0; i < size; ++i) {
+ data.push_back(mFuzzedDataProvider->ConsumeIntegral<T>());
+ }
+ }
+
private:
FuzzedDataProvider* mFuzzedDataProvider = nullptr;
VehiclePropValue mActualValue = VehiclePropValue{};
@@ -108,6 +115,7 @@
std::unique_ptr<VehicleHalManager> mManager;
void invokeDebug();
+ void initValue();
void invokePropConfigs();
void invokeSubscribe();
void invokeSetAndGetValues();
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index 0bcafa3..c283148 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -439,6 +439,9 @@
}
void BluetoothAudioSession::ReportLowLatencyModeAllowedChanged(bool allowed) {
+ if (session_type_ != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+ return;
+ }
std::lock_guard<std::recursive_mutex> guard(mutex_);
low_latency_allowed_ = allowed;
// TODO(b/294498919): Remove this after there is API to update latency mode
@@ -588,15 +591,32 @@
<< " has NO session";
return std::vector<LatencyMode>();
}
- if (low_latency_allowed_) return latency_modes_;
- std::vector<LatencyMode> modes;
- for (LatencyMode mode : latency_modes_) {
- if (mode == LatencyMode::LOW_LATENCY)
- // ignore those low latency mode if Bluetooth stack doesn't allow
- continue;
- modes.push_back(mode);
+
+ std::vector<LatencyMode> supported_latency_modes;
+ if (session_type_ ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+ for (LatencyMode mode : latency_modes_) {
+ if (mode == LatencyMode::LOW_LATENCY) {
+ // LOW_LATENCY is not supported for LE_HARDWARE_OFFLOAD_ENC sessions
+ continue;
+ }
+ supported_latency_modes.push_back(mode);
+ }
+ } else {
+ for (LatencyMode mode : latency_modes_) {
+ if (!low_latency_allowed_ && mode == LatencyMode::LOW_LATENCY) {
+ // ignore LOW_LATENCY mode if Bluetooth stack doesn't allow
+ continue;
+ }
+ if (mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_SOFTWARE ||
+ mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_HARDWARE) {
+ // DSA_SW and DSA_HW only supported for LE_HARDWARE_OFFLOAD_ENC sessions
+ continue;
+ }
+ supported_latency_modes.push_back(mode);
+ }
}
- return modes;
+ return supported_latency_modes;
}
void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Arc.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/Arc.cddl
index 4c1b965..0bc39d6 100644
--- a/security/authgraph/aidl/android/hardware/security/authgraph/Arc.cddl
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/Arc.cddl
@@ -28,19 +28,19 @@
? -70003 : int, ; Timestamp in milliseconds since some starting point (generally
; the most recent device boot) which all of the applications within
; the secure domain must agree upon
- ? -70004 : bstr .size 16, ; Nonce used in key exchange methods
+ ? -70004 : bstr .size 16, ; Nonce (a cryptographic random number of 16 bytes) used in key
+ ; exchange methods
? -70005 : PayloadType, ; Payload type, if needed to disambiguate, when processing an arc
? -70006 : int, ; Version of the payload structure (if applicable)
? -70007 : int, ; Sequence number (if needed to prevent replay attacks)
? -70008 : Direction ; Direction of the encryption key (i.e. whether it is used to
; encrypt incoming messages or outgoing messages)
? -70009 : bool, ; "authentication_completed" - this is used during authenticated
- ; key exchange indicate whether signature verification is done
- ? -70010 : bstr .size 32 ; "session_id" computed during key exchange protocol
+ ; key exchange to indicate whether signature verification is done
+ ? -70010 : bstr .size 32 ; "session_id" computed during the key exchange protocol
}
-; Permissions indicate what an arc can be used with. Permissions are added to an arc during the
-; `create()` primitive operation and are propagated during `mint` and `snap` primitive operations.
+; Permissions indicate what an arc can be used with.
Permission = &(
-4770552 : IdentityEncoded, ; "source_id" - in the operations performed by a source, the
; source adds its own identity to the permissions of an arc.
@@ -54,12 +54,10 @@
; biometrics.
)
-; Limitations indicate what restrictions are applied on the usage of an arc. Permissions are added
-; to an arc during the `create` primitive operation and are propagated during `snap` primitive
-; operation.
+; Limitations indicate what restrictions are applied on the usage of an arc.
Limitation = &(
- -4770554 : bstr, ; "challenge" - is added to an arc that transfers an auth key to a channel
- ; key, in order to ensure the freshness of the authentication.
+ -4770554 : bstr, ; "challenge" - is added to an arc that encrypts an auth key from a
+ ; channel key, in order to ensure the freshness of the authentication.
; A challenge is issued by a sink (e.g. Keymint TA, Biometric TAs).
)
@@ -83,7 +81,7 @@
; Any other payload formats should also be defined here
)
-SecretKey = &( ; One of the payload types of an Arc is a secret key
+SecretKey = &(
SymmetricKey,
ECPrivateKey, ; Private key of a key pair generated for key exchange
)
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl
index 6ceb09c..a3fb959 100644
--- a/security/authgraph/aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl
@@ -41,8 +41,8 @@
interface IAuthGraphKeyExchange {
/**
* This method is invoked on P1 (source).
- * Create an ephermeral EC key pair on NIST curve P-256 and a nonce (of 16 bytes) for
- * key exchange.
+ * Create an ephermeral EC key pair on NIST curve P-256 and a nonce (a cryptographic random
+ * number of 16 bytes) for key exchange.
*
* @return SessionInitiationInfo including the `Key` containing the public key of the created
* key pair and an arc from the per-boot key to the private key, the nonce, the persistent
@@ -52,8 +52,8 @@
* `SessionInitiationInfo` serves two purposes:
* i. A mapping to correlate `create` and `finish` calls to P1 in a particular instance of the
* key exchange protocol.
- * ii.A way to minimize the in-memory storage (P1 can include the nonce in the protected headers
- * of the arc).
+ * ii.A way to minimize the in-memory storage of P1 allocated for key exchange (P1 can include
+ * the nonce in the protected headers of the arc).
* However, P1 should maintain some form of in-memory record to be able to verify that the input
* `Key` sent to `finish` is from an unfinished instance of a key exchange protocol, to prevent
* any replay attacks in `finish`.
@@ -66,9 +66,9 @@
* 0. If either `peerPubKey`, `peerId`, `peerNonce` is not in the expected format, return
* errors: INVALID_PEER_KE_KEY, INVALID_IDENTITY, INVALID_PEER_NONCE respectively.
* 1. Create an ephemeral EC key pair on NIST curve P-256.
- * 2. Create a nonce (of 16 bytes).
- * 3. Compute the diffie-hellman shared secret: Z.
- * 4. Compute a salt = bstr .cbor [
+ * 2. Create a nonce (a cryptographic random number of 16 bytes).
+ * 3. Compute the Diffie-Hellman shared secret: Z.
+ * 4. Compute a salt_input = bstr .cbor [
* source_version: int, ; from input `peerVersion`
* sink_pub_key: bstr .cbor PlainPubKey, ; from step #1
* source_pub_key: bstr .cbor PlainPubKey, ; from input `peerPubKey`
@@ -77,7 +77,8 @@
* sink_cert_chain: bstr .cbor ExplicitKeyDiceCertChain, ; from own identity
* source_cert_chain: bstr .cbor ExplicitKeyDiceCertChain, ; from input `peerId`
* ]
- * 5. Extract a cryptographic secret S from Z, using the salt from #4 above.
+ * 5. Extract a cryptographic secret S from Z, using the SHA256 digest of the salt_input
+ * as the salt.
* 6. Derive two symmetric encryption keys of 256 bits with:
* i. b"KE_ENCRYPTION_KEY_SOURCE_TO_SINK" as context for the key used to encrypt incoming
* messages
@@ -96,28 +97,29 @@
* part of the party's identity.
*
* @param peerPubKey - the public key of the key pair created by the peer (P1) for key exchange
+ * in `create`
*
* @param peerId - the persistent identity of the peer
*
- * @param peerNonce - nonce created by the peer
+ * @param peerNonce - nonce created by the peer in `create`
*
* @param peerVersion - an integer representing the latest protocol version (i.e. AIDL version)
* supported by the peer
*
- * @return KeInitResult including the `Key` containing the public key of the created key pair,
- * the nonce, the persistent identity, two shared key arcs from step #7, session id, signature
- * over the session id and the negotiated protocol version. The negotiated protocol version
- * should be less than or equal to the peer's version.
+ * @return KeInitResult including the `Key` containing the public key of the key pair created in
+ * step #1, the nonce from step #2, the persistent identity of P2, two shared key arcs
+ * from step #7, session id from step #10, signature over the session id from step #11 and the
+ * negotiated protocol version. The negotiated protocol version should be less than or equal to
+ * the `peerVersion`.
*
- * Note: The two shared key arcs in the return type: `KeInitResult` serves two purposes:
+ * Note: The two shared key arcs in the return type: `KeInitResult` serve two purposes:
* i. A mapping to correlate `init` and `authenticationComplete` calls to P2 in a particular
* instance of the key exchange protocol.
* ii.A way to minimize the in-memory storage of P2 allocated for key exchange.
* However, P2 should maintain some in-memory record to be able to verify that the input
- * `sharedkeys` sent to `authenticationComplete` and to any subsequent AuthGraph protocol
- * methods are valid shared keys agreed with the party identified by `peerId`, to prevent
- * any replay attacks in `authenticationComplete` and in any subsequent AuthGraph protocol
- * methods which use the shared keys to encrypt the secret messages.
+ * `sharedkeys` sent to `authenticationComplete` are from an unfinished instance of a key
+ * exchange protocol carried out with the party identified by `peerId`, to prevent any replay
+ * attacks in `authenticationComplete`.
*/
KeInitResult init(
in PubKey peerPubKey, in Identity peerId, in byte[] peerNonce, in int peerVersion);
@@ -133,8 +135,8 @@
* exchange protocol, return error: INVALID_KE_KEY. Similarly, if the public key or the
* arc containing the private key in `ownKey` is invalid, return INVALID_PUB_KEY_IN_KEY
* and INVALID_PRIV_KEY_ARC_IN_KEY respectively.
- * 1. Compute the diffie-hellman shared secret: Z.
- * 2. Compute a salt = bstr .cbor [
+ * 1. Compute the Diffie-Hellman shared secret: Z.
+ * 2. Compute a salt_input = bstr .cbor [
* source_version: int, ; the protocol version used in `create`
* sink_pub_key: bstr .cbor PlainPubKey, ; from input `peerPubKey`
* source_pub_key: bstr .cbor PlainPubKey, ; from the output of `create`
@@ -143,7 +145,8 @@
* sink_cert_chain: bstr .cbor ExplicitKeyDiceCertChain, ; from input `peerId`
* source_cert_chain: bstr .cbor ExplicitKeyDiceCertChain, ; from own identity
* ]
- * 3. Extract a cryptographic secret S from Z, using the salt from #2 above.
+ * 3. Extract a cryptographic secret S from Z, using the SHA256 digest of the salt_input
+ * as the salt.
* 4. Derive two symmetric encryption keys of 256 bits with:
* i. b"KE_ENCRYPTION_KEY_SOURCE_TO_SINK" as context for the key used to encrypt outgoing
* messages
@@ -164,25 +167,26 @@
* part of the party's identity.
*
* @param peerPubKey - the public key of the key pair created by the peer (P2) for key exchange
+ * in `init`
*
* @param peerId - the persistent identity of the peer
*
* @param peerSignature - the signature created by the peer over the session id computed by the
- * peer
+ * peer in `init`
*
- * @param peerNonce - nonce created by the peer
+ * @param peerNonce - nonce created by the peer in `init`
*
* @param peerVersion - an integer representing the protocol version (i.e. AIDL version)
* negotiated with the peer
*
- * @param ownKey - the key created by P1 (source) in `create()` for key exchange
+ * @param ownKey - the key created by P1 (source) in `create` for key exchange
*
- * @return SessionInfo including the two shared key arcs from step #9, session id and the
- * signature over the session id.
+ * @return SessionInfo including the two shared key arcs from step #9, session id from step #7
+ * and the signature over the session id from step #10.
*
- * Note: The two shared key arcs in the return type: `SessionInfo` serves two purposes:
+ * Note: The two shared key arcs in the return type: `SessionInfo` serve two purposes:
* i. A mapping to correlate the key exchange protocol taken place with a particular peer and
- * subsequent AuthGraph protocols execued with the same peer.
+ * subsequent AuthGraph protocols executed with the same peer.
* ii.A way to minimize the in-memory storage for shared keys.
* However, P1 should maintain some in-memory record to be able to verify that the shared key
* arcs sent to any subsequent AuthGraph protocol methods are valid shared keys agreed with the
@@ -196,21 +200,33 @@
* This method is invoked on P2 (sink).
* Perform the following steps:
* 0. If input `sharedKeys` is invalid (i.e. they cannot be decrypted with P2's per-boot key
- * or they are not in P2's in-memory records as valid shared keys agreed with the party
- * identified by `peerId`), return error: INVALID_SHARED_KEY_ARCS.
+ * or they are not in P2's in-memory records for unfinished instances of a key exchange
+ * protocol carried out with the party identified by the identity included in the
+ * `source_id` protected header of the shared key arcs),
+ * return error: INVALID_SHARED_KEY_ARCS.
* 1. Verify that both shared key arcs have the same session id and peer identity.
- * 2. Verify the peer's signature over the session id attached to the shared key arcs'
- * headers. If successful, proceed, otherwise, return error: INVALID_SIGNATURE.
- * 3. Mark authentication_complete = true in the shared key arcs' headers
+ * 2. Verify the `peerSignature` over the session id included in the `session_id` protected
+ * header of the shared key arcs.
+ * If successful, proceed, otherwise, return error: INVALID_SIGNATURE.
+ * 3. Mark authentication_complete = true in the shared key arcs' headers.
*
* @param peerSignature - the signature created by the peer over the session id computed by the
- * peer
+ * peer in `finish`
*
* @param sharedKeys - two shared key arcs created by P2 in `init`. P2 obtains from the arcs'
* protected headers, the session id and the peer's identity to verify the
* peer's signature over the session id.
*
* @return Arc[] - an array of two updated shared key arcs
+ *
+ * Note: The two returned shared key arcs serve two purposes:
+ * i. A mapping to correlate the key exchange protocol taken place with a particular peer and
+ * subsequent AuthGraph protocols executed with the same peer.
+ * ii.A way to minimize the in-memory storage for shared keys.
+ * However, P2 should maintain some in-memory record to be able to verify that the shared key
+ * arcs sent to any subsequent AuthGraph protocol methods are valid shared keys agreed with the
+ * party identified by the identity included in the `source_id` protected header of the shared
+ * key arcs, to prevent any replay attacks.
*/
Arc[2] authenticationComplete(in SessionIdSignature peerSignature, in Arc[2] sharedKeys);
}
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SessionInfo.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInfo.aidl
index ef49a1a..82b8c17 100644
--- a/security/authgraph/aidl/android/hardware/security/authgraph/SessionInfo.aidl
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInfo.aidl
@@ -26,8 +26,8 @@
@RustDerive(Clone=true, Eq=true, PartialEq=true)
parcelable SessionInfo {
/**
- * The arcs that encrypt the two derived symmetric encryption keys (for two-way communication)
- * from the party's per-boot key.
+ * The arcs that encrypt the two derived symmetric encryption keys (for two-way communication).
+ * The encryption key is the party's per-boot key.
*/
Arc[2] sharedKeys;
diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SessionInitiationInfo.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInitiationInfo.aidl
index c630d91..8179ac2 100644
--- a/security/authgraph/aidl/android/hardware/security/authgraph/SessionInitiationInfo.aidl
+++ b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInitiationInfo.aidl
@@ -27,20 +27,22 @@
@RustDerive(Clone=true, Eq=true, PartialEq=true)
parcelable SessionInitiationInfo {
/**
- * An ephemeral EC key created for the ECDH process.
+ * An ephemeral EC key created for the Elliptic-curve Diffie-Hellman (ECDH) process.
*/
Key key;
/**
- * The identity of the party who created the Diffie-Hellman key exchange key.
+ * The identity of the party who creates this `SessionInitiationInfo`.
*/
Identity identity;
/**
- * Nonce value specific to this session. The nonce serves three purposes:
+ * Nonce (a cryptographic random number of 16 bytes) specific to this session.
+ * The nonce serves three purposes:
* 1. freshness of key exchange
* 2. creating a session id (a publicly known value related to the exchanged keys)
- * 3. usage as salt into the HKDF-EXTRACT function during key derivation from the shared DH key
+ * 3. usage as salt into the HKDF-EXTRACT function during key derivation from the Diffie-Hellman
+ * shared secret
*/
byte[] nonce;
diff --git a/security/authgraph/aidl/vts/functional/lib.rs b/security/authgraph/aidl/vts/functional/lib.rs
index 7b9b2b9..da3fa1c 100644
--- a/security/authgraph/aidl/vts/functional/lib.rs
+++ b/security/authgraph/aidl/vts/functional/lib.rs
@@ -24,22 +24,19 @@
PlainPubKey::PlainPubKey, PubKey::PubKey, SessionIdSignature::SessionIdSignature,
};
use authgraph_boringssl as boring;
-use authgraph_core::keyexchange as ke;
-use authgraph_core::{arc, key, traits};
-use authgraph_nonsecure::StdClock;
+use authgraph_core::{error::Error as AgError, keyexchange as ke};
use coset::CborSerializable;
pub mod sink;
pub mod source;
-/// Return a collection of AuthGraph trait implementations suitable for testing.
-pub fn test_impls() -> traits::TraitImpl {
- // Note that the local implementation is using a clock with a potentially different epoch than
- // the implementation under test.
- boring::trait_impls(
+/// Return an AuthGraphParticipant suitable for testing.
+pub fn test_ag_participant() -> Result<ke::AuthGraphParticipant, AgError> {
+ Ok(ke::AuthGraphParticipant::new(
+ boring::crypto_trait_impls(),
Box::<boring::test_device::AgDevice>::default(),
- Some(Box::new(StdClock::default())),
- )
+ ke::MAX_OPENED_SESSIONS,
+ )?)
}
fn build_plain_pub_key(pub_key: &Option<Vec<u8>>) -> PubKey {
@@ -56,14 +53,6 @@
}
}
-fn verification_key_from_identity(impls: &traits::TraitImpl, identity: &[u8]) -> key::EcVerifyKey {
- let identity = key::Identity::from_slice(identity).expect("invalid identity CBOR");
- impls
- .device
- .process_peer_cert_chain(&identity.cert_chain, &*impls.ecdsa)
- .expect("failed to extract signing key")
-}
-
fn vec_to_identity(data: &[u8]) -> Identity {
Identity {
identity: data.to_vec(),
@@ -75,26 +64,3 @@
signature: data.to_vec(),
}
}
-
-/// Decrypt a pair of AES-256 keys encrypted with the AuthGraph PBK.
-pub fn decipher_aes_keys(imp: &traits::TraitImpl, arc: &[Vec<u8>; 2]) -> [key::AesKey; 2] {
- [
- decipher_aes_key(imp, &arc[0]),
- decipher_aes_key(imp, &arc[1]),
- ]
-}
-
-/// Decrypt an AES-256 key encrypted with the AuthGraph PBK.
-pub fn decipher_aes_key(imp: &traits::TraitImpl, arc: &[u8]) -> key::AesKey {
- let pbk = imp.device.get_per_boot_key().expect("no PBK available");
- let arc::ArcContent {
- payload,
- protected_headers: _,
- unprotected_headers: _,
- } = arc::decipher_arc(&pbk, arc, &*imp.aes_gcm).expect("failed to decrypt arc");
- assert_eq!(payload.0.len(), 32);
- let mut key = key::AesKey([0; 32]);
- key.0.copy_from_slice(&payload.0);
- assert_ne!(key.0, [0; 32], "agreed AES-256 key should be non-zero");
- key
-}
diff --git a/security/authgraph/aidl/vts/functional/role_test.rs b/security/authgraph/aidl/vts/functional/role_test.rs
index e95361a..71a2fae 100644
--- a/security/authgraph/aidl/vts/functional/role_test.rs
+++ b/security/authgraph/aidl/vts/functional/role_test.rs
@@ -48,31 +48,31 @@
#[test]
fn test_nonsecure_source_mainline() {
- let mut impls = vts::test_impls();
- vts::source::test_mainline(&mut impls, require_nonsecure!());
+ let mut sink = vts::test_ag_participant().expect("failed to create a local sink");
+ vts::source::test_mainline(&mut sink, require_nonsecure!());
}
#[test]
fn test_nonsecure_source_corrupt_sig() {
- let mut impls = vts::test_impls();
- vts::source::test_corrupt_sig(&mut impls, require_nonsecure!());
+ let mut sink = vts::test_ag_participant().expect("failed to create a local sink");
+ vts::source::test_corrupt_sig(&mut sink, require_nonsecure!());
}
#[test]
fn test_nonsecure_source_corrupt_keys() {
- let mut impls = vts::test_impls();
- vts::source::test_corrupt_key(&mut impls, require_nonsecure!());
+ let mut sink = vts::test_ag_participant().expect("failed to create a local sink");
+ vts::source::test_corrupt_key(&mut sink, require_nonsecure!());
}
#[test]
fn test_nonsecure_sink_mainline() {
- let mut impls = vts::test_impls();
- vts::sink::test_mainline(&mut impls, require_nonsecure!());
+ let mut source = vts::test_ag_participant().expect("failed to create a local source");
+ vts::sink::test_mainline(&mut source, require_nonsecure!());
}
#[test]
fn test_nonsecure_sink_corrupt_sig() {
- let mut impls = vts::test_impls();
- vts::sink::test_corrupt_sig(&mut impls, require_nonsecure!());
+ let mut source = vts::test_ag_participant().expect("failed to create a local source");
+ vts::sink::test_corrupt_sig(&mut source, require_nonsecure!());
}
#[test]
fn test_nonsecure_sink_corrupt_keys() {
- let mut impls = vts::test_impls();
- vts::sink::test_corrupt_keys(&mut impls, require_nonsecure!());
+ let mut source = vts::test_ag_participant().expect("failed to create a local source");
+ vts::sink::test_corrupt_keys(&mut source, require_nonsecure!());
}
diff --git a/security/authgraph/aidl/vts/functional/sink.rs b/security/authgraph/aidl/vts/functional/sink.rs
index 5c81593..bb357b8 100644
--- a/security/authgraph/aidl/vts/functional/sink.rs
+++ b/security/authgraph/aidl/vts/functional/sink.rs
@@ -16,23 +16,28 @@
//! VTS tests for sinks
use super::*;
-use authgraph_core::traits;
+use authgraph_core::{key, keyexchange as ke};
/// Run AuthGraph tests against the provided sink, using a local test source implementation.
-pub fn test(impls: &mut traits::TraitImpl, sink: binder::Strong<dyn IAuthGraphKeyExchange>) {
- test_mainline(impls, sink.clone());
- test_corrupt_sig(impls, sink.clone());
- test_corrupt_keys(impls, sink);
+pub fn test(
+ local_source: &mut ke::AuthGraphParticipant,
+ sink: binder::Strong<dyn IAuthGraphKeyExchange>,
+) {
+ test_mainline(local_source, sink.clone());
+ test_corrupt_sig(local_source, sink.clone());
+ test_corrupt_keys(local_source, sink);
}
/// Perform mainline AuthGraph key exchange with the provided sink and local implementation.
/// Return the agreed AES keys in plaintext.
pub fn test_mainline(
- impls: &mut traits::TraitImpl,
+ local_source: &mut ke::AuthGraphParticipant,
sink: binder::Strong<dyn IAuthGraphKeyExchange>,
) -> [key::AesKey; 2] {
// Step 1: create an ephemeral ECDH key at the (local) source.
- let source_init_info = ke::create(impls).expect("failed to create() with local impl");
+ let source_init_info = local_source
+ .create()
+ .expect("failed to create() with local impl");
// Step 2: pass the source's ECDH public key and other session info to the (remote) sink.
let init_result = sink
@@ -50,40 +55,43 @@
assert!(!sink_info.sessionId.is_empty());
// The AuthGraph core library will verify the session ID signature, but do it here too.
- let sink_verification_key =
- verification_key_from_identity(&impls, &sink_init_info.identity.identity);
- ke::verify_signature_on_session_id(
- &sink_verification_key,
- &sink_info.sessionId,
- &sink_info.signature.signature,
- &*impls.ecdsa,
- )
- .expect("failed verification of signed session ID");
+ let sink_verification_key = local_source
+ .peer_verification_key_from_identity(&sink_init_info.identity.identity)
+ .expect("failed to get peer verification from identity");
+ local_source
+ .verify_signature_on_session_id(
+ &sink_verification_key,
+ &sink_info.sessionId,
+ &sink_info.signature.signature,
+ )
+ .expect("failed verification of signed session ID");
// Step 3: pass the sink's ECDH public key and other session info to the (local) source, so it
// can calculate the same pair of symmetric keys.
- let source_info = ke::finish(
- impls,
- &sink_pub_key.plainPubKey,
- &sink_init_info.identity.identity,
- &sink_info.signature.signature,
- &sink_init_info.nonce,
- sink_init_info.version,
- source_init_info.ke_key,
- )
- .expect("failed to finish() with local impl");
+ let source_info = local_source
+ .finish(
+ &sink_pub_key.plainPubKey,
+ &sink_init_info.identity.identity,
+ &sink_info.signature.signature,
+ &sink_init_info.nonce,
+ sink_init_info.version,
+ source_init_info.ke_key,
+ )
+ .expect("failed to finish() with local impl");
assert!(!source_info.session_id.is_empty());
// The AuthGraph core library will verify the session ID signature, but do it here too.
- let source_verification_key =
- verification_key_from_identity(&impls, &source_init_info.identity);
- ke::verify_signature_on_session_id(
- &source_verification_key,
- &source_info.session_id,
- &source_info.session_id_signature,
- &*impls.ecdsa,
- )
- .expect("failed verification of signed session ID");
+ let source_verification_key = key::Identity::from_slice(&source_init_info.identity)
+ .expect("invalid identity CBOR")
+ .cert_chain
+ .root_key;
+ local_source
+ .verify_signature_on_session_id(
+ &source_verification_key,
+ &source_info.session_id,
+ &source_info.session_id_signature,
+ )
+ .expect("failed verification of signed session ID");
// Both ends should agree on the session ID.
assert_eq!(source_info.session_id, sink_info.sessionId);
@@ -96,19 +104,28 @@
&sink_info.sharedKeys,
)
.expect("failed to authenticationComplete() with remote sink");
-
// Decrypt and return the session keys.
- decipher_aes_keys(&impls, &source_info.shared_keys)
+ let decrypted_shared_keys = local_source
+ .decipher_shared_keys_from_arcs(&source_info.shared_keys)
+ .expect("failed to decrypt shared key arcs")
+ .try_into();
+ let decrypted_shared_keys_array = match decrypted_shared_keys {
+ Ok(array) => array,
+ Err(_) => panic!("wrong number of decrypted shared key arcs"),
+ };
+ decrypted_shared_keys_array
}
/// Perform mainline AuthGraph key exchange with the provided sink, but provide an invalid
/// session ID signature.
pub fn test_corrupt_sig(
- impls: &mut traits::TraitImpl,
+ local_source: &mut ke::AuthGraphParticipant,
sink: binder::Strong<dyn IAuthGraphKeyExchange>,
) {
// Step 1: create an ephemeral ECDH key at the (local) source.
- let source_init_info = ke::create(impls).expect("failed to create() with local impl");
+ let source_init_info = local_source
+ .create()
+ .expect("failed to create() with local impl");
// Step 2: pass the source's ECDH public key and other session info to the (remote) sink.
let init_result = sink
@@ -127,16 +144,16 @@
// Step 3: pass the sink's ECDH public key and other session info to the (local) source, so it
// can calculate the same pair of symmetric keys.
- let source_info = ke::finish(
- impls,
- &sink_pub_key.plainPubKey,
- &sink_init_info.identity.identity,
- &sink_info.signature.signature,
- &sink_init_info.nonce,
- sink_init_info.version,
- source_init_info.ke_key,
- )
- .expect("failed to finish() with local impl");
+ let source_info = local_source
+ .finish(
+ &sink_pub_key.plainPubKey,
+ &sink_init_info.identity.identity,
+ &sink_info.signature.signature,
+ &sink_init_info.nonce,
+ sink_init_info.version,
+ source_init_info.ke_key,
+ )
+ .expect("failed to finish() with local impl");
assert!(!source_info.session_id.is_empty());
// Build a corrupted version of the (local) source's session ID signature.
@@ -158,11 +175,13 @@
/// Perform mainline AuthGraph key exchange with the provided sink, but provide an invalid
/// Arc for the sink's key.
pub fn test_corrupt_keys(
- impls: &mut traits::TraitImpl,
+ local_source: &mut ke::AuthGraphParticipant,
sink: binder::Strong<dyn IAuthGraphKeyExchange>,
) {
// Step 1: create an ephemeral ECDH key at the (local) source.
- let source_init_info = ke::create(impls).expect("failed to create() with local impl");
+ let source_init_info = local_source
+ .create()
+ .expect("failed to create() with local impl");
// Step 2: pass the source's ECDH public key and other session info to the (remote) sink.
let init_result = sink
@@ -181,16 +200,16 @@
// Step 3: pass the sink's ECDH public key and other session info to the (local) source, so it
// can calculate the same pair of symmetric keys.
- let source_info = ke::finish(
- impls,
- &sink_pub_key.plainPubKey,
- &sink_init_info.identity.identity,
- &sink_info.signature.signature,
- &sink_init_info.nonce,
- sink_init_info.version,
- source_init_info.ke_key,
- )
- .expect("failed to finish() with local impl");
+ let source_info = local_source
+ .finish(
+ &sink_pub_key.plainPubKey,
+ &sink_init_info.identity.identity,
+ &sink_info.signature.signature,
+ &sink_init_info.nonce,
+ sink_init_info.version,
+ source_init_info.ke_key,
+ )
+ .expect("failed to finish() with local impl");
assert!(!source_info.session_id.is_empty());
// Deliberately corrupt the sink's shared key Arcs before returning them
diff --git a/security/authgraph/aidl/vts/functional/source.rs b/security/authgraph/aidl/vts/functional/source.rs
index 9aaaaee..4178a99 100644
--- a/security/authgraph/aidl/vts/functional/source.rs
+++ b/security/authgraph/aidl/vts/functional/source.rs
@@ -16,19 +16,22 @@
//! VTS tests for sources
use super::*;
-use authgraph_core::traits;
+use authgraph_core::{key, keyexchange as ke};
/// Run AuthGraph tests against the provided source, using a local test sink implementation.
-pub fn test(impls: &mut traits::TraitImpl, source: binder::Strong<dyn IAuthGraphKeyExchange>) {
- test_mainline(impls, source.clone());
- test_corrupt_sig(impls, source.clone());
- test_corrupt_key(impls, source);
+pub fn test(
+ local_sink: &mut ke::AuthGraphParticipant,
+ source: binder::Strong<dyn IAuthGraphKeyExchange>,
+) {
+ test_mainline(local_sink, source.clone());
+ test_corrupt_sig(local_sink, source.clone());
+ test_corrupt_key(local_sink, source);
}
/// Perform mainline AuthGraph key exchange with the provided source.
/// Return the agreed AES keys in plaintext.
pub fn test_mainline(
- impls: &mut traits::TraitImpl,
+ local_sink: &mut ke::AuthGraphParticipant,
source: binder::Strong<dyn IAuthGraphKeyExchange>,
) -> [key::AesKey; 2] {
// Step 1: create an ephemeral ECDH key at the (remote) source.
@@ -40,14 +43,14 @@
let source_pub_key = extract_plain_pub_key(&source_init_info.key.pubKey);
// Step 2: pass the source's ECDH public key and other session info to the (local) sink.
- let init_result = ke::init(
- impls,
- &source_pub_key.plainPubKey,
- &source_init_info.identity.identity,
- &source_init_info.nonce,
- source_init_info.version,
- )
- .expect("failed to init() with local impl");
+ let init_result = local_sink
+ .init(
+ &source_pub_key.plainPubKey,
+ &source_init_info.identity.identity,
+ &source_init_info.nonce,
+ source_init_info.version,
+ )
+ .expect("failed to init() with local impl");
let sink_init_info = init_result.session_init_info;
let sink_pub_key = sink_init_info
.ke_key
@@ -58,14 +61,17 @@
assert!(!sink_info.session_id.is_empty());
// The AuthGraph core library will verify the session ID signature, but do it here too.
- let sink_verification_key = verification_key_from_identity(&impls, &sink_init_info.identity);
- ke::verify_signature_on_session_id(
- &sink_verification_key,
- &sink_info.session_id,
- &sink_info.session_id_signature,
- &*impls.ecdsa,
- )
- .expect("failed verification of signed session ID");
+ let sink_verification_key = key::Identity::from_slice(&sink_init_info.identity)
+ .expect("invalid identity CBOR")
+ .cert_chain
+ .root_key;
+ local_sink
+ .verify_signature_on_session_id(
+ &sink_verification_key,
+ &sink_info.session_id,
+ &sink_info.session_id_signature,
+ )
+ .expect("failed verification of signed session ID");
// Step 3: pass the sink's ECDH public key and other session info to the (remote) source, so it
// can calculate the same pair of symmetric keys.
@@ -86,36 +92,41 @@
assert!(!source_info.sessionId.is_empty());
// The AuthGraph core library will verify the session ID signature, but do it here too.
- let source_verification_key =
- verification_key_from_identity(&impls, &source_init_info.identity.identity);
- ke::verify_signature_on_session_id(
- &source_verification_key,
- &source_info.sessionId,
- &source_info.signature.signature,
- &*impls.ecdsa,
- )
- .expect("failed verification of signed session ID");
+ let source_verification_key = local_sink
+ .peer_verification_key_from_identity(&source_init_info.identity.identity)
+ .expect("failed to get peer verification from identity");
+ local_sink
+ .verify_signature_on_session_id(
+ &source_verification_key,
+ &source_info.sessionId,
+ &source_info.signature.signature,
+ )
+ .expect("failed verification of signed session ID");
// Both ends should agree on the session ID.
assert_eq!(source_info.sessionId, sink_info.session_id);
// Step 4: pass the (remote) source's session ID signature back to the sink, so it can check it
// and update the symmetric keys so they're marked as authentication complete.
- let sink_arcs = ke::authentication_complete(
- impls,
- &source_info.signature.signature,
- sink_info.shared_keys,
- )
- .expect("failed to authenticationComplete() with local sink");
-
+ let sink_arcs = local_sink
+ .authentication_complete(&source_info.signature.signature, sink_info.shared_keys)
+ .expect("failed to authenticationComplete() with local sink");
// Decrypt and return the session keys.
- decipher_aes_keys(&impls, &sink_arcs)
+ let decrypted_shared_keys = local_sink
+ .decipher_shared_keys_from_arcs(&sink_arcs)
+ .expect("failed to decrypt shared key arcs")
+ .try_into();
+ let decrypted_shared_keys_array = match decrypted_shared_keys {
+ Ok(array) => array,
+ Err(_) => panic!("wrong number of decrypted shared key arcs"),
+ };
+ decrypted_shared_keys_array
}
/// Perform mainline AuthGraph key exchange with the provided source, but provide an invalid session
/// ID signature.
pub fn test_corrupt_sig(
- impls: &mut traits::TraitImpl,
+ local_sink: &mut ke::AuthGraphParticipant,
source: binder::Strong<dyn IAuthGraphKeyExchange>,
) {
// Step 1: create an ephemeral ECDH key at the (remote) source.
@@ -127,14 +138,14 @@
let source_pub_key = extract_plain_pub_key(&source_init_info.key.pubKey);
// Step 2: pass the source's ECDH public key and other session info to the (local) sink.
- let init_result = ke::init(
- impls,
- &source_pub_key.plainPubKey,
- &source_init_info.identity.identity,
- &source_init_info.nonce,
- source_init_info.version,
- )
- .expect("failed to init() with local impl");
+ let init_result = local_sink
+ .init(
+ &source_pub_key.plainPubKey,
+ &source_init_info.identity.identity,
+ &source_init_info.nonce,
+ source_init_info.version,
+ )
+ .expect("failed to init() with local impl");
let sink_init_info = init_result.session_init_info;
let sink_pub_key = sink_init_info
.ke_key
@@ -172,7 +183,7 @@
/// Perform mainline AuthGraph key exchange with the provided source, but give it back
/// a corrupted key.
pub fn test_corrupt_key(
- impls: &mut traits::TraitImpl,
+ local_sink: &mut ke::AuthGraphParticipant,
source: binder::Strong<dyn IAuthGraphKeyExchange>,
) {
// Step 1: create an ephemeral ECDH key at the (remote) source.
@@ -184,14 +195,14 @@
let source_pub_key = extract_plain_pub_key(&source_init_info.key.pubKey);
// Step 2: pass the source's ECDH public key and other session info to the (local) sink.
- let init_result = ke::init(
- impls,
- &source_pub_key.plainPubKey,
- &source_init_info.identity.identity,
- &source_init_info.nonce,
- source_init_info.version,
- )
- .expect("failed to init() with local impl");
+ let init_result = local_sink
+ .init(
+ &source_pub_key.plainPubKey,
+ &source_init_info.identity.identity,
+ &source_init_info.nonce,
+ source_init_info.version,
+ )
+ .expect("failed to init() with local impl");
let sink_init_info = init_result.session_init_info;
let sink_pub_key = sink_init_info
.ke_key
@@ -202,14 +213,17 @@
assert!(!sink_info.session_id.is_empty());
// The AuthGraph core library will verify the session ID signature, but do it here too.
- let sink_verification_key = verification_key_from_identity(&impls, &sink_init_info.identity);
- ke::verify_signature_on_session_id(
- &sink_verification_key,
- &sink_info.session_id,
- &sink_info.session_id_signature,
- &*impls.ecdsa,
- )
- .expect("failed verification of signed session ID");
+ let sink_verification_key = key::Identity::from_slice(&sink_init_info.identity)
+ .expect("invalid identity CBOR")
+ .cert_chain
+ .root_key;
+ local_sink
+ .verify_signature_on_session_id(
+ &sink_verification_key,
+ &sink_info.session_id,
+ &sink_info.session_id_signature,
+ )
+ .expect("failed verification of signed session ID");
// Deliberately corrupt the source's encrypted key.
let mut corrupt_key = source_init_info.key.clone();
diff --git a/security/authgraph/default/src/fuzzer.rs b/security/authgraph/default/src/fuzzer.rs
index 6a9cfdd..d401777 100644
--- a/security/authgraph/default/src/fuzzer.rs
+++ b/security/authgraph/default/src/fuzzer.rs
@@ -25,7 +25,7 @@
use std::sync::{Arc, Mutex};
fuzz_target!(|data: &[u8]| {
- let local_ta = LocalTa::new();
+ let local_ta = LocalTa::new().expect("Failed to create an AuthGraph local TA.");
let service = AuthGraphService::new_as_binder(Arc::new(Mutex::new(local_ta)));
fuzz_service(&mut service.as_binder(), data);
});
diff --git a/security/authgraph/default/src/lib.rs b/security/authgraph/default/src/lib.rs
index 4cd0cb7..43d037c 100644
--- a/security/authgraph/default/src/lib.rs
+++ b/security/authgraph/default/src/lib.rs
@@ -18,7 +18,9 @@
use authgraph_boringssl as boring;
use authgraph_core::{
+ error,
key::MillisecondsSinceEpoch,
+ keyexchange,
ta::{AuthGraphTa, Role},
traits,
};
@@ -57,16 +59,17 @@
impl LocalTa {
/// Create a new instance.
- pub fn new() -> Self {
- Self {
+ pub fn new() -> Result<Self, error::Error> {
+ Ok(Self {
ta: Arc::new(Mutex::new(AuthGraphTa::new(
- boring::trait_impls(
+ keyexchange::AuthGraphParticipant::new(
+ boring::crypto_trait_impls(),
Box::<boring::test_device::AgDevice>::default(),
- Some(Box::new(StdClock::default())),
- ),
+ keyexchange::MAX_OPENED_SESSIONS,
+ )?,
Role::Both,
))),
- }
+ })
}
}
diff --git a/security/authgraph/default/src/main.rs b/security/authgraph/default/src/main.rs
index 873eb4e..81f2dd6 100644
--- a/security/authgraph/default/src/main.rs
+++ b/security/authgraph/default/src/main.rs
@@ -65,7 +65,8 @@
binder::ProcessState::start_thread_pool();
// Register the service
- let local_ta = LocalTa::new();
+ let local_ta =
+ LocalTa::new().map_err(|e| format!("Failed to create the TA because: {e:?}"))?;
let service = service::AuthGraphService::new_as_binder(Arc::new(Mutex::new(local_ta)));
let service_name = format!("{}/{}", SERVICE_NAME, SERVICE_INSTANCE);
binder::add_service(&service_name, service.as_binder()).map_err(|e| {
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index aa7bf28..be29f59 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -974,8 +974,8 @@
* time in milliseconds. This value is used when generating attestation or self signed
* certificates. ErrorCode::MISSING_NOT_BEFORE must be returned if this tag is not provided if
* this tag is not provided to generateKey or importKey. For importWrappedKey, there is no way
- * to specify the value of this tag for the wrapped key, so a value of 0 must be used for
- * certificate generation.
+ * to specify the value of this tag for a wrapped asymmetric key, so a value of 0 is suggested
+ * for certificate generation.
*/
CERTIFICATE_NOT_BEFORE = TagType.DATE | 1008,
@@ -983,8 +983,9 @@
* Tag::CERTIFICATE_NOT_AFTER the end of the validity of the certificate in UNIX epoch time in
* milliseconds. This value is used when generating attestation or self signed certificates.
* ErrorCode::MISSING_NOT_AFTER must be returned if this tag is not provided to generateKey or
- * importKey. For importWrappedKey, there is no way to specify the value of this tag for the
- * wrapped key, so a value of 253402300799000 is used for certificate generation.
+ * importKey. For importWrappedKey, there is no way to specify the value of this tag for a
+ * wrapped asymmetric key, so a value of 253402300799000 is suggested for certificate
+ * generation.
*/
CERTIFICATE_NOT_AFTER = TagType.DATE | 1009,
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index a8f17dd..d4adab5 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -4123,13 +4123,13 @@
* when the EC_CURVE is not explicitly specified.
*/
TEST_P(ImportKeyTest, EcdsaSuccessCurveNotSpecified) {
- if (AidlVersion() < 4) {
+ if (get_vsr_api_level() < __ANDROID_API_V__) {
/*
- * The KeyMint spec before V4 was not clear as to whether EC_CURVE was optional on import of
- * EC keys. However, this was not checked at the time so we can only be strict about
- * checking this for implementations of KeyMint version 4 and above.
+ * The KeyMint spec was previously not clear as to whether EC_CURVE was optional on import
+ * of EC keys. However, this was not checked at the time so we can only be strict about
+ * checking this for implementations at VSR-V or later.
*/
- GTEST_SKIP() << "Skipping EC_CURVE on import only strict since KeyMint v4";
+ GTEST_SKIP() << "Skipping EC_CURVE on import only strict >= VSR-V";
}
ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()