cts128.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /* ====================================================================
  2. * Copyright (c) 2008 The OpenSSL Project. All rights reserved.
  3. *
  4. * Rights for redistribution and usage in source and binary
  5. * forms are granted according to the OpenSSL license.
  6. */
  7. #include <openssl/crypto.h>
  8. #include "modes_lcl.h"
  9. #include <string.h>
  10. #ifndef MODES_DEBUG
  11. # ifndef NDEBUG
  12. # define NDEBUG
  13. # endif
  14. #endif
  15. #include <assert.h>
  16. /*
  17. * Trouble with Ciphertext Stealing, CTS, mode is that there is no
  18. * common official specification, but couple of cipher/application
  19. * specific ones: RFC2040 and RFC3962. Then there is 'Proposal to
  20. * Extend CBC Mode By "Ciphertext Stealing"' at NIST site, which
  21. * deviates from mentioned RFCs. Most notably it allows input to be
  22. * of block length and it doesn't flip the order of the last two
  23. * blocks. CTS is being discussed even in ECB context, but it's not
  24. * adopted for any known application. This implementation provides
  25. * two interfaces: one compliant with above mentioned RFCs and one
  26. * compliant with the NIST proposal, both extending CBC mode.
  27. */
  28. size_t CRYPTO_cts128_encrypt_block(const unsigned char *in, unsigned char *out,
  29. size_t len, const void *key,
  30. unsigned char ivec[16], block128_f block)
  31. { size_t residue, n;
  32. assert (in && out && key && ivec);
  33. if (len <= 16) return 0;
  34. if ((residue=len%16) == 0) residue = 16;
  35. len -= residue;
  36. CRYPTO_cbc128_encrypt(in,out,len,key,ivec,block);
  37. in += len;
  38. out += len;
  39. for (n=0; n<residue; ++n)
  40. ivec[n] ^= in[n];
  41. (*block)(ivec,ivec,key);
  42. memcpy(out,out-16,residue);
  43. memcpy(out-16,ivec,16);
  44. return len+residue;
  45. }
  46. size_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in, unsigned char *out,
  47. size_t len, const void *key,
  48. unsigned char ivec[16], block128_f block)
  49. { size_t residue, n;
  50. assert (in && out && key && ivec);
  51. if (len < 16) return 0;
  52. residue=len%16;
  53. len -= residue;
  54. CRYPTO_cbc128_encrypt(in,out,len,key,ivec,block);
  55. if (residue==0) return len;
  56. in += len;
  57. out += len;
  58. for (n=0; n<residue; ++n)
  59. ivec[n] ^= in[n];
  60. (*block)(ivec,ivec,key);
  61. memcpy(out-16+residue,ivec,16);
  62. return len+residue;
  63. }
  64. size_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out,
  65. size_t len, const void *key,
  66. unsigned char ivec[16], cbc128_f cbc)
  67. { size_t residue;
  68. union { size_t align; unsigned char c[16]; } tmp;
  69. assert (in && out && key && ivec);
  70. if (len <= 16) return 0;
  71. if ((residue=len%16) == 0) residue = 16;
  72. len -= residue;
  73. (*cbc)(in,out,len,key,ivec,1);
  74. in += len;
  75. out += len;
  76. #if defined(CBC_HANDLES_TRUNCATED_IO)
  77. memcpy(tmp.c,out-16,16);
  78. (*cbc)(in,out-16,residue,key,ivec,1);
  79. memcpy(out,tmp.c,residue);
  80. #else
  81. {
  82. size_t n;
  83. for (n=0; n<16; n+=sizeof(size_t))
  84. *(size_t *)(tmp.c+n) = 0;
  85. memcpy(tmp.c,in,residue);
  86. }
  87. memcpy(out,out-16,residue);
  88. (*cbc)(tmp.c,out-16,16,key,ivec,1);
  89. #endif
  90. return len+residue;
  91. }
  92. size_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out,
  93. size_t len, const void *key,
  94. unsigned char ivec[16], cbc128_f cbc)
  95. { size_t residue;
  96. union { size_t align; unsigned char c[16]; } tmp;
  97. assert (in && out && key && ivec);
  98. if (len < 16) return 0;
  99. residue=len%16;
  100. len -= residue;
  101. (*cbc)(in,out,len,key,ivec,1);
  102. if (residue==0) return len;
  103. in += len;
  104. out += len;
  105. #if defined(CBC_HANDLES_TRUNCATED_IO)
  106. (*cbc)(in,out-16+residue,residue,key,ivec,1);
  107. #else
  108. {
  109. size_t n;
  110. for (n=0; n<16; n+=sizeof(size_t))
  111. *(size_t *)(tmp.c+n) = 0;
  112. memcpy(tmp.c,in,residue);
  113. }
  114. (*cbc)(tmp.c,out-16+residue,16,key,ivec,1);
  115. #endif
  116. return len+residue;
  117. }
  118. size_t CRYPTO_cts128_decrypt_block(const unsigned char *in, unsigned char *out,
  119. size_t len, const void *key,
  120. unsigned char ivec[16], block128_f block)
  121. { size_t residue, n;
  122. union { size_t align; unsigned char c[32]; } tmp;
  123. assert (in && out && key && ivec);
  124. if (len<=16) return 0;
  125. if ((residue=len%16) == 0) residue = 16;
  126. len -= 16+residue;
  127. if (len) {
  128. CRYPTO_cbc128_decrypt(in,out,len,key,ivec,block);
  129. in += len;
  130. out += len;
  131. }
  132. (*block)(in,tmp.c+16,key);
  133. for (n=0; n<16; n+=sizeof(size_t))
  134. *(size_t *)(tmp.c+n) = *(size_t *)(tmp.c+16+n);
  135. memcpy(tmp.c,in+16,residue);
  136. (*block)(tmp.c,tmp.c,key);
  137. for(n=0; n<16; ++n) {
  138. unsigned char c = in[n];
  139. out[n] = tmp.c[n] ^ ivec[n];
  140. ivec[n] = c;
  141. }
  142. for(residue+=16; n<residue; ++n)
  143. out[n] = tmp.c[n] ^ in[n];
  144. return 16+len+residue;
  145. }
  146. size_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in, unsigned char *out,
  147. size_t len, const void *key,
  148. unsigned char ivec[16], block128_f block)
  149. { size_t residue, n;
  150. union { size_t align; unsigned char c[32]; } tmp;
  151. assert (in && out && key && ivec);
  152. if (len<16) return 0;
  153. residue=len%16;
  154. if (residue==0) {
  155. CRYPTO_cbc128_decrypt(in,out,len,key,ivec,block);
  156. return len;
  157. }
  158. len -= 16+residue;
  159. if (len) {
  160. CRYPTO_cbc128_decrypt(in,out,len,key,ivec,block);
  161. in += len;
  162. out += len;
  163. }
  164. (*block)(in+residue,tmp.c+16,key);
  165. for (n=0; n<16; n+=sizeof(size_t))
  166. *(size_t *)(tmp.c+n) = *(size_t *)(tmp.c+16+n);
  167. memcpy(tmp.c,in,residue);
  168. (*block)(tmp.c,tmp.c,key);
  169. for(n=0; n<16; ++n) {
  170. unsigned char c = in[n];
  171. out[n] = tmp.c[n] ^ ivec[n];
  172. ivec[n] = in[n+residue];
  173. tmp.c[n] = c;
  174. }
  175. for(residue+=16; n<residue; ++n)
  176. out[n] = tmp.c[n] ^ tmp.c[n-16];
  177. return 16+len+residue;
  178. }
  179. size_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out,
  180. size_t len, const void *key,
  181. unsigned char ivec[16], cbc128_f cbc)
  182. { size_t residue, n;
  183. union { size_t align; unsigned char c[32]; } tmp;
  184. assert (in && out && key && ivec);
  185. if (len<=16) return 0;
  186. if ((residue=len%16) == 0) residue = 16;
  187. len -= 16+residue;
  188. if (len) {
  189. (*cbc)(in,out,len,key,ivec,0);
  190. in += len;
  191. out += len;
  192. }
  193. for (n=16; n<32; n+=sizeof(size_t))
  194. *(size_t *)(tmp.c+n) = 0;
  195. /* this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0] */
  196. (*cbc)(in,tmp.c,16,key,tmp.c+16,0);
  197. memcpy(tmp.c,in+16,residue);
  198. #if defined(CBC_HANDLES_TRUNCATED_IO)
  199. (*cbc)(tmp.c,out,16+residue,key,ivec,0);
  200. #else
  201. (*cbc)(tmp.c,tmp.c,32,key,ivec,0);
  202. memcpy(out,tmp.c,16+residue);
  203. #endif
  204. return 16+len+residue;
  205. }
  206. size_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out,
  207. size_t len, const void *key,
  208. unsigned char ivec[16], cbc128_f cbc)
  209. { size_t residue, n;
  210. union { size_t align; unsigned char c[32]; } tmp;
  211. assert (in && out && key && ivec);
  212. if (len<16) return 0;
  213. residue=len%16;
  214. if (residue==0) {
  215. (*cbc)(in,out,len,key,ivec,0);
  216. return len;
  217. }
  218. len -= 16+residue;
  219. if (len) {
  220. (*cbc)(in,out,len,key,ivec,0);
  221. in += len;
  222. out += len;
  223. }
  224. for (n=16; n<32; n+=sizeof(size_t))
  225. *(size_t *)(tmp.c+n) = 0;
  226. /* this places in[16] at &tmp.c[16] and decrypted block at &tmp.c[0] */
  227. (*cbc)(in+residue,tmp.c,16,key,tmp.c+16,0);
  228. memcpy(tmp.c,in,residue);
  229. #if defined(CBC_HANDLES_TRUNCATED_IO)
  230. (*cbc)(tmp.c,out,16+residue,key,ivec,0);
  231. #else
  232. (*cbc)(tmp.c,tmp.c,32,key,ivec,0);
  233. memcpy(out,tmp.c,16+residue);
  234. #endif
  235. return 16+len+residue;
  236. }
  237. #if defined(SELFTEST)
  238. #include <stdio.h>
  239. #include <openssl/aes.h>
  240. /* test vectors from RFC 3962 */
  241. static const unsigned char test_key[16] = "chicken teriyaki";
  242. static const unsigned char test_input[64] =
  243. "I would like the" " General Gau's C"
  244. "hicken, please, " "and wonton soup.";
  245. static const unsigned char test_iv[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  246. static const unsigned char vector_17[17] =
  247. {0xc6,0x35,0x35,0x68,0xf2,0xbf,0x8c,0xb4, 0xd8,0xa5,0x80,0x36,0x2d,0xa7,0xff,0x7f,
  248. 0x97};
  249. static const unsigned char vector_31[31] =
  250. {0xfc,0x00,0x78,0x3e,0x0e,0xfd,0xb2,0xc1, 0xd4,0x45,0xd4,0xc8,0xef,0xf7,0xed,0x22,
  251. 0x97,0x68,0x72,0x68,0xd6,0xec,0xcc,0xc0, 0xc0,0x7b,0x25,0xe2,0x5e,0xcf,0xe5};
  252. static const unsigned char vector_32[32] =
  253. {0x39,0x31,0x25,0x23,0xa7,0x86,0x62,0xd5, 0xbe,0x7f,0xcb,0xcc,0x98,0xeb,0xf5,0xa8,
  254. 0x97,0x68,0x72,0x68,0xd6,0xec,0xcc,0xc0, 0xc0,0x7b,0x25,0xe2,0x5e,0xcf,0xe5,0x84};
  255. static const unsigned char vector_47[47] =
  256. {0x97,0x68,0x72,0x68,0xd6,0xec,0xcc,0xc0, 0xc0,0x7b,0x25,0xe2,0x5e,0xcf,0xe5,0x84,
  257. 0xb3,0xff,0xfd,0x94,0x0c,0x16,0xa1,0x8c, 0x1b,0x55,0x49,0xd2,0xf8,0x38,0x02,0x9e,
  258. 0x39,0x31,0x25,0x23,0xa7,0x86,0x62,0xd5, 0xbe,0x7f,0xcb,0xcc,0x98,0xeb,0xf5};
  259. static const unsigned char vector_48[48] =
  260. {0x97,0x68,0x72,0x68,0xd6,0xec,0xcc,0xc0, 0xc0,0x7b,0x25,0xe2,0x5e,0xcf,0xe5,0x84,
  261. 0x9d,0xad,0x8b,0xbb,0x96,0xc4,0xcd,0xc0, 0x3b,0xc1,0x03,0xe1,0xa1,0x94,0xbb,0xd8,
  262. 0x39,0x31,0x25,0x23,0xa7,0x86,0x62,0xd5, 0xbe,0x7f,0xcb,0xcc,0x98,0xeb,0xf5,0xa8};
  263. static const unsigned char vector_64[64] =
  264. {0x97,0x68,0x72,0x68,0xd6,0xec,0xcc,0xc0, 0xc0,0x7b,0x25,0xe2,0x5e,0xcf,0xe5,0x84,
  265. 0x39,0x31,0x25,0x23,0xa7,0x86,0x62,0xd5, 0xbe,0x7f,0xcb,0xcc,0x98,0xeb,0xf5,0xa8,
  266. 0x48,0x07,0xef,0xe8,0x36,0xee,0x89,0xa5, 0x26,0x73,0x0d,0xbc,0x2f,0x7b,0xc8,0x40,
  267. 0x9d,0xad,0x8b,0xbb,0x96,0xc4,0xcd,0xc0, 0x3b,0xc1,0x03,0xe1,0xa1,0x94,0xbb,0xd8};
  268. static AES_KEY encks, decks;
  269. void test_vector(const unsigned char *vector,size_t len)
  270. { unsigned char iv[sizeof(test_iv)];
  271. unsigned char cleartext[64],ciphertext[64];
  272. size_t tail;
  273. printf("vector_%d\n",len); fflush(stdout);
  274. if ((tail=len%16) == 0) tail = 16;
  275. tail += 16;
  276. /* test block-based encryption */
  277. memcpy(iv,test_iv,sizeof(test_iv));
  278. CRYPTO_cts128_encrypt_block(test_input,ciphertext,len,&encks,iv,(block128_f)AES_encrypt);
  279. if (memcmp(ciphertext,vector,len))
  280. fprintf(stderr,"output_%d mismatch\n",len), exit(1);
  281. if (memcmp(iv,vector+len-tail,sizeof(iv)))
  282. fprintf(stderr,"iv_%d mismatch\n",len), exit(1);
  283. /* test block-based decryption */
  284. memcpy(iv,test_iv,sizeof(test_iv));
  285. CRYPTO_cts128_decrypt_block(ciphertext,cleartext,len,&decks,iv,(block128_f)AES_decrypt);
  286. if (memcmp(cleartext,test_input,len))
  287. fprintf(stderr,"input_%d mismatch\n",len), exit(2);
  288. if (memcmp(iv,vector+len-tail,sizeof(iv)))
  289. fprintf(stderr,"iv_%d mismatch\n",len), exit(2);
  290. /* test streamed encryption */
  291. memcpy(iv,test_iv,sizeof(test_iv));
  292. CRYPTO_cts128_encrypt(test_input,ciphertext,len,&encks,iv,(cbc128_f)AES_cbc_encrypt);
  293. if (memcmp(ciphertext,vector,len))
  294. fprintf(stderr,"output_%d mismatch\n",len), exit(3);
  295. if (memcmp(iv,vector+len-tail,sizeof(iv)))
  296. fprintf(stderr,"iv_%d mismatch\n",len), exit(3);
  297. /* test streamed decryption */
  298. memcpy(iv,test_iv,sizeof(test_iv));
  299. CRYPTO_cts128_decrypt(ciphertext,cleartext,len,&decks,iv,(cbc128_f)AES_cbc_encrypt);
  300. if (memcmp(cleartext,test_input,len))
  301. fprintf(stderr,"input_%d mismatch\n",len), exit(4);
  302. if (memcmp(iv,vector+len-tail,sizeof(iv)))
  303. fprintf(stderr,"iv_%d mismatch\n",len), exit(4);
  304. }
  305. void test_nistvector(const unsigned char *vector,size_t len)
  306. { unsigned char iv[sizeof(test_iv)];
  307. unsigned char cleartext[64],ciphertext[64],nistvector[64];
  308. size_t tail;
  309. printf("nistvector_%d\n",len); fflush(stdout);
  310. if ((tail=len%16) == 0) tail = 16;
  311. len -= 16 + tail;
  312. memcpy(nistvector,vector,len);
  313. /* flip two last blocks */
  314. memcpy(nistvector+len,vector+len+16,tail);
  315. memcpy(nistvector+len+tail,vector+len,16);
  316. len += 16 + tail;
  317. tail = 16;
  318. /* test block-based encryption */
  319. memcpy(iv,test_iv,sizeof(test_iv));
  320. CRYPTO_nistcts128_encrypt_block(test_input,ciphertext,len,&encks,iv,(block128_f)AES_encrypt);
  321. if (memcmp(ciphertext,nistvector,len))
  322. fprintf(stderr,"output_%d mismatch\n",len), exit(1);
  323. if (memcmp(iv,nistvector+len-tail,sizeof(iv)))
  324. fprintf(stderr,"iv_%d mismatch\n",len), exit(1);
  325. /* test block-based decryption */
  326. memcpy(iv,test_iv,sizeof(test_iv));
  327. CRYPTO_nistcts128_decrypt_block(ciphertext,cleartext,len,&decks,iv,(block128_f)AES_decrypt);
  328. if (memcmp(cleartext,test_input,len))
  329. fprintf(stderr,"input_%d mismatch\n",len), exit(2);
  330. if (memcmp(iv,nistvector+len-tail,sizeof(iv)))
  331. fprintf(stderr,"iv_%d mismatch\n",len), exit(2);
  332. /* test streamed encryption */
  333. memcpy(iv,test_iv,sizeof(test_iv));
  334. CRYPTO_nistcts128_encrypt(test_input,ciphertext,len,&encks,iv,(cbc128_f)AES_cbc_encrypt);
  335. if (memcmp(ciphertext,nistvector,len))
  336. fprintf(stderr,"output_%d mismatch\n",len), exit(3);
  337. if (memcmp(iv,nistvector+len-tail,sizeof(iv)))
  338. fprintf(stderr,"iv_%d mismatch\n",len), exit(3);
  339. /* test streamed decryption */
  340. memcpy(iv,test_iv,sizeof(test_iv));
  341. CRYPTO_nistcts128_decrypt(ciphertext,cleartext,len,&decks,iv,(cbc128_f)AES_cbc_encrypt);
  342. if (memcmp(cleartext,test_input,len))
  343. fprintf(stderr,"input_%d mismatch\n",len), exit(4);
  344. if (memcmp(iv,nistvector+len-tail,sizeof(iv)))
  345. fprintf(stderr,"iv_%d mismatch\n",len), exit(4);
  346. }
  347. int main()
  348. {
  349. AES_set_encrypt_key(test_key,128,&encks);
  350. AES_set_decrypt_key(test_key,128,&decks);
  351. test_vector(vector_17,sizeof(vector_17));
  352. test_vector(vector_31,sizeof(vector_31));
  353. test_vector(vector_32,sizeof(vector_32));
  354. test_vector(vector_47,sizeof(vector_47));
  355. test_vector(vector_48,sizeof(vector_48));
  356. test_vector(vector_64,sizeof(vector_64));
  357. test_nistvector(vector_17,sizeof(vector_17));
  358. test_nistvector(vector_31,sizeof(vector_31));
  359. test_nistvector(vector_32,sizeof(vector_32));
  360. test_nistvector(vector_47,sizeof(vector_47));
  361. test_nistvector(vector_48,sizeof(vector_48));
  362. test_nistvector(vector_64,sizeof(vector_64));
  363. return 0;
  364. }
  365. #endif