Files
tubestation/toolkit/components/resistfingerprinting/nsRFPService.h
Tom Ritter b401d95a03 Bug 1440195 Add a per-context mix-in value for our Timer Precision Reduction Functions r=baku
We need to include a seed for each context (origin, iframe, worker, etc) we reduce
the time precision of. This prevents a replay attack of the random midpoint sequence.

MozReview-Commit-ID: EFoHev1SrTM
2018-03-09 16:22:37 -06:00

287 lines
9.1 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __nsRFPService_h__
#define __nsRFPService_h__
#include "mozilla/Atomics.h"
#include "mozilla/EventForwards.h"
#include "mozilla/Mutex.h"
#include "nsIDocument.h"
#include "nsIObserver.h"
#include "nsDataHashtable.h"
#include "nsString.h"
// Defines regarding spoofed values of Navigator object. These spoofed values
// are returned when 'privacy.resistFingerprinting' is true.
// We decided to give different spoofed values according to the platform. The
// reason is that it is easy to detect the real platform. So there is no benefit
// for hiding the platform: it only brings breakages, like keyboard shortcuts won't
// work in MAC OS if we spoof it as a window platform.
#ifdef XP_WIN
#define SPOOFED_UA_OS "Windows NT 6.1; Win64; x64"
#define SPOOFED_APPVERSION "5.0 (Windows)"
#define SPOOFED_OSCPU "Windows NT 6.1; Win64; x64"
#define SPOOFED_PLATFORM "Win64"
#elif defined(XP_MACOSX)
#define SPOOFED_UA_OS "Macintosh; Intel Mac OS X 10.13"
#define SPOOFED_APPVERSION "5.0 (Macintosh)"
#define SPOOFED_OSCPU "Intel Mac OS X 10.13"
#define SPOOFED_PLATFORM "MacIntel"
#elif defined(MOZ_WIDGET_ANDROID)
#define SPOOFED_UA_OS "Android 6.0; Mobile"
#define SPOOFED_APPVERSION "5.0 (Android 6.0)"
#define SPOOFED_OSCPU "Linux armv7l"
#define SPOOFED_PLATFORM "Linux armv7l"
#else
// For Linux and other platforms, like BSDs, SunOS and etc, we will use Linux
// platform.
#define SPOOFED_UA_OS "X11; Linux x86_64"
#define SPOOFED_APPVERSION "5.0 (X11)"
#define SPOOFED_OSCPU "Linux x86_64"
#define SPOOFED_PLATFORM "Linux x86_64"
#endif
#define SPOOFED_APPNAME "Netscape"
#define LEGACY_BUILD_ID "20100101"
// Forward declare LRUCache, defined in nsRFPService.cpp
class LRUCache;
namespace mozilla {
enum KeyboardLang {
EN = 0x01
};
#define RFP_KEYBOARD_LANG_STRING_EN "en"
typedef uint8_t KeyboardLangs;
enum KeyboardRegion {
US = 0x01
};
#define RFP_KEYBOARD_REGION_STRING_US "US"
typedef uint8_t KeyboardRegions;
// This struct has the information about how to spoof the keyboardEvent.code,
// keyboardEvent.keycode and modifier states.
struct SpoofingKeyboardCode
{
CodeNameIndex mCode;
uint8_t mKeyCode;
Modifiers mModifierStates;
};
struct SpoofingKeyboardInfo
{
KeyNameIndex mKeyIdx;
nsString mKey;
SpoofingKeyboardCode mSpoofingCode;
};
class KeyboardHashKey : public PLDHashEntryHdr
{
public:
typedef const KeyboardHashKey& KeyType;
typedef const KeyboardHashKey* KeyTypePointer;
KeyboardHashKey(const KeyboardLangs aLang,
const KeyboardRegions aRegion,
const KeyNameIndexType aKeyIdx,
const nsAString &aKey)
: mLang(aLang)
, mRegion(aRegion)
, mKeyIdx(aKeyIdx)
, mKey(aKey)
{}
explicit KeyboardHashKey(KeyTypePointer aOther)
: mLang(aOther->mLang)
, mRegion(aOther->mRegion)
, mKeyIdx(aOther->mKeyIdx)
, mKey(aOther->mKey)
{}
KeyboardHashKey(KeyType aOther)
: mLang(aOther.mLang)
, mRegion(aOther.mRegion)
, mKeyIdx(aOther.mKeyIdx)
, mKey(aOther.mKey)
{}
~KeyboardHashKey()
{}
bool KeyEquals(KeyTypePointer aOther) const
{
return mLang == aOther->mLang &&
mRegion == aOther->mRegion &&
mKeyIdx == aOther->mKeyIdx &&
mKey == aOther->mKey;
}
static KeyTypePointer KeyToPointer(KeyType aKey)
{
return &aKey;
}
static PLDHashNumber HashKey(KeyTypePointer aKey)
{
PLDHashNumber hash = mozilla::HashString(aKey->mKey);
return mozilla::AddToHash(hash,
aKey->mRegion,
aKey->mKeyIdx,
aKey->mLang);
}
enum { ALLOW_MEMMOVE = true };
KeyboardLangs mLang;
KeyboardRegions mRegion;
KeyNameIndexType mKeyIdx;
nsString mKey;
};
enum TimerPrecisionType {
All = 1,
RFPOnly = 2
};
class nsRFPService final : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
static nsRFPService* GetOrCreate();
static bool IsResistFingerprintingEnabled();
static bool IsTimerPrecisionReductionEnabled(TimerPrecisionType aType);
enum TimeScale {
Seconds = 1,
MilliSeconds = 1000,
MicroSeconds = 1000000
};
// The following Reduce methods can be called off main thread.
static double ReduceTimePrecisionAsUSecs(
double aTime,
int64_t aContextMixin,
TimerPrecisionType aType = TimerPrecisionType::All);
static double ReduceTimePrecisionAsMSecs(
double aTime,
int64_t aContextMixin,
TimerPrecisionType aType = TimerPrecisionType::All);
static double ReduceTimePrecisionAsSecs(
double aTime,
int64_t aContextMixin,
TimerPrecisionType aType = TimerPrecisionType::All);
// Used by the JS Engine, as it doesn't know about the TimerPrecisionType enum
static double ReduceTimePrecisionAsUSecsWrapper(
double aTime);
// Public only for testing purposes
static double ReduceTimePrecisionImpl(
double aTime,
TimeScale aTimeScale,
double aResolutionUSec,
int64_t aContextMixin,
TimerPrecisionType aType);
static nsresult RandomMidpoint(long long aClampedTimeUSec,
long long aResolutionUSec,
int64_t aContextMixin,
long long* aMidpointOut,
uint8_t * aSecretSeed = nullptr);
// This method calculates the video resolution (i.e. height x width) based
// on the video quality (480p, 720p, etc).
static uint32_t CalculateTargetVideoResolution(uint32_t aVideoQuality);
// Methods for getting spoofed media statistics and the return value will
// depend on the video resolution.
static uint32_t GetSpoofedTotalFrames(double aTime);
static uint32_t GetSpoofedDroppedFrames(double aTime, uint32_t aWidth, uint32_t aHeight);
static uint32_t GetSpoofedPresentedFrames(double aTime, uint32_t aWidth, uint32_t aHeight);
// This method generates the spoofed value of User Agent.
static nsresult GetSpoofedUserAgent(nsACString &userAgent);
/**
* This method for getting spoofed modifier states for the given keyboard event.
*
* @param aDoc [in] the owner's document for getting content language.
* @param aKeyboardEvent [in] the keyboard event that needs to be spoofed.
* @param aModifier [in] the modifier that needs to be spoofed.
* @param aOut [out] the spoofed state for the given modifier.
* @return true if there is a spoofed state for the modifier.
*/
static bool GetSpoofedModifierStates(const nsIDocument* aDoc,
const WidgetKeyboardEvent* aKeyboardEvent,
const Modifiers aModifier,
bool& aOut);
/**
* This method for getting spoofed code for the given keyboard event.
*
* @param aDoc [in] the owner's document for getting content language.
* @param aKeyboardEvent [in] the keyboard event that needs to be spoofed.
* @param aOut [out] the spoofed code.
* @return true if there is a spoofed code in the fake keyboard layout.
*/
static bool GetSpoofedCode(const nsIDocument* aDoc,
const WidgetKeyboardEvent* aKeyboardEvent,
nsAString& aOut);
/**
* This method for getting spoofed keyCode for the given keyboard event.
*
* @param aDoc [in] the owner's document for getting content language.
* @param aKeyboardEvent [in] the keyboard event that needs to be spoofed.
* @param aOut [out] the spoofed keyCode.
* @return true if there is a spoofed keyCode in the fake keyboard layout.
*/
static bool GetSpoofedKeyCode(const nsIDocument* aDoc,
const WidgetKeyboardEvent* aKeyboardEvent,
uint32_t& aOut);
private:
nsresult Init();
nsRFPService() {}
~nsRFPService() {}
void UpdateTimers();
void UpdateRFPPref();
void StartShutdown();
static void MaybeCreateSpoofingKeyCodes(const KeyboardLangs aLang,
const KeyboardRegions aRegion);
static void MaybeCreateSpoofingKeyCodesForEnUS();
static void GetKeyboardLangAndRegion(const nsAString& aLanguage,
KeyboardLangs& aLang,
KeyboardRegions& aRegion);
static bool GetSpoofedKeyCodeInfo(const nsIDocument* aDoc,
const WidgetKeyboardEvent* aKeyboardEvent,
SpoofingKeyboardCode& aOut);
static Atomic<bool, Relaxed> sPrivacyResistFingerprinting;
static Atomic<bool, Relaxed> sPrivacyTimerPrecisionReduction;
static nsDataHashtable<KeyboardHashKey, const SpoofingKeyboardCode*>* sSpoofingKeyboardCodes;
nsCString mInitialTZValue;
};
} // mozilla namespace
#endif /* __nsRFPService_h__ */