Skip to main content

bssl_crypto/
tls12_prf.rs

1// Copyright 2026 The BoringSSL Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! A special pseudo-random function used by TLS up to version 1.2
16//!
17//! This function is described in [RFC 5246] Section 5.
18//!
19//! [RFC 5246]: https://datatracker.ietf.org/doc/html/rfc5246#section-5
20
21use core::marker::PhantomData;
22
23use bssl_sys::CRYPTO_tls1_prf;
24
25use crate::{digest, sealed, FfiMutSlice, FfiSlice, ForeignTypeRef};
26
27/// The special pseudo-random function used by TLS 1.2
28pub struct Tls12Prf<A>(PhantomData<fn() -> A>);
29
30impl<A: digest::Algorithm> Tls12Prf<A> {
31    /// Generate a new secret using the definition in [RFC 5246] Section 5.
32    ///
33    /// [RFC 5246]: https://datatracker.ietf.org/doc/html/rfc5246#section-5
34    // TODO(@xfding) switch to const generics when associated const
35    // is stable at generic location.
36    pub fn generate_secret(
37        secret: &[u8],
38        label: &[u8],
39        seed1: &[u8],
40        seed2: Option<&[u8]>,
41        output: &mut [u8],
42    ) -> Result<(), ()> {
43        let (seed2_ptr, seed2_len) = if let Some(seed2) = seed2 {
44            (seed2.as_ffi_ptr(), seed2.len())
45        } else {
46            (core::ptr::null(), 0)
47        };
48
49        let ret = unsafe {
50            // Safety:
51            // - All pointers are valid and live at this point.
52            // - All buffer lengths are verified.
53            CRYPTO_tls1_prf(
54                A::get_md(sealed::SealedType).as_ptr(),
55                output.as_mut_ffi_ptr(),
56                output.len(),
57                secret.as_ffi_ptr(),
58                secret.len(),
59                label.as_ffi_ptr(),
60                label.len(),
61                seed1.as_ffi_ptr(),
62                seed1.len(),
63                seed2_ptr,
64                seed2_len,
65            )
66        };
67        if ret == 1 {
68            Ok(())
69        } else {
70            Err(())
71        }
72    }
73}