Coverage Report

Created: 2024-11-21 07:03

/src/nss-nspr/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
13.0k
{
33
13.0k
    uint32_t sta = st[a];
34
13.0k
    uint32_t stb0 = st[b];
35
13.0k
    uint32_t std0 = st[d];
36
13.0k
    uint32_t sta10 = sta + stb0;
37
13.0k
    uint32_t std10 = std0 ^ sta10;
38
13.0k
    uint32_t std2 = std10 << (uint32_t)16U | std10 >> (uint32_t)16U;
39
13.0k
    st[a] = sta10;
40
13.0k
    st[d] = std2;
41
13.0k
    uint32_t sta0 = st[c];
42
13.0k
    uint32_t stb1 = st[d];
43
13.0k
    uint32_t std3 = st[b];
44
13.0k
    uint32_t sta11 = sta0 + stb1;
45
13.0k
    uint32_t std11 = std3 ^ sta11;
46
13.0k
    uint32_t std20 = std11 << (uint32_t)12U | std11 >> (uint32_t)20U;
47
13.0k
    st[c] = sta11;
48
13.0k
    st[b] = std20;
49
13.0k
    uint32_t sta2 = st[a];
50
13.0k
    uint32_t stb2 = st[b];
51
13.0k
    uint32_t std4 = st[d];
52
13.0k
    uint32_t sta12 = sta2 + stb2;
53
13.0k
    uint32_t std12 = std4 ^ sta12;
54
13.0k
    uint32_t std21 = std12 << (uint32_t)8U | std12 >> (uint32_t)24U;
55
13.0k
    st[a] = sta12;
56
13.0k
    st[d] = std21;
57
13.0k
    uint32_t sta3 = st[c];
58
13.0k
    uint32_t stb = st[d];
59
13.0k
    uint32_t std = st[b];
60
13.0k
    uint32_t sta1 = sta3 + stb;
61
13.0k
    uint32_t std1 = std ^ sta1;
62
13.0k
    uint32_t std22 = std1 << (uint32_t)7U | std1 >> (uint32_t)25U;
63
13.0k
    st[c] = sta1;
64
13.0k
    st[b] = std22;
65
13.0k
}
66
67
static inline void
68
double_round(uint32_t *st)
69
1.63k
{
70
1.63k
    quarter_round(st, (uint32_t)0U, (uint32_t)4U, (uint32_t)8U, (uint32_t)12U);
71
1.63k
    quarter_round(st, (uint32_t)1U, (uint32_t)5U, (uint32_t)9U, (uint32_t)13U);
72
1.63k
    quarter_round(st, (uint32_t)2U, (uint32_t)6U, (uint32_t)10U, (uint32_t)14U);
73
1.63k
    quarter_round(st, (uint32_t)3U, (uint32_t)7U, (uint32_t)11U, (uint32_t)15U);
74
1.63k
    quarter_round(st, (uint32_t)0U, (uint32_t)5U, (uint32_t)10U, (uint32_t)15U);
75
1.63k
    quarter_round(st, (uint32_t)1U, (uint32_t)6U, (uint32_t)11U, (uint32_t)12U);
76
1.63k
    quarter_round(st, (uint32_t)2U, (uint32_t)7U, (uint32_t)8U, (uint32_t)13U);
77
1.63k
    quarter_round(st, (uint32_t)3U, (uint32_t)4U, (uint32_t)9U, (uint32_t)14U);
78
1.63k
}
79
80
static inline void
81
rounds(uint32_t *st)
82
163
{
83
163
    double_round(st);
84
163
    double_round(st);
85
163
    double_round(st);
86
163
    double_round(st);
87
163
    double_round(st);
88
163
    double_round(st);
89
163
    double_round(st);
90
163
    double_round(st);
91
163
    double_round(st);
92
163
    double_round(st);
93
163
}
94
95
static inline void
96
chacha20_core(uint32_t *k, uint32_t *ctx, uint32_t ctr)
97
163
{
98
163
    memcpy(k, ctx, (uint32_t)16U * sizeof(uint32_t));
99
163
    uint32_t ctr_u32 = ctr;
100
163
    k[12U] = k[12U] + ctr_u32;
101
163
    rounds(k);
102
163
    KRML_MAYBE_FOR16(i,
103
163
                     (uint32_t)0U,
104
163
                     (uint32_t)16U,
105
163
                     (uint32_t)1U,
106
163
                     uint32_t *os = k;
107
163
                     uint32_t x = k[i] + ctx[i];
108
163
                     os[i] = x;);
109
163
    k[12U] = k[12U] + ctr_u32;
110
163
}
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
156
{
118
156
    KRML_MAYBE_FOR4(i,
119
156
                    (uint32_t)0U,
120
156
                    (uint32_t)4U,
121
156
                    (uint32_t)1U,
122
156
                    uint32_t *os = ctx;
123
156
                    uint32_t x = chacha20_constants[i];
124
156
                    os[i] = x;);
125
156
    KRML_MAYBE_FOR8(i,
126
156
                    (uint32_t)0U,
127
156
                    (uint32_t)8U,
128
156
                    (uint32_t)1U,
129
156
                    uint32_t *os = ctx + (uint32_t)4U;
130
156
                    uint8_t *bj = k + i * (uint32_t)4U;
131
156
                    uint32_t u = load32_le(bj);
132
156
                    uint32_t r = u;
133
156
                    uint32_t x = r;
134
156
                    os[i] = x;);
135
156
    ctx[12U] = ctr;
136
156
    KRML_MAYBE_FOR3(i,
137
156
                    (uint32_t)0U,
138
156
                    (uint32_t)3U,
139
156
                    (uint32_t)1U,
140
156
                    uint32_t *os = ctx + (uint32_t)13U;
141
156
                    uint8_t *bj = n + i * (uint32_t)4U;
142
156
                    uint32_t u = load32_le(bj);
143
156
                    uint32_t r = u;
144
156
                    uint32_t x = r;
145
156
                    os[i] = x;);
146
156
}
147
148
static void
149
chacha20_encrypt_block(uint32_t *ctx, uint8_t *out, uint32_t incr, uint8_t *text)
150
163
{
151
163
    uint32_t k[16U] = { 0U };
152
163
    chacha20_core(k, ctx, incr);
153
163
    uint32_t bl[16U] = { 0U };
154
163
    KRML_MAYBE_FOR16(i,
155
163
                     (uint32_t)0U,
156
163
                     (uint32_t)16U,
157
163
                     (uint32_t)1U,
158
163
                     uint32_t *os = bl;
159
163
                     uint8_t *bj = text + i * (uint32_t)4U;
160
163
                     uint32_t u = load32_le(bj);
161
163
                     uint32_t r = u;
162
163
                     uint32_t x = r;
163
163
                     os[i] = x;);
164
163
    KRML_MAYBE_FOR16(i,
165
163
                     (uint32_t)0U,
166
163
                     (uint32_t)16U,
167
163
                     (uint32_t)1U,
168
163
                     uint32_t *os = bl;
169
163
                     uint32_t x = bl[i] ^ k[i];
170
163
                     os[i] = x;);
171
163
    KRML_MAYBE_FOR16(i,
172
163
                     (uint32_t)0U,
173
163
                     (uint32_t)16U,
174
163
                     (uint32_t)1U,
175
163
                     store32_le(out + i * (uint32_t)4U, bl[i]););
176
163
}
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
154
{
181
154
    uint8_t plain[64U] = { 0U };
182
154
    memcpy(plain, text, len * sizeof(uint8_t));
183
154
    chacha20_encrypt_block(ctx, plain, incr, plain);
184
154
    memcpy(out, plain, len * sizeof(uint8_t));
185
154
}
186
187
void
188
Hacl_Impl_Chacha20_chacha20_update(uint32_t *ctx, uint32_t len, uint8_t *out, uint8_t *text)
189
156
{
190
156
    uint32_t rem = len % (uint32_t)64U;
191
156
    uint32_t nb = len / (uint32_t)64U;
192
156
    uint32_t rem1 = len % (uint32_t)64U;
193
165
    for (uint32_t i = (uint32_t)0U; i < nb; i++) {
194
9
        chacha20_encrypt_block(ctx, out + i * (uint32_t)64U, i, text + i * (uint32_t)64U);
195
9
    }
196
156
    if (rem1 > (uint32_t)0U) {
197
154
        chacha20_encrypt_last(ctx, rem, out + nb * (uint32_t)64U, nb, text + nb * (uint32_t)64U);
198
154
    }
199
156
}
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
156
{
210
156
    uint32_t ctx[16U] = { 0U };
211
156
    Hacl_Impl_Chacha20_chacha20_init(ctx, key, n, ctr);
212
156
    Hacl_Impl_Chacha20_chacha20_update(ctx, len, out, text);
213
156
}
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
}