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