rustls_mbedcrypto_provider/
self_tests.rs

1//! This module defines self-tests. Running tests in this module (i.e., calling [`self_tests()`](self::self_tests()))
2//! at runtime can help with [FIPS 140-3] compliance.
3//!
4//! [FIPS 140-3]: (https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS%20140-3%20IG.pdf)
5
6use rustls::crypto::{
7    tls12::{Prf, PrfUsingHmac},
8    tls13::{expand, Hkdf, HkdfUsingHmac},
9    ActiveKeyExchange,
10};
11use std::vec::Vec;
12
13// test copied from rustls repo
14/// TLS 1.2 SHA256 PRF test
15#[cfg(feature = "tls12")]
16pub fn tls12_sha256_prf_test_1() {
17    let secret = b"\x9b\xbe\x43\x6b\xa9\x40\xf0\x17\xb1\x76\x52\x84\x9a\x71\xdb\x35";
18    let seed = b"\xa0\xba\x9f\x93\x6c\xda\x31\x18\x27\xa6\xf7\x96\xff\xd5\x19\x8c";
19    let label = b"test label";
20    let expect = include_bytes!("../testdata/prf-result.1.bin");
21    let mut output = [0u8; 100];
22
23    let prf = PrfUsingHmac(&super::hmac::HMAC_SHA256);
24    prf.for_secret(&mut output, secret, label, seed);
25
26    assert_eq!(expect.len(), output.len());
27    assert_eq!(&expect[..], &output[..]);
28}
29
30/// TLS 1.2 SHA256 PRF test with `"extended master secret"`
31#[cfg(feature = "tls12")]
32pub fn tls12_sha256_prf_test_2() {
33    let secret = b"\x9b\xbe\x43\x6b\xa9\x40\xf0\x17\xb1\x76\x52\x84\x9a\x71\xdb\x35";
34    let session_hash: &[u8; 32] = b"\xa0\xba\x9f\x93\x6c\xda\x31\x18\x27\xa6\xf7\x96\xff\xd5\x19\x8c\
35                                    \xb1\x7c\x53\x8e\xcd\x16\x73\x8a\x59\x18\xf7\xd2\xff\x21\xbb\x81";
36    let label = b"extended master secret";
37    let expect = [
38        0x39, 0x10, 0x1e, 0xdf, 0x15, 0x16, 0xb8, 0xbf, 0x3b, 0xbb, 0x0b, 0x62, 0x9b, 0xf8, 0x05, 0x47, 0x5b, 0xef, 0x76, 0x1b,
39        0x3d, 0x62, 0xc1, 0x0d, 0x99, 0x06, 0x44, 0x87, 0xaa, 0x7a, 0xee, 0x09, 0x55, 0x6c, 0xb1, 0xa8, 0x24, 0xd6, 0xfc, 0x24,
40        0x99, 0x2b, 0x98, 0x22, 0x7f, 0x30, 0xc1, 0x19, 0x4b, 0x91, 0xf2, 0xbb, 0xed, 0x40, 0xee, 0xe1, 0x05, 0x36, 0xcb, 0x49,
41        0x93, 0xc4, 0x93, 0x21, 0x7f, 0x31, 0x01, 0xc9, 0x23, 0x7c, 0x31, 0x8c, 0x12, 0x93, 0xe4, 0xb8, 0xcf, 0x0b, 0xcb, 0x9f,
42        0xb6, 0x5e, 0x80, 0x83, 0xfe, 0xd3, 0x70, 0x5b, 0x7d, 0x86, 0x7a, 0x02, 0xe1, 0x7c, 0x4a, 0x7f, 0xf5, 0x30, 0x29, 0xee,
43    ];
44    let mut output = [0u8; 100];
45
46    let prf = PrfUsingHmac(&super::hmac::HMAC_SHA256);
47    prf.for_secret(&mut output, secret, label, session_hash);
48
49    assert_eq!(expect.len(), output.len());
50    assert_eq!(&expect[..], &output[..]);
51}
52
53// test copied from rustls repo
54/// TLS 1.2 SHA384 PRF test
55#[cfg(feature = "tls12")]
56pub fn tls12_sha384_prf_test_1() {
57    let secret = b"\xb8\x0b\x73\x3d\x6c\xee\xfc\xdc\x71\x56\x6e\xa4\x8e\x55\x67\xdf";
58    let seed = b"\xcd\x66\x5c\xf6\xa8\x44\x7d\xd6\xff\x8b\x27\x55\x5e\xdb\x74\x65";
59    let label = b"test label";
60    let expect = include_bytes!("../testdata/prf-result.3.bin");
61    let mut output = [0u8; 148];
62
63    let prf = PrfUsingHmac(&super::hmac::HMAC_SHA384);
64    prf.for_secret(&mut output, secret, label, seed);
65
66    assert_eq!(expect.len(), output.len());
67    assert_eq!(&expect[..], &output[..]);
68}
69
70/// TLS 1.2 SHA384 PRF test with `"extended master secret"`
71#[cfg(feature = "tls12")]
72pub fn tls12_sha384_prf_test_2() {
73    let secret = b"\xb8\x0b\x73\x3d\x6c\xee\xfc\xdc\x71\x56\x6e\xa4\x8e\x55\x67\xdf";
74    let session_hash: &[u8; 48] = b"\xd9\x00\xfc\x5a\x86\xf0\x3d\xc6\x57\xc8\x5d\x24\x17\xfd\xb2\xfa\
75                                    \x03\xaf\x25\x40\x76\xde\xc5\x94\x71\xac\x2a\x09\xf1\xb3\x6b\xd3\
76                                    \xa2\x71\xa8\x54\x50\xe1\xf2\x06\x03\x8f\xe8\x88\xfe\x95\x2a\xba";
77    let label = b"extended master secret";
78    let expect = [
79        0xbb, 0x98, 0xf0, 0x38, 0x1e, 0xcc, 0xea, 0xde, 0xb5, 0x5e, 0xd1, 0xea, 0xfb, 0x3a, 0xf7, 0x65, 0xfe, 0x1f, 0xbe, 0x07,
80        0xc6, 0x9e, 0xd9, 0x96, 0xf3, 0x7f, 0xea, 0x1c, 0x9e, 0x36, 0xfd, 0xa8, 0xd7, 0xe8, 0x73, 0x61, 0xc4, 0xb6, 0x78, 0x76,
81        0xfc, 0xf4, 0xac, 0xa5, 0xbf, 0x32, 0x0a, 0x9a, 0x3a, 0x41, 0x68, 0x2e, 0x19, 0x59, 0xd0, 0xb7, 0x18, 0x6d, 0x99, 0x90,
82        0x3b, 0x58, 0x40, 0xd9, 0x64, 0x33, 0x91, 0x74, 0x8b, 0xca, 0x0b, 0xfd, 0x3f, 0xe1, 0xaf, 0xa7, 0x6d, 0x12, 0x01, 0xf2,
83        0xb5, 0x17, 0x38, 0xc1, 0xae, 0xed, 0x17, 0x99, 0x42, 0xbb, 0xad, 0x41, 0x1d, 0x32, 0x37, 0xa4, 0x55, 0x2e, 0x82, 0x86,
84        0x88, 0x1a, 0x42, 0x4d, 0xc5, 0x02, 0xc7, 0x02, 0x50, 0x6a, 0x70, 0xfe, 0xf8, 0x62, 0xaf, 0xc1, 0xcf, 0x38, 0x26, 0xf3,
85        0x28, 0x05, 0x63, 0x5f, 0xaf, 0x08, 0x74, 0x48, 0x4e, 0xa6, 0x0d, 0x6f, 0x97, 0x64, 0x13, 0xb1, 0x3a, 0xea, 0x57, 0x60,
86        0x6e, 0x3a, 0x6b, 0x3b, 0x65, 0x34, 0x47, 0xfb,
87    ];
88    let mut output = [0u8; 148];
89
90    let prf = PrfUsingHmac(&super::hmac::HMAC_SHA384);
91    prf.for_secret(&mut output, secret, label, session_hash);
92
93    assert_eq!(expect.len(), output.len());
94    assert_eq!(&expect[..], &output[..]);
95}
96
97// test copied from rustls repo
98/// TLS 1.3 KDF [test case 1](https://datatracker.ietf.org/doc/html/rfc5869#appendix-A.1).
99pub fn tls13_kdf_test_case_1() {
100    let hkdf = HkdfUsingHmac(&super::hmac::HMAC_SHA256);
101    let ikm = &[0x0b; 22];
102    let salt = &[0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c];
103    let info: &[&[u8]] = &[&[0xf0, 0xf1, 0xf2], &[0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9]];
104
105    let output: [u8; 42] = expand(
106        hkdf.extract_from_secret(Some(salt), ikm)
107            .as_ref(),
108        info,
109    );
110
111    assert_eq!(
112        &output,
113        &[
114            0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a,
115            0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8,
116            0x87, 0x18, 0x58, 0x65
117        ]
118    );
119}
120
121// test copied from rustls repo
122/// TLS 1.3 KDF [test case 2](https://datatracker.ietf.org/doc/html/rfc5869#appendix-A.2).
123pub fn tls13_kdf_test_case_2() {
124    let hkdf = HkdfUsingHmac(&super::hmac::HMAC_SHA256);
125    let ikm: Vec<u8> = (0x00u8..=0x4f).collect();
126    let salt: Vec<u8> = (0x60u8..=0xaf).collect();
127    let info: Vec<u8> = (0xb0u8..=0xff).collect();
128
129    let output: [u8; 82] = expand(
130        hkdf.extract_from_secret(Some(&salt), &ikm)
131            .as_ref(),
132        &[&info],
133    );
134
135    assert_eq!(
136        &output,
137        &[
138            0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e,
139            0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7,
140            0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36,
141            0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5,
142            0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87
143        ]
144    );
145}
146
147// test copied from rustls repo
148/// TLS 1.3 KDF [test case 3](https://datatracker.ietf.org/doc/html/rfc5869#appendix-A.3).
149pub fn tls13_kdf_test_case_3() {
150    let hkdf = HkdfUsingHmac(&super::hmac::HMAC_SHA256);
151    let ikm = &[0x0b; 22];
152    let salt = &[];
153    let info = &[];
154
155    let output: [u8; 42] = expand(
156        hkdf.extract_from_secret(Some(salt), ikm)
157            .as_ref(),
158        info,
159    );
160
161    assert_eq!(
162        &output,
163        &[
164            0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f,
165            0x5c, 0x5e, 0xe1, 0x87, 0x9e, 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4,
166            0xb6, 0x1a, 0x96, 0xc8
167        ]
168    );
169}
170
171/// Known answer Cryptographic Algorithm Self Test (CAST) for FFDHE.
172/// This is required by [FIPS 140-3 IG D.F]:
173///
174/// > The CAST for a solution complying with path (1) above shall
175/// > consist of verifying the correctness of the computation of the
176/// > shared secret Z in at least two of the schemes listed in Section 6
177/// > of [SP 800-56Arev3]: one CAST for the Finite Field Cryptography
178/// > (FFC) methods and one CAST for the Elliptic Curve Cryptography
179/// > methods, if both the FFC and ECC methods are implemented;
180/// > otherwise, just one. No separate CASTs are required to test
181/// > Diffie-Hellman and MQV schemes.
182///
183/// [FIPS 140-3 IG D.F]:
184///     https://csrc.nist.gov/projects/cryptographic-module-validation-program/fips-140-3-ig-announcements
185/// [SP 800-56Arev3]: https://csrc.nist.gov/pubs/sp/800/56/a/r3/final
186pub fn ffdhe_crypto_algo_self_test() {
187    // known binary variables
188    let server_private_key_vec = [
189        0x4f, 0x51, 0xa9, 0x0b, 0x6b, 0x56, 0x38, 0x26, 0x2a, 0x55, 0x13, 0xf4, 0x5b, 0x91, 0x4c, 0x1a, 0x3c, 0x40, 0x4e, 0xfa,
190        0x95, 0xf1, 0x4c, 0xc3, 0x3a, 0x53, 0xf0, 0x02, 0xb3, 0xcc, 0x07, 0xd3, 0x35, 0xd4, 0x2c, 0x27, 0x2e, 0xb0, 0x4e, 0x30,
191        0x4c, 0x64, 0xb8, 0x7d, 0x1c, 0xfc, 0x07, 0xf6,
192    ];
193    let peer_public_key_vec = [
194        0x62, 0x56, 0x4a, 0x73, 0x21, 0x0d, 0x76, 0xa1, 0xcf, 0xef, 0x6c, 0x99, 0xf7, 0x58, 0xf9, 0x41, 0xb3, 0xcd, 0x69, 0xca,
195        0x2f, 0xfd, 0x84, 0xdd, 0xc6, 0xf1, 0x30, 0xe2, 0x94, 0xb9, 0xe0, 0xa0, 0x9b, 0x45, 0xa5, 0xbd, 0xf0, 0x5a, 0x6c, 0xf3,
196        0xd9, 0x8e, 0x73, 0x2e, 0x99, 0x15, 0x7a, 0xd5, 0x27, 0xba, 0x18, 0x18, 0x46, 0x47, 0xd7, 0x78, 0xa4, 0xb1, 0x94, 0xdd,
197        0x23, 0xe6, 0x43, 0x20, 0xee, 0x91, 0x19, 0x47, 0x64, 0x51, 0x1b, 0x49, 0x8f, 0xe5, 0x2c, 0xd5, 0x56, 0x3c, 0x41, 0x62,
198        0xa5, 0x0f, 0xd2, 0x1f, 0xec, 0x09, 0x19, 0x0f, 0xde, 0x68, 0xff, 0x27, 0x33, 0x14, 0xa4, 0x5d, 0xb9, 0xb4, 0xa1, 0x8a,
199        0xc4, 0x49, 0x5a, 0x07, 0x30, 0xed, 0xed, 0x6b, 0xb4, 0x69, 0xc7, 0x63, 0x5b, 0x7c, 0x53, 0x34, 0xc8, 0xac, 0x3d, 0x4e,
200        0xdd, 0x97, 0x13, 0x93, 0x3b, 0x63, 0xbb, 0xcf, 0x13, 0x09, 0x03, 0x58, 0x8a, 0xdb, 0x8d, 0xd9, 0x05, 0xe9, 0x63, 0x26,
201        0x9b, 0x6d, 0x61, 0xb6, 0xe2, 0xfd, 0xb8, 0x57, 0x86, 0x6f, 0x10, 0xdd, 0xff, 0x90, 0xe6, 0x4b, 0xfd, 0x35, 0x83, 0xeb,
202        0x0a, 0x2d, 0x56, 0xfa, 0x09, 0x88, 0x1a, 0x54, 0x06, 0x6d, 0x9e, 0x5c, 0x2d, 0x2f, 0x70, 0xd9, 0x22, 0xcf, 0x2c, 0x32,
203        0xb8, 0x9e, 0x5c, 0x5b, 0xc5, 0xa9, 0x4c, 0xb5, 0x3c, 0x5f, 0x67, 0x62, 0x91, 0x4f, 0x39, 0xb1, 0xa7, 0x46, 0x35, 0xeb,
204        0xab, 0x90, 0xd9, 0x0c, 0x2b, 0x9d, 0x2f, 0x42, 0x46, 0x2d, 0x43, 0xae, 0x29, 0x89, 0xda, 0x87, 0x3b, 0x1c, 0x48, 0x44,
205        0x86, 0x1f, 0x11, 0xc5, 0x10, 0xc9, 0x09, 0x0c, 0x1f, 0xb7, 0x8e, 0x7a, 0x5e, 0xfc, 0xd6, 0x09, 0x2b, 0xf2, 0xc6, 0xb2,
206        0xe3, 0xff, 0x40, 0xdd, 0x11, 0x61, 0xd9, 0xed, 0xb2, 0xda, 0x6c, 0xe3, 0xba, 0x1b, 0xb3, 0x75,
207    ];
208    let expected_shared_secret = [
209        0x99, 0x8e, 0xa6, 0x14, 0x62, 0x67, 0x20, 0x37, 0x5f, 0xa3, 0x61, 0x3f, 0xa7, 0xcb, 0xf0, 0x92, 0x1e, 0xec, 0xbb, 0x89,
210        0xf2, 0x5a, 0x52, 0x55, 0xb9, 0xe1, 0xcd, 0x4f, 0x34, 0x8b, 0xf6, 0x5d, 0x1e, 0x22, 0x93, 0x58, 0xd7, 0xae, 0xcf, 0xac,
211        0x50, 0xff, 0xff, 0x5b, 0x3d, 0x22, 0x1e, 0x32, 0xd0, 0xfc, 0xfc, 0xa3, 0xd1, 0xe0, 0x3b, 0x8c, 0x04, 0xf9, 0x4a, 0x7b,
212        0x61, 0x3e, 0x61, 0xda, 0x5f, 0x81, 0x7e, 0xd7, 0x6f, 0xbc, 0xf6, 0xdd, 0x30, 0x7d, 0xfe, 0x91, 0x6c, 0x4c, 0x84, 0x55,
213        0xdf, 0xa5, 0x89, 0x5a, 0x4e, 0xba, 0x4f, 0x08, 0xe9, 0xff, 0xf7, 0x2d, 0xc9, 0xbe, 0x22, 0xf9, 0xfe, 0xd5, 0x03, 0xbc,
214        0x4c, 0xee, 0xfc, 0x24, 0x70, 0x40, 0xd3, 0x3d, 0x7e, 0x8e, 0x8f, 0x57, 0xf2, 0x19, 0xd5, 0x0d, 0x8a, 0x44, 0xf8, 0x1e,
215        0x47, 0x89, 0x93, 0xc5, 0x5d, 0xce, 0x00, 0x07, 0x07, 0xa6, 0x45, 0xe9, 0x57, 0x85, 0x5d, 0x63, 0x58, 0xac, 0xa8, 0xa9,
216        0xfe, 0x34, 0x0d, 0x72, 0x5e, 0x5b, 0xc8, 0x69, 0x66, 0x96, 0x96, 0x2a, 0x57, 0x50, 0xb5, 0x61, 0xd2, 0xae, 0x0d, 0x9f,
217        0x9d, 0x94, 0x8b, 0x38, 0x3a, 0xcc, 0xc3, 0x4e, 0xf2, 0xdb, 0xdf, 0x79, 0x7a, 0xd5, 0x21, 0xb3, 0xab, 0x2d, 0x43, 0x19,
218        0x82, 0x1a, 0x41, 0x22, 0x01, 0xe3, 0xe5, 0x87, 0x21, 0x0b, 0xf5, 0x2e, 0x79, 0x1f, 0x33, 0x2c, 0x6b, 0x90, 0x9c, 0xf4,
219        0xd2, 0x28, 0x1c, 0xe6, 0xf1, 0xd3, 0x45, 0x05, 0xe8, 0x5e, 0x96, 0x7f, 0x24, 0xb9, 0x68, 0x4a, 0xbf, 0x3d, 0x7d, 0x0c,
220        0xad, 0x59, 0x25, 0xc1, 0x4a, 0xd2, 0x97, 0x2a, 0xc0, 0xb7, 0x64, 0x26, 0x20, 0x44, 0xa2, 0x5a, 0xc4, 0x46, 0xe6, 0x1d,
221        0x95, 0xe1, 0xdb, 0x82, 0x55, 0x3c, 0x8b, 0xd8, 0xfa, 0x2a, 0x2a, 0x5e, 0x04, 0x30, 0x76, 0xf8,
222    ];
223    // Create a FFDHE2048 DheActiveKeyExchange object based on a known private key
224    let named_group = rustls::NamedGroup::FFDHE2048;
225    let group = rustls::ffdhe_groups::FFDHE2048;
226    let g = mbedtls::bignum::Mpi::from_binary(group.g).unwrap();
227    let p = mbedtls::bignum::Mpi::from_binary(group.p).unwrap();
228    let self_private_key = mbedtls::bignum::Mpi::from_binary(&server_private_key_vec).unwrap();
229    let self_public_key = g
230        .mod_exp(&self_private_key, &p)
231        .unwrap();
232    let self_public_key_vec = self_public_key
233        .to_binary_padded(group.p.len())
234        .unwrap();
235    let dhe_kx = Box::new(crate::kx::DheActiveKeyExchangeImpl::new(
236        named_group,
237        group,
238        std::sync::Mutex::new(p),
239        std::sync::Mutex::new(self_private_key),
240        self_public_key_vec,
241    ));
242    // Compute share secret again a known peer public key
243    let shared_secret = dhe_kx
244        .complete(&peer_public_key_vec)
245        .unwrap();
246    // Check result
247    assert_eq!(&expected_shared_secret, shared_secret.secret_bytes());
248}
249
250/// Run all the self_tests. If any test fails, this function will panic.
251///
252/// If `verbose` is true, print messages about tests that have been executed.
253pub fn self_tests(verbose: bool) {
254    macro_rules! print_msg {
255        ($($tt: tt)*) => {
256            if verbose { std::println!($($tt)*) }
257        };
258    }
259
260    #[cfg(feature = "tls12")]
261    {
262        tls12_sha256_prf_test_1();
263        print_msg!("tls12_sha256_prf_test_1 passed.");
264        tls12_sha256_prf_test_2();
265        print_msg!("tls12_sha256_prf_test_2 passed.");
266        tls12_sha384_prf_test_1();
267        print_msg!("tls12_sha384_prf_test_1 passed.");
268        tls12_sha384_prf_test_2();
269        print_msg!("tls12_sha384_prf_test_2 passed.");
270    }
271
272    tls13_kdf_test_case_1();
273    print_msg!("tls13_kdf_test_case_1 passed.");
274    tls13_kdf_test_case_2();
275    print_msg!("tls13_kdf_test_case_2 passed.");
276    tls13_kdf_test_case_3();
277    print_msg!("tls13_kdf_test_case_3 passed.");
278    ffdhe_crypto_algo_self_test();
279    print_msg!("ffdhe_crypto_algo_self_test passed.");
280
281    print_msg!("All rustls-mbedcrypto-provider self-tests passed.");
282}
283
284#[test]
285fn self_tests_succeed() {
286    self_tests(true)
287}