cipher-siv.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /* cipher-siv.c - SIV implementation (RFC 5297)
  2. * Copyright (C) 2021 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  3. *
  4. * This file is part of Libgcrypt.
  5. *
  6. * Libgcrypt is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as
  8. * published by the Free Software Foundation; either version 2.1 of
  9. * the License, or (at your option) any later version.
  10. *
  11. * Libgcrypt is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <config.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <errno.h>
  24. #include "g10lib.h"
  25. #include "cipher.h"
  26. #include "bufhelp.h"
  27. #include "./cipher-internal.h"
  28. static inline void
  29. s2v_double (unsigned char *d)
  30. {
  31. u64 hi, lo, mask;
  32. hi = buf_get_be64(d + 0);
  33. lo = buf_get_be64(d + 8);
  34. mask = -(hi >> 63);
  35. hi = (hi << 1) ^ (lo >> 63);
  36. lo = (lo << 1) ^ (mask & 0x87);
  37. buf_put_be64(d + 0, hi);
  38. buf_put_be64(d + 8, lo);
  39. }
  40. static void
  41. s2v_pad (unsigned char *out, const byte *in, size_t inlen)
  42. {
  43. static const unsigned char padding[GCRY_SIV_BLOCK_LEN] = { 0x80 };
  44. gcry_assert(inlen < GCRY_SIV_BLOCK_LEN);
  45. buf_cpy (out, in, inlen);
  46. buf_cpy (out + inlen, padding, GCRY_SIV_BLOCK_LEN - inlen);
  47. }
  48. gcry_err_code_t
  49. _gcry_cipher_siv_setkey (gcry_cipher_hd_t c,
  50. const unsigned char *ctrkey, size_t ctrkeylen)
  51. {
  52. static const unsigned char zero[GCRY_SIV_BLOCK_LEN] = { 0 };
  53. gcry_err_code_t err;
  54. if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
  55. return GPG_ERR_CIPHER_ALGO;
  56. c->u_mode.siv.aad_count = 0;
  57. c->u_mode.siv.dec_tag_set = 0;
  58. c->marks.tag = 0;
  59. c->marks.iv = 0;
  60. /* Set CTR mode key. */
  61. err = c->spec->setkey (c->u_mode.siv.ctr_context, ctrkey, ctrkeylen,
  62. &c->bulk);
  63. if (err != 0)
  64. return err;
  65. /* Initialize S2V. */
  66. memset (&c->u_mode.siv.s2v_cmac, 0, sizeof(c->u_mode.siv.s2v_cmac));
  67. err = _gcry_cmac_generate_subkeys (c, &c->u_mode.siv.s2v_cmac);
  68. if (err != 0)
  69. return err;
  70. err = _gcry_cmac_write (c, &c->u_mode.siv.s2v_cmac, zero, GCRY_SIV_BLOCK_LEN);
  71. if (err != 0)
  72. return err;
  73. err = _gcry_cmac_final (c, &c->u_mode.siv.s2v_cmac);
  74. if (err != 0)
  75. return err;
  76. memcpy (c->u_mode.siv.s2v_zero_block, c->u_mode.siv.s2v_cmac.u_iv.iv,
  77. GCRY_SIV_BLOCK_LEN);
  78. memcpy (c->u_mode.siv.s2v_d, c->u_mode.siv.s2v_zero_block,
  79. GCRY_SIV_BLOCK_LEN);
  80. return 0;
  81. }
  82. gcry_err_code_t
  83. _gcry_cipher_siv_authenticate (gcry_cipher_hd_t c,
  84. const byte *aadbuf, size_t aadbuflen)
  85. {
  86. gcry_err_code_t err;
  87. if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
  88. return GPG_ERR_CIPHER_ALGO;
  89. if (c->marks.tag)
  90. return GPG_ERR_INV_STATE;
  91. if (c->marks.iv)
  92. return GPG_ERR_INV_STATE;
  93. if (c->u_mode.siv.aad_count >= 126)
  94. return GPG_ERR_INV_STATE; /* Too many AD vector components. */
  95. c->u_mode.siv.aad_count++;
  96. _gcry_cmac_reset (&c->u_mode.siv.s2v_cmac);
  97. err = _gcry_cmac_write (c, &c->u_mode.siv.s2v_cmac, aadbuf, aadbuflen);
  98. if (err != 0)
  99. return err;
  100. err = _gcry_cmac_final (c, &c->u_mode.siv.s2v_cmac);
  101. if (err != 0)
  102. return err;
  103. s2v_double (c->u_mode.siv.s2v_d);
  104. cipher_block_xor_1 (c->u_mode.siv.s2v_d, c->u_mode.siv.s2v_cmac.u_iv.iv,
  105. GCRY_SIV_BLOCK_LEN);
  106. return 0;
  107. }
  108. gcry_err_code_t
  109. _gcry_cipher_siv_set_nonce (gcry_cipher_hd_t c, const byte *nonce,
  110. size_t noncelen)
  111. {
  112. gcry_err_code_t err;
  113. err = _gcry_cipher_siv_authenticate (c, nonce, noncelen);
  114. if (err)
  115. return err;
  116. /* Nonce is the last AD before plaintext. */
  117. c->marks.iv = 1;
  118. return 0;
  119. }
  120. static gcry_err_code_t
  121. s2v_plaintext (gcry_cipher_hd_t c, const byte *plain, size_t plainlen)
  122. {
  123. gcry_err_code_t err;
  124. if (c->u_mode.siv.aad_count >= 127)
  125. return GPG_ERR_INV_STATE; /* Too many AD vector components. */
  126. _gcry_cmac_reset (&c->u_mode.siv.s2v_cmac);
  127. if (plainlen >= GCRY_SIV_BLOCK_LEN)
  128. {
  129. err = _gcry_cmac_write (c, &c->u_mode.siv.s2v_cmac, plain,
  130. plainlen - GCRY_SIV_BLOCK_LEN);
  131. if (err)
  132. return err;
  133. cipher_block_xor_1 (c->u_mode.siv.s2v_d,
  134. plain + plainlen - GCRY_SIV_BLOCK_LEN,
  135. GCRY_SIV_BLOCK_LEN);
  136. err = _gcry_cmac_write (c, &c->u_mode.siv.s2v_cmac, c->u_mode.siv.s2v_d,
  137. GCRY_SIV_BLOCK_LEN);
  138. if (err)
  139. return err;
  140. }
  141. else
  142. {
  143. unsigned char pad_sn[GCRY_SIV_BLOCK_LEN];
  144. s2v_double (c->u_mode.siv.s2v_d);
  145. s2v_pad (pad_sn, plain, plainlen);
  146. cipher_block_xor_1 (pad_sn, c->u_mode.siv.s2v_d, GCRY_SIV_BLOCK_LEN);
  147. err = _gcry_cmac_write (c, &c->u_mode.siv.s2v_cmac, pad_sn,
  148. GCRY_SIV_BLOCK_LEN);
  149. wipememory (pad_sn, sizeof(pad_sn));
  150. if (err)
  151. return err;
  152. }
  153. c->u_mode.siv.aad_count++;
  154. return _gcry_cmac_final (c, &c->u_mode.siv.s2v_cmac);
  155. }
  156. gcry_err_code_t
  157. _gcry_cipher_siv_encrypt (gcry_cipher_hd_t c,
  158. byte *outbuf, size_t outbuflen,
  159. const byte *inbuf, size_t inbuflen)
  160. {
  161. gcry_err_code_t err;
  162. u64 q_lo;
  163. if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
  164. return GPG_ERR_CIPHER_ALGO;
  165. if (outbuflen < inbuflen)
  166. return GPG_ERR_BUFFER_TOO_SHORT;
  167. if (c->marks.tag)
  168. return GPG_ERR_INV_STATE;
  169. if (c->u_mode.siv.dec_tag_set)
  170. return GPG_ERR_INV_STATE;
  171. /* Pass plaintext to S2V. */
  172. err = s2v_plaintext (c, inbuf, inbuflen);
  173. if (err != 0)
  174. return err;
  175. /* Clear 31th and 63th bits. */
  176. memcpy (c->u_ctr.ctr, c->u_mode.siv.s2v_cmac.u_iv.iv, GCRY_SIV_BLOCK_LEN);
  177. q_lo = buf_get_be64(c->u_ctr.ctr + 8);
  178. q_lo &= ~((u64)1 << 31);
  179. q_lo &= ~((u64)1 << 63);
  180. buf_put_be64(c->u_ctr.ctr + 8, q_lo);
  181. /* Encrypt plaintext. */
  182. err = _gcry_cipher_ctr_encrypt_ctx(c, outbuf, outbuflen, inbuf, inbuflen,
  183. c->u_mode.siv.ctr_context);
  184. if (err != 0)
  185. return err;
  186. c->marks.tag = 1;
  187. return 0;
  188. }
  189. gcry_err_code_t
  190. _gcry_cipher_siv_set_decryption_tag (gcry_cipher_hd_t c,
  191. const byte *tag, size_t taglen)
  192. {
  193. if (taglen != GCRY_SIV_BLOCK_LEN)
  194. return GPG_ERR_INV_ARG;
  195. if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
  196. return GPG_ERR_CIPHER_ALGO;
  197. if (c->marks.tag)
  198. return GPG_ERR_INV_STATE;
  199. memcpy (&c->u_mode.siv.dec_tag, tag, GCRY_SIV_BLOCK_LEN);
  200. c->u_mode.siv.dec_tag_set = 1;
  201. return 0;
  202. }
  203. gcry_err_code_t
  204. _gcry_cipher_siv_decrypt (gcry_cipher_hd_t c,
  205. byte *outbuf, size_t outbuflen,
  206. const byte *inbuf, size_t inbuflen)
  207. {
  208. gcry_err_code_t err;
  209. u64 q_lo;
  210. if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
  211. return GPG_ERR_CIPHER_ALGO;
  212. if (outbuflen < inbuflen)
  213. return GPG_ERR_BUFFER_TOO_SHORT;
  214. if (c->marks.tag)
  215. return GPG_ERR_INV_STATE;
  216. if (!c->u_mode.siv.dec_tag_set)
  217. return GPG_ERR_INV_STATE;
  218. /* Clear 31th and 63th bits. */
  219. memcpy (c->u_ctr.ctr, c->u_mode.siv.dec_tag, GCRY_SIV_BLOCK_LEN);
  220. q_lo = buf_get_be64(c->u_ctr.ctr + 8);
  221. q_lo &= ~((u64)1 << 31);
  222. q_lo &= ~((u64)1 << 63);
  223. buf_put_be64(c->u_ctr.ctr + 8, q_lo);
  224. /* Decrypt ciphertext. */
  225. err = _gcry_cipher_ctr_encrypt_ctx(c, outbuf, outbuflen, inbuf, inbuflen,
  226. c->u_mode.siv.ctr_context);
  227. if (err != 0)
  228. return err;
  229. /* Pass plaintext to S2V. */
  230. err = s2v_plaintext (c, outbuf, inbuflen);
  231. if (err != 0)
  232. return err;
  233. c->marks.tag = 1;
  234. if (!buf_eq_const(c->u_mode.siv.s2v_cmac.u_iv.iv, c->u_mode.siv.dec_tag,
  235. GCRY_SIV_BLOCK_LEN))
  236. {
  237. wipememory (outbuf, inbuflen);
  238. return GPG_ERR_CHECKSUM;
  239. }
  240. return 0;
  241. }
  242. gcry_err_code_t
  243. _gcry_cipher_siv_get_tag (gcry_cipher_hd_t c, unsigned char *outbuf,
  244. size_t outbuflen)
  245. {
  246. gcry_err_code_t err;
  247. if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
  248. return GPG_ERR_CIPHER_ALGO;
  249. if (c->u_mode.siv.dec_tag_set)
  250. return GPG_ERR_INV_STATE;
  251. if (!c->marks.tag)
  252. {
  253. /* Finalize SIV with zero-length plaintext. */
  254. err = s2v_plaintext (c, NULL, 0);
  255. if (err != 0)
  256. return err;
  257. c->marks.tag = 1;
  258. }
  259. if (outbuflen > GCRY_SIV_BLOCK_LEN)
  260. outbuflen = GCRY_SIV_BLOCK_LEN;
  261. /* We already checked that OUTBUF is large enough to hold
  262. * the result or has valid truncated length. */
  263. memcpy (outbuf, c->u_mode.siv.s2v_cmac.u_iv.iv, outbuflen);
  264. return 0;
  265. }
  266. gcry_err_code_t
  267. _gcry_cipher_siv_check_tag (gcry_cipher_hd_t c, const unsigned char *intag,
  268. size_t taglen)
  269. {
  270. gcry_err_code_t err;
  271. size_t n;
  272. if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
  273. return GPG_ERR_CIPHER_ALGO;
  274. if (!c->marks.tag)
  275. {
  276. /* Finalize SIV with zero-length plaintext. */
  277. err = s2v_plaintext (c, NULL, 0);
  278. if (err != 0)
  279. return err;
  280. c->marks.tag = 1;
  281. }
  282. n = GCRY_SIV_BLOCK_LEN;
  283. if (taglen < n)
  284. n = taglen;
  285. if (!buf_eq_const(c->u_mode.siv.s2v_cmac.u_iv.iv, intag, n)
  286. || GCRY_SIV_BLOCK_LEN != taglen)
  287. {
  288. return GPG_ERR_CHECKSUM;
  289. }
  290. return 0;
  291. }