diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml new file mode 100644 index 0000000..4a628f7 --- /dev/null +++ b/.github/workflows/audit.yml @@ -0,0 +1,17 @@ +name: Security Audit +on: + schedule: + - cron: '0 0 * * 1' + push: + paths: + - Cargo.toml +jobs: + security_audit: + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v1 + - name: Security Audit + uses: actions-rs/audit-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..575a6a9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,42 @@ +name: CI +on: push +jobs: + ci: + runs-on: windows-latest + strategy: + matrix: + rust: + - 1.37.0 # MSRV + - stable + - beta + - nightly + features: + - "" + - "zeroize" + exclude: # Zeroize 1.1 supports Rust 1.39+ + - rust: 1.37.0 + features: "zeroize" + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + override: true + components: rustfmt, clippy + - uses: actions-rs/cargo@v1 + with: + command: build + args: --no-default-features --features "${{ matrix.features }}" + - uses: actions-rs/cargo@v1 + with: + command: test + args: --no-default-features --features "${{ matrix.features }}" + - uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check + - uses: actions-rs/cargo@v1 + with: + command: clippy + args: --no-default-features --features "${{ matrix.features }}" -- -D warnings \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 1458a48..34ef604 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,10 @@ maintenance = { status = "experimental" } [dependencies] winapi = { version = "0.3", features = ["bcrypt", "ntstatus"] } zeroize = { version = "1.1", optional = true } +doc-comment = "0.3" + +[dev-dependencies] +doc-comment = "0.3" [features] default = ["zeroize"] diff --git a/README.md b/README.md index 7879140..cd275b1 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,9 @@ [![crates.io](https://img.shields.io/crates/v/win-crypto-ng.svg)](https://crates.io/crates/win-crypto-ng) [![docs.rs](https://docs.rs/win-crypto-ng/badge.svg)](https://docs.rs/crate/win-crypto-ng) +![MSRV](https://img.shields.io/badge/rustc-1.37+-blue.svg) +[![Build status](https://github.com/emgre/win-crypto-ng/workflows/CI/badge.svg)](https://github.com/emgre/win-crypto-ng/actions) +[![License](https://img.shields.io/github/license/emgre/win-crypto-ng)](https://github.com/emgre/win-crypto-ng/blob/master/LICENSE.md) Safe Rust bindings to Microsoft Windows [Cryptography API : Next Generation (CNG)](https://docs.microsoft.com/en-us/windows/win32/seccng/cng-portal) diff --git a/src/buffer.rs b/src/buffer.rs index bf181cb..78e9962 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -24,7 +24,9 @@ impl Buffer { /// assert_eq!(buf.len(), 76); /// ``` pub fn new(size: usize) -> Self { - Buffer { inner: vec![0; size] } + Buffer { + inner: vec![0; size], + } } /// Create a new buffer with its data copied from the slice. @@ -38,7 +40,9 @@ impl Buffer { /// assert_eq!(buf.as_slice(), SOME_DATA); /// ``` pub fn from(data: &[u8]) -> Self { - Buffer { inner: data.to_vec() } + Buffer { + inner: data.to_vec(), + } } pub fn len(&self) -> usize { diff --git a/src/hash.rs b/src/hash.rs index 2ffb924..e343cd7 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -44,12 +44,12 @@ //! [`hash`]: struct.Hash.html#method.hash //! [`finish`]: struct.Hash.html#method.finish -use crate::{Error, Result}; use crate::buffer::Buffer; use crate::helpers::{AlgoHandle, Handle}; -use winapi::shared::bcrypt::*; -use winapi::shared::minwindef::{DWORD, ULONG, PUCHAR}; +use crate::{Error, Result}; use std::ptr::null_mut; +use winapi::shared::bcrypt::*; +use winapi::shared::minwindef::{DWORD, PUCHAR, ULONG}; /// Hashing algorithm identifiers #[derive(Debug, Clone, Copy, PartialOrd, PartialEq)] @@ -141,17 +141,19 @@ impl HashAlgorithm { let mut hash_handle = HashHandle::new(); let mut object = Buffer::new(object_size); unsafe { - Error::check( - BCryptCreateHash( - self.handle.as_ptr(), - hash_handle.as_mut_ptr(), - object.as_mut_ptr(), - object.len() as ULONG, - null_mut(), - 0, - 0 - ) - ).map(|_| Hash { handle: hash_handle, _object: object }) + Error::check(BCryptCreateHash( + self.handle.as_ptr(), + hash_handle.as_mut_ptr(), + object.as_mut_ptr(), + object.len() as ULONG, + null_mut(), + 0, + 0, + )) + .map(|_| Hash { + handle: hash_handle, + _object: object, + }) } } } @@ -169,7 +171,9 @@ impl HashHandle { impl Drop for HashHandle { fn drop(&mut self) { if !self.handle.is_null() { - unsafe { BCryptDestroyHash(self.handle); } + unsafe { + BCryptDestroyHash(self.handle); + } } } } @@ -212,7 +216,7 @@ impl Hash { self.handle.as_ptr(), data.as_ptr() as PUCHAR, data.len() as ULONG, - 0 + 0, )) } } @@ -242,14 +246,13 @@ impl Hash { let mut result = Buffer::new(hash_size); unsafe { - Error::check( - BCryptFinishHash( - self.handle.as_ptr(), - result.as_mut_ptr(), - result.len() as ULONG, - 0 - ) - ).map(|_| result) + Error::check(BCryptFinishHash( + self.handle.as_ptr(), + result.as_mut_ptr(), + result.len() as ULONG, + 0, + )) + .map(|_| result) } } @@ -266,7 +269,9 @@ impl Hash { /// assert_eq!(hash_size, 32); /// ``` pub fn hash_size(&self) -> Result { - self.handle.get_property::(BCRYPT_HASH_LENGTH).map(|hash_size| hash_size as usize) + self.handle + .get_property::(BCRYPT_HASH_LENGTH) + .map(|hash_size| hash_size as usize) } } @@ -278,71 +283,92 @@ mod tests { #[test] fn sha1() { - check_hash(HashAlgorithmId::Sha1, DATA.as_bytes(), &[ - 0x2B, 0x44, 0x89, 0x60, 0x6A, 0x23, 0xFB, 0x31, - 0xFC, 0xDC, 0x84, 0x9F, 0xA7, 0xE5, 0x77, 0xBA, - 0x90, 0xF6, 0xD3, 0x9A, - ]) + check_hash( + HashAlgorithmId::Sha1, + DATA.as_bytes(), + &[ + 0x2B, 0x44, 0x89, 0x60, 0x6A, 0x23, 0xFB, 0x31, 0xFC, 0xDC, 0x84, 0x9F, 0xA7, 0xE5, + 0x77, 0xBA, 0x90, 0xF6, 0xD3, 0x9A, + ], + ) } #[test] fn sha256() { - check_hash(HashAlgorithmId::Sha256, DATA.as_bytes(), &[ - 0x0E, 0xA3, 0x7C, 0x24, 0x3F, 0x60, 0x97, 0x4B, - 0x0D, 0x54, 0xC6, 0xB2, 0xD7, 0x6C, 0xEC, 0xE3, - 0xF4, 0xC7, 0x42, 0x49, 0x2C, 0xCE, 0x48, 0xEA, - 0xF8, 0x1F, 0x35, 0x79, 0x31, 0xD6, 0xD6, 0x9E, - ]) + check_hash( + HashAlgorithmId::Sha256, + DATA.as_bytes(), + &[ + 0x0E, 0xA3, 0x7C, 0x24, 0x3F, 0x60, 0x97, 0x4B, 0x0D, 0x54, 0xC6, 0xB2, 0xD7, 0x6C, + 0xEC, 0xE3, 0xF4, 0xC7, 0x42, 0x49, 0x2C, 0xCE, 0x48, 0xEA, 0xF8, 0x1F, 0x35, 0x79, + 0x31, 0xD6, 0xD6, 0x9E, + ], + ) } #[test] fn sha384() { - check_hash(HashAlgorithmId::Sha384, DATA.as_bytes(), &[ - 0x2A, 0x10, 0x60, 0x89, 0x6A, 0xCB, 0xA9, 0xFA, - 0x37, 0x11, 0xBF, 0x10, 0x9E, 0x90, 0x24, 0xEA, - 0x19, 0xF5, 0xFC, 0x33, 0xAF, 0x0F, 0x47, 0x15, - 0xC3, 0xE9, 0xD8, 0x63, 0xB3, 0x24, 0xA5, 0x08, - 0x9F, 0xAB, 0x95, 0x36, 0xB2, 0xAC, 0x10, 0xF6, - 0xC1, 0xE7, 0x31, 0x03, 0x09, 0x54, 0x18, 0x41, - ]) + check_hash( + HashAlgorithmId::Sha384, + DATA.as_bytes(), + &[ + 0x2A, 0x10, 0x60, 0x89, 0x6A, 0xCB, 0xA9, 0xFA, 0x37, 0x11, 0xBF, 0x10, 0x9E, 0x90, + 0x24, 0xEA, 0x19, 0xF5, 0xFC, 0x33, 0xAF, 0x0F, 0x47, 0x15, 0xC3, 0xE9, 0xD8, 0x63, + 0xB3, 0x24, 0xA5, 0x08, 0x9F, 0xAB, 0x95, 0x36, 0xB2, 0xAC, 0x10, 0xF6, 0xC1, 0xE7, + 0x31, 0x03, 0x09, 0x54, 0x18, 0x41, + ], + ) } #[test] fn sha512() { - check_hash(HashAlgorithmId::Sha512, DATA.as_bytes(), &[ - 0x39, 0x50, 0xAC, 0xCD, 0xFE, 0xF7, 0x46, 0x20, - 0x71, 0x42, 0x78, 0x76, 0x5B, 0xBD, 0xCE, 0x04, - 0xD4, 0x57, 0x90, 0x4B, 0x7C, 0xEA, 0x86, 0x31, - 0x39, 0x6C, 0xBA, 0x6D, 0x8B, 0xCE, 0xFC, 0xE0, - 0x30, 0x8F, 0xC4, 0x7C, 0xFB, 0x88, 0x5B, 0xC8, - 0x9E, 0xBD, 0xF4, 0xFF, 0xA6, 0xF9, 0x8F, 0xC8, - 0x51, 0x05, 0x54, 0x7C, 0xBD, 0xDF, 0x56, 0x57, - 0xB6, 0xAD, 0xBD, 0xDD, 0xA3, 0x8C, 0xB9, 0xB5, - ]) + check_hash( + HashAlgorithmId::Sha512, + DATA.as_bytes(), + &[ + 0x39, 0x50, 0xAC, 0xCD, 0xFE, 0xF7, 0x46, 0x20, 0x71, 0x42, 0x78, 0x76, 0x5B, 0xBD, + 0xCE, 0x04, 0xD4, 0x57, 0x90, 0x4B, 0x7C, 0xEA, 0x86, 0x31, 0x39, 0x6C, 0xBA, 0x6D, + 0x8B, 0xCE, 0xFC, 0xE0, 0x30, 0x8F, 0xC4, 0x7C, 0xFB, 0x88, 0x5B, 0xC8, 0x9E, 0xBD, + 0xF4, 0xFF, 0xA6, 0xF9, 0x8F, 0xC8, 0x51, 0x05, 0x54, 0x7C, 0xBD, 0xDF, 0x56, 0x57, + 0xB6, 0xAD, 0xBD, 0xDD, 0xA3, 0x8C, 0xB9, 0xB5, + ], + ) } #[test] fn md2() { - check_hash(HashAlgorithmId::Md2, DATA.as_bytes(), &[ - 0x08, 0x18, 0x53, 0xA0, 0x5C, 0x1F, 0x58, 0xC6, - 0xED, 0x43, 0x46, 0x4C, 0x79, 0x7D, 0x65, 0x26, - ]) + check_hash( + HashAlgorithmId::Md2, + DATA.as_bytes(), + &[ + 0x08, 0x18, 0x53, 0xA0, 0x5C, 0x1F, 0x58, 0xC6, 0xED, 0x43, 0x46, 0x4C, 0x79, 0x7D, + 0x65, 0x26, + ], + ) } #[test] fn md4() { - check_hash(HashAlgorithmId::Md4, DATA.as_bytes(), &[ - 0x24, 0x3C, 0xDA, 0xF5, 0x91, 0x4A, 0xE8, 0x70, - 0x91, 0xC7, 0x13, 0xB5, 0xFA, 0x9F, 0xA7, 0x98, - ]) + check_hash( + HashAlgorithmId::Md4, + DATA.as_bytes(), + &[ + 0x24, 0x3C, 0xDA, 0xF5, 0x91, 0x4A, 0xE8, 0x70, 0x91, 0xC7, 0x13, 0xB5, 0xFA, 0x9F, + 0xA7, 0x98, + ], + ) } #[test] fn md5() { - check_hash(HashAlgorithmId::Md5, DATA.as_bytes(), &[ - 0xE8, 0x89, 0xD8, 0x2D, 0xD1, 0x11, 0xD6, 0x31, - 0x5D, 0x7B, 0x1E, 0xDC, 0xE2, 0xB1, 0xB3, 0x0F, - ]) + check_hash( + HashAlgorithmId::Md5, + DATA.as_bytes(), + &[ + 0xE8, 0x89, 0xD8, 0x2D, 0xD1, 0x11, 0xD6, 0x31, 0x5D, 0x7B, 0x1E, 0xDC, 0xE2, 0xB1, + 0xB3, 0x0F, + ], + ) } fn check_hash(algo_id: HashAlgorithmId, data: &[u8], expected_hash: &[u8]) { @@ -355,4 +381,4 @@ mod tests { assert_eq!(hash_size, expected_hash.len()); assert_eq!(result.as_slice(), expected_hash); } -} \ No newline at end of file +} diff --git a/src/helpers.rs b/src/helpers.rs index d64b771..2e408c7 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1,10 +1,10 @@ use crate::{Error, Result}; -use winapi::shared::bcrypt::*; -use winapi::shared::ntdef::{LPCWSTR, PUCHAR, UCHAR, ULONG, VOID}; use std::ffi::{OsStr, OsString}; use std::mem::MaybeUninit; use std::os::windows::ffi::{OsStrExt, OsStringExt}; use std::ptr::{null, null_mut}; +use winapi::shared::bcrypt::*; +use winapi::shared::ntdef::{LPCWSTR, PUCHAR, UCHAR, ULONG, VOID}; pub trait Handle { fn as_ptr(&self) -> BCRYPT_HANDLE; @@ -13,15 +13,13 @@ pub trait Handle { fn set_property(&self, property: &str, value: &T) -> Result<()> { let property_str = WindowsString::from_str(property); unsafe { - Error::check( - BCryptSetProperty( - self.as_ptr(), - property_str.as_ptr(), - value as *const _ as PUCHAR, - std::mem::size_of_val(value) as ULONG, - 0 - ) - ) + Error::check(BCryptSetProperty( + self.as_ptr(), + property_str.as_ptr(), + value as *const _ as PUCHAR, + std::mem::size_of_val(value) as ULONG, + 0, + )) } } @@ -30,16 +28,15 @@ pub trait Handle { let mut value = MaybeUninit::::uninit(); let mut result_len = MaybeUninit::::uninit(); unsafe { - Error::check( - BCryptGetProperty( - self.as_ptr(), - property_str.as_ptr(), - value.as_mut_ptr() as *mut UCHAR, - std::mem::size_of::() as ULONG, - result_len.as_mut_ptr(), - 0 - ) - ).map(|_| value.assume_init()) + Error::check(BCryptGetProperty( + self.as_ptr(), + property_str.as_ptr(), + value.as_mut_ptr() as *mut UCHAR, + std::mem::size_of::() as ULONG, + result_len.as_mut_ptr(), + 0, + )) + .map(|_| value.assume_init()) } } } @@ -53,13 +50,13 @@ impl AlgoHandle { let mut handle = null_mut::(); unsafe { let id_str = WindowsString::from_str(id); - Error::check( - BCryptOpenAlgorithmProvider( - &mut handle, - id_str.as_ptr(), - null(), - 0) - ).map(|_| Self { handle }) + Error::check(BCryptOpenAlgorithmProvider( + &mut handle, + id_str.as_ptr(), + null(), + 0, + )) + .map(|_| Self { handle }) } } } @@ -67,7 +64,9 @@ impl AlgoHandle { impl Drop for AlgoHandle { fn drop(&mut self) { if !self.handle.is_null() { - unsafe { BCryptCloseAlgorithmProvider(self.handle, 0); } + unsafe { + BCryptCloseAlgorithmProvider(self.handle, 0); + } } } } @@ -86,15 +85,23 @@ pub struct WindowsString { inner: Vec, } +#[allow(dead_code)] impl WindowsString { pub fn from_str(value: &str) -> Self { - Self { inner: OsStr::new(value).encode_wide().chain(Some(0).into_iter()).collect() } + Self { + inner: OsStr::new(value) + .encode_wide() + .chain(Some(0).into_iter()) + .collect(), + } } pub fn from_ptr(ptr: *const u16) -> Self { unsafe { let len = (0..).take_while(|&i| *ptr.offset(i) != 0).count(); - Self { inner: std::slice::from_raw_parts(ptr, len).to_vec() } + Self { + inner: std::slice::from_raw_parts(ptr, len).to_vec(), + } } } @@ -107,7 +114,10 @@ impl WindowsString { } pub fn to_str(&self) -> String { - OsString::from_wide(&self.inner).to_string_lossy().as_ref().to_string() + OsString::from_wide(&self.inner) + .to_string_lossy() + .as_ref() + .to_string() } } @@ -127,4 +137,4 @@ impl WindowsString { println!("{}", name.to_str()); } } -}*/ \ No newline at end of file +}*/ diff --git a/src/lib.rs b/src/lib.rs index c06b1df..6f5957d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +use doc_comment::doctest; use winapi::shared::ntdef::NTSTATUS; use winapi::shared::ntstatus; @@ -7,6 +8,9 @@ pub mod symmetric; mod helpers; +// Compile and test the README +doctest!("../README.md"); + /// Error type /// /// These errors are a subset of [`NTSTATUS`](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55). @@ -42,4 +46,4 @@ impl Error { } } -pub type Result = std::result::Result; \ No newline at end of file +pub type Result = std::result::Result; diff --git a/src/symmetric.rs b/src/symmetric.rs index e096683..ff050c7 100644 --- a/src/symmetric.rs +++ b/src/symmetric.rs @@ -42,13 +42,13 @@ //! [`ChainingMode`]: enum.ChainingMode.html //! [`SymmetricAlgorithm.valid_key_sizes`]: struct.SymmetricAlgorithm.html#method.valid_key_sizes -use crate::{Error, Result}; use crate::buffer::Buffer; use crate::helpers::{AlgoHandle, Handle, WindowsString}; -use winapi::shared::bcrypt::*; -use winapi::shared::minwindef::{DWORD, ULONG, PUCHAR}; +use crate::{Error, Result}; use std::mem::MaybeUninit; use std::ptr::null_mut; +use winapi::shared::bcrypt::*; +use winapi::shared::minwindef::{DWORD, PUCHAR, ULONG}; /// Symmetric algorithm identifiers #[derive(Debug, Clone, Copy, PartialOrd, PartialEq)] @@ -168,7 +168,10 @@ impl SymmetricAlgorithm { let chaining_mode_str = WindowsString::from_str(chaining_mode.to_str()); handle.set_property(BCRYPT_CHAINING_MODE, chaining_mode_str.as_slice())?; - Ok(Self { handle, chaining_mode }) + Ok(Self { + handle, + chaining_mode, + }) } /// Returns the chaining mode of the algorithm. @@ -200,10 +203,16 @@ impl SymmetricAlgorithm { /// assert_eq!([128, 192, 256], valid_key_sizes.as_slice()); /// ``` pub fn valid_key_sizes(&self) -> Result> { - let key_sizes_struct = self.handle.get_property::(BCRYPT_KEY_LENGTHS)?; + let key_sizes_struct = self + .handle + .get_property::(BCRYPT_KEY_LENGTHS)?; if key_sizes_struct.dwIncrement != 0 { - Ok((key_sizes_struct.dwMinLength as usize ..= key_sizes_struct.dwMaxLength as usize).step_by(key_sizes_struct.dwIncrement as usize).collect()) + Ok( + (key_sizes_struct.dwMinLength as usize..=key_sizes_struct.dwMaxLength as usize) + .step_by(key_sizes_struct.dwIncrement as usize) + .collect(), + ) } else { Ok(vec![key_sizes_struct.dwMinLength as usize]) } @@ -222,17 +231,19 @@ impl SymmetricAlgorithm { let mut key_handle = KeyHandle::new(); let mut object = Buffer::new(object_size); unsafe { - Error::check( - BCryptGenerateSymmetricKey( - self.handle.as_ptr(), - key_handle.as_mut_ptr(), - object.as_mut_ptr(), - object.len() as ULONG, - secret.as_ptr() as PUCHAR, - secret.len() as ULONG, - 0 - ) - ).map(|_| SymmetricAlgorithmKey { handle: key_handle, _object: object }) + Error::check(BCryptGenerateSymmetricKey( + self.handle.as_ptr(), + key_handle.as_mut_ptr(), + object.as_mut_ptr(), + object.len() as ULONG, + secret.as_ptr() as PUCHAR, + secret.len() as ULONG, + 0, + )) + .map(|_| SymmetricAlgorithmKey { + handle: key_handle, + _object: object, + }) } } } @@ -250,7 +261,9 @@ impl KeyHandle { impl Drop for KeyHandle { fn drop(&mut self) { if !self.handle.is_null() { - unsafe { BCryptDestroyKey(self.handle); } + unsafe { + BCryptDestroyKey(self.handle); + } } } } @@ -285,7 +298,9 @@ impl SymmetricAlgorithmKey { /// assert_eq!(128, key_size); /// ``` pub fn key_size(&self) -> Result { - self.handle.get_property::(BCRYPT_KEY_LENGTH).map(|key_size| key_size as usize) + self.handle + .get_property::(BCRYPT_KEY_LENGTH) + .map(|key_size| key_size as usize) } /// Returns the block size in bytes. @@ -303,7 +318,9 @@ impl SymmetricAlgorithmKey { /// assert_eq!(16, key_size); /// ``` pub fn block_size(&self) -> Result { - self.handle.get_property::(BCRYPT_BLOCK_LENGTH).map(|block_size| block_size as usize) + self.handle + .get_property::(BCRYPT_BLOCK_LENGTH) + .map(|block_size| block_size as usize) } /// Encrypts data using the symmetric key @@ -341,38 +358,34 @@ impl SymmetricAlgorithmKey { let mut encrypted_len = MaybeUninit::::uninit(); unsafe { - Error::check( - BCryptEncrypt( - self.handle.as_ptr(), - data.as_ptr() as PUCHAR, - data.len() as ULONG, - null_mut(), - iv_ptr, - iv_len, - null_mut(), - 0, - encrypted_len.as_mut_ptr(), - BCRYPT_BLOCK_PADDING - ) - )?; + Error::check(BCryptEncrypt( + self.handle.as_ptr(), + data.as_ptr() as PUCHAR, + data.len() as ULONG, + null_mut(), + iv_ptr, + iv_len, + null_mut(), + 0, + encrypted_len.as_mut_ptr(), + BCRYPT_BLOCK_PADDING, + ))?; let mut output = Buffer::new(encrypted_len.assume_init() as usize); - Error::check( - BCryptEncrypt( - self.handle.as_ptr(), - data.as_ptr() as PUCHAR, - data.len() as ULONG, - null_mut(), - iv_ptr, - iv_len, - output.as_mut_ptr(), - output.len() as ULONG, - encrypted_len.as_mut_ptr(), - BCRYPT_BLOCK_PADDING - ) - ).map(|_| output) - + Error::check(BCryptEncrypt( + self.handle.as_ptr(), + data.as_ptr() as PUCHAR, + data.len() as ULONG, + null_mut(), + iv_ptr, + iv_len, + output.as_mut_ptr(), + output.len() as ULONG, + encrypted_len.as_mut_ptr(), + BCRYPT_BLOCK_PADDING, + )) + .map(|_| output) } } @@ -408,38 +421,34 @@ impl SymmetricAlgorithmKey { let mut plaintext_len = MaybeUninit::::uninit(); unsafe { - Error::check( - BCryptDecrypt( - self.handle.as_ptr(), - data.as_ptr() as PUCHAR, - data.len() as ULONG, - null_mut(), - iv_ptr, - iv_len, - null_mut(), - 0, - plaintext_len.as_mut_ptr(), - BCRYPT_BLOCK_PADDING - ) - )?; + Error::check(BCryptDecrypt( + self.handle.as_ptr(), + data.as_ptr() as PUCHAR, + data.len() as ULONG, + null_mut(), + iv_ptr, + iv_len, + null_mut(), + 0, + plaintext_len.as_mut_ptr(), + BCRYPT_BLOCK_PADDING, + ))?; let mut output = Buffer::new(plaintext_len.assume_init() as usize); - Error::check( - BCryptDecrypt( - self.handle.as_ptr(), - data.as_ptr() as PUCHAR, - data.len() as ULONG, - null_mut(), - iv_ptr, - iv_len, - output.as_mut_ptr(), - output.len() as ULONG, - plaintext_len.as_mut_ptr(), - BCRYPT_BLOCK_PADDING - ) - ).map(|_| output) - + Error::check(BCryptDecrypt( + self.handle.as_ptr(), + data.as_ptr() as PUCHAR, + data.len() as ULONG, + null_mut(), + iv_ptr, + iv_len, + output.as_mut_ptr(), + output.len() as ULONG, + plaintext_len.as_mut_ptr(), + BCRYPT_BLOCK_PADDING, + )) + .map(|_| output) } } } @@ -498,13 +507,45 @@ mod tests { check_common_chaining_modes(SymmetricAlgorithmId::TripleDes112, 16, 8); } - fn check_common_chaining_modes(algo_id: SymmetricAlgorithmId, key_size: usize, block_size: usize) { - check_encryption_decryption(algo_id, ChainingMode::Ecb, &SECRET.as_bytes()[..key_size], None, &DATA.as_bytes()[..block_size], block_size); - check_encryption_decryption(algo_id, ChainingMode::Cbc, &SECRET.as_bytes()[..key_size], Some(&IV.as_bytes()[..block_size]), &DATA.as_bytes(), block_size); - check_encryption_decryption(algo_id, ChainingMode::Cfb, &SECRET.as_bytes()[..key_size], Some(&IV.as_bytes()[..block_size]), &DATA.as_bytes(), block_size); + fn check_common_chaining_modes( + algo_id: SymmetricAlgorithmId, + key_size: usize, + block_size: usize, + ) { + check_encryption_decryption( + algo_id, + ChainingMode::Ecb, + &SECRET.as_bytes()[..key_size], + None, + &DATA.as_bytes()[..block_size], + block_size, + ); + check_encryption_decryption( + algo_id, + ChainingMode::Cbc, + &SECRET.as_bytes()[..key_size], + Some(&IV.as_bytes()[..block_size]), + &DATA.as_bytes(), + block_size, + ); + check_encryption_decryption( + algo_id, + ChainingMode::Cfb, + &SECRET.as_bytes()[..key_size], + Some(&IV.as_bytes()[..block_size]), + &DATA.as_bytes(), + block_size, + ); } - fn check_encryption_decryption(algo_id: SymmetricAlgorithmId, chaining_mode: ChainingMode, secret: &[u8], iv: Option<&[u8]>, data: &[u8], expected_block_size: usize) { + fn check_encryption_decryption( + algo_id: SymmetricAlgorithmId, + chaining_mode: ChainingMode, + secret: &[u8], + iv: Option<&[u8]>, + data: &[u8], + expected_block_size: usize, + ) { let algo = SymmetricAlgorithm::open(algo_id, chaining_mode).unwrap(); let key = algo.new_key(secret).unwrap(); let ciphertext = key.encrypt(iv, data).unwrap(); @@ -514,4 +555,4 @@ mod tests { assert_eq!(secret.len() * 8, key.key_size().unwrap()); assert_eq!(expected_block_size, key.block_size().unwrap()); } -} \ No newline at end of file +}