cts128.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <string.h>
  10. #include <openssl/crypto.h>
  11. #include "crypto/modes.h"
  12. /*
  13. * Trouble with Ciphertext Stealing, CTS, mode is that there is no
  14. * common official specification, but couple of cipher/application
  15. * specific ones: RFC2040 and RFC3962. Then there is 'Proposal to
  16. * Extend CBC Mode By "Ciphertext Stealing"' at NIST site, which
  17. * deviates from mentioned RFCs. Most notably it allows input to be
  18. * of block length and it doesn't flip the order of the last two
  19. * blocks. CTS is being discussed even in ECB context, but it's not
  20. * adopted for any known application. This implementation provides
  21. * two interfaces: one compliant with above mentioned RFCs and one
  22. * compliant with the NIST proposal, both extending CBC mode.
  23. */
  24. size_t CRYPTO_cts128_encrypt_block(const unsigned char *in,
  25. unsigned char *out, size_t len,
  26. const void *key, unsigned char ivec[16],
  27. block128_f block)
  28. {
  29. size_t residue, n;
  30. if (len <= 16)
  31. return 0;
  32. if ((residue = len % 16) == 0)
  33. residue = 16;
  34. len -= residue;
  35. CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block);
  36. in += len;
  37. out += len;
  38. for (n = 0; n < residue; ++n)
  39. ivec[n] ^= in[n];
  40. (*block) (ivec, ivec, key);
  41. memcpy(out, out - 16, residue);
  42. memcpy(out - 16, ivec, 16);
  43. return len + residue;
  44. }
  45. size_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in,
  46. unsigned char *out, size_t len,
  47. const void *key,
  48. unsigned char ivec[16],
  49. block128_f block)
  50. {
  51. size_t residue, n;
  52. if (len < 16)
  53. return 0;
  54. residue = len % 16;
  55. len -= residue;
  56. CRYPTO_cbc128_encrypt(in, out, len, key, ivec, block);
  57. if (residue == 0)
  58. return len;
  59. in += len;
  60. out += len;
  61. for (n = 0; n < residue; ++n)
  62. ivec[n] ^= in[n];
  63. (*block) (ivec, ivec, key);
  64. memcpy(out - 16 + residue, ivec, 16);
  65. return len + residue;
  66. }
  67. size_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out,
  68. size_t len, const void *key,
  69. unsigned char ivec[16], cbc128_f cbc)
  70. {
  71. size_t residue;
  72. union {
  73. size_t align;
  74. unsigned char c[16];
  75. } tmp;
  76. if (len <= 16)
  77. return 0;
  78. if ((residue = len % 16) == 0)
  79. residue = 16;
  80. len -= residue;
  81. (*cbc) (in, out, len, key, ivec, 1);
  82. in += len;
  83. out += len;
  84. #if defined(CBC_HANDLES_TRUNCATED_IO)
  85. memcpy(tmp.c, out - 16, 16);
  86. (*cbc) (in, out - 16, residue, key, ivec, 1);
  87. memcpy(out, tmp.c, residue);
  88. #else
  89. memset(tmp.c, 0, sizeof(tmp));
  90. memcpy(tmp.c, in, residue);
  91. memcpy(out, out - 16, residue);
  92. (*cbc) (tmp.c, out - 16, 16, key, ivec, 1);
  93. #endif
  94. return len + residue;
  95. }
  96. size_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out,
  97. size_t len, const void *key,
  98. unsigned char ivec[16], cbc128_f cbc)
  99. {
  100. size_t residue;
  101. union {
  102. size_t align;
  103. unsigned char c[16];
  104. } tmp;
  105. if (len < 16)
  106. return 0;
  107. residue = len % 16;
  108. len -= residue;
  109. (*cbc) (in, out, len, key, ivec, 1);
  110. if (residue == 0)
  111. return len;
  112. in += len;
  113. out += len;
  114. #if defined(CBC_HANDLES_TRUNCATED_IO)
  115. (*cbc) (in, out - 16 + residue, residue, key, ivec, 1);
  116. #else
  117. memset(tmp.c, 0, sizeof(tmp));
  118. memcpy(tmp.c, in, residue);
  119. (*cbc) (tmp.c, out - 16 + residue, 16, key, ivec, 1);
  120. #endif
  121. return len + residue;
  122. }
  123. size_t CRYPTO_cts128_decrypt_block(const unsigned char *in,
  124. unsigned char *out, size_t len,
  125. const void *key, unsigned char ivec[16],
  126. block128_f block)
  127. {
  128. size_t residue, n;
  129. union {
  130. size_t align;
  131. unsigned char c[32];
  132. } tmp;
  133. if (len <= 16)
  134. return 0;
  135. if ((residue = len % 16) == 0)
  136. residue = 16;
  137. len -= 16 + residue;
  138. if (len) {
  139. CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
  140. in += len;
  141. out += len;
  142. }
  143. (*block) (in, tmp.c + 16, key);
  144. memcpy(tmp.c, tmp.c + 16, 16);
  145. memcpy(tmp.c, in + 16, residue);
  146. (*block) (tmp.c, tmp.c, key);
  147. for (n = 0; n < 16; ++n) {
  148. unsigned char c = in[n];
  149. out[n] = tmp.c[n] ^ ivec[n];
  150. ivec[n] = c;
  151. }
  152. for (residue += 16; n < residue; ++n)
  153. out[n] = tmp.c[n] ^ in[n];
  154. return 16 + len + residue;
  155. }
  156. size_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in,
  157. unsigned char *out, size_t len,
  158. const void *key,
  159. unsigned char ivec[16],
  160. block128_f block)
  161. {
  162. size_t residue, n;
  163. union {
  164. size_t align;
  165. unsigned char c[32];
  166. } tmp;
  167. if (len < 16)
  168. return 0;
  169. residue = len % 16;
  170. if (residue == 0) {
  171. CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
  172. return len;
  173. }
  174. len -= 16 + residue;
  175. if (len) {
  176. CRYPTO_cbc128_decrypt(in, out, len, key, ivec, block);
  177. in += len;
  178. out += len;
  179. }
  180. (*block) (in + residue, tmp.c + 16, key);
  181. memcpy(tmp.c, tmp.c + 16, 16);
  182. memcpy(tmp.c, in, residue);
  183. (*block) (tmp.c, tmp.c, key);
  184. for (n = 0; n < 16; ++n) {
  185. unsigned char c = in[n];
  186. out[n] = tmp.c[n] ^ ivec[n];
  187. ivec[n] = in[n + residue];
  188. tmp.c[n] = c;
  189. }
  190. for (residue += 16; n < residue; ++n)
  191. out[n] = tmp.c[n] ^ tmp.c[n - 16];
  192. return 16 + len + residue;
  193. }
  194. size_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out,
  195. size_t len, const void *key,
  196. unsigned char ivec[16], cbc128_f cbc)
  197. {
  198. size_t residue;
  199. union {
  200. size_t align;
  201. unsigned char c[32];
  202. } tmp;
  203. if (len <= 16)
  204. return 0;
  205. if ((residue = len % 16) == 0)
  206. residue = 16;
  207. len -= 16 + residue;
  208. if (len) {
  209. (*cbc) (in, out, len, key, ivec, 0);
  210. in += len;
  211. out += len;
  212. }
  213. memset(tmp.c, 0, sizeof(tmp));
  214. /*
  215. * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0]
  216. */
  217. (*cbc) (in, tmp.c, 16, key, tmp.c + 16, 0);
  218. memcpy(tmp.c, in + 16, residue);
  219. #if defined(CBC_HANDLES_TRUNCATED_IO)
  220. (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0);
  221. #else
  222. (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0);
  223. memcpy(out, tmp.c, 16 + residue);
  224. #endif
  225. return 16 + len + residue;
  226. }
  227. size_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out,
  228. size_t len, const void *key,
  229. unsigned char ivec[16], cbc128_f cbc)
  230. {
  231. size_t residue;
  232. union {
  233. size_t align;
  234. unsigned char c[32];
  235. } tmp;
  236. if (len < 16)
  237. return 0;
  238. residue = len % 16;
  239. if (residue == 0) {
  240. (*cbc) (in, out, len, key, ivec, 0);
  241. return len;
  242. }
  243. len -= 16 + residue;
  244. if (len) {
  245. (*cbc) (in, out, len, key, ivec, 0);
  246. in += len;
  247. out += len;
  248. }
  249. memset(tmp.c, 0, sizeof(tmp));
  250. /*
  251. * this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0]
  252. */
  253. (*cbc) (in + residue, tmp.c, 16, key, tmp.c + 16, 0);
  254. memcpy(tmp.c, in, residue);
  255. #if defined(CBC_HANDLES_TRUNCATED_IO)
  256. (*cbc) (tmp.c, out, 16 + residue, key, ivec, 0);
  257. #else
  258. (*cbc) (tmp.c, tmp.c, 32, key, ivec, 0);
  259. memcpy(out, tmp.c, 16 + residue);
  260. #endif
  261. return 16 + len + residue;
  262. }