cipher-cbc.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /* cipher-cbc.c - Generic CBC mode implementation
  2. * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
  3. * 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
  4. *
  5. * This file is part of Libgcrypt.
  6. *
  7. * Libgcrypt is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * Libgcrypt is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <config.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <errno.h>
  25. #include "g10lib.h"
  26. #include "cipher.h"
  27. #include "./cipher-internal.h"
  28. #include "bufhelp.h"
  29. static inline unsigned int
  30. cbc_encrypt_inner(gcry_cipher_hd_t c, unsigned char *outbuf,
  31. const unsigned char *inbuf, size_t nblocks, size_t blocksize,
  32. int is_cbc_cmac)
  33. {
  34. unsigned int burn, nburn;
  35. size_t n;
  36. burn = 0;
  37. if (c->bulk.cbc_enc)
  38. {
  39. c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks,
  40. is_cbc_cmac);
  41. }
  42. else
  43. {
  44. gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
  45. unsigned char *ivp;
  46. ivp = c->u_iv.iv;
  47. for (n=0; n < nblocks; n++ )
  48. {
  49. cipher_block_xor (outbuf, inbuf, ivp, blocksize);
  50. nburn = enc_fn ( &c->context.c, outbuf, outbuf );
  51. burn = nburn > burn ? nburn : burn;
  52. ivp = outbuf;
  53. inbuf += blocksize;
  54. if (!is_cbc_cmac)
  55. outbuf += blocksize;
  56. }
  57. if (ivp != c->u_iv.iv)
  58. cipher_block_cpy (c->u_iv.iv, ivp, blocksize);
  59. }
  60. return burn;
  61. }
  62. gcry_err_code_t
  63. _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c,
  64. unsigned char *outbuf, size_t outbuflen,
  65. const unsigned char *inbuf, size_t inbuflen)
  66. {
  67. size_t blocksize_shift = _gcry_blocksize_shift(c);
  68. size_t blocksize = 1 << blocksize_shift;
  69. size_t blocksize_mask = blocksize - 1;
  70. size_t nblocks = inbuflen >> blocksize_shift;
  71. int is_cbc_cmac = !!(c->flags & GCRY_CIPHER_CBC_MAC);
  72. unsigned int burn;
  73. if (outbuflen < (is_cbc_cmac ? blocksize : inbuflen))
  74. return GPG_ERR_BUFFER_TOO_SHORT;
  75. if (inbuflen & blocksize_mask)
  76. return GPG_ERR_INV_LENGTH;
  77. burn = cbc_encrypt_inner(c, outbuf, inbuf, nblocks, blocksize, is_cbc_cmac);
  78. if (burn > 0)
  79. _gcry_burn_stack (burn + 4 * sizeof(void *));
  80. return 0;
  81. }
  82. gcry_err_code_t
  83. _gcry_cipher_cbc_cts_encrypt (gcry_cipher_hd_t c,
  84. unsigned char *outbuf, size_t outbuflen,
  85. const unsigned char *inbuf, size_t inbuflen)
  86. {
  87. size_t blocksize_shift = _gcry_blocksize_shift(c);
  88. size_t blocksize = 1 << blocksize_shift;
  89. size_t blocksize_mask = blocksize - 1;
  90. gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
  91. size_t nblocks = inbuflen >> blocksize_shift;
  92. unsigned int burn, nburn;
  93. unsigned char *ivp;
  94. int i;
  95. if (outbuflen < inbuflen)
  96. return GPG_ERR_BUFFER_TOO_SHORT;
  97. if ((inbuflen & blocksize_mask) && !(inbuflen > blocksize))
  98. return GPG_ERR_INV_LENGTH;
  99. burn = 0;
  100. if (inbuflen > blocksize)
  101. {
  102. if ((inbuflen & blocksize_mask) == 0)
  103. nblocks--;
  104. }
  105. burn = cbc_encrypt_inner(c, outbuf, inbuf, nblocks, blocksize, 0);
  106. inbuf += nblocks << blocksize_shift;
  107. outbuf += nblocks << blocksize_shift;
  108. if (inbuflen > blocksize)
  109. {
  110. /* We have to be careful here, since outbuf might be equal to
  111. inbuf. */
  112. size_t restbytes;
  113. unsigned char b;
  114. if ((inbuflen & blocksize_mask) == 0)
  115. restbytes = blocksize;
  116. else
  117. restbytes = inbuflen & blocksize_mask;
  118. outbuf -= blocksize;
  119. for (ivp = c->u_iv.iv, i = 0; i < restbytes; i++)
  120. {
  121. b = inbuf[i];
  122. outbuf[blocksize + i] = outbuf[i];
  123. outbuf[i] = b ^ *ivp++;
  124. }
  125. for (; i < blocksize; i++)
  126. outbuf[i] = 0 ^ *ivp++;
  127. nburn = enc_fn (&c->context.c, outbuf, outbuf);
  128. burn = nburn > burn ? nburn : burn;
  129. cipher_block_cpy (c->u_iv.iv, outbuf, blocksize);
  130. }
  131. if (burn > 0)
  132. _gcry_burn_stack (burn + 4 * sizeof(void *));
  133. return 0;
  134. }
  135. static inline unsigned int
  136. cbc_decrypt_inner(gcry_cipher_hd_t c, unsigned char *outbuf,
  137. const unsigned char *inbuf, size_t nblocks, size_t blocksize)
  138. {
  139. unsigned int burn, nburn;
  140. size_t n;
  141. burn = 0;
  142. if (c->bulk.cbc_dec)
  143. {
  144. c->bulk.cbc_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
  145. }
  146. else
  147. {
  148. gcry_cipher_decrypt_t dec_fn = c->spec->decrypt;
  149. for (n = 0; n < nblocks; n++)
  150. {
  151. /* Because outbuf and inbuf might be the same, we must not overwrite
  152. the original ciphertext block. We use LASTIV as intermediate
  153. storage here because it is not used otherwise. */
  154. nburn = dec_fn ( &c->context.c, c->lastiv, inbuf );
  155. burn = nburn > burn ? nburn : burn;
  156. cipher_block_xor_n_copy_2 (outbuf, c->lastiv, c->u_iv.iv, inbuf,
  157. blocksize);
  158. inbuf += blocksize;
  159. outbuf += blocksize;
  160. }
  161. }
  162. return burn;
  163. }
  164. gcry_err_code_t
  165. _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c,
  166. unsigned char *outbuf, size_t outbuflen,
  167. const unsigned char *inbuf, size_t inbuflen)
  168. {
  169. size_t blocksize_shift = _gcry_blocksize_shift(c);
  170. size_t blocksize = 1 << blocksize_shift;
  171. size_t blocksize_mask = blocksize - 1;
  172. size_t nblocks = inbuflen >> blocksize_shift;
  173. unsigned int burn;
  174. if (outbuflen < inbuflen)
  175. return GPG_ERR_BUFFER_TOO_SHORT;
  176. if (inbuflen & blocksize_mask)
  177. return GPG_ERR_INV_LENGTH;
  178. burn = cbc_decrypt_inner(c, outbuf, inbuf, nblocks, blocksize);
  179. if (burn > 0)
  180. _gcry_burn_stack (burn + 4 * sizeof(void *));
  181. return 0;
  182. }
  183. gcry_err_code_t
  184. _gcry_cipher_cbc_cts_decrypt (gcry_cipher_hd_t c,
  185. unsigned char *outbuf, size_t outbuflen,
  186. const unsigned char *inbuf, size_t inbuflen)
  187. {
  188. size_t blocksize_shift = _gcry_blocksize_shift(c);
  189. size_t blocksize = 1 << blocksize_shift;
  190. size_t blocksize_mask = blocksize - 1;
  191. gcry_cipher_decrypt_t dec_fn = c->spec->decrypt;
  192. size_t nblocks = inbuflen >> blocksize_shift;
  193. unsigned int burn, nburn;
  194. int i;
  195. if (outbuflen < inbuflen)
  196. return GPG_ERR_BUFFER_TOO_SHORT;
  197. if ((inbuflen & blocksize_mask) && !(inbuflen > blocksize))
  198. return GPG_ERR_INV_LENGTH;
  199. burn = 0;
  200. if (inbuflen > blocksize)
  201. {
  202. nblocks--;
  203. if ((inbuflen & blocksize_mask) == 0)
  204. nblocks--;
  205. cipher_block_cpy (c->lastiv, c->u_iv.iv, blocksize);
  206. }
  207. burn = cbc_decrypt_inner(c, outbuf, inbuf, nblocks, blocksize);
  208. inbuf += nblocks << blocksize_shift;
  209. outbuf += nblocks << blocksize_shift;
  210. if (inbuflen > blocksize)
  211. {
  212. size_t restbytes;
  213. if ((inbuflen & blocksize_mask) == 0)
  214. restbytes = blocksize;
  215. else
  216. restbytes = inbuflen & blocksize_mask;
  217. cipher_block_cpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */
  218. buf_cpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */
  219. nburn = dec_fn ( &c->context.c, outbuf, inbuf );
  220. burn = nburn > burn ? nburn : burn;
  221. buf_xor(outbuf, outbuf, c->u_iv.iv, restbytes);
  222. buf_cpy (outbuf + blocksize, outbuf, restbytes);
  223. for(i=restbytes; i < blocksize; i++)
  224. c->u_iv.iv[i] = outbuf[i];
  225. nburn = dec_fn (&c->context.c, outbuf, c->u_iv.iv);
  226. burn = nburn > burn ? nburn : burn;
  227. cipher_block_xor(outbuf, outbuf, c->lastiv, blocksize);
  228. /* c->lastiv is now really lastlastiv, does this matter? */
  229. }
  230. if (burn > 0)
  231. _gcry_burn_stack (burn + 4 * sizeof(void *));
  232. return 0;
  233. }