Merge "Adjust nonce flood rate in mock oemcrypto"
This commit is contained in:
committed by
Android (Google) Code Review
commit
b6729a0b14
@@ -514,6 +514,8 @@ class AndroidModifiableCryptoEngine : public CryptoEngine {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int nonce_flood_count() { GetOption("nonce_flood_count", 20); }
|
||||||
|
|
||||||
virtual void adjust_destination(OEMCrypto_DestBufferDesc *out_description,
|
virtual void adjust_destination(OEMCrypto_DestBufferDesc *out_description,
|
||||||
size_t data_length, uint8_t subsample_flags) {
|
size_t data_length, uint8_t subsample_flags) {
|
||||||
if (out_description->type != OEMCrypto_BufferType_Secure) return;
|
if (out_description->type != OEMCrypto_BufferType_Secure) return;
|
||||||
|
|||||||
@@ -146,6 +146,9 @@ class CryptoEngine {
|
|||||||
|
|
||||||
virtual bool srm_blacklisted_device_attached() { return false; }
|
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.
|
// Set destination pointer based on the output destination description.
|
||||||
OEMCryptoResult SetDestination(OEMCrypto_DestBufferDesc* out_description,
|
OEMCryptoResult SetDestination(OEMCrypto_DestBufferDesc* out_description,
|
||||||
size_t data_length, uint8_t subsample_flags);
|
size_t data_length, uint8_t subsample_flags);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -196,6 +197,13 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateDerivedKeys(
|
|||||||
return OEMCrypto_SUCCESS;
|
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,
|
extern "C" OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
|
||||||
uint32_t* nonce) {
|
uint32_t* nonce) {
|
||||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||||
@@ -213,12 +221,15 @@ extern "C" OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prevent nonce flood.
|
// Prevent nonce flood.
|
||||||
static time_t last_nonce_time = 0;
|
uint64_t now = TimeStamp();
|
||||||
static int nonce_count = 0;
|
static uint64_t last_nonce_time = now;
|
||||||
time_t now = time(NULL);
|
// For testing, we set nonce_flood_count to 1. Since count is initialized to
|
||||||
if (now == last_nonce_time) {
|
// 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++;
|
nonce_count++;
|
||||||
if (nonce_count > 20) {
|
if (nonce_count > crypto_engine->nonce_flood_count()) {
|
||||||
LOGE("[OEMCrypto_GenerateNonce(): Nonce Flood detected]");
|
LOGE("[OEMCrypto_GenerateNonce(): Nonce Flood detected]");
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1197,15 +1197,17 @@ void Session::VerifyPST(const Test_PST_Report& expected) {
|
|||||||
char* pst_ptr = reinterpret_cast<char *>(computed.pst());
|
char* pst_ptr = reinterpret_cast<char *>(computed.pst());
|
||||||
std::string computed_pst(pst_ptr, pst_ptr + computed.pst_length());
|
std::string computed_pst(pst_ptr, pst_ptr + computed.pst_length());
|
||||||
ASSERT_EQ(expected.pst, computed_pst);
|
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(),
|
computed.seconds_since_license_received(),
|
||||||
kTimeTolerance);
|
kTimeTolerance);
|
||||||
// Decrypt times only valid on licenses that have been active.
|
// Decrypt times only valid on licenses that have been active.
|
||||||
if (expected.status == kActive || expected.status == kInactiveUsed) {
|
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(),
|
computed.seconds_since_first_decrypt(),
|
||||||
kUsageTableTimeTolerance);
|
kUsageTableTimeTolerance);
|
||||||
EXPECT_NEAR(expected.seconds_since_last_decrypt,
|
EXPECT_NEAR(expected.seconds_since_last_decrypt + age,
|
||||||
computed.seconds_since_last_decrypt(),
|
computed.seconds_since_last_decrypt(),
|
||||||
kUsageTableTimeTolerance);
|
kUsageTableTimeTolerance);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,13 +94,14 @@ struct RSAPrivateKeyMessage {
|
|||||||
struct Test_PST_Report {
|
struct Test_PST_Report {
|
||||||
Test_PST_Report(const std::string& pst_in,
|
Test_PST_Report(const std::string& pst_in,
|
||||||
OEMCrypto_Usage_Entry_Status status_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;
|
OEMCrypto_Usage_Entry_Status status;
|
||||||
int64_t seconds_since_license_received;
|
int64_t seconds_since_license_received;
|
||||||
int64_t seconds_since_first_decrypt;
|
int64_t seconds_since_first_decrypt;
|
||||||
int64_t seconds_since_last_decrypt;
|
int64_t seconds_since_last_decrypt;
|
||||||
std::string pst;
|
std::string pst;
|
||||||
|
time_t time_created;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EntitledContentKeyData {
|
struct EntitledContentKeyData {
|
||||||
|
|||||||
@@ -4935,6 +4935,7 @@ TEST_P(UsageTableTestWithMAC, BadReloadOfflineLicense) {
|
|||||||
std::string pst = "my_pst";
|
std::string pst = "my_pst";
|
||||||
Session s;
|
Session s;
|
||||||
ASSERT_NO_FATAL_FAILURE(LoadOfflineLicense(s, pst));
|
ASSERT_NO_FATAL_FAILURE(LoadOfflineLicense(s, pst));
|
||||||
|
time_t loaded = time(NULL);
|
||||||
|
|
||||||
// Offline license with new mac keys should fail.
|
// Offline license with new mac keys should fail.
|
||||||
Session s2;
|
Session s2;
|
||||||
@@ -4961,7 +4962,10 @@ TEST_P(UsageTableTestWithMAC, BadReloadOfflineLicense) {
|
|||||||
ASSERT_NO_FATAL_FAILURE(s.ReloadUsageEntry());
|
ASSERT_NO_FATAL_FAILURE(s.ReloadUsageEntry());
|
||||||
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys(pst, new_mac_keys_));
|
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys(pst, new_mac_keys_));
|
||||||
ASSERT_NO_FATAL_FAILURE(s.UpdateUsageEntry(&encrypted_usage_header_));
|
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.
|
// An offline license should not load on the first call if the nonce is bad.
|
||||||
|
|||||||
Reference in New Issue
Block a user