From 3e2d4eec6959fdda99c1351505cc7fcc7ba541c5 Mon Sep 17 00:00:00 2001 From: Steven Malis Date: Thu, 21 May 2026 19:48:19 -0400 Subject: [PATCH] crypto: Add symcrypt backends for aes-kwp and xts-aes. --- Cargo.lock | 4 +- support/crypto/src/aes_kwp/mod.rs | 7 ++- support/crypto/src/aes_kwp/symcrypt.rs | 65 ++++++++++++++++++++++ support/crypto/src/xts_aes_256/mod.rs | 7 ++- support/crypto/src/xts_aes_256/symcrypt.rs | 61 ++++++++++++++++++++ 5 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 support/crypto/src/aes_kwp/symcrypt.rs create mode 100644 support/crypto/src/xts_aes_256/symcrypt.rs diff --git a/Cargo.lock b/Cargo.lock index f061cf32e0..70900d6dda 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7651,7 +7651,7 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "symcrypt" version = "0.6.0" -source = "git+https://github.com/microsoft/rust-symcrypt.git?branch=release%2F0.6.0#050dc7e0e3741e226d0de250b36c15e51524e815" +source = "git+https://github.com/microsoft/rust-symcrypt.git?branch=release%2F0.6.0#b76fde36469a0571a7253b8875597c1973f0bddc" dependencies = [ "libc", "symcrypt-sys", @@ -7660,7 +7660,7 @@ dependencies = [ [[package]] name = "symcrypt-sys" version = "0.4.0" -source = "git+https://github.com/microsoft/rust-symcrypt.git?branch=release%2F0.6.0#050dc7e0e3741e226d0de250b36c15e51524e815" +source = "git+https://github.com/microsoft/rust-symcrypt.git?branch=release%2F0.6.0#b76fde36469a0571a7253b8875597c1973f0bddc" dependencies = [ "libc", ] diff --git a/support/crypto/src/aes_kwp/mod.rs b/support/crypto/src/aes_kwp/mod.rs index 88f7813662..5dc3908d0a 100644 --- a/support/crypto/src/aes_kwp/mod.rs +++ b/support/crypto/src/aes_kwp/mod.rs @@ -3,7 +3,7 @@ //! AES key wrap with padding (RFC 5649). -#![cfg(any(openssl, rust))] +#![cfg(any(openssl, rust, symcrypt))] #[cfg(openssl)] mod ossl; @@ -15,6 +15,11 @@ mod rust; #[cfg(rust)] use rust as sys; +#[cfg(symcrypt)] +mod symcrypt; +#[cfg(symcrypt)] +use symcrypt as sys; + use thiserror::Error; /// An error for AES key wrap operations. diff --git a/support/crypto/src/aes_kwp/symcrypt.rs b/support/crypto/src/aes_kwp/symcrypt.rs new file mode 100644 index 0000000000..dc48accd91 --- /dev/null +++ b/support/crypto/src/aes_kwp/symcrypt.rs @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +//! AES key wrap with padding (RFC 5649) implementation using SymCrypt. + +use super::AesKeyWrapError; +use super::AesKeyWrapErrorInner; +use symcrypt::cipher::aes_kw::AesKwpKey; + +fn err(e: symcrypt::errors::SymCryptError, op: &'static str) -> AesKeyWrapError { + AesKeyWrapError(AesKeyWrapErrorInner::Backend( + crate::BackendError::SymCrypt(e, op), + )) +} + +pub struct AesKeyWrapInner { + key: AesKwpKey, +} + +pub struct AesKeyWrapCtxInner<'a> { + key: &'a AesKwpKey, +} + +pub struct AesKeyUnwrapCtxInner<'a> { + key: &'a AesKwpKey, +} + +impl AesKeyWrapInner { + pub fn new(key: &[u8]) -> Result { + match key.len() { + 16 | 24 | 32 => {} + key_size => { + return Err(AesKeyWrapError(AesKeyWrapErrorInner::InvalidKeySize( + key_size, + ))); + } + } + let key = AesKwpKey::new(key).map_err(|e| err(e, "expanding kwp key"))?; + Ok(AesKeyWrapInner { key }) + } + + pub fn wrap_ctx(&self) -> Result, AesKeyWrapError> { + Ok(AesKeyWrapCtxInner { key: &self.key }) + } + + pub fn unwrap_ctx(&self) -> Result, AesKeyWrapError> { + Ok(AesKeyUnwrapCtxInner { key: &self.key }) + } +} + +impl AesKeyWrapCtxInner<'_> { + pub fn wrap(&mut self, payload: &[u8]) -> Result, AesKeyWrapError> { + self.key + .encrypt(payload) + .map_err(|e| err(e, "wrapping key")) + } +} + +impl AesKeyUnwrapCtxInner<'_> { + pub fn unwrap(&mut self, wrapped_payload: &[u8]) -> Result, AesKeyWrapError> { + self.key + .decrypt(wrapped_payload) + .map_err(|e| err(e, "unwrapping key")) + } +} diff --git a/support/crypto/src/xts_aes_256/mod.rs b/support/crypto/src/xts_aes_256/mod.rs index fcaca1db16..7ba75b0b11 100644 --- a/support/crypto/src/xts_aes_256/mod.rs +++ b/support/crypto/src/xts_aes_256/mod.rs @@ -3,7 +3,7 @@ //! XTS-AES-256 encryption and decryption. -#![cfg(any(openssl, all(native, windows)))] +#![cfg(any(openssl, symcrypt, all(native, windows)))] #[cfg(openssl)] mod ossl; @@ -15,6 +15,11 @@ mod win; #[cfg(all(native, windows))] use win as sys; +#[cfg(symcrypt)] +mod symcrypt; +#[cfg(symcrypt)] +use symcrypt as sys; + use thiserror::Error; /// The required key length for the algorithm. diff --git a/support/crypto/src/xts_aes_256/symcrypt.rs b/support/crypto/src/xts_aes_256/symcrypt.rs new file mode 100644 index 0000000000..1ff9be064d --- /dev/null +++ b/support/crypto/src/xts_aes_256/symcrypt.rs @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +//! XTS-AES-256 implementation using SymCrypt. + +use super::KEY_LEN; +use super::XtsAes256Error; +use symcrypt::cipher::xts::XtsAesKey; + +pub struct XtsAes256Inner { + key: XtsAesKey, + data_unit_size: u32, +} + +pub struct XtsAes256EncCtxInner<'a> { + inner: &'a XtsAes256Inner, +} + +pub struct XtsAes256DecCtxInner<'a> { + inner: &'a XtsAes256Inner, +} + +fn err(e: symcrypt::errors::SymCryptError, op: &'static str) -> XtsAes256Error { + XtsAes256Error(crate::BackendError::SymCrypt(e, op)) +} + +impl XtsAes256Inner { + pub fn new(key: &[u8; KEY_LEN], data_unit_size: u32) -> Result { + let key = XtsAesKey::new(key).map_err(|e| err(e, "expanding xts key"))?; + Ok(Self { + key, + data_unit_size, + }) + } + + pub fn enc_ctx(&self) -> Result, XtsAes256Error> { + Ok(XtsAes256EncCtxInner { inner: self }) + } + + pub fn dec_ctx(&self) -> Result, XtsAes256Error> { + Ok(XtsAes256DecCtxInner { inner: self }) + } +} + +impl XtsAes256EncCtxInner<'_> { + pub fn cipher(&mut self, tweak: u64, data: &mut [u8]) -> Result<(), XtsAes256Error> { + self.inner + .key + .encrypt_in_place(self.inner.data_unit_size as u64, tweak, data) + .map_err(|e| err(e, "xts encrypt")) + } +} + +impl XtsAes256DecCtxInner<'_> { + pub fn cipher(&mut self, tweak: u64, data: &mut [u8]) -> Result<(), XtsAes256Error> { + self.inner + .key + .decrypt_in_place(self.inner.data_unit_size as u64, tweak, data) + .map_err(|e| err(e, "xts decrypt")) + } +}