Imported Upstream version 5.10.0.47

Former-commit-id: d0813289fa2d35e1f8ed77530acb4fb1df441bc0
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-01-24 17:04:36 +00:00
parent 88ff76fe28
commit e46a49ecf1
5927 changed files with 226314 additions and 129848 deletions

View File

@@ -1182,6 +1182,7 @@ namespace System.IO.Pipes {
// our WaitNamedPipe and CreateFile calls.
int startTime = Environment.TickCount;
int elapsed = 0;
var sw = new SpinWait();
do {
// Wait for pipe to become free (this will block unless the pipe does not exist).
if (!UnsafeNativeMethods.WaitNamedPipe(m_normalizedPipePath, timeout - elapsed)) {
@@ -1189,6 +1190,7 @@ namespace System.IO.Pipes {
// Server is not yet created so let's keep looping.
if (errorCode == UnsafeNativeMethods.ERROR_FILE_NOT_FOUND) {
sw.SpinOnce();
continue;
}
@@ -1215,6 +1217,7 @@ namespace System.IO.Pipes {
// Handle the possible race condition of someone else connecting to the server
// between our calls to WaitNamedPipe & CreateFile.
if (errorCode == UnsafeNativeMethods.ERROR_PIPE_BUSY) {
sw.SpinOnce();
continue;
}
@@ -1284,6 +1287,7 @@ namespace System.IO.Pipes {
// straight away in such cases), and 2) when another client connects to our server in between
// our WaitNamedPipe and CreateFile calls.
int elapsed = 0;
var sw = new SpinWait();
do {
// We want any other exception and and success to have priority over cancellation.
cancellationToken.ThrowIfCancellationRequested();
@@ -1303,6 +1307,7 @@ namespace System.IO.Pipes {
// Server is not yet created so let's keep looping.
if (errorCode == UnsafeNativeMethods.ERROR_FILE_NOT_FOUND) {
sw.SpinOnce();
continue;
}
@@ -1311,6 +1316,7 @@ namespace System.IO.Pipes {
if (cancellationToken.CanBeCanceled) {
// It may not be real timeout and only checking for cancellation
// let the while condition check it and decide
sw.SpinOnce();
continue;
}
else {
@@ -1336,6 +1342,7 @@ namespace System.IO.Pipes {
// Handle the possible race condition of someone else connecting to the server
// between our calls to WaitNamedPipe & CreateFile.
if (errorCode == UnsafeNativeMethods.ERROR_PIPE_BUSY) {
sw.SpinOnce();
continue;
}

View File

@@ -1 +1 @@
aef6a32d8ec54693b7c067fa73fbe8a7bc2d7a63
84a0435571889ce58bd34856be36335002eb5e30

View File

@@ -173,6 +173,17 @@ namespace System.Security.Cryptography {
internal int cbSalt;
}
[StructLayout(LayoutKind.Sequential)]
private struct BCRYPT_KEY_DATA_BLOB_HEADER
{
public uint dwMagic;
public uint dwVersion;
public uint cbKeyData;
public const uint BCRYPT_KEY_DATA_BLOB_MAGIC = 0x4d42444b;
public const uint BCRYPT_KEY_DATA_BLOB_VERSION1 = 0x1;
}
/// <summary>
/// Well known KDF names
/// </summary>
@@ -295,6 +306,120 @@ namespace System.Security.Cryptography {
[In] int dwFlags,
[In] IntPtr pvAuxInfo,
[Out] out SafeBCryptKeyHandle phKey);
[DllImport("bcrypt.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern ErrorCode BCryptImportKey(
SafeBCryptAlgorithmHandle hAlgorithm,
IntPtr hImportKey,
string pszBlobType,
out SafeBCryptKeyHandle hKey,
IntPtr pbKeyObject,
int cbKeyObject,
byte[] pbInput,
int cbInput,
int dwFlags);
[DllImport("bcrypt.dll", SetLastError = true)]
public static extern unsafe ErrorCode BCryptEncrypt(
SafeBCryptKeyHandle hKey,
byte* pbInput,
int cbInput,
IntPtr paddingInfo,
[In, Out] byte[] pbIV,
int cbIV,
byte* pbOutput,
int cbOutput,
out int cbResult,
int dwFlags);
[DllImport("bcrypt.dll", SetLastError = true)]
public static extern unsafe ErrorCode BCryptDecrypt(
SafeBCryptKeyHandle hKey,
byte* pbInput,
int cbInput,
IntPtr paddingInfo,
[In, Out] byte[] pbIV,
int cbIV,
byte* pbOutput,
int cbOutput,
out int cbResult,
int dwFlags);
[DllImport("bcrypt.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern ErrorCode BCryptSetProperty(
SafeBCryptAlgorithmHandle hObject,
string pszProperty,
string pbInput,
int cbInput,
int dwFlags);
}
[SecuritySafeCritical]
internal static class AesBCryptModes
{
[SecurityCritical]
private static readonly SafeBCryptAlgorithmHandle s_hAlgCbc = OpenAesAlgorithm(Interop.BCrypt.BCRYPT_CHAIN_MODE_CBC);
[SecurityCritical]
private static readonly SafeBCryptAlgorithmHandle s_hAlgEcb = OpenAesAlgorithm(Interop.BCrypt.BCRYPT_CHAIN_MODE_ECB);
internal static SafeBCryptAlgorithmHandle GetSharedHandle(CipherMode cipherMode)
{
// Windows 8 added support to set the CipherMode value on a key,
// but Windows 7 requires that it be set on the algorithm before key creation.
switch (cipherMode)
{
case CipherMode.CBC:
return s_hAlgCbc;
case CipherMode.ECB:
return s_hAlgEcb;
default:
throw new NotSupportedException();
}
}
private static SafeBCryptAlgorithmHandle OpenAesAlgorithm(string cipherMode)
{
const string BCRYPT_AES_ALGORITHM = "AES";
SafeBCryptAlgorithmHandle hAlg = OpenAlgorithm(BCRYPT_AES_ALGORITHM, null);
SetCipherMode(hAlg, cipherMode);
return hAlg;
}
}
[SecuritySafeCritical]
internal static class TripleDesBCryptModes
{
[SecurityCritical]
private static readonly SafeBCryptAlgorithmHandle s_hAlgCbc = OpenAesAlgorithm(Interop.BCrypt.BCRYPT_CHAIN_MODE_CBC);
[SecurityCritical]
private static readonly SafeBCryptAlgorithmHandle s_hAlgEcb = OpenAesAlgorithm(Interop.BCrypt.BCRYPT_CHAIN_MODE_ECB);
internal static SafeBCryptAlgorithmHandle GetSharedHandle(CipherMode cipherMode)
{
// Windows 8 added support to set the CipherMode value on a key,
// but Windows 7 requires that it be set on the algorithm before key creation.
switch (cipherMode)
{
case CipherMode.CBC:
return s_hAlgCbc;
case CipherMode.ECB:
return s_hAlgEcb;
default:
throw new NotSupportedException();
}
}
private static SafeBCryptAlgorithmHandle OpenAesAlgorithm(string cipherMode)
{
const string BCRYPT_3DES_ALGORITHM = "3DES";
SafeBCryptAlgorithmHandle hAlg = OpenAlgorithm(BCRYPT_3DES_ALGORITHM, null);
SetCipherMode(hAlg, cipherMode);
return hAlg;
}
}
//
@@ -493,6 +618,163 @@ namespace System.Security.Cryptography {
}
return keyBlob;
}
[SecuritySafeCritical]
internal static SafeBCryptKeyHandle BCryptImportKey(SafeBCryptAlgorithmHandle hAlg, byte[] key)
{
unsafe
{
const String BCRYPT_KEY_DATA_BLOB = "KeyDataBlob";
int keySize = key.Length;
int blobSize = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) keySize;
byte[] blob = new byte[blobSize];
fixed (byte* pbBlob = blob)
{
BCRYPT_KEY_DATA_BLOB_HEADER* pBlob = (BCRYPT_KEY_DATA_BLOB_HEADER*)pbBlob;
pBlob->dwMagic = BCRYPT_KEY_DATA_BLOB_HEADER.BCRYPT_KEY_DATA_BLOB_MAGIC;
pBlob->dwVersion = BCRYPT_KEY_DATA_BLOB_HEADER.BCRYPT_KEY_DATA_BLOB_VERSION1;
pBlob->cbKeyData = (uint)keySize;
}
Buffer.BlockCopy(key, 0, blob, sizeof(BCRYPT_KEY_DATA_BLOB_HEADER), keySize);
SafeBCryptKeyHandle hKey;
ErrorCode error = UnsafeNativeMethods.BCryptImportKey(
hAlg,
IntPtr.Zero,
BCRYPT_KEY_DATA_BLOB,
out hKey,
IntPtr.Zero,
0,
blob,
blobSize,
0);
if (error != ErrorCode.Success)
throw new CryptographicException((int)error);
return hKey;
}
}
// Note: input and output are allowed to be the same buffer.
// BCryptEncrypt will correctly do the encryption in place according to CNG documentation.
[SecuritySafeCritical]
public static int BCryptEncrypt(
SafeBCryptKeyHandle hKey,
byte[] input,
int inputOffset,
int inputCount,
byte[] iv,
byte[] output,
int outputOffset,
int outputCount)
{
Debug.Assert(input != null);
Debug.Assert(inputOffset >= 0);
Debug.Assert(inputCount >= 0);
Debug.Assert(inputCount <= input.Length - inputOffset);
Debug.Assert(output != null);
Debug.Assert(outputOffset >= 0);
Debug.Assert(outputCount >= 0);
Debug.Assert(outputCount <= output.Length - outputOffset);
unsafe
{
fixed (byte* pbInput = input)
{
fixed (byte* pbOutput = output)
{
int cbResult;
ErrorCode error = UnsafeNativeMethods.BCryptEncrypt(
hKey,
pbInput inputOffset,
inputCount,
IntPtr.Zero,
iv,
iv == null ? 0 : iv.Length,
pbOutput outputOffset,
outputCount,
out cbResult,
0);
if (error != ErrorCode.Success)
throw new CryptographicException((int)error);
return cbResult;
}
}
}
}
// Note: input and output are allowed to be the same buffer.
// BCryptDecrypt will correctly do the decryption in place according to CNG documentation.
[SecuritySafeCritical]
public static int BCryptDecrypt(
SafeBCryptKeyHandle hKey,
byte[] input,
int inputOffset,
int inputCount,
byte[] iv,
byte[] output,
int outputOffset,
int outputCount)
{
Debug.Assert(input != null);
Debug.Assert(inputOffset >= 0);
Debug.Assert(inputCount >= 0);
Debug.Assert(inputCount <= input.Length - inputOffset);
Debug.Assert(output != null);
Debug.Assert(outputOffset >= 0);
Debug.Assert(outputCount >= 0);
Debug.Assert(outputCount <= output.Length - outputOffset);
unsafe
{
fixed (byte* pbInput = input)
{
fixed (byte* pbOutput = output)
{
int cbResult;
ErrorCode error = UnsafeNativeMethods.BCryptDecrypt(
hKey,
pbInput inputOffset,
inputCount,
IntPtr.Zero,
iv,
iv == null ? 0 : iv.Length,
pbOutput outputOffset,
outputCount,
out cbResult,
0);
if (error != ErrorCode.Success)
throw new CryptographicException((int)error);
return cbResult;
}
}
}
}
[SecurityCritical]
public static void SetCipherMode(SafeBCryptAlgorithmHandle hAlg, string cipherMode)
{
const string BCRYPT_CHAINING_MODE = "ChainingMode";
ErrorCode error = UnsafeNativeMethods.BCryptSetProperty(
hAlg,
BCRYPT_CHAINING_MODE,
cipherMode,
// Explicit \0 terminator, UCS-2
(cipherMode.Length 1) * 2,
0);
if (error != ErrorCode.Success)
{
throw new CryptographicException((int)error);
}
}
#endif
}
}

View File

@@ -976,7 +976,8 @@ namespace System.Security.Cryptography {
: base(true) {
}
[DllImport("kernel32.dll")]
[DllImport("kernel32.dll"), SuppressUnmanagedCodeSecurity]
[SecurityCritical]
private static extern IntPtr LocalFree(IntPtr hMem);
[SecuritySafeCritical]

View File

@@ -87,6 +87,7 @@ namespace System.Security.Cryptography
/// <exception cref="ArgumentException">if <paramref name="key" /> is not an RSA key</exception>
/// <exception cref="ArgumentNullException">if <paramref name="key" /> is null.</exception>
[SecuritySafeCritical]
[SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)]
public RSACng(CngKey key)
{
if (key == null)
@@ -115,6 +116,7 @@ namespace System.Security.Cryptography
public CngKey Key
{
[SecuritySafeCritical]
[SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)]
get
{
// If our key size was changed from the key we're using, we need to generate a new key
@@ -133,15 +135,15 @@ namespace System.Security.Cryptography
};
CngProperty keySizeProperty = new CngProperty(NCryptNative.KeyPropertyName.Length,
BitConverter.GetBytes(KeySize),
CngPropertyOptions.None);
BitConverter.GetBytes(KeySize),
CngPropertyOptions.None);
creationParameters.Parameters.Add(keySizeProperty);
_key = CngKey.Create(CngAlgorithm.Rsa, null, creationParameters);
}
return _key;
}
private set
{
Debug.Assert(value != null, "value != null");
@@ -181,6 +183,7 @@ namespace System.Security.Cryptography
private SafeNCryptKeyHandle KeyHandle
{
[SecuritySafeCritical]
[SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)]
get { return Key.Handle; }
}
@@ -442,7 +445,7 @@ namespace System.Security.Cryptography
throw new ArgumentNullException("padding");
}
SafeNCryptKeyHandle keyHandle = Key.Handle;
SafeNCryptKeyHandle keyHandle = KeyHandle;
if (padding == RSAEncryptionPadding.Pkcs1)
{
@@ -492,6 +495,7 @@ namespace System.Security.Cryptography
//
[SecuritySafeCritical]
[SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)]
public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
{
if (hash == null)

View File

@@ -412,7 +412,7 @@ namespace System.Threading
continue; // since we left the lock, start over.
}
retVal = WaitOnEvent(readEvent, ref numReadWaiters, timeout);
retVal = WaitOnEvent(readEvent, ref numReadWaiters, timeout, isWriteWaiter: false);
if (!retVal)
{
return false;
@@ -586,7 +586,7 @@ namespace System.Threading
Debug.Assert(numWriteUpgradeWaiters == 0, "There can be at most one thread with the upgrade lock held.");
retVal = WaitOnEvent(waitUpgradeEvent, ref numWriteUpgradeWaiters, timeout);
retVal = WaitOnEvent(waitUpgradeEvent, ref numWriteUpgradeWaiters, timeout, isWriteWaiter: true);
//The lock is not held in case of failure.
if (!retVal)
@@ -601,7 +601,7 @@ namespace System.Threading
continue; // since we left the lock, start over.
}
retVal = WaitOnEvent(writeEvent, ref numWriteWaiters, timeout);
retVal = WaitOnEvent(writeEvent, ref numWriteWaiters, timeout, isWriteWaiter: true);
//The lock is not held in case of failure.
if (!retVal)
return false;
@@ -757,7 +757,7 @@ namespace System.Threading
}
//Only one thread with the upgrade lock held can proceed.
retVal = WaitOnEvent(upgradeEvent, ref numUpgradeWaiters, timeout);
retVal = WaitOnEvent(upgradeEvent, ref numUpgradeWaiters, timeout, isWriteWaiter: false);
if (!retVal)
return false;
}
@@ -956,7 +956,11 @@ namespace System.Threading
/// Waits on 'waitEvent' with a timeout
/// Before the wait 'numWaiters' is incremented and is restored before leaving this routine.
/// </summary>
private bool WaitOnEvent(EventWaitHandle waitEvent, ref uint numWaiters, TimeoutTracker timeout)
private bool WaitOnEvent(
EventWaitHandle waitEvent,
ref uint numWaiters,
TimeoutTracker timeout,
bool isWriteWaiter)
{
#if DEBUG
Debug.Assert(MyLockHeld);
@@ -991,8 +995,17 @@ namespace System.Threading
if (numWriteUpgradeWaiters == 0)
ClearUpgraderWaiting();
if (!waitSuccessful) // We may also be aboutto throw for some reason. Exit myLock.
ExitMyLock();
if (!waitSuccessful) // We may also be about to throw for some reason. Exit myLock.
{
if (isWriteWaiter)
{
// Write waiters block read waiters from acquiring the lock. Since this was the last write waiter, try
// to wake up the appropriate read waiters.
ExitAndWakeUpAppropriateReadWaiters();
}
else
ExitMyLock();
}
}
return waitSuccessful;
}
@@ -1016,8 +1029,6 @@ namespace System.Threading
private void ExitAndWakeUpAppropriateWaitersPreferringWriters()
{
bool setUpgradeEvent = false;
bool setReadEvent = false;
uint readercount = GetNumReaders();
//We need this case for EU->ER->EW case, as the read count will be 2 in
@@ -1046,31 +1057,36 @@ namespace System.Threading
ExitMyLock(); // Exit before signaling to improve efficiency (wakee will need the lock)
writeEvent.Set(); // release one writer.
}
else if (readercount >= 0)
{
if (numReadWaiters != 0 || numUpgradeWaiters != 0)
{
if (numReadWaiters != 0)
setReadEvent = true;
if (numUpgradeWaiters != 0 && upgradeLockOwnerId == -1)
{
setUpgradeEvent = true;
}
ExitMyLock(); // Exit before signaling to improve efficiency (wakee will need the lock)
if (setReadEvent)
readEvent.Set(); // release all readers.
if (setUpgradeEvent)
upgradeEvent.Set(); //release one upgrader.
}
else
ExitMyLock();
}
else
{
ExitAndWakeUpAppropriateReadWaiters();
}
}
private void ExitAndWakeUpAppropriateReadWaiters()
{
#if DEBUG
Debug.Assert(MyLockHeld);
#endif
if (numWriteWaiters != 0 || numWriteUpgradeWaiters != 0 || fNoWaiters)
{
ExitMyLock();
return;
}
Debug.Assert(numReadWaiters != 0 || numUpgradeWaiters != 0);
bool setReadEvent = numReadWaiters != 0;
bool setUpgradeEvent = numUpgradeWaiters != 0 && upgradeLockOwnerId == -1;
ExitMyLock(); // Exit before signaling to improve efficiency (wakee will need the lock)
if (setReadEvent)
readEvent.Set(); // release all readers.
if (setUpgradeEvent)
upgradeEvent.Set(); //release one upgrader.
}
private bool IsWriterAcquired()