Skip to main content

aws_lc_rs/digest/
sha.rs

1// Copyright 2015-2022 Brian Smith.
2// SPDX-License-Identifier: ISC
3// Modifications copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4// SPDX-License-Identifier: Apache-2.0 OR ISC
5
6use crate::digest::{Algorithm, AlgorithmID, Context};
7
8/// The length of a block for SHA-1, in bytes.
9const SHA1_BLOCK_LEN: usize = 512 / 8;
10
11/// The length of the output of SHA-1, in bytes.
12pub const SHA1_OUTPUT_LEN: usize = 160 / 8;
13
14/// The length of the output of SHA-224, in bytes.
15pub const SHA224_OUTPUT_LEN: usize = 224 / 8;
16
17/// The length of the output of SHA-256, in bytes.
18pub const SHA256_OUTPUT_LEN: usize = 256 / 8;
19
20/// The length of a block for SHA-256-based algorithms, in bytes.
21const SHA256_BLOCK_LEN: usize = 512 / 8;
22
23/// The length of the output of SHA-384, in bytes.
24pub const SHA384_OUTPUT_LEN: usize = 384 / 8;
25
26/// The length of the output of SHA-512, in bytes.
27pub const SHA512_OUTPUT_LEN: usize = 512 / 8;
28
29/// The length of the output of SHA-512/256, in bytes.
30pub const SHA512_256_OUTPUT_LEN: usize = 256 / 8;
31
32/// The length of a block for SHA-512-based algorithms, in bytes.
33const SHA512_BLOCK_LEN: usize = 1024 / 8;
34
35/// The length of a block for SHA3-256-based algorithms, in bytes.
36const SHA3_256_BLOCK_LEN: usize = 136;
37
38/// The length of a block for SHA3-384-based algorithms, in bytes.
39const SHA3_384_BLOCK_LEN: usize = 104;
40
41/// The length of a block for SHA3-512-based algorithms, in bytes.
42const SHA3_512_BLOCK_LEN: usize = 72;
43
44/// The length of the output of SHA3-256 in bytes.
45pub const SHA3_256_OUTPUT_LEN: usize = 256 / 8;
46
47/// The length of the output of SHA3-384, in bytes.
48pub const SHA3_384_OUTPUT_LEN: usize = 384 / 8;
49
50/// The length of the output of SHA3-512, in bytes.
51pub const SHA3_512_OUTPUT_LEN: usize = 512 / 8;
52
53/// The length of a block for Keccak-256, in bytes.
54#[cfg(all(not(feature = "fips"), feature = "unstable"))]
55const KECCAK256_BLOCK_LEN: usize = SHA3_256_BLOCK_LEN;
56
57/// The length of the output of Keccak-256, in bytes.
58#[cfg(all(not(feature = "fips"), feature = "unstable"))]
59#[cfg_attr(aws_lc_rs_docsrs, doc(cfg(not(feature = "fips"))))]
60pub const KECCAK256_OUTPUT_LEN: usize = 256 / 8;
61
62/// SHA-1, SHA-224, and SHA-256 are limited to an input size of 2^64-1 bits.
63/// SHA-384, SHA-512, and SHA-512/256 are limited to an input size of 2^128-1 bits according to the spec.
64/// u64 is more than sufficient enough for practical usecases, so we limit the input length to 2^64-1 bits.
65#[allow(clippy::cast_possible_truncation)]
66const DIGEST_MAX_INPUT_LEN: u64 = u64::MAX;
67
68/// SHA-1 as specified in [FIPS 180-4]. Deprecated.
69///
70/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
71#[allow(deprecated)]
72pub const SHA1_FOR_LEGACY_USE_ONLY: Algorithm = Algorithm {
73    output_len: SHA1_OUTPUT_LEN,
74    chaining_len: SHA1_OUTPUT_LEN,
75    block_len: SHA1_BLOCK_LEN,
76    max_input_len: DIGEST_MAX_INPUT_LEN,
77
78    one_shot_hash: sha1_digest,
79
80    id: AlgorithmID::SHA1,
81};
82
83/// SHA-224 as specified in [FIPS 180-4].
84///
85/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
86#[allow(deprecated)]
87pub const SHA224: Algorithm = Algorithm {
88    output_len: SHA224_OUTPUT_LEN,
89
90    // The chaining length is equivalent to the length before truncation.
91    // SHA-224 is truncated from 256 bits so the chaining length is 256 bits, or 32 bytes.
92    chaining_len: SHA256_OUTPUT_LEN,
93    block_len: SHA256_BLOCK_LEN,
94    max_input_len: DIGEST_MAX_INPUT_LEN,
95
96    one_shot_hash: sha224_digest,
97
98    id: AlgorithmID::SHA224,
99};
100
101/// SHA-256 as specified in [FIPS 180-4].
102///
103/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
104#[allow(deprecated)]
105pub const SHA256: Algorithm = Algorithm {
106    output_len: SHA256_OUTPUT_LEN,
107    chaining_len: SHA256_OUTPUT_LEN,
108    block_len: SHA256_BLOCK_LEN,
109    max_input_len: DIGEST_MAX_INPUT_LEN,
110
111    one_shot_hash: sha256_digest,
112
113    id: AlgorithmID::SHA256,
114};
115
116/// SHA-384 as specified in [FIPS 180-4].
117///
118/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
119#[allow(deprecated)]
120pub const SHA384: Algorithm = Algorithm {
121    output_len: SHA384_OUTPUT_LEN,
122
123    // The chaining length is equivalent to the length before truncation.
124    // SHA-384 is truncated from 512 bits so the chaining length is 512 bits, or 64 bytes.
125    chaining_len: SHA512_OUTPUT_LEN,
126    block_len: SHA512_BLOCK_LEN,
127    max_input_len: DIGEST_MAX_INPUT_LEN,
128
129    one_shot_hash: sha384_digest,
130
131    id: AlgorithmID::SHA384,
132};
133
134/// SHA-512 as specified in [FIPS 180-4].
135///
136/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
137#[allow(deprecated)]
138pub const SHA512: Algorithm = Algorithm {
139    output_len: SHA512_OUTPUT_LEN,
140    chaining_len: SHA512_OUTPUT_LEN,
141    block_len: SHA512_BLOCK_LEN,
142    max_input_len: DIGEST_MAX_INPUT_LEN,
143
144    one_shot_hash: sha512_digest,
145
146    id: AlgorithmID::SHA512,
147};
148
149/// SHA-512/256 as specified in [FIPS 180-4].
150///
151/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
152#[allow(deprecated)]
153pub const SHA512_256: Algorithm = Algorithm {
154    output_len: SHA512_256_OUTPUT_LEN,
155    chaining_len: SHA512_OUTPUT_LEN,
156    block_len: SHA512_BLOCK_LEN,
157    max_input_len: DIGEST_MAX_INPUT_LEN,
158
159    one_shot_hash: sha512_256_digest,
160
161    id: AlgorithmID::SHA512_256,
162};
163
164/// SHA3-256 as specified in [FIPS 202].
165///
166/// [FIPS 202]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
167#[allow(deprecated)]
168pub const SHA3_256: Algorithm = Algorithm {
169    output_len: SHA3_256_OUTPUT_LEN,
170    chaining_len: SHA3_256_OUTPUT_LEN,
171    block_len: SHA3_256_BLOCK_LEN,
172    max_input_len: DIGEST_MAX_INPUT_LEN,
173
174    one_shot_hash: sha3_256_digest,
175
176    id: AlgorithmID::SHA3_256,
177};
178
179/// SHA3-384 as specified in [FIPS 202].
180///
181/// [FIPS 202]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
182#[allow(deprecated)]
183pub const SHA3_384: Algorithm = Algorithm {
184    output_len: SHA3_384_OUTPUT_LEN,
185    chaining_len: SHA3_384_OUTPUT_LEN,
186    block_len: SHA3_384_BLOCK_LEN,
187    max_input_len: DIGEST_MAX_INPUT_LEN,
188
189    one_shot_hash: sha3_384_digest,
190
191    id: AlgorithmID::SHA3_384,
192};
193
194/// SHA3-512 as specified in [FIPS 202].
195///
196/// [FIPS 202]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
197#[allow(deprecated)]
198pub const SHA3_512: Algorithm = Algorithm {
199    output_len: SHA3_512_OUTPUT_LEN,
200    chaining_len: SHA3_512_OUTPUT_LEN,
201    block_len: SHA3_512_BLOCK_LEN,
202    max_input_len: DIGEST_MAX_INPUT_LEN,
203
204    one_shot_hash: sha3_512_digest,
205
206    id: AlgorithmID::SHA3_512,
207};
208
209/// Keccak-256, the original Keccak variant used by Ethereum.
210///
211/// Not SHA3-256: it applies the original `0x01` padding rather than the
212/// [FIPS 202] `0x06` padding, so the digests differ. Prefer [`SHA3_256`].
213///
214/// Unavailable with the `fips` feature: `aws-lc-fips-sys` does not expose
215/// `EVP_keccak256`. Reached through [`crate::unstable::digest`], so that the
216/// stable `digest` API does not change when `fips` is enabled.
217///
218/// [FIPS 202]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
219//
220// # FIPS
221// Keccak-256 is not FIPS-approved.
222//
223// When `aws-lc-fips-sys` supports Keccak-256, move it to the stable API: re-export it
224// from `digest` (deprecated alias in `unstable::digest`), make `mod sha` private again,
225// drop the Keccak-256 `cfg`/`doc(cfg)` gates, and add a `digest/tests/fips.rs` case
226// asserting `NonApproved`.
227#[cfg(all(not(feature = "fips"), feature = "unstable"))]
228#[cfg_attr(aws_lc_rs_docsrs, doc(cfg(not(feature = "fips"))))]
229#[allow(deprecated)]
230pub const KECCAK256: Algorithm = Algorithm {
231    output_len: KECCAK256_OUTPUT_LEN,
232    chaining_len: KECCAK256_OUTPUT_LEN,
233    block_len: KECCAK256_BLOCK_LEN,
234    max_input_len: DIGEST_MAX_INPUT_LEN,
235
236    one_shot_hash: keccak256_digest,
237
238    id: AlgorithmID::KECCAK256,
239};
240
241fn sha1_digest(msg: &[u8], output: &mut [u8]) {
242    unsafe {
243        aws_lc::SHA1(msg.as_ptr(), msg.len(), output.as_mut_ptr());
244    }
245}
246
247fn sha224_digest(msg: &[u8], output: &mut [u8]) {
248    unsafe {
249        aws_lc::SHA224(msg.as_ptr(), msg.len(), output.as_mut_ptr());
250    }
251}
252
253fn sha256_digest(msg: &[u8], output: &mut [u8]) {
254    unsafe {
255        aws_lc::SHA256(msg.as_ptr(), msg.len(), output.as_mut_ptr());
256    }
257}
258
259fn sha384_digest(msg: &[u8], output: &mut [u8]) {
260    unsafe {
261        aws_lc::SHA384(msg.as_ptr(), msg.len(), output.as_mut_ptr());
262    }
263}
264
265fn sha512_digest(msg: &[u8], output: &mut [u8]) {
266    unsafe {
267        aws_lc::SHA512(msg.as_ptr(), msg.len(), output.as_mut_ptr());
268    }
269}
270
271fn sha512_256_digest(msg: &[u8], output: &mut [u8]) {
272    unsafe {
273        aws_lc::SHA512_256(msg.as_ptr(), msg.len(), output.as_mut_ptr());
274    }
275}
276
277fn sha3_256_digest(msg: &[u8], output: &mut [u8]) {
278    let mut ctx = Context::new(&SHA3_256);
279    ctx.update(msg);
280    let digest = ctx.finish();
281    output[0..SHA3_256_OUTPUT_LEN].copy_from_slice(digest.as_ref());
282}
283
284fn sha3_384_digest(msg: &[u8], output: &mut [u8]) {
285    let mut ctx = Context::new(&SHA3_384);
286    ctx.update(msg);
287    let digest = ctx.finish();
288    output[0..SHA3_384_OUTPUT_LEN].copy_from_slice(digest.as_ref());
289}
290
291fn sha3_512_digest(msg: &[u8], output: &mut [u8]) {
292    let mut ctx = Context::new(&SHA3_512);
293    ctx.update(msg);
294    let digest = ctx.finish();
295    output[0..SHA3_512_OUTPUT_LEN].copy_from_slice(digest.as_ref());
296}
297
298#[cfg(all(not(feature = "fips"), feature = "unstable"))]
299fn keccak256_digest(msg: &[u8], output: &mut [u8]) {
300    let mut ctx = Context::new(&KECCAK256);
301    ctx.update(msg);
302    let digest = ctx.finish();
303    output[0..KECCAK256_OUTPUT_LEN].copy_from_slice(digest.as_ref());
304}