From 73d48d25f3cb9b4829874bea2eace55526c18757 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Fri, 26 Jun 2026 21:58:05 -0400 Subject: [PATCH] Improve AES-KWP for Windows --- .../src/System/Security/Cryptography/Aes.cs | 14 ++---- .../Cryptography/AesImplementation.Windows.cs | 49 +++++++++++++++++++ 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Aes.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Aes.cs index 2f07e043fa6a3d..45436e08e799d2 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Aes.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Aes.cs @@ -365,7 +365,7 @@ private protected int DecryptKeyWrapPaddedCore( ReadOnlySpan source, Span destination, TState state, - KeyWrapEcbTransform decryptEcb) + Func, Span, int> decryptEcb) { ulong iv; @@ -429,17 +429,11 @@ protected virtual unsafe void EncryptKeyWrapPaddedCore(ReadOnlySpan source this, static (instance, source, destination) => instance.EncryptEcb(source, destination, PaddingMode.None)); } - - private protected delegate int KeyWrapEcbTransform( - TState state, - ReadOnlySpan source, - Span destination); - private protected void EncryptKeyWrapPaddedCore( ReadOnlySpan source, Span destination, TState state, - KeyWrapEcbTransform encryptEcb) + Func, Span, int> encryptEcb) { Debug.Assert(destination.Length == GetKeyWrapPaddedLength(source.Length)); @@ -491,7 +485,7 @@ private void Rfc3394Wrap( ReadOnlySpan source, Span destination, TState state, - KeyWrapEcbTransform encryptEcb) + Func, Span, int> encryptEcb) { Debug.Assert(source.Length % 8 == 0); Debug.Assert(source.Length >= 16); @@ -530,7 +524,7 @@ private ulong Rfc3394Unwrap( ReadOnlySpan source, Span destination, TState state, - KeyWrapEcbTransform decryptEcb) + Func, Span, int> decryptEcb) { Span B = stackalloc byte[16]; Span A = B.Slice(0, 8); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.Windows.cs index 77dc9472650892..2e2cd0e646f7c7 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/AesImplementation.Windows.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using Internal.Cryptography; using Internal.NativeCrypto; @@ -44,5 +45,53 @@ private static BasicSymmetricCipherLiteBCrypt CreateLiteCipher( iv, encrypting); } + + protected override void EncryptKeyWrapPaddedCore(ReadOnlySpan source, Span destination) + { + Debug.Assert(destination.Length == GetKeyWrapPaddedLength(source.Length)); + + ILiteSymmetricCipher cipher = GetKey().UseKey( + BlockSize / BitsPerByte, + static (blockSizeBytes, key) => CreateLiteCipher( + CipherMode.ECB, + key, + iv: default, + blockSize: blockSizeBytes, + paddingSize: blockSizeBytes, + feedbackSize: 0, + encrypting: true)); + + using (cipher) + { + EncryptKeyWrapPaddedCore( + source, + destination, + cipher, + static (cipher, source, destination) => cipher.Transform(source, destination)); + } + } + + protected override int DecryptKeyWrapPaddedCore(ReadOnlySpan source, Span destination) + { + ILiteSymmetricCipher cipher = GetKey().UseKey( + BlockSize / BitsPerByte, + static (blockSizeBytes, key) => CreateLiteCipher( + CipherMode.ECB, + key, + iv: default, + blockSize: blockSizeBytes, + paddingSize: blockSizeBytes, + feedbackSize: 0, + encrypting: false)); + + using (cipher) + { + return DecryptKeyWrapPaddedCore( + source, + destination, + cipher, + static (cipher, source, destination) => cipher.Transform(source, destination)); + } + } } }