You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

206 lines
6.2 KiB

  1. /**
  2. * @file shake.hxx
  3. * @copyright
  4. * Based on CC0 code by David Leon Gil, 2015 \n
  5. * Copyright (c) 2015 Cryptography Research, Inc. \n
  6. * Released under the MIT License. See LICENSE.txt for license information.
  7. * @author Mike Hamburg
  8. * @brief SHA-3-n and SHAKE-n instances, C++ wrapper.
  9. * @warning EXPERIMENTAL! The names, parameter orders etc are likely to change.
  10. */
  11. #ifndef __SHAKE_HXX__
  12. #define __SHAKE_HXX__
  13. #include "shake.h"
  14. #include <string>
  15. #include <sys/types.h>
  16. /** @cond internal */
  17. #if __cplusplus >= 201103L
  18. #define DELETE = delete
  19. #define NOEXCEPT noexcept
  20. #define EXPLICIT_CON explicit
  21. #define GET_DATA(str) ((const unsigned char *)&(str)[0])
  22. #else
  23. #define DELETE
  24. #define NOEXCEPT throw()
  25. #define EXPLICIT_CON
  26. #define GET_DATA(str) ((const unsigned char *)((str).data()))
  27. #endif
  28. /** @endcond */
  29. namespace decaf {
  30. /** A Keccak sponge internal class */
  31. class KeccakSponge {
  32. protected:
  33. /** The C-wrapper sponge state */
  34. keccak_sponge_t sp;
  35. /** Initialize from parameters */
  36. inline KeccakSponge(const struct kparams_s *params) NOEXCEPT { sponge_init(sp, params); }
  37. /** No initialization */
  38. inline KeccakSponge(const NOINIT &) NOEXCEPT { }
  39. public:
  40. /** Destructor zeroizes state */
  41. inline ~KeccakSponge() NOEXCEPT { sponge_destroy(sp); }
  42. };
  43. /**
  44. * Hash function derived from Keccak
  45. * @todo throw exceptions when hash is misused.
  46. */
  47. class KeccakHash : public KeccakSponge {
  48. protected:
  49. /** Initialize from parameters */
  50. inline KeccakHash(const kparams_s *params) NOEXCEPT : KeccakSponge(params) {}
  51. public:
  52. /** Add more data to running hash */
  53. inline void update(const uint8_t *__restrict__ in, size_t len) { sha3_update(sp,in,len); }
  54. /** Add more data to running hash, C++ version. */
  55. inline void update(const Block &s) { sha3_update(sp,s.data(),s.size()); }
  56. /** Add more data, stream version. */
  57. inline KeccakHash &operator<<(const Block &s) { update(s); return *this; }
  58. /** Same as <<. */
  59. inline KeccakHash &operator+=(const Block &s) { return *this << s; }
  60. /**
  61. * @brief Output bytes from the sponge.
  62. * @todo make this throw exceptions.
  63. */
  64. inline void output(TmpBuffer b) { sha3_output(sp,b.data(),b.size()); }
  65. /**
  66. * @brief Output bytes from the sponge.
  67. * @todo make this throw exceptions.
  68. */
  69. inline void output(Buffer &b) { sha3_output(sp,b.data(),b.size()); }
  70. /** @brief Output bytes from the sponge. */
  71. inline SecureBuffer output(size_t len) {
  72. SecureBuffer buffer(len);
  73. sha3_output(sp,buffer,len);
  74. return buffer;
  75. }
  76. /** @brief Return the sponge's default output size. */
  77. inline size_t default_output_size() const NOEXCEPT {
  78. return sponge_default_output_bytes(sp);
  79. }
  80. /** Output the default number of bytes. */
  81. inline SecureBuffer output() {
  82. return output(default_output_size());
  83. }
  84. };
  85. /** Fixed-output-length SHA3 */
  86. template<int bits> class SHA3 : public KeccakHash {
  87. private:
  88. /** Get the parameter template block for this hash */
  89. const struct kparams_s *get_params();
  90. public:
  91. /** Initializer */
  92. inline SHA3() NOEXCEPT : KeccakHash(get_params()) {}
  93. };
  94. /** Variable-output-length SHAKE */
  95. template<int bits>
  96. class SHAKE : public KeccakHash {
  97. private:
  98. /** Get the parameter template block for this hash */
  99. const struct kparams_s *get_params();
  100. public:
  101. /** Initializer */
  102. inline SHAKE() NOEXCEPT : KeccakHash(get_params()) {}
  103. };
  104. /** @cond internal */
  105. template<> const struct kparams_s *SHAKE<128>::get_params() { return &SHAKE128_params_s; }
  106. template<> const struct kparams_s *SHAKE<256>::get_params() { return &SHAKE256_params_s; }
  107. template<> const struct kparams_s *SHA3<224>::get_params() { return &SHA3_224_params_s; }
  108. template<> const struct kparams_s *SHA3<256>::get_params() { return &SHA3_256_params_s; }
  109. template<> const struct kparams_s *SHA3<384>::get_params() { return &SHA3_384_params_s; }
  110. template<> const struct kparams_s *SHA3<512>::get_params() { return &SHA3_512_params_s; }
  111. /** @endcond */
  112. /** Sponge-based random-number generator */
  113. class SpongeRng : private KeccakSponge {
  114. public:
  115. class RngException : public std::exception {
  116. private:
  117. const char *const what_;
  118. public:
  119. const int err_code;
  120. const char *what() const NOEXCEPT { return what_; }
  121. RngException(int err_code, const char *what_) NOEXCEPT : what_(what_), err_code(err_code) {}
  122. };
  123. /** Initialize, deterministically by default, from block */
  124. inline SpongeRng( const Block &in, bool deterministic = true )
  125. : KeccakSponge((NOINIT())) {
  126. spongerng_init_from_buffer(sp,in.data(),in.size(),deterministic);
  127. }
  128. /** Initialize, non-deterministically by default, from C/C++ filename */
  129. inline SpongeRng( const std::string &in = "/dev/urandom", size_t len = 32, bool deterministic = false )
  130. throw(RngException)
  131. : KeccakSponge((NOINIT())) {
  132. int ret = spongerng_init_from_file(sp,in.c_str(),len,deterministic);
  133. if (ret) {
  134. throw RngException(ret, "Couldn't load from file");
  135. }
  136. }
  137. /** Read data to a buffer. */
  138. inline void read(Buffer &buffer) { spongerng_next(sp,buffer.data(),buffer.size()); }
  139. /** Read data to a buffer. */
  140. inline void read(TmpBuffer buffer) { read((Buffer &)buffer); }
  141. /** Read data to a C++ string
  142. * @warning TODO Future versions of this function may throw RngException if a
  143. * nondeterministic RNG fails a reseed.
  144. */
  145. inline SecureBuffer read(size_t length) throw(std::bad_alloc) {
  146. SecureBuffer out(length); read(out); return out;
  147. }
  148. private:
  149. SpongeRng(const SpongeRng &) DELETE;
  150. SpongeRng &operator=(const SpongeRng &) DELETE;
  151. };
  152. /**@cond internal*/
  153. /* FIXME: multiple sizes */
  154. decaf<448>::Scalar::Scalar(SpongeRng &rng) {
  155. *this = rng.read(SER_BYTES);
  156. }
  157. decaf<448>::Point::Point(SpongeRng &rng, bool uniform) {
  158. SecureBuffer buffer((uniform ? 2 : 1) * HASH_BYTES);
  159. rng.read(buffer);
  160. if (uniform) {
  161. decaf_448_point_from_hash_uniform(p,buffer);
  162. } else {
  163. decaf_448_point_from_hash_nonuniform(p,buffer);
  164. }
  165. }
  166. /**@endcond*/
  167. } /* namespace decaf */
  168. #undef NOEXCEPT
  169. #undef EXPLICIT_CON
  170. #undef GET_DATA
  171. #undef DELETE
  172. #endif /* __SHAKE_HXX__ */