rustls_ffi/crypto_provider.rs
1use std::slice;
2use std::sync::Arc;
3
4use libc::size_t;
5
6use rustls::SupportedCipherSuite;
7#[cfg(feature = "aws-lc-rs")]
8use rustls::crypto::aws_lc_rs;
9#[cfg(feature = "ring")]
10use rustls::crypto::ring;
11use rustls::crypto::{CryptoProvider, hpke};
12use rustls::pki_types::PrivateKeyDer;
13use rustls::pki_types::pem::PemObject;
14use rustls::sign::SigningKey;
15
16use crate::cipher::rustls_supported_ciphersuite;
17use crate::error::{map_error, rustls_result};
18use crate::ffi::{
19 arc_castable, box_castable, free_arc, free_box, ref_castable, set_arc_mut_ptr,
20 set_boxed_mut_ptr, to_boxed_mut_ptr, try_clone_arc, try_mut_from_ptr, try_mut_from_ptr_ptr,
21 try_ref_from_ptr, try_ref_from_ptr_ptr, try_slice, try_slice_mut, try_take,
22};
23use crate::panic::ffi_panic_boundary;
24
25box_castable! {
26 /// A `rustls_crypto_provider` builder.
27 pub struct rustls_crypto_provider_builder(Option<CryptoProviderBuilder>);
28}
29
30/// A builder for customizing a `CryptoProvider`. Can be used to install a process-wide default.
31#[derive(Debug)]
32pub struct CryptoProviderBuilder {
33 base: Arc<CryptoProvider>,
34 cipher_suites: Vec<SupportedCipherSuite>,
35}
36
37impl CryptoProviderBuilder {
38 fn build_provider(self) -> CryptoProvider {
39 let cipher_suites = match self.cipher_suites.is_empty() {
40 true => self.base.cipher_suites.clone(),
41 false => self.cipher_suites,
42 };
43
44 // Unfortunately we can't use the `..` syntax to fill in the rest of the provider
45 // fields, because we're working with `Arc<CryptoProvider>` as the base,
46 // not `CryptoProvider`.
47 // TODO(#450): once MSRV is 1.76+, use `Arc::unwrap_or_clone`.
48 CryptoProvider {
49 cipher_suites,
50 kx_groups: self.base.kx_groups.clone(),
51 signature_verification_algorithms: self.base.signature_verification_algorithms,
52 secure_random: self.base.secure_random,
53 key_provider: self.base.key_provider,
54 }
55 }
56}
57
58/// Constructs a new `rustls_crypto_provider_builder` using the process-wide default crypto
59/// provider as the base crypto provider to be customized.
60///
61/// When this function returns `rustls_result::Ok` a pointer to the `rustls_crypto_provider_builder`
62/// is written to `builder_out`. It returns `rustls_result::NoDefaultCryptoProvider` if no default
63/// provider has been registered.
64///
65/// The caller owns the returned `rustls_crypto_provider_builder` and must free it using
66/// `rustls_crypto_provider_builder_free`.
67///
68/// This function is typically used for customizing the default crypto provider for specific
69/// connections. For example, a typical workflow might be to:
70///
71/// * Either:
72/// * Use the default `aws-lc-rs` or `*ring*` provider that rustls-ffi is built with based on
73/// the `CRYPTO_PROVIDER` build variable.
74/// * Call `rustls_crypto_provider_builder_new_with_base` with the desired provider, and
75/// then install it as the process default with
76/// `rustls_crypto_provider_builder_build_as_default`.
77/// * Afterward, as required for customization:
78/// * Use `rustls_crypto_provider_builder_new_from_default` to get a builder backed by the
79/// default crypto provider.
80/// * Use `rustls_crypto_provider_builder_set_cipher_suites` to customize the supported
81/// ciphersuites.
82/// * Use `rustls_crypto_provider_builder_build` to build a customized provider.
83/// * Provide that customized provider to client or server configuration builders.
84#[no_mangle]
85pub extern "C" fn rustls_crypto_provider_builder_new_from_default(
86 builder_out: *mut *mut rustls_crypto_provider_builder,
87) -> rustls_result {
88 ffi_panic_boundary! {
89 let provider_out = try_mut_from_ptr_ptr!(builder_out);
90
91 let base = match get_default_or_install_from_crate_features() {
92 Some(provider) => provider,
93 None => return rustls_result::NoDefaultCryptoProvider,
94 };
95
96 set_boxed_mut_ptr(
97 provider_out,
98 Some(CryptoProviderBuilder {
99 base,
100 cipher_suites: Vec::default(),
101 }),
102 );
103
104 rustls_result::Ok
105 }
106}
107
108/// Constructs a new `rustls_crypto_provider_builder` using the given `rustls_crypto_provider`
109/// as the base crypto provider to be customized.
110///
111/// The caller owns the returned `rustls_crypto_provider_builder` and must free it using
112/// `rustls_crypto_provider_builder_free`.
113///
114/// This function can be used for setting the default process wide crypto provider,
115/// or for constructing a custom crypto provider for a specific connection. A typical
116/// workflow could be to:
117///
118/// * Call `rustls_crypto_provider_builder_new_with_base` with a custom provider
119/// * Install the custom provider as the process-wide default with
120/// `rustls_crypto_provider_builder_build_as_default`.
121///
122/// Or, for per-connection customization:
123///
124/// * Call `rustls_crypto_provider_builder_new_with_base` with a custom provider
125/// * Use `rustls_crypto_provider_builder_set_cipher_suites` to customize the supported
126/// ciphersuites.
127/// * Use `rustls_crypto_provider_builder_build` to build a customized provider.
128/// * Provide that customized provider to client or server configuration builders.
129#[no_mangle]
130pub extern "C" fn rustls_crypto_provider_builder_new_with_base(
131 base: *const rustls_crypto_provider,
132) -> *mut rustls_crypto_provider_builder {
133 ffi_panic_boundary! {
134 to_boxed_mut_ptr(Some(CryptoProviderBuilder {
135 base: try_clone_arc!(base),
136 cipher_suites: Vec::default(),
137 }))
138 }
139}
140
141/// Customize the supported ciphersuites of the `rustls_crypto_provider_builder`.
142///
143/// Returns an error if the builder has already been built. Overwrites any previously
144/// set ciphersuites.
145#[no_mangle]
146pub extern "C" fn rustls_crypto_provider_builder_set_cipher_suites(
147 builder: *mut rustls_crypto_provider_builder,
148 cipher_suites: *const *const rustls_supported_ciphersuite,
149 cipher_suites_len: size_t,
150) -> rustls_result {
151 ffi_panic_boundary! {
152 let builder = try_mut_from_ptr!(builder);
153 let builder = match builder {
154 Some(builder) => builder,
155 None => return rustls_result::AlreadyUsed,
156 };
157
158 let cipher_suites = try_slice!(cipher_suites, cipher_suites_len);
159 let mut supported_cipher_suites = Vec::new();
160 for cs in cipher_suites {
161 let cs = *cs;
162 let cs = try_ref_from_ptr!(cs);
163 supported_cipher_suites.push(*cs);
164 }
165
166 builder.cipher_suites = supported_cipher_suites;
167 rustls_result::Ok
168 }
169}
170
171/// Builds a `rustls_crypto_provider` from the builder and returns it. Returns an error if the
172/// builder has already been built.
173///
174/// The `rustls_crypto_provider_builder` builder is consumed and should not be used
175/// for further calls, except to `rustls_crypto_provider_builder_free`. The caller must
176/// still free the builder after a successful build.
177#[no_mangle]
178pub extern "C" fn rustls_crypto_provider_builder_build(
179 builder: *mut rustls_crypto_provider_builder,
180 provider_out: *mut *const rustls_crypto_provider,
181) -> rustls_result {
182 ffi_panic_boundary! {
183 let builder = try_mut_from_ptr!(builder);
184 set_arc_mut_ptr(
185 try_ref_from_ptr_ptr!(provider_out),
186 try_take!(builder).build_provider(),
187 );
188 rustls_result::Ok
189 }
190}
191
192/// Builds a `rustls_crypto_provider` from the builder and sets it as the
193/// process-wide default crypto provider.
194///
195/// Afterward, the default provider can be retrieved using `rustls_crypto_provider_default`.
196///
197/// This can only be done once per process, and will return an error if a
198/// default provider has already been set, or if the builder has already been built.
199///
200/// The `rustls_crypto_provider_builder` builder is consumed and should not be used
201/// for further calls, except to `rustls_crypto_provider_builder_free`. The caller must
202/// still free the builder after a successful build.
203#[no_mangle]
204pub extern "C" fn rustls_crypto_provider_builder_build_as_default(
205 builder: *mut rustls_crypto_provider_builder,
206) -> rustls_result {
207 let builder = try_mut_from_ptr!(builder);
208 match try_take!(builder).build_provider().install_default() {
209 Ok(_) => rustls_result::Ok,
210 Err(_) => rustls_result::AlreadyUsed,
211 }
212}
213
214/// Free the `rustls_crypto_provider_builder`.
215///
216/// Calling with `NULL` is fine.
217/// Must not be called twice with the same value.
218#[no_mangle]
219pub extern "C" fn rustls_crypto_provider_builder_free(
220 builder: *mut rustls_crypto_provider_builder,
221) {
222 ffi_panic_boundary! {
223 free_box(builder);
224 }
225}
226
227/// Return the `rustls_crypto_provider` backed by the `*ring*` cryptography library.
228///
229/// The caller owns the returned `rustls_crypto_provider` and must free it using
230/// `rustls_crypto_provider_free`.
231#[no_mangle]
232#[cfg(feature = "ring")]
233pub extern "C" fn rustls_ring_crypto_provider() -> *const rustls_crypto_provider {
234 ffi_panic_boundary! {
235 Arc::into_raw(Arc::new(ring::default_provider())) as *const rustls_crypto_provider
236 }
237}
238
239/// Return the `rustls_crypto_provider` backed by the `aws-lc-rs` cryptography library.
240///
241/// The caller owns the returned `rustls_crypto_provider` and must free it using
242/// `rustls_crypto_provider_free`.
243#[no_mangle]
244#[cfg(feature = "aws-lc-rs")]
245pub extern "C" fn rustls_aws_lc_rs_crypto_provider() -> *const rustls_crypto_provider {
246 ffi_panic_boundary! {
247 Arc::into_raw(Arc::new(aws_lc_rs::default_provider())) as *const rustls_crypto_provider
248 }
249}
250
251/// Return a `rustls_crypto_provider` that uses FIPS140-3 approved cryptography.
252///
253/// Using this function expresses in your code that you require FIPS-approved cryptography,
254/// and will not compile if you make a mistake with cargo features.
255///
256/// See the upstream [rustls FIPS documentation][FIPS] for more information.
257///
258/// The caller owns the returned `rustls_crypto_provider` and must free it using
259/// `rustls_crypto_provider_free`.
260///
261/// [FIPS]: https://docs.rs/rustls/latest/rustls/manual/_06_fips/index.html
262#[no_mangle]
263#[cfg(feature = "fips")]
264pub extern "C" fn rustls_default_fips_provider() -> *const rustls_crypto_provider {
265 ffi_panic_boundary! {
266 Arc::into_raw(Arc::new(rustls::crypto::default_fips_provider()))
267 as *const rustls_crypto_provider
268 }
269}
270
271/// Retrieve a pointer to the process default `rustls_crypto_provider`.
272///
273/// This may return `NULL` if no process default provider has been set using
274/// `rustls_crypto_provider_builder_build_default`.
275///
276/// Caller owns the returned `rustls_crypto_provider` and must free it w/ `rustls_crypto_provider_free`.
277#[no_mangle]
278pub extern "C" fn rustls_crypto_provider_default() -> *const rustls_crypto_provider {
279 ffi_panic_boundary! {
280 match CryptoProvider::get_default() {
281 Some(provider) => Arc::into_raw(provider.clone()) as *const rustls_crypto_provider,
282 None => core::ptr::null(),
283 }
284 }
285}
286
287arc_castable! {
288 /// A C representation of a Rustls [`CryptoProvider`].
289 pub struct rustls_crypto_provider(CryptoProvider);
290}
291
292/// Returns the number of ciphersuites the `rustls_crypto_provider` supports.
293///
294/// You can use this to know the maximum allowed index for use with
295/// `rustls_crypto_provider_ciphersuites_get`.
296///
297/// This function will return 0 if the `provider` is NULL.
298#[no_mangle]
299pub extern "C" fn rustls_crypto_provider_ciphersuites_len(
300 provider: *const rustls_crypto_provider,
301) -> usize {
302 ffi_panic_boundary! {
303 try_clone_arc!(provider).cipher_suites.len()
304 }
305}
306
307/// Retrieve a pointer to a supported ciphersuite of the `rustls_crypto_provider`.
308///
309/// This function will return NULL if the `provider` is NULL, or if the index is out of bounds
310/// with respect to `rustls_crypto_provider_ciphersuites_len`.
311///
312/// The lifetime of the returned `rustls_supported_ciphersuite` is equal to the lifetime of the
313/// `provider` and should not be used after the `provider` is freed.
314#[no_mangle]
315pub extern "C" fn rustls_crypto_provider_ciphersuites_get(
316 provider: *const rustls_crypto_provider,
317 index: usize,
318) -> *const rustls_supported_ciphersuite {
319 ffi_panic_boundary! {
320 match try_clone_arc!(provider).cipher_suites.get(index) {
321 Some(ciphersuite) => ciphersuite as *const SupportedCipherSuite as *const _,
322 None => core::ptr::null(),
323 }
324 }
325}
326
327/// Load a private key from the provided PEM content using the crypto provider.
328///
329/// `private_key` must point to a buffer of `private_key_len` bytes, containing
330/// a PEM-encoded private key. The exact formats supported will differ based on
331/// the crypto provider in use. The default providers support PKCS#1, PKCS#8 or
332/// SEC1 formats.
333///
334/// When this function returns `rustls_result::Ok` a pointer to a `rustls_signing_key`
335/// is written to `signing_key_out`. The caller owns the returned `rustls_signing_key`
336/// and must free it with `rustls_signing_key_free`.
337#[no_mangle]
338pub extern "C" fn rustls_crypto_provider_load_key(
339 provider: *const rustls_crypto_provider,
340 private_key: *const u8,
341 private_key_len: size_t,
342 signing_key_out: *mut *mut rustls_signing_key,
343) -> rustls_result {
344 ffi_panic_boundary! {
345 let provider = try_clone_arc!(provider);
346 let private_key_pem = try_slice!(private_key, private_key_len);
347 let signing_key_out = try_mut_from_ptr_ptr!(signing_key_out);
348
349 let private_key_der = match PrivateKeyDer::from_pem_slice(private_key_pem) {
350 Ok(der) => der,
351 Err(_) => return rustls_result::PrivateKeyParseError,
352 };
353
354 let private_key = match provider.key_provider.load_private_key(private_key_der) {
355 Ok(key) => key,
356 Err(e) => return map_error(e),
357 };
358
359 set_boxed_mut_ptr(signing_key_out, private_key);
360 rustls_result::Ok
361 }
362}
363
364/// Write `len` bytes of cryptographically secure random data to `buff` using the crypto provider.
365///
366/// `buff` must point to a buffer of at least `len` bytes. The caller maintains ownership
367/// of the buffer.
368///
369/// Returns `RUSTLS_RESULT_OK` on success, or `RUSTLS_RESULT_GET_RANDOM_FAILED` on failure.
370#[no_mangle]
371pub extern "C" fn rustls_crypto_provider_random(
372 provider: *const rustls_crypto_provider,
373 buff: *mut u8,
374 len: size_t,
375) -> rustls_result {
376 ffi_panic_boundary! {
377 match try_clone_arc!(provider)
378 .secure_random
379 .fill(try_slice_mut!(buff, len))
380 {
381 Ok(_) => rustls_result::Ok,
382 Err(_) => rustls_result::GetRandomFailed,
383 }
384 }
385}
386
387/// Returns true if the `rustls_crypto_provider` is operating in FIPS mode.
388///
389/// This covers only the cryptographic parts of FIPS approval. There are also
390/// TLS protocol-level recommendations made by NIST. You should prefer to call
391/// `rustls_client_config_fips` or `rustls_server_config_fips` which take these
392/// into account.
393#[no_mangle]
394pub extern "C" fn rustls_crypto_provider_fips(provider: *const rustls_crypto_provider) -> bool {
395 ffi_panic_boundary! {
396 try_ref_from_ptr!(provider).fips()
397 }
398}
399
400/// Frees the `rustls_crypto_provider`.
401///
402/// Calling with `NULL` is fine.
403/// Must not be called twice with the same value.
404#[no_mangle]
405pub extern "C" fn rustls_crypto_provider_free(provider: *const rustls_crypto_provider) {
406 ffi_panic_boundary! {
407 free_arc(provider);
408 }
409}
410
411/// Returns the number of ciphersuites the default process-wide crypto provider supports.
412///
413/// You can use this to know the maximum allowed index for use with
414/// `rustls_default_crypto_provider_ciphersuites_get`.
415///
416/// This function will return 0 if no process-wide default `rustls_crypto_provider` is available.
417#[no_mangle]
418pub extern "C" fn rustls_default_crypto_provider_ciphersuites_len() -> usize {
419 ffi_panic_boundary! {
420 match get_default_or_install_from_crate_features() {
421 Some(provider) => provider.cipher_suites.len(),
422 None => return 0,
423 }
424 }
425}
426
427/// Retrieve a pointer to a supported ciphersuite of the default process-wide crypto provider.
428///
429/// This function will return NULL if the `provider` is NULL, or if the index is out of bounds
430/// with respect to `rustls_default_crypto_provider_ciphersuites_len`.
431///
432/// The lifetime of the returned `rustls_supported_ciphersuite` is static, as the process-wide
433/// default provider lives for as long as the process.
434#[no_mangle]
435pub extern "C" fn rustls_default_crypto_provider_ciphersuites_get(
436 index: usize,
437) -> *const rustls_supported_ciphersuite {
438 ffi_panic_boundary! {
439 let default_provider = match get_default_or_install_from_crate_features() {
440 Some(provider) => provider,
441 None => return core::ptr::null(),
442 };
443 match default_provider.cipher_suites.get(index) {
444 Some(ciphersuite) => ciphersuite as *const SupportedCipherSuite as *const _,
445 None => core::ptr::null(),
446 }
447 }
448}
449
450/// Write `len` bytes of cryptographically secure random data to `buff` using the process-wide
451/// default crypto provider.
452///
453/// `buff` must point to a buffer of at least `len` bytes. The caller maintains ownership
454/// of the buffer.
455///
456/// Returns `RUSTLS_RESULT_OK` on success, and one of `RUSTLS_RESULT_NO_DEFAULT_CRYPTO_PROVIDER`
457/// or `RUSTLS_RESULT_GET_RANDOM_FAILED` on failure.
458#[no_mangle]
459pub extern "C" fn rustls_default_crypto_provider_random(
460 buff: *mut u8,
461 len: size_t,
462) -> rustls_result {
463 ffi_panic_boundary! {
464 match get_default_or_install_from_crate_features() {
465 Some(provider) => match provider.secure_random.fill(try_slice_mut!(buff, len)) {
466 Ok(_) => rustls_result::Ok,
467 Err(_) => rustls_result::GetRandomFailed,
468 },
469 None => rustls_result::NoDefaultCryptoProvider,
470 }
471 }
472}
473
474box_castable! {
475 /// A signing key that can be used to construct a certified key.
476 // NOTE: we box cast an arc over the dyn trait per the pattern described
477 // in our docs[0] for dynamically sized types.
478 // [0]: <https://github.com/rustls/rustls-ffi/blob/main/CONTRIBUTING.md#dynamically-sized-types>
479 pub struct rustls_signing_key(Arc<dyn SigningKey>);
480}
481
482impl rustls_signing_key {
483 /// Frees the `rustls_signing_key`. This is safe to call with a `NULL` argument, but
484 /// must not be called twice with the same value.
485 #[no_mangle]
486 pub extern "C" fn rustls_signing_key_free(signing_key: *mut rustls_signing_key) {
487 ffi_panic_boundary! {
488 free_box(signing_key);
489 }
490 }
491}
492
493ref_castable! {
494 /// A collection of supported Hybrid Public Key Encryption (HPKE) suites.
495 ///
496 /// `rustls_hpke` can be provided to `rustls_client_config_builder_enable_ech` and
497 /// `rustls_client_config_builder_enable_ech_grease()` to customize a
498 /// `rustls_client_config_builder` to use Encrypted Client Hello (ECH).
499 pub struct rustls_hpke(Hpke);
500}
501
502pub(crate) struct Hpke {
503 pub(crate) suites: &'static [&'static dyn hpke::Hpke],
504}
505
506impl Hpke {
507 /// Chooses a random supported HPKE suite and generates a throw-away public key.
508 ///
509 /// Returns both the selected Rustls `hpke::Hpke` suite and the `hpke::HpkePublicKey`
510 /// or `None` if an error occurs.
511 pub(crate) fn grease_public_key(
512 &self,
513 provider: &CryptoProvider,
514 ) -> Option<(&dyn hpke::Hpke, hpke::HpkePublicKey)> {
515 let num_suites = self.suites.len();
516 if num_suites == 0 {
517 return None;
518 }
519 debug_assert!(num_suites < u32::MAX as usize);
520
521 let mut buf = [0u8; 4];
522 let threshold = u32::MAX - (u32::MAX % num_suites as u32);
523 let suite = loop {
524 provider.secure_random.fill(&mut buf).ok()?;
525 let value = u32::from_ne_bytes(buf);
526 if value < threshold {
527 break self.suites[value as usize / (threshold as usize / num_suites)];
528 }
529 };
530
531 let pk = suite.generate_key_pair().map(|pair| pair.0).ok()?;
532 Some((suite, pk))
533 }
534}
535
536#[cfg(feature = "aws-lc-rs")]
537static AWS_LC_RS_HPKE: &Hpke = &Hpke {
538 suites: aws_lc_rs::hpke::ALL_SUPPORTED_SUITES,
539};
540
541/// Returns a pointer to the supported `rustls_hpke` Hybrid Public Key Encryption (HPKE)
542/// suites, or `NULL` if HPKE is not supported.
543///
544/// HPKE is only supported with the `aws-lc-rs` cryptography provider.
545///
546/// The returned pointer has a static lifetime equal to that of the program and does not
547/// need to be freed.
548#[no_mangle]
549pub extern "C" fn rustls_supported_hpke() -> *const rustls_hpke {
550 ffi_panic_boundary! {
551 #[cfg(feature = "aws-lc-rs")]
552 {
553 AWS_LC_RS_HPKE as *const _ as _
554 }
555 #[cfg(not(feature = "aws-lc-rs"))]
556 {
557 core::ptr::null()
558 }
559 }
560}
561
562pub(crate) fn get_default_or_install_from_crate_features() -> Option<Arc<CryptoProvider>> {
563 // If a process-wide default has already been installed, return it.
564 if let Some(provider) = CryptoProvider::get_default() {
565 return Some(provider.clone());
566 }
567
568 // Ignore the error resulting from us losing a race to install the default,
569 // and accept the outcome.
570 let _ = provider_from_crate_features()?.install_default();
571
572 // Safety: we can unwrap safely here knowing we've just set the default, or
573 // lost a race to something else setting the default.
574 Some(CryptoProvider::get_default().unwrap().clone())
575}
576
577fn provider_from_crate_features() -> Option<CryptoProvider> {
578 // Provider default is unambiguously aws-lc-rs
579 #[cfg(all(feature = "aws-lc-rs", not(feature = "ring")))]
580 {
581 return Some(aws_lc_rs::default_provider());
582 }
583
584 // Provider default is unambiguously ring
585 #[cfg(all(feature = "ring", not(feature = "aws-lc-rs")))]
586 {
587 return Some(ring::default_provider());
588 }
589
590 // Both features activated - no clear default provider based on
591 // crate features.
592 #[allow(unreachable_code)]
593 None
594}
595
596#[cfg(all(test, not(miri), any(feature = "aws-lc-rs", feature = "ring")))]
597mod tests {
598 use std::ptr;
599
600 use crate::rustls_result;
601
602 use super::*;
603
604 /// Simple smoketest of CSRNG fill with specific provider.
605 #[test]
606 fn random_data() {
607 let provider = rustls_crypto_provider_default();
608 assert!(!provider.is_null());
609
610 // NULL buffer should return an error.
611 let result = rustls_crypto_provider_random(provider, ptr::null_mut(), 1337);
612 assert_eq!(result, rustls_result::NullParameter);
613
614 let mut buff = vec![0; 32];
615
616 // NULL provider should return an error and not touch buff.
617 let result = rustls_crypto_provider_random(ptr::null(), buff.as_mut_ptr(), buff.len());
618 assert_eq!(buff, vec![0; 32]);
619 assert_eq!(result, rustls_result::NullParameter);
620
621 // Proper parameters should return OK and overwrite the buffer.
622 let result = rustls_crypto_provider_random(provider, buff.as_mut_ptr(), buff.len());
623 assert_eq!(result, rustls_result::Ok);
624 assert_ne!(buff, vec![0; 32]);
625 }
626
627 /// Simple smoketest of CSRNG fill with default provider.
628 #[test]
629 fn default_random_data() {
630 // NULL buffer should return an error.
631 let result = rustls_default_crypto_provider_random(ptr::null_mut(), 1337);
632 assert_eq!(result, rustls_result::NullParameter);
633
634 let mut buff = vec![0; 32];
635
636 // Proper parameters should return OK and overwrite the buffer.
637 let result = rustls_default_crypto_provider_random(buff.as_mut_ptr(), buff.len());
638 assert_eq!(result, rustls_result::Ok);
639 assert_ne!(buff, vec![0; 32]);
640 }
641
642 #[test]
643 #[cfg(feature = "aws-lc-rs")]
644 fn test_hpke_aws_lc_rs() {
645 let provider = rustls_crypto_provider_default();
646 assert!(!provider.is_null());
647 let provider = try_clone_arc!(provider);
648
649 let hpke = rustls_supported_hpke();
650 assert!(!hpke.is_null());
651
652 let hpke = try_ref_from_ptr!(hpke);
653
654 // We should be able to pick an HPKE suite and a pubkey for ECH GREASE.
655 let (suite, pk) = hpke.grease_public_key(&provider).unwrap();
656 // The PK and the suite should be compatible. Setup a sealer to check.
657 let (_, _) = suite.setup_sealer(&[0xC0, 0xFF, 0xEE], &pk).unwrap();
658 }
659
660 #[test]
661 #[cfg(not(feature = "aws-lc-rs"))]
662 fn test_hpke_not_aws_lc_rs() {
663 assert!(rustls_supported_hpke().is_null());
664 }
665}