You've already forked linux-packaging-mono
Imported Upstream version 5.0.0.42
Former-commit-id: fd56571888259555122d8a0f58c68838229cea2b
This commit is contained in:
parent
1190d13a04
commit
6bdd276d05
40
external/corefx/src/Common/Common.Tests.sln
vendored
Normal file
40
external/corefx/src/Common/Common.Tests.sln
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.23107.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Tests", "tests\Common.Tests.csproj", "{C72FD34C-539A-4447-9796-62A229571199}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
FreeBSD_Debug|Any CPU = FreeBSD_Debug|Any CPU
|
||||
FreeBSD_Release|Any CPU = FreeBSD_Release|Any CPU
|
||||
Linux_Debug|Any CPU = Linux_Debug|Any CPU
|
||||
Linux_Release|Any CPU = Linux_Release|Any CPU
|
||||
OSX_Debug|Any CPU = OSX_Debug|Any CPU
|
||||
OSX_Release|Any CPU = OSX_Release|Any CPU
|
||||
Windows_Debug|Any CPU = Windows_Debug|Any CPU
|
||||
Windows_Release|Any CPU = Windows_Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.FreeBSD_Debug|Any CPU.ActiveCfg = FreeBSD_Debug|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.FreeBSD_Debug|Any CPU.Build.0 = FreeBSD_Debug|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.FreeBSD_Release|Any CPU.ActiveCfg = FreeBSD_Release|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.FreeBSD_Release|Any CPU.Build.0 = FreeBSD_Release|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.Linux_Debug|Any CPU.ActiveCfg = Linux_Debug|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.Linux_Debug|Any CPU.Build.0 = Linux_Debug|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.Linux_Release|Any CPU.ActiveCfg = Linux_Release|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.Linux_Release|Any CPU.Build.0 = Linux_Release|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.OSX_Debug|Any CPU.ActiveCfg = OSX_Debug|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.OSX_Debug|Any CPU.Build.0 = OSX_Debug|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.OSX_Release|Any CPU.ActiveCfg = OSX_Release|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.OSX_Release|Any CPU.Build.0 = OSX_Release|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.Windows_Debug|Any CPU.ActiveCfg = Windows_Debug|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.Windows_Debug|Any CPU.Build.0 = Windows_Debug|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.Windows_Release|Any CPU.ActiveCfg = Windows_Release|Any CPU
|
||||
{C72FD34C-539A-4447-9796-62A229571199}.Windows_Release|Any CPU.Build.0 = Windows_Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
28
external/corefx/src/Common/perf/project.json
vendored
Normal file
28
external/corefx/src/Common/perf/project.json
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"Microsoft.DotNet.xunit.performance.analysis": "1.0.0-alpha-build0040",
|
||||
"Microsoft.DotNet.xunit.performance.analysis.cli": "1.0.0-alpha-build0040",
|
||||
"Microsoft.DotNet.xunit.performance.runner.cli": "1.0.0-alpha-build0040",
|
||||
"Microsoft.DotNet.xunit.performance.runner.Windows": "1.0.0-alpha-build0040"
|
||||
},
|
||||
"frameworks": {
|
||||
"netstandard1.3": {}
|
||||
},
|
||||
"supports": {
|
||||
"coreFx.Test.netcoreapp1.0": {
|
||||
"netcoreapp1.0": [
|
||||
"win7-x86",
|
||||
"win7-x64",
|
||||
"osx.10.10-x64",
|
||||
"centos.7-x64",
|
||||
"debian.8-x64",
|
||||
"rhel.7-x64",
|
||||
"ubuntu.14.04-x64",
|
||||
"ubuntu.16.04-x64",
|
||||
"fedora.23-x64",
|
||||
"linux-x64",
|
||||
"opensuse.13.2-x64"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
57
external/corefx/src/Common/src/Internal/Cryptography/BasicSymmetricCipher.cs
vendored
Normal file
57
external/corefx/src/Common/src/Internal/Cryptography/BasicSymmetricCipher.cs
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
//
|
||||
// Represents a symmetric reusable cipher encryptor or decryptor. Underlying technology may be CNG or OpenSSL or anything else.
|
||||
// The key, IV, chaining mode, blocksize and direction of encryption are all locked in when the BasicSymmetricCipher is instantiated.
|
||||
//
|
||||
// - Performs no padding. Padding is done by a higher-level layer.
|
||||
//
|
||||
// - Transform and TransformFinal only accept blocks whose sizes are a multiple of the crypto algorithms block size.
|
||||
//
|
||||
// - Transform() can do in-place encryption/decryption (input and output referencing the same array.)
|
||||
//
|
||||
// - TransformFinal() resets the object for reuse.
|
||||
//
|
||||
internal abstract class BasicSymmetricCipher : IDisposable
|
||||
{
|
||||
protected BasicSymmetricCipher(byte[] iv, int blockSizeInBytes)
|
||||
{
|
||||
IV = iv;
|
||||
BlockSizeInBytes = blockSizeInBytes;
|
||||
}
|
||||
|
||||
public abstract int Transform(byte[] input, int inputOffset, int count, byte[] output, int outputOffset);
|
||||
|
||||
public abstract byte[] TransformFinal(byte[] input, int inputOffset, int count);
|
||||
|
||||
public int BlockSizeInBytes { get; private set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (IV != null)
|
||||
{
|
||||
Array.Clear(IV, 0, IV.Length);
|
||||
IV = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected byte[] IV { get; private set; }
|
||||
}
|
||||
}
|
||||
122
external/corefx/src/Common/src/Internal/Cryptography/BasicSymmetricCipherBCrypt.cs
vendored
Normal file
122
external/corefx/src/Common/src/Internal/Cryptography/BasicSymmetricCipherBCrypt.cs
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
using Internal.NativeCrypto;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
internal sealed class BasicSymmetricCipherBCrypt : BasicSymmetricCipher
|
||||
{
|
||||
private readonly bool _encrypting;
|
||||
private SafeKeyHandle _hKey;
|
||||
private byte[] _currentIv; // CNG mutates this with the updated IV for the next stage on each Encrypt/Decrypt call.
|
||||
// The base IV holds a copy of the original IV for Reset(), until it is cleared by Dispose().
|
||||
|
||||
public BasicSymmetricCipherBCrypt(SafeAlgorithmHandle algorithm, CipherMode cipherMode, int blockSizeInBytes, byte[] key, bool ownsParentHandle, byte[] iv, bool encrypting)
|
||||
: base(cipherMode.GetCipherIv(iv), blockSizeInBytes)
|
||||
{
|
||||
Debug.Assert(algorithm != null);
|
||||
|
||||
_encrypting = encrypting;
|
||||
|
||||
if (IV != null)
|
||||
{
|
||||
_currentIv = new byte[IV.Length];
|
||||
}
|
||||
|
||||
_hKey = algorithm.BCryptImportKey(key);
|
||||
|
||||
if (ownsParentHandle)
|
||||
{
|
||||
_hKey.SetParentHandle(algorithm);
|
||||
}
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
SafeKeyHandle hKey = _hKey;
|
||||
_hKey = null;
|
||||
if (hKey != null)
|
||||
{
|
||||
hKey.Dispose();
|
||||
}
|
||||
|
||||
byte[] currentIv = _currentIv;
|
||||
_currentIv = null;
|
||||
if (currentIv != null)
|
||||
{
|
||||
Array.Clear(currentIv, 0, currentIv.Length);
|
||||
}
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
public override int Transform(byte[] input, int inputOffset, int count, byte[] output, int outputOffset)
|
||||
{
|
||||
Debug.Assert(input != null);
|
||||
Debug.Assert(inputOffset >= 0);
|
||||
Debug.Assert(count > 0);
|
||||
Debug.Assert((count % BlockSizeInBytes) == 0);
|
||||
Debug.Assert(input.Length - inputOffset >= count);
|
||||
Debug.Assert(output != null);
|
||||
Debug.Assert(outputOffset >= 0);
|
||||
Debug.Assert(output.Length - outputOffset >= count);
|
||||
|
||||
int numBytesWritten;
|
||||
if (_encrypting)
|
||||
{
|
||||
numBytesWritten = _hKey.BCryptEncrypt(input, inputOffset, count, _currentIv, output, outputOffset, output.Length - outputOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
numBytesWritten = _hKey.BCryptDecrypt(input, inputOffset, count, _currentIv, output, outputOffset, output.Length - outputOffset);
|
||||
}
|
||||
|
||||
if (numBytesWritten != count)
|
||||
{
|
||||
// CNG gives us no way to tell BCryptDecrypt() that we're decrypting the final block, nor is it performing any
|
||||
// padding /depadding for us. So there's no excuse for a provider to hold back output for "future calls." Though
|
||||
// this isn't technically our problem to detect, we might as well detect it now for easier diagnosis.
|
||||
throw new CryptographicException(SR.Cryptography_UnexpectedTransformTruncation);
|
||||
}
|
||||
|
||||
return numBytesWritten;
|
||||
}
|
||||
|
||||
public override byte[] TransformFinal(byte[] input, int inputOffset, int count)
|
||||
{
|
||||
Debug.Assert(input != null);
|
||||
Debug.Assert(inputOffset >= 0);
|
||||
Debug.Assert(count >= 0);
|
||||
Debug.Assert((count % BlockSizeInBytes) == 0);
|
||||
Debug.Assert(input.Length - inputOffset >= count);
|
||||
|
||||
byte[] output = new byte[count];
|
||||
if (count != 0)
|
||||
{
|
||||
int numBytesWritten = Transform(input, inputOffset, count, output, 0);
|
||||
Debug.Assert(numBytesWritten == count); // Our implementation of Transform() guarantees this. See comment above.
|
||||
}
|
||||
|
||||
Reset();
|
||||
return output;
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
if (IV != null)
|
||||
{
|
||||
Buffer.BlockCopy(IV, 0, _currentIv, 0, IV.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
50
external/corefx/src/Common/src/Internal/Cryptography/CngCommon.Hash.cs
vendored
Normal file
50
external/corefx/src/Common/src/Internal/Cryptography/CngCommon.Hash.cs
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
internal static partial class CngCommon
|
||||
{
|
||||
public static byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm)
|
||||
{
|
||||
// The classes that call us are sealed and their base class has checked this already.
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(offset >= 0 && offset <= data.Length);
|
||||
Debug.Assert(count >= 0 && count <= data.Length);
|
||||
Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name));
|
||||
|
||||
using (HashProviderCng hashProvider = new HashProviderCng(hashAlgorithm.Name, null))
|
||||
{
|
||||
hashProvider.AppendHashData(data, offset, count);
|
||||
byte[] hash = hashProvider.FinalizeHashAndReset();
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm)
|
||||
{
|
||||
// The classes that call us are sealed and their base class has checked this already.
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name));
|
||||
|
||||
using (HashProviderCng hashProvider = new HashProviderCng(hashAlgorithm.Name, null))
|
||||
{
|
||||
// Default the buffer size to 4K.
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = data.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
hashProvider.AppendHashData(buffer, 0, bytesRead);
|
||||
}
|
||||
byte[] hash = hashProvider.FinalizeHashAndReset();
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
45
external/corefx/src/Common/src/Internal/Cryptography/CngCommon.SignVerify.cs
vendored
Normal file
45
external/corefx/src/Common/src/Internal/Cryptography/CngCommon.SignVerify.cs
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
|
||||
using ErrorCode = Interop.NCrypt.ErrorCode;
|
||||
using AsymmetricPaddingMode = Interop.NCrypt.AsymmetricPaddingMode;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
internal static partial class CngCommon
|
||||
{
|
||||
public static unsafe byte[] SignHash(this SafeNCryptKeyHandle keyHandle, byte[] hash, AsymmetricPaddingMode paddingMode, void* pPaddingInfo, int estimatedSize)
|
||||
{
|
||||
#if DEBUG
|
||||
estimatedSize = 2; // Make sure the NTE_BUFFER_TOO_SMALL scenario gets exercised.
|
||||
#endif
|
||||
byte[] signature = new byte[estimatedSize];
|
||||
int numBytesNeeded;
|
||||
ErrorCode errorCode = Interop.NCrypt.NCryptSignHash(keyHandle, pPaddingInfo, hash, hash.Length, signature, signature.Length, out numBytesNeeded, paddingMode);
|
||||
if (errorCode == ErrorCode.NTE_BUFFER_TOO_SMALL)
|
||||
{
|
||||
signature = new byte[numBytesNeeded];
|
||||
errorCode = Interop.NCrypt.NCryptSignHash(keyHandle, pPaddingInfo, hash, hash.Length, signature, signature.Length, out numBytesNeeded, paddingMode);
|
||||
}
|
||||
if (errorCode != ErrorCode.ERROR_SUCCESS)
|
||||
throw errorCode.ToCryptographicException();
|
||||
|
||||
Array.Resize(ref signature, numBytesNeeded);
|
||||
return signature;
|
||||
}
|
||||
|
||||
public static unsafe bool VerifyHash(this SafeNCryptKeyHandle keyHandle, byte[] hash, byte[] signature, AsymmetricPaddingMode paddingMode, void* pPaddingInfo)
|
||||
{
|
||||
ErrorCode errorCode = Interop.NCrypt.NCryptVerifySignature(keyHandle, pPaddingInfo, hash, hash.Length, signature, signature.Length, paddingMode);
|
||||
bool verified = (errorCode == ErrorCode.ERROR_SUCCESS); // For consistency with other AsymmetricAlgorithm-derived classes, return "false" for any error code rather than making the caller catch an exception.
|
||||
return verified;
|
||||
}
|
||||
}
|
||||
}
|
||||
56
external/corefx/src/Common/src/Internal/Cryptography/HashProvider.cs
vendored
Normal file
56
external/corefx/src/Common/src/Internal/Cryptography/HashProvider.cs
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
//
|
||||
// This abstract class represents a reusable hash object and can wrap a CNG or WinRT hash object.
|
||||
//
|
||||
internal abstract class HashProvider : IDisposable
|
||||
{
|
||||
// Adds new data to be hashed. This can be called repeatedly in order to hash data from noncontiguous sources.
|
||||
public void AppendHashData(byte[] data, int offset, int count)
|
||||
{
|
||||
// AppendHashData can be called via exposed APIs (e.g. a type that derives from
|
||||
// HMACSHA1 and calls HashCore) and could be passed bad data from there. It could
|
||||
// also receive a bad count from HashAlgorithm reading from a Stream that returns
|
||||
// an invalid number of bytes read. Since our implementations of AppendHashDataCore
|
||||
// end up using unsafe code, we want to be sure the arguments are valid.
|
||||
if (data == null)
|
||||
throw new ArgumentNullException(nameof(data), SR.ArgumentNull_Buffer);
|
||||
if (offset < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum);
|
||||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
|
||||
if (data.Length - offset < count)
|
||||
throw new ArgumentException(SR.Argument_InvalidOffLen);
|
||||
|
||||
AppendHashDataCore(data, offset, count);
|
||||
}
|
||||
|
||||
// Adds new data to be hashed. This can be called repeatedly in order to hash data from noncontiguous sources.
|
||||
// Argument validation is handled by AppendHashData.
|
||||
public abstract void AppendHashDataCore(byte[] data, int offset, int count);
|
||||
|
||||
// Compute the hash based on the appended data and resets the HashProvider for more hashing.
|
||||
public abstract byte[] FinalizeHashAndReset();
|
||||
|
||||
// Returns the length of the byte array returned by FinalizeHashAndReset.
|
||||
public abstract int HashSizeInBytes { get; }
|
||||
|
||||
// Releases any native resources and keys used by the HashProvider.
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// Releases any native resources and keys used by the HashProvider.
|
||||
public abstract void Dispose(bool disposing);
|
||||
}
|
||||
}
|
||||
|
||||
152
external/corefx/src/Common/src/Internal/Cryptography/HashProviderCng.cs
vendored
Normal file
152
external/corefx/src/Common/src/Internal/Cryptography/HashProviderCng.cs
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using NTSTATUS = Interop.BCrypt.NTSTATUS;
|
||||
using BCryptOpenAlgorithmProviderFlags = Interop.BCrypt.BCryptOpenAlgorithmProviderFlags;
|
||||
using BCryptCreateHashFlags = Interop.BCrypt.BCryptCreateHashFlags;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
//
|
||||
// Provides hash services via the native provider (CNG).
|
||||
//
|
||||
internal sealed class HashProviderCng : HashProvider
|
||||
{
|
||||
//
|
||||
// - "hashAlgId" must be a name recognized by BCryptOpenAlgorithmProvider(). Examples: MD5, SHA1, SHA256.
|
||||
//
|
||||
// - "key" activates MAC hashing if present. If null, this HashProvider performs a regular old hash.
|
||||
//
|
||||
public HashProviderCng(string hashAlgId, byte[] key)
|
||||
{
|
||||
BCryptOpenAlgorithmProviderFlags dwFlags = BCryptOpenAlgorithmProviderFlags.None;
|
||||
if (key != null)
|
||||
{
|
||||
_key = key.CloneByteArray();
|
||||
dwFlags |= BCryptOpenAlgorithmProviderFlags.BCRYPT_ALG_HANDLE_HMAC_FLAG;
|
||||
}
|
||||
|
||||
_hAlgorithm = Interop.BCrypt.BCryptAlgorithmCache.GetCachedBCryptAlgorithmHandle(hashAlgId, dwFlags);
|
||||
|
||||
// Win7 won't set hHash, Win8+ will; and both will set _hHash.
|
||||
// So keep hHash trapped in this scope to prevent (mis-)use of it.
|
||||
{
|
||||
SafeBCryptHashHandle hHash = null;
|
||||
NTSTATUS ntStatus = Interop.BCrypt.BCryptCreateHash(_hAlgorithm, out hHash, IntPtr.Zero, 0, key, key == null ? 0 : key.Length, BCryptCreateHashFlags.BCRYPT_HASH_REUSABLE_FLAG);
|
||||
if (ntStatus == NTSTATUS.STATUS_INVALID_PARAMETER)
|
||||
{
|
||||
// If we got here, we're running on a downlevel OS (pre-Win8) that doesn't support reusable CNG hash objects. Fall back to creating a
|
||||
// new HASH object each time.
|
||||
ResetHashObject();
|
||||
}
|
||||
else if (ntStatus != NTSTATUS.STATUS_SUCCESS)
|
||||
{
|
||||
throw Interop.BCrypt.CreateCryptographicException(ntStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
_hHash = hHash;
|
||||
_reusable = true;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe
|
||||
{
|
||||
int cbSizeOfHashSize;
|
||||
int hashSize;
|
||||
NTSTATUS ntStatus = Interop.BCrypt.BCryptGetProperty(_hHash, Interop.BCrypt.BCryptPropertyStrings.BCRYPT_HASH_LENGTH, &hashSize, sizeof(int), out cbSizeOfHashSize, 0);
|
||||
if (ntStatus != NTSTATUS.STATUS_SUCCESS)
|
||||
throw Interop.BCrypt.CreateCryptographicException(ntStatus);
|
||||
_hashSize = hashSize;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
public sealed override void AppendHashDataCore(byte[] data, int offset, int count)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* pRgb = data)
|
||||
{
|
||||
NTSTATUS ntStatus = Interop.BCrypt.BCryptHashData(_hHash, pRgb + offset, count, 0);
|
||||
if (ntStatus != NTSTATUS.STATUS_SUCCESS)
|
||||
throw Interop.BCrypt.CreateCryptographicException(ntStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed override byte[] FinalizeHashAndReset()
|
||||
{
|
||||
byte[] hash = new byte[_hashSize];
|
||||
NTSTATUS ntStatus = Interop.BCrypt.BCryptFinishHash(_hHash, hash, hash.Length, 0);
|
||||
if (ntStatus != NTSTATUS.STATUS_SUCCESS)
|
||||
throw Interop.BCrypt.CreateCryptographicException(ntStatus);
|
||||
|
||||
ResetHashObject();
|
||||
return hash;
|
||||
}
|
||||
|
||||
public sealed override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
DestroyHash();
|
||||
if (_key != null)
|
||||
{
|
||||
byte[] key = _key;
|
||||
_key = null;
|
||||
Array.Clear(key, 0, key.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed override int HashSizeInBytes
|
||||
{
|
||||
get
|
||||
{
|
||||
return _hashSize;
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetHashObject()
|
||||
{
|
||||
if (_reusable)
|
||||
return;
|
||||
DestroyHash();
|
||||
|
||||
SafeBCryptHashHandle hHash;
|
||||
NTSTATUS ntStatus = Interop.BCrypt.BCryptCreateHash(_hAlgorithm, out hHash, IntPtr.Zero, 0, _key, _key == null ? 0 : _key.Length, BCryptCreateHashFlags.None);
|
||||
if (ntStatus != NTSTATUS.STATUS_SUCCESS)
|
||||
throw Interop.BCrypt.CreateCryptographicException(ntStatus);
|
||||
|
||||
_hHash = hHash;
|
||||
}
|
||||
|
||||
private void DestroyHash()
|
||||
{
|
||||
SafeBCryptHashHandle hHash = _hHash;
|
||||
_hHash = null;
|
||||
if (hHash != null)
|
||||
{
|
||||
hHash.Dispose();
|
||||
}
|
||||
|
||||
// Not disposing of _hAlgorithm as we got this from a cache. So it's not ours to Dispose().
|
||||
}
|
||||
|
||||
private readonly SafeBCryptAlgorithmHandle _hAlgorithm;
|
||||
private SafeBCryptHashHandle _hHash;
|
||||
private byte[] _key;
|
||||
private readonly bool _reusable;
|
||||
|
||||
private readonly int _hashSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
153
external/corefx/src/Common/src/Internal/Cryptography/OpenSslAsymmetricAlgorithmCore.cs
vendored
Normal file
153
external/corefx/src/Common/src/Internal/Cryptography/OpenSslAsymmetricAlgorithmCore.cs
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
//
|
||||
// Common infrastructure for AsymmetricAlgorithm-derived classes that layer on OpenSSL.
|
||||
//
|
||||
internal static class OpenSslAsymmetricAlgorithmCore
|
||||
{
|
||||
public static byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm)
|
||||
{
|
||||
// The classes that call us are sealed and their base class has checked this already.
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(count >= 0 && count <= data.Length);
|
||||
Debug.Assert(offset >= 0 && offset <= data.Length - count);
|
||||
Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name));
|
||||
|
||||
using (HashAlgorithm hasher = GetHashAlgorithm(hashAlgorithm))
|
||||
{
|
||||
return hasher.ComputeHash(data, offset, count);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] HashData(Stream data, HashAlgorithmName hashAlgorithm)
|
||||
{
|
||||
// The classes that call us are sealed and their base class has checked this already.
|
||||
Debug.Assert(data != null);
|
||||
Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name));
|
||||
|
||||
using (HashAlgorithm hasher = GetHashAlgorithm(hashAlgorithm))
|
||||
{
|
||||
return hasher.ComputeHash(data);
|
||||
}
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5351", Justification = "MD5 is used when the user asks for it.")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "SHA1 is used when the user asks for it.")]
|
||||
private static HashAlgorithm GetHashAlgorithm(HashAlgorithmName hashAlgorithmName)
|
||||
{
|
||||
HashAlgorithm hasher;
|
||||
|
||||
if (hashAlgorithmName == HashAlgorithmName.MD5)
|
||||
{
|
||||
hasher = MD5.Create();
|
||||
}
|
||||
else if (hashAlgorithmName == HashAlgorithmName.SHA1)
|
||||
{
|
||||
hasher = SHA1.Create();
|
||||
}
|
||||
else if (hashAlgorithmName == HashAlgorithmName.SHA256)
|
||||
{
|
||||
hasher = SHA256.Create();
|
||||
}
|
||||
else if (hashAlgorithmName == HashAlgorithmName.SHA384)
|
||||
{
|
||||
hasher = SHA384.Create();
|
||||
}
|
||||
else if (hashAlgorithmName == HashAlgorithmName.SHA512)
|
||||
{
|
||||
hasher = SHA512.Create();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new CryptographicException(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmName.Name);
|
||||
}
|
||||
|
||||
return hasher;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert Ieee1363 format of (r, s) to Der format
|
||||
/// </summary>
|
||||
public static byte[] ConvertIeee1363ToDer(byte[] input)
|
||||
{
|
||||
Debug.Assert(input != null);
|
||||
Debug.Assert(input.Length % 2 == 0);
|
||||
Debug.Assert(input.Length > 1);
|
||||
|
||||
// Input is (r, s), each of them exactly half of the array.
|
||||
// Output is the DER encoded value of CONSTRUCTEDSEQUENCE(INTEGER(r), INTEGER(s)).
|
||||
int halfLength = input.Length / 2;
|
||||
|
||||
byte[][] rEncoded = DerEncoder.SegmentedEncodeUnsignedInteger(input, 0, halfLength);
|
||||
byte[][] sEncoded = DerEncoder.SegmentedEncodeUnsignedInteger(input, halfLength, halfLength);
|
||||
|
||||
return DerEncoder.ConstructSequence(rEncoded, sEncoded);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert Der format of (r, s) to Ieee1363 format
|
||||
/// </summary>
|
||||
public static byte[] ConvertDerToIeee1363(byte[] input, int inputOffset, int inputCount, int fieldSizeBits)
|
||||
{
|
||||
int size = BitsToBytes(fieldSizeBits);
|
||||
|
||||
try
|
||||
{
|
||||
DerSequenceReader reader = new DerSequenceReader(input, inputOffset, inputCount);
|
||||
byte[] rDer = reader.ReadIntegerBytes();
|
||||
byte[] sDer = reader.ReadIntegerBytes();
|
||||
byte[] response = new byte[2 * size];
|
||||
|
||||
CopySignatureField(rDer, response, 0, size);
|
||||
CopySignatureField(sDer, response, size, size);
|
||||
|
||||
return response;
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
throw new CryptographicException(SR.Arg_CryptographyException, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static int BitsToBytes(int bitLength)
|
||||
{
|
||||
int byteLength = (bitLength + 7) / 8;
|
||||
return byteLength;
|
||||
}
|
||||
|
||||
private static void CopySignatureField(byte[] signatureField, byte[] response, int offset, int fieldLength)
|
||||
{
|
||||
if (signatureField.Length > fieldLength)
|
||||
{
|
||||
// The only way this should be true is if the value required a zero-byte-pad.
|
||||
Debug.Assert(signatureField.Length == fieldLength + 1, "signatureField.Length == fieldLength + 1");
|
||||
Debug.Assert(signatureField[0] == 0, "signatureField[0] == 0");
|
||||
Debug.Assert(signatureField[1] > 0x7F, "signatureField[1] > 0x7F");
|
||||
|
||||
Buffer.BlockCopy(signatureField, 1, response, offset, fieldLength);
|
||||
}
|
||||
else if (signatureField.Length == fieldLength)
|
||||
{
|
||||
Buffer.BlockCopy(signatureField, 0, response, offset, fieldLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the field is too short then it needs to be prepended
|
||||
// with zeroes in the response. Since the array was already
|
||||
// zeroed out, just figure out where we need to start copying.
|
||||
int writeOffset = fieldLength - signatureField.Length;
|
||||
|
||||
Buffer.BlockCopy(signatureField, 0, response, offset + writeOffset, signatureField.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
242
external/corefx/src/Common/src/Internal/Cryptography/UniversalCryptoDecryptor.cs
vendored
Normal file
242
external/corefx/src/Common/src/Internal/Cryptography/UniversalCryptoDecryptor.cs
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
//
|
||||
// A cross-platform ICryptoTransform implementation for decryption.
|
||||
//
|
||||
// - Implements the various padding algorithms (as we support padding algorithms that the underlying native apis don't.)
|
||||
//
|
||||
// - Parameterized by a BasicSymmetricCipher which encapsulates the algorithm, key, IV, chaining mode, direction of encryption
|
||||
// and the underlying native apis implementing the encryption.
|
||||
//
|
||||
internal sealed class UniversalCryptoDecryptor : UniversalCryptoTransform
|
||||
{
|
||||
public UniversalCryptoDecryptor(PaddingMode paddingMode, BasicSymmetricCipher basicSymmetricCipher)
|
||||
: base(paddingMode, basicSymmetricCipher)
|
||||
{
|
||||
}
|
||||
|
||||
protected sealed override int UncheckedTransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
//
|
||||
// If we're decrypting, it's possible to be called with the last blocks of the data, and then
|
||||
// have TransformFinalBlock called with an empty array. Since we don't know if this is the case,
|
||||
// we won't decrypt the last block of the input until either TransformBlock or
|
||||
// TransformFinalBlock is next called.
|
||||
//
|
||||
// We don't need to do this for PaddingMode.None because there is no padding to strip, and
|
||||
// we also don't do this for PaddingMode.Zeros since there is no way for us to tell if the
|
||||
// zeros at the end of a block are part of the plaintext or the padding.
|
||||
//
|
||||
int decryptedBytes = 0;
|
||||
if (DepaddingRequired)
|
||||
{
|
||||
// If we have data saved from a previous call, decrypt that into the output first
|
||||
if (_heldoverCipher != null)
|
||||
{
|
||||
int depadDecryptLength = BasicSymmetricCipher.Transform(_heldoverCipher, 0, _heldoverCipher.Length, outputBuffer, outputOffset);
|
||||
outputOffset += depadDecryptLength;
|
||||
decryptedBytes += depadDecryptLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
_heldoverCipher = new byte[InputBlockSize];
|
||||
}
|
||||
|
||||
// Postpone the last block to the next round.
|
||||
Debug.Assert(inputCount >= _heldoverCipher.Length, "inputCount >= _heldoverCipher.Length");
|
||||
int startOfLastBlock = inputOffset + inputCount - _heldoverCipher.Length;
|
||||
Buffer.BlockCopy(inputBuffer, startOfLastBlock, _heldoverCipher, 0, _heldoverCipher.Length);
|
||||
inputCount -= _heldoverCipher.Length;
|
||||
Debug.Assert(inputCount % InputBlockSize == 0, "Did not remove whole blocks for depadding");
|
||||
}
|
||||
|
||||
if (inputCount > 0)
|
||||
{
|
||||
decryptedBytes += BasicSymmetricCipher.Transform(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
|
||||
}
|
||||
|
||||
return decryptedBytes;
|
||||
}
|
||||
|
||||
protected sealed override byte[] UncheckedTransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
|
||||
{
|
||||
// We can't complete decryption on a partial block
|
||||
if (inputCount % InputBlockSize != 0)
|
||||
throw new CryptographicException(SR.Cryptography_PartialBlock);
|
||||
|
||||
//
|
||||
// If we have postponed cipher bits from the prior round, copy that into the decryption buffer followed by the input data.
|
||||
// Otherwise the decryption buffer is just the input data.
|
||||
//
|
||||
|
||||
byte[] ciphertext = null;
|
||||
|
||||
if (_heldoverCipher == null)
|
||||
{
|
||||
ciphertext = new byte[inputCount];
|
||||
Buffer.BlockCopy(inputBuffer, inputOffset, ciphertext, 0, inputCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
ciphertext = new byte[_heldoverCipher.Length + inputCount];
|
||||
Buffer.BlockCopy(_heldoverCipher, 0, ciphertext, 0, _heldoverCipher.Length);
|
||||
Buffer.BlockCopy(inputBuffer, inputOffset, ciphertext, _heldoverCipher.Length, inputCount);
|
||||
}
|
||||
|
||||
// Decrypt the data, then strip the padding to get the final decrypted data. Note that even if the cipherText length is 0, we must
|
||||
// invoke TransformFinal() so that the cipher object knows to reset for the next cipher operation.
|
||||
byte[] decryptedBytes = BasicSymmetricCipher.TransformFinal(ciphertext, 0, ciphertext.Length);
|
||||
byte[] outputData;
|
||||
if (ciphertext.Length > 0)
|
||||
{
|
||||
outputData = DepadBlock(decryptedBytes, 0, decryptedBytes.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputData = Array.Empty<byte>();
|
||||
}
|
||||
|
||||
Reset();
|
||||
return outputData;
|
||||
}
|
||||
|
||||
protected sealed override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
byte[] heldoverCipher = _heldoverCipher;
|
||||
_heldoverCipher = null;
|
||||
if (heldoverCipher != null)
|
||||
{
|
||||
Array.Clear(heldoverCipher, 0, heldoverCipher.Length);
|
||||
}
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
if (_heldoverCipher != null)
|
||||
{
|
||||
Array.Clear(_heldoverCipher, 0, _heldoverCipher.Length);
|
||||
_heldoverCipher = null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool DepaddingRequired
|
||||
{
|
||||
get
|
||||
{
|
||||
// Some padding modes encode sufficient information to allow for automatic depadding to happen.
|
||||
switch (PaddingMode)
|
||||
{
|
||||
case PaddingMode.PKCS7:
|
||||
case PaddingMode.ANSIX923:
|
||||
case PaddingMode.ISO10126:
|
||||
return true;
|
||||
case PaddingMode.Zeros:
|
||||
case PaddingMode.None:
|
||||
return false;
|
||||
default:
|
||||
Debug.Fail($"Invalid padding mode {PaddingMode}.");
|
||||
throw new CryptographicException(SR.Cryptography_InvalidPadding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the padding from the last blocks being decrypted
|
||||
/// </summary>
|
||||
private byte[] DepadBlock(byte[] block, int offset, int count)
|
||||
{
|
||||
Debug.Assert(block != null && count >= block.Length - offset);
|
||||
Debug.Assert(0 <= offset);
|
||||
Debug.Assert(0 <= count);
|
||||
|
||||
int padBytes = 0;
|
||||
|
||||
// See PadBlock for a description of the padding modes.
|
||||
switch (PaddingMode)
|
||||
{
|
||||
case PaddingMode.ANSIX923:
|
||||
padBytes = block[offset + count - 1];
|
||||
|
||||
// Verify the amount of padding is reasonable
|
||||
if (padBytes <= 0 || padBytes > InputBlockSize)
|
||||
{
|
||||
throw new CryptographicException(SR.Cryptography_InvalidPadding);
|
||||
}
|
||||
|
||||
// Verify that all the padding bytes are 0s
|
||||
for (int i = offset + count - padBytes; i < offset + count - 1; i++)
|
||||
{
|
||||
if (block[i] != 0)
|
||||
{
|
||||
throw new CryptographicException(SR.Cryptography_InvalidPadding);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PaddingMode.ISO10126:
|
||||
padBytes = block[offset + count - 1];
|
||||
|
||||
// Verify the amount of padding is reasonable
|
||||
if (padBytes <= 0 || padBytes > InputBlockSize)
|
||||
{
|
||||
throw new CryptographicException(SR.Cryptography_InvalidPadding);
|
||||
}
|
||||
|
||||
// Since the padding consists of random bytes, we cannot verify the actual pad bytes themselves
|
||||
break;
|
||||
|
||||
case PaddingMode.PKCS7:
|
||||
padBytes = block[offset + count - 1];
|
||||
|
||||
// Verify the amount of padding is reasonable
|
||||
if (padBytes <= 0 || padBytes > InputBlockSize)
|
||||
throw new CryptographicException(SR.Cryptography_InvalidPadding);
|
||||
|
||||
// Verify all the padding bytes match the amount of padding
|
||||
for (int i = offset + count - padBytes; i < offset + count; i++)
|
||||
{
|
||||
if (block[i] != padBytes)
|
||||
throw new CryptographicException(SR.Cryptography_InvalidPadding);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// We cannot remove Zeros padding because we don't know if the zeros at the end of the block
|
||||
// belong to the padding or the plaintext itself.
|
||||
case PaddingMode.Zeros:
|
||||
case PaddingMode.None:
|
||||
padBytes = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new CryptographicException(SR.Cryptography_UnknownPaddingMode);
|
||||
}
|
||||
|
||||
// Copy everything but the padding to the output
|
||||
byte[] depadded = new byte[count - padBytes];
|
||||
Buffer.BlockCopy(block, offset, depadded, 0, depadded.Length);
|
||||
return depadded;
|
||||
}
|
||||
|
||||
//
|
||||
// For padding modes that support automatic depadding, TransformBlock() leaves the last block it is given undone since it has no way of knowing
|
||||
// whether this is the final block that needs depadding. This block is held (in encrypted form) in _heldoverCipher. The next call to TransformBlock
|
||||
// or TransformFinalBlock must include the decryption of _heldoverCipher in the results.
|
||||
//
|
||||
private byte[] _heldoverCipher;
|
||||
}
|
||||
}
|
||||
115
external/corefx/src/Common/src/Internal/Cryptography/UniversalCryptoEncryptor.cs
vendored
Normal file
115
external/corefx/src/Common/src/Internal/Cryptography/UniversalCryptoEncryptor.cs
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
//
|
||||
// A cross-platform ICryptoTransform implementation for encryption.
|
||||
//
|
||||
// - Implements the various padding algorithms (as we support padding algorithms that the underlying native apis don't.)
|
||||
//
|
||||
// - Parameterized by a BasicSymmetricCipher which encapsulates the algorithm, key, IV, chaining mode, direction of encryption
|
||||
// and the underlying native apis implementing the encryption.
|
||||
//
|
||||
internal sealed class UniversalCryptoEncryptor : UniversalCryptoTransform
|
||||
{
|
||||
private static readonly RandomNumberGenerator s_randomNumberGenerator = RandomNumberGenerator.Create();
|
||||
|
||||
public UniversalCryptoEncryptor(PaddingMode paddingMode, BasicSymmetricCipher basicSymmetricCipher)
|
||||
: base(paddingMode, basicSymmetricCipher)
|
||||
{
|
||||
}
|
||||
|
||||
protected sealed override int UncheckedTransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
return BasicSymmetricCipher.Transform(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
|
||||
}
|
||||
|
||||
protected sealed override byte[] UncheckedTransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
|
||||
{
|
||||
byte[] paddedBlock = PadBlock(inputBuffer, inputOffset, inputCount);
|
||||
byte[] output = BasicSymmetricCipher.TransformFinal(paddedBlock, 0, paddedBlock.Length);
|
||||
return output;
|
||||
}
|
||||
|
||||
private byte[] PadBlock(byte[] block, int offset, int count)
|
||||
{
|
||||
byte[] result;
|
||||
int padBytes = InputBlockSize - (count % InputBlockSize);
|
||||
|
||||
switch (PaddingMode)
|
||||
{
|
||||
case PaddingMode.None:
|
||||
if (count % InputBlockSize != 0)
|
||||
throw new CryptographicException(SR.Cryptography_PartialBlock);
|
||||
|
||||
result = new byte[count];
|
||||
Buffer.BlockCopy(block, offset, result, 0, result.Length);
|
||||
break;
|
||||
|
||||
// ANSI padding fills the blocks with zeros and adds the total number of padding bytes as
|
||||
// the last pad byte, adding an extra block if the last block is complete.
|
||||
//
|
||||
// x 00 00 00 00 00 00 07
|
||||
case PaddingMode.ANSIX923:
|
||||
result = new byte[count + padBytes];
|
||||
|
||||
Buffer.BlockCopy(block, offset, result, 0, count);
|
||||
result[result.Length - 1] = (byte)padBytes;
|
||||
|
||||
break;
|
||||
|
||||
// ISO padding fills the blocks up with random bytes and adds the total number of padding
|
||||
// bytes as the last pad byte, adding an extra block if the last block is complete.
|
||||
//
|
||||
// xx rr rr rr rr rr rr 07
|
||||
case PaddingMode.ISO10126:
|
||||
result = new byte[count + padBytes];
|
||||
|
||||
Buffer.BlockCopy(block, offset, result, 0, count);
|
||||
s_randomNumberGenerator.GetBytes(result, count + 1, padBytes - 1);
|
||||
result[result.Length - 1] = (byte)padBytes;
|
||||
|
||||
break;
|
||||
|
||||
// PKCS padding fills the blocks up with bytes containing the total number of padding bytes
|
||||
// used, adding an extra block if the last block is complete.
|
||||
//
|
||||
// xx xx 06 06 06 06 06 06
|
||||
case PaddingMode.PKCS7:
|
||||
result = new byte[count + padBytes];
|
||||
Buffer.BlockCopy(block, offset, result, 0, count);
|
||||
|
||||
for (int i = count; i < result.Length; i++)
|
||||
{
|
||||
result[i] = (byte)padBytes;
|
||||
}
|
||||
break;
|
||||
|
||||
// Zeros padding fills the last partial block with zeros, and does not add a new block to
|
||||
// the end if the last block is already complete.
|
||||
//
|
||||
// xx 00 00 00 00 00 00 00
|
||||
case PaddingMode.Zeros:
|
||||
if (padBytes == InputBlockSize)
|
||||
{
|
||||
padBytes = 0;
|
||||
}
|
||||
|
||||
result = new byte[count + padBytes];
|
||||
Buffer.BlockCopy(block, offset, result, 0, count);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new CryptographicException(SR.Cryptography_UnknownPaddingMode);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
119
external/corefx/src/Common/src/Internal/Cryptography/UniversalCryptoTransform.cs
vendored
Normal file
119
external/corefx/src/Common/src/Internal/Cryptography/UniversalCryptoTransform.cs
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
//
|
||||
// The common base class for the cross-platform CreateEncryptor()/CreateDecryptor() implementations.
|
||||
//
|
||||
// - Implements the various padding algorithms (as we support padding algorithms that the underlying native apis don't.)
|
||||
//
|
||||
// - Parameterized by a BasicSymmetricCipher which encapsulates the algorithm, key, IV, chaining mode, direction of encryption
|
||||
// and the underlying native apis implementing the encryption.
|
||||
//
|
||||
internal abstract class UniversalCryptoTransform : ICryptoTransform
|
||||
{
|
||||
public static ICryptoTransform Create(PaddingMode paddingMode, BasicSymmetricCipher cipher, bool encrypting)
|
||||
{
|
||||
if (encrypting)
|
||||
return new UniversalCryptoEncryptor(paddingMode, cipher);
|
||||
else
|
||||
return new UniversalCryptoDecryptor(paddingMode, cipher);
|
||||
}
|
||||
|
||||
protected UniversalCryptoTransform(PaddingMode paddingMode, BasicSymmetricCipher basicSymmetricCipher)
|
||||
{
|
||||
PaddingMode = paddingMode;
|
||||
BasicSymmetricCipher = basicSymmetricCipher;
|
||||
}
|
||||
|
||||
public bool CanReuseTransform
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public bool CanTransformMultipleBlocks
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public int InputBlockSize
|
||||
{
|
||||
get { return BasicSymmetricCipher.BlockSizeInBytes; }
|
||||
}
|
||||
|
||||
public int OutputBlockSize
|
||||
{
|
||||
get { return BasicSymmetricCipher.BlockSizeInBytes; }
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
|
||||
{
|
||||
if (inputBuffer == null)
|
||||
throw new ArgumentNullException(nameof(inputBuffer));
|
||||
if (inputOffset < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(inputOffset));
|
||||
if (inputOffset > inputBuffer.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(inputOffset));
|
||||
if (inputCount <= 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(inputCount));
|
||||
if (inputCount % InputBlockSize != 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(inputCount), SR.Cryptography_MustTransformWholeBlock);
|
||||
if (inputCount > inputBuffer.Length - inputOffset)
|
||||
throw new ArgumentOutOfRangeException(nameof(inputCount), SR.Cryptography_TransformBeyondEndOfBuffer);
|
||||
if (outputBuffer == null)
|
||||
throw new ArgumentNullException(nameof(outputBuffer));
|
||||
if (outputOffset > outputBuffer.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(outputOffset));
|
||||
if (inputCount > outputBuffer.Length - outputOffset)
|
||||
throw new ArgumentOutOfRangeException(nameof(outputOffset), SR.Cryptography_TransformBeyondEndOfBuffer);
|
||||
|
||||
int numBytesWritten = UncheckedTransformBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
|
||||
Debug.Assert(numBytesWritten >= 0 && numBytesWritten <= inputCount);
|
||||
return numBytesWritten;
|
||||
}
|
||||
|
||||
public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
|
||||
{
|
||||
if (inputBuffer == null)
|
||||
throw new ArgumentNullException(nameof(inputBuffer));
|
||||
if (inputOffset < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(inputOffset));
|
||||
if (inputCount < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(inputCount));
|
||||
if (inputOffset > inputBuffer.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(inputOffset));
|
||||
if (inputCount > inputBuffer.Length - inputOffset)
|
||||
throw new ArgumentOutOfRangeException(nameof(inputCount), SR.Cryptography_TransformBeyondEndOfBuffer);
|
||||
|
||||
byte[] output = UncheckedTransformFinalBlock(inputBuffer, inputOffset, inputCount);
|
||||
return output;
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
BasicSymmetricCipher.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract int UncheckedTransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
|
||||
protected abstract byte[] UncheckedTransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount);
|
||||
|
||||
protected PaddingMode PaddingMode { get; private set; }
|
||||
protected BasicSymmetricCipher BasicSymmetricCipher { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
28
external/corefx/src/Common/src/Internal/Cryptography/Windows/CryptoThrowHelper.cs
vendored
Normal file
28
external/corefx/src/Common/src/Internal/Cryptography/Windows/CryptoThrowHelper.cs
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
internal static class CryptoThrowHelper
|
||||
{
|
||||
public static CryptographicException ToCryptographicException(this int hr)
|
||||
{
|
||||
string message = Interop.Kernel32.GetMessage(hr);
|
||||
return new WindowsCryptographicException(hr, message);
|
||||
}
|
||||
|
||||
private sealed class WindowsCryptographicException : CryptographicException
|
||||
{
|
||||
public WindowsCryptographicException(int hr, string message)
|
||||
: base(message)
|
||||
{
|
||||
HResult = hr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
external/corefx/src/Common/src/Internal/Cryptography/Windows/ErrorCodeHelper.cs
vendored
Normal file
16
external/corefx/src/Common/src/Internal/Cryptography/Windows/ErrorCodeHelper.cs
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
internal static class ErrorCodeHelper
|
||||
{
|
||||
public static CryptographicException ToCryptographicException(this Interop.NCrypt.ErrorCode errorCode)
|
||||
{
|
||||
return ((int)errorCode).ToCryptographicException();
|
||||
}
|
||||
}
|
||||
}
|
||||
69
external/corefx/src/Common/src/Interop/Interop.CheckedAccess.cs
vendored
Normal file
69
external/corefx/src/Common/src/Interop/Interop.CheckedAccess.cs
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
internal static partial class Interop
|
||||
{
|
||||
public static unsafe void CheckBounds(byte* buffer, int bufferSize, byte* offset, int accessSize)
|
||||
{
|
||||
var start = checked((int)(IntPtr)(offset - buffer));
|
||||
var end = checked(start + accessSize);
|
||||
if (start < 0 || end > bufferSize)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe void CheckBounds(byte* buffer, int bufferSize, byte* offset)
|
||||
{
|
||||
CheckBounds(buffer, bufferSize, offset, sizeof(byte));
|
||||
}
|
||||
|
||||
public static unsafe void CheckBounds(byte* buffer, int bufferSize, ushort* offset)
|
||||
{
|
||||
CheckBounds(buffer, bufferSize, (byte*)offset, sizeof(ushort));
|
||||
}
|
||||
|
||||
public static unsafe void CheckBounds(byte* buffer, int bufferSize, uint* offset)
|
||||
{
|
||||
CheckBounds(buffer, bufferSize, (byte*)offset, sizeof(uint));
|
||||
}
|
||||
|
||||
public static unsafe byte CheckedRead(byte* buffer, int bufferSize, byte* offset)
|
||||
{
|
||||
CheckBounds(buffer, bufferSize, offset);
|
||||
return *offset;
|
||||
}
|
||||
|
||||
public static unsafe ushort CheckedRead(byte* buffer, int bufferSize, ushort* offset)
|
||||
{
|
||||
CheckBounds(buffer, bufferSize, offset);
|
||||
return *offset;
|
||||
}
|
||||
|
||||
public static unsafe uint CheckedRead(byte* buffer, int bufferSize, uint* offset)
|
||||
{
|
||||
CheckBounds(buffer, bufferSize, offset);
|
||||
return *offset;
|
||||
}
|
||||
|
||||
public static unsafe void CheckedWrite(byte* buffer, int bufferSize, byte* offset, byte value)
|
||||
{
|
||||
CheckBounds(buffer, bufferSize, offset);
|
||||
*offset = value;
|
||||
}
|
||||
|
||||
public static unsafe void CheckedWrite(byte* buffer, int bufferSize, ushort* offset, ushort value)
|
||||
{
|
||||
CheckBounds(buffer, bufferSize, offset);
|
||||
*offset = value;
|
||||
}
|
||||
|
||||
public static unsafe void CheckedWrite(byte* buffer, int bufferSize, uint* offset, uint value)
|
||||
{
|
||||
CheckBounds(buffer, bufferSize, offset);
|
||||
*offset = value;
|
||||
}
|
||||
}
|
||||
33
external/corefx/src/Common/src/Interop/Linux/Interop.LinuxNetDeviceFlags.cs
vendored
Normal file
33
external/corefx/src/Common/src/Interop/Linux/Interop.LinuxNetDeviceFlags.cs
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
internal static partial class Interop
|
||||
{
|
||||
// /usr/include/linux/if.h
|
||||
[Flags]
|
||||
internal enum LinuxNetDeviceFlags
|
||||
{
|
||||
IFF_UP = 1 << 0, /* sysfs */
|
||||
IFF_BROADCAST = 1 << 1, /* volatile */
|
||||
IFF_DEBUG = 1 << 2, /* sysfs */
|
||||
IFF_LOOPBACK = 1 << 3, /* volatile */
|
||||
IFF_POINTOPOINT = 1 << 4, /* volatile */
|
||||
IFF_NOTRAILERS = 1 << 5, /* sysfs */
|
||||
IFF_RUNNING = 1 << 6, /* volatile */
|
||||
IFF_NOARP = 1 << 7, /* sysfs */
|
||||
IFF_PROMISC = 1 << 8, /* sysfs */
|
||||
IFF_ALLMULTI = 1 << 9, /* sysfs */
|
||||
IFF_MASTER = 1 << 10, /* volatile */
|
||||
IFF_SLAVE = 1 << 11, /* volatile */
|
||||
IFF_MULTICAST = 1 << 12, /* sysfs */
|
||||
IFF_PORTSEL = 1 << 13, /* sysfs */
|
||||
IFF_AUTOMEDIA = 1 << 14, /* sysfs */
|
||||
IFF_DYNAMIC = 1 << 15, /* sysfs */
|
||||
IFF_LOWER_UP = 1 << 16, /* volatile */
|
||||
IFF_DORMANT = 1 << 17, /* volatile */
|
||||
IFF_ECHO = 1 << 18, /* volatile */
|
||||
}
|
||||
}
|
||||
26
external/corefx/src/Common/src/Interop/Linux/Interop.LinuxTcpState.cs
vendored
Normal file
26
external/corefx/src/Common/src/Interop/Linux/Interop.LinuxTcpState.cs
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
internal static partial class Interop
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a TCP state from the Linux kernel.
|
||||
/// Taken from /include/net/tcp_states.h
|
||||
/// </summary>
|
||||
internal enum LinuxTcpState
|
||||
{
|
||||
TCP_ESTABLISHED = 1,
|
||||
TCP_SYN_SENT,
|
||||
TCP_SYN_RECV,
|
||||
TCP_FIN_WAIT1,
|
||||
TCP_FIN_WAIT2,
|
||||
TCP_TIME_WAIT,
|
||||
TCP_CLOSE,
|
||||
TCP_CLOSE_WAIT,
|
||||
TCP_LAST_ACK,
|
||||
TCP_LISTEN,
|
||||
TCP_CLOSING,
|
||||
TCP_NEW_SYN_RECV,
|
||||
}
|
||||
}
|
||||
63
external/corefx/src/Common/src/Interop/Linux/System.Native/Interop.INotify.cs
vendored
Normal file
63
external/corefx/src/Common/src/Interop/Linux/System.Native/Interop.INotify.cs
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
|
||||
internal static partial class Interop
|
||||
{
|
||||
internal static partial class Sys
|
||||
{
|
||||
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_INotifyInit", SetLastError = true)]
|
||||
internal static extern SafeFileHandle INotifyInit();
|
||||
|
||||
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_INotifyAddWatch", SetLastError = true)]
|
||||
internal static extern int INotifyAddWatch(SafeFileHandle fd, string pathName, uint mask);
|
||||
|
||||
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_INotifyRemoveWatch", SetLastError = true)]
|
||||
private static extern int INotifyRemoveWatch_private(SafeFileHandle fd, int wd);
|
||||
|
||||
internal static int INotifyRemoveWatch(SafeFileHandle fd, int wd)
|
||||
{
|
||||
int result = INotifyRemoveWatch_private(fd, wd);
|
||||
if (result < 0)
|
||||
{
|
||||
Error hr = GetLastError();
|
||||
if (hr == Error.EINVAL)
|
||||
{
|
||||
// This specific case means that there was a deleted event in the queue that was not processed
|
||||
// so this call is expected to fail since the WatchDescriptor is no longer valid and was cleaned
|
||||
// up automatically by the OS.
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Fail("inotify_rm_watch failed with " + hr);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum NotifyEvents
|
||||
{
|
||||
IN_ACCESS = 0x00000001,
|
||||
IN_MODIFY = 0x00000002,
|
||||
IN_ATTRIB = 0x00000004,
|
||||
IN_MOVED_FROM = 0x00000040,
|
||||
IN_MOVED_TO = 0x00000080,
|
||||
IN_CREATE = 0x00000100,
|
||||
IN_DELETE = 0x00000200,
|
||||
IN_Q_OVERFLOW = 0x00004000,
|
||||
IN_IGNORED = 0x00008000,
|
||||
IN_ONLYDIR = 0x01000000,
|
||||
IN_DONT_FOLLOW = 0x02000000,
|
||||
IN_EXCL_UNLINK = 0x04000000,
|
||||
IN_ISDIR = 0x40000000,
|
||||
}
|
||||
}
|
||||
}
|
||||
33
external/corefx/src/Common/src/Interop/Linux/System.Native/Interop.NetworkChange.cs
vendored
Normal file
33
external/corefx/src/Common/src/Interop/Linux/System.Native/Interop.NetworkChange.cs
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
|
||||
internal static partial class Interop
|
||||
{
|
||||
internal static partial class Sys
|
||||
{
|
||||
public enum NetworkChangeKind
|
||||
{
|
||||
None = -1,
|
||||
AddressAdded = 0,
|
||||
AddressRemoved = 1,
|
||||
LinkAdded = 2,
|
||||
LinkRemoved = 3,
|
||||
AvailabilityChanged = 4
|
||||
}
|
||||
|
||||
public delegate void NetworkChangeEvent(int socket, NetworkChangeKind kind);
|
||||
|
||||
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CreateNetworkChangeListenerSocket")]
|
||||
public static extern Error CreateNetworkChangeListenerSocket(out int socket);
|
||||
|
||||
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CloseNetworkChangeListenerSocket")]
|
||||
public static extern Error CloseNetworkChangeListenerSocket(int socket);
|
||||
|
||||
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReadEvents")]
|
||||
public static extern void ReadEvents(int socket, NetworkChangeEvent onNetworkChange);
|
||||
}
|
||||
}
|
||||
284
external/corefx/src/Common/src/Interop/Linux/procfs/Interop.ProcFsStat.cs
vendored
Normal file
284
external/corefx/src/Common/src/Interop/Linux/procfs/Interop.ProcFsStat.cs
vendored
Normal file
@@ -0,0 +1,284 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
internal static partial class Interop
|
||||
{
|
||||
internal static partial class procfs
|
||||
{
|
||||
internal const string RootPath = "/proc/";
|
||||
internal const string SelfExeFilePath = RootPath + "self/exe";
|
||||
internal const string ProcUptimeFilePath = RootPath + "uptime";
|
||||
private const string StatFileName = "/stat";
|
||||
private const string MapsFileName = "/maps";
|
||||
private const string FileDescriptorDirectoryName = "/fd/";
|
||||
private const string TaskDirectoryName = "/task/";
|
||||
|
||||
internal struct ParsedStat
|
||||
{
|
||||
// Commented out fields are available in the stat data file but
|
||||
// are currently not used. If/when needed, they can be uncommented,
|
||||
// and the corresponding entry can be added back to StatParser, replacing
|
||||
// the MoveNext() with the appropriate ParseNext* call and assignment.
|
||||
|
||||
internal int pid;
|
||||
internal string comm;
|
||||
internal char state;
|
||||
//internal int ppid;
|
||||
//internal int pgrp;
|
||||
internal int session;
|
||||
//internal int tty_nr;
|
||||
//internal int tpgid;
|
||||
//internal uint flags;
|
||||
//internal ulong minflt;
|
||||
//internal ulong cminflt;
|
||||
//internal ulong majflt;
|
||||
//internal ulong cmajflt;
|
||||
internal ulong utime;
|
||||
internal ulong stime;
|
||||
//internal long cutime;
|
||||
//internal long cstime;
|
||||
//internal long priority;
|
||||
internal long nice;
|
||||
//internal long num_threads;
|
||||
//internal long itrealvalue;
|
||||
internal ulong starttime;
|
||||
internal ulong vsize;
|
||||
internal long rss;
|
||||
internal ulong rsslim;
|
||||
//internal ulong startcode;
|
||||
//internal ulong endcode;
|
||||
//internal ulong startstack;
|
||||
//internal ulong kstkesp;
|
||||
//internal ulong kstkeip;
|
||||
//internal ulong signal;
|
||||
//internal ulong blocked;
|
||||
//internal ulong sigignore;
|
||||
//internal ulong sigcatch;
|
||||
//internal ulong wchan;
|
||||
//internal ulong nswap;
|
||||
//internal ulong cnswap;
|
||||
//internal int exit_signal;
|
||||
//internal int processor;
|
||||
//internal uint rt_priority;
|
||||
//internal uint policy;
|
||||
//internal ulong delayacct_blkio_ticks;
|
||||
//internal ulong guest_time;
|
||||
//internal long cguest_time;
|
||||
}
|
||||
|
||||
internal struct ParsedMapsModule
|
||||
{
|
||||
internal string FileName;
|
||||
internal KeyValuePair<long, long> AddressRange;
|
||||
}
|
||||
|
||||
internal static string GetStatFilePathForProcess(int pid)
|
||||
{
|
||||
return RootPath + pid.ToString(CultureInfo.InvariantCulture) + StatFileName;
|
||||
}
|
||||
|
||||
internal static string GetMapsFilePathForProcess(int pid)
|
||||
{
|
||||
return RootPath + pid.ToString(CultureInfo.InvariantCulture) + MapsFileName;
|
||||
}
|
||||
|
||||
internal static string GetTaskDirectoryPathForProcess(int pid)
|
||||
{
|
||||
return RootPath + pid.ToString(CultureInfo.InvariantCulture) + TaskDirectoryName;
|
||||
}
|
||||
|
||||
internal static string GetFileDescriptorDirectoryPathForProcess(int pid)
|
||||
{
|
||||
return RootPath + pid.ToString(CultureInfo.InvariantCulture) + FileDescriptorDirectoryName;
|
||||
}
|
||||
|
||||
internal static IEnumerable<ParsedMapsModule> ParseMapsModules(int pid)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ParseMapsModulesCore(File.ReadLines(GetMapsFilePathForProcess(pid)));
|
||||
}
|
||||
catch (IOException) { }
|
||||
catch (UnauthorizedAccessException) { }
|
||||
|
||||
return Array.Empty<ParsedMapsModule>();
|
||||
}
|
||||
|
||||
private static IEnumerable<ParsedMapsModule> ParseMapsModulesCore(IEnumerable<string> lines)
|
||||
{
|
||||
Debug.Assert(lines != null);
|
||||
|
||||
// Parse each line from the maps file into a ParsedMapsModule result
|
||||
foreach (string line in lines)
|
||||
{
|
||||
// Use a StringParser to avoid string.Split costs
|
||||
var parser = new StringParser(line, separator: ' ', skipEmpty: true);
|
||||
|
||||
// Parse the address range
|
||||
KeyValuePair<long, long> addressRange =
|
||||
parser.ParseRaw(delegate (string s, ref int start, ref int end)
|
||||
{
|
||||
long startingAddress = 0, endingAddress = 0;
|
||||
int pos = s.IndexOf('-', start, end - start);
|
||||
if (pos > 0)
|
||||
{
|
||||
string startingString = s.Substring(start, pos);
|
||||
if (long.TryParse(startingString, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out startingAddress))
|
||||
{
|
||||
string endingString = s.Substring(pos + 1, end - (pos + 1));
|
||||
long.TryParse(endingString, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out endingAddress);
|
||||
}
|
||||
}
|
||||
return new KeyValuePair<long, long>(startingAddress, endingAddress);
|
||||
});
|
||||
|
||||
// Parse the permissions (we only care about entries with 'r' and 'x' set)
|
||||
if (!parser.ParseRaw(delegate (string s, ref int start, ref int end)
|
||||
{
|
||||
bool sawRead = false, sawExec = false;
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
if (s[i] == 'r')
|
||||
sawRead = true;
|
||||
else if (s[i] == 'x')
|
||||
sawExec = true;
|
||||
}
|
||||
return sawRead & sawExec;
|
||||
}))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip past the offset, dev, and inode fields
|
||||
parser.MoveNext();
|
||||
parser.MoveNext();
|
||||
parser.MoveNext();
|
||||
|
||||
// Parse the pathname
|
||||
if (!parser.MoveNext())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
string pathname = parser.ExtractCurrentToEnd();
|
||||
|
||||
// We only get here if a we have a non-empty pathname and
|
||||
// the permissions included both readability and executability.
|
||||
// Yield the result.
|
||||
yield return new ParsedMapsModule { FileName = pathname, AddressRange = addressRange };
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetStatFilePathForThread(int pid, int tid)
|
||||
{
|
||||
// Perf note: Calling GetTaskDirectoryPathForProcess will allocate a string,
|
||||
// which we then use in another Concat call to produce another string. The straightforward alternative,
|
||||
// though, since we have five input strings, is to use the string.Concat overload that takes a params array.
|
||||
// This results in allocating not only the params array but also a defensive copy inside of Concat,
|
||||
// which means allocating two five-element arrays. This two-string approach will result not only in fewer
|
||||
// allocations, but also typically in less memory allocated, and it's a bit more maintainable.
|
||||
return GetTaskDirectoryPathForProcess(pid) + tid.ToString(CultureInfo.InvariantCulture) + StatFileName;
|
||||
}
|
||||
|
||||
internal static bool TryReadStatFile(int pid, out ParsedStat result, ReusableTextReader reusableReader)
|
||||
{
|
||||
bool b = TryParseStatFile(GetStatFilePathForProcess(pid), out result, reusableReader);
|
||||
Debug.Assert(!b || result.pid == pid, "Expected process ID from stat file to match supplied pid");
|
||||
return b;
|
||||
}
|
||||
|
||||
internal static bool TryReadStatFile(int pid, int tid, out ParsedStat result, ReusableTextReader reusableReader)
|
||||
{
|
||||
bool b = TryParseStatFile(GetStatFilePathForThread(pid, tid), out result, reusableReader);
|
||||
//
|
||||
// This assert currently fails in the Windows Subsystem For Linux. See https://github.com/Microsoft/BashOnWindows/issues/967.
|
||||
//
|
||||
//Debug.Assert(!b || result.pid == tid, "Expected thread ID from stat file to match supplied tid");
|
||||
return b;
|
||||
}
|
||||
|
||||
internal static bool TryParseStatFile(string statFilePath, out ParsedStat result, ReusableTextReader reusableReader)
|
||||
{
|
||||
string statFileContents;
|
||||
try
|
||||
{
|
||||
using (var source = new FileStream(statFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1, useAsync: false))
|
||||
{
|
||||
statFileContents = reusableReader.ReadAllText(source);
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
// Between the time that we get an ID and the time that we try to read the associated stat
|
||||
// file(s), the process could be gone.
|
||||
result = default(ParsedStat);
|
||||
return false;
|
||||
}
|
||||
|
||||
var parser = new StringParser(statFileContents, ' ');
|
||||
var results = default(ParsedStat);
|
||||
|
||||
results.pid = parser.ParseNextInt32();
|
||||
results.comm = parser.MoveAndExtractNextInOuterParens();
|
||||
results.state = parser.ParseNextChar();
|
||||
parser.MoveNextOrFail(); // ppid
|
||||
parser.MoveNextOrFail(); // pgrp
|
||||
results.session = parser.ParseNextInt32();
|
||||
parser.MoveNextOrFail(); // tty_nr
|
||||
parser.MoveNextOrFail(); // tpgid
|
||||
parser.MoveNextOrFail(); // flags
|
||||
parser.MoveNextOrFail(); // majflt
|
||||
parser.MoveNextOrFail(); // cmagflt
|
||||
parser.MoveNextOrFail(); // minflt
|
||||
parser.MoveNextOrFail(); // cminflt
|
||||
results.utime = parser.ParseNextUInt64();
|
||||
results.stime = parser.ParseNextUInt64();
|
||||
parser.MoveNextOrFail(); // cutime
|
||||
parser.MoveNextOrFail(); // cstime
|
||||
parser.MoveNextOrFail(); // priority
|
||||
results.nice = parser.ParseNextInt64();
|
||||
parser.MoveNextOrFail(); // num_threads
|
||||
parser.MoveNextOrFail(); // itrealvalue
|
||||
results.starttime = parser.ParseNextUInt64();
|
||||
results.vsize = parser.ParseNextUInt64();
|
||||
results.rss = parser.ParseNextInt64();
|
||||
results.rsslim = parser.ParseNextUInt64();
|
||||
|
||||
// The following lines are commented out as there's no need to parse through
|
||||
// the rest of the entry (we've gotten all of the data we need). Should any
|
||||
// of these fields be needed in the future, uncomment all of the lines up
|
||||
// through and including the one that's needed. For now, these are being left
|
||||
// commented to document what's available in the remainder of the entry.
|
||||
|
||||
//parser.MoveNextOrFail(); // startcode
|
||||
//parser.MoveNextOrFail(); // endcode
|
||||
//parser.MoveNextOrFail(); // startstack
|
||||
//parser.MoveNextOrFail(); // kstkesp
|
||||
//parser.MoveNextOrFail(); // kstkeip
|
||||
//parser.MoveNextOrFail(); // signal
|
||||
//parser.MoveNextOrFail(); // blocked
|
||||
//parser.MoveNextOrFail(); // sigignore
|
||||
//parser.MoveNextOrFail(); // sigcatch
|
||||
//parser.MoveNextOrFail(); // wchan
|
||||
//parser.MoveNextOrFail(); // nswap
|
||||
//parser.MoveNextOrFail(); // cnswap
|
||||
//parser.MoveNextOrFail(); // exit_signal
|
||||
//parser.MoveNextOrFail(); // processor
|
||||
//parser.MoveNextOrFail(); // rt_priority
|
||||
//parser.MoveNextOrFail(); // policy
|
||||
//parser.MoveNextOrFail(); // delayacct_blkio_ticks
|
||||
//parser.MoveNextOrFail(); // guest_time
|
||||
//parser.MoveNextOrFail(); // cguest_time
|
||||
|
||||
result = results;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user