cipher-ccm.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /* cipher-ccm.c - CTR mode with CBC-MAC mode implementation
  2. * Copyright (C) 2013 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. #define set_burn(burn, nburn) do { \
  29. unsigned int __nburn = (nburn); \
  30. (burn) = (burn) > __nburn ? (burn) : __nburn; } while (0)
  31. static unsigned int
  32. do_cbc_mac (gcry_cipher_hd_t c, const unsigned char *inbuf, size_t inlen,
  33. int do_padding)
  34. {
  35. gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
  36. unsigned char tmp[16];
  37. const unsigned int blocksize = DIM(tmp);
  38. unsigned int burn = 0;
  39. unsigned int unused = c->u_mode.ccm.mac_unused;
  40. size_t nblocks;
  41. size_t n;
  42. if (inlen == 0 && (unused == 0 || !do_padding))
  43. return 0;
  44. do
  45. {
  46. if (inlen + unused < blocksize || unused > 0)
  47. {
  48. n = (inlen > blocksize - unused) ? blocksize - unused : inlen;
  49. buf_cpy (&c->u_mode.ccm.macbuf[unused], inbuf, n);
  50. unused += n;
  51. inlen -= n;
  52. inbuf += n;
  53. }
  54. if (!inlen)
  55. {
  56. if (!do_padding)
  57. break;
  58. n = blocksize - unused;
  59. if (n > 0)
  60. {
  61. memset (&c->u_mode.ccm.macbuf[unused], 0, n);
  62. unused = blocksize;
  63. }
  64. }
  65. if (unused > 0)
  66. {
  67. /* Process one block from macbuf. */
  68. cipher_block_xor(c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.macbuf,
  69. blocksize);
  70. set_burn (burn, enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ));
  71. unused = 0;
  72. }
  73. if (c->bulk.cbc_enc)
  74. {
  75. nblocks = inlen / blocksize;
  76. c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, tmp, inbuf, nblocks, 1);
  77. inbuf += nblocks * blocksize;
  78. inlen -= nblocks * blocksize;
  79. wipememory (tmp, sizeof(tmp));
  80. }
  81. else
  82. {
  83. while (inlen >= blocksize)
  84. {
  85. cipher_block_xor(c->u_iv.iv, c->u_iv.iv, inbuf, blocksize);
  86. set_burn (burn, enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ));
  87. inlen -= blocksize;
  88. inbuf += blocksize;
  89. }
  90. }
  91. }
  92. while (inlen > 0);
  93. c->u_mode.ccm.mac_unused = unused;
  94. if (burn)
  95. burn += 4 * sizeof(void *);
  96. return burn;
  97. }
  98. gcry_err_code_t
  99. _gcry_cipher_ccm_set_nonce (gcry_cipher_hd_t c, const unsigned char *nonce,
  100. size_t noncelen)
  101. {
  102. unsigned int marks_key;
  103. size_t L = 15 - noncelen;
  104. size_t L_;
  105. L_ = L - 1;
  106. if (!nonce)
  107. return GPG_ERR_INV_ARG;
  108. /* Length field must be 2, 3, ..., or 8. */
  109. if (L < 2 || L > 8)
  110. return GPG_ERR_INV_LENGTH;
  111. /* Reset state */
  112. marks_key = c->marks.key;
  113. memset (&c->u_mode, 0, sizeof(c->u_mode));
  114. memset (&c->marks, 0, sizeof(c->marks));
  115. memset (&c->u_iv, 0, sizeof(c->u_iv));
  116. memset (&c->u_ctr, 0, sizeof(c->u_ctr));
  117. memset (c->lastiv, 0, sizeof(c->lastiv));
  118. c->unused = 0;
  119. c->marks.key = marks_key;
  120. /* Setup CTR */
  121. c->u_ctr.ctr[0] = L_;
  122. memcpy (&c->u_ctr.ctr[1], nonce, noncelen);
  123. memset (&c->u_ctr.ctr[1 + noncelen], 0, L);
  124. /* Setup IV */
  125. c->u_iv.iv[0] = L_;
  126. memcpy (&c->u_iv.iv[1], nonce, noncelen);
  127. /* Add (8 * M_ + 64 * flags) to iv[0] and set iv[noncelen + 1 ... 15] later
  128. in set_aad. */
  129. memset (&c->u_iv.iv[1 + noncelen], 0, L);
  130. c->u_mode.ccm.nonce = 1;
  131. return GPG_ERR_NO_ERROR;
  132. }
  133. gcry_err_code_t
  134. _gcry_cipher_ccm_set_lengths (gcry_cipher_hd_t c, u64 encryptlen, u64 aadlen,
  135. u64 taglen)
  136. {
  137. unsigned int burn = 0;
  138. unsigned char b0[16];
  139. size_t noncelen = 15 - (c->u_iv.iv[0] + 1);
  140. u64 M = taglen;
  141. u64 M_;
  142. int i;
  143. M_ = (M - 2) / 2;
  144. /* Authentication field must be 4, 6, 8, 10, 12, 14 or 16. */
  145. if ((M_ * 2 + 2) != M || M < 4 || M > 16)
  146. return GPG_ERR_INV_LENGTH;
  147. if (!c->u_mode.ccm.nonce || c->marks.tag)
  148. return GPG_ERR_INV_STATE;
  149. if (c->u_mode.ccm.lengths)
  150. return GPG_ERR_INV_STATE;
  151. c->u_mode.ccm.authlen = taglen;
  152. c->u_mode.ccm.encryptlen = encryptlen;
  153. c->u_mode.ccm.aadlen = aadlen;
  154. /* Complete IV setup. */
  155. c->u_iv.iv[0] += (aadlen > 0) * 64 + M_ * 8;
  156. for (i = 16 - 1; i >= 1 + noncelen; i--)
  157. {
  158. c->u_iv.iv[i] = encryptlen & 0xff;
  159. encryptlen >>= 8;
  160. }
  161. memcpy (b0, c->u_iv.iv, 16);
  162. memset (c->u_iv.iv, 0, 16);
  163. set_burn (burn, do_cbc_mac (c, b0, 16, 0));
  164. if (aadlen == 0)
  165. {
  166. /* Do nothing. */
  167. }
  168. else if (aadlen > 0 && aadlen <= (unsigned int)0xfeff)
  169. {
  170. b0[0] = (aadlen >> 8) & 0xff;
  171. b0[1] = aadlen & 0xff;
  172. set_burn (burn, do_cbc_mac (c, b0, 2, 0));
  173. }
  174. else if (aadlen > 0xfeff && aadlen <= (unsigned int)0xffffffff)
  175. {
  176. b0[0] = 0xff;
  177. b0[1] = 0xfe;
  178. buf_put_be32(&b0[2], aadlen);
  179. set_burn (burn, do_cbc_mac (c, b0, 6, 0));
  180. }
  181. else if (aadlen > (unsigned int)0xffffffff)
  182. {
  183. b0[0] = 0xff;
  184. b0[1] = 0xff;
  185. buf_put_be64(&b0[2], aadlen);
  186. set_burn (burn, do_cbc_mac (c, b0, 10, 0));
  187. }
  188. /* Generate S_0 and increase counter. */
  189. set_burn (burn, c->spec->encrypt ( &c->context.c, c->u_mode.ccm.s0,
  190. c->u_ctr.ctr ));
  191. c->u_ctr.ctr[15]++;
  192. if (burn)
  193. _gcry_burn_stack (burn + sizeof(void *) * 5);
  194. c->u_mode.ccm.lengths = 1;
  195. return GPG_ERR_NO_ERROR;
  196. }
  197. gcry_err_code_t
  198. _gcry_cipher_ccm_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf,
  199. size_t abuflen)
  200. {
  201. unsigned int burn;
  202. if (abuflen > 0 && !abuf)
  203. return GPG_ERR_INV_ARG;
  204. if (!c->u_mode.ccm.nonce || !c->u_mode.ccm.lengths || c->marks.tag)
  205. return GPG_ERR_INV_STATE;
  206. if (abuflen > c->u_mode.ccm.aadlen)
  207. return GPG_ERR_INV_LENGTH;
  208. c->u_mode.ccm.aadlen -= abuflen;
  209. burn = do_cbc_mac (c, abuf, abuflen, c->u_mode.ccm.aadlen == 0);
  210. if (burn)
  211. _gcry_burn_stack (burn + sizeof(void *) * 5);
  212. return GPG_ERR_NO_ERROR;
  213. }
  214. static gcry_err_code_t
  215. _gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf,
  216. size_t outbuflen, int check)
  217. {
  218. unsigned int burn;
  219. if (!outbuf || outbuflen == 0)
  220. return GPG_ERR_INV_ARG;
  221. /* Tag length must be same as initial authlen. */
  222. if (c->u_mode.ccm.authlen != outbuflen)
  223. return GPG_ERR_INV_LENGTH;
  224. if (!c->u_mode.ccm.nonce || !c->u_mode.ccm.lengths || c->u_mode.ccm.aadlen > 0)
  225. return GPG_ERR_INV_STATE;
  226. /* Initial encrypt length must match with length of actual data processed. */
  227. if (c->u_mode.ccm.encryptlen > 0)
  228. return GPG_ERR_UNFINISHED;
  229. if (!c->marks.tag)
  230. {
  231. burn = do_cbc_mac (c, NULL, 0, 1); /* Perform final padding. */
  232. /* Add S_0 */
  233. cipher_block_xor (c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.s0, 16);
  234. wipememory (c->u_ctr.ctr, 16);
  235. wipememory (c->u_mode.ccm.s0, 16);
  236. wipememory (c->u_mode.ccm.macbuf, 16);
  237. if (burn)
  238. _gcry_burn_stack (burn + sizeof(void *) * 5);
  239. c->marks.tag = 1;
  240. }
  241. if (!check)
  242. {
  243. memcpy (outbuf, c->u_iv.iv, outbuflen);
  244. return GPG_ERR_NO_ERROR;
  245. }
  246. else
  247. {
  248. return buf_eq_const(outbuf, c->u_iv.iv, outbuflen) ?
  249. GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM;
  250. }
  251. }
  252. gcry_err_code_t
  253. _gcry_cipher_ccm_get_tag (gcry_cipher_hd_t c, unsigned char *outtag,
  254. size_t taglen)
  255. {
  256. return _gcry_cipher_ccm_tag (c, outtag, taglen, 0);
  257. }
  258. gcry_err_code_t
  259. _gcry_cipher_ccm_check_tag (gcry_cipher_hd_t c, const unsigned char *intag,
  260. size_t taglen)
  261. {
  262. return _gcry_cipher_ccm_tag (c, (unsigned char *)intag, taglen, 1);
  263. }
  264. gcry_err_code_t
  265. _gcry_cipher_ccm_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
  266. size_t outbuflen, const unsigned char *inbuf,
  267. size_t inbuflen)
  268. {
  269. gcry_err_code_t err = 0;
  270. unsigned int burn = 0;
  271. unsigned int nburn;
  272. if (outbuflen < inbuflen)
  273. return GPG_ERR_BUFFER_TOO_SHORT;
  274. if (!c->u_mode.ccm.nonce || c->marks.tag || !c->u_mode.ccm.lengths ||
  275. c->u_mode.ccm.aadlen > 0)
  276. return GPG_ERR_INV_STATE;
  277. if (inbuflen > c->u_mode.ccm.encryptlen)
  278. return GPG_ERR_INV_LENGTH;
  279. while (inbuflen)
  280. {
  281. size_t currlen = inbuflen;
  282. /* Since checksumming is done before encryption, process input in 24KiB
  283. * chunks to keep data loaded in L1 cache for encryption. However only
  284. * do splitting if input is large enough so that last chunks does not
  285. * end up being short. */
  286. if (currlen > 32 * 1024)
  287. currlen = 24 * 1024;
  288. c->u_mode.ccm.encryptlen -= currlen;
  289. nburn = do_cbc_mac (c, inbuf, currlen, 0);
  290. burn = nburn > burn ? nburn : burn;
  291. err = _gcry_cipher_ctr_encrypt (c, outbuf, outbuflen, inbuf, currlen);
  292. if (err)
  293. break;
  294. outbuf += currlen;
  295. inbuf += currlen;
  296. outbuflen -= currlen;
  297. inbuflen -= currlen;
  298. }
  299. if (burn)
  300. _gcry_burn_stack (burn + sizeof(void *) * 5);
  301. return err;
  302. }
  303. gcry_err_code_t
  304. _gcry_cipher_ccm_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
  305. size_t outbuflen, const unsigned char *inbuf,
  306. size_t inbuflen)
  307. {
  308. gcry_err_code_t err = 0;
  309. unsigned int burn = 0;
  310. unsigned int nburn;
  311. if (outbuflen < inbuflen)
  312. return GPG_ERR_BUFFER_TOO_SHORT;
  313. if (!c->u_mode.ccm.nonce || c->marks.tag || !c->u_mode.ccm.lengths ||
  314. c->u_mode.ccm.aadlen > 0)
  315. return GPG_ERR_INV_STATE;
  316. if (inbuflen > c->u_mode.ccm.encryptlen)
  317. return GPG_ERR_INV_LENGTH;
  318. while (inbuflen)
  319. {
  320. size_t currlen = inbuflen;
  321. /* Since checksumming is done after decryption, process input in 24KiB
  322. * chunks to keep data loaded in L1 cache for checksumming. However
  323. * only do splitting if input is large enough so that last chunks
  324. * does not end up being short. */
  325. if (currlen > 32 * 1024)
  326. currlen = 24 * 1024;
  327. err = _gcry_cipher_ctr_encrypt (c, outbuf, outbuflen, inbuf, currlen);
  328. if (err)
  329. break;
  330. c->u_mode.ccm.encryptlen -= currlen;
  331. nburn = do_cbc_mac (c, outbuf, currlen, 0);
  332. burn = nburn > burn ? nburn : burn;
  333. outbuf += currlen;
  334. inbuf += currlen;
  335. outbuflen -= currlen;
  336. inbuflen -= currlen;
  337. }
  338. if (burn)
  339. _gcry_burn_stack (burn + sizeof(void *) * 5);
  340. return err;
  341. }