cipher_aes_cts_fips.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*
  2. * Copyright 2020 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. /* Helper functions for AES CBC CTS ciphers related to fips */
  10. /*
  11. * Refer to SP800-38A-Addendum
  12. *
  13. * Ciphertext stealing encrypts plaintext using a block cipher, without padding
  14. * the message to a multiple of the block size, so the ciphertext is the same
  15. * size as the plaintext.
  16. * It does this by altering processing of the last two blocks of the message.
  17. * The processing of all but the last two blocks is unchanged, but a portion of
  18. * the second-last block's ciphertext is "stolen" to pad the last plaintext
  19. * block. The padded final block is then encrypted as usual.
  20. * The final ciphertext for the last two blocks, consists of the partial block
  21. * (with the "stolen" portion omitted) plus the full final block,
  22. * which are the same size as the original plaintext.
  23. * Decryption requires decrypting the final block first, then restoring the
  24. * stolen ciphertext to the partial block, which can then be decrypted as usual.
  25. * AES_CBC_CTS has 3 variants:
  26. * (1) CS1 The NIST variant.
  27. * If the length is a multiple of the blocksize it is the same as CBC mode.
  28. * otherwise it produces C1||C2||(C(n-1))*||Cn.
  29. * Where C(n-1)* is a partial block.
  30. * (2) CS2
  31. * If the length is a multiple of the blocksize it is the same as CBC mode.
  32. * otherwise it produces C1||C2||Cn||(C(n-1))*.
  33. * Where C(n-1)* is a partial block.
  34. * (3) CS3 The Kerberos5 variant.
  35. * Produces C1||C2||Cn||(C(n-1))* regardless of the length.
  36. * If the length is a multiple of the blocksize it looks similar to CBC mode
  37. * with the last 2 blocks swapped.
  38. * Otherwise it is the same as CS2.
  39. */
  40. #include "e_os.h" /* strcasecmp */
  41. #include <openssl/core_names.h>
  42. #include <openssl/aes.h>
  43. #include "prov/ciphercommon.h"
  44. #include "internal/nelem.h"
  45. #include "cipher_aes_cts.h"
  46. /* The value assigned to 0 is the default */
  47. #define CTS_CS1 0
  48. #define CTS_CS2 1
  49. #define CTS_CS3 2
  50. typedef union {
  51. size_t align;
  52. unsigned char c[AES_BLOCK_SIZE];
  53. } aligned_16bytes;
  54. typedef struct cts_mode_name2id_st {
  55. unsigned int id;
  56. const char *name;
  57. } CTS_MODE_NAME2ID;
  58. static CTS_MODE_NAME2ID cts_modes[] =
  59. {
  60. { CTS_CS1, OSSL_CIPHER_CTS_MODE_CS1 },
  61. #ifndef FIPS_MODULE
  62. { CTS_CS2, OSSL_CIPHER_CTS_MODE_CS2 },
  63. { CTS_CS3, OSSL_CIPHER_CTS_MODE_CS3 },
  64. #endif
  65. };
  66. const char *ossl_aes_cbc_cts_mode_id2name(unsigned int id)
  67. {
  68. size_t i;
  69. for (i = 0; i < OSSL_NELEM(cts_modes); ++i) {
  70. if (cts_modes[i].id == id)
  71. return cts_modes[i].name;
  72. }
  73. return NULL;
  74. }
  75. int ossl_aes_cbc_cts_mode_name2id(const char *name)
  76. {
  77. size_t i;
  78. for (i = 0; i < OSSL_NELEM(cts_modes); ++i) {
  79. if (strcasecmp(name, cts_modes[i].name) == 0)
  80. return (int)cts_modes[i].id;
  81. }
  82. return -1;
  83. }
  84. static size_t cts128_cs1_encrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
  85. unsigned char *out, size_t len)
  86. {
  87. aligned_16bytes tmp_in;
  88. size_t residue;
  89. residue = len % AES_BLOCK_SIZE;
  90. len -= residue;
  91. if (!ctx->hw->cipher(ctx, out, in, len))
  92. return 0;
  93. if (residue == 0)
  94. return len;
  95. in += len;
  96. out += len;
  97. memset(tmp_in.c, 0, sizeof(tmp_in));
  98. memcpy(tmp_in.c, in, residue);
  99. if (!ctx->hw->cipher(ctx, out - AES_BLOCK_SIZE + residue, tmp_in.c,
  100. AES_BLOCK_SIZE))
  101. return 0;
  102. return len + residue;
  103. }
  104. static void do_xor(const unsigned char *in1, const unsigned char *in2,
  105. size_t len, unsigned char *out)
  106. {
  107. size_t i;
  108. for (i = 0; i < len; ++i)
  109. out[i] = in1[i] ^ in2[i];
  110. }
  111. static size_t cts128_cs1_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
  112. unsigned char *out, size_t len)
  113. {
  114. aligned_16bytes mid_iv, ct_mid, pt_last;
  115. size_t residue;
  116. residue = len % AES_BLOCK_SIZE;
  117. if (residue == 0) {
  118. /* If there are no partial blocks then it is the same as CBC mode */
  119. if (!ctx->hw->cipher(ctx, out, in, len))
  120. return 0;
  121. return len;
  122. }
  123. /* Process blocks at the start - but leave the last 2 blocks */
  124. len -= AES_BLOCK_SIZE + residue;
  125. if (len > 0) {
  126. if (!ctx->hw->cipher(ctx, out, in, len))
  127. return 0;
  128. in += len;
  129. out += len;
  130. }
  131. /* Save the iv that will be used by the second last block */
  132. memcpy(mid_iv.c, ctx->iv, AES_BLOCK_SIZE);
  133. /* Decrypt the last block first using an iv of zero */
  134. memset(ctx->iv, 0, AES_BLOCK_SIZE);
  135. if (!ctx->hw->cipher(ctx, pt_last.c, in + residue, AES_BLOCK_SIZE))
  136. return 0;
  137. /*
  138. * Rebuild the ciphertext of the second last block as a combination of
  139. * the decrypted last block + replace the start with the ciphertext bytes
  140. * of the partial second last block.
  141. */
  142. memcpy(ct_mid.c, in, residue);
  143. memcpy(ct_mid.c + residue, pt_last.c + residue, AES_BLOCK_SIZE - residue);
  144. /*
  145. * Restore the last partial ciphertext block.
  146. * Now that we have the cipher text of the second last block, apply
  147. * that to the partial plaintext end block. We have already decrypted the
  148. * block using an IV of zero. For decryption the IV is just XORed after
  149. * doing an AES block - so just XOR in the cipher text.
  150. */
  151. do_xor(ct_mid.c, pt_last.c, residue, out + AES_BLOCK_SIZE);
  152. /* Restore the iv needed by the second last block */
  153. memcpy(ctx->iv, mid_iv.c, AES_BLOCK_SIZE);
  154. /*
  155. * Decrypt the second last plaintext block now that we have rebuilt the
  156. * ciphertext.
  157. */
  158. if (!ctx->hw->cipher(ctx, out, ct_mid.c, AES_BLOCK_SIZE))
  159. return 0;
  160. return len + AES_BLOCK_SIZE + residue;
  161. }
  162. #ifndef FIPS_MODULE
  163. static size_t cts128_cs3_encrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
  164. unsigned char *out, size_t len)
  165. {
  166. aligned_16bytes tmp_in;
  167. size_t residue;
  168. if (len <= AES_BLOCK_SIZE) /* CS3 requires 2 blocks */
  169. return 0;
  170. residue = len % AES_BLOCK_SIZE;
  171. if (residue == 0)
  172. residue = AES_BLOCK_SIZE;
  173. len -= residue;
  174. if (!ctx->hw->cipher(ctx, out, in, len))
  175. return 0;
  176. in += len;
  177. out += len;
  178. memset(tmp_in.c, 0, sizeof(tmp_in));
  179. memcpy(tmp_in.c, in, residue);
  180. memcpy(out, out - AES_BLOCK_SIZE, residue);
  181. if (!ctx->hw->cipher(ctx, out - AES_BLOCK_SIZE, tmp_in.c, AES_BLOCK_SIZE))
  182. return 0;
  183. return len + residue;
  184. }
  185. /*
  186. * Note:
  187. * The cipher text (in) is of the form C(0), C(1), ., C(n), C(n-1)* where
  188. * C(n) is a full block and C(n-1)* can be a partial block
  189. * (but could be a full block).
  190. * This means that the output plaintext (out) needs to swap the plaintext of
  191. * the last two decoded ciphertext blocks.
  192. */
  193. static size_t cts128_cs3_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
  194. unsigned char *out, size_t len)
  195. {
  196. aligned_16bytes mid_iv, ct_mid, pt_last;
  197. size_t residue;
  198. if (len <= AES_BLOCK_SIZE) /* CS3 requires 2 blocks */
  199. return 0;
  200. /* Process blocks at the start - but leave the last 2 blocks */
  201. residue = len % AES_BLOCK_SIZE;
  202. if (residue == 0)
  203. residue = AES_BLOCK_SIZE;
  204. len -= AES_BLOCK_SIZE + residue;
  205. if (len > 0) {
  206. if (!ctx->hw->cipher(ctx, out, in, len))
  207. return 0;
  208. in += len;
  209. out += len;
  210. }
  211. /* Save the iv that will be used by the second last block */
  212. memcpy(mid_iv.c, ctx->iv, AES_BLOCK_SIZE);
  213. /* Decrypt the Cn block first using an iv of zero */
  214. memset(ctx->iv, 0, AES_BLOCK_SIZE);
  215. if (!ctx->hw->cipher(ctx, pt_last.c, in, AES_BLOCK_SIZE))
  216. return 0;
  217. /*
  218. * Rebuild the ciphertext of C(n-1) as a combination of
  219. * the decrypted C(n) block + replace the start with the ciphertext bytes
  220. * of the partial last block.
  221. */
  222. memcpy(ct_mid.c, in + AES_BLOCK_SIZE, residue);
  223. if (residue != AES_BLOCK_SIZE)
  224. memcpy(ct_mid.c + residue, pt_last.c + residue, AES_BLOCK_SIZE - residue);
  225. /*
  226. * Restore the last partial ciphertext block.
  227. * Now that we have the cipher text of the second last block, apply
  228. * that to the partial plaintext end block. We have already decrypted the
  229. * block using an IV of zero. For decryption the IV is just XORed after
  230. * doing an AES block - so just XOR in the ciphertext.
  231. */
  232. do_xor(ct_mid.c, pt_last.c, residue, out + AES_BLOCK_SIZE);
  233. /* Restore the iv needed by the second last block */
  234. memcpy(ctx->iv, mid_iv.c, AES_BLOCK_SIZE);
  235. /*
  236. * Decrypt the second last plaintext block now that we have rebuilt the
  237. * ciphertext.
  238. */
  239. if (!ctx->hw->cipher(ctx, out, ct_mid.c, AES_BLOCK_SIZE))
  240. return 0;
  241. return len + AES_BLOCK_SIZE + residue;
  242. }
  243. static size_t cts128_cs2_encrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
  244. unsigned char *out, size_t len)
  245. {
  246. if (len % AES_BLOCK_SIZE == 0) {
  247. /* If there are no partial blocks then it is the same as CBC mode */
  248. if (!ctx->hw->cipher(ctx, out, in, len))
  249. return 0;
  250. return len;
  251. }
  252. /* For partial blocks CS2 is equivalent to CS3 */
  253. return cts128_cs3_encrypt(ctx, in, out, len);
  254. }
  255. static size_t cts128_cs2_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
  256. unsigned char *out, size_t len)
  257. {
  258. if (len % AES_BLOCK_SIZE == 0) {
  259. /* If there are no partial blocks then it is the same as CBC mode */
  260. if (!ctx->hw->cipher(ctx, out, in, len))
  261. return 0;
  262. return len;
  263. }
  264. /* For partial blocks CS2 is equivalent to CS3 */
  265. return cts128_cs3_decrypt(ctx, in, out, len);
  266. }
  267. #endif
  268. int ossl_aes_cbc_cts_block_update(void *vctx, unsigned char *out, size_t *outl,
  269. size_t outsize, const unsigned char *in,
  270. size_t inl)
  271. {
  272. PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
  273. size_t sz = 0;
  274. if (inl < AES_BLOCK_SIZE) /* There must be at least one block for CTS mode */
  275. return 0;
  276. if (outsize < inl)
  277. return 0;
  278. if (out == NULL) {
  279. *outl = inl;
  280. return 1;
  281. }
  282. /*
  283. * Return an error if the update is called multiple times, only one shot
  284. * is supported.
  285. */
  286. if (ctx->updated == 1)
  287. return 0;
  288. if (ctx->enc) {
  289. #ifdef FIPS_MODULE
  290. sz = cts128_cs1_encrypt(ctx, in, out, inl);
  291. #else
  292. if (ctx->cts_mode == CTS_CS1)
  293. sz = cts128_cs1_encrypt(ctx, in, out, inl);
  294. else if (ctx->cts_mode == CTS_CS2)
  295. sz = cts128_cs2_encrypt(ctx, in, out, inl);
  296. else if (ctx->cts_mode == CTS_CS3)
  297. sz = cts128_cs3_encrypt(ctx, in, out, inl);
  298. #endif
  299. } else {
  300. #ifdef FIPS_MODULE
  301. sz = cts128_cs1_decrypt(ctx, in, out, inl);
  302. #else
  303. if (ctx->cts_mode == CTS_CS1)
  304. sz = cts128_cs1_decrypt(ctx, in, out, inl);
  305. else if (ctx->cts_mode == CTS_CS2)
  306. sz = cts128_cs2_decrypt(ctx, in, out, inl);
  307. else if (ctx->cts_mode == CTS_CS3)
  308. sz = cts128_cs3_decrypt(ctx, in, out, inl);
  309. #endif
  310. }
  311. if (sz == 0)
  312. return 0;
  313. ctx->updated = 1; /* Stop multiple updates being allowed */
  314. *outl = sz;
  315. return 1;
  316. }
  317. int ossl_aes_cbc_cts_block_final(void *vctx, unsigned char *out, size_t *outl,
  318. size_t outsize)
  319. {
  320. *outl = 0;
  321. return 1;
  322. }