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}