1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 */
9 #include "tomcrypt.h"
10
11 /**
12 @file ctr_encrypt.c
13 CTR implementation, encrypt data, Tom St Denis
14 */
15
16
17 #ifdef LTC_CTR_MODE
18
19 /**
20 CTR encrypt software implementation
21 @param pt Plaintext
22 @param ct [out] Ciphertext
23 @param len Length of plaintext (octets)
24 @param ctr CTR state
25 @return CRYPT_OK if successful
26 */
_ctr_encrypt(const unsigned char * pt,unsigned char * ct,unsigned long len,symmetric_CTR * ctr)27 static int _ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr)
28 {
29 int x, err;
30
31 while (len) {
32 /* is the pad empty? */
33 if (ctr->padlen == ctr->blocklen) {
34 /* increment counter */
35 if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) {
36 /* little-endian */
37 for (x = 0; x < ctr->ctrlen; x++) {
38 ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
39 if (ctr->ctr[x] != (unsigned char)0) {
40 break;
41 }
42 }
43 } else {
44 /* big-endian */
45 for (x = ctr->blocklen-1; x >= ctr->ctrlen; x--) {
46 ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
47 if (ctr->ctr[x] != (unsigned char)0) {
48 break;
49 }
50 }
51 }
52
53 /* encrypt it */
54 if ((err = cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key)) != CRYPT_OK) {
55 return err;
56 }
57 ctr->padlen = 0;
58 }
59 #ifdef LTC_FAST
60 if ((ctr->padlen == 0) && (len >= (unsigned long)ctr->blocklen)) {
61 for (x = 0; x < ctr->blocklen; x += sizeof(LTC_FAST_TYPE)) {
62 *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) ^
63 *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ctr->pad + x));
64 }
65 pt += ctr->blocklen;
66 ct += ctr->blocklen;
67 len -= ctr->blocklen;
68 ctr->padlen = ctr->blocklen;
69 continue;
70 }
71 #endif
72 *ct++ = *pt++ ^ ctr->pad[ctr->padlen++];
73 --len;
74 }
75 return CRYPT_OK;
76 }
77
78 /**
79 CTR encrypt
80 @param pt Plaintext
81 @param ct [out] Ciphertext
82 @param len Length of plaintext (octets)
83 @param ctr CTR state
84 @return CRYPT_OK if successful
85 */
ctr_encrypt(const unsigned char * pt,unsigned char * ct,unsigned long len,symmetric_CTR * ctr)86 int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr)
87 {
88 int err, fr;
89
90 LTC_ARGCHK(pt != NULL);
91 LTC_ARGCHK(ct != NULL);
92 LTC_ARGCHK(ctr != NULL);
93
94 if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {
95 return err;
96 }
97
98 /* is blocklen/padlen valid? */
99 if ((ctr->blocklen < 1) || (ctr->blocklen > (int)sizeof(ctr->ctr)) ||
100 (ctr->padlen < 0) || (ctr->padlen > (int)sizeof(ctr->pad))) {
101 return CRYPT_INVALID_ARG;
102 }
103
104 #ifdef LTC_FAST
105 if (ctr->blocklen % sizeof(LTC_FAST_TYPE)) {
106 return CRYPT_INVALID_ARG;
107 }
108 #endif
109
110 /* handle acceleration only if pad is empty, accelerator is present and length is >= a block size */
111 if ((cipher_descriptor[ctr->cipher].accel_ctr_encrypt != NULL) && (len >= (unsigned long)ctr->blocklen)) {
112 if (ctr->padlen < ctr->blocklen) {
113 fr = ctr->blocklen - ctr->padlen;
114 if ((err = _ctr_encrypt(pt, ct, fr, ctr)) != CRYPT_OK) {
115 return err;
116 }
117 pt += fr;
118 ct += fr;
119 len -= fr;
120 }
121
122 if (len >= (unsigned long)ctr->blocklen) {
123 if ((err = cipher_descriptor[ctr->cipher].accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) {
124 return err;
125 }
126 pt += (len / ctr->blocklen) * ctr->blocklen;
127 ct += (len / ctr->blocklen) * ctr->blocklen;
128 len %= ctr->blocklen;
129 }
130 }
131
132 return _ctr_encrypt(pt, ct, len, ctr);
133 }
134
135 #endif
136
137 /* ref: $Format:%D$ */
138 /* git commit: $Format:%H$ */
139 /* commit time: $Format:%ai$ */
140