| // 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(()) | |
| } | |
| } | |
| } |