Adjust nonce flood rate in mock oemcrypto

Merge from Widevine repo of http://go/wvgerrit/43721

This CL allows the tester to change the nonce flood rate from the
default of 20.  A tester would want this value to be larger to make
tests run more quickly.

Setting the rate to 1 makes every other nonce request a flood error.
A tester wants to do this in order to verify cdm code responds to
nonce flood correctly.  Several failing oemcrypto tests have also been
corrected.

This CL changes test code only.

bug: 73607610
test: unit tests
Change-Id: I3f52ff7ea9bcc1db7bc0e010da0b64a12d3b4dd3
This commit is contained in:
Fred Gylys-Colwell
2018-02-21 13:34:09 -08:00
parent aef1f6f48e
commit 9729663671
6 changed files with 33 additions and 10 deletions

View File

@@ -514,6 +514,8 @@ class AndroidModifiableCryptoEngine : public CryptoEngine {
return false;
}
virtual int nonce_flood_count() { GetOption("nonce_flood_count", 20); }
virtual void adjust_destination(OEMCrypto_DestBufferDesc *out_description,
size_t data_length, uint8_t subsample_flags) {
if (out_description->type != OEMCrypto_BufferType_Secure) return;

View File

@@ -146,6 +146,9 @@ class CryptoEngine {
virtual bool srm_blacklisted_device_attached() { return false; }
// Rate limit for nonce generation. Default to 20 nonce/second.
virtual int nonce_flood_count() { return 20; }
// Set destination pointer based on the output destination description.
OEMCryptoResult SetDestination(OEMCrypto_DestBufferDesc* out_description,
size_t data_length, uint8_t subsample_flags);

View File

@@ -13,6 +13,7 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <iostream>
#include <string>
@@ -196,6 +197,13 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateDerivedKeys(
return OEMCrypto_SUCCESS;
}
static const uint64_t one_second = 1000000ull;
static uint64_t TimeStamp(void) {
struct timeval tv;
gettimeofday(&tv,NULL);
return tv.tv_sec * one_second + tv.tv_usec;
}
extern "C" OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
uint32_t* nonce) {
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
@@ -213,12 +221,15 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
}
// Prevent nonce flood.
static time_t last_nonce_time = 0;
static int nonce_count = 0;
time_t now = time(NULL);
if (now == last_nonce_time) {
uint64_t now = TimeStamp();
static uint64_t last_nonce_time = now;
// For testing, we set nonce_flood_count to 1. Since count is initialized to
// 1, the very first nonce after initialization is counted as a flood.
static int nonce_count = 1;
if (now - last_nonce_time < one_second) {
nonce_count++;
if (nonce_count > 20) {
if (nonce_count > crypto_engine->nonce_flood_count()) {
LOGE("[OEMCrypto_GenerateNonce(): Nonce Flood detected]");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}

View File

@@ -1197,15 +1197,17 @@ void Session::VerifyPST(const Test_PST_Report& expected) {
char* pst_ptr = reinterpret_cast<char *>(computed.pst());
std::string computed_pst(pst_ptr, pst_ptr + computed.pst_length());
ASSERT_EQ(expected.pst, computed_pst);
EXPECT_NEAR(expected.seconds_since_license_received,
time_t now = time(NULL);
int64_t age = now - expected.time_created; // How old is this report.
EXPECT_NEAR(expected.seconds_since_license_received + age,
computed.seconds_since_license_received(),
kTimeTolerance);
// Decrypt times only valid on licenses that have been active.
if (expected.status == kActive || expected.status == kInactiveUsed) {
EXPECT_NEAR(expected.seconds_since_first_decrypt,
EXPECT_NEAR(expected.seconds_since_first_decrypt + age,
computed.seconds_since_first_decrypt(),
kUsageTableTimeTolerance);
EXPECT_NEAR(expected.seconds_since_last_decrypt,
EXPECT_NEAR(expected.seconds_since_last_decrypt + age,
computed.seconds_since_last_decrypt(),
kUsageTableTimeTolerance);
}

View File

@@ -94,13 +94,14 @@ struct RSAPrivateKeyMessage {
struct Test_PST_Report {
Test_PST_Report(const std::string& pst_in,
OEMCrypto_Usage_Entry_Status status_in)
: status(status_in), pst(pst_in) {}
: status(status_in), pst(pst_in), time_created(time(NULL)) {}
OEMCrypto_Usage_Entry_Status status;
int64_t seconds_since_license_received;
int64_t seconds_since_first_decrypt;
int64_t seconds_since_last_decrypt;
std::string pst;
time_t time_created;
};
struct EntitledContentKeyData {

View File

@@ -4935,6 +4935,7 @@ TEST_P(UsageTableTestWithMAC, BadReloadOfflineLicense) {
std::string pst = "my_pst";
Session s;
ASSERT_NO_FATAL_FAILURE(LoadOfflineLicense(s, pst));
time_t loaded = time(NULL);
// Offline license with new mac keys should fail.
Session s2;
@@ -4961,7 +4962,10 @@ TEST_P(UsageTableTestWithMAC, BadReloadOfflineLicense) {
ASSERT_NO_FATAL_FAILURE(s.ReloadUsageEntry());
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys(pst, new_mac_keys_));
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
ASSERT_NO_FATAL_FAILURE(s.GenerateVerifyReport(pst, kUnused));
ASSERT_NO_FATAL_FAILURE(
s.GenerateVerifyReport(pst, kUnused,
loaded, // license loaded.
0, 0)); // first and last decrypt
}
// An offline license should not load on the first call if the nonce is bad.