1 /*############################################################################ 2 # Copyright 2017 Intel Corporation 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 # http://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 /// One time pad class 17 /*! \file */ 18 19 #ifndef EPID_MEMBER_TINY_MATH_UNITTESTS_ONETIMEPAD_H_ 20 #define EPID_MEMBER_TINY_MATH_UNITTESTS_ONETIMEPAD_H_ 21 22 #include <climits> // for CHAR_BIT 23 #include <cstdint> 24 #include <random> 25 #include <stdexcept> 26 #include <vector> 27 28 #if defined(_WIN32) || defined(_WIN64) 29 #define __STDCALL __stdcall 30 #else 31 #define __STDCALL 32 #endif 33 34 /// One time pad with Bitsupplier interface 35 class OneTimePad { 36 public: 37 /// Default constructor OneTimePad()38 OneTimePad() : bytes_consumed_(0), reported_having_no_data_(false) {} 39 /// Construct using mersenne twister OneTimePad(size_t num_bytes)40 explicit OneTimePad(size_t num_bytes) 41 : bytes_consumed_(0), reported_having_no_data_(false) { 42 data_.resize(num_bytes); 43 std::mt19937 generator; 44 generator.seed(1); 45 for (size_t i = 0; i < num_bytes; i++) 46 data_[i] = static_cast<uint8_t>(generator() & 0x000000ff); 47 } 48 /// Construct with data OneTimePad(std::vector<uint8_t> const & uint8_data)49 explicit OneTimePad(std::vector<uint8_t> const& uint8_data) 50 : reported_having_no_data_(false) { 51 InitUint8(uint8_data); 52 } 53 /// Re-initialize with unit8 data InitUint8(std::vector<uint8_t> const & uint8_data)54 void InitUint8(std::vector<uint8_t> const& uint8_data) { 55 if (uint8_data.size() > SIZE_MAX / CHAR_BIT) 56 throw std::invalid_argument("input exceeded SIZE_MAX bits"); 57 bytes_consumed_ = 0; 58 data_.clear(); 59 data_ = uint8_data; 60 reported_having_no_data_ = false; 61 } 62 /// Re-initialize with unit32 data InitUint32(std::vector<uint32_t> const & uint32_data)63 void InitUint32(std::vector<uint32_t> const& uint32_data) { 64 if (uint32_data.size() * sizeof(uint32_t) > SIZE_MAX / CHAR_BIT) 65 throw std::invalid_argument("input exceeded SIZE_MAX bits"); 66 bytes_consumed_ = 0; 67 data_.clear(); 68 for (auto u32 : uint32_data) { 69 data_.push_back((uint8_t)(u32 & 0xFF)); 70 data_.push_back((uint8_t)((u32 & 0xFF00) >> 8)); 71 data_.push_back((uint8_t)((u32 & 0xFF0000) >> 16)); 72 data_.push_back((uint8_t)((u32 & 0xFF000000) >> 24)); 73 reported_having_no_data_ = false; 74 } 75 } 76 /// Destructor ~OneTimePad()77 ~OneTimePad() {} 78 /// returns bits consumed BitsConsumed()79 size_t BitsConsumed() const { return bytes_consumed_ * CHAR_BIT; } 80 /// Generates random number Generate(unsigned int * random_data,int num_bits,void * user_data)81 static int __STDCALL Generate(unsigned int* random_data, int num_bits, 82 void* user_data) { 83 size_t num_bytes = num_bits / CHAR_BIT; 84 size_t extra_bits = num_bits % CHAR_BIT; 85 uint8_t* random_bytes = reinterpret_cast<uint8_t*>(random_data); 86 OneTimePad* myprng = (OneTimePad*)user_data; 87 if ((!random_data) || (num_bits <= 0)) { 88 return -5; // bad arg 89 } 90 if (myprng->reported_having_no_data_) { 91 throw std::runtime_error( 92 "request for random data after being informed random data was " 93 "exhausted"); 94 } 95 if ((size_t)num_bits > myprng->BitsAvailable()) { 96 // cause an exception to be thrown on next invocation 97 myprng->reported_having_no_data_ = true; 98 return -1; // out of random data 99 } 100 if (0 != extra_bits) { 101 // can only handle even number of byte requests 102 return -5; 103 } 104 105 for (unsigned int n = 0; n < num_bytes; n++) { 106 random_bytes[n] = myprng->data_[myprng->bytes_consumed_++]; 107 } 108 return 0; 109 } 110 111 private: 112 /// returns bits available BitsAvailable()113 size_t BitsAvailable() const { 114 return (data_.size() - bytes_consumed_) * CHAR_BIT; 115 } 116 117 size_t bytes_consumed_ = 0; 118 std::vector<uint8_t> data_; 119 bool reported_having_no_data_ = false; 120 }; 121 122 #endif // EPID_MEMBER_TINY_MATH_UNITTESTS_ONETIMEPAD_H_ 123