diff --git a/fdbclient/Tenant.cpp b/fdbclient/Tenant.cpp index 1071059114..16e60d20c5 100644 --- a/fdbclient/Tenant.cpp +++ b/fdbclient/Tenant.cpp @@ -70,7 +70,7 @@ TEST_CASE("/fdbclient/TenantMapEntry/Serialization") { int subspaceLength = deterministicRandom()->randomInt(0, 20); Standalone subspace = makeString(subspaceLength); - generateRandomData(mutateString(subspace), subspaceLength); + deterministicRandom()->randomBytes(mutateString(subspace), subspaceLength); TenantMapEntry entry(id, subspace); int64_t bigEndianId = bigEndian64(id); diff --git a/fdbrpc/AsyncFileEncrypted.actor.cpp b/fdbrpc/AsyncFileEncrypted.actor.cpp index bf1c44da59..ec37f79414 100644 --- a/fdbrpc/AsyncFileEncrypted.actor.cpp +++ b/fdbrpc/AsyncFileEncrypted.actor.cpp @@ -258,7 +258,7 @@ Optional> AsyncFileEncrypted::RandomCache::get(uint32_t bl TEST_CASE("fdbrpc/AsyncFileEncrypted") { state const int bytes = FLOW_KNOBS->ENCRYPTION_BLOCK_SIZE * deterministicRandom()->randomInt(0, 1000); state std::vector writeBuffer(bytes, 0); - generateRandomData(&writeBuffer.front(), bytes); + deterministicRandom()->randomBytes(&writeBuffer.front(), bytes); state std::vector readBuffer(bytes, 0); ASSERT(g_network->isSimulated()); StreamCipherKey::initializeGlobalRandomTestKey(); diff --git a/fdbserver/RESTKmsConnector.actor.cpp b/fdbserver/RESTKmsConnector.actor.cpp index dbb1271ebb..4979307a69 100644 --- a/fdbserver/RESTKmsConnector.actor.cpp +++ b/fdbserver/RESTKmsConnector.actor.cpp @@ -880,7 +880,7 @@ std::shared_ptr prepareTokenFile(const uint8_t* buff, const i std::shared_ptr prepareTokenFile(const int tokenLen) { Standalone buff = makeString(tokenLen); - generateRandomData(mutateString(buff), tokenLen); + deterministicRandom()->randomBytes(mutateString(buff), tokenLen); return prepareTokenFile(buff.begin(), tokenLen); } @@ -941,7 +941,7 @@ ACTOR Future testValidationFileTokenPayloadTooLarge(ReferenceREST_KMS_CONNECTOR_VALIDATION_TOKEN_MAX_SIZE + 2; Standalone buff = makeString(tokenLen); - generateRandomData(mutateString(buff), tokenLen); + deterministicRandom()->randomBytes(mutateString(buff), tokenLen); std::string details; state std::vector> tokenfiles; @@ -972,7 +972,7 @@ ACTOR Future testMultiValidationFileTokenFiles(Reference tokenNameValueMap; state std::string tokenDetailsStr; - generateRandomData(mutateString(buff), tokenLen); + deterministicRandom()->randomBytes(mutateString(buff), tokenLen); for (int i = 1; i <= numFiles; i++) { std::string tokenName = std::to_string(i); @@ -1350,7 +1350,7 @@ TEST_CASE("/KmsConnector/REST/ParseKmsDiscoveryUrls") { state Arena arena; // initialize cipher key used for testing - generateRandomData(&BASE_CIPHER_KEY_TEST[0], 32); + deterministicRandom()->randomBytes(&BASE_CIPHER_KEY_TEST[0], 32); wait(testParseDiscoverKmsUrlFileNotFound(ctx)); wait(testParseDiscoverKmsUrlFile(ctx)); @@ -1363,7 +1363,7 @@ TEST_CASE("/KmsConnector/REST/ParseValidationTokenFile") { state Arena arena; // initialize cipher key used for testing - generateRandomData(&BASE_CIPHER_KEY_TEST[0], 32); + deterministicRandom()->randomBytes(&BASE_CIPHER_KEY_TEST[0], 32); wait(testEmptyValidationFileDetails(ctx)); wait(testMalformedFileValidationTokenDetails(ctx)); @@ -1380,7 +1380,7 @@ TEST_CASE("/KmsConnector/REST/ParseKmsResponse") { state Arena arena; // initialize cipher key used for testing - generateRandomData(&BASE_CIPHER_KEY_TEST[0], 32); + deterministicRandom()->randomBytes(&BASE_CIPHER_KEY_TEST[0], 32); testMissingCipherDetailsTag(ctx); testMalformedCipherDetails(ctx); @@ -1394,7 +1394,7 @@ TEST_CASE("/KmsConnector/REST/GetEncryptionKeyOps") { state Arena arena; // initialize cipher key used for testing - generateRandomData(&BASE_CIPHER_KEY_TEST[0], 32); + deterministicRandom()->randomBytes(&BASE_CIPHER_KEY_TEST[0], 32); // Prepare KmsConnector context details wait(testParseDiscoverKmsUrlFile(ctx)); diff --git a/fdbserver/VersionedBTree.actor.cpp b/fdbserver/VersionedBTree.actor.cpp index 98bd0f684a..b0273962a6 100644 --- a/fdbserver/VersionedBTree.actor.cpp +++ b/fdbserver/VersionedBTree.actor.cpp @@ -10273,7 +10273,7 @@ TEST_CASE(":/redwood/performance/extentQueue") { state int v; state ExtentQueueEntry<16> e; - generateRandomData(e.entry, 16); + deterministicRandom()->randomBytes(e.entry, 16); state int sinceYield = 0; for (v = 1; v <= numEntries; ++v) { // Sometimes do a commit diff --git a/fdbserver/include/fdbserver/EncryptedMutationMessage.h b/fdbserver/include/fdbserver/EncryptedMutationMessage.h index d94e7f7f1f..b65be8269e 100644 --- a/fdbserver/include/fdbserver/EncryptedMutationMessage.h +++ b/fdbserver/include/fdbserver/EncryptedMutationMessage.h @@ -65,7 +65,7 @@ struct EncryptedMutationMessage { ASSERT(textCipherItr != cipherKeys.end() && textCipherItr->second.isValid()); ASSERT(headerCipherItr != cipherKeys.end() && headerCipherItr->second.isValid()); uint8_t iv[AES_256_IV_LENGTH]; - generateRandomData(iv, AES_256_IV_LENGTH); + deterministicRandom()->randomBytes(iv, AES_256_IV_LENGTH); BinaryWriter bw(AssumeVersion(g_network->protocolVersion())); bw << mutation; EncryptedMutationMessage encrypted_mutation; @@ -114,4 +114,4 @@ struct EncryptedMutationMessage { return mutation; } }; -#endif \ No newline at end of file +#endif diff --git a/fdbserver/workloads/AsyncFileCorrectness.actor.cpp b/fdbserver/workloads/AsyncFileCorrectness.actor.cpp index 3eff9d3a05..cbf47d47dc 100644 --- a/fdbserver/workloads/AsyncFileCorrectness.actor.cpp +++ b/fdbserver/workloads/AsyncFileCorrectness.actor.cpp @@ -377,7 +377,7 @@ struct AsyncFileCorrectnessWorkload : public AsyncFileWorkload { } } else if (info.operation == WRITE) { info.data = self->allocateBuffer(info.length); - generateRandomData(reinterpret_cast(info.data->buffer), info.length); + deterministicRandom()->randomBytes(reinterpret_cast(info.data->buffer), info.length); memcpy(&self->memoryFile->buffer[info.offset], info.data->buffer, info.length); memset(&self->fileValidityMask[info.offset], 0xFF, info.length); diff --git a/fdbserver/workloads/EncryptionOps.actor.cpp b/fdbserver/workloads/EncryptionOps.actor.cpp index eb86ec12fc..3a124951d2 100644 --- a/fdbserver/workloads/EncryptionOps.actor.cpp +++ b/fdbserver/workloads/EncryptionOps.actor.cpp @@ -159,7 +159,7 @@ struct EncryptionOpsWorkload : TestWorkload { void generateRandomBaseCipher(const int maxLen, uint8_t* buff, int* retLen) { memset(buff, 0, maxLen); *retLen = deterministicRandom()->randomInt(maxLen / 2, maxLen); - generateRandomData(buff, *retLen); + deterministicRandom()->randomBytes(buff, *retLen); } void setupCipherEssentials() { @@ -247,7 +247,7 @@ struct EncryptionOpsWorkload : TestWorkload { const EncryptAuthTokenMode authMode, BlobCipherEncryptHeader* header) { uint8_t iv[AES_256_IV_LENGTH]; - generateRandomData(&iv[0], AES_256_IV_LENGTH); + deterministicRandom()->randomBytes(&iv[0], AES_256_IV_LENGTH); EncryptBlobCipherAes265Ctr encryptor(textCipherKey, headerCipherKey, &iv[0], AES_256_IV_LENGTH, authMode); auto start = std::chrono::high_resolution_clock::now(); @@ -341,7 +341,7 @@ struct EncryptionOpsWorkload : TestWorkload { } int dataLen = isFixedSizePayload() ? pageSize : deterministicRandom()->randomInt(100, maxBufSize); - generateRandomData(buff.get(), dataLen); + deterministicRandom()->randomBytes(buff.get(), dataLen); // Encrypt the payload - generates BlobCipherEncryptHeader to assist decryption later BlobCipherEncryptHeader header; diff --git a/fdbserver/workloads/TenantManagementWorkload.actor.cpp b/fdbserver/workloads/TenantManagementWorkload.actor.cpp index c57c3da4ad..7f0a855ef1 100644 --- a/fdbserver/workloads/TenantManagementWorkload.actor.cpp +++ b/fdbserver/workloads/TenantManagementWorkload.actor.cpp @@ -85,7 +85,7 @@ struct TenantManagementWorkload : TestWorkload { if (self->clientId == 0) { self->tenantSubspace = makeString(deterministicRandom()->randomInt(0, 10)); loop { - generateRandomData(mutateString(self->tenantSubspace), self->tenantSubspace.size()); + deterministicRandom()->randomBytes(mutateString(self->tenantSubspace), self->tenantSubspace.size()); if (!self->tenantSubspace.startsWith(systemKeys.begin)) { break; } diff --git a/flow/BlobCipher.cpp b/flow/BlobCipher.cpp index 4b36623f60..60626af4f8 100644 --- a/flow/BlobCipher.cpp +++ b/flow/BlobCipher.cpp @@ -389,7 +389,7 @@ EncryptBlobCipherAes265Ctr::EncryptBlobCipherAes265Ctr(Reference const EncryptAuthTokenMode mode) : ctx(EVP_CIPHER_CTX_new()), textCipherKey(tCipherKey), headerCipherKey(hCipherKey), authTokenMode(mode) { ASSERT(isEncryptHeaderAuthTokenModeValid(mode)); - generateRandomData(iv, AES_256_IV_LENGTH); + deterministicRandom()->randomBytes(iv, AES_256_IV_LENGTH); init(); } @@ -767,7 +767,7 @@ TEST_CASE("flow/BlobCipher") { BaseCipher(const EncryptCipherDomainId& dId, const EncryptCipherBaseKeyId& kId) : domainId(dId), len(deterministicRandom()->randomInt(AES_256_KEY_LENGTH / 2, AES_256_KEY_LENGTH + 1)), keyId(kId), key(std::make_unique(len)) { - generateRandomData(key.get(), len); + deterministicRandom()->randomBytes(key.get(), len); } }; @@ -870,11 +870,11 @@ TEST_CASE("flow/BlobCipher") { Reference headerCipherKey = cipherKeyCache->getLatestCipherKey(ENCRYPT_HEADER_DOMAIN_ID); const int bufLen = deterministicRandom()->randomInt(786, 2127) + 512; uint8_t orgData[bufLen]; - generateRandomData(&orgData[0], bufLen); + deterministicRandom()->randomBytes(&orgData[0], bufLen); Arena arena; uint8_t iv[AES_256_IV_LENGTH]; - generateRandomData(&iv[0], AES_256_IV_LENGTH); + deterministicRandom()->randomBytes(&iv[0], AES_256_IV_LENGTH); BlobCipherEncryptHeader headerCopy; // validate basic encrypt followed by decrypt operation for AUTH_MODE_NONE diff --git a/flow/DeterministicRandom.cpp b/flow/DeterministicRandom.cpp index 5fff2e0cb5..63cc25c8d1 100644 --- a/flow/DeterministicRandom.cpp +++ b/flow/DeterministicRandom.cpp @@ -19,6 +19,7 @@ */ #include "fmt/format.h" +#include "flow/Arena.h" #include "flow/DeterministicRandom.h" #include @@ -124,6 +125,23 @@ std::string DeterministicRandom::randomAlphaNumeric(int length) { return s; } +void DeterministicRandom::randomBytes(uint8_t* buf, int length) { + constexpr const int unitLen = sizeof(decltype(gen64())); + for (int i = 0; i < length; i += unitLen) { + auto val = gen64(); + memcpy(buf + i, &val, std::min(unitLen, length - i)); + } + if (randLog && useRandLog) { + constexpr const int cutOff = 32; + bool tooLong = length > cutOff; + fmt::print(randLog, + "Rbytes[{}] {}{}\n", + length, + StringRef(buf, std::min(cutOff, length)).printable(), + tooLong ? "..." : ""); + } +} + uint64_t DeterministicRandom::peek() const { return next; } @@ -134,10 +152,3 @@ void DeterministicRandom::addref() { void DeterministicRandom::delref() { ReferenceCounted::delref(); } - -void generateRandomData(uint8_t* buffer, int length) { - for (int i = 0; i < length; i += sizeof(uint32_t)) { - uint32_t val = deterministicRandom()->randomUInt32(); - memcpy(&buffer[i], &val, std::min(length - i, (int)sizeof(uint32_t))); - } -} diff --git a/flow/StreamCipher.cpp b/flow/StreamCipher.cpp index cf5f8d7b2f..4a2f1869a5 100644 --- a/flow/StreamCipher.cpp +++ b/flow/StreamCipher.cpp @@ -199,11 +199,11 @@ TEST_CASE("flow/StreamCipher") { StreamCipherKey const* key = StreamCipherKey::getGlobalCipherKey(); StreamCipher::IV iv; - generateRandomData(iv.data(), iv.size()); + deterministicRandom()->randomBytes(iv.data(), iv.size()); Arena arena; std::vector plaintext(deterministicRandom()->randomInt(0, 10001)); - generateRandomData(&plaintext.front(), plaintext.size()); + deterministicRandom()->randomBytes(&plaintext.front(), plaintext.size()); std::vector ciphertext(plaintext.size() + AES_BLOCK_SIZE); std::vector decryptedtext(plaintext.size() + AES_BLOCK_SIZE); diff --git a/flow/include/flow/DeterministicRandom.h b/flow/include/flow/DeterministicRandom.h index 3f5115c371..235a910f6c 100644 --- a/flow/include/flow/DeterministicRandom.h +++ b/flow/include/flow/DeterministicRandom.h @@ -49,6 +49,7 @@ public: UID randomUniqueID() override; char randomAlphaNumeric() override; std::string randomAlphaNumeric(int length) override; + void randomBytes(uint8_t* buf, int length) override; uint64_t peek() const override; void addref() override; void delref() override; diff --git a/flow/include/flow/IRandom.h b/flow/include/flow/IRandom.h index 1430fb018d..fe23becb17 100644 --- a/flow/include/flow/IRandom.h +++ b/flow/include/flow/IRandom.h @@ -143,6 +143,7 @@ public: virtual UID randomUniqueID() = 0; virtual char randomAlphaNumeric() = 0; virtual std::string randomAlphaNumeric(int length) = 0; + virtual void randomBytes(uint8_t* buf, int length) = 0; virtual uint32_t randomSkewedUInt32(uint32_t min, uint32_t maxPlusOne) = 0; virtual uint64_t peek() const = 0; // returns something that is probably different for different random states. // Deterministic (and idempotent) for a deterministic generator. @@ -196,7 +197,4 @@ Reference nondeterministicRandom(); // WARNING: This is not thread safe and must not be called from any other thread than the network thread! Reference debugRandom(); -// Populates a buffer with a random sequence of bytes -void generateRandomData(uint8_t* buffer, int length); - #endif diff --git a/flow/include/flow/StreamCipher.h b/flow/include/flow/StreamCipher.h index cc7df84e47..787c31c4c0 100644 --- a/flow/include/flow/StreamCipher.h +++ b/flow/include/flow/StreamCipher.h @@ -53,7 +53,7 @@ public: int size() const { return keySize; } uint8_t* data() const { return arr.get(); } void initializeKey(uint8_t* data, int len); - void initializeRandomTestKey() { generateRandomData(arr.get(), keySize); } + void initializeRandomTestKey() { deterministicRandom()->randomBytes(arr.get(), keySize); } void reset() { memset(arr.get(), 0, keySize); } static bool isGlobalKeyPresent(); diff --git a/flowbench/BenchEncrypt.cpp b/flowbench/BenchEncrypt.cpp index e99e80a209..41d923a1af 100644 --- a/flowbench/BenchEncrypt.cpp +++ b/flowbench/BenchEncrypt.cpp @@ -25,7 +25,7 @@ static StreamCipher::IV getRandomIV() { StreamCipher::IV iv; - generateRandomData(iv.data(), iv.size()); + deterministicRandom()->randomBytes(iv.data(), iv.size()); return iv; } diff --git a/flowbench/GlobalData.cpp b/flowbench/GlobalData.cpp index 8cdd38a844..88883909b5 100644 --- a/flowbench/GlobalData.cpp +++ b/flowbench/GlobalData.cpp @@ -28,7 +28,7 @@ static inline void initGlobalData() { if (!globalData) { globalData = static_cast(allocateFast(globalDataSize)); } - generateRandomData(globalData, globalDataSize); + deterministicRandom()->randomBytes(globalData, globalDataSize); } KeyValueRef getKV(size_t keySize, size_t valueSize) {