script/dom/subtlecrypto/
cshake_operation.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use digest::{ExtendableOutput, Update};
6use sha3::{CShake128, CShake128Core, CShake256, CShake256Core};
7
8use crate::dom::bindings::error::Error;
9use crate::dom::subtlecrypto::{ALG_CSHAKE_128, ALG_CSHAKE_256, SubtleCShakeParams};
10
11/// <https://wicg.github.io/webcrypto-modern-algos/#cshake-operations-digest>
12pub(crate) fn digest(
13    normalized_algorithm: &SubtleCShakeParams,
14    message: &[u8],
15) -> Result<Vec<u8>, Error> {
16    // Step 1. Let length be the length member of normalizedAlgorithm.
17    let length = normalized_algorithm.length as usize;
18
19    // Step 2. Let functionName be the functionName member of normalizedAlgorithm if present or the
20    // empty octet string otherwise.
21    let function_name = normalized_algorithm.function_name.as_deref().unwrap_or(&[]);
22
23    // Step 3. Let customization be the customization member of normalizedAlgorithm if present or
24    // the empty octet string otherwise.
25    let customization = normalized_algorithm.customization.as_deref().unwrap_or(&[]);
26
27    // Step 4.
28    // If the name member of normalizedAlgorithm is a case-sensitive string match for "cSHAKE128":
29    //     Let result be the result of performing the cSHAKE128 function defined in Section 3 of
30    //     [NIST-SP800-185] using message as the X input parameter, length as the L input
31    //     parameter, functionName as the N input parameter, and customization as the S input
32    //     parameter.
33    // If the name member of normalizedAlgorithm is a case-sensitive string match for "cSHAKE256":
34    //     Let result be the result of performing the cSHAKE256 function defined in Section 3 of
35    //     [NIST-SP800-185] using message as the X input parameter, length as the L input
36    //     parameter, functionName as the N input parameter, and customization as the S input
37    //     parameter.
38    // Step 5. If performing the operation results in an error, then throw an OperationError.
39    let result = match normalized_algorithm.name.as_str() {
40        ALG_CSHAKE_128 => {
41            let core = CShake128Core::new_with_function_name(function_name, customization);
42            let mut hasher = CShake128::from_core(core);
43            hasher.update(message);
44            hasher.finalize_boxed(length / 8).to_vec()
45        },
46        ALG_CSHAKE_256 => {
47            let core = CShake256Core::new_with_function_name(function_name, customization);
48            let mut hasher = CShake256::from_core(core);
49            hasher.update(message);
50            hasher.finalize_boxed(length / 8).to_vec()
51        },
52        _ => return Err(Error::NotSupported(None)),
53    };
54
55    // Step 6. Return result.
56    Ok(result)
57}