secretstream.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. #define TEST_NAME "secretstream"
  2. #include "cmptest.h"
  3. int
  4. main(void)
  5. {
  6. crypto_secretstream_xchacha20poly1305_state *state;
  7. crypto_secretstream_xchacha20poly1305_state state_copy;
  8. unsigned char *ad;
  9. unsigned char *header;
  10. unsigned char *k;
  11. unsigned char *c1, *c2, *c3;
  12. unsigned char *m1, *m2, *m3;
  13. unsigned char *m1_, *m2_, *m3_;
  14. unsigned long long res_len;
  15. size_t ad_len;
  16. size_t m1_len, m2_len, m3_len;
  17. int ret;
  18. unsigned char tag;
  19. state = (crypto_secretstream_xchacha20poly1305_state *)
  20. sodium_malloc(crypto_secretstream_xchacha20poly1305_statebytes());
  21. header = (unsigned char *)
  22. sodium_malloc(crypto_secretstream_xchacha20poly1305_HEADERBYTES);
  23. ad_len = randombytes_uniform(100);
  24. m1_len = randombytes_uniform(1000);
  25. m2_len = randombytes_uniform(1000);
  26. m3_len = randombytes_uniform(1000);
  27. c1 = (unsigned char *)
  28. sodium_malloc(m1_len + crypto_secretstream_xchacha20poly1305_ABYTES);
  29. c2 = (unsigned char *)
  30. sodium_malloc(m2_len + crypto_secretstream_xchacha20poly1305_ABYTES);
  31. c3 = (unsigned char *)
  32. sodium_malloc(m3_len + crypto_secretstream_xchacha20poly1305_ABYTES);
  33. ad = (unsigned char *) sodium_malloc(ad_len);
  34. m1 = (unsigned char *) sodium_malloc(m1_len);
  35. m2 = (unsigned char *) sodium_malloc(m2_len);
  36. m3 = (unsigned char *) sodium_malloc(m3_len);
  37. m1_ = (unsigned char *) sodium_malloc(m1_len);
  38. m2_ = (unsigned char *) sodium_malloc(m2_len);
  39. m3_ = (unsigned char *) sodium_malloc(m3_len);
  40. randombytes_buf(ad, ad_len);
  41. randombytes_buf(m1, m1_len);
  42. memcpy(m1_, m1, m1_len);
  43. randombytes_buf(m2, m2_len);
  44. memcpy(m2_, m2, m2_len);
  45. randombytes_buf(m3, m3_len);
  46. memcpy(m3_, m3, m3_len);
  47. k = (unsigned char *)
  48. sodium_malloc(crypto_secretstream_xchacha20poly1305_KEYBYTES);
  49. crypto_secretstream_xchacha20poly1305_keygen(k);
  50. /* push */
  51. ret = crypto_secretstream_xchacha20poly1305_init_push(state, header, k);
  52. assert(ret == 0);
  53. ret = crypto_secretstream_xchacha20poly1305_push
  54. (state, c1, &res_len, m1, m1_len, NULL, 0, 0);
  55. assert(ret == 0);
  56. assert(res_len == m1_len + crypto_secretstream_xchacha20poly1305_ABYTES);
  57. ret = crypto_secretstream_xchacha20poly1305_push
  58. (state, c2, NULL, m2, m2_len, ad, 0, 0);
  59. assert(ret == 0);
  60. ret = crypto_secretstream_xchacha20poly1305_push
  61. (state, c3, NULL, m3, m3_len, ad, ad_len,
  62. crypto_secretstream_xchacha20poly1305_TAG_FINAL);
  63. assert(ret == 0);
  64. /* pull */
  65. ret = crypto_secretstream_xchacha20poly1305_init_pull(state, header, k);
  66. assert(ret == 0);
  67. ret = crypto_secretstream_xchacha20poly1305_pull
  68. (state, m1, &res_len, &tag,
  69. c1, m1_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
  70. assert(ret == 0);
  71. assert(tag == 0);
  72. assert(memcmp(m1, m1_, m1_len) == 0);
  73. assert(res_len == m1_len);
  74. ret = crypto_secretstream_xchacha20poly1305_pull
  75. (state, m2, NULL, &tag,
  76. c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
  77. assert(ret == 0);
  78. assert(tag == 0);
  79. assert(memcmp(m2, m2_, m2_len) == 0);
  80. if (ad_len > 0) {
  81. ret = crypto_secretstream_xchacha20poly1305_pull
  82. (state, m3, NULL, &tag,
  83. c3, m3_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
  84. assert(ret == -1);
  85. }
  86. ret = crypto_secretstream_xchacha20poly1305_pull
  87. (state, m3, NULL, &tag,
  88. c3, m3_len + crypto_secretstream_xchacha20poly1305_ABYTES, ad, ad_len);
  89. assert(ret == 0);
  90. assert(tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL);
  91. assert(memcmp(m3, m3_, m3_len) == 0);
  92. /* previous with FINAL tag */
  93. ret = crypto_secretstream_xchacha20poly1305_pull
  94. (state, m3, NULL, &tag,
  95. c3, m3_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
  96. assert(ret == -1);
  97. /* previous without a tag */
  98. ret = crypto_secretstream_xchacha20poly1305_pull
  99. (state, m2, NULL, &tag,
  100. c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
  101. assert(ret == -1);
  102. /* short ciphertext */
  103. ret = crypto_secretstream_xchacha20poly1305_pull
  104. (state, m2, NULL, &tag, c2,
  105. randombytes_uniform(crypto_secretstream_xchacha20poly1305_ABYTES),
  106. NULL, 0);
  107. assert(ret == -1);
  108. ret = crypto_secretstream_xchacha20poly1305_pull
  109. (state, m2, NULL, &tag, c2, 0, NULL, 0);
  110. assert(ret == -1);
  111. /* empty ciphertext */
  112. ret = crypto_secretstream_xchacha20poly1305_pull
  113. (state, m2, NULL, &tag, c2,
  114. crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
  115. assert(ret == -1);
  116. /* without explicit rekeying */
  117. ret = crypto_secretstream_xchacha20poly1305_init_push(state, header, k);
  118. assert(ret == 0);
  119. ret = crypto_secretstream_xchacha20poly1305_push
  120. (state, c1, NULL, m1, m1_len, NULL, 0, 0);
  121. assert(ret == 0);
  122. ret = crypto_secretstream_xchacha20poly1305_push
  123. (state, c2, NULL, m2, m2_len, NULL, 0, 0);
  124. assert(ret == 0);
  125. ret = crypto_secretstream_xchacha20poly1305_init_pull(state, header, k);
  126. assert(ret == 0);
  127. ret = crypto_secretstream_xchacha20poly1305_pull
  128. (state, m1, NULL, &tag,
  129. c1, m1_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
  130. assert(ret == 0);
  131. ret = crypto_secretstream_xchacha20poly1305_pull
  132. (state, m2, NULL, &tag,
  133. c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
  134. assert(ret == 0);
  135. /* with explicit rekeying */
  136. ret = crypto_secretstream_xchacha20poly1305_init_push(state, header, k);
  137. assert(ret == 0);
  138. ret = crypto_secretstream_xchacha20poly1305_push
  139. (state, c1, NULL, m1, m1_len, NULL, 0, 0);
  140. assert(ret == 0);
  141. crypto_secretstream_xchacha20poly1305_rekey(state);
  142. ret = crypto_secretstream_xchacha20poly1305_push
  143. (state, c2, NULL, m2, m2_len, NULL, 0, 0);
  144. assert(ret == 0);
  145. ret = crypto_secretstream_xchacha20poly1305_init_pull(state, header, k);
  146. assert(ret == 0);
  147. ret = crypto_secretstream_xchacha20poly1305_pull
  148. (state, m1, NULL, &tag,
  149. c1, m1_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
  150. assert(ret == 0);
  151. ret = crypto_secretstream_xchacha20poly1305_pull
  152. (state, m2, NULL, &tag,
  153. c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
  154. assert(ret == -1);
  155. crypto_secretstream_xchacha20poly1305_rekey(state);
  156. ret = crypto_secretstream_xchacha20poly1305_pull
  157. (state, m2, NULL, &tag,
  158. c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
  159. assert(ret == 0);
  160. /* New stream */
  161. ret = crypto_secretstream_xchacha20poly1305_init_push(state, header, k);
  162. assert(ret == 0);
  163. ret = crypto_secretstream_xchacha20poly1305_push
  164. (state, c1, &res_len, m1, m1_len, NULL, 0,
  165. crypto_secretstream_xchacha20poly1305_TAG_PUSH);
  166. assert(ret == 0);
  167. assert(res_len == m1_len + crypto_secretstream_xchacha20poly1305_ABYTES);
  168. /* Force a counter overflow, check that the key has been updated
  169. * even though the tag was not changed to REKEY */
  170. memset(state->nonce, 0xff, 4U);
  171. state_copy = *state;
  172. ret = crypto_secretstream_xchacha20poly1305_push
  173. (state, c2, NULL, m2, m2_len, ad, 0, 0);
  174. assert(ret == 0);
  175. assert(memcmp(state_copy.k, state->k, sizeof state->k) != 0);
  176. assert(memcmp(state_copy.nonce, state->nonce, sizeof state->nonce) != 0);
  177. assert(state->nonce[0] == 1U);
  178. assert(sodium_is_zero(state->nonce + 1, 3U));
  179. ret = crypto_secretstream_xchacha20poly1305_init_pull(state, header, k);
  180. assert(ret == 0);
  181. ret = crypto_secretstream_xchacha20poly1305_pull
  182. (state, m1, &res_len, &tag,
  183. c1, m1_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
  184. assert(ret == 0);
  185. assert(tag == crypto_secretstream_xchacha20poly1305_TAG_PUSH);
  186. assert(memcmp(m1, m1_, m1_len) == 0);
  187. assert(res_len == m1_len);
  188. memset(state->nonce, 0xff, 4U);
  189. ret = crypto_secretstream_xchacha20poly1305_pull
  190. (state, m2, NULL, &tag,
  191. c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
  192. assert(ret == 0);
  193. assert(tag == 0);
  194. assert(memcmp(m2, m2_, m2_len) == 0);
  195. sodium_free(m3_);
  196. sodium_free(m2_);
  197. sodium_free(m1_);
  198. sodium_free(m3);
  199. sodium_free(m2);
  200. sodium_free(m1);
  201. sodium_free(ad);
  202. sodium_free(c3);
  203. sodium_free(c2);
  204. sodium_free(c1);
  205. sodium_free(k);
  206. sodium_free(header);
  207. sodium_free(state);
  208. assert(crypto_secretstream_xchacha20poly1305_abytes() ==
  209. crypto_secretstream_xchacha20poly1305_ABYTES);
  210. assert(crypto_secretstream_xchacha20poly1305_headerbytes() ==
  211. crypto_secretstream_xchacha20poly1305_HEADERBYTES);
  212. assert(crypto_secretstream_xchacha20poly1305_keybytes() ==
  213. crypto_secretstream_xchacha20poly1305_KEYBYTES);
  214. assert(crypto_secretstream_xchacha20poly1305_messagebytes_max() ==
  215. crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX);
  216. assert(crypto_secretstream_xchacha20poly1305_tag_message() ==
  217. crypto_secretstream_xchacha20poly1305_TAG_MESSAGE);
  218. assert(crypto_secretstream_xchacha20poly1305_tag_push() ==
  219. crypto_secretstream_xchacha20poly1305_TAG_PUSH);
  220. assert(crypto_secretstream_xchacha20poly1305_tag_rekey() ==
  221. crypto_secretstream_xchacha20poly1305_TAG_REKEY);
  222. assert(crypto_secretstream_xchacha20poly1305_tag_final() ==
  223. crypto_secretstream_xchacha20poly1305_TAG_FINAL);
  224. printf("OK\n");
  225. return 0;
  226. }