Skip to content

Commit 2a8d471

Browse files
authored
Do some tweaks and cleanups (#60)
Order imports as: std, third-party, crate. Use `try_ref_from_ptr!` to turn `out_n`'s into refs. This moves unsafe blocks from later in the function to earlier in the function, closer to where their safety properties are checked. Also, remove pre-emptive zeroing of `out_n`'s. According to the conventions listed in our README, there are no partial successes or partial failures, so we shouldn't write to `out_n` if we early-return. Remove `strong_count < 1` checks on Arc. Follow-up from #32. Add some missing comments and fix some formatting.
1 parent 8758c1d commit 2a8d471

File tree

4 files changed

+252
-111
lines changed

4 files changed

+252
-111
lines changed

src/cipher.rs

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
use std::{cmp::min, slice};
2-
3-
use crate::error::rustls_result;
4-
use crate::{
5-
ffi_panic_boundary, ffi_panic_boundary_generic, ffi_panic_boundary_unit, try_ref_from_ptr,
6-
};
71
use libc::{c_char, size_t};
82
use std::io::Cursor;
93
use std::os::raw::c_ushort;
104
use std::sync::Arc;
5+
use std::{cmp::min, slice};
116

7+
use rustls::sign::CertifiedKey;
128
use rustls::{Certificate, PrivateKey};
139
use rustls_pemfile::{certs, pkcs8_private_keys, rsa_private_keys};
1410

15-
use rustls::sign::CertifiedKey;
11+
use crate::error::rustls_result;
12+
use crate::{
13+
ffi_panic_boundary, ffi_panic_boundary_generic, ffi_panic_boundary_unit, try_ref_from_ptr,
14+
};
1615
use rustls_result::NullParameter;
1716

1817
/// All SignatureScheme currently defined in rustls.
@@ -49,12 +48,11 @@ fn signature_scheme_name(n: u16) -> String {
4948

5049
/// Get the name of a SignatureScheme, represented by the `scheme` short value,
5150
/// if known by the rustls library. For unknown schemes, this returns a string
52-
/// with the scheme value in hex notation.
53-
/// Mainly useful for debugging output.
51+
/// with the scheme value in hex notation. Mainly useful for debugging output.
52+
///
5453
/// The caller provides `buf` for holding the string and gives its size as `len`
5554
/// bytes. On return `out_n` carries the number of bytes copied into `buf`. The
5655
/// `buf` is not NUL-terminated.
57-
///
5856
#[no_mangle]
5957
pub extern "C" fn rustls_cipher_get_signature_scheme_name(
6058
scheme: c_ushort,
@@ -63,36 +61,46 @@ pub extern "C" fn rustls_cipher_get_signature_scheme_name(
6361
out_n: *mut size_t,
6462
) {
6563
ffi_panic_boundary_unit! {
64+
if buf.is_null() {
65+
return;
66+
}
6667
let write_buf: &mut [u8] = unsafe {
67-
let out_n: &mut size_t = match out_n.as_mut() {
68-
Some(out_n) => out_n,
69-
None => return,
70-
};
71-
*out_n = 0;
72-
if buf.is_null() {
73-
return;
74-
}
7568
slice::from_raw_parts_mut(buf as *mut u8, len as usize)
7669
};
70+
let out_n: &mut size_t = try_ref_from_ptr!(out_n, &mut size_t, ());
7771
let name = signature_scheme_name(scheme);
7872
let len: usize = min(write_buf.len() - 1, name.len());
7973
write_buf[..len].copy_from_slice(&name.as_bytes()[..len]);
80-
unsafe {
81-
*out_n = len;
82-
}
74+
*out_n = len;
8375
}
8476
}
8577

86-
/// The complete chain of certificates plus private key for
87-
/// being certified against someones list of trust anchors (commonly
88-
/// called root store). Corresponds to `CertifiedKey` in the Rust API.
78+
/// The complete chain of certificates to send during a TLS handshake,
79+
/// plus a private key that matches the end-entity (leaf) certificate.
80+
/// Corresponds to `CertifiedKey` in the Rust API.
81+
/// https://docs.rs/rustls/0.19.0/rustls/sign/struct.CertifiedKey.html
8982
pub struct rustls_certified_key {
9083
// We use the opaque struct pattern to tell C about our types without
9184
// telling them what's inside.
9285
// https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
9386
_private: [u8; 0],
9487
}
9588

89+
/// Build a `rustls_certified_key` from a certificate chain and a private key.
90+
/// `cert_chain` must point to a buffer of `cert_chain_len` bytes, containing
91+
/// a series of PEM-encoded certificates, with the end-entity (leaf)
92+
/// certificate first.
93+
///
94+
/// `private_key` must point to a buffer of `private_key_len` bytes, containing
95+
/// a PEM-encoded private key in either PKCS#1 or PKCS#8 format.
96+
///
97+
/// On success, this writes a pointer to the newly created
98+
/// `rustls_certified_key` in `certified_key_out`. That pointer must later
99+
/// be freed with `rustls_certified_key_free` to avoid memory leaks. Note that
100+
/// internally, this is an atomically reference-counted pointer, so even after
101+
/// the original caller has called `rustls_certified_key_free`, other objects
102+
/// may retain a pointer to the object. The memory will be freed when all
103+
/// references are gone.
96104
#[no_mangle]
97105
pub extern "C" fn rustls_certified_key_build(
98106
cert_chain: *const u8,
@@ -102,14 +110,15 @@ pub extern "C" fn rustls_certified_key_build(
102110
certified_key_out: *mut *const rustls_certified_key,
103111
) -> rustls_result {
104112
ffi_panic_boundary! {
113+
let certified_key_out: &mut *const rustls_certified_key =
114+
try_ref_from_ptr!(certified_key_out, &mut *const rustls_certified_key);
105115
let certified_key = match certified_key_build(
106116
cert_chain, cert_chain_len, private_key, private_key_len) {
107117
Ok(key) => Box::new(key),
108118
Err(rr) => return rr,
109119
};
110-
unsafe {
111-
*certified_key_out = Arc::into_raw(Arc::new(*certified_key)) as *const _;
112-
}
120+
let certified_key = Arc::into_raw(Arc::new(*certified_key)) as *const _;
121+
*certified_key_out = certified_key;
113122
return rustls_result::Ok
114123
}
115124
}
@@ -127,19 +136,11 @@ pub extern "C" fn rustls_certified_key_free(config: *const rustls_certified_key)
127136
// To free the certified_key, we reconstruct the Arc. It should have a refcount of 1,
128137
// representing the C code's copy. When it drops, that refcount will go down to 0
129138
// and the inner ServerConfig will be dropped.
130-
let arc: Arc<CertifiedKey> = unsafe { Arc::from_raw(key) };
131-
let strong_count = Arc::strong_count(&arc);
132-
if strong_count < 1 {
133-
eprintln!(
134-
"rustls_certified_key_free: invariant failed: arc.strong_count was < 1: {}. \
135-
You must not free the same certified_key multiple times.",
136-
strong_count
137-
);
138-
}
139+
unsafe { drop(Arc::from_raw(key)) };
139140
}
140141
}
141142

142-
pub(crate) fn certified_key_build(
143+
fn certified_key_build(
143144
cert_chain: *const u8,
144145
cert_chain_len: size_t,
145146
private_key: *const u8,

src/client.rs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -483,12 +483,7 @@ pub extern "C" fn rustls_client_session_read(
483483
}
484484
slice::from_raw_parts_mut(buf, count as usize)
485485
};
486-
let out_n = unsafe {
487-
match out_n.as_mut() {
488-
Some(out_n) => out_n,
489-
None => return NullParameter,
490-
}
491-
};
486+
let out_n: &mut size_t = try_ref_from_ptr!(out_n, &mut size_t);
492487
let n_read: usize = match session.read(read_buf) {
493488
Ok(n) => n,
494489
// The CloseNotify TLS alert is benign, but rustls returns it as an Error. See comment on
@@ -528,12 +523,7 @@ pub extern "C" fn rustls_client_session_read_tls(
528523
}
529524
slice::from_raw_parts(buf, count as usize)
530525
};
531-
let out_n = unsafe {
532-
match out_n.as_mut() {
533-
Some(out_n) => out_n,
534-
None => return NullParameter,
535-
}
536-
};
526+
let out_n: &mut size_t = try_ref_from_ptr!(out_n, &mut size_t);
537527
let mut cursor = Cursor::new(input_buf);
538528
let n_read: usize = match session.read_tls(&mut cursor) {
539529
Ok(n) => n,
@@ -569,12 +559,7 @@ pub extern "C" fn rustls_client_session_write_tls(
569559
}
570560
slice::from_raw_parts_mut(buf, count as usize)
571561
};
572-
let out_n = unsafe {
573-
match out_n.as_mut() {
574-
Some(out_n) => out_n,
575-
None => return NullParameter,
576-
}
577-
};
562+
let out_n: &mut size_t = try_ref_from_ptr!(out_n, &mut size_t);
578563
let n_written: usize = match session.write_tls(&mut output_buf) {
579564
Ok(n) => n,
580565
Err(_) => return rustls_result::Io,

0 commit comments

Comments
 (0)