Coverage Report

Created: 2025-10-13 07:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dropbear/libtomcrypt/src/modes/ctr/ctr_encrypt.c
Line
Count
Source
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
99.1k
{
29
99.1k
   int x, err;
30
31
12.8M
   while (len) {
32
      /* is the pad empty? */
33
12.7M
      if (ctr->padlen == ctr->blocklen) {
34
         /* increment counter */
35
12.6M
         if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) {
36
            /* little-endian */
37
0
            for (x = 0; x < ctr->ctrlen; x++) {
38
0
               ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
39
0
               if (ctr->ctr[x] != (unsigned char)0) {
40
0
                  break;
41
0
               }
42
0
            }
43
12.6M
         } else {
44
            /* big-endian */
45
12.7M
            for (x = ctr->blocklen-1; x >= ctr->ctrlen; x--) {
46
12.7M
               ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
47
12.7M
               if (ctr->ctr[x] != (unsigned char)0) {
48
12.6M
                  break;
49
12.6M
               }
50
12.7M
            }
51
12.6M
         }
52
53
         /* encrypt it */
54
12.6M
         if ((err = cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key)) != CRYPT_OK) {
55
0
            return err;
56
0
         }
57
12.6M
         ctr->padlen = 0;
58
12.6M
      }
59
12.7M
#ifdef LTC_FAST
60
12.7M
      if ((ctr->padlen == 0) && (len >= (unsigned long)ctr->blocklen)) {
61
38.1M
         for (x = 0; x < ctr->blocklen; x += sizeof(LTC_FAST_TYPE)) {
62
25.4M
            *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) ^
63
25.4M
                                                           *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ctr->pad + x));
64
25.4M
         }
65
12.7M
       pt         += ctr->blocklen;
66
12.7M
       ct         += ctr->blocklen;
67
12.7M
       len        -= ctr->blocklen;
68
12.7M
       ctr->padlen = ctr->blocklen;
69
12.7M
       continue;
70
12.7M
      }
71
0
#endif
72
0
      *ct++ = *pt++ ^ ctr->pad[ctr->padlen++];
73
0
      --len;
74
0
   }
75
99.1k
   return CRYPT_OK;
76
99.1k
}
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
99.1k
{
88
99.1k
   int err, fr;
89
90
99.1k
   LTC_ARGCHK(pt != NULL);
91
99.1k
   LTC_ARGCHK(ct != NULL);
92
99.1k
   LTC_ARGCHK(ctr != NULL);
93
94
99.1k
   if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {
95
0
       return err;
96
0
   }
97
98
   /* is blocklen/padlen valid? */
99
99.1k
   if ((ctr->blocklen < 1) || (ctr->blocklen > (int)sizeof(ctr->ctr)) ||
100
99.1k
       (ctr->padlen   < 0) || (ctr->padlen   > (int)sizeof(ctr->pad))) {
101
0
      return CRYPT_INVALID_ARG;
102
0
   }
103
104
99.1k
#ifdef LTC_FAST
105
99.1k
   if (ctr->blocklen % sizeof(LTC_FAST_TYPE)) {
106
0
      return CRYPT_INVALID_ARG;
107
0
   }
108
99.1k
#endif
109
110
   /* handle acceleration only if pad is empty, accelerator is present and length is >= a block size */
111
99.1k
   if ((cipher_descriptor[ctr->cipher].accel_ctr_encrypt != NULL) && (len >= (unsigned long)ctr->blocklen)) {
112
0
     if (ctr->padlen < ctr->blocklen) {
113
0
       fr = ctr->blocklen - ctr->padlen;
114
0
       if ((err = _ctr_encrypt(pt, ct, fr, ctr)) != CRYPT_OK) {
115
0
          return err;
116
0
       }
117
0
       pt += fr;
118
0
       ct += fr;
119
0
       len -= fr;
120
0
     }
121
122
0
     if (len >= (unsigned long)ctr->blocklen) {
123
0
       if ((err = cipher_descriptor[ctr->cipher].accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) {
124
0
          return err;
125
0
       }
126
0
       pt += (len / ctr->blocklen) * ctr->blocklen;
127
0
       ct += (len / ctr->blocklen) * ctr->blocklen;
128
0
       len %= ctr->blocklen;
129
0
     }
130
0
   }
131
132
99.1k
   return _ctr_encrypt(pt, ct, len, ctr);
133
99.1k
}
134
135
#endif
136
137
/* ref:         $Format:%D$ */
138
/* git commit:  $Format:%H$ */
139
/* commit time: $Format:%ai$ */