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.
 
 
 
 
 

240 lines
8.8 KiB

  1. /**
  2. * @file decaf/strobe.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 STROBE instances, C++ wrapper.
  9. * @warning This protocol framework is entirely experimental, and shouldn't be
  10. * relied on for anything serious yet.
  11. */
  12. #ifndef __DECAF_STROBE_HXX__
  13. #define __DECAF_STROBE_HXX__
  14. #include <decaf/strobe.h>
  15. #include <sys/types.h>
  16. /** @cond internal */
  17. #if __cplusplus >= 201103L
  18. #define NOEXCEPT noexcept
  19. #define DELETE = delete
  20. #else
  21. #define NOEXCEPT throw()
  22. #define DELETE
  23. #endif
  24. /** @endcond */
  25. namespace decaf {
  26. /** @brief An exception for misused protocol, eg encrypt with no key. */
  27. class ProtocolException : public std::exception {
  28. public:
  29. /** @return "ProtocolException" */
  30. virtual const char * what() const NOEXCEPT { return "ProtocolException"; }
  31. };
  32. /** STROBE protocol framework object */
  33. class Strobe {
  34. public:
  35. /** The wrapped object */
  36. keccak_decaf_TOY_strobe_t wrapped;
  37. /** Number of bytes in a default authentication size. */
  38. static const uint16_t DEFAULT_AUTH_SIZE = 16;
  39. /** Am I a server or a client? */
  40. enum client_or_server { SERVER, CLIENT };
  41. /** Create protocol object. */
  42. inline Strobe (
  43. const char *description, /**< Description of this protocol. */
  44. client_or_server whoami, /**< Am I client or server? */
  45. const decaf_kparams_s &params = STROBE_256 /**< Strength parameters */
  46. ) NOEXCEPT {
  47. decaf_TOY_strobe_init(wrapped, &params, description, whoami == CLIENT);
  48. keyed = false;
  49. }
  50. /** Securely destroy by overwriting state. */
  51. inline ~Strobe() NOEXCEPT { decaf_TOY_strobe_destroy(wrapped); }
  52. /** Stir in fixed key, from a C++ block. */
  53. inline void fixed_key (
  54. const Block &data /**< The key. */
  55. ) throw(ProtocolException) {
  56. decaf_TOY_strobe_fixed_key(wrapped, data.data(), data.size());
  57. keyed = true;
  58. }
  59. /** Stir in fixed key, from a serializeable object. */
  60. template<class T> inline void fixed_key (
  61. const Serializable<T> &data /**< The key. */
  62. ) throw(ProtocolException) {
  63. fixed_key(data.serialize());
  64. }
  65. /** Stir in DH key, from a C++ block. */
  66. inline void dh_key (
  67. const Block &data /**< The key. */
  68. ) throw(ProtocolException) {
  69. decaf_TOY_strobe_dh_key(wrapped, data.data(), data.size());
  70. keyed = true;
  71. }
  72. /** Stir in DH key, from a serializeable object. */
  73. template<class T> inline void dh_key (
  74. const Serializable<T> &data /**< The key. */
  75. ) throw(ProtocolException) {
  76. dh_key(data.serialize());
  77. }
  78. /** Stir in an explicit nonce. */
  79. inline void nonce(const Block &data) NOEXCEPT {
  80. decaf_TOY_strobe_nonce(wrapped, data.data(), data.size());
  81. }
  82. /** Stir in data we sent as plaintext. NB This doesn't actually send anything. */
  83. inline void send_plaintext(const Block &data) NOEXCEPT {
  84. decaf_TOY_strobe_plaintext(wrapped, data.data(), data.size(), true);
  85. }
  86. /** Stir in serializeable data we sent as plaintext. NB This doesn't actually send anything. */
  87. template<class T> inline void send_plaintext(const Serializable<T> &data) NOEXCEPT {
  88. send_plaintext(data.serialize());
  89. }
  90. /** Stir in data we received as plaintext. NB This doesn't actually receive anything. */
  91. inline void recv_plaintext(const Block &data) NOEXCEPT {
  92. decaf_TOY_strobe_plaintext(wrapped, data.data(), data.size(), false);
  93. }
  94. /** Stir in associated data. */
  95. inline void ad(const Block &data) {
  96. decaf_TOY_strobe_ad(wrapped, data.data(), data.size());
  97. }
  98. /** Stir in associated serializable data. */
  99. template<class T> inline void ad(const Serializable<T> &data) NOEXCEPT {
  100. ad(data.serialize());
  101. }
  102. /** Encrypt into a buffer, without appending authentication data */
  103. inline void encrypt_no_auth(Buffer out, const Block &data) throw(LengthException,ProtocolException) {
  104. if (!keyed) throw ProtocolException();
  105. if (out.size() != data.size()) throw LengthException();
  106. decaf_TOY_strobe_encrypt(wrapped, out.data(), data.data(), data.size());
  107. }
  108. /** Encrypt, without appending authentication data */
  109. inline SecureBuffer encrypt_no_auth(const Block &data) throw(ProtocolException) {
  110. SecureBuffer out(data.size()); encrypt_no_auth(out, data); return out;
  111. }
  112. /** Encrypt a serializable object, without appending authentication data */
  113. template<class T> inline SecureBuffer encrypt_no_auth(const Serializable<T> &data) throw(ProtocolException) {
  114. return encrypt_no_auth(data.serialize());
  115. }
  116. /** Decrypt into a buffer, without checking authentication data. */
  117. inline void decrypt_no_auth(Buffer out, const Block &data) throw(LengthException,ProtocolException) {
  118. if (!keyed) throw ProtocolException();
  119. if (out.size() != data.size()) throw LengthException();
  120. decaf_TOY_strobe_decrypt(wrapped, out.data(), data.data(), data.size());
  121. }
  122. /** Decrypt, without checking authentication data. */
  123. inline SecureBuffer decrypt_no_auth(const Block &data) throw(ProtocolException) {
  124. SecureBuffer out(data.size()); decrypt_no_auth(out, data); return out;
  125. }
  126. /** Produce an authenticator into a buffer. */
  127. inline void produce_auth(Buffer out, bool even_though_unkeyed = false) throw(LengthException,ProtocolException) {
  128. if (!keyed && !even_though_unkeyed) throw ProtocolException();
  129. if (out.size() > STROBE_MAX_AUTH_BYTES) throw LengthException();
  130. decaf_TOY_strobe_produce_auth(wrapped, out.data(), out.size());
  131. }
  132. /** Produce an authenticator. */
  133. inline SecureBuffer produce_auth(uint8_t bytes = DEFAULT_AUTH_SIZE) throw(ProtocolException) {
  134. SecureBuffer out(bytes); produce_auth(out); return out;
  135. }
  136. /** Encrypt into a buffer and append authentication data */
  137. inline void encrypt(
  138. Buffer out, const Block &data, uint8_t auth = DEFAULT_AUTH_SIZE
  139. ) throw(LengthException,ProtocolException) {
  140. if (out.size() < data.size() || out.size() != data.size() + auth) throw LengthException();
  141. encrypt_no_auth(out.slice(0,data.size()), data);
  142. produce_auth(out.slice(data.size(),auth));
  143. }
  144. /** Encrypt and append authentication data */
  145. inline SecureBuffer encrypt (
  146. const Block &data, uint8_t auth = DEFAULT_AUTH_SIZE
  147. ) throw(LengthException,ProtocolException,std::bad_alloc ){
  148. SecureBuffer out(data.size() + auth); encrypt(out, data, auth); return out;
  149. }
  150. /** Encrypt a serializable object and append authentication data */
  151. template<class T> inline SecureBuffer encrypt (
  152. const Serializable<T> &data, uint8_t auth = DEFAULT_AUTH_SIZE
  153. ) throw(LengthException,ProtocolException,std::bad_alloc ){
  154. return encrypt(data.serialize(), auth);
  155. }
  156. /** Decrypt into a buffer and check authentication data */
  157. inline void decrypt (
  158. Buffer out, const Block &data, uint8_t bytes = DEFAULT_AUTH_SIZE
  159. ) throw(LengthException, CryptoException, ProtocolException) {
  160. if (out.size() > data.size() || out.size() != data.size() - bytes) throw LengthException();
  161. decrypt_no_auth(out, data.slice(0,out.size()));
  162. verify_auth(data.slice(out.size(),bytes));
  163. }
  164. /** Decrypt and check authentication data */
  165. inline SecureBuffer decrypt (
  166. const Block &data, uint8_t bytes = DEFAULT_AUTH_SIZE
  167. ) throw(LengthException,CryptoException,ProtocolException,std::bad_alloc) {
  168. if (data.size() < bytes) throw LengthException();
  169. SecureBuffer out(data.size() - bytes); decrypt(out, data, bytes); return out;
  170. }
  171. /** Check authentication data */
  172. inline void verify_auth(const Block &auth) throw(LengthException,CryptoException) {
  173. if (auth.size() == 0 || auth.size() > STROBE_MAX_AUTH_BYTES) throw LengthException();
  174. if (decaf_TOY_strobe_verify_auth(wrapped, auth.data(), auth.size()) != DECAF_SUCCESS) throw CryptoException();
  175. }
  176. /** Fill pseudorandom data into a buffer */
  177. inline void prng(Buffer out) NOEXCEPT {
  178. (void)decaf_TOY_strobe_prng(wrapped, out.data(), out.size());
  179. }
  180. /** Return pseudorandom data */
  181. inline SecureBuffer prng(size_t bytes) {
  182. SecureBuffer out(bytes); prng(out); return out;
  183. }
  184. /** Change specs, perhaps to a faster spec that takes advantage of being keyed.
  185. * @warning Experimental.
  186. */
  187. inline void respec(const decaf_kparams_s &params) throw(ProtocolException) {
  188. if (!keyed) throw(ProtocolException());
  189. decaf_TOY_strobe_respec(wrapped, &params);
  190. }
  191. private:
  192. bool keyed;
  193. };
  194. } /* namespace decaf */
  195. #undef NOEXCEPT
  196. #undef DELETE
  197. #endif /* __DECAF_STROBE_HXX__ */