]> pd.if.org Git - zpackage/blob - ctr_encrypt.c
eb7328c2dcbc7d2563901e98a8ce87fad0956577
[zpackage] / ctr_encrypt.c
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 */
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 */
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$ */