Coverage Report

Created: 2024-11-21 07:03

/src/libtomcrypt/src/modes/ctr/ctr_encrypt.c
Line
Count
Source (jump to first uncovered line)
1
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2
/* SPDX-License-Identifier: Unlicense */
3
#include "tomcrypt_private.h"
4
5
/**
6
  @file ctr_encrypt.c
7
  CTR implementation, encrypt data, Tom St Denis
8
*/
9
10
11
#ifdef LTC_CTR_MODE
12
13
/**
14
  CTR encrypt software implementation
15
  @param pt     Plaintext
16
  @param ct     [out] Ciphertext
17
  @param len    Length of plaintext (octets)
18
  @param ctr    CTR state
19
  @return CRYPT_OK if successful
20
*/
21
static int s_ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr)
22
15
{
23
15
   int x, err;
24
25
5.69k
   while (len) {
26
      /* is the pad empty? */
27
5.67k
      if (ctr->padlen == ctr->blocklen) {
28
         /* increment counter */
29
5.60k
         if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) {
30
            /* little-endian */
31
0
            for (x = 0; x < ctr->ctrlen; x++) {
32
0
               ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
33
0
               if (ctr->ctr[x] != (unsigned char)0) {
34
0
                  break;
35
0
               }
36
0
            }
37
5.60k
         } else {
38
            /* big-endian */
39
5.62k
            for (x = ctr->blocklen-1; x >= ctr->ctrlen; x--) {
40
5.62k
               ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
41
5.62k
               if (ctr->ctr[x] != (unsigned char)0) {
42
5.60k
                  break;
43
5.60k
               }
44
5.62k
            }
45
5.60k
         }
46
47
         /* encrypt it */
48
5.60k
         if ((err = cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key)) != CRYPT_OK) {
49
0
            return err;
50
0
         }
51
5.60k
         ctr->padlen = 0;
52
5.60k
      }
53
5.67k
#ifdef LTC_FAST
54
5.67k
      if ((ctr->padlen == 0) && (len >= (unsigned long)ctr->blocklen)) {
55
11.2k
         for (x = 0; x < ctr->blocklen; x += sizeof(LTC_FAST_TYPE)) {
56
5.61k
            *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) ^
57
5.61k
                                                           *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ctr->pad + x));
58
5.61k
         }
59
5.61k
       pt         += ctr->blocklen;
60
5.61k
       ct         += ctr->blocklen;
61
5.61k
       len        -= ctr->blocklen;
62
5.61k
       ctr->padlen = ctr->blocklen;
63
5.61k
       continue;
64
5.61k
      }
65
64
#endif
66
64
      *ct++ = *pt++ ^ ctr->pad[ctr->padlen++];
67
64
      --len;
68
64
   }
69
15
   return CRYPT_OK;
70
15
}
71
72
/**
73
  CTR encrypt
74
  @param pt     Plaintext
75
  @param ct     [out] Ciphertext
76
  @param len    Length of plaintext (octets)
77
  @param ctr    CTR state
78
  @return CRYPT_OK if successful
79
*/
80
int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr)
81
15
{
82
15
   int err, fr;
83
84
15
   LTC_ARGCHK(pt != NULL);
85
15
   LTC_ARGCHK(ct != NULL);
86
15
   LTC_ARGCHK(ctr != NULL);
87
88
15
   if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {
89
0
       return err;
90
0
   }
91
92
   /* is blocklen/padlen valid? */
93
15
   if ((ctr->blocklen < 1) || (ctr->blocklen > (int)sizeof(ctr->ctr)) ||
94
15
       (ctr->padlen   < 0) || (ctr->padlen   > (int)sizeof(ctr->pad))) {
95
0
      return CRYPT_INVALID_ARG;
96
0
   }
97
98
15
#ifdef LTC_FAST
99
15
   if (ctr->blocklen % sizeof(LTC_FAST_TYPE)) {
100
0
      return CRYPT_INVALID_ARG;
101
0
   }
102
15
#endif
103
104
   /* handle acceleration only if pad is empty, accelerator is present and length is >= a block size */
105
15
   if ((cipher_descriptor[ctr->cipher].accel_ctr_encrypt != NULL) && (len >= (unsigned long)ctr->blocklen)) {
106
0
     if (ctr->padlen < ctr->blocklen) {
107
0
       fr = ctr->blocklen - ctr->padlen;
108
0
       if ((err = s_ctr_encrypt(pt, ct, fr, ctr)) != CRYPT_OK) {
109
0
          return err;
110
0
       }
111
0
       pt += fr;
112
0
       ct += fr;
113
0
       len -= fr;
114
0
     }
115
116
0
     if (len >= (unsigned long)ctr->blocklen) {
117
0
       if ((err = cipher_descriptor[ctr->cipher].accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) {
118
0
          return err;
119
0
       }
120
0
       pt += (len / ctr->blocklen) * ctr->blocklen;
121
0
       ct += (len / ctr->blocklen) * ctr->blocklen;
122
0
       len %= ctr->blocklen;
123
0
     }
124
0
   }
125
126
15
   return s_ctr_encrypt(pt, ct, len, ctr);
127
15
}
128
129
#endif