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