portable_rustls/crypto/
tls12.rs1use alloc::boxed::Box;
2
3use super::{hmac, ActiveKeyExchange};
4use crate::error::Error;
5use crate::version::TLS12;
6
7pub struct PrfUsingHmac<'a>(pub &'a dyn hmac::Hmac);
9
10impl Prf for PrfUsingHmac<'_> {
11 fn for_key_exchange(
12 &self,
13 output: &mut [u8; 48],
14 kx: Box<dyn ActiveKeyExchange>,
15 peer_pub_key: &[u8],
16 label: &[u8],
17 seed: &[u8],
18 ) -> Result<(), Error> {
19 prf(
20 output,
21 self.0
22 .with_key(
23 kx.complete_for_tls_version(peer_pub_key, &TLS12)?
24 .secret_bytes(),
25 )
26 .as_ref(),
27 label,
28 seed,
29 );
30 Ok(())
31 }
32
33 fn for_secret(&self, output: &mut [u8], secret: &[u8], label: &[u8], seed: &[u8]) {
34 prf(output, self.0.with_key(secret).as_ref(), label, seed);
35 }
36}
37
38pub trait Prf: Send + Sync {
45 fn for_key_exchange(
54 &self,
55 output: &mut [u8; 48],
56 kx: Box<dyn ActiveKeyExchange>,
57 peer_pub_key: &[u8],
58 label: &[u8],
59 seed: &[u8],
60 ) -> Result<(), Error>;
61
62 fn for_secret(&self, output: &mut [u8], secret: &[u8], label: &[u8], seed: &[u8]);
66
67 #[cfg(unstable_api_not_supported)] fn fips(&self) -> bool {
70 false
71 }
72}
73
74pub(crate) fn prf(out: &mut [u8], hmac_key: &dyn hmac::Key, label: &[u8], seed: &[u8]) {
75 let mut current_a = hmac_key.sign(&[label, seed]);
77
78 let chunk_size = hmac_key.tag_len();
79 for chunk in out.chunks_mut(chunk_size) {
80 let p_term = hmac_key.sign(&[current_a.as_ref(), label, seed]);
82 chunk.copy_from_slice(&p_term.as_ref()[..chunk.len()]);
83
84 current_a = hmac_key.sign(&[current_a.as_ref()]);
86 }
87}
88
89#[cfg(all(test, feature = "ring"))]
90mod tests {
91 use crate::crypto::hmac::Hmac;
92 use crate::crypto::ring::hmac;
95
96 #[test]
99 fn check_sha256() {
100 let secret = b"\x9b\xbe\x43\x6b\xa9\x40\xf0\x17\xb1\x76\x52\x84\x9a\x71\xdb\x35";
101 let seed = b"\xa0\xba\x9f\x93\x6c\xda\x31\x18\x27\xa6\xf7\x96\xff\xd5\x19\x8c";
102 let label = b"test label";
103 let expect = include_bytes!("../testdata/prf-result.1.bin");
104 let mut output = [0u8; 100];
105
106 super::prf(
107 &mut output,
108 &*hmac::HMAC_SHA256.with_key(secret),
109 label,
110 seed,
111 );
112 assert_eq!(expect.len(), output.len());
113 assert_eq!(expect.to_vec(), output.to_vec());
114 }
115
116 #[test]
117 fn check_sha512() {
118 let secret = b"\xb0\x32\x35\x23\xc1\x85\x35\x99\x58\x4d\x88\x56\x8b\xbb\x05\xeb";
119 let seed = b"\xd4\x64\x0e\x12\xe4\xbc\xdb\xfb\x43\x7f\x03\xe6\xae\x41\x8e\xe5";
120 let label = b"test label";
121 let expect = include_bytes!("../testdata/prf-result.2.bin");
122 let mut output = [0u8; 196];
123
124 super::prf(
125 &mut output,
126 &*hmac::HMAC_SHA512.with_key(secret),
127 label,
128 seed,
129 );
130 assert_eq!(expect.len(), output.len());
131 assert_eq!(expect.to_vec(), output.to_vec());
132 }
133
134 #[test]
135 fn check_sha384() {
136 let secret = b"\xb8\x0b\x73\x3d\x6c\xee\xfc\xdc\x71\x56\x6e\xa4\x8e\x55\x67\xdf";
137 let seed = b"\xcd\x66\x5c\xf6\xa8\x44\x7d\xd6\xff\x8b\x27\x55\x5e\xdb\x74\x65";
138 let label = b"test label";
139 let expect = include_bytes!("../testdata/prf-result.3.bin");
140 let mut output = [0u8; 148];
141
142 super::prf(
143 &mut output,
144 &*hmac::HMAC_SHA384.with_key(secret),
145 label,
146 seed,
147 );
148 assert_eq!(expect.len(), output.len());
149 assert_eq!(expect.to_vec(), output.to_vec());
150 }
151}
152
153#[cfg(all(bench, feature = "ring"))]
154mod benchmarks {
155 #[bench]
156 fn bench_sha256(b: &mut test::Bencher) {
157 use crate::crypto::hmac::Hmac;
158 use crate::crypto::ring::hmac;
159
160 let label = &b"extended master secret"[..];
161 let seed = [0u8; 32];
162 let key = &b"secret"[..];
163
164 b.iter(|| {
165 let mut out = [0u8; 48];
166 super::prf(&mut out, &*hmac::HMAC_SHA256.with_key(key), &label, &seed);
167 test::black_box(out);
168 });
169 }
170}