Skip to main content

Ssl

Struct Ssl 

Source
pub struct Ssl { /* private fields */ }
Expand description

Per-connection TLS object (SSL*).

Has exclusive ownership over its state; no Clone. BIOs passed to Ssl::set_bio_duplex or Ssl::set_bio are owned by the Ssl thereafter.

Implementations§

Source§

impl Ssl

Source

pub fn set_bio_duplex(&mut self, bio: Bio)

Set a single duplex BIO for both reading and writing.

Transfers ownership of bio to the SSL object; do not use bio afterwards. Suitable for BIO_new_bio_pair endpoints.

When rbio == wbio (same pointer), OpenSSL only increments the reference count once, so the single reference in bio is correct.

Examples found in repository?
examples/ssl.rs (line 63)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    // ── Key pair and self-signed certificate ───────────────────────────────────
16
17    let mut kgen = KeygenCtx::new(c"ED25519")?;
18    let priv_key = kgen.generate()?;
19    let pub_key = native_ossl::pkey::Pkey::<native_ossl::pkey::Public>::from(priv_key.clone());
20
21    let mut name = X509NameOwned::new()?;
22    name.add_entry_by_txt(c"CN", b"localhost")?;
23
24    let cert = X509Builder::new()?
25        .set_version(2)?
26        .set_serial_number(1)?
27        .set_not_before_offset(0)?
28        .set_not_after_offset(86400)?
29        .set_subject_name(&name)?
30        .set_issuer_name(&name)?
31        .set_public_key(&pub_key)?
32        .sign(&priv_key, None)?
33        .build();
34
35    // ── Server context ─────────────────────────────────────────────────────────
36
37    let server_ctx = SslCtx::new_server()?;
38    server_ctx.set_min_proto_version(TlsVersion::Tls13)?;
39    server_ctx.use_certificate(&cert)?;
40    server_ctx.use_private_key(&priv_key)?;
41    server_ctx.check_private_key()?;
42
43    // ── Client context ─────────────────────────────────────────────────────────
44
45    let client_ctx = SslCtx::new_client()?;
46    client_ctx.set_min_proto_version(TlsVersion::Tls13)?;
47    // Skip certificate verification for this self-signed example.
48    client_ctx.set_verify(SslVerifyMode::NONE);
49
50    // ── SSL objects ────────────────────────────────────────────────────────────
51
52    let mut client = client_ctx.new_ssl()?;
53    let mut server = server_ctx.new_ssl()?;
54
55    client.set_connect_state();
56    client.set_hostname(c"localhost")?;
57    server.set_accept_state();
58
59    // ── In-process BIO pair ────────────────────────────────────────────────────
60    // Data written to client_bio is readable from server_bio and vice-versa.
61
62    let (client_bio, server_bio) = Bio::new_pair()?;
63    client.set_bio_duplex(client_bio);
64    server.set_bio_duplex(server_bio);
65
66    // ── Drive the handshake ────────────────────────────────────────────────────
67    // Alternate between client and server until both report success.
68
69    let mut client_done = false;
70    let mut server_done = false;
71
72    for step in 0..20 {
73        if !client_done {
74            match client.connect() {
75                Ok(()) => {
76                    client_done = true;
77                    println!("Client handshake done at step {step}");
78                }
79                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
80                Err(e) => return Err(format!("client error: {e}").into()),
81            }
82        }
83        if !server_done {
84            match server.accept() {
85                Ok(()) => {
86                    server_done = true;
87                    println!("Server handshake done at step {step}");
88                }
89                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
90                Err(e) => return Err(format!("server error: {e}").into()),
91            }
92        }
93        if client_done && server_done {
94            break;
95        }
96    }
97    assert!(client_done && server_done, "handshake did not complete");
98
99    // ── Inspect the peer certificate on the client ─────────────────────────────
100
101    if let Some(peer_cert) = client.peer_certificate() {
102        if let Some(subject) = peer_cert.subject_name().to_string() {
103            println!("Server cert subject: {subject}");
104        }
105    }
106
107    // ── Application data exchange ──────────────────────────────────────────────
108
109    let request = b"GET / HTTP/1.0\r\n\r\n";
110    let response = b"HTTP/1.0 200 OK\r\n\r\nHello, TLS!";
111
112    let written = client.write(request)?;
113    assert_eq!(written, request.len());
114
115    let mut rbuf = [0u8; 64];
116    let n = server.read(&mut rbuf)?;
117    assert_eq!(&rbuf[..n], request);
118    println!("Server received: {:?}", std::str::from_utf8(&rbuf[..n])?);
119
120    let written = server.write(response)?;
121    assert_eq!(written, response.len());
122
123    let n = client.read(&mut rbuf)?;
124    assert_eq!(&rbuf[..n], response);
125    println!("Client received: {:?}", std::str::from_utf8(&rbuf[..n])?);
126
127    println!("In-process TLS 1.3 round-trip: OK");
128
129    Ok(())
130}
Source

pub fn set_bio(&mut self, rbio: Bio, wbio: Bio)

Set separate read and write BIOs.

Transfers ownership of both rbio and wbio to the SSL object.

Source

pub fn set_hostname(&mut self, hostname: &CStr) -> Result<(), ErrorStack>

Set the SNI hostname extension sent during the TLS handshake.

Call before Self::connect on client connections to enable SNI. hostname must be a NUL-terminated ASCII/UTF-8 hostname.

SSL_set_tlsext_host_name is a C macro expanding to SSL_ctrl(s, 55 /*SSL_CTRL_SET_TLSEXT_HOSTNAME*/, 0 /*TLSEXT_NAMETYPE_host_name*/, name).

§Errors

Returns Err if the control call fails.

Examples found in repository?
examples/ssl.rs (line 56)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    // ── Key pair and self-signed certificate ───────────────────────────────────
16
17    let mut kgen = KeygenCtx::new(c"ED25519")?;
18    let priv_key = kgen.generate()?;
19    let pub_key = native_ossl::pkey::Pkey::<native_ossl::pkey::Public>::from(priv_key.clone());
20
21    let mut name = X509NameOwned::new()?;
22    name.add_entry_by_txt(c"CN", b"localhost")?;
23
24    let cert = X509Builder::new()?
25        .set_version(2)?
26        .set_serial_number(1)?
27        .set_not_before_offset(0)?
28        .set_not_after_offset(86400)?
29        .set_subject_name(&name)?
30        .set_issuer_name(&name)?
31        .set_public_key(&pub_key)?
32        .sign(&priv_key, None)?
33        .build();
34
35    // ── Server context ─────────────────────────────────────────────────────────
36
37    let server_ctx = SslCtx::new_server()?;
38    server_ctx.set_min_proto_version(TlsVersion::Tls13)?;
39    server_ctx.use_certificate(&cert)?;
40    server_ctx.use_private_key(&priv_key)?;
41    server_ctx.check_private_key()?;
42
43    // ── Client context ─────────────────────────────────────────────────────────
44
45    let client_ctx = SslCtx::new_client()?;
46    client_ctx.set_min_proto_version(TlsVersion::Tls13)?;
47    // Skip certificate verification for this self-signed example.
48    client_ctx.set_verify(SslVerifyMode::NONE);
49
50    // ── SSL objects ────────────────────────────────────────────────────────────
51
52    let mut client = client_ctx.new_ssl()?;
53    let mut server = server_ctx.new_ssl()?;
54
55    client.set_connect_state();
56    client.set_hostname(c"localhost")?;
57    server.set_accept_state();
58
59    // ── In-process BIO pair ────────────────────────────────────────────────────
60    // Data written to client_bio is readable from server_bio and vice-versa.
61
62    let (client_bio, server_bio) = Bio::new_pair()?;
63    client.set_bio_duplex(client_bio);
64    server.set_bio_duplex(server_bio);
65
66    // ── Drive the handshake ────────────────────────────────────────────────────
67    // Alternate between client and server until both report success.
68
69    let mut client_done = false;
70    let mut server_done = false;
71
72    for step in 0..20 {
73        if !client_done {
74            match client.connect() {
75                Ok(()) => {
76                    client_done = true;
77                    println!("Client handshake done at step {step}");
78                }
79                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
80                Err(e) => return Err(format!("client error: {e}").into()),
81            }
82        }
83        if !server_done {
84            match server.accept() {
85                Ok(()) => {
86                    server_done = true;
87                    println!("Server handshake done at step {step}");
88                }
89                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
90                Err(e) => return Err(format!("server error: {e}").into()),
91            }
92        }
93        if client_done && server_done {
94            break;
95        }
96    }
97    assert!(client_done && server_done, "handshake did not complete");
98
99    // ── Inspect the peer certificate on the client ─────────────────────────────
100
101    if let Some(peer_cert) = client.peer_certificate() {
102        if let Some(subject) = peer_cert.subject_name().to_string() {
103            println!("Server cert subject: {subject}");
104        }
105    }
106
107    // ── Application data exchange ──────────────────────────────────────────────
108
109    let request = b"GET / HTTP/1.0\r\n\r\n";
110    let response = b"HTTP/1.0 200 OK\r\n\r\nHello, TLS!";
111
112    let written = client.write(request)?;
113    assert_eq!(written, request.len());
114
115    let mut rbuf = [0u8; 64];
116    let n = server.read(&mut rbuf)?;
117    assert_eq!(&rbuf[..n], request);
118    println!("Server received: {:?}", std::str::from_utf8(&rbuf[..n])?);
119
120    let written = server.write(response)?;
121    assert_eq!(written, response.len());
122
123    let n = client.read(&mut rbuf)?;
124    assert_eq!(&rbuf[..n], response);
125    println!("Client received: {:?}", std::str::from_utf8(&rbuf[..n])?);
126
127    println!("In-process TLS 1.3 round-trip: OK");
128
129    Ok(())
130}
Source

pub fn set_connect_state(&mut self)

Set this SSL object to operate in client (connect) mode.

Required before calling Self::do_handshake if neither Self::connect nor Self::accept will be used.

Examples found in repository?
examples/ssl.rs (line 55)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    // ── Key pair and self-signed certificate ───────────────────────────────────
16
17    let mut kgen = KeygenCtx::new(c"ED25519")?;
18    let priv_key = kgen.generate()?;
19    let pub_key = native_ossl::pkey::Pkey::<native_ossl::pkey::Public>::from(priv_key.clone());
20
21    let mut name = X509NameOwned::new()?;
22    name.add_entry_by_txt(c"CN", b"localhost")?;
23
24    let cert = X509Builder::new()?
25        .set_version(2)?
26        .set_serial_number(1)?
27        .set_not_before_offset(0)?
28        .set_not_after_offset(86400)?
29        .set_subject_name(&name)?
30        .set_issuer_name(&name)?
31        .set_public_key(&pub_key)?
32        .sign(&priv_key, None)?
33        .build();
34
35    // ── Server context ─────────────────────────────────────────────────────────
36
37    let server_ctx = SslCtx::new_server()?;
38    server_ctx.set_min_proto_version(TlsVersion::Tls13)?;
39    server_ctx.use_certificate(&cert)?;
40    server_ctx.use_private_key(&priv_key)?;
41    server_ctx.check_private_key()?;
42
43    // ── Client context ─────────────────────────────────────────────────────────
44
45    let client_ctx = SslCtx::new_client()?;
46    client_ctx.set_min_proto_version(TlsVersion::Tls13)?;
47    // Skip certificate verification for this self-signed example.
48    client_ctx.set_verify(SslVerifyMode::NONE);
49
50    // ── SSL objects ────────────────────────────────────────────────────────────
51
52    let mut client = client_ctx.new_ssl()?;
53    let mut server = server_ctx.new_ssl()?;
54
55    client.set_connect_state();
56    client.set_hostname(c"localhost")?;
57    server.set_accept_state();
58
59    // ── In-process BIO pair ────────────────────────────────────────────────────
60    // Data written to client_bio is readable from server_bio and vice-versa.
61
62    let (client_bio, server_bio) = Bio::new_pair()?;
63    client.set_bio_duplex(client_bio);
64    server.set_bio_duplex(server_bio);
65
66    // ── Drive the handshake ────────────────────────────────────────────────────
67    // Alternate between client and server until both report success.
68
69    let mut client_done = false;
70    let mut server_done = false;
71
72    for step in 0..20 {
73        if !client_done {
74            match client.connect() {
75                Ok(()) => {
76                    client_done = true;
77                    println!("Client handshake done at step {step}");
78                }
79                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
80                Err(e) => return Err(format!("client error: {e}").into()),
81            }
82        }
83        if !server_done {
84            match server.accept() {
85                Ok(()) => {
86                    server_done = true;
87                    println!("Server handshake done at step {step}");
88                }
89                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
90                Err(e) => return Err(format!("server error: {e}").into()),
91            }
92        }
93        if client_done && server_done {
94            break;
95        }
96    }
97    assert!(client_done && server_done, "handshake did not complete");
98
99    // ── Inspect the peer certificate on the client ─────────────────────────────
100
101    if let Some(peer_cert) = client.peer_certificate() {
102        if let Some(subject) = peer_cert.subject_name().to_string() {
103            println!("Server cert subject: {subject}");
104        }
105    }
106
107    // ── Application data exchange ──────────────────────────────────────────────
108
109    let request = b"GET / HTTP/1.0\r\n\r\n";
110    let response = b"HTTP/1.0 200 OK\r\n\r\nHello, TLS!";
111
112    let written = client.write(request)?;
113    assert_eq!(written, request.len());
114
115    let mut rbuf = [0u8; 64];
116    let n = server.read(&mut rbuf)?;
117    assert_eq!(&rbuf[..n], request);
118    println!("Server received: {:?}", std::str::from_utf8(&rbuf[..n])?);
119
120    let written = server.write(response)?;
121    assert_eq!(written, response.len());
122
123    let n = client.read(&mut rbuf)?;
124    assert_eq!(&rbuf[..n], response);
125    println!("Client received: {:?}", std::str::from_utf8(&rbuf[..n])?);
126
127    println!("In-process TLS 1.3 round-trip: OK");
128
129    Ok(())
130}
Source

pub fn set_accept_state(&mut self)

Set this SSL object to operate in server (accept) mode.

Examples found in repository?
examples/ssl.rs (line 57)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    // ── Key pair and self-signed certificate ───────────────────────────────────
16
17    let mut kgen = KeygenCtx::new(c"ED25519")?;
18    let priv_key = kgen.generate()?;
19    let pub_key = native_ossl::pkey::Pkey::<native_ossl::pkey::Public>::from(priv_key.clone());
20
21    let mut name = X509NameOwned::new()?;
22    name.add_entry_by_txt(c"CN", b"localhost")?;
23
24    let cert = X509Builder::new()?
25        .set_version(2)?
26        .set_serial_number(1)?
27        .set_not_before_offset(0)?
28        .set_not_after_offset(86400)?
29        .set_subject_name(&name)?
30        .set_issuer_name(&name)?
31        .set_public_key(&pub_key)?
32        .sign(&priv_key, None)?
33        .build();
34
35    // ── Server context ─────────────────────────────────────────────────────────
36
37    let server_ctx = SslCtx::new_server()?;
38    server_ctx.set_min_proto_version(TlsVersion::Tls13)?;
39    server_ctx.use_certificate(&cert)?;
40    server_ctx.use_private_key(&priv_key)?;
41    server_ctx.check_private_key()?;
42
43    // ── Client context ─────────────────────────────────────────────────────────
44
45    let client_ctx = SslCtx::new_client()?;
46    client_ctx.set_min_proto_version(TlsVersion::Tls13)?;
47    // Skip certificate verification for this self-signed example.
48    client_ctx.set_verify(SslVerifyMode::NONE);
49
50    // ── SSL objects ────────────────────────────────────────────────────────────
51
52    let mut client = client_ctx.new_ssl()?;
53    let mut server = server_ctx.new_ssl()?;
54
55    client.set_connect_state();
56    client.set_hostname(c"localhost")?;
57    server.set_accept_state();
58
59    // ── In-process BIO pair ────────────────────────────────────────────────────
60    // Data written to client_bio is readable from server_bio and vice-versa.
61
62    let (client_bio, server_bio) = Bio::new_pair()?;
63    client.set_bio_duplex(client_bio);
64    server.set_bio_duplex(server_bio);
65
66    // ── Drive the handshake ────────────────────────────────────────────────────
67    // Alternate between client and server until both report success.
68
69    let mut client_done = false;
70    let mut server_done = false;
71
72    for step in 0..20 {
73        if !client_done {
74            match client.connect() {
75                Ok(()) => {
76                    client_done = true;
77                    println!("Client handshake done at step {step}");
78                }
79                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
80                Err(e) => return Err(format!("client error: {e}").into()),
81            }
82        }
83        if !server_done {
84            match server.accept() {
85                Ok(()) => {
86                    server_done = true;
87                    println!("Server handshake done at step {step}");
88                }
89                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
90                Err(e) => return Err(format!("server error: {e}").into()),
91            }
92        }
93        if client_done && server_done {
94            break;
95        }
96    }
97    assert!(client_done && server_done, "handshake did not complete");
98
99    // ── Inspect the peer certificate on the client ─────────────────────────────
100
101    if let Some(peer_cert) = client.peer_certificate() {
102        if let Some(subject) = peer_cert.subject_name().to_string() {
103            println!("Server cert subject: {subject}");
104        }
105    }
106
107    // ── Application data exchange ──────────────────────────────────────────────
108
109    let request = b"GET / HTTP/1.0\r\n\r\n";
110    let response = b"HTTP/1.0 200 OK\r\n\r\nHello, TLS!";
111
112    let written = client.write(request)?;
113    assert_eq!(written, request.len());
114
115    let mut rbuf = [0u8; 64];
116    let n = server.read(&mut rbuf)?;
117    assert_eq!(&rbuf[..n], request);
118    println!("Server received: {:?}", std::str::from_utf8(&rbuf[..n])?);
119
120    let written = server.write(response)?;
121    assert_eq!(written, response.len());
122
123    let n = client.read(&mut rbuf)?;
124    assert_eq!(&rbuf[..n], response);
125    println!("Client received: {:?}", std::str::from_utf8(&rbuf[..n])?);
126
127    println!("In-process TLS 1.3 round-trip: OK");
128
129    Ok(())
130}
Source

pub fn connect(&mut self) -> Result<(), SslIoError>

Initiate a client-side TLS handshake (SSL_connect).

Returns Ok(()) on success, SslIoError::WantRead / SslIoError::WantWrite when the operation must be retried after more data is available.

§Errors
Examples found in repository?
examples/ssl.rs (line 74)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    // ── Key pair and self-signed certificate ───────────────────────────────────
16
17    let mut kgen = KeygenCtx::new(c"ED25519")?;
18    let priv_key = kgen.generate()?;
19    let pub_key = native_ossl::pkey::Pkey::<native_ossl::pkey::Public>::from(priv_key.clone());
20
21    let mut name = X509NameOwned::new()?;
22    name.add_entry_by_txt(c"CN", b"localhost")?;
23
24    let cert = X509Builder::new()?
25        .set_version(2)?
26        .set_serial_number(1)?
27        .set_not_before_offset(0)?
28        .set_not_after_offset(86400)?
29        .set_subject_name(&name)?
30        .set_issuer_name(&name)?
31        .set_public_key(&pub_key)?
32        .sign(&priv_key, None)?
33        .build();
34
35    // ── Server context ─────────────────────────────────────────────────────────
36
37    let server_ctx = SslCtx::new_server()?;
38    server_ctx.set_min_proto_version(TlsVersion::Tls13)?;
39    server_ctx.use_certificate(&cert)?;
40    server_ctx.use_private_key(&priv_key)?;
41    server_ctx.check_private_key()?;
42
43    // ── Client context ─────────────────────────────────────────────────────────
44
45    let client_ctx = SslCtx::new_client()?;
46    client_ctx.set_min_proto_version(TlsVersion::Tls13)?;
47    // Skip certificate verification for this self-signed example.
48    client_ctx.set_verify(SslVerifyMode::NONE);
49
50    // ── SSL objects ────────────────────────────────────────────────────────────
51
52    let mut client = client_ctx.new_ssl()?;
53    let mut server = server_ctx.new_ssl()?;
54
55    client.set_connect_state();
56    client.set_hostname(c"localhost")?;
57    server.set_accept_state();
58
59    // ── In-process BIO pair ────────────────────────────────────────────────────
60    // Data written to client_bio is readable from server_bio and vice-versa.
61
62    let (client_bio, server_bio) = Bio::new_pair()?;
63    client.set_bio_duplex(client_bio);
64    server.set_bio_duplex(server_bio);
65
66    // ── Drive the handshake ────────────────────────────────────────────────────
67    // Alternate between client and server until both report success.
68
69    let mut client_done = false;
70    let mut server_done = false;
71
72    for step in 0..20 {
73        if !client_done {
74            match client.connect() {
75                Ok(()) => {
76                    client_done = true;
77                    println!("Client handshake done at step {step}");
78                }
79                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
80                Err(e) => return Err(format!("client error: {e}").into()),
81            }
82        }
83        if !server_done {
84            match server.accept() {
85                Ok(()) => {
86                    server_done = true;
87                    println!("Server handshake done at step {step}");
88                }
89                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
90                Err(e) => return Err(format!("server error: {e}").into()),
91            }
92        }
93        if client_done && server_done {
94            break;
95        }
96    }
97    assert!(client_done && server_done, "handshake did not complete");
98
99    // ── Inspect the peer certificate on the client ─────────────────────────────
100
101    if let Some(peer_cert) = client.peer_certificate() {
102        if let Some(subject) = peer_cert.subject_name().to_string() {
103            println!("Server cert subject: {subject}");
104        }
105    }
106
107    // ── Application data exchange ──────────────────────────────────────────────
108
109    let request = b"GET / HTTP/1.0\r\n\r\n";
110    let response = b"HTTP/1.0 200 OK\r\n\r\nHello, TLS!";
111
112    let written = client.write(request)?;
113    assert_eq!(written, request.len());
114
115    let mut rbuf = [0u8; 64];
116    let n = server.read(&mut rbuf)?;
117    assert_eq!(&rbuf[..n], request);
118    println!("Server received: {:?}", std::str::from_utf8(&rbuf[..n])?);
119
120    let written = server.write(response)?;
121    assert_eq!(written, response.len());
122
123    let n = client.read(&mut rbuf)?;
124    assert_eq!(&rbuf[..n], response);
125    println!("Client received: {:?}", std::str::from_utf8(&rbuf[..n])?);
126
127    println!("In-process TLS 1.3 round-trip: OK");
128
129    Ok(())
130}
Source

pub fn accept(&mut self) -> Result<(), SslIoError>

Accept an incoming TLS connection (SSL_accept).

Returns Ok(()) on success, SslIoError::WantRead / SslIoError::WantWrite on non-blocking retry.

§Errors
Examples found in repository?
examples/ssl.rs (line 84)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    // ── Key pair and self-signed certificate ───────────────────────────────────
16
17    let mut kgen = KeygenCtx::new(c"ED25519")?;
18    let priv_key = kgen.generate()?;
19    let pub_key = native_ossl::pkey::Pkey::<native_ossl::pkey::Public>::from(priv_key.clone());
20
21    let mut name = X509NameOwned::new()?;
22    name.add_entry_by_txt(c"CN", b"localhost")?;
23
24    let cert = X509Builder::new()?
25        .set_version(2)?
26        .set_serial_number(1)?
27        .set_not_before_offset(0)?
28        .set_not_after_offset(86400)?
29        .set_subject_name(&name)?
30        .set_issuer_name(&name)?
31        .set_public_key(&pub_key)?
32        .sign(&priv_key, None)?
33        .build();
34
35    // ── Server context ─────────────────────────────────────────────────────────
36
37    let server_ctx = SslCtx::new_server()?;
38    server_ctx.set_min_proto_version(TlsVersion::Tls13)?;
39    server_ctx.use_certificate(&cert)?;
40    server_ctx.use_private_key(&priv_key)?;
41    server_ctx.check_private_key()?;
42
43    // ── Client context ─────────────────────────────────────────────────────────
44
45    let client_ctx = SslCtx::new_client()?;
46    client_ctx.set_min_proto_version(TlsVersion::Tls13)?;
47    // Skip certificate verification for this self-signed example.
48    client_ctx.set_verify(SslVerifyMode::NONE);
49
50    // ── SSL objects ────────────────────────────────────────────────────────────
51
52    let mut client = client_ctx.new_ssl()?;
53    let mut server = server_ctx.new_ssl()?;
54
55    client.set_connect_state();
56    client.set_hostname(c"localhost")?;
57    server.set_accept_state();
58
59    // ── In-process BIO pair ────────────────────────────────────────────────────
60    // Data written to client_bio is readable from server_bio and vice-versa.
61
62    let (client_bio, server_bio) = Bio::new_pair()?;
63    client.set_bio_duplex(client_bio);
64    server.set_bio_duplex(server_bio);
65
66    // ── Drive the handshake ────────────────────────────────────────────────────
67    // Alternate between client and server until both report success.
68
69    let mut client_done = false;
70    let mut server_done = false;
71
72    for step in 0..20 {
73        if !client_done {
74            match client.connect() {
75                Ok(()) => {
76                    client_done = true;
77                    println!("Client handshake done at step {step}");
78                }
79                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
80                Err(e) => return Err(format!("client error: {e}").into()),
81            }
82        }
83        if !server_done {
84            match server.accept() {
85                Ok(()) => {
86                    server_done = true;
87                    println!("Server handshake done at step {step}");
88                }
89                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
90                Err(e) => return Err(format!("server error: {e}").into()),
91            }
92        }
93        if client_done && server_done {
94            break;
95        }
96    }
97    assert!(client_done && server_done, "handshake did not complete");
98
99    // ── Inspect the peer certificate on the client ─────────────────────────────
100
101    if let Some(peer_cert) = client.peer_certificate() {
102        if let Some(subject) = peer_cert.subject_name().to_string() {
103            println!("Server cert subject: {subject}");
104        }
105    }
106
107    // ── Application data exchange ──────────────────────────────────────────────
108
109    let request = b"GET / HTTP/1.0\r\n\r\n";
110    let response = b"HTTP/1.0 200 OK\r\n\r\nHello, TLS!";
111
112    let written = client.write(request)?;
113    assert_eq!(written, request.len());
114
115    let mut rbuf = [0u8; 64];
116    let n = server.read(&mut rbuf)?;
117    assert_eq!(&rbuf[..n], request);
118    println!("Server received: {:?}", std::str::from_utf8(&rbuf[..n])?);
119
120    let written = server.write(response)?;
121    assert_eq!(written, response.len());
122
123    let n = client.read(&mut rbuf)?;
124    assert_eq!(&rbuf[..n], response);
125    println!("Client received: {:?}", std::str::from_utf8(&rbuf[..n])?);
126
127    println!("In-process TLS 1.3 round-trip: OK");
128
129    Ok(())
130}
Source

pub fn do_handshake(&mut self) -> Result<(), SslIoError>

Drive the TLS handshake in either role (SSL_do_handshake).

The role must have been set via Self::set_connect_state or Self::set_accept_state (or implicitly by Self::connect / Self::accept).

§Errors
Source

pub fn read(&mut self, buf: &mut [u8]) -> Result<usize, SslIoError>

Read decrypted application data (SSL_read_ex).

Returns the number of bytes written into buf on success.

§Errors
Examples found in repository?
examples/ssl.rs (line 116)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    // ── Key pair and self-signed certificate ───────────────────────────────────
16
17    let mut kgen = KeygenCtx::new(c"ED25519")?;
18    let priv_key = kgen.generate()?;
19    let pub_key = native_ossl::pkey::Pkey::<native_ossl::pkey::Public>::from(priv_key.clone());
20
21    let mut name = X509NameOwned::new()?;
22    name.add_entry_by_txt(c"CN", b"localhost")?;
23
24    let cert = X509Builder::new()?
25        .set_version(2)?
26        .set_serial_number(1)?
27        .set_not_before_offset(0)?
28        .set_not_after_offset(86400)?
29        .set_subject_name(&name)?
30        .set_issuer_name(&name)?
31        .set_public_key(&pub_key)?
32        .sign(&priv_key, None)?
33        .build();
34
35    // ── Server context ─────────────────────────────────────────────────────────
36
37    let server_ctx = SslCtx::new_server()?;
38    server_ctx.set_min_proto_version(TlsVersion::Tls13)?;
39    server_ctx.use_certificate(&cert)?;
40    server_ctx.use_private_key(&priv_key)?;
41    server_ctx.check_private_key()?;
42
43    // ── Client context ─────────────────────────────────────────────────────────
44
45    let client_ctx = SslCtx::new_client()?;
46    client_ctx.set_min_proto_version(TlsVersion::Tls13)?;
47    // Skip certificate verification for this self-signed example.
48    client_ctx.set_verify(SslVerifyMode::NONE);
49
50    // ── SSL objects ────────────────────────────────────────────────────────────
51
52    let mut client = client_ctx.new_ssl()?;
53    let mut server = server_ctx.new_ssl()?;
54
55    client.set_connect_state();
56    client.set_hostname(c"localhost")?;
57    server.set_accept_state();
58
59    // ── In-process BIO pair ────────────────────────────────────────────────────
60    // Data written to client_bio is readable from server_bio and vice-versa.
61
62    let (client_bio, server_bio) = Bio::new_pair()?;
63    client.set_bio_duplex(client_bio);
64    server.set_bio_duplex(server_bio);
65
66    // ── Drive the handshake ────────────────────────────────────────────────────
67    // Alternate between client and server until both report success.
68
69    let mut client_done = false;
70    let mut server_done = false;
71
72    for step in 0..20 {
73        if !client_done {
74            match client.connect() {
75                Ok(()) => {
76                    client_done = true;
77                    println!("Client handshake done at step {step}");
78                }
79                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
80                Err(e) => return Err(format!("client error: {e}").into()),
81            }
82        }
83        if !server_done {
84            match server.accept() {
85                Ok(()) => {
86                    server_done = true;
87                    println!("Server handshake done at step {step}");
88                }
89                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
90                Err(e) => return Err(format!("server error: {e}").into()),
91            }
92        }
93        if client_done && server_done {
94            break;
95        }
96    }
97    assert!(client_done && server_done, "handshake did not complete");
98
99    // ── Inspect the peer certificate on the client ─────────────────────────────
100
101    if let Some(peer_cert) = client.peer_certificate() {
102        if let Some(subject) = peer_cert.subject_name().to_string() {
103            println!("Server cert subject: {subject}");
104        }
105    }
106
107    // ── Application data exchange ──────────────────────────────────────────────
108
109    let request = b"GET / HTTP/1.0\r\n\r\n";
110    let response = b"HTTP/1.0 200 OK\r\n\r\nHello, TLS!";
111
112    let written = client.write(request)?;
113    assert_eq!(written, request.len());
114
115    let mut rbuf = [0u8; 64];
116    let n = server.read(&mut rbuf)?;
117    assert_eq!(&rbuf[..n], request);
118    println!("Server received: {:?}", std::str::from_utf8(&rbuf[..n])?);
119
120    let written = server.write(response)?;
121    assert_eq!(written, response.len());
122
123    let n = client.read(&mut rbuf)?;
124    assert_eq!(&rbuf[..n], response);
125    println!("Client received: {:?}", std::str::from_utf8(&rbuf[..n])?);
126
127    println!("In-process TLS 1.3 round-trip: OK");
128
129    Ok(())
130}
Source

pub fn write(&mut self, buf: &[u8]) -> Result<usize, SslIoError>

Write application data (SSL_write_ex).

Returns the number of bytes consumed from buf on success.

§Errors
Examples found in repository?
examples/ssl.rs (line 112)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    // ── Key pair and self-signed certificate ───────────────────────────────────
16
17    let mut kgen = KeygenCtx::new(c"ED25519")?;
18    let priv_key = kgen.generate()?;
19    let pub_key = native_ossl::pkey::Pkey::<native_ossl::pkey::Public>::from(priv_key.clone());
20
21    let mut name = X509NameOwned::new()?;
22    name.add_entry_by_txt(c"CN", b"localhost")?;
23
24    let cert = X509Builder::new()?
25        .set_version(2)?
26        .set_serial_number(1)?
27        .set_not_before_offset(0)?
28        .set_not_after_offset(86400)?
29        .set_subject_name(&name)?
30        .set_issuer_name(&name)?
31        .set_public_key(&pub_key)?
32        .sign(&priv_key, None)?
33        .build();
34
35    // ── Server context ─────────────────────────────────────────────────────────
36
37    let server_ctx = SslCtx::new_server()?;
38    server_ctx.set_min_proto_version(TlsVersion::Tls13)?;
39    server_ctx.use_certificate(&cert)?;
40    server_ctx.use_private_key(&priv_key)?;
41    server_ctx.check_private_key()?;
42
43    // ── Client context ─────────────────────────────────────────────────────────
44
45    let client_ctx = SslCtx::new_client()?;
46    client_ctx.set_min_proto_version(TlsVersion::Tls13)?;
47    // Skip certificate verification for this self-signed example.
48    client_ctx.set_verify(SslVerifyMode::NONE);
49
50    // ── SSL objects ────────────────────────────────────────────────────────────
51
52    let mut client = client_ctx.new_ssl()?;
53    let mut server = server_ctx.new_ssl()?;
54
55    client.set_connect_state();
56    client.set_hostname(c"localhost")?;
57    server.set_accept_state();
58
59    // ── In-process BIO pair ────────────────────────────────────────────────────
60    // Data written to client_bio is readable from server_bio and vice-versa.
61
62    let (client_bio, server_bio) = Bio::new_pair()?;
63    client.set_bio_duplex(client_bio);
64    server.set_bio_duplex(server_bio);
65
66    // ── Drive the handshake ────────────────────────────────────────────────────
67    // Alternate between client and server until both report success.
68
69    let mut client_done = false;
70    let mut server_done = false;
71
72    for step in 0..20 {
73        if !client_done {
74            match client.connect() {
75                Ok(()) => {
76                    client_done = true;
77                    println!("Client handshake done at step {step}");
78                }
79                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
80                Err(e) => return Err(format!("client error: {e}").into()),
81            }
82        }
83        if !server_done {
84            match server.accept() {
85                Ok(()) => {
86                    server_done = true;
87                    println!("Server handshake done at step {step}");
88                }
89                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
90                Err(e) => return Err(format!("server error: {e}").into()),
91            }
92        }
93        if client_done && server_done {
94            break;
95        }
96    }
97    assert!(client_done && server_done, "handshake did not complete");
98
99    // ── Inspect the peer certificate on the client ─────────────────────────────
100
101    if let Some(peer_cert) = client.peer_certificate() {
102        if let Some(subject) = peer_cert.subject_name().to_string() {
103            println!("Server cert subject: {subject}");
104        }
105    }
106
107    // ── Application data exchange ──────────────────────────────────────────────
108
109    let request = b"GET / HTTP/1.0\r\n\r\n";
110    let response = b"HTTP/1.0 200 OK\r\n\r\nHello, TLS!";
111
112    let written = client.write(request)?;
113    assert_eq!(written, request.len());
114
115    let mut rbuf = [0u8; 64];
116    let n = server.read(&mut rbuf)?;
117    assert_eq!(&rbuf[..n], request);
118    println!("Server received: {:?}", std::str::from_utf8(&rbuf[..n])?);
119
120    let written = server.write(response)?;
121    assert_eq!(written, response.len());
122
123    let n = client.read(&mut rbuf)?;
124    assert_eq!(&rbuf[..n], response);
125    println!("Client received: {:?}", std::str::from_utf8(&rbuf[..n])?);
126
127    println!("In-process TLS 1.3 round-trip: OK");
128
129    Ok(())
130}
Source

pub fn shutdown(&mut self) -> Result<ShutdownResult, ErrorStack>

Send a TLS close-notify alert (SSL_shutdown).

Returns ShutdownResult::Sent after the first shutdown stage and ShutdownResult::Complete after a bidirectional shutdown. Call twice on a non-blocking connection to complete the exchange.

§Errors

Returns Err on a fatal error during shutdown.

Source

pub fn peer_cert_chain(&self) -> Option<Vec<X509>>

Return the peer’s full certificate chain (leaf + intermediates), or None.

Each certificate in the returned Vec has its reference count independently incremented via X509_up_ref, so the certificates outlive self.

Returns None when:

  • the handshake has not yet completed, or
  • the peer did not present a certificate (e.g. a server without client-auth configured will see None for the client chain).

An empty Vec is returned if the stack exists but contains no elements (unusual in practice).

Note: this calls SSL_get_peer_cert_chain, which on the server side does not include the leaf certificate — only intermediates. On the client side the full chain including the server leaf is returned. Use Self::peer_certificate to obtain the leaf cert in all cases.

Source

pub fn peer_certificate(&self) -> Option<X509>

Return the peer’s certificate, or None if unavailable.

The returned certificate has its reference count incremented, so it outlives self.

Examples found in repository?
examples/ssl.rs (line 101)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    // ── Key pair and self-signed certificate ───────────────────────────────────
16
17    let mut kgen = KeygenCtx::new(c"ED25519")?;
18    let priv_key = kgen.generate()?;
19    let pub_key = native_ossl::pkey::Pkey::<native_ossl::pkey::Public>::from(priv_key.clone());
20
21    let mut name = X509NameOwned::new()?;
22    name.add_entry_by_txt(c"CN", b"localhost")?;
23
24    let cert = X509Builder::new()?
25        .set_version(2)?
26        .set_serial_number(1)?
27        .set_not_before_offset(0)?
28        .set_not_after_offset(86400)?
29        .set_subject_name(&name)?
30        .set_issuer_name(&name)?
31        .set_public_key(&pub_key)?
32        .sign(&priv_key, None)?
33        .build();
34
35    // ── Server context ─────────────────────────────────────────────────────────
36
37    let server_ctx = SslCtx::new_server()?;
38    server_ctx.set_min_proto_version(TlsVersion::Tls13)?;
39    server_ctx.use_certificate(&cert)?;
40    server_ctx.use_private_key(&priv_key)?;
41    server_ctx.check_private_key()?;
42
43    // ── Client context ─────────────────────────────────────────────────────────
44
45    let client_ctx = SslCtx::new_client()?;
46    client_ctx.set_min_proto_version(TlsVersion::Tls13)?;
47    // Skip certificate verification for this self-signed example.
48    client_ctx.set_verify(SslVerifyMode::NONE);
49
50    // ── SSL objects ────────────────────────────────────────────────────────────
51
52    let mut client = client_ctx.new_ssl()?;
53    let mut server = server_ctx.new_ssl()?;
54
55    client.set_connect_state();
56    client.set_hostname(c"localhost")?;
57    server.set_accept_state();
58
59    // ── In-process BIO pair ────────────────────────────────────────────────────
60    // Data written to client_bio is readable from server_bio and vice-versa.
61
62    let (client_bio, server_bio) = Bio::new_pair()?;
63    client.set_bio_duplex(client_bio);
64    server.set_bio_duplex(server_bio);
65
66    // ── Drive the handshake ────────────────────────────────────────────────────
67    // Alternate between client and server until both report success.
68
69    let mut client_done = false;
70    let mut server_done = false;
71
72    for step in 0..20 {
73        if !client_done {
74            match client.connect() {
75                Ok(()) => {
76                    client_done = true;
77                    println!("Client handshake done at step {step}");
78                }
79                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
80                Err(e) => return Err(format!("client error: {e}").into()),
81            }
82        }
83        if !server_done {
84            match server.accept() {
85                Ok(()) => {
86                    server_done = true;
87                    println!("Server handshake done at step {step}");
88                }
89                Err(SslIoError::WantRead | SslIoError::WantWrite) => {}
90                Err(e) => return Err(format!("server error: {e}").into()),
91            }
92        }
93        if client_done && server_done {
94            break;
95        }
96    }
97    assert!(client_done && server_done, "handshake did not complete");
98
99    // ── Inspect the peer certificate on the client ─────────────────────────────
100
101    if let Some(peer_cert) = client.peer_certificate() {
102        if let Some(subject) = peer_cert.subject_name().to_string() {
103            println!("Server cert subject: {subject}");
104        }
105    }
106
107    // ── Application data exchange ──────────────────────────────────────────────
108
109    let request = b"GET / HTTP/1.0\r\n\r\n";
110    let response = b"HTTP/1.0 200 OK\r\n\r\nHello, TLS!";
111
112    let written = client.write(request)?;
113    assert_eq!(written, request.len());
114
115    let mut rbuf = [0u8; 64];
116    let n = server.read(&mut rbuf)?;
117    assert_eq!(&rbuf[..n], request);
118    println!("Server received: {:?}", std::str::from_utf8(&rbuf[..n])?);
119
120    let written = server.write(response)?;
121    assert_eq!(written, response.len());
122
123    let n = client.read(&mut rbuf)?;
124    assert_eq!(&rbuf[..n], response);
125    println!("Client received: {:?}", std::str::from_utf8(&rbuf[..n])?);
126
127    println!("In-process TLS 1.3 round-trip: OK");
128
129    Ok(())
130}
Source

pub fn get1_session(&self) -> Option<SslSession>

Get an owned reference to the current session (SSL_get1_session).

Returns None if no session is established. The session can be passed to Self::set_session on a new Ssl for resumption.

Source

pub fn session(&self) -> Option<BorrowedSslSession<'_>>

Borrow the current session without incrementing the reference count (SSL_get_session).

Returns None if no session is associated with this connection (e.g. the handshake has not yet completed or session caching is disabled).

The returned BorrowedSslSession is valid for the lifetime of self and must not be retained beyond it. Use Self::get1_session if you need a session that outlives the connection.

§Lifetimes

The borrow is tied to '_ (the lifetime of self): the SSL_SESSION* is owned by the SSL object and is invalidated when the Ssl is dropped or a new session is negotiated.

Source

pub fn set_session(&mut self, session: &SslSession) -> Result<(), ErrorStack>

Set a previously obtained session for resumption (SSL_set_session).

Call before the handshake.

§Errors
Source

pub fn set_verify_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack>

Override the expected server hostname for this connection’s certificate verification.

Use this when one SslCtx is shared across connections to different servers and per-connection hostname checking is needed. Wraps SSL_set1_host.

§Errors

Returns Err if hostname contains a NUL byte or if SSL_set1_host fails.

Trait Implementations§

Source§

impl Drop for Ssl

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl Send for Ssl

Auto Trait Implementations§

§

impl Freeze for Ssl

§

impl RefUnwindSafe for Ssl

§

impl !Sync for Ssl

§

impl Unpin for Ssl

§

impl UnsafeUnpin for Ssl

§

impl UnwindSafe for Ssl

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.