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