rustls_ffi/
cipher.rs

1use rustls::SupportedCipherSuite;
2
3use crate::enums::rustls_tls_version;
4use crate::ffi::{ref_castable, try_ref_from_ptr};
5use crate::panic::ffi_panic_boundary;
6use crate::rslice::rustls_str;
7
8ref_castable! {
9    /// A cipher suite supported by rustls.
10    pub struct rustls_supported_ciphersuite(SupportedCipherSuite);
11}
12
13impl rustls_supported_ciphersuite {
14    /// Return a 16-bit unsigned integer corresponding to this cipher suite's assignment from
15    /// <https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4>.
16    ///
17    /// The bytes from the assignment are interpreted in network order.
18    #[no_mangle]
19    pub extern "C" fn rustls_supported_ciphersuite_get_suite(
20        supported_ciphersuite: *const rustls_supported_ciphersuite,
21    ) -> u16 {
22        let supported_ciphersuite = try_ref_from_ptr!(supported_ciphersuite);
23        u16::from(
24            match supported_ciphersuite {
25                SupportedCipherSuite::Tls12(sc) => &sc.common,
26                SupportedCipherSuite::Tls13(sc) => &sc.common,
27            }
28            .suite,
29        )
30    }
31}
32
33/// Returns the name of the ciphersuite as a `rustls_str`.
34///
35/// If the provided ciphersuite is invalid, the `rustls_str` will contain the
36/// empty string. The lifetime of the `rustls_str` is the lifetime of the program,
37/// it does not need to be freed.
38#[no_mangle]
39pub extern "C" fn rustls_supported_ciphersuite_get_name(
40    supported_ciphersuite: *const rustls_supported_ciphersuite,
41) -> rustls_str<'static> {
42    let supported_ciphersuite = try_ref_from_ptr!(supported_ciphersuite);
43    let s = supported_ciphersuite.suite().as_str().unwrap_or("");
44    match rustls_str::try_from(s) {
45        Ok(s) => s,
46        Err(_) => rustls_str::from_str_unchecked(""),
47    }
48}
49
50/// Returns the `rustls_tls_version` of the ciphersuite.
51///
52/// See also `RUSTLS_ALL_VERSIONS`.
53#[no_mangle]
54pub extern "C" fn rustls_supported_ciphersuite_protocol_version(
55    supported_ciphersuite: *const rustls_supported_ciphersuite,
56) -> rustls_tls_version {
57    ffi_panic_boundary! {
58        rustls_tls_version::from(try_ref_from_ptr!(supported_ciphersuite).version())
59    }
60}
61
62#[cfg(all(test, any(feature = "ring", feature = "aws-lc-rs")))]
63mod tests {
64    use crate::crypto_provider::{
65        rustls_default_crypto_provider_ciphersuites_get,
66        rustls_default_crypto_provider_ciphersuites_len,
67    };
68
69    use super::*;
70
71    #[test]
72    fn default_cipher_suites() {
73        let num_suites = rustls_default_crypto_provider_ciphersuites_len();
74        assert!(num_suites > 2);
75        for i in 0..num_suites {
76            let suite = rustls_default_crypto_provider_ciphersuites_get(i);
77            let name = rustls_supported_ciphersuite_get_name(suite);
78            let name = unsafe { name.to_str() };
79            let proto = rustls_supported_ciphersuite_protocol_version(suite);
80            println!("{}: {} {:?}", i, name, proto);
81        }
82    }
83}