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.
 
 
 
 
 

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