mirror of
https://github.com/servo/servo.git
synced 2025-09-30 00:29:14 +01:00
script: Refactoring of algorithm normalization in SubtleCrypto
(#39431)
In our current implementation, we have multiple functions such as `normalize_algoirthm_for_encrypt_or_decrypt` and `normalize_algorithm_for_sign_or_verify` to normalize an algorithm, and each of them works slightly differently. However, the spec defines a single normalization procedure to handle all normalization. This patch tries to consolidate our functions into a single spec-compliant normalization function named `normalize_algorithm`. The refactoring involves many existing code, so this patch only introduces the new infrastructure without touching the existing. When this patch gets approved and merged, we can then start migrating the existing to the new infrastructure. (Note that SHA's digestion and AES_CTR's encryption are also copied to the new infrastructure as demonstration.) More details about the refactoring can be found in the comment: https://github.com/servo/servo/issues/39368#issuecomment-3316943206 Testing: The new code is not in used right now. No test is needed. Fixes: Part of #39368 --------- Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
This commit is contained in:
parent
2ccaf86ff6
commit
c15495b3e7
3 changed files with 288 additions and 9 deletions
52
components/script/dom/subtlecrypto/aes_operation.rs
Normal file
52
components/script/dom/subtlecrypto/aes_operation.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use aes::cipher::generic_array::GenericArray;
|
||||
use aes::cipher::{KeyIvInit, StreamCipher};
|
||||
use aes::{Aes128, Aes192, Aes256};
|
||||
|
||||
use crate::dom::bindings::error::Error;
|
||||
use crate::dom::cryptokey::{CryptoKey, Handle};
|
||||
use crate::dom::subtlecrypto::SubtleAesCtrParams;
|
||||
|
||||
/// <https://w3c.github.io/webcrypto/#aes-ctr-operations-encrypt>
|
||||
pub(crate) fn encrypt_aes_ctr(
|
||||
params: &SubtleAesCtrParams,
|
||||
key: &CryptoKey,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
// Step 1. If the counter member of normalizedAlgorithm does not have a length of 16 bytes,
|
||||
// then throw an OperationError.
|
||||
// Step 2. If the length member of normalizedAlgorithm is zero or is greater than 128, then
|
||||
// throw an OperationError.
|
||||
if params.counter.len() != 16 || params.length == 0 || params.length > 128 {
|
||||
return Err(Error::Operation);
|
||||
}
|
||||
|
||||
// Step 3. Let ciphertext be the result of performing the CTR Encryption operation described in
|
||||
// Section 6.5 of [NIST-SP800-38A] using AES as the block cipher, the counter member of
|
||||
// normalizedAlgorithm as the initial value of the counter block, the length member of
|
||||
// normalizedAlgorithm as the input parameter m to the standard counter block incrementing
|
||||
// function defined in Appendix B.1 of [NIST-SP800-38A] and plaintext as the input plaintext.
|
||||
let mut ciphertext = Vec::from(data);
|
||||
let counter = GenericArray::from_slice(¶ms.counter);
|
||||
match key.handle() {
|
||||
Handle::Aes128(data) => {
|
||||
let key_data = GenericArray::from_slice(data);
|
||||
ctr::Ctr64BE::<Aes128>::new(key_data, counter).apply_keystream(&mut ciphertext)
|
||||
},
|
||||
Handle::Aes192(data) => {
|
||||
let key_data = GenericArray::from_slice(data);
|
||||
ctr::Ctr64BE::<Aes192>::new(key_data, counter).apply_keystream(&mut ciphertext)
|
||||
},
|
||||
Handle::Aes256(data) => {
|
||||
let key_data = GenericArray::from_slice(data);
|
||||
ctr::Ctr64BE::<Aes256>::new(key_data, counter).apply_keystream(&mut ciphertext)
|
||||
},
|
||||
_ => return Err(Error::Data),
|
||||
};
|
||||
|
||||
// Step 3. Return ciphertext.
|
||||
Ok(ciphertext)
|
||||
}
|
43
components/script/dom/subtlecrypto/sha_operation.rs
Normal file
43
components/script/dom/subtlecrypto/sha_operation.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use aws_lc_rs::digest;
|
||||
|
||||
use crate::dom::bindings::error::Error;
|
||||
use crate::dom::subtlecrypto::{ALG_SHA1, ALG_SHA256, ALG_SHA384, ALG_SHA512, SubtleAlgorithm};
|
||||
|
||||
/// <https://w3c.github.io/webcrypto/#sha-operations-digest>
|
||||
pub(crate) fn digest(
|
||||
nomrmalized_algorithm: &SubtleAlgorithm,
|
||||
message: &[u8],
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
// Step 1.
|
||||
// If the name member of normalizedAlgorithm is a cases-sensitive string match for "SHA-1":
|
||||
// Let result be the result of performing the SHA-1 hash function defined in Section 6.1 of
|
||||
// [FIPS-180-4] using message as the input message, M.
|
||||
// If the name member of normalizedAlgorithm is a cases-sensitive string match for "SHA-256":
|
||||
// Let result be the result of performing the SHA-256 hash function defined in Section 6.2
|
||||
// of [FIPS-180-4] using message as the input message, M.
|
||||
// If the name member of normalizedAlgorithm is a cases-sensitive string match for "SHA-384":
|
||||
// Let result be the result of performing the SHA-384 hash function defined in Section 6.5
|
||||
// of [FIPS-180-4] using message as the input message, M.
|
||||
// If the name member of normalizedAlgorithm is a cases-sensitive string match for "SHA-512":
|
||||
// Let result be the result of performing the SHA-512 hash function defined in Section 6.4
|
||||
// of [FIPS-180-4] using message as the input message, M.
|
||||
// Step 2. If performing the operation results in an error, then throw an OperationError.
|
||||
let result = match nomrmalized_algorithm.name.as_str() {
|
||||
ALG_SHA1 => digest::digest(&digest::SHA1_FOR_LEGACY_USE_ONLY, message)
|
||||
.as_ref()
|
||||
.to_vec(),
|
||||
ALG_SHA256 => digest::digest(&digest::SHA256, message).as_ref().to_vec(),
|
||||
ALG_SHA384 => digest::digest(&digest::SHA384, message).as_ref().to_vec(),
|
||||
ALG_SHA512 => digest::digest(&digest::SHA512, message).as_ref().to_vec(),
|
||||
_ => {
|
||||
return Err(Error::NotSupported);
|
||||
},
|
||||
};
|
||||
|
||||
// Step 3. Return result.
|
||||
Ok(result)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue