rust: hoist FFI slice converters to bssl-crypto Signed-off-by: Xiangfei Ding <xfding@google.com> Change-Id: I2147920ede90e01772b67e6c0a2d3e236a6a6964 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/100227 Reviewed-by: Rudolf Polzer <rpolzer@google.com> Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/rust/bssl-crypto/src/lib.rs b/rust/bssl-crypto/src/lib.rs index a2c550d..75fc7a5 100644 --- a/rust/bssl-crypto/src/lib.rs +++ b/rust/bssl-crypto/src/lib.rs
@@ -29,7 +29,10 @@ use alloc::boxed::Box; use alloc::vec::Vec; -use core::ffi::c_void; +use core::{ + debug_assert, + ffi::c_void, // +}; #[macro_use] mod macros; @@ -132,6 +135,89 @@ } } +#[doc(hidden)] +/// The reverse of [`FfiSlice`], to re-interpret a FFI pointer back into a Rust slice. +pub trait FromFfiSlice: Sized { + /// Converts an FFI pointer and length to a Rust slice. This is similar to + /// [core::slice::from_raw_parts] but handles a mismatch between C and Rust empty slice + /// conventions. + /// In C, empty slices may use a `NULL` pointer in C. + /// In Rust, they may not. + /// + /// **NOTE** This trait is set up only for BoringSSL internal use. + /// + /// # Safety + /// + /// The caller must meet the following safety pre-conditions: + /// - The `ptr` and `len` are from a slice returned from BoringSSL via FFI. + /// - The memory referenced by the returned slice must not be mutated or deallocated for the + /// duration of lifetime `'a`, including by BoringSSL. + /// + /// The first condition implies the following properties: + /// + /// - `ptr` is correctly aligned for Self. + /// - The total bytes of the slice, in other words `size_of<Self>() * len`, is below [isize::MAX]. + /// - If `ptr.is_null()` then `len == 0`. + /// - There are `len` objects of type Self at ptr. + /// - The entire memory range for these objects is contained in a single allocation. + /// - The entire memory range is not mutated within the `'a` lifetime through aliased accesses. + /// - Each element of the slice has a valid bit pattern as a value of `Self`. + unsafe fn from_ffi_ptr<'a>(ptr: *const Self, len: usize) -> &'a [Self]; +} + +impl<T> FromFfiSlice for T { + #[inline] + unsafe fn from_ffi_ptr<'a>(ptr: *const T, len: usize) -> &'a [T] { + debug_assert!(ptr.is_aligned()); + #[cfg(debug_assertions)] + if let Some(len) = len.checked_mul(core::mem::size_of::<T>()) { + debug_assert!(len < isize::MAX.unsigned_abs()); + } else { + unreachable!("length overflow"); + }; + + if len == 0 { + &[] + } else { + debug_assert!(!ptr.is_null()); + unsafe { + // Safety: + // - pre-condition has asserted that the pointer outlives the returned slice. + // - pre-condition has asserted that the memory range does not overlap with any + // other allocations. + // - pre-condition has asserted that the bit pattern behind the pointer is valid for + // the type `T`. + core::slice::from_raw_parts(ptr, len) + } + } + } +} + +/// Sanitize the data pointer and length and reconstitute the mutable slice. +/// +/// This method will **zeroize** the content. +/// +/// This method returns an empty slice if the length is 0. +/// +/// # Safety +/// +/// Caller must ensure that +/// - `ptr` outlives `'a`. +/// - access to `out` is exclusive and strictly not aliased. +/// - if `ptr` is NULL, `capacity == 0`. +#[inline] +pub unsafe fn zeroize_mut_byteslice<'a>(ptr: *mut u8, capacity: usize) -> &'a mut [u8] { + if capacity == 0 { + return &mut []; + } + debug_assert!(capacity < isize::MAX.unsigned_abs() && !ptr.is_null()); + unsafe { + // Safety: `out` is 1-aligned and `0` is a valid pattern for `u8`. + core::ptr::write_bytes(ptr, 0, capacity); + core::slice::from_raw_parts_mut(ptr, capacity) + } +} + /// This is a helper struct which provides functions for passing slices over FFI. /// /// Deprecated: use `FfiSlice` which adds less noise and lets one grep for `as_ptr`
diff --git a/rust/bssl-tls/src/credentials.rs b/rust/bssl-tls/src/credentials.rs index 723dc7b..aa24387 100644 --- a/rust/bssl-tls/src/credentials.rs +++ b/rust/bssl-tls/src/credentials.rs
@@ -40,6 +40,7 @@ }, // }; +use bssl_crypto::FromFfiSlice; use bssl_x509::{ errors::PemReason, keys::{PrivateKey, PublicKey}, @@ -68,7 +69,6 @@ CryptoBufferWrapper, Stack, StackIterator, - sanitize_slice, slice_into_ffi_raw_parts, // }, has_duplicates, // @@ -444,7 +444,7 @@ } unsafe { // Safety: `id_ptr` will be outlived by `self`. - sanitize_slice(id_ptr, id_len) + Some(u8::from_ffi_ptr(id_ptr, id_len)) } } } @@ -553,12 +553,10 @@ if buf.to_bytes() != b"CERTIFICATE" { continue; } - let Some(contents) = (unsafe { + let contents = unsafe { // Safety: the slice is only used within the loop and we will copy the contents // when constructing the certificate object. - sanitize_slice(data.0, len) - }) else { - return Err(Error::Io(IoError::TooLong)); + u8::from_ffi_ptr(data.0, len) }; let cert = Certificate::from_bytes(contents, cache)?; return Ok((cert, eof)); @@ -576,7 +574,7 @@ }; unsafe { // Safety: `data` will be outlived by `self` - sanitize_slice(data, len).expect("buffer is too large") + u8::from_ffi_ptr(data, len) } } } @@ -817,7 +815,7 @@ core::mem::transmute(call_slice_getter!( bssl_sys::SSL_get0_ech_name_override, self.ptr() - )?) + )) }; if name.is_empty() || !name.is_ascii() { return None; @@ -834,7 +832,7 @@ /// [RFC 2560]: <https://datatracker.ietf.org/doc/html/rfc6960> pub fn get_ocsp_response(&self) -> Option<&[u8]> { // Safety: response, when it exists, is outlived by the connection. - let response = call_slice_getter!(bssl_sys::SSL_get0_ocsp_response, self.ptr())?; + let response = call_slice_getter!(bssl_sys::SSL_get0_ocsp_response, self.ptr()); (!response.is_empty()).then_some(response) } @@ -843,7 +841,7 @@ /// [RFC 6962]: <https://datatracker.ietf.org/doc/html/rfc6962#section-3.2> pub fn get_signed_cert_timestamp_list(&self) -> Option<&[u8]> { // Safety: list, when it exists, is outlived by the connection. - let list = call_slice_getter!(bssl_sys::SSL_get0_signed_cert_timestamp_list, self.ptr())?; + let list = call_slice_getter!(bssl_sys::SSL_get0_signed_cert_timestamp_list, self.ptr()); (!list.is_empty()).then_some(list) }
diff --git a/rust/bssl-tls/src/credentials/early_callback.rs b/rust/bssl-tls/src/credentials/early_callback.rs index fd498c9..5fc9198c 100644 --- a/rust/bssl-tls/src/credentials/early_callback.rs +++ b/rust/bssl-tls/src/credentials/early_callback.rs
@@ -23,6 +23,8 @@ }, // }; +use bssl_crypto::FromFfiSlice; + use crate::{ EarlyCallbackMethods, abort_on_panic, @@ -30,8 +32,7 @@ connection::{ Server, lifecycle::TlsConnectionInHandshake, // - }, - ffi::sanitize_slice, // + }, // }; bssl_macros::bssl_enum! { @@ -158,7 +159,7 @@ ($client_hello:expr, $data:ident, $len:ident) => { unsafe { // Safety: `$client_hello` is a valid pointer - sanitize_slice($client_hello.$data, $client_hello.$len)? + u8::from_ffi_ptr($client_hello.$data, $client_hello.$len) } }; } @@ -215,22 +216,12 @@ /// Get the legacy compression methods bytes. pub fn legacy_compression_methods(&self) -> &'a [u8] { - unsafe { - // Safety: `self.ptr` is a valid pointer to `SSL_CLIENT_HELLO` provided by BoringSSL. - sanitize_slice( - (*self.ptr).compression_methods, - (*self.ptr).compression_methods_len, - ) - .unwrap_or(&[]) - } + client_hello_getter!(*self.ptr, compression_methods, compression_methods_len) } /// Get the extensions bytes. pub fn extensions(&self) -> &'a [u8] { - unsafe { - // Safety: `self.ptr` is a valid pointer to `SSL_CLIENT_HELLO` provided by BoringSSL. - sanitize_slice((*self.ptr).extensions, (*self.ptr).extensions_len).unwrap_or(&[]) - } + client_hello_getter!(*self.ptr, extensions, extensions_len) } /// Extract a specific extension from the client hello. @@ -253,7 +244,7 @@ if ret == 1 { unsafe { // Safety: `out_data` and `out_len` are valid if the function returns 1. - sanitize_slice(out_data, out_len) + Some(u8::from_ffi_ptr(out_data, out_len)) } } else { None
diff --git a/rust/bssl-tls/src/credentials/methods.rs b/rust/bssl-tls/src/credentials/methods.rs index 2a40cba..f5a34da 100644 --- a/rust/bssl-tls/src/credentials/methods.rs +++ b/rust/bssl-tls/src/credentials/methods.rs
@@ -22,6 +22,7 @@ }, // }; +use bssl_crypto::FromFfiSlice; use once_cell::sync::Lazy; use crate::{ @@ -36,10 +37,6 @@ SignatureOperation, waker_data_from_ssl, // }, - ffi::{ - sanitise_mut_byteslice, - sanitize_slice, // - }, methods::drop_box_rust_methods, // }; @@ -144,20 +141,16 @@ // TODO(@xfding) maybe we should log this error? Err(_) => return bssl_sys::ssl_private_key_result_t_ssl_private_key_failure, }; - let Some(output) = (unsafe { - // Safety: the slice will only be used within this callback. - sanitise_mut_byteslice(out, max_out) - }) else { - return bssl_sys::ssl_private_key_result_t_ssl_private_key_failure; + let output = unsafe { + // Safety: the slice comes from BoringSSL and it will only be used within this callback. + bssl_crypto::zeroize_mut_byteslice(out, max_out) }; if output.is_empty() { return bssl_sys::ssl_private_key_result_t_ssl_private_key_failure; } - let Some(message) = (unsafe { + let message = unsafe { // Safety: `msg` outlives `message` because it is owned by BoringSSL. - sanitize_slice(msg, msg_len) - }) else { - return bssl_sys::ssl_private_key_result_t_ssl_private_key_failure; + u8::from_ffi_ptr(msg, msg_len) }; // Unwind-safety: when panic happens, we will not inspect the `output` buffer. abort_on_panic(move || { @@ -204,20 +197,16 @@ // Unwind-safety: later when panic happens, we detach the poisoned private key method // without calling destructor. - let Some(output) = (unsafe { - // Safety: the slice will only be used within this callback. - sanitise_mut_byteslice(out, max_out) - }) else { - return bssl_sys::ssl_private_key_result_t_ssl_private_key_failure; + let output = unsafe { + // Safety: the slice comes from BoringSSL and it will only be used within this callback. + bssl_crypto::zeroize_mut_byteslice(out, max_out) }; if output.is_empty() { return bssl_sys::ssl_private_key_result_t_ssl_private_key_failure; } - let Some(ciphertext) = (unsafe { + let ciphertext = unsafe { // Safety: `ciphertext` is now owned by BoringSSL and outlives the slice. - sanitize_slice(ciphertext, ciphertext_len) - }) else { - return bssl_sys::ssl_private_key_result_t_ssl_private_key_failure; + u8::from_ffi_ptr(ciphertext, ciphertext_len) }; // Unwind-safety: when panic happens, we will not inspect the `output` buffer. abort_on_panic(move || { @@ -252,11 +241,9 @@ // Unwind-safety: later when panic happens, we detach the poisoned private key method // without calling destructor. - let Some(output) = (unsafe { - // Safety: the slice will only be used within this callback. - sanitise_mut_byteslice(out, max_out) - }) else { - return bssl_sys::ssl_private_key_result_t_ssl_private_key_failure; + let output = unsafe { + // Safety: the slice comes from BoringSSL and it will only be used within this callback. + bssl_crypto::zeroize_mut_byteslice(out, max_out) }; if output.is_empty() { return bssl_sys::ssl_private_key_result_t_ssl_private_key_failure;
diff --git a/rust/bssl-tls/src/credentials/select_cert.rs b/rust/bssl-tls/src/credentials/select_cert.rs index a5f5a83..675cc7e 100644 --- a/rust/bssl-tls/src/credentials/select_cert.rs +++ b/rust/bssl-tls/src/credentials/select_cert.rs
@@ -14,29 +14,35 @@ //! TLS certificate selection hook. -use alloc::{vec, vec::Vec}; +use alloc::vec::Vec; use core::{ - ffi::{c_int, c_void}, + ffi::{ + c_int, + c_void, // + }, marker::PhantomData, - ptr::{NonNull, null}, + ptr::{ + NonNull, + null, // + }, task::Context, }; +use bssl_crypto::FromFfiSlice; + use super::{ CryptoBufferIterator, - DistinguishedName, // + DistinguishedName, SignatureAlgorithm, get_peer_certificate_type, - get_peer_raw_public_key, + get_peer_raw_public_key, // }; - use crate::{ CertCallback, abort_on_panic, config::ProtocolVersion, connection::methods::waker_data_from_ssl, - context::TlsContext, - ffi::sanitize_slice, // + context::TlsContext, // }; /// Result of certificate selection. @@ -233,18 +239,17 @@ // Safety: `self.0` is still valid by BoringSSL invariant. bssl_sys::SSL_get0_peer_verify_algorithms(self.ptr(), &raw mut algs) }; - if let Some(slice) = unsafe { - // Safety: `algs` is only live within this call. - sanitize_slice(algs, len) - } { - slice - .iter() - .copied() - .map(SignatureAlgorithm::try_from) - .collect() - } else { - vec![] - } + let slice = unsafe { + // Safety: + // - `slice` is only live within this call. + // - `slice` is generated by BoringSSL. + u16::from_ffi_ptr(algs, len) + }; + slice + .iter() + .copied() + .map(SignatureAlgorithm::try_from) + .collect() } /// Get TLS 1.2 certificate types. @@ -257,18 +262,17 @@ // Safety: `self.0` is still valid by BoringSSL invariant. bssl_sys::SSL_get0_certificate_types(self.ptr(), &raw mut types) }; - if let Some(slice) = unsafe { - // Safety: `types` is only live within this call. - sanitize_slice(types, len) - } { - slice - .iter() - .copied() - .map(RequestedCertificateType::try_from) - .collect() - } else { - vec![] - } + let slice = unsafe { + // Safety: + // - `types` is only live within this call. + // - `types` is generated by BoringSSL. + u8::from_ffi_ptr(types, len) + }; + slice + .iter() + .copied() + .map(RequestedCertificateType::try_from) + .collect() } /// Get server requested CAs for client authentication.
diff --git a/rust/bssl-tls/src/ffi.rs b/rust/bssl-tls/src/ffi.rs index 55d4b02..d27ce62 100644 --- a/rust/bssl-tls/src/ffi.rs +++ b/rust/bssl-tls/src/ffi.rs
@@ -23,14 +23,13 @@ NonNull, null, null_mut, // - }, - slice::{ - from_raw_parts, - from_raw_parts_mut, // }, // }; -use bssl_crypto::FfiSlice; +use bssl_crypto::{ + FfiSlice, + FromFfiSlice, // +}; use crate::{ context::CertificateCache, @@ -69,50 +68,6 @@ } } -/// Sanitize the data pointer and length and reconstitute the slice. -/// -/// This method returns an empty slice if the length is 0 or the pointer is NULL. -/// # Safety -/// Caller must ensure that `'a` outlives `input`. -#[inline] -pub(crate) unsafe fn sanitize_slice<'a, T>(input: *const T, len: usize) -> Option<&'a [T]> { - if len == 0 || input.is_null() { - return Some(&[]); - } - if !input.is_aligned() || len.checked_mul(size_of::<T>())? > isize::MAX as usize { - return None; - } - unsafe { - // Safety: the pointer and the size has been sanitised. - Some(from_raw_parts(input, len)) - } -} - -/// Sanitize the data pointer and length and reconstitute the mutable slice. -/// -/// `capacity` counts the number of `T`s that `out` can hold, **not number of bytes**. -/// -/// This method returns an empty slice if the length is 0 or the pointer is NULL. -/// # Safety -/// Caller must ensure that `'a` outlives `input`. -#[inline] -pub(crate) unsafe fn sanitise_mut_byteslice<'a>( - out: *mut u8, - capacity: usize, -) -> Option<&'a mut [u8]> { - if capacity == 0 || out.is_null() { - return Some(&mut []); - } - if capacity > isize::MAX as usize { - return None; - } - unsafe { - // Safety: `out` is 1-aligned and `0` is a valid pattern for `u8`. - core::ptr::write_bytes(out, 0, capacity); - Some(from_raw_parts_mut(out, capacity)) - } -} - pub(crate) fn crypto_buffer_from_buf( buf: &[u8], pool: Option<&CertificateCache>, @@ -253,7 +208,7 @@ unsafe { // Safety: `self` still exclusively owns the buffer region and the range of bytes // is known to be initialised by us. See `advance`. - sanitize_slice(self.ptr, self.cursor).unwrap_or(&[]) + u8::from_ffi_ptr(self.ptr, self.cursor) } }
diff --git a/rust/bssl-tls/src/io.rs b/rust/bssl-tls/src/io.rs index 756aab3..240765f 100644 --- a/rust/bssl-tls/src/io.rs +++ b/rust/bssl-tls/src/io.rs
@@ -31,6 +31,7 @@ }, }; +use bssl_crypto::FromFfiSlice; use once_cell::sync::Lazy; use crate::{ @@ -38,11 +39,7 @@ errors::{ Error, TlsRetryReason, // - }, - ffi::{ - sanitise_mut_byteslice, - sanitize_slice, // - }, + }, // }; #[cfg(feature = "std")] @@ -369,11 +366,9 @@ }; // Zero the buffer now. // TODO(@xfding): maybe we want to have a buffer wrapper that tracks initialised region. - let Some(buf) = (unsafe { + let buf = unsafe { // Safety: `buffer` and `len` are sanitised and initialised for the right memory region. - sanitise_mut_byteslice(buffer as *mut u8, len) - }) else { - return -1; + bssl_crypto::zeroize_mut_byteslice(buffer as *mut u8, len) }; let work = { let Some(reader) = rust_bio.get_reader() else { @@ -429,11 +424,11 @@ } else { None }; - let Some(buf) = (unsafe { - // Safety: `buffer` and `len` are sanitised and initialised for the right memory region. - sanitize_slice(buffer as *mut u8, len) - }) else { - return -1; + let buf = unsafe { + // Safety: + // - `buffer` and `len` are sanitised and initialised for the right memory region. + // - in `libssl` context, `buffer` is an allocation generated by BoringSSL. + u8::from_ffi_ptr(buffer as *const u8, len) }; let work = { let Some(writer) = rust_bio.get_writer() else {
diff --git a/rust/bssl-tls/src/macros.rs b/rust/bssl-tls/src/macros.rs index 3b6a19a..93bf11c 100644 --- a/rust/bssl-tls/src/macros.rs +++ b/rust/bssl-tls/src/macros.rs
@@ -93,14 +93,12 @@ ::bssl_sys::CRYPTO_BUFFER_len(self.ptr()), ) }; - if data.is_null() || len == 0 || len > isize::MAX as usize { - return &[] - } unsafe { // Safety: // - `data` is 1-size and 1-align and `len` is valid by BoringSSL invariant. // - `len` is sanitised to be within bound. - $crate::ffi::sanitize_slice(data, len).unwrap_or(&[]) + // - `data` is sourced from BoringSSL. + ::bssl_crypto::FromFfiSlice::from_ffi_ptr(data, len) } } } @@ -153,7 +151,7 @@ #[allow(unused_unsafe)] unsafe { // Safety: data and len are returned by BoringSSL and are valid. - $crate::ffi::sanitize_slice(data, len) + ::bssl_crypto::FromFfiSlice::from_ffi_ptr(data, len) } }}; }
diff --git a/rust/bssl-tls/src/sessions.rs b/rust/bssl-tls/src/sessions.rs index aee4f83..eada1b0 100644 --- a/rust/bssl-tls/src/sessions.rs +++ b/rust/bssl-tls/src/sessions.rs
@@ -17,6 +17,8 @@ use alloc::vec::Vec; use core::ptr::NonNull; +use bssl_crypto::FromFfiSlice; + use crate::{ call_slice_getter, config::ProtocolVersion, @@ -24,7 +26,6 @@ errors::Error, ffi::{ Alloc, - sanitize_slice, slice_into_ffi_raw_parts, // }, // }; @@ -76,7 +77,7 @@ let out_data = Alloc(out_data); let slice = unsafe { // Safety: out_data.0 and out_len are returned by BoringSSL and are valid. - sanitize_slice(out_data.0, out_len).unwrap() + u8::from_ffi_ptr(out_data.0, out_len) }; Ok(slice.to_vec()) } @@ -95,7 +96,7 @@ let out_data = Alloc(out_data); let slice = unsafe { // Safety: out_data.0 and out_len are returned by BoringSSL and are valid. - sanitize_slice(out_data.0, out_len).unwrap() + u8::from_ffi_ptr(out_data.0, out_len) }; Ok(slice.to_vec()) } @@ -165,11 +166,9 @@ bssl_sys::CRYPTO_BUFFER_len(buf), ) }; - let Some(slice) = (unsafe { + let slice = unsafe { // Safety: data and len are valid. - sanitize_slice(data, len) - }) else { - continue; + u8::from_ffi_ptr(data, len) }; res.push(slice.to_vec()); } @@ -178,17 +177,19 @@ /// Get the signed certificate timestamp list, if any. pub fn get_signed_cert_timestamp_list(&self) -> Option<&[u8]> { - call_slice_getter!( + let sct = call_slice_getter!( bssl_sys::SSL_SESSION_get0_signed_cert_timestamp_list, self.ptr() - ) + ); + (!sct.is_empty()).then_some(sct) } /// Get the OCSP response, if any. /// /// See [RFC 8446 §4.4.2.1](https://datatracker.ietf.org/doc/html/rfc8446#section-4.4.2.1). pub fn get_ocsp_response(&self) -> Option<&[u8]> { - call_slice_getter!(bssl_sys::SSL_SESSION_get0_ocsp_response, self.ptr()) + let ocsp = call_slice_getter!(bssl_sys::SSL_SESSION_get0_ocsp_response, self.ptr()); + (!ocsp.is_empty()).then_some(ocsp) } /// Check if the session should be single use. @@ -217,7 +218,8 @@ /// Get the ticket, if any. pub fn get_ticket(&self) -> Option<&[u8]> { - call_slice_getter!(bssl_sys::SSL_SESSION_get0_ticket, self.ptr()) + let ticket = call_slice_getter!(bssl_sys::SSL_SESSION_get0_ticket, self.ptr()); + (!ticket.is_empty()).then_some(ticket) } /// Check if the session has a peer SHA256. @@ -230,7 +232,8 @@ /// Get the peer SHA256, if any. pub fn get_peer_sha256(&self) -> Option<&[u8]> { - call_slice_getter!(bssl_sys::SSL_SESSION_get0_peer_sha256, self.ptr()) + let sha256 = call_slice_getter!(bssl_sys::SSL_SESSION_get0_peer_sha256, self.ptr()); + (!sha256.is_empty()).then_some(sha256) } /// Check if the session is resumable across names.
diff --git a/rust/bssl-x509/src/certificates.rs b/rust/bssl-x509/src/certificates.rs index ece3a6d..7156d8a 100644 --- a/rust/bssl-x509/src/certificates.rs +++ b/rust/bssl-x509/src/certificates.rs
@@ -72,10 +72,22 @@ ptr::{NonNull, null_mut}, }; +use bssl_crypto::FromFfiSlice; + use crate::{ - errors::{PemReason, PkiError, X509Error}, - ffi::{Bio, sanitize_slice, slice_into_ffi_raw_parts}, - keys::{PrivateKey, PublicKey}, + errors::{ + PemReason, + PkiError, + X509Error, // + }, + ffi::{ + Bio, + slice_into_ffi_raw_parts, // + }, + keys::{ + PrivateKey, + PublicKey, // + }, }; bssl_macros::bssl_enum! { @@ -175,8 +187,10 @@ return None; } let bytes = unsafe { - // Safety: `'a` will still outlive the input buffer and this byte slice. - sanitize_slice(ptr, str_len)? + // Safety: + // - `'a` will still outlive the input buffer and this byte slice. + // - `ptr` is sourced from BoringSSL. + u8::from_ffi_ptr(ptr, str_len) }; core::str::from_utf8(bytes).ok() } @@ -249,8 +263,10 @@ continue; } let bytes = unsafe { - // Safety: `self` will outlive the input buffer and this byte slice. - sanitize_slice(ptr, len as usize)? + // Safety: + // - `self` will outlive the input buffer and this byte slice. + // - `ptr` is sourced from BoringSSL. + u8::from_ffi_ptr(ptr, len as usize) }; return Some(GeneralName::Ip(bytes)); }
diff --git a/rust/bssl-x509/src/ffi.rs b/rust/bssl-x509/src/ffi.rs index 3137423..11f186f 100644 --- a/rust/bssl-x509/src/ffi.rs +++ b/rust/bssl-x509/src/ffi.rs
@@ -14,8 +14,10 @@ use core::{ marker::PhantomData, - ptr::{NonNull, null}, - slice::from_raw_parts, + ptr::{ + NonNull, + null, // + },// }; use bssl_crypto::FfiSlice; @@ -50,25 +52,6 @@ } } -/// Sanitize the data pointer and length and reconstitute the slice. -/// -/// This method returns an empty slice if the length is 0 or the pointer is NULL. -/// # Safety -/// Caller must ensure that `'a` outlives `input`. -#[inline] -pub(crate) unsafe fn sanitize_slice<'a, T>(input: *const T, len: usize) -> Option<&'a [T]> { - if len == 0 || input.is_null() { - return Some(&[]); - } - if !input.is_aligned() || len.checked_mul(size_of::<T>())? > isize::MAX as usize { - return None; - } - unsafe { - // Safety: the pointer and the size has been sanitised. - Some(from_raw_parts(input, len)) - } -} - /// BIO wrapper only for internal use. pub(crate) struct Bio<'a>(NonNull<bssl_sys::BIO>, PhantomData<&'a ()>);