Implement AES-GCM support for subtlecrypto (#34269)

* Support normalizing AES-GCM for encryption

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Implement "encrypt" operation for AES-GCM

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Allow importing AES-GCM keys

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Implement AES-GCM decryption

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Allow normalizing AES-GCM for "generate key"

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Update WPT expectations

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* fmt

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Fix clippy errors

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Remove silly checks

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Support AES-GCM 128-bit encryption with 128 bit IV

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Support AES-GCM with wrapKey/unwrapKey

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

* Update WPT expectations (again)

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
Simon Wülker 2024-11-19 13:42:37 +01:00 committed by GitHub
parent 5113147f80
commit 83f8e88818
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 1168 additions and 13478 deletions

View file

@ -10,8 +10,10 @@ use aes::cipher::block_padding::Pkcs7;
use aes::cipher::generic_array::GenericArray;
use aes::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit, StreamCipher};
use aes::{Aes128, Aes192, Aes256};
use aes_gcm::{AeadInPlace, AesGcm, KeyInit};
use aes_kw::{KekAes128, KekAes192, KekAes256};
use base64::prelude::*;
use cipher::consts::{U12, U16, U32};
use dom_struct::dom_struct;
use js::conversions::ConversionResult;
use js::jsapi::{JSObject, JS_NewObject};
@ -28,9 +30,10 @@ use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
CryptoKeyMethods, KeyType, KeyUsage,
};
use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{
AesCbcParams, AesCtrParams, AesDerivedKeyParams, AesKeyAlgorithm, AesKeyGenParams, Algorithm,
AlgorithmIdentifier, HkdfParams, HmacImportParams, HmacKeyAlgorithm, HmacKeyGenParams,
JsonWebKey, KeyAlgorithm, KeyFormat, Pbkdf2Params, SubtleCryptoMethods,
AesCbcParams, AesCtrParams, AesDerivedKeyParams, AesGcmParams, AesKeyAlgorithm,
AesKeyGenParams, Algorithm, AlgorithmIdentifier, HkdfParams, HmacImportParams,
HmacKeyAlgorithm, HmacKeyGenParams, JsonWebKey, KeyAlgorithm, KeyFormat, Pbkdf2Params,
SubtleCryptoMethods,
};
use crate::dom::bindings::codegen::UnionTypes::{
ArrayBufferViewOrArrayBuffer, ArrayBufferViewOrArrayBufferOrJsonWebKey,
@ -108,6 +111,14 @@ type Aes128Ctr = ctr::Ctr64BE<Aes128>;
type Aes192Ctr = ctr::Ctr64BE<Aes192>;
type Aes256Ctr = ctr::Ctr64BE<Aes256>;
type Aes128Gcm96Iv = AesGcm<Aes128, U12>;
type Aes128Gcm128Iv = AesGcm<Aes128, U16>;
type Aes192Gcm96Iv = AesGcm<Aes192, U12>;
type Aes256Gcm96Iv = AesGcm<Aes256, U12>;
type Aes128Gcm256Iv = AesGcm<Aes128, U32>;
type Aes192Gcm256Iv = AesGcm<Aes192, U32>;
type Aes256Gcm256Iv = AesGcm<Aes256, U32>;
#[dom_struct]
pub struct SubtleCrypto {
reflector_: Reflector,
@ -838,7 +849,7 @@ impl SubtleCryptoMethods for SubtleCrypto {
return;
}
let exported_key = match alg_name.as_str() {
ALG_AES_CBC | ALG_AES_CTR | ALG_AES_KW => subtle.export_key_aes(format, &key),
ALG_AES_CBC | ALG_AES_CTR | ALG_AES_KW | ALG_AES_GCM => subtle.export_key_aes(format, &key),
_ => Err(Error::NotSupported),
};
match exported_key {
@ -965,6 +976,11 @@ impl SubtleCryptoMethods for SubtleCrypto {
&params, &wrapping_key, &bytes, cx, array_buffer_ptr.handle_mut()
)
},
KeyWrapAlgorithm::AesGcm(params) => {
subtle.encrypt_aes_gcm(
&params, &wrapping_key, &bytes, cx, array_buffer_ptr.handle_mut()
)
},
};
match result {
@ -1047,6 +1063,11 @@ impl SubtleCryptoMethods for SubtleCrypto {
&params, &unwrapping_key, &wrapped_key_bytes, cx, array_buffer_ptr.handle_mut()
)
},
KeyWrapAlgorithm::AesGcm(params) => {
subtle.decrypt_aes_gcm(
&params, &unwrapping_key, &wrapped_key_bytes, cx, array_buffer_ptr.handle_mut()
)
},
};
let bytes = match result {
@ -1139,6 +1160,34 @@ impl From<RootedTraceableBox<AesCtrParams>> for SubtleAesCtrParams {
}
}
#[derive(Clone, Debug)]
pub struct SubtleAesGcmParams {
pub name: String,
pub iv: Vec<u8>,
pub additional_data: Option<Vec<u8>>,
pub tag_length: Option<u8>,
}
impl From<RootedTraceableBox<AesGcmParams>> for SubtleAesGcmParams {
fn from(params: RootedTraceableBox<AesGcmParams>) -> Self {
let iv = match &params.iv {
ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
};
let additional_data = params.additionalData.as_ref().map(|data| match data {
ArrayBufferViewOrArrayBuffer::ArrayBufferView(view) => view.to_vec(),
ArrayBufferViewOrArrayBuffer::ArrayBuffer(buffer) => buffer.to_vec(),
});
SubtleAesGcmParams {
name: params.parent.name.to_string(),
iv,
additional_data,
tag_length: params.tagLength,
}
}
}
#[derive(Clone, Debug)]
pub struct SubtleAesKeyGenParams {
pub name: String,
@ -1313,6 +1362,7 @@ enum ImportKeyAlgorithm {
AesCbc,
AesCtr,
AesKw,
AesGcm,
Hmac(SubtleHmacImportParams),
Pbkdf2,
Hkdf,
@ -1329,9 +1379,11 @@ enum DeriveBitsAlgorithm {
/// A normalized algorithm returned by [`normalize_algorithm`] with operation `"encrypt"` or `"decrypt"`
///
/// [`normalize_algorithm`]: https://w3c.github.io/webcrypto/#algorithm-normalization-normalize-an-algorithm
#[allow(clippy::enum_variant_names)]
enum EncryptionAlgorithm {
AesCbc(SubtleAesCbcParams),
AesCtr(SubtleAesCtrParams),
AesGcm(SubtleAesGcmParams),
}
/// A normalized algorithm returned by [`normalize_algorithm`] with operation `"sign"` or `"verify"`
@ -1357,6 +1409,7 @@ enum KeyWrapAlgorithm {
AesKw,
AesCbc(SubtleAesCbcParams),
AesCtr(SubtleAesCtrParams),
AesGcm(SubtleAesGcmParams),
}
macro_rules! value_from_js_object {
@ -1381,7 +1434,8 @@ fn normalize_algorithm_for_get_key_length(
let name = algorithm.name.str();
let normalized_algorithm = if name.eq_ignore_ascii_case(ALG_AES_CBC) ||
name.eq_ignore_ascii_case(ALG_AES_CTR)
name.eq_ignore_ascii_case(ALG_AES_CTR) ||
name.eq_ignore_ascii_case(ALG_AES_GCM)
{
let params = value_from_js_object!(AesDerivedKeyParams, cx, value);
GetKeyLengthAlgorithm::Aes(params.length)
@ -1454,6 +1508,7 @@ fn normalize_algorithm_for_import_key(
ALG_AES_CBC => ImportKeyAlgorithm::AesCbc,
ALG_AES_CTR => ImportKeyAlgorithm::AesCtr,
ALG_AES_KW => ImportKeyAlgorithm::AesKw,
ALG_AES_GCM => ImportKeyAlgorithm::AesGcm,
ALG_PBKDF2 => ImportKeyAlgorithm::Pbkdf2,
ALG_HKDF => ImportKeyAlgorithm::Hkdf,
_ => return Err(Error::NotSupported),
@ -1510,6 +1565,9 @@ fn normalize_algorithm_for_encrypt_or_decrypt(
} else if name.eq_ignore_ascii_case(ALG_AES_CTR) {
let params = value_from_js_object!(AesCtrParams, cx, value);
EncryptionAlgorithm::AesCtr(params.into())
} else if name.eq_ignore_ascii_case(ALG_AES_GCM) {
let params = value_from_js_object!(AesGcmParams, cx, value);
EncryptionAlgorithm::AesGcm(params.into())
} else {
return Err(Error::NotSupported);
};
@ -1557,7 +1615,8 @@ fn normalize_algorithm_for_generate_key(
let name = algorithm.name.str();
let normalized_algorithm = if name.eq_ignore_ascii_case(ALG_AES_CBC) ||
name.eq_ignore_ascii_case(ALG_AES_CTR) ||
name.eq_ignore_ascii_case(ALG_AES_KW)
name.eq_ignore_ascii_case(ALG_AES_KW) ||
name.eq_ignore_ascii_case(ALG_AES_GCM)
{
let params = value_from_js_object!(AesKeyGenParams, cx, value);
KeyGenerationAlgorithm::Aes(params.into())
@ -1603,6 +1662,13 @@ fn normalize_algorithm_for_key_wrap(
rooted!(in(*cx) let value = ObjectValue(obj.get()));
KeyWrapAlgorithm::AesCtr(value_from_js_object!(AesCtrParams, cx, value).into())
},
ALG_AES_GCM => {
let AlgorithmIdentifier::Object(obj) = algorithm else {
return Err(Error::Syntax);
};
rooted!(in(*cx) let value = ObjectValue(obj.get()));
KeyWrapAlgorithm::AesGcm(value_from_js_object!(AesGcmParams, cx, value).into())
},
_ => return Err(Error::NotSupported),
};
@ -1730,6 +1796,250 @@ impl SubtleCrypto {
Ok(ciphertext)
}
/// <https://w3c.github.io/webcrypto/#aes-gcm-operations>
fn encrypt_aes_gcm(
&self,
params: &SubtleAesGcmParams,
key: &CryptoKey,
plaintext: &[u8],
cx: JSContext,
handle: MutableHandleObject,
) -> Result<Vec<u8>, Error> {
// Step 1. If plaintext has a length greater than 2^39 - 256 bytes, then throw an OperationError.
if plaintext.len() as u64 > (2 << 39) - 256 {
return Err(Error::Operation);
}
// Step 2. If the iv member of normalizedAlgorithm has a length greater than 2^64 - 1 bytes,
// then throw an OperationError.
// NOTE: servo does not currently support 128-bit platforms, so this can never happen
// Step 3. If the additionalData member of normalizedAlgorithm is present and has a length greater than 2^64 - 1
// bytes, then throw an OperationError.
if params
.additional_data
.as_ref()
.is_some_and(|data| data.len() > u64::MAX as usize)
{
return Err(Error::Operation);
}
// Step 4.
let tag_length = match params.tag_length {
// If the tagLength member of normalizedAlgorithm is not present:
None => {
// Let tagLength be 128.
128
},
// If the tagLength member of normalizedAlgorithm is one of 32, 64, 96, 104, 112, 120 or 128:
Some(length) if matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128) => {
// Let tagLength be equal to the tagLength member of normalizedAlgorithm
length
},
// Otherwise:
_ => {
// throw an OperationError.
return Err(Error::Operation);
},
};
// Step 5. Let additionalData be the contents of the additionalData member of normalizedAlgorithm if present
// or the empty octet string otherwise.
let additional_data = params.additional_data.as_deref().unwrap_or_default();
// Step 6. Let C and T be the outputs that result from performing the Authenticated Encryption Function
// described in Section 7.1 of [NIST-SP800-38D] using AES as the block cipher, the contents of the iv member
// of normalizedAlgorithm as the IV input parameter, the contents of additionalData as the A input parameter,
// tagLength as the t pre-requisite and the contents of plaintext as the input plaintext.
let key_length = key.handle().as_bytes().len();
let iv_length = params.iv.len();
let mut ciphertext = plaintext.to_vec();
let key_bytes = key.handle().as_bytes();
let tag = match (key_length, iv_length) {
(16, 12) => {
let nonce = GenericArray::from_slice(&params.iv);
<Aes128Gcm96Iv>::new_from_slice(key_bytes)
.expect("key length did not match")
.encrypt_in_place_detached(nonce, additional_data, &mut ciphertext)
},
(16, 16) => {
let nonce = GenericArray::from_slice(&params.iv);
<Aes128Gcm128Iv>::new_from_slice(key_bytes)
.expect("key length did not match")
.encrypt_in_place_detached(nonce, additional_data, &mut ciphertext)
},
(20, 12) => {
let nonce = GenericArray::from_slice(&params.iv);
<Aes192Gcm96Iv>::new_from_slice(key_bytes)
.expect("key length did not match")
.encrypt_in_place_detached(nonce, additional_data, &mut ciphertext)
},
(32, 12) => {
let nonce = GenericArray::from_slice(&params.iv);
<Aes256Gcm96Iv>::new_from_slice(key_bytes)
.expect("key length did not match")
.encrypt_in_place_detached(nonce, additional_data, &mut ciphertext)
},
(16, 32) => {
let nonce = GenericArray::from_slice(&params.iv);
<Aes128Gcm256Iv>::new_from_slice(key_bytes)
.expect("key length did not match")
.encrypt_in_place_detached(nonce, additional_data, &mut ciphertext)
},
(20, 32) => {
let nonce = GenericArray::from_slice(&params.iv);
<Aes192Gcm256Iv>::new_from_slice(key_bytes)
.expect("key length did not match")
.encrypt_in_place_detached(nonce, additional_data, &mut ciphertext)
},
(32, 32) => {
let nonce = GenericArray::from_slice(&params.iv);
<Aes256Gcm256Iv>::new_from_slice(key_bytes)
.expect("key length did not match")
.encrypt_in_place_detached(nonce, additional_data, &mut ciphertext)
},
_ => {
log::warn!(
"Missing AES-GCM encryption implementation with {key_length}-byte key and {iv_length}-byte IV"
);
return Err(Error::NotSupported);
},
};
// Step 7. Let ciphertext be equal to C | T, where '|' denotes concatenation.
ciphertext.extend_from_slice(&tag.unwrap()[..tag_length as usize / 8]);
// Step 8. Return the result of creating an ArrayBuffer containing ciphertext.
create_buffer_source::<ArrayBufferU8>(cx, &ciphertext, handle)
.expect("failed to create buffer source for encrypted ciphertext");
Ok(ciphertext)
}
/// <https://w3c.github.io/webcrypto/#aes-gcm-operations>
fn decrypt_aes_gcm(
&self,
params: &SubtleAesGcmParams,
key: &CryptoKey,
ciphertext: &[u8],
cx: JSContext,
handle: MutableHandleObject,
) -> Result<Vec<u8>, Error> {
// Step 1.
// FIXME: aes_gcm uses a fixed tag length
let tag_length = match params.tag_length {
// If the tagLength member of normalizedAlgorithm is not present:
None => {
// Let tagLength be 128.
128
},
// If the tagLength member of normalizedAlgorithm is one of 32, 64, 96, 104, 112, 120 or 128:
Some(length) if matches!(length, 32 | 64 | 96 | 104 | 112 | 120 | 128) => {
// Let tagLength be equal to the tagLength member of normalizedAlgorithm
length as usize
},
// Otherwise:
_ => {
// throw an OperationError.
return Err(Error::Operation);
},
};
// Step 2. If ciphertext has a length less than tagLength bits, then throw an OperationError.
if ciphertext.len() < tag_length / 8 {
return Err(Error::Operation);
}
// Step 3. If the iv member of normalizedAlgorithm has a length greater than 2^64 - 1 bytes,
// then throw an OperationError.
// NOTE: servo does not currently support 128-bit platforms, so this can never happen
// Step 4. If the additionalData member of normalizedAlgorithm is present and has a length greater than 2^64 - 1
// bytes, then throw an OperationError.
// NOTE: servo does not currently support 128-bit platforms, so this can never happen
// Step 5. Let tag be the last tagLength bits of ciphertext.
// Step 6. Let actualCiphertext be the result of removing the last tagLength bits from ciphertext.
// NOTE: aes_gcm splits the ciphertext for us
// Step 7. Let additionalData be the contents of the additionalData member of normalizedAlgorithm if present or
// the empty octet string otherwise.
let additional_data = params.additional_data.as_deref().unwrap_or_default();
// Step 8. Perform the Authenticated Decryption Function described in Section 7.2 of [NIST-SP800-38D] using AES
// as the block cipher, the contents of the iv member of normalizedAlgorithm as the IV input parameter, the
// contents of additionalData as the A input parameter, tagLength as the t pre-requisite, the contents of
// actualCiphertext as the input ciphertext, C and the contents of tag as the authentication tag, T.
let mut plaintext = ciphertext.to_vec();
let key_length = key.handle().as_bytes().len();
let iv_length = params.iv.len();
let key_bytes = key.handle().as_bytes();
let result = match (key_length, iv_length) {
(16, 12) => {
let nonce = GenericArray::from_slice(&params.iv);
<Aes128Gcm96Iv>::new_from_slice(key_bytes)
.expect("key length did not match")
.decrypt_in_place(nonce, additional_data, &mut plaintext)
},
(16, 16) => {
let nonce = GenericArray::from_slice(&params.iv);
<Aes128Gcm128Iv>::new_from_slice(key_bytes)
.expect("key length did not match")
.decrypt_in_place(nonce, additional_data, &mut plaintext)
},
(20, 12) => {
let nonce = GenericArray::from_slice(&params.iv);
<Aes192Gcm96Iv>::new_from_slice(key_bytes)
.expect("key length did not match")
.decrypt_in_place(nonce, additional_data, &mut plaintext)
},
(32, 12) => {
let nonce = GenericArray::from_slice(&params.iv);
<Aes256Gcm96Iv>::new_from_slice(key_bytes)
.expect("key length did not match")
.decrypt_in_place(nonce, additional_data, &mut plaintext)
},
(16, 32) => {
let nonce = GenericArray::from_slice(&params.iv);
<Aes128Gcm256Iv>::new_from_slice(key_bytes)
.expect("key length did not match")
.decrypt_in_place(nonce, additional_data, &mut plaintext)
},
(20, 32) => {
let nonce = GenericArray::from_slice(&params.iv);
<Aes192Gcm256Iv>::new_from_slice(key_bytes)
.expect("key length did not match")
.decrypt_in_place(nonce, additional_data, &mut plaintext)
},
(32, 32) => {
let nonce = GenericArray::from_slice(&params.iv);
<Aes256Gcm256Iv>::new_from_slice(key_bytes)
.expect("key length did not match")
.decrypt_in_place(nonce, additional_data, &mut plaintext)
},
_ => {
log::warn!(
"Missing AES-GCM decryption implementation with {key_length}-byte key and {iv_length}-byte IV"
);
return Err(Error::NotSupported);
},
};
// If the result of the algorithm is the indication of inauthenticity, "FAIL":
if result.is_err() {
// throw an OperationError
return Err(Error::Operation);
}
// Otherwise:
// Let plaintext be the output P of the Authenticated Decryption Function.
// Step 9. Return the result of creating an ArrayBuffer containing plaintext.
create_buffer_source::<ArrayBufferU8>(cx, &plaintext, handle)
.expect("failed to create buffer source for decrypted plaintext");
Ok(plaintext)
}
/// <https://w3c.github.io/webcrypto/#aes-cbc-operations>
/// <https://w3c.github.io/webcrypto/#aes-ctr-operations>
/// <https://w3c.github.io/webcrypto/#aes-kw-operations>
@ -1750,7 +2060,7 @@ impl SubtleCrypto {
};
match key_gen_params.name.as_str() {
ALG_AES_CBC | ALG_AES_CTR => {
ALG_AES_CBC | ALG_AES_CTR | ALG_AES_GCM => {
if usages.iter().any(|usage| {
!matches!(
usage,
@ -1780,6 +2090,7 @@ impl SubtleCrypto {
ALG_AES_CBC => DOMString::from(ALG_AES_CBC),
ALG_AES_CTR => DOMString::from(ALG_AES_CTR),
ALG_AES_KW => DOMString::from(ALG_AES_KW),
ALG_AES_GCM => DOMString::from(ALG_AES_GCM),
_ => return Err(Error::NotSupported),
};
@ -2303,6 +2614,7 @@ fn data_to_jwk_params(alg: &str, size: &str, key: &[u8]) -> (DOMString, DOMStrin
ALG_AES_CBC => DOMString::from(format!("A{}CBC", size)),
ALG_AES_CTR => DOMString::from(format!("A{}CTR", size)),
ALG_AES_KW => DOMString::from(format!("A{}KW", size)),
ALG_AES_GCM => DOMString::from(format!("A{}GCM", size)),
_ => unreachable!(),
};
let data = base64::engine::general_purpose::STANDARD_NO_PAD.encode(key);
@ -2529,6 +2841,9 @@ impl ImportKeyAlgorithm {
Self::AesKw => {
subtle.import_key_aes(format, secret, extractable, key_usages, ALG_AES_KW)
},
Self::AesGcm => {
subtle.import_key_aes(format, secret, extractable, key_usages, ALG_AES_GCM)
},
Self::Hmac(params) => {
subtle.import_key_hmac(params, format, secret, extractable, key_usages)
},
@ -2551,8 +2866,9 @@ impl EncryptionAlgorithm {
/// <https://w3c.github.io/webcrypto/#dom-algorithm-name>
fn name(&self) -> &str {
match self {
Self::AesCbc(key_gen_params) => &key_gen_params.name,
Self::AesCtr(key_gen_params) => &key_gen_params.name,
Self::AesCbc(params) => &params.name,
Self::AesCtr(params) => &params.name,
Self::AesGcm(params) => &params.name,
}
}
@ -2566,12 +2882,9 @@ impl EncryptionAlgorithm {
result: MutableHandleObject,
) -> Result<Vec<u8>, Error> {
match self {
Self::AesCbc(key_gen_params) => {
subtle.encrypt_aes_cbc(key_gen_params, key, data, cx, result)
},
Self::AesCtr(key_gen_params) => {
subtle.encrypt_decrypt_aes_ctr(key_gen_params, key, data, cx, result)
},
Self::AesCbc(params) => subtle.encrypt_aes_cbc(params, key, data, cx, result),
Self::AesCtr(params) => subtle.encrypt_decrypt_aes_ctr(params, key, data, cx, result),
Self::AesGcm(params) => subtle.encrypt_aes_gcm(params, key, data, cx, result),
}
}
@ -2585,12 +2898,9 @@ impl EncryptionAlgorithm {
result: MutableHandleObject,
) -> Result<Vec<u8>, Error> {
match self {
Self::AesCbc(key_gen_params) => {
subtle.decrypt_aes_cbc(key_gen_params, key, data, cx, result)
},
Self::AesCtr(key_gen_params) => {
subtle.encrypt_decrypt_aes_ctr(key_gen_params, key, data, cx, result)
},
Self::AesCbc(params) => subtle.decrypt_aes_cbc(params, key, data, cx, result),
Self::AesCtr(params) => subtle.encrypt_decrypt_aes_ctr(params, key, data, cx, result),
Self::AesGcm(params) => subtle.decrypt_aes_gcm(params, key, data, cx, result),
}
}
}
@ -2684,6 +2994,7 @@ impl KeyWrapAlgorithm {
Self::AesKw => ALG_AES_KW,
Self::AesCbc(key_gen_params) => &key_gen_params.name,
Self::AesCtr(key_gen_params) => &key_gen_params.name,
Self::AesGcm(_) => ALG_AES_GCM,
}
}
}
@ -2704,7 +3015,10 @@ fn parse_jwk(bytes: &[u8], alg: ImportKeyAlgorithm, extractable: bool) -> Result
}
match alg {
ImportKeyAlgorithm::AesCbc | ImportKeyAlgorithm::AesCtr | ImportKeyAlgorithm::AesKw => {
ImportKeyAlgorithm::AesCbc |
ImportKeyAlgorithm::AesCtr |
ImportKeyAlgorithm::AesKw |
ImportKeyAlgorithm::AesGcm => {
if kty != "oct" {
return Err(Error::Data);
}