Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit adc46ae

Browse files
committed
Merge pull request #2673 from bartonjs/AES_Win7
Make AES work on Windows 7
2 parents bd93302 + 6c3ffe1 commit adc46ae

File tree

2 files changed

+34
-22
lines changed

2 files changed

+34
-22
lines changed

src/Common/src/Interop/Windows/BCrypt/Cng.cs

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -164,27 +164,14 @@ private struct BCRYPT_KEY_DATA_BLOB_HEADER
164164
public const UInt32 BCRYPT_KEY_DATA_BLOB_VERSION1 = 0x1;
165165
}
166166

167-
public static void SetCipherMode(this SafeKeyHandle hKey, CipherMode cipherMode)
167+
public static void SetCipherMode(this SafeAlgorithmHandle hAlg, string cipherMode)
168168
{
169-
String cipherModePropertyName;
170-
switch (cipherMode)
171-
{
172-
case CipherMode.CBC:
173-
cipherModePropertyName = "ChainingModeCBC";
174-
break;
175-
case CipherMode.CTS:
176-
throw new NotSupportedException();
177-
case CipherMode.ECB:
178-
cipherModePropertyName = "ChainingModeECB";
179-
break;
180-
181-
default:
182-
throw new NotSupportedException();
183-
}
184-
NTSTATUS ntStatus = Interop.BCryptSetProperty(hKey, "ChainingMode", cipherModePropertyName, (cipherModePropertyName.Length + 1) * 2, 0);
169+
NTSTATUS ntStatus = Interop.BCryptSetProperty(hAlg, "ChainingMode", cipherMode, (cipherMode.Length + 1) * 2, 0);
170+
185171
if (ntStatus != NTSTATUS.STATUS_SUCCESS)
172+
{
186173
throw CreateCryptographicException(ntStatus);
187-
return;
174+
}
188175
}
189176

190177
// Note: input and output are allowed to be the same buffer. BCryptEncrypt will correctly do the encryption in place according to CNG documentation.
@@ -300,7 +287,7 @@ private static class Interop
300287
public static extern unsafe NTSTATUS BCryptGetProperty(SafeBCryptHandle hObject, String pszProperty, byte* pbOutput, int cbOutput, out int pcbResult, int dwFlags);
301288

302289
[DllImport(CngDll, CharSet = CharSet.Unicode)]
303-
public static extern unsafe NTSTATUS BCryptSetProperty(SafeBCryptHandle hObject, String pszProperty, String pbInput, int cbInput, int dwFlags);
290+
public static extern unsafe NTSTATUS BCryptSetProperty(SafeAlgorithmHandle hObject, String pszProperty, String pbInput, int cbInput, int dwFlags);
304291

305292
[DllImport(CngDll, CharSet = CharSet.Unicode)]
306293
public static extern NTSTATUS BCryptImportKey(SafeAlgorithmHandle hAlgorithm, IntPtr hImportKey, String pszBlobType, out SafeKeyHandle hKey, IntPtr pbKeyObject, int cbKeyObject, byte[] pbInput, int cbInput, int dwFlags);

src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/AesCngCryptoTransform.cs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ protected AesCngCryptoTransform(CipherMode cipherMode, PaddingMode paddingMode,
2020
_iv = cipherIv.CloneByteArray();
2121
_currentIv = new byte[cipherIv.Length];
2222
}
23-
_hKey = s_hAlg.BCryptImportKey(key);
24-
_hKey.SetCipherMode(cipherMode);
23+
24+
SafeAlgorithmHandle hAlg = GetCipherAlgorithm(cipherMode);
25+
_hKey = hAlg.BCryptImportKey(key);
2526
Reset();
2627
}
2728

@@ -72,6 +73,29 @@ protected override void Reset()
7273
}
7374
}
7475

76+
private static SafeAlgorithmHandle GetCipherAlgorithm(CipherMode cipherMode)
77+
{
78+
// Windows 8 added support to set the CipherMode value on a key,
79+
// but Windows 7 requires that it be set on the algorithm before key creation.
80+
switch (cipherMode)
81+
{
82+
case CipherMode.CBC:
83+
return s_hAlgCbc;
84+
case CipherMode.ECB:
85+
return s_hAlgEcb;
86+
default:
87+
throw new NotSupportedException();
88+
}
89+
}
90+
91+
private static SafeAlgorithmHandle OpenAesAlgorithm(string cipherMode)
92+
{
93+
SafeAlgorithmHandle hAlg = Cng.BCryptOpenAlgorithmProvider(Cng.BCRYPT_AES_ALGORITHM, null, Cng.OpenAlgorithmProviderFlags.NONE);
94+
hAlg.SetCipherMode(cipherMode);
95+
96+
return hAlg;
97+
}
98+
7599
protected abstract int UncheckedTransformBlock(SafeKeyHandle hKey, byte[] currentIv, byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
76100

77101
protected abstract byte[] UncheckedTransformFinalBlock(SafeKeyHandle hKey, byte[] currentIv, byte[] inputBuffer, int inputOffset, int inputCount);
@@ -80,6 +104,7 @@ protected override void Reset()
80104
private byte[] _iv; // _iv holds a copy of the original IV for Reset(), until it is cleared by Dispose().
81105
private byte[] _currentIv; // CNG mutates this with the updated IV for the next stage on each Encrypt/Decrypt call.
82106

83-
private static readonly SafeAlgorithmHandle s_hAlg = Cng.BCryptOpenAlgorithmProvider(Cng.BCRYPT_AES_ALGORITHM, null, Cng.OpenAlgorithmProviderFlags.NONE);
107+
private static readonly SafeAlgorithmHandle s_hAlgCbc = OpenAesAlgorithm("ChainingModeCBC");
108+
private static readonly SafeAlgorithmHandle s_hAlgEcb = OpenAesAlgorithm("ChainingModeECB");
84109
}
85110
}

0 commit comments

Comments
 (0)