]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/openssl/crypto/modes/ctr128.c
Merge OpenSSL 1.1.1h.
[FreeBSD/FreeBSD.git] / crypto / openssl / crypto / modes / ctr128.c
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 {
28     u32 n = 16, c = 1;
29
30     do {
31         --n;
32         c += counter[n];
33         counter[n] = (u8)c;
34         c >>= 8;
35     } while (n);
36 }
37
38 #if !defined(OPENSSL_SMALL_FOOTPRINT)
39 static void ctr128_inc_aligned(unsigned char *counter)
40 {
41     size_t *data, c, d, n;
42     const union {
43         long one;
44         char little;
45     } is_endian = {
46         1
47     };
48
49     if (is_endian.little || ((size_t)counter % sizeof(size_t)) != 0) {
50         ctr128_inc(counter);
51         return;
52     }
53
54     data = (size_t *)counter;
55     c = 1;
56     n = 16 / sizeof(size_t);
57     do {
58         --n;
59         d = data[n] += c;
60         /* did addition carry? */
61         c = ((d - c) & ~d) >> (sizeof(size_t) * 8 - 1);
62     } while (n);
63 }
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 {
83     unsigned int n;
84     size_t l = 0;
85
86     n = *num;
87
88 #if !defined(OPENSSL_SMALL_FOOTPRINT)
89     if (16 % sizeof(size_t) == 0) { /* always true actually */
90         do {
91             while (n && len) {
92                 *(out++) = *(in++) ^ ecount_buf[n];
93                 --len;
94                 n = (n + 1) % 16;
95             }
96
97 # if defined(STRICT_ALIGNMENT)
98             if (((size_t)in | (size_t)out | (size_t)ecount_buf)
99                 % sizeof(size_t) != 0)
100                 break;
101 # endif
102             while (len >= 16) {
103                 (*block) (ivec, ecount_buf, key);
104                 ctr128_inc_aligned(ivec);
105                 for (n = 0; n < 16; n += sizeof(size_t))
106                     *(size_t_aX *)(out + n) =
107                         *(size_t_aX *)(in + n)
108                         ^ *(size_t_aX *)(ecount_buf + n);
109                 len -= 16;
110                 out += 16;
111                 in += 16;
112                 n = 0;
113             }
114             if (len) {
115                 (*block) (ivec, ecount_buf, key);
116                 ctr128_inc_aligned(ivec);
117                 while (len--) {
118                     out[n] = in[n] ^ ecount_buf[n];
119                     ++n;
120                 }
121             }
122             *num = n;
123             return;
124         } while (0);
125     }
126     /* the rest would be commonly eliminated by x86* compiler */
127 #endif
128     while (l < len) {
129         if (n == 0) {
130             (*block) (ivec, ecount_buf, key);
131             ctr128_inc(ivec);
132         }
133         out[l] = in[l] ^ ecount_buf[n];
134         ++l;
135         n = (n + 1) % 16;
136     }
137
138     *num = n;
139 }
140
141 /* increment upper 96 bits of 128-bit counter by 1 */
142 static void ctr96_inc(unsigned char *counter)
143 {
144     u32 n = 12, c = 1;
145
146     do {
147         --n;
148         c += counter[n];
149         counter[n] = (u8)c;
150         c >>= 8;
151     } while (n);
152 }
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 {
160     unsigned int n, ctr32;
161
162     n = *num;
163
164     while (n && len) {
165         *(out++) = *(in++) ^ ecount_buf[n];
166         --len;
167         n = (n + 1) % 16;
168     }
169
170     ctr32 = GETU32(ivec + 12);
171     while (len >= 16) {
172         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         if (sizeof(size_t) > sizeof(unsigned int) && blocks > (1U << 28))
179             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         ctr32 += (u32)blocks;
187         if (ctr32 < blocks) {
188             blocks -= ctr32;
189             ctr32 = 0;
190         }
191         (*func) (in, out, blocks, key, ivec);
192         /* (*ctr) does not update ivec, caller does: */
193         PUTU32(ivec + 12, ctr32);
194         /* ... overflow was detected, propagate carry. */
195         if (ctr32 == 0)
196             ctr96_inc(ivec);
197         blocks *= 16;
198         len -= blocks;
199         out += blocks;
200         in += blocks;
201     }
202     if (len) {
203         memset(ecount_buf, 0, 16);
204         (*func) (ecount_buf, ecount_buf, 1, key, ivec);
205         ++ctr32;
206         PUTU32(ivec + 12, ctr32);
207         if (ctr32 == 0)
208             ctr96_inc(ivec);
209         while (len--) {
210             out[n] = in[n] ^ ecount_buf[n];
211             ++n;
212         }
213     }
214
215     *num = n;
216 }