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
impl Ssl
Sourcepub fn set_bio_duplex(&mut self, bio: Bio)
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?
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}Sourcepub fn set_bio(&mut self, rbio: Bio, wbio: Bio)
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.
Sourcepub fn set_hostname(&mut self, hostname: &CStr) -> Result<(), ErrorStack>
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?
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}Sourcepub fn set_connect_state(&mut self)
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?
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}Sourcepub fn set_accept_state(&mut self)
pub fn set_accept_state(&mut self)
Set this SSL object to operate in server (accept) mode.
Examples found in repository?
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}Sourcepub fn connect(&mut self) -> Result<(), SslIoError>
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?
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}Sourcepub fn accept(&mut self) -> Result<(), SslIoError>
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?
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}Sourcepub fn do_handshake(&mut self) -> Result<(), SslIoError>
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
Sourcepub fn read(&mut self, buf: &mut [u8]) -> Result<usize, SslIoError>
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?
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}Sourcepub fn write(&mut self, buf: &[u8]) -> Result<usize, SslIoError>
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?
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}Sourcepub fn shutdown(&mut self) -> Result<ShutdownResult, ErrorStack>
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.
Sourcepub fn peer_cert_chain(&self) -> Option<Vec<X509>>
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
Nonefor 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.
Sourcepub fn peer_certificate(&self) -> Option<X509>
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?
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}Sourcepub fn get1_session(&self) -> Option<SslSession>
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.
Sourcepub fn session(&self) -> Option<BorrowedSslSession<'_>>
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.
Sourcepub fn set_session(&mut self, session: &SslSession) -> Result<(), ErrorStack>
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
Sourcepub fn set_verify_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack>
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.