Coverage Report

Created: 2025-02-21 07:11

/rust/registry/src/index.crates.io-6f17d22bba15001f/ring-0.17.8/src/digest/sha2.rs
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2019 Brian Smith.
2
//
3
// Permission to use, copy, modify, and/or distribute this software for any
4
// purpose with or without fee is hereby granted, provided that the above
5
// copyright notice and this permission notice appear in all copies.
6
//
7
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15
use crate::c;
16
use core::{
17
    num::Wrapping,
18
    ops::{Add, AddAssign, BitAnd, BitOr, BitXor, Not, Shr},
19
};
20
21
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm", target_arch = "x86_64")))]
22
pub(super) extern "C" fn sha256_block_data_order(
23
    state: &mut super::State,
24
    data: *const u8,
25
    num: c::size_t,
26
) {
27
    let state = unsafe { &mut state.as32 };
28
    *state = block_data_order(*state, data, num)
29
}
30
31
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm", target_arch = "x86_64")))]
32
pub(super) extern "C" fn sha512_block_data_order(
33
    state: &mut super::State,
34
    data: *const u8,
35
    num: c::size_t,
36
) {
37
    let state = unsafe { &mut state.as64 };
38
    *state = block_data_order(*state, data, num)
39
}
40
41
#[cfg_attr(
42
    any(target_arch = "aarch64", target_arch = "arm", target_arch = "x86_64"),
43
    allow(dead_code)
44
)]
45
#[inline]
46
0
fn block_data_order<S: Sha2>(
47
0
    mut H: [S; CHAINING_WORDS],
48
0
    M: *const u8,
49
0
    num: c::size_t,
50
0
) -> [S; CHAINING_WORDS] {
51
0
    let M = M.cast::<[S::InputBytes; 16]>();
52
0
    let M: &[[S::InputBytes; 16]] = unsafe { core::slice::from_raw_parts(M, num) };
53
54
0
    for M in M {
55
        // FIPS 180-4 {6.2.2, 6.4.2} Step 1
56
        //
57
        // TODO: Use `let W: [S::ZERO; S::ROUNDS]` instead of allocating
58
        // `MAX_ROUNDS` items and then slicing to `K.len()`; depends on
59
        // https://github.com/rust-lang/rust/issues/43408.
60
0
        let mut W = [S::ZERO; MAX_ROUNDS];
61
0
        let W: &[S] = {
62
0
            let W = &mut W[..S::K.len()];
63
0
            for (W, M) in W.iter_mut().zip(M) {
64
0
                *W = S::from_be_bytes(*M);
65
0
            }
66
0
            for t in M.len()..S::K.len() {
67
0
                W[t] = sigma_1(W[t - 2]) + W[t - 7] + sigma_0(W[t - 15]) + W[t - 16]
68
            }
69
70
0
            W
71
0
        };
72
0
73
0
        // FIPS 180-4 {6.2.2, 6.4.2} Step 2
74
0
        let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut h] = H;
75
76
        // FIPS 180-4 {6.2.2, 6.4.2} Step 3
77
0
        for (Kt, Wt) in S::K.iter().zip(W.iter()) {
78
0
            let T1 = h + SIGMA_1(e) + ch(e, f, g) + *Kt + *Wt;
79
0
            let T2 = SIGMA_0(a) + maj(a, b, c);
80
0
            h = g;
81
0
            g = f;
82
0
            f = e;
83
0
            e = d + T1;
84
0
            d = c;
85
0
            c = b;
86
0
            b = a;
87
0
            a = T1 + T2;
88
0
        }
89
90
        // FIPS 180-4 {6.2.2, 6.4.2} Step 4
91
0
        H[0] += a;
92
0
        H[1] += b;
93
0
        H[2] += c;
94
0
        H[3] += d;
95
0
        H[4] += e;
96
0
        H[5] += f;
97
0
        H[6] += g;
98
0
        H[7] += h;
99
    }
100
101
0
    H
102
0
}
103
104
// FIPS 180-4 {4.1.1, 4.1.2, 4.1.3}
105
#[inline(always)]
106
0
pub(super) fn ch<W: Word>(x: W, y: W, z: W) -> W {
107
0
    (x & y) | (!x & z)
108
0
}
109
110
// FIPS 180-4 {4.1.1, 4.1.2, 4.1.3}
111
#[inline(always)]
112
0
pub(super) fn maj<W: Word>(x: W, y: W, z: W) -> W {
113
0
    (x & y) | (x & z) | (y & z)
114
0
}
115
116
// FIPS 180-4 {4.1.2, 4.1.3}
117
#[inline(always)]
118
0
fn SIGMA_0<S: Sha2>(x: S) -> S {
119
0
    x.rotr(S::BIG_SIGMA_0.0) ^ x.rotr(S::BIG_SIGMA_0.1) ^ x.rotr(S::BIG_SIGMA_0.2)
120
0
}
121
122
// FIPS 180-4 {4.1.2, 4.1.3}
123
#[inline(always)]
124
0
fn SIGMA_1<S: Sha2>(x: S) -> S {
125
0
    x.rotr(S::BIG_SIGMA_1.0) ^ x.rotr(S::BIG_SIGMA_1.1) ^ x.rotr(S::BIG_SIGMA_1.2)
126
0
}
127
128
// FIPS 180-4 {4.1.2, 4.1.3}
129
#[inline(always)]
130
0
fn sigma_0<S: Sha2>(x: S) -> S {
131
0
    x.rotr(S::SMALL_SIGMA_0.0) ^ x.rotr(S::SMALL_SIGMA_0.1) ^ (x >> S::SMALL_SIGMA_0.2)
132
0
}
133
134
// FIPS 180-4 {4.1.2, 4.1.3}
135
#[inline(always)]
136
0
fn sigma_1<S: Sha2>(x: S) -> S {
137
0
    x.rotr(S::SMALL_SIGMA_1.0) ^ x.rotr(S::SMALL_SIGMA_1.1) ^ (x >> S::SMALL_SIGMA_1.2)
138
0
}
139
140
// Commonality between SHA-1 and SHA-2 words.
141
pub(super) trait Word:
142
    'static
143
    + Sized
144
    + Copy
145
    + Add<Output = Self>
146
    + AddAssign
147
    + BitAnd<Output = Self>
148
    + BitOr<Output = Self>
149
    + Not<Output = Self>
150
{
151
    const ZERO: Self;
152
153
    type InputBytes: Copy;
154
155
    fn from_be_bytes(input: Self::InputBytes) -> Self;
156
157
    fn rotr(self, count: u32) -> Self;
158
}
159
160
/// A SHA-2 input word.
161
trait Sha2: Word + BitXor<Output = Self> + Shr<usize, Output = Self> {
162
    const BIG_SIGMA_0: (u32, u32, u32);
163
    const BIG_SIGMA_1: (u32, u32, u32);
164
    const SMALL_SIGMA_0: (u32, u32, usize);
165
    const SMALL_SIGMA_1: (u32, u32, usize);
166
167
    const K: &'static [Self];
168
}
169
170
const MAX_ROUNDS: usize = 80;
171
pub(super) const CHAINING_WORDS: usize = 8;
172
173
impl Word for Wrapping<u32> {
174
    const ZERO: Self = Self(0);
175
    type InputBytes = [u8; 4];
176
177
    #[inline(always)]
178
0
    fn from_be_bytes(input: Self::InputBytes) -> Self {
179
0
        Self(u32::from_be_bytes(input))
180
0
    }
181
182
    #[inline(always)]
183
0
    fn rotr(self, count: u32) -> Self {
184
0
        Self(self.0.rotate_right(count))
185
0
    }
186
}
187
188
// SHA-256
189
impl Sha2 for Wrapping<u32> {
190
    // FIPS 180-4 4.1.2
191
    const BIG_SIGMA_0: (u32, u32, u32) = (2, 13, 22);
192
    const BIG_SIGMA_1: (u32, u32, u32) = (6, 11, 25);
193
    const SMALL_SIGMA_0: (u32, u32, usize) = (7, 18, 3);
194
    const SMALL_SIGMA_1: (u32, u32, usize) = (17, 19, 10);
195
196
    // FIPS 180-4 4.2.2
197
    const K: &'static [Self] = &[
198
        Self(0x428a2f98),
199
        Self(0x71374491),
200
        Self(0xb5c0fbcf),
201
        Self(0xe9b5dba5),
202
        Self(0x3956c25b),
203
        Self(0x59f111f1),
204
        Self(0x923f82a4),
205
        Self(0xab1c5ed5),
206
        Self(0xd807aa98),
207
        Self(0x12835b01),
208
        Self(0x243185be),
209
        Self(0x550c7dc3),
210
        Self(0x72be5d74),
211
        Self(0x80deb1fe),
212
        Self(0x9bdc06a7),
213
        Self(0xc19bf174),
214
        Self(0xe49b69c1),
215
        Self(0xefbe4786),
216
        Self(0x0fc19dc6),
217
        Self(0x240ca1cc),
218
        Self(0x2de92c6f),
219
        Self(0x4a7484aa),
220
        Self(0x5cb0a9dc),
221
        Self(0x76f988da),
222
        Self(0x983e5152),
223
        Self(0xa831c66d),
224
        Self(0xb00327c8),
225
        Self(0xbf597fc7),
226
        Self(0xc6e00bf3),
227
        Self(0xd5a79147),
228
        Self(0x06ca6351),
229
        Self(0x14292967),
230
        Self(0x27b70a85),
231
        Self(0x2e1b2138),
232
        Self(0x4d2c6dfc),
233
        Self(0x53380d13),
234
        Self(0x650a7354),
235
        Self(0x766a0abb),
236
        Self(0x81c2c92e),
237
        Self(0x92722c85),
238
        Self(0xa2bfe8a1),
239
        Self(0xa81a664b),
240
        Self(0xc24b8b70),
241
        Self(0xc76c51a3),
242
        Self(0xd192e819),
243
        Self(0xd6990624),
244
        Self(0xf40e3585),
245
        Self(0x106aa070),
246
        Self(0x19a4c116),
247
        Self(0x1e376c08),
248
        Self(0x2748774c),
249
        Self(0x34b0bcb5),
250
        Self(0x391c0cb3),
251
        Self(0x4ed8aa4a),
252
        Self(0x5b9cca4f),
253
        Self(0x682e6ff3),
254
        Self(0x748f82ee),
255
        Self(0x78a5636f),
256
        Self(0x84c87814),
257
        Self(0x8cc70208),
258
        Self(0x90befffa),
259
        Self(0xa4506ceb),
260
        Self(0xbef9a3f7),
261
        Self(0xc67178f2),
262
    ];
263
}
264
265
impl Word for Wrapping<u64> {
266
    const ZERO: Self = Self(0);
267
    type InputBytes = [u8; 8];
268
269
    #[inline(always)]
270
0
    fn from_be_bytes(input: Self::InputBytes) -> Self {
271
0
        Self(u64::from_be_bytes(input))
272
0
    }
273
274
    #[inline(always)]
275
0
    fn rotr(self, count: u32) -> Self {
276
0
        Self(self.0.rotate_right(count))
277
0
    }
278
}
279
280
// SHA-384 and SHA-512
281
impl Sha2 for Wrapping<u64> {
282
    // FIPS 180-4 4.1.3
283
    const BIG_SIGMA_0: (u32, u32, u32) = (28, 34, 39);
284
    const BIG_SIGMA_1: (u32, u32, u32) = (14, 18, 41);
285
    const SMALL_SIGMA_0: (u32, u32, usize) = (1, 8, 7);
286
    const SMALL_SIGMA_1: (u32, u32, usize) = (19, 61, 6);
287
288
    // FIPS 180-4 4.2.3
289
    const K: &'static [Self] = &[
290
        Self(0x428a2f98d728ae22),
291
        Self(0x7137449123ef65cd),
292
        Self(0xb5c0fbcfec4d3b2f),
293
        Self(0xe9b5dba58189dbbc),
294
        Self(0x3956c25bf348b538),
295
        Self(0x59f111f1b605d019),
296
        Self(0x923f82a4af194f9b),
297
        Self(0xab1c5ed5da6d8118),
298
        Self(0xd807aa98a3030242),
299
        Self(0x12835b0145706fbe),
300
        Self(0x243185be4ee4b28c),
301
        Self(0x550c7dc3d5ffb4e2),
302
        Self(0x72be5d74f27b896f),
303
        Self(0x80deb1fe3b1696b1),
304
        Self(0x9bdc06a725c71235),
305
        Self(0xc19bf174cf692694),
306
        Self(0xe49b69c19ef14ad2),
307
        Self(0xefbe4786384f25e3),
308
        Self(0x0fc19dc68b8cd5b5),
309
        Self(0x240ca1cc77ac9c65),
310
        Self(0x2de92c6f592b0275),
311
        Self(0x4a7484aa6ea6e483),
312
        Self(0x5cb0a9dcbd41fbd4),
313
        Self(0x76f988da831153b5),
314
        Self(0x983e5152ee66dfab),
315
        Self(0xa831c66d2db43210),
316
        Self(0xb00327c898fb213f),
317
        Self(0xbf597fc7beef0ee4),
318
        Self(0xc6e00bf33da88fc2),
319
        Self(0xd5a79147930aa725),
320
        Self(0x06ca6351e003826f),
321
        Self(0x142929670a0e6e70),
322
        Self(0x27b70a8546d22ffc),
323
        Self(0x2e1b21385c26c926),
324
        Self(0x4d2c6dfc5ac42aed),
325
        Self(0x53380d139d95b3df),
326
        Self(0x650a73548baf63de),
327
        Self(0x766a0abb3c77b2a8),
328
        Self(0x81c2c92e47edaee6),
329
        Self(0x92722c851482353b),
330
        Self(0xa2bfe8a14cf10364),
331
        Self(0xa81a664bbc423001),
332
        Self(0xc24b8b70d0f89791),
333
        Self(0xc76c51a30654be30),
334
        Self(0xd192e819d6ef5218),
335
        Self(0xd69906245565a910),
336
        Self(0xf40e35855771202a),
337
        Self(0x106aa07032bbd1b8),
338
        Self(0x19a4c116b8d2d0c8),
339
        Self(0x1e376c085141ab53),
340
        Self(0x2748774cdf8eeb99),
341
        Self(0x34b0bcb5e19b48a8),
342
        Self(0x391c0cb3c5c95a63),
343
        Self(0x4ed8aa4ae3418acb),
344
        Self(0x5b9cca4f7763e373),
345
        Self(0x682e6ff3d6b2b8a3),
346
        Self(0x748f82ee5defb2fc),
347
        Self(0x78a5636f43172f60),
348
        Self(0x84c87814a1f0ab72),
349
        Self(0x8cc702081a6439ec),
350
        Self(0x90befffa23631e28),
351
        Self(0xa4506cebde82bde9),
352
        Self(0xbef9a3f7b2c67915),
353
        Self(0xc67178f2e372532b),
354
        Self(0xca273eceea26619c),
355
        Self(0xd186b8c721c0c207),
356
        Self(0xeada7dd6cde0eb1e),
357
        Self(0xf57d4f7fee6ed178),
358
        Self(0x06f067aa72176fba),
359
        Self(0x0a637dc5a2c898a6),
360
        Self(0x113f9804bef90dae),
361
        Self(0x1b710b35131c471b),
362
        Self(0x28db77f523047d84),
363
        Self(0x32caab7b40c72493),
364
        Self(0x3c9ebe0a15c9bebc),
365
        Self(0x431d67c49c100d4c),
366
        Self(0x4cc5d4becb3e42b6),
367
        Self(0x597f299cfc657e2a),
368
        Self(0x5fcb6fab3ad6faec),
369
        Self(0x6c44198c4a475817),
370
    ];
371
}
372
373
#[cfg(any(target_arch = "aarch64", target_arch = "arm", target_arch = "x86_64"))]
374
prefixed_extern! {
375
    pub(super) fn sha256_block_data_order(
376
        state: &mut super::State,
377
        data: *const u8,
378
        num: c::size_t,
379
    );
380
    pub(super) fn sha512_block_data_order(
381
        state: &mut super::State,
382
        data: *const u8,
383
        num: c::size_t,
384
    );
385
}