blob: 9c8fa35749f0a3dc5f0d05c82f346f42c92ad723 [file] [log] [blame] [edit]
// Copyright 2026 The BoringSSL Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! A special pseudo-random function used by TLS up to version 1.2
//!
//! This function is described in [RFC 5246] Section 5.
//!
//! [RFC 5246]: https://datatracker.ietf.org/doc/html/rfc5246#section-5
use core::marker::PhantomData;
use bssl_sys::CRYPTO_tls1_prf;
use crate::{digest, sealed, FfiMutSlice, FfiSlice, ForeignTypeRef};
/// The special pseudo-random function used by TLS 1.2
pub struct Tls12Prf<A>(PhantomData<fn() -> A>);
impl<A: digest::Algorithm> Tls12Prf<A> {
/// Generate a new secret using the definition in [RFC 5246] Section 5.
///
/// [RFC 5246]: https://datatracker.ietf.org/doc/html/rfc5246#section-5
// TODO(@xfding) switch to const generics when associated const
// is stable at generic location.
pub fn generate_secret(
secret: &[u8],
label: &[u8],
seed1: &[u8],
seed2: Option<&[u8]>,
output: &mut [u8],
) -> Result<(), ()> {
let (seed2_ptr, seed2_len) = if let Some(seed2) = seed2 {
(seed2.as_ffi_ptr(), seed2.len())
} else {
(core::ptr::null(), 0)
};
let ret = unsafe {
// Safety:
// - All pointers are valid and live at this point.
// - All buffer lengths are verified.
CRYPTO_tls1_prf(
A::get_md(sealed::SealedType).as_ptr(),
output.as_mut_ffi_ptr(),
output.len(),
secret.as_ffi_ptr(),
secret.len(),
label.as_ffi_ptr(),
label.len(),
seed1.as_ffi_ptr(),
seed1.len(),
seed2_ptr,
seed2_len,
)
};
if ret == 1 {
Ok(())
} else {
Err(())
}
}
}