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