1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 /**
6 @file cbc_decrypt.c
7 CBC implementation, encrypt block, Tom St Denis
8 */
9
10
11 #ifdef LTC_CBC_MODE
12
13 /**
14 CBC decrypt
15 @param ct Ciphertext
16 @param pt [out] Plaintext
17 @param len The number of bytes to process (must be multiple of block length)
18 @param cbc CBC state
19 @return CRYPT_OK if successful
20 */
cbc_decrypt(const unsigned char * ct,unsigned char * pt,unsigned long len,symmetric_CBC * cbc)21 int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc)
22 {
23 int x, err;
24 unsigned char tmp[16];
25 #ifdef LTC_FAST
26 LTC_FAST_TYPE tmpy;
27 #else
28 unsigned char tmpy;
29 #endif
30
31 LTC_ARGCHK(pt != NULL);
32 LTC_ARGCHK(ct != NULL);
33 LTC_ARGCHK(cbc != NULL);
34
35 if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
36 return err;
37 }
38
39 /* is blocklen valid? */
40 if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV) || cbc->blocklen > (int)sizeof(tmp)) {
41 return CRYPT_INVALID_ARG;
42 }
43
44 if (len % cbc->blocklen) {
45 return CRYPT_INVALID_ARG;
46 }
47 #ifdef LTC_FAST
48 if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) {
49 return CRYPT_INVALID_ARG;
50 }
51 #endif
52
53 if (cipher_descriptor[cbc->cipher]->accel_cbc_decrypt != NULL) {
54 return cipher_descriptor[cbc->cipher]->accel_cbc_decrypt(ct, pt, len / cbc->blocklen, cbc->IV, &cbc->key);
55 }
56 while (len) {
57 /* decrypt */
58 if ((err = cipher_descriptor[cbc->cipher]->ecb_decrypt(ct, tmp, &cbc->key)) != CRYPT_OK) {
59 return err;
60 }
61
62 /* xor IV against plaintext */
63 #if defined(LTC_FAST)
64 for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) {
65 tmpy = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) ^ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)tmp + x));
66 *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x));
67 *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) = tmpy;
68 }
69 #else
70 for (x = 0; x < cbc->blocklen; x++) {
71 tmpy = tmp[x] ^ cbc->IV[x];
72 cbc->IV[x] = ct[x];
73 pt[x] = tmpy;
74 }
75 #endif
76
77 ct += cbc->blocklen;
78 pt += cbc->blocklen;
79 len -= cbc->blocklen;
80 }
81 return CRYPT_OK;
82 }
83
84 #endif
85