diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/neqo-crypto/src/hkdf.rs | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/neqo-crypto/src/hkdf.rs')
-rw-r--r-- | third_party/rust/neqo-crypto/src/hkdf.rs | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/third_party/rust/neqo-crypto/src/hkdf.rs b/third_party/rust/neqo-crypto/src/hkdf.rs new file mode 100644 index 0000000000..8de9c01fc8 --- /dev/null +++ b/third_party/rust/neqo-crypto/src/hkdf.rs @@ -0,0 +1,128 @@ +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::constants::{ + Cipher, Version, TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, + TLS_VERSION_1_3, +}; +use crate::err::{Error, Res}; +use crate::p11::{ + random, Item, PK11Origin, PK11SymKey, PK11_ImportDataKey, Slot, SymKey, CKA_DERIVE, + CKM_HKDF_DERIVE, CK_ATTRIBUTE_TYPE, CK_MECHANISM_TYPE, +}; + +use std::convert::TryFrom; +use std::os::raw::{c_char, c_uint}; +use std::ptr::null_mut; + +experimental_api!(SSL_HkdfExtract( + version: Version, + cipher: Cipher, + salt: *mut PK11SymKey, + ikm: *mut PK11SymKey, + prk: *mut *mut PK11SymKey, +)); +experimental_api!(SSL_HkdfExpandLabel( + version: Version, + cipher: Cipher, + prk: *mut PK11SymKey, + handshake_hash: *const u8, + handshake_hash_len: c_uint, + label: *const c_char, + label_len: c_uint, + secret: *mut *mut PK11SymKey, +)); + +fn key_size(version: Version, cipher: Cipher) -> Res<usize> { + if version != TLS_VERSION_1_3 { + return Err(Error::UnsupportedVersion); + } + Ok(match cipher { + TLS_AES_128_GCM_SHA256 | TLS_CHACHA20_POLY1305_SHA256 => 32, + TLS_AES_256_GCM_SHA384 => 48, + _ => return Err(Error::UnsupportedCipher), + }) +} + +/// Generate a random key of the right size for the given suite. +/// +/// # Errors +/// Only if NSS fails. +pub fn generate_key(version: Version, cipher: Cipher) -> Res<SymKey> { + import_key(version, &random(key_size(version, cipher)?)) +} + +/// Import a symmetric key for use with HKDF. +/// +/// # Errors +/// Errors returned if the key buffer is an incompatible size or the NSS functions fail. +pub fn import_key(version: Version, buf: &[u8]) -> Res<SymKey> { + if version != TLS_VERSION_1_3 { + return Err(Error::UnsupportedVersion); + } + let slot = Slot::internal()?; + let key_ptr = unsafe { + PK11_ImportDataKey( + *slot, + CK_MECHANISM_TYPE::from(CKM_HKDF_DERIVE), + PK11Origin::PK11_OriginUnwrap, + CK_ATTRIBUTE_TYPE::from(CKA_DERIVE), + &mut Item::wrap(buf), + null_mut(), + ) + }; + SymKey::from_ptr(key_ptr) +} + +/// Extract a PRK from the given salt and IKM using the algorithm defined in RFC 5869. +/// +/// # Errors +/// Errors returned if inputs are too large or the NSS functions fail. +pub fn extract( + version: Version, + cipher: Cipher, + salt: Option<&SymKey>, + ikm: &SymKey, +) -> Res<SymKey> { + let mut prk: *mut PK11SymKey = null_mut(); + let salt_ptr: *mut PK11SymKey = match salt { + Some(s) => **s, + None => null_mut(), + }; + unsafe { SSL_HkdfExtract(version, cipher, salt_ptr, **ikm, &mut prk) }?; + SymKey::from_ptr(prk) +} + +/// Expand a PRK using the HKDF-Expand-Label function defined in RFC 8446. +/// +/// # Errors +/// Errors returned if inputs are too large or the NSS functions fail. +pub fn expand_label( + version: Version, + cipher: Cipher, + prk: &SymKey, + handshake_hash: &[u8], + label: &str, +) -> Res<SymKey> { + let l = label.as_bytes(); + let mut secret: *mut PK11SymKey = null_mut(); + + // Note that this doesn't allow for passing null() for the handshake hash. + // A zero-length slice produces an identical result. + unsafe { + SSL_HkdfExpandLabel( + version, + cipher, + **prk, + handshake_hash.as_ptr(), + c_uint::try_from(handshake_hash.len())?, + l.as_ptr().cast(), + c_uint::try_from(l.len())?, + &mut secret, + ) + }?; + SymKey::from_ptr(secret) +} |