Note that this version does not have Widevine Provisioning 4.0 support. It is only suitable for device upgrades. A new patch with provisioning 4.0 support will be made later.
118 lines
4.3 KiB
C++
118 lines
4.3 KiB
C++
// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
|
// source code may only be used and distributed under the Widevine License
|
|
// Agreement.
|
|
#ifndef WVCDM_CORE_CDM_RANDOM_H_
|
|
#define WVCDM_CORE_CDM_RANDOM_H_
|
|
|
|
#include <mutex>
|
|
#include <random>
|
|
#include <string>
|
|
|
|
namespace wvutil {
|
|
|
|
// CdmRandomGenerator is a thread safe, pseudo-random number generator.
|
|
// It's purpose is to simplified interface for C++11's <random> library.
|
|
// Some of the methods use a "device specific" random seed, if the
|
|
// compiler/device does not support device specific randomizers, then the
|
|
// actual value supplied may not be random. The generator is designed to
|
|
// meet the C++ named requirement UniformRandomBitGenerator to allow it to
|
|
// be used with standard library functions / class which are designed to
|
|
// work with the standard library generators.
|
|
class CdmRandomGenerator {
|
|
public:
|
|
// Result type of operator().
|
|
using result_type = unsigned int;
|
|
// Inclusive boundaries of operator().
|
|
static constexpr unsigned int min() { return 0; }
|
|
static constexpr unsigned int max() { return RAND_MAX; }
|
|
|
|
// The maximum number of bytes that can be generated at once for
|
|
// `RandomData()`.
|
|
static constexpr size_t kMaxRandomDataLength = 8192; // 8 kB
|
|
|
|
// Initializes the pseudo-random generator with a value from a device
|
|
// specific random number generator.
|
|
CdmRandomGenerator();
|
|
|
|
// Initializes the pseudo-random generator with the specified seed value.
|
|
explicit CdmRandomGenerator(unsigned int seed) : generator_(seed) {}
|
|
|
|
// All of these methods are thread-safe.
|
|
|
|
// Seeds the pseudo-random generator with a value from a device specific
|
|
// random number generator.
|
|
void Seed();
|
|
|
|
// Seeds the pseudo-random generator with the specified seed value.
|
|
// This is somewhat similar to `srand()` from the C standard library;
|
|
// except that the sequence generated from successive calls to `Rand()`
|
|
// will not necessarily be the same as they would be from the
|
|
// standard library `rand()`. This is due to the underlying pseudo-random
|
|
// generator that is used.
|
|
void Seed(unsigned int seed);
|
|
|
|
// Returns a pseudo-random integer.
|
|
// This is similar to `rand()` from the C standard library. The integer
|
|
// returned is in the range of [min(), max()].
|
|
unsigned int Rand();
|
|
|
|
// Allows for RNG to be callable.
|
|
unsigned int operator()() { return Rand(); }
|
|
|
|
// Returns a pseudo-random integer within the provided inclusive range.
|
|
uint64_t RandomInRange(uint64_t lower, uint64_t upper);
|
|
uint64_t RandomInRange(uint64_t upper) { return RandomInRange(0, upper); }
|
|
|
|
// Returns a byte string containing randomized bytes of the specified
|
|
// length.
|
|
// If |length| is greater than |CdmRandomGenerator::kMaxRandomDataLength|,
|
|
// then an error is logged and an empty string is returned.
|
|
std::string RandomData(size_t length);
|
|
|
|
// Random true/false using Bernoulli distribution of equal probability.
|
|
bool RandomBool();
|
|
|
|
private:
|
|
// Mutex is used to lock the object, and allowing it to be used
|
|
// concurrently in different threads.
|
|
std::mutex generator_lock_;
|
|
|
|
// The `default_random_engine` depends on the compiler used and
|
|
// potentially its version. This is important to know if you need to
|
|
// create reproducible tests between platforms.
|
|
std::default_random_engine generator_;
|
|
};
|
|
|
|
// Provides a static interface to a process-wide instance of
|
|
// CdmRandomGenerator.
|
|
class CdmRandom {
|
|
public:
|
|
static unsigned int Rand() { return GetInstance()->Rand(); }
|
|
static uint64_t RandomInRange(uint64_t lower, uint64_t upper) {
|
|
return GetInstance()->RandomInRange(lower, upper);
|
|
}
|
|
static uint64_t RandomInRange(uint64_t upper) {
|
|
return GetInstance()->RandomInRange(upper);
|
|
}
|
|
|
|
static std::string RandomData(size_t length) {
|
|
return GetInstance()->RandomData(length);
|
|
}
|
|
|
|
static bool RandomBool() { return GetInstance()->RandomBool(); }
|
|
|
|
private:
|
|
// These are intended to be used by tests if needed.
|
|
static void Seed(unsigned int seed) { GetInstance()->Seed(seed); }
|
|
static void Seed() { GetInstance()->Seed(); }
|
|
|
|
// Returns the process-wide instance of CdmRandomGenerator.
|
|
// It the global instance has not yet been created, then a new instance
|
|
// is created using a device-specific random seed.
|
|
static CdmRandomGenerator* GetInstance();
|
|
};
|
|
|
|
} // namespace wvutil
|
|
|
|
#endif // WVCDM_CORE_CDM_RANDOM_H_
|