xref: /aosp_15_r20/external/federated-compute/fcp/secagg/shared/aes_ctr_prng.h (revision 14675a029014e728ec732f129a32e299b2da0601)
1 /*
2  * Copyright 2018 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef FCP_SECAGG_SHARED_AES_CTR_PRNG_H_
18 #define FCP_SECAGG_SHARED_AES_CTR_PRNG_H_
19 
20 #include <cstdint>
21 #include <string>
22 
23 #include "fcp/secagg/shared/aes_key.h"
24 #include "fcp/secagg/shared/prng.h"
25 #include "openssl/evp.h"
26 
27 namespace fcp {
28 namespace secagg {
29 
30 // A cryptographically strong Deterministic Pseudorandom Number Generator based
31 // on AES-CTR in OpenSSL. The seed must be supplied by the user.
32 //
33 // This code is used for the very specific purpose of generating *reproduceable*
34 // numbers which appear pseudorandom to any party not in possession of the input
35 // seed. DO NOT use AesCtrPrng in any situation where real randomness would be
36 // useful, because it uses no entropy at all and will always produce the same
37 // numbers if given the same seed.
38 //
39 // A single instance of AesCtrPrng can generate up to 2^36 bytes of
40 // pseudorandom output. If more than 2^36 bytes of output are needed, multiple
41 // instances of AesCtrPrng with different seeds should be used.
42 //
43 // This class is not thread-safe.
44 
45 class AesCtrPrng : public SecureBatchPrng {
46  public:
47   // This class should only be instantiated via AesCtrPrngFactory.
48   friend class AesCtrPrngFactory;
49 
50   ~AesCtrPrng() override;
51 
52   // Returns a new pseudorandom number of the specified size, generating new
53   // pseudorandom bytes as needed.
54   uint8_t Rand8() override;
55   uint64_t Rand64() override;
56 
57   // Fills the provided buffer with pseudorandom bytes. Returns the number of
58   // bytes that has been generated, which can be smaller than the requested
59   // buffer_size if it exceeds the maximum buffer size returned by
60   // GetMaxBufferSize().
61   int RandBuffer(uint8_t* buffer, int buffer_size) override;
62 
63   // Get the maximum size of a buffer that can be filled by RandBuffer() in a
64   // single call.
GetMaxBufferSize()65   size_t GetMaxBufferSize() const override { return kCacheSize; }
66 
67  private:
68   static constexpr size_t kIvSize = 16;  // IV size, in bytes
69 
70   // Constructs the PRNG with the given seed, and an IV of all zeroes.
71   // This is ONLY secure if the seed is never used more than once.
72   explicit AesCtrPrng(const AesKey& seed);
73 
74   // Number of AES blocks in the cache.
75   // The number of blocks is optimized to make kCacheSize to be a multiple
76   // of any possible number of bytes in a SecAgg output (i.e. 1 to 8).
77   static constexpr size_t kBatchSize = 3 * 5 * 7;
78 
79   // Block size, in bytes
80   static constexpr size_t kBlockSize = 16;
81 
82   // Size of our cache, in bytes. We cache blocks to save leftover bytes.
83   static constexpr int kCacheSize = kBatchSize * kBlockSize;
84 
85   // For security, we don't want to generate more than 2^32-1 blocks.
86   static constexpr size_t kMaxBlocks = 0xFFFFFFFF;
87 
88   // Fills the selected cache with deterministic pseudorandomly generated bytes.
89   // After this, the associated next_byte_pos counter must be set to 0.
90   void GenerateBytes(uint8_t* cache, int cache_size);
91 
92   // Cache used by both Rand8() and Rand64()
93   uint8_t cache_[kCacheSize];
94   size_t next_byte_pos_;
95 
96   // This is used to generate bytes.
97   static constexpr uint8_t kAllZeroes[kCacheSize] = {0};
98 
99   EVP_CIPHER_CTX* ctx_;
100   size_t blocks_generated_;
101 };
102 
103 }  // namespace secagg
104 }  // namespace fcp
105 
106 #endif  // FCP_SECAGG_SHARED_AES_CTR_PRNG_H_
107