You've already forked linux-packaging-mono
Imported Upstream version 5.4.0.167
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
This commit is contained in:
parent
e49d6f06c0
commit
536cd135cc
@@ -2,7 +2,8 @@
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\dir.props" />
|
||||
<PropertyGroup>
|
||||
<AssemblyVersion>4.2.0.0</AssemblyVersion>
|
||||
<AssemblyVersion>4.2.1.0</AssemblyVersion>
|
||||
<AssemblyKey>MSFT</AssemblyKey>
|
||||
<IsNETCoreApp>true</IsNETCoreApp>
|
||||
<IsUAP>true</IsUAP>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -18,13 +18,32 @@ namespace Microsoft.Win32.SafeHandles
|
||||
|
||||
namespace System.Security.Cryptography.X509Certificates
|
||||
{
|
||||
public sealed partial class CertificateRequest
|
||||
{
|
||||
public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.ECDsa key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { }
|
||||
public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.RSA key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { }
|
||||
public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.X509Certificates.PublicKey publicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { }
|
||||
public CertificateRequest(string subjectName, System.Security.Cryptography.ECDsa key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { }
|
||||
public CertificateRequest(string subjectName, System.Security.Cryptography.RSA key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) { }
|
||||
public System.Collections.ObjectModel.Collection<System.Security.Cryptography.X509Certificates.X509Extension> CertificateExtensions { get { throw null; } }
|
||||
public System.Security.Cryptography.HashAlgorithmName HashAlgorithm { get { throw null; } }
|
||||
public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get { throw null; } }
|
||||
public System.Security.Cryptography.X509Certificates.X500DistinguishedName SubjectName { get { throw null; } }
|
||||
public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X500DistinguishedName issuerName, System.Security.Cryptography.X509Certificates.X509SignatureGenerator generator, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, byte[] serialNumber) { throw null; }
|
||||
public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCertificate, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, byte[] serialNumber) { throw null; }
|
||||
public System.Security.Cryptography.X509Certificates.X509Certificate2 CreateSelfSigned(System.DateTimeOffset notBefore, System.DateTimeOffset notAfter) { throw null; }
|
||||
public byte[] CreateSigningRequest() { throw null; }
|
||||
public byte[] CreateSigningRequest(System.Security.Cryptography.X509Certificates.X509SignatureGenerator signatureGenerator) { throw null; }
|
||||
}
|
||||
public static partial class DSACertificateExtensions
|
||||
{
|
||||
public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.DSA privateKey) { throw null; }
|
||||
public static System.Security.Cryptography.DSA GetDSAPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; }
|
||||
public static System.Security.Cryptography.DSA GetDSAPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; }
|
||||
}
|
||||
public static partial class ECDsaCertificateExtensions
|
||||
{
|
||||
public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.ECDsa privateKey) { throw null; }
|
||||
public static System.Security.Cryptography.ECDsa GetECDsaPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; }
|
||||
public static System.Security.Cryptography.ECDsa GetECDsaPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; }
|
||||
}
|
||||
@@ -47,6 +66,7 @@ namespace System.Security.Cryptography.X509Certificates
|
||||
}
|
||||
public static partial class RSACertificateExtensions
|
||||
{
|
||||
public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.RSA privateKey) { throw null; }
|
||||
public static System.Security.Cryptography.RSA GetRSAPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; }
|
||||
public static System.Security.Cryptography.RSA GetRSAPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) { throw null; }
|
||||
}
|
||||
@@ -66,6 +86,16 @@ namespace System.Security.Cryptography.X509Certificates
|
||||
TrustedPeople = 7,
|
||||
TrustedPublisher = 8,
|
||||
}
|
||||
public sealed partial class SubjectAlternativeNameBuilder
|
||||
{
|
||||
public SubjectAlternativeNameBuilder() { }
|
||||
public void AddDnsName(string dnsName) { }
|
||||
public void AddEmailAddress(string emailAddress) { }
|
||||
public void AddIpAddress(System.Net.IPAddress ipAddress) { }
|
||||
public void AddUri(System.Uri uri) { }
|
||||
public void AddUserPrincipalName(string upn) { }
|
||||
public System.Security.Cryptography.X509Certificates.X509Extension Build(bool critical=false) { throw null; }
|
||||
}
|
||||
public sealed partial class X500DistinguishedName : System.Security.Cryptography.AsnEncodedData
|
||||
{
|
||||
public X500DistinguishedName(byte[] encodedDistinguishedName) { }
|
||||
@@ -501,6 +531,16 @@ namespace System.Security.Cryptography.X509Certificates
|
||||
Offline = 2,
|
||||
Online = 1,
|
||||
}
|
||||
public abstract partial class X509SignatureGenerator
|
||||
{
|
||||
protected X509SignatureGenerator() { }
|
||||
public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get { throw null; } }
|
||||
protected abstract System.Security.Cryptography.X509Certificates.PublicKey BuildPublicKey();
|
||||
public static System.Security.Cryptography.X509Certificates.X509SignatureGenerator CreateForECDsa(System.Security.Cryptography.ECDsa key) { throw null; }
|
||||
public static System.Security.Cryptography.X509Certificates.X509SignatureGenerator CreateForRSA(System.Security.Cryptography.RSA key, System.Security.Cryptography.RSASignaturePadding signaturePadding) { throw null; }
|
||||
public abstract byte[] GetSignatureAlgorithmIdentifier(System.Security.Cryptography.HashAlgorithmName hashAlgorithm);
|
||||
public abstract byte[] SignData(byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm);
|
||||
}
|
||||
public sealed partial class X509Store : System.IDisposable
|
||||
{
|
||||
public X509Store() { }
|
||||
@@ -508,9 +548,12 @@ namespace System.Security.Cryptography.X509Certificates
|
||||
public X509Store(System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) { }
|
||||
public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName) { }
|
||||
public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) { }
|
||||
public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation, System.Security.Cryptography.X509Certificates.OpenFlags flags) { }
|
||||
public X509Store(string storeName) { }
|
||||
public X509Store(string storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) { }
|
||||
public X509Store(string storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation, System.Security.Cryptography.X509Certificates.OpenFlags flags) { }
|
||||
public System.Security.Cryptography.X509Certificates.X509Certificate2Collection Certificates { get { throw null; } }
|
||||
public bool IsOpen { get { throw null; } }
|
||||
public System.Security.Cryptography.X509Certificates.StoreLocation Location { get { throw null; } }
|
||||
public string Name { get { throw null; } }
|
||||
public System.IntPtr StoreHandle { get { throw null; } }
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<Compile Include="System.Security.Cryptography.X509Certificates.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\System.Net.Primitives\ref\System.Net.Primitives.csproj" />
|
||||
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
|
||||
<ProjectReference Include="..\..\System.Runtime.InteropServices\ref\System.Runtime.InteropServices.csproj" />
|
||||
<ProjectReference Include="..\..\System.Collections.NonGeneric\ref\System.Collections.NonGeneric.csproj" />
|
||||
@@ -20,4 +21,4 @@
|
||||
<ProjectReference Include="..\..\System.Security.Cryptography.Primitives\ref\System.Security.Cryptography.Primitives.csproj" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
// 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.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
internal static class EncodingHelpers
|
||||
{
|
||||
internal static byte[][] WrapAsSegmentedForSequence(this byte[] derData)
|
||||
{
|
||||
// ConstructSegmentedSequence understands triplets, but doesn't care they're valid,
|
||||
// so lift this up into a "triplet".
|
||||
return new[] { Array.Empty<byte>(), Array.Empty<byte>(), derData };
|
||||
}
|
||||
|
||||
internal static void ValidateSignatureAlgorithm(byte[] signatureAlgorithm)
|
||||
{
|
||||
Debug.Assert(signatureAlgorithm != null);
|
||||
|
||||
// AlgorithmIdentifier ::= SEQUENCE { OBJECT IDENTIFIER, ANY }
|
||||
DerSequenceReader validator = new DerSequenceReader(signatureAlgorithm);
|
||||
validator.ReadOidAsString();
|
||||
|
||||
if (validator.HasData)
|
||||
{
|
||||
validator.ValidateAndSkipDerValue();
|
||||
}
|
||||
|
||||
if (validator.HasData)
|
||||
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
|
||||
}
|
||||
|
||||
internal static byte[][] SegmentedEncodeSubjectPublicKeyInfo(this PublicKey publicKey)
|
||||
{
|
||||
if (publicKey == null)
|
||||
throw new ArgumentNullException(nameof(publicKey));
|
||||
|
||||
if (publicKey.Oid == null ||
|
||||
string.IsNullOrEmpty(publicKey.Oid.Value) ||
|
||||
publicKey.EncodedKeyValue == null)
|
||||
{
|
||||
throw new CryptographicException(SR.Cryptography_InvalidPublicKey_Object);
|
||||
}
|
||||
|
||||
// SubjectPublicKeyInfo::= SEQUENCE {
|
||||
// algorithm AlgorithmIdentifier,
|
||||
// subjectPublicKey BIT STRING
|
||||
// }
|
||||
//
|
||||
// AlgorithmIdentifier::= SEQUENCE {
|
||||
// algorithm OBJECT IDENTIFIER,
|
||||
// parameters ANY DEFINED BY algorithm OPTIONAL
|
||||
// }
|
||||
|
||||
byte[][] algorithmIdentifier;
|
||||
|
||||
if (publicKey.EncodedParameters == null)
|
||||
{
|
||||
algorithmIdentifier = DerEncoder.ConstructSegmentedSequence(
|
||||
DerEncoder.SegmentedEncodeOid(publicKey.Oid));
|
||||
}
|
||||
else
|
||||
{
|
||||
DerSequenceReader validator =
|
||||
DerSequenceReader.CreateForPayload(publicKey.EncodedParameters.RawData);
|
||||
|
||||
validator.ValidateAndSkipDerValue();
|
||||
|
||||
if (validator.HasData)
|
||||
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
|
||||
|
||||
algorithmIdentifier = DerEncoder.ConstructSegmentedSequence(
|
||||
DerEncoder.SegmentedEncodeOid(publicKey.Oid),
|
||||
publicKey.EncodedParameters.RawData.WrapAsSegmentedForSequence());
|
||||
}
|
||||
|
||||
return DerEncoder.ConstructSegmentedSequence(
|
||||
algorithmIdentifier,
|
||||
DerEncoder.SegmentedEncodeBitString(
|
||||
publicKey.EncodedKeyValue.RawData));
|
||||
}
|
||||
|
||||
internal static byte[][] SegmentedEncodedX509Extension(this X509Extension extension)
|
||||
{
|
||||
if (extension.Critical)
|
||||
{
|
||||
return DerEncoder.ConstructSegmentedSequence(
|
||||
DerEncoder.SegmentedEncodeOid(extension.Oid),
|
||||
DerEncoder.SegmentedEncodeBoolean(extension.Critical),
|
||||
DerEncoder.SegmentedEncodeOctetString(extension.RawData));
|
||||
}
|
||||
|
||||
return DerEncoder.ConstructSegmentedSequence(
|
||||
DerEncoder.SegmentedEncodeOid(extension.Oid),
|
||||
DerEncoder.SegmentedEncodeOctetString(extension.RawData));
|
||||
}
|
||||
|
||||
internal static byte[][] SegmentedEncodeAttributeSet(this IEnumerable<X501Attribute> attributes)
|
||||
{
|
||||
List<byte[][]> encodedAttributes = new List<byte[][]>();
|
||||
|
||||
foreach (X501Attribute attribute in attributes)
|
||||
{
|
||||
encodedAttributes.Add(
|
||||
DerEncoder.ConstructSegmentedSequence(
|
||||
DerEncoder.SegmentedEncodeOid(attribute.Oid),
|
||||
DerEncoder.ConstructSegmentedPresortedSet(
|
||||
attribute.RawData.WrapAsSegmentedForSequence())));
|
||||
}
|
||||
|
||||
return DerEncoder.ConstructSegmentedSet(encodedAttributes.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,6 +125,14 @@ namespace Internal.Cryptography
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static void AddRange<T>(this ICollection<T> coll, IEnumerable<T> newData)
|
||||
{
|
||||
foreach (T datum in newData)
|
||||
{
|
||||
coll.Add(datum);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The following group of helpers emulates the non-public Calendar.IsValidDay() method used by X509Certificate.ToString(bool).
|
||||
//
|
||||
@@ -151,4 +159,27 @@ namespace Internal.Cryptography
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal struct PinAndClear : IDisposable
|
||||
{
|
||||
private byte[] _data;
|
||||
private System.Runtime.InteropServices.GCHandle _gcHandle;
|
||||
|
||||
internal static PinAndClear Track(byte[] data)
|
||||
{
|
||||
return new PinAndClear
|
||||
{
|
||||
_gcHandle = System.Runtime.InteropServices.GCHandle.Alloc(
|
||||
data,
|
||||
System.Runtime.InteropServices.GCHandleType.Pinned),
|
||||
_data = data,
|
||||
};
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Array.Clear(_data, 0, _data.Length);
|
||||
_gcHandle.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,5 +36,8 @@ namespace Internal.Cryptography
|
||||
ECDsa GetECDsaPrivateKey();
|
||||
string GetNameInfo(X509NameType nameType, bool forIssuer);
|
||||
void AppendPrivateKeyInfo(StringBuilder sb);
|
||||
ICertificatePal CopyWithPrivateKey(DSA privateKey);
|
||||
ICertificatePal CopyWithPrivateKey(ECDsa privateKey);
|
||||
ICertificatePal CopyWithPrivateKey(RSA privateKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,6 @@
|
||||
// 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.Text;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
//
|
||||
@@ -31,8 +25,23 @@ namespace Internal.Cryptography
|
||||
public const string CertPolicyConstraints = "2.5.29.36";
|
||||
public const string EnhancedKeyUsage = "2.5.29.37";
|
||||
public const string InhibitAnyPolicyExtension = "2.5.29.54";
|
||||
public const string Sha256 = "2.16.840.1.101.3.4.2.1";
|
||||
public const string Sha384 = "2.16.840.1.101.3.4.2.2";
|
||||
public const string Sha512 = "2.16.840.1.101.3.4.2.3";
|
||||
public const string EccCurveSecp384r1 = "1.3.132.0.34";
|
||||
public const string EccCurveSecp521r1 = "1.3.132.0.35";
|
||||
public const string Ecc = "1.2.840.10045.2.1";
|
||||
public const string EccCurveSecp256r1 = "1.2.840.10045.3.1.7";
|
||||
public const string ECDsaSha256 = "1.2.840.10045.4.3.2";
|
||||
public const string ECDsaSha384 = "1.2.840.10045.4.3.3";
|
||||
public const string ECDsaSha512 = "1.2.840.10045.4.3.4";
|
||||
public const string RsaRsa = "1.2.840.113549.1.1.1";
|
||||
public const string Mgf1 = "1.2.840.113549.1.1.8";
|
||||
public const string RsaSsaPss = "1.2.840.113549.1.1.10";
|
||||
public const string RsaPkcs1Sha256 = "1.2.840.113549.1.1.11";
|
||||
public const string RsaPkcs1Sha384 = "1.2.840.113549.1.1.12";
|
||||
public const string RsaPkcs1Sha512 = "1.2.840.113549.1.1.13";
|
||||
public const string Pkcs9ExtensionRequest = "1.2.840.113549.1.9.14";
|
||||
public const string DsaDsa = "1.2.840.10040.4.1";
|
||||
public const string EmailAddress = "1.2.840.113549.1.9.1";
|
||||
public const string EnrollCertTypeExtension = "1.3.6.1.4.1.311.20.2";
|
||||
|
||||
@@ -59,7 +59,9 @@ namespace Internal.Cryptography.Pal
|
||||
{
|
||||
Debug.Assert(cert.Pal != null);
|
||||
|
||||
return FromHandle(cert.Handle);
|
||||
ICertificatePal pal = FromHandle(cert.Handle);
|
||||
GC.KeepAlive(cert); // ensure cert's safe handle isn't finalized while raw handle is in use
|
||||
return pal;
|
||||
}
|
||||
|
||||
public static ICertificatePal FromBlob(
|
||||
@@ -153,6 +155,9 @@ namespace Internal.Cryptography.Pal
|
||||
internal sealed class AppleCertificatePal : ICertificatePal
|
||||
{
|
||||
private SafeSecIdentityHandle _identityHandle;
|
||||
// Do not give out this reference, it's only needed in certain cases to prevent temporary keychains
|
||||
// from being deleted.
|
||||
private SafeSecKeyRefHandle _privateKeyHolder;
|
||||
private SafeSecCertificateHandle _certHandle;
|
||||
private CertificateData _certData;
|
||||
private bool _readCertData;
|
||||
@@ -176,9 +181,11 @@ namespace Internal.Cryptography.Pal
|
||||
{
|
||||
_certHandle?.Dispose();
|
||||
_identityHandle?.Dispose();
|
||||
_privateKeyHolder?.Dispose();
|
||||
|
||||
_certHandle = null;
|
||||
_identityHandle = null;
|
||||
_privateKeyHolder = null;
|
||||
}
|
||||
|
||||
internal SafeSecCertificateHandle CertificateHandle => _certHandle;
|
||||
@@ -358,21 +365,6 @@ namespace Internal.Cryptography.Pal
|
||||
}
|
||||
}
|
||||
|
||||
public AsymmetricAlgorithm GetPrivateKey()
|
||||
{
|
||||
switch (KeyAlgorithm)
|
||||
{
|
||||
case Oids.RsaRsa:
|
||||
return GetRSAPrivateKey();
|
||||
case Oids.DsaDsa:
|
||||
return GetDSAPrivateKey();
|
||||
case Oids.Ecc:
|
||||
return GetECDsaPrivateKey();
|
||||
}
|
||||
|
||||
throw new NotSupportedException(SR.NotSupported_KeyAlgorithm);
|
||||
}
|
||||
|
||||
public RSA GetRSAPrivateKey()
|
||||
{
|
||||
if (_identityHandle == null)
|
||||
@@ -409,6 +401,103 @@ namespace Internal.Cryptography.Pal
|
||||
return new ECDsaImplementation.ECDsaSecurityTransforms(publicKey, privateKey);
|
||||
}
|
||||
|
||||
private void HoldPrivateKey()
|
||||
{
|
||||
_privateKeyHolder = Interop.AppleCrypto.X509GetPrivateKeyFromIdentity(_identityHandle);
|
||||
Debug.Assert(!_privateKeyHolder.IsInvalid);
|
||||
}
|
||||
|
||||
public ICertificatePal CopyWithPrivateKey(DSA privateKey)
|
||||
{
|
||||
var typedKey = privateKey as DSAImplementation.DSASecurityTransforms;
|
||||
|
||||
if (typedKey != null)
|
||||
{
|
||||
return CopyWithPrivateKey(typedKey.GetKeys());
|
||||
}
|
||||
|
||||
DSAParameters dsaParameters = privateKey.ExportParameters(true);
|
||||
|
||||
using (PinAndClear.Track(dsaParameters.X))
|
||||
using (typedKey = new DSAImplementation.DSASecurityTransforms())
|
||||
{
|
||||
typedKey.ImportParameters(dsaParameters);
|
||||
return CopyWithPrivateKey(typedKey.GetKeys());
|
||||
}
|
||||
}
|
||||
|
||||
public ICertificatePal CopyWithPrivateKey(ECDsa privateKey)
|
||||
{
|
||||
var typedKey = privateKey as ECDsaImplementation.ECDsaSecurityTransforms;
|
||||
|
||||
if (typedKey != null)
|
||||
{
|
||||
return CopyWithPrivateKey(typedKey.GetKeys());
|
||||
}
|
||||
|
||||
ECParameters ecParameters = privateKey.ExportParameters(true);
|
||||
|
||||
using (PinAndClear.Track(ecParameters.D))
|
||||
using (typedKey = new ECDsaImplementation.ECDsaSecurityTransforms())
|
||||
{
|
||||
typedKey.ImportParameters(ecParameters);
|
||||
return CopyWithPrivateKey(typedKey.GetKeys());
|
||||
}
|
||||
}
|
||||
|
||||
public ICertificatePal CopyWithPrivateKey(RSA privateKey)
|
||||
{
|
||||
var typedKey = privateKey as RSAImplementation.RSASecurityTransforms;
|
||||
|
||||
if (typedKey != null)
|
||||
{
|
||||
return CopyWithPrivateKey(typedKey.GetKeys());
|
||||
}
|
||||
|
||||
RSAParameters rsaParameters = privateKey.ExportParameters(true);
|
||||
|
||||
using (PinAndClear.Track(rsaParameters.D))
|
||||
using (PinAndClear.Track(rsaParameters.P))
|
||||
using (PinAndClear.Track(rsaParameters.Q))
|
||||
using (PinAndClear.Track(rsaParameters.DP))
|
||||
using (PinAndClear.Track(rsaParameters.DQ))
|
||||
using (PinAndClear.Track(rsaParameters.InverseQ))
|
||||
using (typedKey = new RSAImplementation.RSASecurityTransforms())
|
||||
{
|
||||
typedKey.ImportParameters(rsaParameters);
|
||||
return CopyWithPrivateKey(typedKey.GetKeys());
|
||||
}
|
||||
}
|
||||
|
||||
private ICertificatePal CopyWithPrivateKey(SecKeyPair keyPair)
|
||||
{
|
||||
if (keyPair.PrivateKey == null)
|
||||
{
|
||||
// Both Windows and Linux/OpenSSL are unaware if they bound a public or private key.
|
||||
// Here, we do know. So throw if we can't do what they asked.
|
||||
throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey);
|
||||
}
|
||||
|
||||
SafeKeychainHandle keychain = Interop.AppleCrypto.SecKeychainItemCopyKeychain(keyPair.PrivateKey);
|
||||
|
||||
if (keychain.IsInvalid)
|
||||
{
|
||||
keychain = Interop.AppleCrypto.CreateTemporaryKeychain();
|
||||
}
|
||||
|
||||
using (keychain)
|
||||
{
|
||||
SafeSecIdentityHandle identityHandle = Interop.AppleCrypto.X509CopyWithPrivateKey(
|
||||
_certHandle,
|
||||
keyPair.PrivateKey,
|
||||
keychain);
|
||||
|
||||
AppleCertificatePal newPal = new AppleCertificatePal(identityHandle);
|
||||
newPal.HoldPrivateKey();
|
||||
return newPal;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetNameInfo(X509NameType nameType, bool forIssuer)
|
||||
{
|
||||
// Algorithm behaviors (pseudocode). When forIssuer is true, replace "Subject" with "Issuer" and
|
||||
|
||||
@@ -14,11 +14,17 @@ namespace Internal.Cryptography.Pal
|
||||
{
|
||||
internal sealed class SecTrustChainPal : IChainPal
|
||||
{
|
||||
private const X509ChainStatusFlags RevocationRelevantFlags =
|
||||
X509ChainStatusFlags.RevocationStatusUnknown |
|
||||
X509ChainStatusFlags.Revoked |
|
||||
X509ChainStatusFlags.OfflineRevocation;
|
||||
|
||||
private Stack<SafeHandle> _extraHandles;
|
||||
private SafeX509ChainHandle _chainHandle;
|
||||
public X509ChainElement[] ChainElements { get; private set; }
|
||||
public X509ChainStatus[] ChainStatus { get; private set; }
|
||||
private DateTime _verificationTime;
|
||||
private X509RevocationMode _revocationMode;
|
||||
|
||||
internal SecTrustChainPal()
|
||||
{
|
||||
@@ -30,9 +36,10 @@ namespace Internal.Cryptography.Pal
|
||||
internal void OpenTrustHandle(
|
||||
ICertificatePal leafCert,
|
||||
X509Certificate2Collection extraStore,
|
||||
bool checkRevocation)
|
||||
X509RevocationMode revocationMode)
|
||||
{
|
||||
SafeCreateHandle policiesArray = PreparePoliciesArray(checkRevocation);
|
||||
_revocationMode = revocationMode;
|
||||
SafeCreateHandle policiesArray = PreparePoliciesArray(revocationMode != X509RevocationMode.NoCheck);
|
||||
SafeCreateHandle certsArray = PrepareCertsArray(leafCert, extraStore);
|
||||
|
||||
int osStatus;
|
||||
@@ -173,7 +180,8 @@ namespace Internal.Cryptography.Pal
|
||||
DateTime verificationTime,
|
||||
bool allowNetwork,
|
||||
OidCollection applicationPolicy,
|
||||
OidCollection certificatePolicy)
|
||||
OidCollection certificatePolicy,
|
||||
X509RevocationFlag revocationFlag)
|
||||
{
|
||||
int osStatus;
|
||||
|
||||
@@ -199,7 +207,8 @@ namespace Internal.Cryptography.Pal
|
||||
throw new CryptographicException();
|
||||
}
|
||||
|
||||
Tuple<X509Certificate2, int>[] elements = ParseResults(_chainHandle);
|
||||
Tuple<X509Certificate2, int>[] elements = ParseResults(_chainHandle, _revocationMode);
|
||||
Debug.Assert(elements.Length > 0);
|
||||
|
||||
if (!IsPolicyMatch(elements, applicationPolicy, certificatePolicy))
|
||||
{
|
||||
@@ -210,10 +219,13 @@ namespace Internal.Cryptography.Pal
|
||||
currentValue.Item2 | (int)X509ChainStatusFlags.NotValidForUsage);
|
||||
}
|
||||
|
||||
FixupRevocationStatus(elements, revocationFlag);
|
||||
BuildAndSetProperties(elements);
|
||||
}
|
||||
|
||||
private static Tuple<X509Certificate2,int>[] ParseResults(SafeX509ChainHandle chainHandle)
|
||||
private static Tuple<X509Certificate2, int>[] ParseResults(
|
||||
SafeX509ChainHandle chainHandle,
|
||||
X509RevocationMode revocationMode)
|
||||
{
|
||||
long elementCount = Interop.AppleCrypto.X509ChainGetChainSize(chainHandle);
|
||||
var elements = new Tuple<X509Certificate2, int>[elementCount];
|
||||
@@ -238,7 +250,7 @@ namespace Internal.Cryptography.Pal
|
||||
|
||||
X509Certificate2 cert = new X509Certificate2(certHandle);
|
||||
|
||||
FixupStatus(cert, ref dwStatus);
|
||||
FixupStatus(cert, revocationMode, ref dwStatus);
|
||||
|
||||
elements[elementIdx] = Tuple.Create(cert, dwStatus);
|
||||
}
|
||||
@@ -302,7 +314,47 @@ namespace Internal.Cryptography.Pal
|
||||
ChainStatus = rollupElement.ChainElementStatus;
|
||||
}
|
||||
|
||||
private static void FixupStatus(X509Certificate2 cert, ref int dwStatus)
|
||||
private static void FixupRevocationStatus(
|
||||
Tuple<X509Certificate2, int>[] elements,
|
||||
X509RevocationFlag revocationFlag)
|
||||
{
|
||||
if (revocationFlag == X509RevocationFlag.ExcludeRoot)
|
||||
{
|
||||
// When requested
|
||||
int idx = elements.Length - 1;
|
||||
Tuple<X509Certificate2, int> element = elements[idx];
|
||||
X509ChainStatusFlags statusFlags = (X509ChainStatusFlags)element.Item2;
|
||||
|
||||
// Apple will terminate the chain at the first "root" or "trustAsRoot" certificate
|
||||
// it finds, which it refers to as "anchors". We'll consider a "trustAsRoot" cert
|
||||
// as a root for the purposes of ExcludeRoot. So as long as the last element doesn't
|
||||
// have PartialChain consider it the root.
|
||||
if ((statusFlags & X509ChainStatusFlags.PartialChain) == 0)
|
||||
{
|
||||
statusFlags &= ~RevocationRelevantFlags;
|
||||
elements[idx] = Tuple.Create(element.Item1, (int)statusFlags);
|
||||
}
|
||||
}
|
||||
else if (revocationFlag == X509RevocationFlag.EndCertificateOnly)
|
||||
{
|
||||
// In Windows the EndCertificateOnly flag (CERT_CHAIN_REVOCATION_CHECK_END_CERT) will apply
|
||||
// to a root if that's the only element, so we'll do the same.
|
||||
// Start at element 1, and move to the end.
|
||||
for (int i = 1; i < elements.Length; i++)
|
||||
{
|
||||
Tuple<X509Certificate2, int> element = elements[i];
|
||||
X509ChainStatusFlags statusFlags = (X509ChainStatusFlags)element.Item2;
|
||||
|
||||
statusFlags &= ~RevocationRelevantFlags;
|
||||
elements[i] = Tuple.Create(element.Item1, (int)statusFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void FixupStatus(
|
||||
X509Certificate2 cert,
|
||||
X509RevocationMode revocationMode,
|
||||
ref int dwStatus)
|
||||
{
|
||||
X509ChainStatusFlags flags = (X509ChainStatusFlags)dwStatus;
|
||||
|
||||
@@ -318,6 +370,15 @@ namespace Internal.Cryptography.Pal
|
||||
dwStatus = (int)flags;
|
||||
}
|
||||
}
|
||||
|
||||
if (revocationMode == X509RevocationMode.NoCheck)
|
||||
{
|
||||
// Clear any revocation-related flags if NoCheck was requested, since
|
||||
// the OS may use cached results opportunistically.
|
||||
flags &= ~RevocationRelevantFlags;
|
||||
|
||||
dwStatus = (int)flags;
|
||||
}
|
||||
}
|
||||
|
||||
private static X509ChainStatusFlags FindUntrustedRootReason(X509Certificate2 cert)
|
||||
@@ -501,14 +562,18 @@ namespace Internal.Cryptography.Pal
|
||||
// or off (and AIA fetching doesn't work). And once an SSL policy is used, or revocation is
|
||||
// being checked, the value is on anyways.
|
||||
const bool allowNetwork = true;
|
||||
bool checkRevocation = revocationMode != X509RevocationMode.NoCheck;
|
||||
|
||||
SecTrustChainPal chainPal = new SecTrustChainPal();
|
||||
|
||||
try
|
||||
{
|
||||
chainPal.OpenTrustHandle(cert, extraStore, checkRevocation);
|
||||
chainPal.Execute(verificationTime, allowNetwork, applicationPolicy, certificatePolicy);
|
||||
chainPal.OpenTrustHandle(cert, extraStore, revocationMode);
|
||||
|
||||
chainPal.Execute(
|
||||
verificationTime,
|
||||
allowNetwork,
|
||||
applicationPolicy,
|
||||
certificatePolicy,
|
||||
revocationFlag);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// 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.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
@@ -57,7 +58,9 @@ namespace Internal.Cryptography.Pal
|
||||
|
||||
protected override X509Certificate2 CloneCertificate(X509Certificate2 cert)
|
||||
{
|
||||
return new X509Certificate2(cert.Handle);
|
||||
var clone = new X509Certificate2(cert.Handle);
|
||||
GC.KeepAlive(cert); // ensure cert's safe handle isn't finalized while raw handle is in use
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,9 @@ namespace Internal.Cryptography.Pal
|
||||
}
|
||||
}
|
||||
|
||||
return Interop.AppleCrypto.X509ExportPfx(certHandles, password);
|
||||
byte[] exported = Interop.AppleCrypto.X509ExportPfx(certHandles, password);
|
||||
GC.KeepAlive(_certs); // ensure certs' safe handles aren't finalized while raw handles are in use
|
||||
return exported;
|
||||
}
|
||||
|
||||
private byte[] ExportPkcs7()
|
||||
|
||||
@@ -123,11 +123,12 @@ namespace Internal.Cryptography.Pal
|
||||
if ((openFlags & OpenFlags.OpenExistingOnly) == OpenFlags.OpenExistingOnly)
|
||||
throw new CryptographicException(SR.Cryptography_X509_StoreNotFound);
|
||||
|
||||
throw new PlatformNotSupportedException(
|
||||
SR.Format(
|
||||
SR.Cryptography_X509_StoreCannotCreate,
|
||||
storeName,
|
||||
storeLocation));
|
||||
string message = SR.Format(
|
||||
SR.Cryptography_X509_StoreCannotCreate,
|
||||
storeName,
|
||||
storeLocation);
|
||||
|
||||
throw new CryptographicException(message, new PlatformNotSupportedException(message));
|
||||
}
|
||||
|
||||
private static void ReadCollection(SafeCFArrayHandle matches, HashSet<X509Certificate2> collection)
|
||||
|
||||
@@ -49,10 +49,17 @@ namespace Internal.Cryptography.Pal
|
||||
verificationTime = verificationTime.ToLocalTime();
|
||||
}
|
||||
|
||||
// Until we support the Disallowed store, ensure it's empty (which is done by the ctor)
|
||||
using (new X509Store(StoreName.Disallowed, StoreLocation.CurrentUser, OpenFlags.ReadOnly))
|
||||
{
|
||||
}
|
||||
|
||||
TimeSpan remainingDownloadTime = timeout;
|
||||
|
||||
using (var leaf = new X509Certificate2(cert.Handle))
|
||||
{
|
||||
GC.KeepAlive(cert); // ensure cert's safe handle isn't finalized while raw handle is in use
|
||||
|
||||
var downloaded = new HashSet<X509Certificate2>();
|
||||
var systemTrusted = new HashSet<X509Certificate2>();
|
||||
|
||||
@@ -66,7 +73,6 @@ namespace Internal.Cryptography.Pal
|
||||
IChainPal chain = OpenSslX509ChainProcessor.BuildChain(
|
||||
leaf,
|
||||
candidates,
|
||||
downloaded,
|
||||
systemTrusted,
|
||||
applicationPolicy,
|
||||
certificatePolicy,
|
||||
|
||||
@@ -48,19 +48,9 @@ namespace Internal.Cryptography.Pal
|
||||
throw new CryptographicException(SR.Arg_EmptyOrNullString);
|
||||
}
|
||||
|
||||
string directoryName = GetDirectoryName(storeName);
|
||||
Debug.Assert(!X509Store.DisallowedStoreName.Equals(storeName, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (s_userStoreRoot == null)
|
||||
{
|
||||
// Do this here instead of a static field initializer so that
|
||||
// the static initializer isn't capable of throwing the "home directory not found"
|
||||
// exception.
|
||||
s_userStoreRoot = PersistedFiles.GetUserFeatureDirectory(
|
||||
X509Persistence.CryptographyFeatureName,
|
||||
X509Persistence.X509StoresSubFeatureName);
|
||||
}
|
||||
|
||||
_storePath = Path.Combine(s_userStoreRoot, directoryName);
|
||||
_storePath = GetStorePath(storeName);
|
||||
|
||||
if (0 != (openFlags & OpenFlags.OpenExistingOnly))
|
||||
{
|
||||
@@ -283,6 +273,23 @@ namespace Internal.Cryptography.Pal
|
||||
throw new CryptographicException(SR.Cryptography_X509_StoreNoFileAvailable);
|
||||
}
|
||||
|
||||
private static string GetStorePath(string storeName)
|
||||
{
|
||||
string directoryName = GetDirectoryName(storeName);
|
||||
|
||||
if (s_userStoreRoot == null)
|
||||
{
|
||||
// Do this here instead of a static field initializer so that
|
||||
// the static initializer isn't capable of throwing the "home directory not found"
|
||||
// exception.
|
||||
s_userStoreRoot = PersistedFiles.GetUserFeatureDirectory(
|
||||
X509Persistence.CryptographyFeatureName,
|
||||
X509Persistence.X509StoresSubFeatureName);
|
||||
}
|
||||
|
||||
return Path.Combine(s_userStoreRoot, directoryName);
|
||||
}
|
||||
|
||||
private static string GetDirectoryName(string storeName)
|
||||
{
|
||||
Debug.Assert(storeName != null);
|
||||
@@ -379,10 +386,87 @@ namespace Internal.Cryptography.Pal
|
||||
new IOException(error.GetErrorMessage(), error.RawErrno));
|
||||
}
|
||||
|
||||
Debug.Assert(Interop.Sys.FStat(stream.SafeFileHandle, out stat) == 0);
|
||||
Debug.Assert((stat.Mode & (int)requiredPermissions) == (int)requiredPermissions);
|
||||
Debug.Assert((stat.Mode & (int)forbiddenPermissions) == 0);
|
||||
// Verify the chmod applied.
|
||||
if (Interop.Sys.FStat(stream.SafeFileHandle, out stat) != 0)
|
||||
{
|
||||
Interop.ErrorInfo error = Interop.Sys.GetLastErrorInfo();
|
||||
throw new CryptographicException(
|
||||
SR.Cryptography_FileStatusError,
|
||||
new IOException(error.GetErrorMessage(), error.RawErrno));
|
||||
}
|
||||
|
||||
if ((stat.Mode & (int)requiredPermissions) != (int)requiredPermissions ||
|
||||
(stat.Mode & (int)forbiddenPermissions) != 0)
|
||||
{
|
||||
throw new CryptographicException(SR.Format(SR.Cryptography_InvalidFilePermissions, stream.Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class UnsupportedDisallowedStore : IStorePal
|
||||
{
|
||||
private readonly bool _readOnly;
|
||||
|
||||
internal UnsupportedDisallowedStore(OpenFlags openFlags)
|
||||
{
|
||||
// ReadOnly is 0x00, so it is implicit unless either ReadWrite or MaxAllowed
|
||||
// was requested.
|
||||
OpenFlags writeFlags = openFlags & (OpenFlags.ReadWrite | OpenFlags.MaxAllowed);
|
||||
|
||||
if (writeFlags == OpenFlags.ReadOnly)
|
||||
{
|
||||
_readOnly = true;
|
||||
}
|
||||
|
||||
string storePath = GetStorePath(X509Store.DisallowedStoreName);
|
||||
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(storePath))
|
||||
{
|
||||
// If it has no files, leave it alone.
|
||||
foreach (string filePath in Directory.EnumerateFiles(storePath))
|
||||
{
|
||||
string msg = SR.Format(SR.Cryptography_Unix_X509_DisallowedStoreNotEmpty, storePath);
|
||||
throw new CryptographicException(msg, new PlatformNotSupportedException(msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
// Suppress the exception, treat the store as empty.
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
public void CloneTo(X509Certificate2Collection collection)
|
||||
{
|
||||
// Never show any data.
|
||||
}
|
||||
|
||||
public void Add(ICertificatePal cert)
|
||||
{
|
||||
if (_readOnly)
|
||||
{
|
||||
throw new CryptographicException(SR.Cryptography_X509_StoreReadOnly);
|
||||
}
|
||||
|
||||
throw new CryptographicException(
|
||||
SR.Cryptography_Unix_X509_NoDisallowedStore,
|
||||
new PlatformNotSupportedException(SR.Cryptography_Unix_X509_NoDisallowedStore));
|
||||
}
|
||||
|
||||
public void Remove(ICertificatePal cert)
|
||||
{
|
||||
// Remove never throws if it does no measurable work.
|
||||
// Since CloneTo always says the store is empty, no measurable work is ever done.
|
||||
}
|
||||
|
||||
SafeHandle IStorePal.SafeHandle { get; } = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,8 @@ namespace Internal.Cryptography.Pal
|
||||
{
|
||||
PushHandle(certPal.Handle, publicCerts);
|
||||
}
|
||||
|
||||
GC.KeepAlive(certPal); // ensure reader's safe handle isn't finalized while raw handle is in use
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -120,6 +122,8 @@ namespace Internal.Cryptography.Pal
|
||||
{
|
||||
PushHandle(cert.Handle, publicCerts);
|
||||
}
|
||||
|
||||
GC.KeepAlive(cert); // ensure cert's safe handle isn't finalized while raw handle is in use
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,6 +179,8 @@ namespace Internal.Cryptography.Pal
|
||||
{
|
||||
throw Interop.Crypto.CreateOpenSslCryptographicException();
|
||||
}
|
||||
|
||||
GC.KeepAlive(cert); // ensure cert's safe handle isn't finalized while raw handle is in use
|
||||
}
|
||||
|
||||
return Interop.Crypto.OpenSslEncode(
|
||||
|
||||
@@ -295,6 +295,78 @@ namespace Internal.Cryptography.Pal
|
||||
return new ECDsaOpenSsl(_privateKey);
|
||||
}
|
||||
|
||||
private ICertificatePal CopyWithPrivateKey(SafeEvpPKeyHandle privateKey)
|
||||
{
|
||||
// This could be X509Duplicate for a full clone, but since OpenSSL certificates
|
||||
// are functionally immutable (unlike Windows ones) an UpRef is sufficient.
|
||||
SafeX509Handle certHandle = Interop.Crypto.X509UpRef(_cert);
|
||||
OpenSslX509CertificateReader duplicate = new OpenSslX509CertificateReader(certHandle);
|
||||
|
||||
duplicate.SetPrivateKey(privateKey);
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
public ICertificatePal CopyWithPrivateKey(DSA privateKey)
|
||||
{
|
||||
DSAOpenSsl typedKey = privateKey as DSAOpenSsl;
|
||||
|
||||
if (typedKey != null)
|
||||
{
|
||||
return CopyWithPrivateKey((SafeEvpPKeyHandle)typedKey.DuplicateKeyHandle());
|
||||
}
|
||||
|
||||
DSAParameters dsaParameters = privateKey.ExportParameters(true);
|
||||
|
||||
using (PinAndClear.Track(dsaParameters.X))
|
||||
using (typedKey = new DSAOpenSsl(dsaParameters))
|
||||
{
|
||||
return CopyWithPrivateKey((SafeEvpPKeyHandle)typedKey.DuplicateKeyHandle());
|
||||
}
|
||||
}
|
||||
|
||||
public ICertificatePal CopyWithPrivateKey(ECDsa privateKey)
|
||||
{
|
||||
ECDsaOpenSsl typedKey = privateKey as ECDsaOpenSsl;
|
||||
|
||||
if (typedKey != null)
|
||||
{
|
||||
return CopyWithPrivateKey((SafeEvpPKeyHandle)typedKey.DuplicateKeyHandle());
|
||||
}
|
||||
|
||||
ECParameters ecParameters = privateKey.ExportParameters(true);
|
||||
|
||||
using (PinAndClear.Track(ecParameters.D))
|
||||
using (typedKey = new ECDsaOpenSsl())
|
||||
{
|
||||
typedKey.ImportParameters(ecParameters);
|
||||
|
||||
return CopyWithPrivateKey((SafeEvpPKeyHandle)typedKey.DuplicateKeyHandle());
|
||||
}
|
||||
}
|
||||
|
||||
public ICertificatePal CopyWithPrivateKey(RSA privateKey)
|
||||
{
|
||||
RSAOpenSsl typedKey = privateKey as RSAOpenSsl;
|
||||
|
||||
if (typedKey != null)
|
||||
{
|
||||
return CopyWithPrivateKey((SafeEvpPKeyHandle)typedKey.DuplicateKeyHandle());
|
||||
}
|
||||
|
||||
RSAParameters rsaParameters = privateKey.ExportParameters(true);
|
||||
|
||||
using (PinAndClear.Track(rsaParameters.D))
|
||||
using (PinAndClear.Track(rsaParameters.P))
|
||||
using (PinAndClear.Track(rsaParameters.Q))
|
||||
using (PinAndClear.Track(rsaParameters.DP))
|
||||
using (PinAndClear.Track(rsaParameters.DQ))
|
||||
using (PinAndClear.Track(rsaParameters.InverseQ))
|
||||
using (typedKey = new RSAOpenSsl(rsaParameters))
|
||||
{
|
||||
return CopyWithPrivateKey((SafeEvpPKeyHandle)typedKey.DuplicateKeyHandle());
|
||||
}
|
||||
}
|
||||
|
||||
public string GetNameInfo(X509NameType nameType, bool forIssuer)
|
||||
{
|
||||
using (SafeBioHandle bioHandle = Interop.Crypto.GetX509NameInfo(_cert, (int)nameType, forIssuer))
|
||||
|
||||
@@ -37,7 +37,6 @@ namespace Internal.Cryptography.Pal
|
||||
public static IChainPal BuildChain(
|
||||
X509Certificate2 leaf,
|
||||
HashSet<X509Certificate2> candidates,
|
||||
HashSet<X509Certificate2> downloaded,
|
||||
HashSet<X509Certificate2> systemTrusted,
|
||||
OidCollection applicationPolicy,
|
||||
OidCollection certificatePolicy,
|
||||
@@ -57,9 +56,11 @@ namespace Internal.Cryptography.Pal
|
||||
// (If you need to think of it as an X509Store, it's a volatile memory store)
|
||||
using (SafeX509StoreHandle store = Interop.Crypto.X509StoreCreate())
|
||||
using (SafeX509StoreCtxHandle storeCtx = Interop.Crypto.X509StoreCtxCreate())
|
||||
using (SafeX509StackHandle extraCerts = Interop.Crypto.NewX509Stack())
|
||||
{
|
||||
Interop.Crypto.CheckValidOpenSslHandle(store);
|
||||
Interop.Crypto.CheckValidOpenSslHandle(storeCtx);
|
||||
Interop.Crypto.CheckValidOpenSslHandle(extraCerts);
|
||||
|
||||
bool lookupCrl = revocationMode != X509RevocationMode.NoCheck;
|
||||
|
||||
@@ -67,9 +68,15 @@ namespace Internal.Cryptography.Pal
|
||||
{
|
||||
OpenSslX509CertificateReader pal = (OpenSslX509CertificateReader)cert.Pal;
|
||||
|
||||
if (!Interop.Crypto.X509StoreAddCert(store, pal.SafeHandle))
|
||||
using (SafeX509Handle handle = Interop.Crypto.X509UpRef(pal.SafeHandle))
|
||||
{
|
||||
throw Interop.Crypto.CreateOpenSslCryptographicException();
|
||||
if (!Interop.Crypto.PushX509StackField(extraCerts, handle))
|
||||
{
|
||||
throw Interop.Crypto.CreateOpenSslCryptographicException();
|
||||
}
|
||||
|
||||
// Ownership was transferred to the cert stack.
|
||||
handle.SetHandleAsInvalid();
|
||||
}
|
||||
|
||||
if (lookupCrl)
|
||||
@@ -95,9 +102,19 @@ namespace Internal.Cryptography.Pal
|
||||
}
|
||||
}
|
||||
|
||||
foreach (X509Certificate2 trustedCert in systemTrusted)
|
||||
{
|
||||
OpenSslX509CertificateReader pal = (OpenSslX509CertificateReader)trustedCert.Pal;
|
||||
|
||||
if (!Interop.Crypto.X509StoreAddCert(store, pal.SafeHandle))
|
||||
{
|
||||
throw Interop.Crypto.CreateOpenSslCryptographicException();
|
||||
}
|
||||
}
|
||||
|
||||
SafeX509Handle leafHandle = ((OpenSslX509CertificateReader)leaf.Pal).SafeHandle;
|
||||
|
||||
if (!Interop.Crypto.X509StoreCtxInit(storeCtx, store, leafHandle))
|
||||
if (!Interop.Crypto.X509StoreCtxInit(storeCtx, store, leafHandle, extraCerts))
|
||||
{
|
||||
throw Interop.Crypto.CreateOpenSslCryptographicException();
|
||||
}
|
||||
@@ -144,22 +161,6 @@ namespace Internal.Cryptography.Pal
|
||||
|
||||
// Duplicate the certificate handle
|
||||
X509Certificate2 elementCert = new X509Certificate2(elementCertPtr);
|
||||
|
||||
// If the last cert is self signed then it's the root cert, do any extra checks.
|
||||
if (i == maybeRootDepth && IsSelfSigned(elementCert))
|
||||
{
|
||||
// If the root certificate was downloaded or the system
|
||||
// doesn't trust it, it's untrusted.
|
||||
if (downloaded.Contains(elementCert) ||
|
||||
!systemTrusted.Contains(elementCert))
|
||||
{
|
||||
AddElementStatus(
|
||||
Interop.Crypto.X509VerifyStatusCode.X509_V_ERR_CERT_UNTRUSTED,
|
||||
status,
|
||||
overallStatus);
|
||||
}
|
||||
}
|
||||
|
||||
elements[i] = new X509ChainElement(elementCert, status.ToArray(), "");
|
||||
}
|
||||
}
|
||||
@@ -416,8 +417,6 @@ namespace Internal.Cryptography.Pal
|
||||
extraStore,
|
||||
userIntermediateCerts,
|
||||
systemIntermediateCerts,
|
||||
userRootCerts,
|
||||
systemRootCerts,
|
||||
};
|
||||
|
||||
while (toProcess.Count > 0)
|
||||
@@ -629,7 +628,7 @@ namespace Internal.Cryptography.Pal
|
||||
|
||||
internal int VerifyCallback(int ok, IntPtr ctx)
|
||||
{
|
||||
if (ok < 0)
|
||||
if (ok != 0)
|
||||
{
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Internal.Cryptography.Pal
|
||||
{
|
||||
@@ -136,14 +137,23 @@ namespace Internal.Cryptography.Pal
|
||||
|
||||
public static IStorePal FromSystemStore(string storeName, StoreLocation storeLocation, OpenFlags openFlags)
|
||||
{
|
||||
if (storeLocation != StoreLocation.LocalMachine)
|
||||
if (storeLocation == StoreLocation.CurrentUser)
|
||||
{
|
||||
if (X509Store.DisallowedStoreName.Equals(storeName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new DirectoryBasedStoreProvider.UnsupportedDisallowedStore(openFlags);
|
||||
}
|
||||
|
||||
return new DirectoryBasedStoreProvider(storeName, openFlags);
|
||||
}
|
||||
|
||||
Debug.Assert(storeLocation == StoreLocation.LocalMachine);
|
||||
|
||||
if ((openFlags & OpenFlags.ReadWrite) == OpenFlags.ReadWrite)
|
||||
{
|
||||
throw new PlatformNotSupportedException(SR.Cryptography_Unix_X509_MachineStoresReadOnly);
|
||||
throw new CryptographicException(
|
||||
SR.Cryptography_Unix_X509_MachineStoresReadOnly,
|
||||
new PlatformNotSupportedException(SR.Cryptography_Unix_X509_MachineStoresReadOnly));
|
||||
}
|
||||
|
||||
// The static store approach here is making an optimization based on not
|
||||
@@ -160,17 +170,19 @@ namespace Internal.Cryptography.Pal
|
||||
}
|
||||
}
|
||||
|
||||
if (StringComparer.Ordinal.Equals("Root", storeName))
|
||||
if (X509Store.RootStoreName.Equals(storeName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return s_machineRootStore;
|
||||
}
|
||||
|
||||
if (StringComparer.Ordinal.Equals("CA", storeName))
|
||||
if (X509Store.IntermediateCAStoreName.Equals(storeName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return s_machineIntermediateStore;
|
||||
}
|
||||
|
||||
throw new PlatformNotSupportedException(SR.Cryptography_Unix_X509_MachineStoresRootOnly);
|
||||
throw new CryptographicException(
|
||||
SR.Cryptography_Unix_X509_MachineStoresRootOnly,
|
||||
new PlatformNotSupportedException(SR.Cryptography_Unix_X509_MachineStoresRootOnly));
|
||||
}
|
||||
|
||||
private static ILoaderPal SingleCertToLoaderPal(ICertificatePal singleCert)
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// .NET Native (UWP) does not have access to the CspParameters type because it is in a non-UWP-compatible
|
||||
// assembly. So these type definitions allow the code to continue to use the same data transport structure
|
||||
// that it has for quite a while.
|
||||
|
||||
#if uap
|
||||
using System;
|
||||
|
||||
namespace Internal.Cryptography.Pal
|
||||
{
|
||||
internal sealed partial class CertificatePal : IDisposable, ICertificatePal
|
||||
{
|
||||
[Flags]
|
||||
private enum CspProviderFlags
|
||||
{
|
||||
// Note: UWP doesn't use any flags other than these, so they have been omitted.
|
||||
NoFlags = 0x0000,
|
||||
UseMachineKeyStore = 0x0001,
|
||||
}
|
||||
|
||||
private sealed class CspParameters
|
||||
{
|
||||
public int ProviderType;
|
||||
public string ProviderName;
|
||||
public string KeyContainerName;
|
||||
public int KeyNumber;
|
||||
private int _flags;
|
||||
|
||||
/// <summary>
|
||||
/// Flag property
|
||||
/// </summary>
|
||||
public CspProviderFlags Flags
|
||||
{
|
||||
get { return (CspProviderFlags)_flags; }
|
||||
set
|
||||
{
|
||||
const int allFlags = 0x00FF; // this should change if more values are added to CspProviderFlags
|
||||
int flags = (int)value;
|
||||
if ((flags & ~allFlags) != 0)
|
||||
{
|
||||
throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, nameof(value)));
|
||||
}
|
||||
_flags = flags;
|
||||
}
|
||||
}
|
||||
|
||||
public CspParameters() : this(-1, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
private CspParameters(int dwTypeIn, string strProviderNameIn, string strContainerNameIn) :
|
||||
this(dwTypeIn, strProviderNameIn, strContainerNameIn, CspProviderFlags.NoFlags)
|
||||
{
|
||||
}
|
||||
|
||||
private CspParameters(int providerType, string providerName, string keyContainerName, CspProviderFlags flags)
|
||||
{
|
||||
ProviderType = providerType;
|
||||
ProviderName = providerName;
|
||||
KeyContainerName = keyContainerName;
|
||||
KeyNumber = -1;
|
||||
Flags = flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if uap
|
||||
@@ -4,8 +4,10 @@
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
|
||||
using Internal.Cryptography.Pal.Native;
|
||||
@@ -80,6 +82,112 @@ namespace Internal.Cryptography.Pal
|
||||
);
|
||||
}
|
||||
|
||||
public ICertificatePal CopyWithPrivateKey(DSA dsa)
|
||||
{
|
||||
DSACng dsaCng = dsa as DSACng;
|
||||
ICertificatePal clone = null;
|
||||
|
||||
if (dsaCng != null)
|
||||
{
|
||||
clone = CopyWithPersistedCngKey(dsaCng.Key);
|
||||
|
||||
if (clone != null)
|
||||
{
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
DSACryptoServiceProvider dsaCsp = dsa as DSACryptoServiceProvider;
|
||||
|
||||
if (dsaCsp != null)
|
||||
{
|
||||
clone = CopyWithPersistedCapiKey(dsaCsp.CspKeyContainerInfo);
|
||||
|
||||
if (clone != null)
|
||||
{
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
DSAParameters privateParameters = dsa.ExportParameters(true);
|
||||
|
||||
using (PinAndClear.Track(privateParameters.X))
|
||||
using (DSACng clonedKey = new DSACng())
|
||||
{
|
||||
clonedKey.ImportParameters(privateParameters);
|
||||
|
||||
return CopyWithEphemeralKey(clonedKey.Key);
|
||||
}
|
||||
}
|
||||
|
||||
public ICertificatePal CopyWithPrivateKey(ECDsa ecdsa)
|
||||
{
|
||||
ECDsaCng ecdsaCng = ecdsa as ECDsaCng;
|
||||
|
||||
if (ecdsaCng != null)
|
||||
{
|
||||
ICertificatePal clone = CopyWithPersistedCngKey(ecdsaCng.Key);
|
||||
|
||||
if (clone != null)
|
||||
{
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
ECParameters privateParameters = ecdsa.ExportParameters(true);
|
||||
|
||||
using (PinAndClear.Track(privateParameters.D))
|
||||
using (ECDsaCng clonedKey = new ECDsaCng())
|
||||
{
|
||||
clonedKey.ImportParameters(privateParameters);
|
||||
|
||||
return CopyWithEphemeralKey(clonedKey.Key);
|
||||
}
|
||||
}
|
||||
|
||||
public ICertificatePal CopyWithPrivateKey(RSA rsa)
|
||||
{
|
||||
RSACng rsaCng = rsa as RSACng;
|
||||
ICertificatePal clone = null;
|
||||
|
||||
if (rsaCng != null)
|
||||
{
|
||||
clone = CopyWithPersistedCngKey(rsaCng.Key);
|
||||
|
||||
if (clone != null)
|
||||
{
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
RSACryptoServiceProvider rsaCsp = rsa as RSACryptoServiceProvider;
|
||||
|
||||
if (rsaCsp != null)
|
||||
{
|
||||
clone = CopyWithPersistedCapiKey(rsaCsp.CspKeyContainerInfo);
|
||||
|
||||
if (clone != null)
|
||||
{
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
RSAParameters privateParameters = rsa.ExportParameters(true);
|
||||
|
||||
using (PinAndClear.Track(privateParameters.D))
|
||||
using (PinAndClear.Track(privateParameters.P))
|
||||
using (PinAndClear.Track(privateParameters.Q))
|
||||
using (PinAndClear.Track(privateParameters.DP))
|
||||
using (PinAndClear.Track(privateParameters.DQ))
|
||||
using (PinAndClear.Track(privateParameters.InverseQ))
|
||||
using (RSACng clonedKey = new RSACng())
|
||||
{
|
||||
clonedKey.ImportParameters(privateParameters);
|
||||
|
||||
return CopyWithEphemeralKey(clonedKey.Key);
|
||||
}
|
||||
}
|
||||
|
||||
private T GetPrivateKey<T>(Func<CspParameters, T> createCsp, Func<CngKey, T> createCng) where T : AsymmetricAlgorithm
|
||||
{
|
||||
CngKeyHandleOpenOptions cngHandleOptions;
|
||||
@@ -239,5 +347,259 @@ namespace Internal.Cryptography.Pal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe ICertificatePal CopyWithPersistedCngKey(CngKey cngKey)
|
||||
{
|
||||
if (string.IsNullOrEmpty(cngKey.KeyName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Make a new pal from bytes.
|
||||
CertificatePal pal = (CertificatePal)FromBlob(RawData, SafePasswordHandle.InvalidHandle, X509KeyStorageFlags.PersistKeySet);
|
||||
|
||||
CngProvider provider = cngKey.Provider;
|
||||
string keyName = cngKey.KeyName;
|
||||
bool machineKey = cngKey.IsMachineKey;
|
||||
|
||||
// CAPI RSA_SIGN keys won't open correctly under CNG without the key number being specified, so
|
||||
// check to see if we can figure out what key number it needs to re-open.
|
||||
int keySpec = GuessKeySpec(provider, keyName, machineKey, cngKey.AlgorithmGroup);
|
||||
|
||||
CRYPT_KEY_PROV_INFO keyProvInfo = new CRYPT_KEY_PROV_INFO();
|
||||
|
||||
fixed (char* keyNamePtr = cngKey.KeyName)
|
||||
fixed (char* provNamePtr = cngKey.Provider.Provider)
|
||||
{
|
||||
keyProvInfo.pwszContainerName = keyNamePtr;
|
||||
keyProvInfo.pwszProvName = provNamePtr;
|
||||
keyProvInfo.dwFlags = machineKey ? CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET : 0;
|
||||
keyProvInfo.dwKeySpec = keySpec;
|
||||
|
||||
if (!Interop.crypt32.CertSetCertificateContextProperty(
|
||||
pal._certContext,
|
||||
CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID,
|
||||
CertSetPropertyFlags.None,
|
||||
&keyProvInfo))
|
||||
{
|
||||
pal.Dispose();
|
||||
throw Marshal.GetLastWin32Error().ToCryptographicException();
|
||||
}
|
||||
}
|
||||
|
||||
return pal;
|
||||
}
|
||||
|
||||
private static int GuessKeySpec(
|
||||
CngProvider provider,
|
||||
string keyName,
|
||||
bool machineKey,
|
||||
CngAlgorithmGroup algorithmGroup)
|
||||
{
|
||||
if (provider == CngProvider.MicrosoftSoftwareKeyStorageProvider ||
|
||||
provider == CngProvider.MicrosoftSmartCardKeyStorageProvider)
|
||||
{
|
||||
// Well-known CNG providers, keySpec is 0.
|
||||
return 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
CngKeyOpenOptions options = machineKey ? CngKeyOpenOptions.MachineKey : CngKeyOpenOptions.None;
|
||||
|
||||
using (CngKey.Open(keyName, provider, options))
|
||||
{
|
||||
// It opened with keySpec 0, so use keySpec 0.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
catch (CryptographicException)
|
||||
{
|
||||
// While NTE_BAD_KEYSET is what we generally expect here for RSA, on Windows 7
|
||||
// PROV_DSS produces NTE_BAD_PROV_TYPE, and PROV_DSS_DH produces NTE_NO_KEY.
|
||||
//
|
||||
// So we'll just try the CAPI fallback for any error code, and see what happens.
|
||||
|
||||
CspParameters cspParameters = new CspParameters
|
||||
{
|
||||
ProviderName = provider.Provider,
|
||||
KeyContainerName = keyName,
|
||||
Flags = CspProviderFlags.UseExistingKey,
|
||||
KeyNumber = (int)KeyNumber.Signature,
|
||||
};
|
||||
|
||||
if (machineKey)
|
||||
{
|
||||
cspParameters.Flags |= CspProviderFlags.UseMachineKeyStore;
|
||||
}
|
||||
|
||||
int keySpec;
|
||||
|
||||
if (TryGuessKeySpec(cspParameters, algorithmGroup, out keySpec))
|
||||
{
|
||||
return keySpec;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryGuessKeySpec(
|
||||
CspParameters cspParameters,
|
||||
CngAlgorithmGroup algorithmGroup,
|
||||
out int keySpec)
|
||||
{
|
||||
if (algorithmGroup == CngAlgorithmGroup.Rsa)
|
||||
{
|
||||
return TryGuessRsaKeySpec(cspParameters, out keySpec);
|
||||
}
|
||||
|
||||
if (algorithmGroup == CngAlgorithmGroup.Dsa)
|
||||
{
|
||||
return TryGuessDsaKeySpec(cspParameters, out keySpec);
|
||||
}
|
||||
|
||||
keySpec = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryGuessRsaKeySpec(CspParameters cspParameters, out int keySpec)
|
||||
{
|
||||
// Try the AT_SIGNATURE spot in each of the 4 RSA provider type values,
|
||||
// ideally one of them will work.
|
||||
const int PROV_RSA_FULL = 1;
|
||||
const int PROV_RSA_SIG = 2;
|
||||
const int PROV_RSA_SCHANNEL = 12;
|
||||
const int PROV_RSA_AES = 24;
|
||||
|
||||
// These are ordered in terms of perceived likeliness, given that the key
|
||||
// is AT_SIGNATURE.
|
||||
int[] provTypes =
|
||||
{
|
||||
PROV_RSA_FULL,
|
||||
PROV_RSA_AES,
|
||||
PROV_RSA_SCHANNEL,
|
||||
|
||||
// Nothing should be PROV_RSA_SIG, but if everything else has failed,
|
||||
// just try this last thing.
|
||||
PROV_RSA_SIG,
|
||||
};
|
||||
|
||||
foreach (int provType in provTypes)
|
||||
{
|
||||
cspParameters.ProviderType = provType;
|
||||
|
||||
try
|
||||
{
|
||||
using (new RSACryptoServiceProvider(cspParameters))
|
||||
{
|
||||
{
|
||||
keySpec = cspParameters.KeyNumber;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (CryptographicException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Fail("RSA key did not open with KeyNumber 0 or AT_SIGNATURE");
|
||||
keySpec = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryGuessDsaKeySpec(CspParameters cspParameters, out int keySpec)
|
||||
{
|
||||
const int PROV_DSS = 3;
|
||||
const int PROV_DSS_DH = 13;
|
||||
|
||||
int[] provTypes =
|
||||
{
|
||||
PROV_DSS_DH,
|
||||
PROV_DSS,
|
||||
};
|
||||
|
||||
foreach (int provType in provTypes)
|
||||
{
|
||||
cspParameters.ProviderType = provType;
|
||||
|
||||
try
|
||||
{
|
||||
using (new DSACryptoServiceProvider(cspParameters))
|
||||
{
|
||||
{
|
||||
keySpec = cspParameters.KeyNumber;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (CryptographicException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Fail("DSA key did not open with KeyNumber 0 or AT_SIGNATURE");
|
||||
keySpec = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
private unsafe ICertificatePal CopyWithPersistedCapiKey(CspKeyContainerInfo keyContainerInfo)
|
||||
{
|
||||
if (string.IsNullOrEmpty(keyContainerInfo.KeyContainerName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Make a new pal from bytes.
|
||||
CertificatePal pal = (CertificatePal)FromBlob(RawData, SafePasswordHandle.InvalidHandle, X509KeyStorageFlags.PersistKeySet);
|
||||
CRYPT_KEY_PROV_INFO keyProvInfo = new CRYPT_KEY_PROV_INFO();
|
||||
|
||||
fixed (char* keyName = keyContainerInfo.KeyContainerName)
|
||||
fixed (char* provName = keyContainerInfo.ProviderName)
|
||||
{
|
||||
keyProvInfo.pwszContainerName = keyName;
|
||||
keyProvInfo.pwszProvName = provName;
|
||||
keyProvInfo.dwFlags = keyContainerInfo.MachineKeyStore ? CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET : 0;
|
||||
keyProvInfo.dwProvType = keyContainerInfo.ProviderType;
|
||||
keyProvInfo.dwKeySpec = (int)keyContainerInfo.KeyNumber;
|
||||
|
||||
if (!Interop.crypt32.CertSetCertificateContextProperty(
|
||||
pal._certContext,
|
||||
CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID,
|
||||
CertSetPropertyFlags.None,
|
||||
&keyProvInfo))
|
||||
{
|
||||
pal.Dispose();
|
||||
throw Marshal.GetLastWin32Error().ToCryptographicException();
|
||||
}
|
||||
}
|
||||
|
||||
return pal;
|
||||
}
|
||||
|
||||
private ICertificatePal CopyWithEphemeralKey(CngKey cngKey)
|
||||
{
|
||||
Debug.Assert(string.IsNullOrEmpty(cngKey.KeyName));
|
||||
|
||||
SafeNCryptKeyHandle handle = cngKey.Handle;
|
||||
|
||||
// Make a new pal from bytes.
|
||||
CertificatePal pal = (CertificatePal)FromBlob(RawData, SafePasswordHandle.InvalidHandle, X509KeyStorageFlags.PersistKeySet);
|
||||
|
||||
if (!Interop.crypt32.CertSetCertificateContextProperty(
|
||||
pal._certContext,
|
||||
CertContextPropId.CERT_NCRYPT_KEY_HANDLE_PROP_ID,
|
||||
CertSetPropertyFlags.CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG,
|
||||
handle))
|
||||
{
|
||||
pal.Dispose();
|
||||
throw Marshal.GetLastWin32Error().ToCryptographicException();
|
||||
}
|
||||
|
||||
// The value was transferred to the certificate.
|
||||
handle.SetHandleAsInvalid();
|
||||
return pal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user