onetimepad.h 4.1 KB

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