initial setup for bssl crate with hmac and sha2 bindings
- update rust folder to split into `bssl` and `bssl-sys`
- add initial bindings for hmac and a subset of sha2

Change-Id: I09e0e778c1590de6818a49e19529ceb011e4d9f6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57285
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: Bob Beck <bbe@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/rust/bssl-crypto/src/digest.rs b/rust/bssl-crypto/src/digest.rs
new file mode 100644
index 0000000..cecdfdf
--- /dev/null
+++ b/rust/bssl-crypto/src/digest.rs
@@ -0,0 +1,80 @@
+/* Copyright (c) 2023, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+use crate::ForeignTypeRef;
+
+/// The BoringSSL implemented SHA-256 digest algorithm.
+#[derive(Clone)]
+pub struct Sha256 {}
+
+/// The BoringSSL implemented SHA-512 digest algorithm.
+#[derive(Clone)]
+pub struct Sha512 {}
+
+/// A reference to an [`Md`], which abstracts the details of a specific hash function allowing code
+/// to deal with the concept of a "hash function" without needing to know exactly which hash function
+/// it is.
+pub(crate) struct MdRef;
+
+unsafe impl ForeignTypeRef for MdRef {
+    type CType = bssl_sys::EVP_MD;
+}
+
+/// Used internally to get a BoringSSL internal MD
+pub(crate) trait Md {
+    /// gets a reference to a message digest algorithm to be used by the hkdf implementation
+    fn get_md() -> &'static MdRef;
+}
+
+impl Md for Sha256 {
+    fn get_md() -> &'static MdRef {
+        // Safety:
+        // - this always returns a valid pointer to an EVP_MD
+        unsafe { MdRef::from_ptr(bssl_sys::EVP_sha256() as *mut _) }
+    }
+}
+
+impl Md for Sha512 {
+    fn get_md() -> &'static MdRef {
+        // Safety:
+        // - this always returns a valid pointer to an EVP_MD
+        unsafe { MdRef::from_ptr(bssl_sys::EVP_sha512() as *mut _) }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn test_sha256_c_type() {
+        unsafe {
+            assert_eq!(
+                MdRef::from_ptr(bssl_sys::EVP_sha256() as *mut _).as_ptr(),
+                bssl_sys::EVP_sha256() as *mut _
+            )
+        }
+    }
+
+    #[test]
+    fn test_sha512_c_type() {
+        unsafe {
+            assert_eq!(
+                MdRef::from_ptr(bssl_sys::EVP_sha512() as *mut _).as_ptr(),
+                bssl_sys::EVP_sha512() as *mut _
+            )
+        }
+    }
+}
diff --git a/rust/bssl-crypto/src/hmac.rs b/rust/bssl-crypto/src/hmac.rs
new file mode 100644
index 0000000..829816c
--- /dev/null
+++ b/rust/bssl-crypto/src/hmac.rs
@@ -0,0 +1,391 @@
+/* Copyright (c) 2023, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+use crate::{
+    digest::{Md, Sha256, Sha512},
+    CSlice, ForeignTypeRef as _, PanicResultHandler,
+};
+use core::{
+    ffi::{c_uint, c_void},
+    marker::PhantomData,
+    ptr,
+};
+
+/// Computes the HMAC-SHA-256 of `data` as a one-shot operation.
+///
+/// Calculates the HMAC of data, using the given `key` and returns the result.
+/// It returns the computed hmac or `InvalidLength` of the input key size is too large.
+/// Can panic if memory allocation fails in the underlying BoringSSL code.
+pub fn hmac_sha_256(key: &[u8], data: &[u8]) -> Result<[u8; 32], InvalidLength> {
+    hmac::<32, Sha256>(key, data)
+}
+
+/// Computes the HMAC-SHA-512 of `data` as a one-shot operation.
+///
+/// Calculates the HMAC of data, using the given `key` and returns the result.
+/// It returns the computed hmac or `InvalidLength` of the input key size is too large.
+/// Can panic if memory allocation fails in the underlying BoringSSL code.
+pub fn hmac_sha_512(key: &[u8], data: &[u8]) -> Result<[u8; 64], InvalidLength> {
+    hmac::<64, Sha512>(key, data)
+}
+
+/// The BoringSSL HMAC-SHA-256 implementation. The operations may panic if memory allocation fails
+/// in BoringSSL.
+pub struct HmacSha256(Hmac<32, Sha256>);
+
+impl HmacSha256 {
+    /// Create a new hmac from a fixed size key.
+    pub fn new(key: [u8; 32]) -> Self {
+        Self(Hmac::new(key))
+    }
+
+    /// Create new hmac value from variable size key.
+    pub fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
+        Hmac::new_from_slice(key).map(Self)
+    }
+
+    /// Update state using the provided data.
+    pub fn update(&mut self, data: &[u8]) {
+        self.0.update(data)
+    }
+
+    /// Obtain the hmac computation consuming the hmac instance.
+    pub fn finalize(self) -> [u8; 32] {
+        self.0.finalize()
+    }
+
+    /// Check that the tag value is correct for the processed input.
+    pub fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> {
+        self.0.verify_slice(tag)
+    }
+
+    /// Check that the tag value is correct for the processed input.
+    pub fn verify(self, tag: [u8; 32]) -> Result<(), MacError> {
+        self.0.verify(tag)
+    }
+
+    /// Check truncated tag correctness using left side bytes of the calculated tag.
+    pub fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
+        self.0.verify_truncated_left(tag)
+    }
+}
+
+/// The BoringSSL HMAC-SHA-512 implementation. The operations may panic if memory allocation fails
+/// in BoringSSL.
+pub struct HmacSha512(Hmac<64, Sha512>);
+
+impl HmacSha512 {
+    /// Create a new hmac from a fixed size key.
+    pub fn new(key: [u8; 64]) -> Self {
+        Self(Hmac::new(key))
+    }
+
+    /// Create new hmac value from variable size key.
+    pub fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
+        Hmac::new_from_slice(key).map(Self)
+    }
+
+    /// Update state using the provided data.
+    pub fn update(&mut self, data: &[u8]) {
+        self.0.update(data)
+    }
+
+    /// Obtain the hmac computation consuming the hmac instance.
+    pub fn finalize(self) -> [u8; 64] {
+        self.0.finalize()
+    }
+
+    /// Check that the tag value is correct for the processed input.
+    pub fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> {
+        self.0.verify_slice(tag)
+    }
+
+    /// Check that the tag value is correct for the processed input.
+    pub fn verify(self, tag: [u8; 64]) -> Result<(), MacError> {
+        self.0.verify(tag)
+    }
+
+    /// Check truncated tag correctness using left side bytes of the calculated tag.
+    pub fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
+        self.0.verify_truncated_left(tag)
+    }
+}
+
+/// Error type for when the provided key material length is invalid.
+#[derive(Debug)]
+pub struct InvalidLength;
+
+/// Error type for when the output of the hmac operation is not equal to the expected value.
+#[derive(Debug)]
+pub struct MacError;
+
+/// Private generically implemented function for computing hmac as a oneshot operation.
+/// This should only be exposed publicly by types with the correct output size `N` which corresponds
+/// to the output size of the provided generic hash function. Ideally `N` would just come from `M`,
+/// but this is not possible until the Rust language can support the `min_const_generics` feature.
+/// Until then we will have to pass both separately: https://github.com/rust-lang/rust/issues/60551
+#[inline]
+fn hmac<const N: usize, M: Md>(key: &[u8], data: &[u8]) -> Result<[u8; N], InvalidLength> {
+    let mut out = [0_u8; N];
+    let mut size: c_uint = 0;
+
+    // Safety:
+    // - buf always contains N bytes of space
+    // - If NULL is returned on error we panic immediately
+    unsafe {
+        bssl_sys::HMAC(
+            M::get_md().as_ptr(),
+            CSlice::from(key).as_ptr(),
+            key.len(),
+            CSlice::from(data).as_ptr(),
+            data.len(),
+            out.as_mut_ptr(),
+            &mut size as *mut c_uint,
+        )
+    }
+    .panic_if_error();
+
+    Ok(out)
+}
+
+/// Private generically implemented hmac  instance given a generic hash function and a length `N`,
+/// where `N` is the output size of the hash function. This should only be exposed publicly by
+/// wrapper types with the correct output size `N` which corresponds to the output size of the
+/// provided generic hash function. Ideally `N` would just come from `M`, but this is not possible
+/// until the Rust language can support the `min_const_generics` feature. Until then we will have to
+/// pass both separately: https://github.com/rust-lang/rust/issues/60551
+struct Hmac<const N: usize, M: Md> {
+    ctx: *mut bssl_sys::HMAC_CTX,
+    _marker: PhantomData<M>,
+}
+
+impl<const N: usize, M: Md> Hmac<N, M> {
+    /// Infallible HMAC creation from a fixed length key.
+    fn new(key: [u8; N]) -> Self {
+        #[allow(clippy::expect_used)]
+        Self::new_from_slice(&key).expect("output length of hash is always a valid hmac key size")
+    }
+
+    /// Create new hmac value from variable size key. Panics on allocation failure
+    /// returns InvalidLength if the key length is greater than the max message digest block size.
+    fn new_from_slice(key: &[u8]) -> Result<Self, InvalidLength> {
+        (validate_key_len(key.len()))
+            .then(|| {
+                // Safety:
+                // - HMAC_CTX_new panics if allocation fails
+                let ctx = unsafe { bssl_sys::HMAC_CTX_new() };
+                ctx.panic_if_error();
+
+                // Safety:
+                // - HMAC_Init_ex must be called with a context previously created with HMAC_CTX_new,
+                //   which is the line above.
+                // - HMAC_Init_ex may return an error if key is null but the md is different from
+                //   before. This is avoided here since key is guaranteed to be non-null.
+                // - HMAC_Init_ex returns 0 on allocation failure in which case we panic
+                unsafe {
+                    bssl_sys::HMAC_Init_ex(
+                        ctx,
+                        CSlice::from(key).as_ptr() as *const c_void,
+                        key.len(),
+                        M::get_md().as_ptr(),
+                        ptr::null_mut(),
+                    )
+                }
+                .panic_if_error();
+
+                Self {
+                    ctx,
+                    _marker: Default::default(),
+                }
+            })
+            .ok_or(InvalidLength)
+    }
+
+    /// Update state using the provided data, can be called repeatedly.
+    fn update(&mut self, data: &[u8]) {
+        unsafe {
+            // Safety: HMAC_Update will always return 1, in case it doesnt we panic
+            bssl_sys::HMAC_Update(self.ctx, data.as_ptr(), data.len())
+        }
+        .panic_if_error()
+    }
+
+    /// Obtain the hmac computation consuming the hmac instance.
+    fn finalize(self) -> [u8; N] {
+        let mut buf = [0_u8; N];
+        let mut size: c_uint = 0;
+        // Safety:
+        // - hmac has a fixed size output of N which will never exceed the length of an N
+        // length array
+        // - on allocation failure we panic
+        unsafe { bssl_sys::HMAC_Final(self.ctx, buf.as_mut_ptr(), &mut size as *mut c_uint) }
+            .panic_if_error();
+        buf
+    }
+
+    /// Check that the tag value is correct for the processed input.
+    fn verify(self, tag: [u8; N]) -> Result<(), MacError> {
+        self.verify_slice(&tag)
+    }
+
+    /// Check truncated tag correctness using all bytes
+    /// of calculated tag.
+    ///
+    /// Returns `Error` if `tag` is not valid or not equal in length
+    /// to MAC's output.
+    fn verify_slice(self, tag: &[u8]) -> Result<(), MacError> {
+        tag.len().eq(&N).then_some(()).ok_or(MacError)?;
+        self.verify_truncated_left(tag)
+    }
+
+    /// Check truncated tag correctness using left side bytes
+    /// (i.e. `tag[..n]`) of calculated tag.
+    ///
+    /// Returns `Error` if `tag` is not valid or empty.
+    fn verify_truncated_left(self, tag: &[u8]) -> Result<(), MacError> {
+        let len = tag.len();
+        if len == 0 || len > N {
+            return Err(MacError);
+        }
+
+        let result = &self.finalize()[..len];
+
+        // Safety:
+        // - if a != b is undefined, it simply returns a non-zero result
+        unsafe {
+            bssl_sys::CRYPTO_memcmp(
+                CSlice::from(result).as_ptr() as *const c_void,
+                CSlice::from(tag).as_ptr() as *const c_void,
+                result.len(),
+            )
+        }
+        .eq(&0)
+        .then_some(())
+        .ok_or(MacError)
+    }
+}
+
+impl<const N: usize, M: Md> Drop for Hmac<N, M> {
+    fn drop(&mut self) {
+        unsafe { bssl_sys::HMAC_CTX_free(self.ctx) }
+    }
+}
+
+// make sure key len is within a valid range
+fn validate_key_len(len: usize) -> bool {
+    if len > bssl_sys::EVP_MAX_MD_BLOCK_SIZE as usize {
+        return false;
+    }
+    true
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn hmac_sha256_test() {
+        let expected_hmac = [
+            0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
+            0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
+            0x2e, 0x32, 0xcf, 0xf7,
+        ];
+
+        let key: [u8; 20] = [0x0b; 20];
+        let data = b"Hi There";
+
+        let mut hmac = HmacSha256::new_from_slice(&key).expect("length is valid");
+        hmac.update(data);
+        let hmac_result: [u8; 32] = hmac.finalize();
+
+        // let hmac_result =
+        //     hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
+        assert_eq!(&hmac_result, &expected_hmac);
+    }
+
+    #[test]
+    fn hmac_sha256_fixed_size_key_test() {
+        let expected_hmac = [
+            0x19, 0x8a, 0x60, 0x7e, 0xb4, 0x4b, 0xfb, 0xc6, 0x99, 0x3, 0xa0, 0xf1, 0xcf, 0x2b,
+            0xbd, 0xc5, 0xba, 0xa, 0xa3, 0xf3, 0xd9, 0xae, 0x3c, 0x1c, 0x7a, 0x3b, 0x16, 0x96,
+            0xa0, 0xb6, 0x8c, 0xf7,
+        ];
+
+        let key: [u8; 32] = [0x0b; 32];
+        let data = b"Hi There";
+
+        let mut hmac = HmacSha256::new(key);
+        hmac.update(data);
+        let hmac_result: [u8; 32] = hmac.finalize();
+        assert_eq!(&hmac_result, &expected_hmac);
+    }
+
+    #[test]
+    fn hmac_sha256_update_test() {
+        let expected_hmac = [
+            0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
+            0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
+            0x2e, 0x32, 0xcf, 0xf7,
+        ];
+        let key: [u8; 20] = [0x0b; 20];
+        let data = b"Hi There";
+        let mut hmac: HmacSha256 = HmacSha256::new_from_slice(&key).expect("");
+        hmac.update(data);
+        let result = hmac.finalize();
+        assert_eq!(&result, &expected_hmac);
+        assert_eq!(result.len(), 32);
+    }
+
+    #[test]
+    fn hmac_sha256_test_big_buffer() {
+        let expected_hmac = [
+            0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
+            0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
+            0x2e, 0x32, 0xcf, 0xf7,
+        ];
+        let key: [u8; 20] = [0x0b; 20];
+        let data = b"Hi There";
+        let hmac_result = hmac_sha_256(&key, data).expect("Couldn't calculate sha256 hmac");
+        assert_eq!(&hmac_result, &expected_hmac);
+    }
+
+    #[test]
+    fn hmac_sha256_update_chunks_test() {
+        let expected_hmac = [
+            0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
+            0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
+            0x2e, 0x32, 0xcf, 0xf7,
+        ];
+        let key: [u8; 20] = [0x0b; 20];
+        let mut hmac = HmacSha256::new_from_slice(&key).expect("key is valid length");
+        hmac.update(b"Hi");
+        hmac.update(b" There");
+        let result = hmac.finalize();
+        assert_eq!(&result, &expected_hmac);
+    }
+
+    #[test]
+    fn hmac_sha256_verify_test() {
+        let expected_hmac = [
+            0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb,
+            0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c,
+            0x2e, 0x32, 0xcf, 0xf7,
+        ];
+        let key: [u8; 20] = [0x0b; 20];
+        let data = b"Hi There";
+        let mut hmac: HmacSha256 = HmacSha256::new_from_slice(&key).expect("");
+        hmac.update(data);
+        assert!(hmac.verify(expected_hmac).is_ok())
+    }
+}
diff --git a/rust/bssl-crypto/src/lib.rs b/rust/bssl-crypto/src/lib.rs
new file mode 100644
index 0000000..166f999
--- /dev/null
+++ b/rust/bssl-crypto/src/lib.rs
@@ -0,0 +1,118 @@
+/* Copyright (c) 2023, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#![deny(
+    missing_docs,
+    clippy::indexing_slicing,
+    clippy::unwrap_used,
+    clippy::panic,
+    clippy::expect_used
+)]
+
+//! Rust boringssl binding
+
+extern crate core;
+use core::ops::Not;
+
+/// BoringSSL implemented hmac operations.
+pub mod hmac;
+
+/// BoringSSL implemented hash functions.
+pub mod digest;
+
+/// Used for handling result types from C APIs.
+trait PanicResultHandler {
+    /// Panics if a C api returns an invalid result
+    /// Used for APIs which return error codes for allocation failures.
+    fn panic_if_error(&self);
+}
+
+impl PanicResultHandler for i32 {
+    /// BoringSSL APIs return 1 on success or 0 on allocation failure.
+    #[allow(clippy::expect_used)]
+    fn panic_if_error(&self) {
+        self.gt(&0).then_some(()).expect("allocation failed!")
+    }
+}
+
+impl<T> PanicResultHandler for *mut T {
+    /// Boringssl APIs return NULL on allocation failure for APIs that return a CTX.
+    #[allow(clippy::expect_used)]
+    fn panic_if_error(&self) {
+        self.is_null()
+            .not()
+            .then_some(())
+            .expect("allocation failed!")
+    }
+}
+
+struct CSlice<'a>(&'a [u8]);
+
+impl CSlice<'_> {
+    pub fn as_ptr<T>(&self) -> *const T {
+        if self.0.is_empty() {
+            std::ptr::null()
+        } else {
+            self.0.as_ptr() as *const T
+        }
+    }
+}
+
+impl<'a> From<&'a [u8]> for CSlice<'a> {
+    fn from(value: &'a [u8]) -> Self {
+        Self(value)
+    }
+}
+
+/// A helper trait implemented by types which reference borrowed foreign types.
+///
+/// # Safety
+///
+/// Implementations of `ForeignTypeRef` must guarantee the following:
+///
+/// - `Self::from_ptr(x).as_ptr() == x`
+/// - `Self::from_mut_ptr(x).as_ptr() == x`
+unsafe trait ForeignTypeRef: Sized {
+    /// The raw C type.
+    type CType;
+
+    /// Constructs a shared instance of this type from its raw type.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be a valid, immutable, instance of the type for the `'a` lifetime.
+    #[inline]
+    unsafe fn from_ptr<'a>(ptr: *mut Self::CType) -> &'a Self {
+        debug_assert!(!ptr.is_null());
+        &*(ptr as *mut _)
+    }
+
+    /// Constructs a mutable reference of this type from its raw type.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be a valid, unique, instance of the type for the `'a` lifetime.
+    #[inline]
+    unsafe fn from_ptr_mut<'a>(ptr: *mut Self::CType) -> &'a mut Self {
+        debug_assert!(!ptr.is_null());
+        &mut *(ptr as *mut _)
+    }
+
+    /// Returns a raw pointer to the wrapped value.
+    #[inline]
+    fn as_ptr(&self) -> *mut Self::CType {
+        self as *const _ as *mut _
+    }
+}