/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 | | using namespace bssl; |
23 | | |
24 | | static_assert(16 % sizeof(crypto_word_t) == 0, |
25 | | "block cannot be divided into crypto_word_t"); |
26 | | |
27 | | // increment upper 96 bits of 128-bit counter by 1 |
28 | 0 | static void ctr96_inc(uint8_t *counter) { |
29 | 0 | uint32_t n = 12, c = 1; |
30 | |
|
31 | 0 | do { |
32 | 0 | --n; |
33 | 0 | c += counter[n]; |
34 | 0 | counter[n] = (uint8_t) c; |
35 | 0 | c >>= 8; |
36 | 0 | } while (n); |
37 | 0 | } |
38 | | |
39 | | void bssl::CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, |
40 | | size_t len, const AES_KEY *key, |
41 | | uint8_t ivec[16], uint8_t ecount_buf[16], |
42 | 0 | unsigned int *num, ctr128_f func) { |
43 | 0 | unsigned int n, ctr32; |
44 | |
|
45 | 0 | assert(key && ecount_buf && num); |
46 | 0 | assert(len == 0 || (in && out)); |
47 | 0 | assert(*num < 16); |
48 | | |
49 | 0 | n = *num; |
50 | |
|
51 | 0 | while (n && len) { |
52 | 0 | *(out++) = *(in++) ^ ecount_buf[n]; |
53 | 0 | --len; |
54 | 0 | n = (n + 1) % 16; |
55 | 0 | } |
56 | |
|
57 | 0 | ctr32 = CRYPTO_load_u32_be(ivec + 12); |
58 | 0 | while (len >= 16) { |
59 | 0 | size_t blocks = len / 16; |
60 | | // 1<<28 is just a not-so-small yet not-so-large number... |
61 | | // Below condition is practically never met, but it has to |
62 | | // be checked for code correctness. |
63 | 0 | if (sizeof(size_t) > sizeof(unsigned int) && blocks > (1U << 28)) { |
64 | 0 | blocks = (1U << 28); |
65 | 0 | } |
66 | | // As (*func) operates on 32-bit counter, caller |
67 | | // has to handle overflow. 'if' below detects the |
68 | | // overflow, which is then handled by limiting the |
69 | | // amount of blocks to the exact overflow point... |
70 | 0 | ctr32 += (uint32_t)blocks; |
71 | 0 | if (ctr32 < blocks) { |
72 | 0 | blocks -= ctr32; |
73 | 0 | ctr32 = 0; |
74 | 0 | } |
75 | 0 | (*func)(in, out, blocks, key, ivec); |
76 | | // (*func) does not update ivec, caller does: |
77 | 0 | CRYPTO_store_u32_be(ivec + 12, ctr32); |
78 | | // ... overflow was detected, propagate carry. |
79 | 0 | if (ctr32 == 0) { |
80 | 0 | ctr96_inc(ivec); |
81 | 0 | } |
82 | 0 | blocks *= 16; |
83 | 0 | len -= blocks; |
84 | 0 | out += blocks; |
85 | 0 | in += blocks; |
86 | 0 | } |
87 | 0 | if (len) { |
88 | 0 | OPENSSL_memset(ecount_buf, 0, 16); |
89 | 0 | (*func)(ecount_buf, ecount_buf, 1, key, ivec); |
90 | 0 | ++ctr32; |
91 | 0 | CRYPTO_store_u32_be(ivec + 12, ctr32); |
92 | 0 | if (ctr32 == 0) { |
93 | 0 | ctr96_inc(ivec); |
94 | 0 | } |
95 | 0 | while (len--) { |
96 | 0 | out[n] = in[n] ^ ecount_buf[n]; |
97 | 0 | ++n; |
98 | 0 | } |
99 | 0 | } |
100 | |
|
101 | 0 | *num = n; |
102 | 0 | } |