Coverage Report

Created: 2026-05-18 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/git/checkouts/nss-rs-71e20fe79ef91440/9b94ca3/src/ssl.rs
Line
Count
Source
1
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4
// option. This file may not be copied, modified, or distributed
5
// except according to those terms.
6
7
use std::os::raw::{c_uint, c_void};
8
9
use crate::{
10
    Epoch,
11
    err::{Res, secstatus_to_res},
12
    nss_prelude::SECStatus,
13
    prio::PRFileDesc,
14
};
15
16
mod nss_ssl {
17
    #![allow(
18
        dead_code,
19
        non_upper_case_globals,
20
        non_snake_case,
21
        nonstandard_style,
22
        unsafe_op_in_unsafe_fn,
23
        unused_qualifications,
24
        clippy::all,
25
        clippy::nursery,
26
        clippy::pedantic,
27
        clippy::restriction,
28
        reason = "For included bindgen code."
29
    )]
30
    use crate::{
31
        err::PRErrorCode,
32
        nss_prelude::*,
33
        p11::{CERTCertificateStr, HpkeAeadId, HpkeKdfId, PK11SymKeyStr, SECKEYPrivateKeyStr},
34
        prio::{PRFileDesc, PRFileInfo, PRFileInfo64, PRIOVec},
35
        time::PRTime,
36
    };
37
38
    include!(concat!(env!("OUT_DIR"), "/nss_ssl.rs"));
39
}
40
pub use nss_ssl::*;
41
42
#[expect(non_snake_case, unused, reason = "OK here.")]
43
mod SSLOption {
44
    include!(concat!(env!("OUT_DIR"), "/nss_sslopt.rs"));
45
}
46
47
// Remap some constants.
48
#[expect(non_upper_case_globals, reason = "OK here.")]
49
pub const SECSuccess: SECStatus = _SECStatus_SECSuccess;
50
#[expect(non_upper_case_globals, reason = "OK here.")]
51
pub const SECFailure: SECStatus = _SECStatus_SECFailure;
52
53
#[derive(Debug, Copy, Clone)]
54
#[repr(u32)]
55
pub enum Opt {
56
    Locking = SSLOption::SSL_NO_LOCKS,
57
    Tickets = SSLOption::SSL_ENABLE_SESSION_TICKETS,
58
    OcspStapling = SSLOption::SSL_ENABLE_OCSP_STAPLING,
59
    Alpn = SSLOption::SSL_ENABLE_ALPN,
60
    ExtendedMasterSecret = SSLOption::SSL_ENABLE_EXTENDED_MASTER_SECRET,
61
    SignedCertificateTimestamps = SSLOption::SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
62
    EarlyData = SSLOption::SSL_ENABLE_0RTT_DATA,
63
    RecordSizeLimit = SSLOption::SSL_RECORD_SIZE_LIMIT,
64
    Tls13CompatMode = SSLOption::SSL_ENABLE_TLS13_COMPAT_MODE,
65
    HelloDowngradeCheck = SSLOption::SSL_ENABLE_HELLO_DOWNGRADE_CHECK,
66
    SuppressEndOfEarlyData = SSLOption::SSL_SUPPRESS_END_OF_EARLY_DATA,
67
    Grease = SSLOption::SSL_ENABLE_GREASE,
68
    EnableChExtensionPermutation = SSLOption::SSL_ENABLE_CH_EXTENSION_PERMUTATION,
69
}
70
71
impl Opt {
72
    #[must_use]
73
18.0k
    pub const fn as_int(self) -> PRInt32 {
74
18.0k
        self as PRInt32
75
18.0k
    }
76
77
    // Some options are backwards, like SSL_NO_LOCKS, so use this to manage that.
78
18.0k
    fn map_enabled(self, enabled: bool) -> PRIntn {
79
18.0k
        let v = match self {
80
2.57k
            Self::Locking => !enabled,
81
15.4k
            _ => enabled,
82
        };
83
18.0k
        PRIntn::from(v)
84
18.0k
    }
85
86
18.0k
    pub(crate) fn set(self, fd: *mut PRFileDesc, value: bool) -> Res<()> {
87
18.0k
        secstatus_to_res(unsafe { SSL_OptionSet(fd, self.as_int(), self.map_enabled(value)) })
88
18.0k
    }
89
}
90
91
experimental_api!(SSL_HelloRetryRequestCallback(
92
    fd: *mut PRFileDesc,
93
    cb: SSLHelloRetryRequestCallback,
94
    arg: *mut c_void,
95
));
96
experimental_api!(SSL_RecordLayerWriteCallback(
97
    fd: *mut PRFileDesc,
98
    cb: SSLRecordWriteCallback,
99
    arg: *mut c_void,
100
));
101
experimental_api!(SSL_RecordLayerData(
102
    fd: *mut PRFileDesc,
103
    epoch: Epoch,
104
    ct: SSLContentType::Type,
105
    data: *const u8,
106
    len: c_uint,
107
));
108
experimental_api!(SSL_SendSessionTicket(
109
    fd: *mut PRFileDesc,
110
    extra: *const u8,
111
    len: c_uint,
112
));
113
experimental_api!(SSL_SetMaxEarlyDataSize(fd: *mut PRFileDesc, size: u32));
114
experimental_api!(SSL_SetResumptionToken(
115
    fd: *mut PRFileDesc,
116
    token: *const u8,
117
    len: c_uint,
118
));
119
experimental_api!(SSL_SetResumptionTokenCallback(
120
    fd: *mut PRFileDesc,
121
    cb: SSLResumptionTokenCallback,
122
    arg: *mut c_void,
123
));
124
125
experimental_api!(SSL_GetResumptionTokenInfo(
126
    token: *const u8,
127
    token_len: c_uint,
128
    info: *mut SSLResumptionTokenInfo,
129
    len: c_uint,
130
));
131
132
experimental_api!(SSL_DestroyResumptionTokenInfo(
133
    info: *mut SSLResumptionTokenInfo,
134
));
135
136
experimental_api!(SSL_SetCertificateCompressionAlgorithm(
137
    fd: *mut PRFileDesc,
138
    t: SSLCertificateCompressionAlgorithm,
139
));
140
141
#[cfg(test)]
142
#[cfg_attr(coverage_nightly, coverage(off))]
143
mod tests {
144
    use super::{SSL_GetNumImplementedCiphers, SSL_NumImplementedCiphers};
145
146
    #[test]
147
    fn num_ciphers() {
148
        assert!(unsafe { SSL_NumImplementedCiphers } > 0);
149
        assert!(unsafe { SSL_GetNumImplementedCiphers() } > 0);
150
        assert_eq!(unsafe { SSL_NumImplementedCiphers }, unsafe {
151
            SSL_GetNumImplementedCiphers()
152
        });
153
    }
154
}