/src/boringssl/crypto/fipsmodule/aes/ctr.cc.inc
Line | Count | Source |
1 | | // Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include <assert.h> |
16 | | #include <string.h> |
17 | | |
18 | | #include "internal.h" |
19 | | #include "../../internal.h" |
20 | | |
21 | | |
22 | | static_assert(16 % sizeof(crypto_word_t) == 0, |
23 | | "block cannot be divided into crypto_word_t"); |
24 | | |
25 | | // increment upper 96 bits of 128-bit counter by 1 |
26 | 0 | static void ctr96_inc(uint8_t *counter) { |
27 | 0 | uint32_t n = 12, c = 1; |
28 | |
|
29 | 0 | do { |
30 | 0 | --n; |
31 | 0 | c += counter[n]; |
32 | 0 | counter[n] = (uint8_t) c; |
33 | 0 | c >>= 8; |
34 | 0 | } while (n); |
35 | 0 | } |
36 | | |
37 | | void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, size_t len, |
38 | | const AES_KEY *key, uint8_t ivec[16], |
39 | | uint8_t ecount_buf[16], unsigned int *num, |
40 | 0 | ctr128_f func) { |
41 | 0 | unsigned int n, ctr32; |
42 | |
|
43 | 0 | assert(key && ecount_buf && num); |
44 | 0 | assert(len == 0 || (in && out)); |
45 | 0 | assert(*num < 16); |
46 | | |
47 | 0 | n = *num; |
48 | |
|
49 | 0 | while (n && len) { |
50 | 0 | *(out++) = *(in++) ^ ecount_buf[n]; |
51 | 0 | --len; |
52 | 0 | n = (n + 1) % 16; |
53 | 0 | } |
54 | |
|
55 | 0 | ctr32 = CRYPTO_load_u32_be(ivec + 12); |
56 | 0 | while (len >= 16) { |
57 | 0 | size_t blocks = len / 16; |
58 | | // 1<<28 is just a not-so-small yet not-so-large number... |
59 | | // Below condition is practically never met, but it has to |
60 | | // be checked for code correctness. |
61 | 0 | if (sizeof(size_t) > sizeof(unsigned int) && blocks > (1U << 28)) { |
62 | 0 | blocks = (1U << 28); |
63 | 0 | } |
64 | | // As (*func) operates on 32-bit counter, caller |
65 | | // has to handle overflow. 'if' below detects the |
66 | | // overflow, which is then handled by limiting the |
67 | | // amount of blocks to the exact overflow point... |
68 | 0 | ctr32 += (uint32_t)blocks; |
69 | 0 | if (ctr32 < blocks) { |
70 | 0 | blocks -= ctr32; |
71 | 0 | ctr32 = 0; |
72 | 0 | } |
73 | 0 | (*func)(in, out, blocks, key, ivec); |
74 | | // (*func) does not update ivec, caller does: |
75 | 0 | CRYPTO_store_u32_be(ivec + 12, ctr32); |
76 | | // ... overflow was detected, propagate carry. |
77 | 0 | if (ctr32 == 0) { |
78 | 0 | ctr96_inc(ivec); |
79 | 0 | } |
80 | 0 | blocks *= 16; |
81 | 0 | len -= blocks; |
82 | 0 | out += blocks; |
83 | 0 | in += blocks; |
84 | 0 | } |
85 | 0 | if (len) { |
86 | 0 | OPENSSL_memset(ecount_buf, 0, 16); |
87 | 0 | (*func)(ecount_buf, ecount_buf, 1, key, ivec); |
88 | 0 | ++ctr32; |
89 | 0 | CRYPTO_store_u32_be(ivec + 12, ctr32); |
90 | 0 | if (ctr32 == 0) { |
91 | 0 | ctr96_inc(ivec); |
92 | 0 | } |
93 | 0 | while (len--) { |
94 | 0 | out[n] = in[n] ^ ecount_buf[n]; |
95 | 0 | ++n; |
96 | 0 | } |
97 | 0 | } |
98 | |
|
99 | 0 | *num = n; |
100 | 0 | } |