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.
 
 
 
 
 

342 lines
15 KiB

  1. /**
  2. * @file decaf/strobe.h
  3. * @copyright
  4. * Copyright (c) 2015-2016 Cryptography Research, Inc. \n
  5. * Released under the MIT License. See LICENSE.txt for license information.
  6. * @author Mike Hamburg
  7. * @brief STROBE experimental protocol framework.
  8. * @warning EXPERIMENTAL! The names, parameter orders etc are likely to change.
  9. */
  10. #ifndef __DECAF_STROBE_H__
  11. #define __DECAF_STROBE_H__
  12. #include <decaf/shake.h>
  13. #ifdef __cplusplus
  14. extern "C" {
  15. #endif
  16. /** Keccak STROBE structure as struct. */
  17. typedef struct {
  18. decaf_keccak_sponge_t sponge; /**< Internal sponge object. */
  19. } keccak_strobe_s;
  20. /** Keccak STROBE structure as one-element array */
  21. typedef keccak_strobe_s keccak_strobe_t[1];
  22. /** STROBE parameters, 128-bit estimated security for hashing and encryption */
  23. extern const struct decaf_kparams_s STROBE_128 API_VIS;
  24. /** STROBE parameters, 256-bit estimated security for hashing and encryption */
  25. extern const struct decaf_kparams_s STROBE_256 API_VIS;
  26. /** STROBE parameters, 128-bit estimated security for encryption only (not hashing) */
  27. extern const struct decaf_kparams_s STROBE_KEYED_128 API_VIS;
  28. /** STROBE parameters, 256-bit estimated security for encryption only (not hashing) */
  29. extern const struct decaf_kparams_s STROBE_KEYED_256 API_VIS;
  30. /** Initialize Strobe protocol context. */
  31. void strobe_init (
  32. keccak_strobe_t strobe, /**< [out] The uninitialized strobe object. */
  33. const struct decaf_kparams_s *params, /**< [in] Parameter set descriptor. */
  34. const char *proto, /**< [in] Unique identifier for the protocol. TODO: define namespaces for this */
  35. uint8_t am_client /**< [in] Nonzero if this party. */
  36. ) NONNULL API_VIS;
  37. /** Run a transaction against a STROBE state. */
  38. void strobe_transact (
  39. keccak_strobe_t strobe, /**< [inout] The initialized STROBE object. */
  40. unsigned char *out, /**< [out] The output. */
  41. const unsigned char *in, /**< [in] The input. */
  42. size_t len, /**< [in] The length of the input/output. */
  43. uint32_t cw_flags /**< [in] The control word with flags. */
  44. ) __attribute__((nonnull(1))) API_VIS;
  45. /** Record a message sent in plaintext */
  46. static INLINE UNUSED NONNULL void strobe_plaintext (
  47. keccak_strobe_t strobe, /**< [inout] The STROBE object */
  48. const unsigned char *in, /**< [in] The message. */
  49. uint16_t len, /**< [in] The length of the message. */
  50. uint8_t iSent /**< [in] If nonzero, I sent the message. */
  51. );
  52. /** Report authenticated data in strobe context. */
  53. static INLINE UNUSED NONNULL void
  54. strobe_ad (
  55. keccak_strobe_t strobe, /**< [inout] The strobe object. */
  56. const unsigned char *in, /**< [in] The plaintext. */
  57. size_t len /**< [in] The length of the ad. */
  58. );
  59. /** Set nonce in strobe context. */
  60. static INLINE UNUSED NONNULL void
  61. strobe_nonce (
  62. keccak_strobe_t strobe, /**< [inout] The initialized strobe object. */
  63. const unsigned char *in, /**< [in] The nonce. */
  64. uint16_t len /**< [in] The length of the nonce. */
  65. );
  66. /** Set fixed key in strobe context. */
  67. static INLINE UNUSED NONNULL void
  68. strobe_fixed_key (
  69. keccak_strobe_t strobe, /**< [inout] The initialized strobe object. */
  70. const unsigned char *in, /**< [in] The key. */
  71. uint16_t len /**< [in] The length of the key. */
  72. );
  73. /** Set Diffie-Hellman key in strobe context. */
  74. static INLINE UNUSED NONNULL void
  75. strobe_dh_key (
  76. keccak_strobe_t strobe, /**< [inout] The initialized strobe object. */
  77. const unsigned char *in, /**< [in] The key. */
  78. uint16_t len /**< [in] The length of the key. */
  79. );
  80. /** The maximum number of bytes that strobe_produce_auth can spit out. */
  81. #define STROBE_MAX_AUTH_BYTES 32
  82. /** Produce an authenticator. */
  83. static INLINE UNUSED NONNULL void
  84. strobe_produce_auth (
  85. keccak_strobe_t strobe, /**< [inout] The Strobe protocol context. */
  86. unsigned char *out, /**< [out] The authenticator. */
  87. uint16_t len /**< [in] The length, at most STROBE_MAX_AUTH_BYTES. */
  88. );
  89. /**
  90. * @brief Verify an authenticator.
  91. * @retval DECAF_SUCCESS The operation applied successfully.
  92. * @retval DECAF_FAILURE The operation failed because of a
  93. * bad validator (or because you aren't keyed)
  94. */
  95. decaf_error_t strobe_verify_auth (
  96. keccak_strobe_t strobe, /**< [inout] The Strobe protocol context */
  97. const unsigned char *in, /**< [in] The authenticator */
  98. uint16_t len /**< [in] The length, at most STROBE_MAX_AUTH_BYTES. */
  99. ) WARN_UNUSED NONNULL API_VIS;
  100. /**
  101. * @brief Encrypt bytes from in to out.
  102. * @warning Doesn't produce an auth tag.
  103. */
  104. static INLINE UNUSED NONNULL void
  105. strobe_encrypt (
  106. keccak_strobe_t strobe, /**< [inout] strobe The Strobe protocol context. */
  107. unsigned char *out, /**< [out] The ciphertext. */
  108. const unsigned char *in, /**< [in] The plaintext. */
  109. uint16_t len /**< [in] The length of plaintext and ciphertext. */
  110. );
  111. /**
  112. * Decrypt bytes from in to out.
  113. * @warning Doesn't check an auth tag.
  114. */
  115. static INLINE UNUSED NONNULL void
  116. strobe_decrypt (
  117. keccak_strobe_t strobe, /**< [inout] The Strobe protocol context. */
  118. unsigned char *out, /**< [out] The plaintext. */
  119. const unsigned char *in, /**< [in] The ciphertext. */
  120. uint16_t len /**< [in] The length of plaintext and ciphertext. */
  121. );
  122. /**
  123. * @brief Produce a session-bound pseudorandom value.
  124. *
  125. * @warning This "prng" value is NOT suitable for
  126. * refreshing forward secrecy! It's to replace things
  127. * like TCP session hash.
  128. */
  129. static inline void NONNULL strobe_prng (
  130. keccak_strobe_t strobe, /**< [inout] The Strobe protocol context */
  131. unsigned char *out, /**< [out] The output random data. */
  132. uint16_t len /**< The length. */
  133. );
  134. /** Respecify Strobe protocol object's crypto. */
  135. void strobe_respec (
  136. keccak_strobe_t strobe, /**< [inout] The initialized strobe context. */
  137. const struct decaf_kparams_s *params /**< [in] Strobe parameter descriptor. */
  138. ) NONNULL API_VIS;
  139. /** Securely destroy a STROBE object by overwriting it. */
  140. static INLINE UNUSED NONNULL void
  141. strobe_destroy (
  142. keccak_strobe_t doomed /**< [in] The object to destroy. */
  143. );
  144. /** @cond internal */
  145. /************************************************************************/
  146. /* Declarations of various constants and operating modes, for extension */
  147. /************************************************************************/
  148. /** STROBE modes of operation */
  149. typedef enum {
  150. STROBE_MODE_ABSORB = 0,
  151. STROBE_MODE_DUPLEX = 1,
  152. STROBE_MODE_ABSORB_R = 2,
  153. STROBE_MODE_DUPLEX_R = 3,
  154. /* FIXME: no bits allocated in .py version */
  155. STROBE_MODE_PLAINTEXT = 4,
  156. STROBE_MODE_SQUEEZE = 5,
  157. STROBE_MODE_FORGET = 6,
  158. STROBE_MODE_SQUEEZE_R = 7
  159. } strobe_mode_t;
  160. #define STROBE_FLAG_CLIENT_SENT (1<<8) /**< Set if the client this message. */
  161. #define STROBE_FLAG_IMPLICIT (1<<9) /**< Set if nobody set this message. */
  162. #define STROBE_FLAG_FORGET (1<<12) /**< After this operation, destroy bytes to prevent rollback. */
  163. /* TODO: maybe just make STROBE heavy non-invertible? */
  164. #define STROBE_FLAG_NO_LENGTH (1<<15) /**< This operation has an unknown length (for streaming). */
  165. /* After 1<<16, flags don't go to the sponge anymore, they just affect the handling */
  166. #define STROBE_FLAG_RECV (1<<16) /**< I received this packet, so reverse directions. */
  167. #define STROBE_FLAG_RUN_F (1<<17) /**< Must run F between control word and data. */
  168. #define STROBE_FLAG_MORE (1<<18) /**< Set for all operations in an unknown-length streaming operation after the first */
  169. #define STROBE_FLAG_LENGTH_64 (1<<19) /**< Length is a 64-bit word instead of a 16-bit one. */
  170. #define STROBE_FLAG_NONDIR (STROBE_FLAG_IMPLICIT)
  171. /** Automatic flags implied by the mode */
  172. /* NB: SQUEEZE_R is treated as directional because its' MAC.
  173. * can of course override by orring in IMPLICIT|NONDIR
  174. */
  175. #define STROBE_AUTO_FLAGS(_mode) \
  176. ( (((_mode)&1) ? STROBE_FLAG_RUN_F : 0) \
  177. | (( ((_mode) & ~2) == STROBE_MODE_ABSORB \
  178. || (_mode) == STROBE_MODE_SQUEEZE \
  179. || (_mode) == STROBE_MODE_FORGET \
  180. ) ? STROBE_FLAG_IMPLICIT|STROBE_FLAG_NONDIR : 0) \
  181. )
  182. /**@ Define a control word for STROBE protocols. */
  183. #define STROBE_CONTROL_WORD(_name,_id,_mode,_flags) \
  184. static const uint32_t _name = _id | (_mode<<10) | (_mode<<29) | _flags | STROBE_AUTO_FLAGS(_mode)
  185. STROBE_CONTROL_WORD(STROBE_CW_INIT, 0x00, STROBE_MODE_ABSORB, 0); /**< Initialization with protocol name */
  186. /* Ciphers */
  187. STROBE_CONTROL_WORD(STROBE_CW_FIXED_KEY, 0x10, STROBE_MODE_ABSORB, 0); /**< Fixed symmetric/preshared key */
  188. STROBE_CONTROL_WORD(STROBE_CW_STATIC_PUB, 0x11, STROBE_MODE_PLAINTEXT, 0); /**< Static public key of other party */
  189. STROBE_CONTROL_WORD(STROBE_CW_DH_EPH, 0x12, STROBE_MODE_PLAINTEXT, 0); /**< DH ephemeral key on the wire */
  190. STROBE_CONTROL_WORD(STROBE_CW_DH_KEY, 0x13, STROBE_MODE_ABSORB, 0); /**< DH shared secret key */
  191. STROBE_CONTROL_WORD(STROBE_CW_PRNG, 0x18, STROBE_MODE_SQUEEZE, STROBE_FLAG_FORGET); /**< Generate random bits (for PRNG) */
  192. STROBE_CONTROL_WORD(STROBE_CW_SESSION_HASH, 0x19, STROBE_MODE_SQUEEZE, 0); /**< Generate session hash */
  193. /* Reuse for PRNG */
  194. STROBE_CONTROL_WORD(STROBE_CW_PRNG_INITIAL_SEED, 0x10, STROBE_MODE_ABSORB, STROBE_FLAG_NO_LENGTH); /**< Initial seeding for PRNG */
  195. STROBE_CONTROL_WORD(STROBE_CW_PRNG_RESEED, 0x11, STROBE_MODE_ABSORB, STROBE_FLAG_NO_LENGTH); /**< Later seeding for PRNG */
  196. STROBE_CONTROL_WORD(STROBE_CW_PRNG_CPU_SEED, 0x12, STROBE_MODE_ABSORB, 0); /**< Seed from CPU-builin RNG */
  197. STROBE_CONTROL_WORD(STROBE_CW_PRNG_USER_SEED, 0x13, STROBE_MODE_ABSORB, STROBE_FLAG_LENGTH_64); /**< Seed from user */
  198. STROBE_CONTROL_WORD(STROBE_CW_PRNG_PRNG, 0x14, STROBE_MODE_SQUEEZE, STROBE_FLAG_LENGTH_64 | STROBE_FLAG_FORGET); /**< Call to generate bits */
  199. /* Signatures */
  200. STROBE_CONTROL_WORD(STROBE_CW_SIG_SCHEME, 0x20, STROBE_MODE_ABSORB, 0); /**< Name of the signature scheme we're using. */
  201. STROBE_CONTROL_WORD(STROBE_CW_SIG_PK, 0x21, STROBE_MODE_ABSORB, 0); /**< Public (verification key) */
  202. STROBE_CONTROL_WORD(STROBE_CW_SIG_EPH, 0x22, STROBE_MODE_PLAINTEXT, 0); /**< Schnorr ephemeral. */
  203. STROBE_CONTROL_WORD(STROBE_CW_SIG_CHAL, 0x23, STROBE_MODE_SQUEEZE, 0); /**< Schnorr challenge. */
  204. STROBE_CONTROL_WORD(STROBE_CW_SIG_RESP, 0x24, STROBE_MODE_DUPLEX, 0); /**< Schnoll response. */
  205. /* Payloads and encrypted data */
  206. STROBE_CONTROL_WORD(STROBE_CW_PAYLOAD_PLAINTEXT, 0x30, STROBE_MODE_PLAINTEXT, 0);
  207. STROBE_CONTROL_WORD(STROBE_CW_PAYLOAD_CIPHERTEXT, 0x31, STROBE_MODE_DUPLEX, 0);
  208. STROBE_CONTROL_WORD(STROBE_CW_MAC, 0x32, STROBE_MODE_SQUEEZE_R, STROBE_FLAG_FORGET);
  209. STROBE_CONTROL_WORD(STROBE_CW_AD_EXPLICIT, 0x34, STROBE_MODE_PLAINTEXT, 0);
  210. STROBE_CONTROL_WORD(STROBE_CW_AD_IMPLICIT, 0x35, STROBE_MODE_ABSORB, 0);
  211. STROBE_CONTROL_WORD(STROBE_CW_NONCE_EXPLICIT, 0x36, STROBE_MODE_PLAINTEXT, 0);
  212. STROBE_CONTROL_WORD(STROBE_CW_NONCE_IMPLICIT, 0x37, STROBE_MODE_ABSORB, 0);
  213. STROBE_CONTROL_WORD(STROBE_CW_STREAMING_PLAINTEXT,0x30, STROBE_MODE_PLAINTEXT, STROBE_FLAG_NO_LENGTH); /* TODO: orly? */
  214. /* Change spec, control flow, etc */
  215. STROBE_CONTROL_WORD(STROBE_CW_COMPRESS, 0x40, STROBE_MODE_ABSORB_R, 0);
  216. /* FIXME: adjust this respec logic */
  217. STROBE_CONTROL_WORD(STROBE_CW_RESPEC_INFO, 0x41, STROBE_MODE_ABSORB, STROBE_FLAG_RUN_F | STROBE_FLAG_FORGET);
  218. STROBE_CONTROL_WORD(STROBE_CW_RESPEC, 0x42, STROBE_MODE_ABSORB_R, STROBE_FLAG_RUN_F);
  219. STROBE_CONTROL_WORD(STROBE_CW_FORK, 0x43, STROBE_MODE_ABSORB_R, STROBE_FLAG_RUN_F | STROBE_FLAG_FORGET);
  220. /* FIXME: instance can be rolled back to recover other INSTANCEs */
  221. STROBE_CONTROL_WORD(STROBE_CW_INSTANCE, 0x44, STROBE_MODE_ABSORB_R, STROBE_FLAG_FORGET);
  222. STROBE_CONTROL_WORD(STROBE_CW_ACKNOWLEDGE, 0x45, STROBE_MODE_PLAINTEXT, 0);
  223. /** Reverse a keyword because it's being received instead of sent */
  224. static INLINE UNUSED WARN_UNUSED uint32_t
  225. strobe_cw_recv(uint32_t cw) {
  226. uint32_t recv_toggle = (cw & STROBE_FLAG_NONDIR) ? 0 : STROBE_FLAG_RECV;
  227. if (cw & STROBE_FLAG_IMPLICIT) {
  228. return cw ^ recv_toggle;
  229. } else {
  230. uint32_t modes_2[8] = {
  231. /* Note: most of these really shouldn't happen... */
  232. STROBE_MODE_ABSORB,
  233. STROBE_MODE_DUPLEX_R,
  234. STROBE_MODE_ABSORB_R,
  235. STROBE_MODE_DUPLEX,
  236. STROBE_MODE_PLAINTEXT,
  237. STROBE_MODE_SQUEEZE,
  238. STROBE_MODE_FORGET,
  239. STROBE_MODE_ABSORB
  240. };
  241. return ((cw & ((1<<29)-1)) | (modes_2[cw>>29]<<29)) ^ recv_toggle;
  242. }
  243. }
  244. /***************************************/
  245. /* Implementations of inline functions */
  246. /***************************************/
  247. void strobe_plaintext(keccak_strobe_t strobe, const unsigned char *in, uint16_t len, uint8_t iSent) {
  248. strobe_transact(
  249. strobe, NULL, in, len,
  250. iSent ? STROBE_CW_PAYLOAD_PLAINTEXT
  251. : strobe_cw_recv(STROBE_CW_PAYLOAD_PLAINTEXT)
  252. );
  253. }
  254. void strobe_ad(keccak_strobe_t strobe, const unsigned char *in, size_t len) {
  255. strobe_transact( strobe, NULL, in, len, STROBE_CW_AD_EXPLICIT );
  256. }
  257. void strobe_nonce (keccak_strobe_t strobe, const unsigned char *in, uint16_t len) {
  258. strobe_transact( strobe, NULL, in, len, STROBE_CW_NONCE_EXPLICIT );
  259. }
  260. void strobe_fixed_key (keccak_strobe_t strobe, const unsigned char *in, uint16_t len) {
  261. strobe_transact( strobe, NULL, in, len, STROBE_CW_FIXED_KEY );
  262. }
  263. void strobe_dh_key (keccak_strobe_t strobe, const unsigned char *in, uint16_t len) {
  264. strobe_transact( strobe, NULL, in, len, STROBE_CW_DH_KEY );
  265. }
  266. void strobe_produce_auth (keccak_strobe_t strobe, unsigned char *out, uint16_t len) {
  267. strobe_transact( strobe, out, NULL, len, STROBE_CW_MAC );
  268. }
  269. void strobe_encrypt (keccak_strobe_t strobe, unsigned char *out, const unsigned char *in, uint16_t len) {
  270. strobe_transact(strobe, out, in, len, STROBE_CW_PAYLOAD_CIPHERTEXT);
  271. }
  272. void strobe_decrypt(keccak_strobe_t strobe, unsigned char *out, const unsigned char *in, uint16_t len) {
  273. strobe_transact(strobe, out, in, len, strobe_cw_recv(STROBE_CW_PAYLOAD_CIPHERTEXT));
  274. }
  275. void strobe_prng(keccak_strobe_t strobe, unsigned char *out, uint16_t len) {
  276. strobe_transact( strobe, out, NULL, len, STROBE_CW_PRNG );
  277. }
  278. void strobe_destroy (keccak_strobe_t doomed) {
  279. decaf_sponge_destroy(doomed->sponge);
  280. }
  281. /** @endcond */ /* internal */
  282. #ifdef __cplusplus
  283. } /* extern "C" */
  284. #endif
  285. #endif /* __DECAF_STROBE_H__ */