Coverage Report

Created: 2023-06-08 06:41

/src/openssl111/crypto/modes/ctr128.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the OpenSSL license (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <openssl/crypto.h>
11
#include "modes_local.h"
12
#include <string.h>
13
14
#if defined(__GNUC__) && !defined(STRICT_ALIGNMENT)
15
typedef size_t size_t_aX __attribute((__aligned__(1)));
16
#else
17
typedef size_t size_t_aX;
18
#endif
19
20
/*
21
 * NOTE: the IV/counter CTR mode is big-endian.  The code itself is
22
 * endian-neutral.
23
 */
24
25
/* increment counter (128-bit int) by 1 */
26
static void ctr128_inc(unsigned char *counter)
27
0
{
28
0
    u32 n = 16, c = 1;
29
30
0
    do {
31
0
        --n;
32
0
        c += counter[n];
33
0
        counter[n] = (u8)c;
34
0
        c >>= 8;
35
0
    } while (n);
36
0
}
37
38
#if !defined(OPENSSL_SMALL_FOOTPRINT)
39
static void ctr128_inc_aligned(unsigned char *counter)
40
0
{
41
0
    size_t *data, c, d, n;
42
0
    const union {
43
0
        long one;
44
0
        char little;
45
0
    } is_endian = {
46
0
        1
47
0
    };
48
49
0
    if (is_endian.little || ((size_t)counter % sizeof(size_t)) != 0) {
50
0
        ctr128_inc(counter);
51
0
        return;
52
0
    }
53
54
0
    data = (size_t *)counter;
55
0
    c = 1;
56
0
    n = 16 / sizeof(size_t);
57
0
    do {
58
0
        --n;
59
0
        d = data[n] += c;
60
        /* did addition carry? */
61
0
        c = ((d - c) & ~d) >> (sizeof(size_t) * 8 - 1);
62
0
    } while (n);
63
0
}
64
#endif
65
66
/*
67
 * The input encrypted as though 128bit counter mode is being used.  The
68
 * extra state information to record how much of the 128bit block we have
69
 * used is contained in *num, and the encrypted counter is kept in
70
 * ecount_buf.  Both *num and ecount_buf must be initialised with zeros
71
 * before the first call to CRYPTO_ctr128_encrypt(). This algorithm assumes
72
 * that the counter is in the x lower bits of the IV (ivec), and that the
73
 * application has full control over overflow and the rest of the IV.  This
74
 * implementation takes NO responsibility for checking that the counter
75
 * doesn't overflow into the rest of the IV when incremented.
76
 */
77
void CRYPTO_ctr128_encrypt(const unsigned char *in, unsigned char *out,
78
                           size_t len, const void *key,
79
                           unsigned char ivec[16],
80
                           unsigned char ecount_buf[16], unsigned int *num,
81
                           block128_f block)
82
0
{
83
0
    unsigned int n;
84
0
    size_t l = 0;
85
86
0
    n = *num;
87
88
0
#if !defined(OPENSSL_SMALL_FOOTPRINT)
89
0
    if (16 % sizeof(size_t) == 0) { /* always true actually */
90
0
        do {
91
0
            while (n && len) {
92
0
                *(out++) = *(in++) ^ ecount_buf[n];
93
0
                --len;
94
0
                n = (n + 1) % 16;
95
0
            }
96
97
0
# if defined(STRICT_ALIGNMENT)
98
0
            if (((size_t)in | (size_t)out | (size_t)ecount_buf)
99
0
                % sizeof(size_t) != 0)
100
0
                break;
101
0
# endif
102
0
            while (len >= 16) {
103
0
                (*block) (ivec, ecount_buf, key);
104
0
                ctr128_inc_aligned(ivec);
105
0
                for (n = 0; n < 16; n += sizeof(size_t))
106
0
                    *(size_t_aX *)(out + n) =
107
0
                        *(size_t_aX *)(in + n)
108
0
                        ^ *(size_t_aX *)(ecount_buf + n);
109
0
                len -= 16;
110
0
                out += 16;
111
0
                in += 16;
112
0
                n = 0;
113
0
            }
114
0
            if (len) {
115
0
                (*block) (ivec, ecount_buf, key);
116
0
                ctr128_inc_aligned(ivec);
117
0
                while (len--) {
118
0
                    out[n] = in[n] ^ ecount_buf[n];
119
0
                    ++n;
120
0
                }
121
0
            }
122
0
            *num = n;
123
0
            return;
124
0
        } while (0);
125
0
    }
126
    /* the rest would be commonly eliminated by x86* compiler */
127
0
#endif
128
0
    while (l < len) {
129
0
        if (n == 0) {
130
0
            (*block) (ivec, ecount_buf, key);
131
0
            ctr128_inc(ivec);
132
0
        }
133
0
        out[l] = in[l] ^ ecount_buf[n];
134
0
        ++l;
135
0
        n = (n + 1) % 16;
136
0
    }
137
138
0
    *num = n;
139
0
}
140
141
/* increment upper 96 bits of 128-bit counter by 1 */
142
static void ctr96_inc(unsigned char *counter)
143
0
{
144
0
    u32 n = 12, c = 1;
145
146
0
    do {
147
0
        --n;
148
0
        c += counter[n];
149
0
        counter[n] = (u8)c;
150
0
        c >>= 8;
151
0
    } while (n);
152
0
}
153
154
void CRYPTO_ctr128_encrypt_ctr32(const unsigned char *in, unsigned char *out,
155
                                 size_t len, const void *key,
156
                                 unsigned char ivec[16],
157
                                 unsigned char ecount_buf[16],
158
                                 unsigned int *num, ctr128_f func)
159
17.5k
{
160
17.5k
    unsigned int n, ctr32;
161
162
17.5k
    n = *num;
163
164
17.5k
    while (n && len) {
165
0
        *(out++) = *(in++) ^ ecount_buf[n];
166
0
        --len;
167
0
        n = (n + 1) % 16;
168
0
    }
169
170
17.5k
    ctr32 = GETU32(ivec + 12);
171
32.2k
    while (len >= 16) {
172
14.6k
        size_t blocks = len / 16;
173
        /*
174
         * 1<<28 is just a not-so-small yet not-so-large number...
175
         * Below condition is practically never met, but it has to
176
         * be checked for code correctness.
177
         */
178
14.6k
        if (sizeof(size_t) > sizeof(unsigned int) && blocks > (1U << 28))
179
0
            blocks = (1U << 28);
180
        /*
181
         * As (*func) operates on 32-bit counter, caller
182
         * has to handle overflow. 'if' below detects the
183
         * overflow, which is then handled by limiting the
184
         * amount of blocks to the exact overflow point...
185
         */
186
14.6k
        ctr32 += (u32)blocks;
187
14.6k
        if (ctr32 < blocks) {
188
0
            blocks -= ctr32;
189
0
            ctr32 = 0;
190
0
        }
191
14.6k
        (*func) (in, out, blocks, key, ivec);
192
        /* (*ctr) does not update ivec, caller does: */
193
14.6k
        PUTU32(ivec + 12, ctr32);
194
        /* ... overflow was detected, propagate carry. */
195
14.6k
        if (ctr32 == 0)
196
0
            ctr96_inc(ivec);
197
14.6k
        blocks *= 16;
198
14.6k
        len -= blocks;
199
14.6k
        out += blocks;
200
14.6k
        in += blocks;
201
14.6k
    }
202
17.5k
    if (len) {
203
17.5k
        memset(ecount_buf, 0, 16);
204
17.5k
        (*func) (ecount_buf, ecount_buf, 1, key, ivec);
205
17.5k
        ++ctr32;
206
17.5k
        PUTU32(ivec + 12, ctr32);
207
17.5k
        if (ctr32 == 0)
208
0
            ctr96_inc(ivec);
209
190k
        while (len--) {
210
172k
            out[n] = in[n] ^ ecount_buf[n];
211
172k
            ++n;
212
172k
        }
213
17.5k
    }
214
215
17.5k
    *num = n;
216
17.5k
}