• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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