Coverage Report

Created: 2024-05-20 06:23

/src/nss/lib/freebl/verified/Hacl_Chacha20.c
Line
Count
Source (jump to first uncovered line)
1
/* MIT License
2
 *
3
 * Copyright (c) 2016-2022 INRIA, CMU and Microsoft Corporation
4
 * Copyright (c) 2022-2023 HACL* Contributors
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in all
14
 * copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
 * SOFTWARE.
23
 */
24
25
#include "internal/Hacl_Chacha20.h"
26
27
const uint32_t
28
    Hacl_Impl_Chacha20_Vec_chacha20_constants[4U] = { (uint32_t)0x61707865U, (uint32_t)0x3320646eU, (uint32_t)0x79622d32U, (uint32_t)0x6b206574U };
29
30
static inline void
31
quarter_round(uint32_t *st, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
32
12.5M
{
33
12.5M
    uint32_t sta = st[a];
34
12.5M
    uint32_t stb0 = st[b];
35
12.5M
    uint32_t std0 = st[d];
36
12.5M
    uint32_t sta10 = sta + stb0;
37
12.5M
    uint32_t std10 = std0 ^ sta10;
38
12.5M
    uint32_t std2 = std10 << (uint32_t)16U | std10 >> (uint32_t)16U;
39
12.5M
    st[a] = sta10;
40
12.5M
    st[d] = std2;
41
12.5M
    uint32_t sta0 = st[c];
42
12.5M
    uint32_t stb1 = st[d];
43
12.5M
    uint32_t std3 = st[b];
44
12.5M
    uint32_t sta11 = sta0 + stb1;
45
12.5M
    uint32_t std11 = std3 ^ sta11;
46
12.5M
    uint32_t std20 = std11 << (uint32_t)12U | std11 >> (uint32_t)20U;
47
12.5M
    st[c] = sta11;
48
12.5M
    st[b] = std20;
49
12.5M
    uint32_t sta2 = st[a];
50
12.5M
    uint32_t stb2 = st[b];
51
12.5M
    uint32_t std4 = st[d];
52
12.5M
    uint32_t sta12 = sta2 + stb2;
53
12.5M
    uint32_t std12 = std4 ^ sta12;
54
12.5M
    uint32_t std21 = std12 << (uint32_t)8U | std12 >> (uint32_t)24U;
55
12.5M
    st[a] = sta12;
56
12.5M
    st[d] = std21;
57
12.5M
    uint32_t sta3 = st[c];
58
12.5M
    uint32_t stb = st[d];
59
12.5M
    uint32_t std = st[b];
60
12.5M
    uint32_t sta1 = sta3 + stb;
61
12.5M
    uint32_t std1 = std ^ sta1;
62
12.5M
    uint32_t std22 = std1 << (uint32_t)7U | std1 >> (uint32_t)25U;
63
12.5M
    st[c] = sta1;
64
12.5M
    st[b] = std22;
65
12.5M
}
66
67
static inline void
68
double_round(uint32_t *st)
69
1.57M
{
70
1.57M
    quarter_round(st, (uint32_t)0U, (uint32_t)4U, (uint32_t)8U, (uint32_t)12U);
71
1.57M
    quarter_round(st, (uint32_t)1U, (uint32_t)5U, (uint32_t)9U, (uint32_t)13U);
72
1.57M
    quarter_round(st, (uint32_t)2U, (uint32_t)6U, (uint32_t)10U, (uint32_t)14U);
73
1.57M
    quarter_round(st, (uint32_t)3U, (uint32_t)7U, (uint32_t)11U, (uint32_t)15U);
74
1.57M
    quarter_round(st, (uint32_t)0U, (uint32_t)5U, (uint32_t)10U, (uint32_t)15U);
75
1.57M
    quarter_round(st, (uint32_t)1U, (uint32_t)6U, (uint32_t)11U, (uint32_t)12U);
76
1.57M
    quarter_round(st, (uint32_t)2U, (uint32_t)7U, (uint32_t)8U, (uint32_t)13U);
77
1.57M
    quarter_round(st, (uint32_t)3U, (uint32_t)4U, (uint32_t)9U, (uint32_t)14U);
78
1.57M
}
79
80
static inline void
81
rounds(uint32_t *st)
82
157k
{
83
157k
    double_round(st);
84
157k
    double_round(st);
85
157k
    double_round(st);
86
157k
    double_round(st);
87
157k
    double_round(st);
88
157k
    double_round(st);
89
157k
    double_round(st);
90
157k
    double_round(st);
91
157k
    double_round(st);
92
157k
    double_round(st);
93
157k
}
94
95
static inline void
96
chacha20_core(uint32_t *k, uint32_t *ctx, uint32_t ctr)
97
157k
{
98
157k
    memcpy(k, ctx, (uint32_t)16U * sizeof(uint32_t));
99
157k
    uint32_t ctr_u32 = ctr;
100
157k
    k[12U] = k[12U] + ctr_u32;
101
157k
    rounds(k);
102
157k
    KRML_MAYBE_FOR16(i,
103
157k
                     (uint32_t)0U,
104
157k
                     (uint32_t)16U,
105
157k
                     (uint32_t)1U,
106
157k
                     uint32_t *os = k;
107
157k
                     uint32_t x = k[i] + ctx[i];
108
157k
                     os[i] = x;);
109
157k
    k[12U] = k[12U] + ctr_u32;
110
157k
}
111
112
static const uint32_t
113
    chacha20_constants[4U] = { (uint32_t)0x61707865U, (uint32_t)0x3320646eU, (uint32_t)0x79622d32U, (uint32_t)0x6b206574U };
114
115
void
116
Hacl_Impl_Chacha20_chacha20_init(uint32_t *ctx, uint8_t *k, uint8_t *n, uint32_t ctr)
117
152k
{
118
152k
    KRML_MAYBE_FOR4(i,
119
152k
                    (uint32_t)0U,
120
152k
                    (uint32_t)4U,
121
152k
                    (uint32_t)1U,
122
152k
                    uint32_t *os = ctx;
123
152k
                    uint32_t x = chacha20_constants[i];
124
152k
                    os[i] = x;);
125
152k
    KRML_MAYBE_FOR8(i,
126
152k
                    (uint32_t)0U,
127
152k
                    (uint32_t)8U,
128
152k
                    (uint32_t)1U,
129
152k
                    uint32_t *os = ctx + (uint32_t)4U;
130
152k
                    uint8_t *bj = k + i * (uint32_t)4U;
131
152k
                    uint32_t u = load32_le(bj);
132
152k
                    uint32_t r = u;
133
152k
                    uint32_t x = r;
134
152k
                    os[i] = x;);
135
152k
    ctx[12U] = ctr;
136
152k
    KRML_MAYBE_FOR3(i,
137
152k
                    (uint32_t)0U,
138
152k
                    (uint32_t)3U,
139
152k
                    (uint32_t)1U,
140
152k
                    uint32_t *os = ctx + (uint32_t)13U;
141
152k
                    uint8_t *bj = n + i * (uint32_t)4U;
142
152k
                    uint32_t u = load32_le(bj);
143
152k
                    uint32_t r = u;
144
152k
                    uint32_t x = r;
145
152k
                    os[i] = x;);
146
152k
}
147
148
static void
149
chacha20_encrypt_block(uint32_t *ctx, uint8_t *out, uint32_t incr, uint8_t *text)
150
157k
{
151
157k
    uint32_t k[16U] = { 0U };
152
157k
    chacha20_core(k, ctx, incr);
153
157k
    uint32_t bl[16U] = { 0U };
154
157k
    KRML_MAYBE_FOR16(i,
155
157k
                     (uint32_t)0U,
156
157k
                     (uint32_t)16U,
157
157k
                     (uint32_t)1U,
158
157k
                     uint32_t *os = bl;
159
157k
                     uint8_t *bj = text + i * (uint32_t)4U;
160
157k
                     uint32_t u = load32_le(bj);
161
157k
                     uint32_t r = u;
162
157k
                     uint32_t x = r;
163
157k
                     os[i] = x;);
164
157k
    KRML_MAYBE_FOR16(i,
165
157k
                     (uint32_t)0U,
166
157k
                     (uint32_t)16U,
167
157k
                     (uint32_t)1U,
168
157k
                     uint32_t *os = bl;
169
157k
                     uint32_t x = bl[i] ^ k[i];
170
157k
                     os[i] = x;);
171
157k
    KRML_MAYBE_FOR16(i,
172
157k
                     (uint32_t)0U,
173
157k
                     (uint32_t)16U,
174
157k
                     (uint32_t)1U,
175
157k
                     store32_le(out + i * (uint32_t)4U, bl[i]););
176
157k
}
177
178
static inline void
179
chacha20_encrypt_last(uint32_t *ctx, uint32_t len, uint8_t *out, uint32_t incr, uint8_t *text)
180
152k
{
181
152k
    uint8_t plain[64U] = { 0U };
182
152k
    memcpy(plain, text, len * sizeof(uint8_t));
183
152k
    chacha20_encrypt_block(ctx, plain, incr, plain);
184
152k
    memcpy(out, plain, len * sizeof(uint8_t));
185
152k
}
186
187
void
188
Hacl_Impl_Chacha20_chacha20_update(uint32_t *ctx, uint32_t len, uint8_t *out, uint8_t *text)
189
152k
{
190
152k
    uint32_t rem = len % (uint32_t)64U;
191
152k
    uint32_t nb = len / (uint32_t)64U;
192
152k
    uint32_t rem1 = len % (uint32_t)64U;
193
157k
    for (uint32_t i = (uint32_t)0U; i < nb; i++) {
194
4.79k
        chacha20_encrypt_block(ctx, out + i * (uint32_t)64U, i, text + i * (uint32_t)64U);
195
4.79k
    }
196
152k
    if (rem1 > (uint32_t)0U) {
197
152k
        chacha20_encrypt_last(ctx, rem, out + nb * (uint32_t)64U, nb, text + nb * (uint32_t)64U);
198
152k
    }
199
152k
}
200
201
void
202
Hacl_Chacha20_chacha20_encrypt(
203
    uint32_t len,
204
    uint8_t *out,
205
    uint8_t *text,
206
    uint8_t *key,
207
    uint8_t *n,
208
    uint32_t ctr)
209
152k
{
210
152k
    uint32_t ctx[16U] = { 0U };
211
152k
    Hacl_Impl_Chacha20_chacha20_init(ctx, key, n, ctr);
212
152k
    Hacl_Impl_Chacha20_chacha20_update(ctx, len, out, text);
213
152k
}
214
215
void
216
Hacl_Chacha20_chacha20_decrypt(
217
    uint32_t len,
218
    uint8_t *out,
219
    uint8_t *cipher,
220
    uint8_t *key,
221
    uint8_t *n,
222
    uint32_t ctr)
223
0
{
224
0
    uint32_t ctx[16U] = { 0U };
225
0
    Hacl_Impl_Chacha20_chacha20_init(ctx, key, n, ctr);
226
0
    Hacl_Impl_Chacha20_chacha20_update(ctx, len, out, cipher);
227
0
}