This patch adds a suite of tests for OEMCrypto that verifying buffer overflow and off-by-one errors. The reference code has also been updated to pass these tests. The ODK library and the OEMCrypto API have not changed since the release of version 16.4.
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 wvcdm {
|
|
|
|
// 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 wvcdm
|
|
|
|
#endif // WVCDM_CORE_CDM_RANDOM_H_
|