From: csagan5 <32685696+csagan5@users.noreply.github.com> Date: Sun, 25 Mar 2018 21:49:37 +0200 Subject: AudioBuffer, AnalyserNode: fp mitigations Truncate base latency precision to two digits License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html --- chrome/browser/about_flags.cc | 4 ++++ chrome/browser/flag_descriptions.cc | 5 +++++ chrome/browser/flag_descriptions.h | 3 +++ third_party/blink/common/features.cc | 4 ++++ third_party/blink/public/common/features.h | 2 ++ .../renderer/modules/webaudio/audio_buffer.cc | 14 ++++++++++++++ .../blink/renderer/modules/webaudio/audio_buffer.h | 2 ++ .../renderer/modules/webaudio/audio_context.cc | 5 ++++- .../modules/webaudio/base_audio_context.cc | 12 ++++++++++++ .../renderer/modules/webaudio/base_audio_context.h | 2 ++ .../modules/webaudio/offline_audio_context.cc | 1 + .../renderer/modules/webaudio/realtime_analyser.cc | 7 +++++++ 12 files changed, 60 insertions(+), 1 deletion(-) diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc @@ -4168,6 +4168,10 @@ const FeatureEntry kFeatureEntries[] = { flag_descriptions::kKioskEnableAppServiceDescription, kOsCrOS, FEATURE_VALUE_TYPE(features::kKioskEnableAppService)}, #endif // BUILDFLAG(IS_CHROMEOS) + {"fingerprinting-audio-context-data-noise", + flag_descriptions::kAudioContextShuffleEnabledName, + flag_descriptions::kAudioContextShuffleEnabledDescription, kOsAll, + FEATURE_VALUE_TYPE(blink::features::kAudioContextShuffleEnabled)}, #if !BUILDFLAG(IS_ANDROID) {"enable-webrtc-remote-event-log", flag_descriptions::kWebRtcRemoteEventLogName, diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc @@ -3740,6 +3740,11 @@ const char kWebTransportDeveloperModeDescription[] = "When enabled, removes the requirement that all certificates used for " "WebTransport over HTTP/3 are issued by a known certificate root."; +const char kAudioContextShuffleEnabledName[] = + "Enable Audio Context fingerprint deception"; +const char kAudioContextShuffleEnabledDescription[] = + "Scale the output values of rendered data with a randomly selected factor."; + const char kWebUsbDeviceDetectionName[] = "Automatic detection of WebUSB-compatible devices"; const char kWebUsbDeviceDetectionDescription[] = diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h @@ -2174,6 +2174,9 @@ extern const char kWebRtcRemoteEventLogDescription[]; extern const char kWebrtcUseMinMaxVEADimensionsName[]; extern const char kWebrtcUseMinMaxVEADimensionsDescription[]; +extern const char kAudioContextShuffleEnabledName[]; +extern const char kAudioContextShuffleEnabledDescription[]; + extern const char kWebTransportDeveloperModeName[]; extern const char kWebTransportDeveloperModeDescription[]; diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc @@ -258,6 +258,10 @@ BASE_FEATURE(kBiddingAndScoringDebugReportingAPI, "BiddingAndScoringDebugReportingAPI", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kAudioContextShuffleEnabled, + "AudioContextShuffleEnabled", + base::FEATURE_ENABLED_BY_DEFAULT); + // Blink garbage collection. // Enables compaction of backing stores on Blink's heap. BASE_FEATURE(kBlinkHeapCompaction, diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h @@ -158,6 +158,8 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBlinkHeapConcurrentSweeping); BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBlinkHeapIncrementalMarking); BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kBlinkHeapIncrementalMarkingStress); +BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kAudioContextShuffleEnabled); + BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE( kBlockingDownloadsInAdFrameWithoutUserActivation); diff --git a/third_party/blink/renderer/modules/webaudio/audio_buffer.cc b/third_party/blink/renderer/modules/webaudio/audio_buffer.cc --- a/third_party/blink/renderer/modules/webaudio/audio_buffer.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_buffer.cc @@ -196,6 +196,20 @@ AudioBuffer::AudioBuffer(AudioBus* bus) } } +void AudioBuffer::ShuffleAudioData() { + for (unsigned i = 0; i < channels_.size(); ++i) { + if (NotShared array = getChannelData(i)) { + size_t len = array->length(); + if (len > 0) { + float* destination = array->Data(); + for (unsigned j = 0; j < len; ++j) { + destination[j] = BaseAudioContext::ShuffleAudioData(destination[j], j); + } + } + } + } +} + NotShared AudioBuffer::getChannelData( unsigned channel_index, ExceptionState& exception_state) { diff --git a/third_party/blink/renderer/modules/webaudio/audio_buffer.h b/third_party/blink/renderer/modules/webaudio/audio_buffer.h --- a/third_party/blink/renderer/modules/webaudio/audio_buffer.h +++ b/third_party/blink/renderer/modules/webaudio/audio_buffer.h @@ -115,6 +115,8 @@ class MODULES_EXPORT AudioBuffer final : public ScriptWrappable { std::unique_ptr CreateSharedAudioBuffer(); + void ShuffleAudioData(); + private: static DOMFloat32Array* CreateFloat32ArrayOrNull( uint32_t length, diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.cc b/third_party/blink/renderer/modules/webaudio/audio_context.cc --- a/third_party/blink/renderer/modules/webaudio/audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_context.cc @@ -11,6 +11,7 @@ #include "services/metrics/public/cpp/ukm_recorder.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" #include "third_party/blink/public/common/mediastream/media_devices.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h" #include "third_party/blink/public/platform/web_audio_latency_hint.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" @@ -586,7 +587,9 @@ double AudioContext::baseLatency() const { DCHECK(IsMainThread()); DCHECK(destination()); - return base_latency_; + // remove precision past two decimal digits + int l = base_latency_ * 100; + return double(l)/100; } double AudioContext::outputLatency() const { diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc --- a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc @@ -29,6 +29,7 @@ #include "base/metrics/histogram_functions.h" #include "build/build_config.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/mojom/devtools/console_message.mojom-blink.h" #include "third_party/blink/public/mojom/frame/lifecycle.mojom-shared.h" #include "third_party/blink/public/platform/platform.h" @@ -721,6 +722,17 @@ LocalDOMWindow* BaseAudioContext::GetWindow() const { return To(GetExecutionContext()); } +/*static*/ +float BaseAudioContext::ShuffleAudioData(float data, unsigned index) { + if (base::FeatureList::IsEnabled(features::kAudioContextShuffleEnabled)) { + float rnd = 1.0f + + (base::RandDouble() / 10000.0) * + (base::RandInt(0,10) > 5 ? 1.f : -1.f); + return data * rnd; + } + return data; +} + void BaseAudioContext::NotifySourceNodeStartedProcessing(AudioNode* node) { DCHECK(IsMainThread()); GraphAutoLocker locker(this); diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.h b/third_party/blink/renderer/modules/webaudio/base_audio_context.h --- a/third_party/blink/renderer/modules/webaudio/base_audio_context.h +++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.h @@ -339,6 +339,8 @@ class MODULES_EXPORT BaseAudioContext // if the execution context does not exist. bool CheckExecutionContextAndThrowIfNecessary(ExceptionState&); + static float ShuffleAudioData(float data, unsigned index); + protected: enum ContextType { kRealtimeContext, kOfflineContext }; diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc b/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc --- a/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc @@ -368,6 +368,7 @@ void OfflineAudioContext::FireCompletionEvent() { if (!rendered_buffer) { return; } + rendered_buffer->ShuffleAudioData(); // Call the offline rendering completion event listener and resolve the // promise too. diff --git a/third_party/blink/renderer/modules/webaudio/realtime_analyser.cc b/third_party/blink/renderer/modules/webaudio/realtime_analyser.cc --- a/third_party/blink/renderer/modules/webaudio/realtime_analyser.cc +++ b/third_party/blink/renderer/modules/webaudio/realtime_analyser.cc @@ -29,6 +29,7 @@ #include #include +#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h" #include "third_party/blink/renderer/platform/audio/audio_bus.h" #include "third_party/blink/renderer/platform/audio/audio_utilities.h" #include "third_party/blink/renderer/platform/audio/vector_math.h" @@ -154,6 +155,7 @@ void RealtimeAnalyser::GetFloatTimeDomainData( input_buffer[(i + write_index - fft_size + kInputBufferSize) % kInputBufferSize]; + value = BaseAudioContext::ShuffleAudioData(value, i); destination[i] = value; } } @@ -181,6 +183,8 @@ void RealtimeAnalyser::GetByteTimeDomainData(DOMUint8Array* destination_array) { input_buffer[(i + write_index - fft_size + kInputBufferSize) % kInputBufferSize]; + value = BaseAudioContext::ShuffleAudioData(value, i); + // Scale from nominal -1 -> +1 to unsigned byte. double scaled_value = 128 * (value + 1); @@ -300,6 +304,8 @@ void RealtimeAnalyser::ConvertToByteData(DOMUint8Array* destination_array) { double scaled_value = UCHAR_MAX * (db_mag - min_decibels) * range_scale_factor; + scaled_value = BaseAudioContext::ShuffleAudioData(scaled_value, i); + // Clip to valid range. destination[i] = static_cast(ClampTo(scaled_value, 0, UCHAR_MAX)); @@ -319,6 +325,7 @@ void RealtimeAnalyser::ConvertFloatToDb(DOMFloat32Array* destination_array) { float linear_value = source[i]; double db_mag = audio_utilities::LinearToDecibels(linear_value); destination[i] = static_cast(db_mag); + destination[i] = BaseAudioContext::ShuffleAudioData(destination[i], i); } } } -- 2.25.1