You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.142
Former-commit-id: 7467d4b717762eeaf652d77f1486dd11ffb1ff1f
This commit is contained in:
parent
e52655b4dc
commit
0abdbe5a7d
@@ -81,4 +81,4 @@ using System.Runtime.InteropServices;
|
||||
|
||||
#if XAMMAC || XAMMAC_4_5
|
||||
[assembly: InternalsVisibleTo ("Xamarin.Mac, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
|
||||
#endif
|
||||
#endif
|
||||
|
77
mcs/class/System/Internal.Cryptography/OidLookup.Managed.cs
Normal file
77
mcs/class/System/Internal.Cryptography/OidLookup.Managed.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// Copyright (c) 2018 Microsoft
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Fully managed implementation of OidLookup for the commonly supported Oids.
|
||||
/// </summary>
|
||||
internal static partial class OidLookup
|
||||
{
|
||||
private static bool ShouldUseCache(OidGroup oidGroup)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string NativeOidToFriendlyName(string oid, OidGroup oidGroup, bool fallBackToAllGroups)
|
||||
{
|
||||
switch (oid) {
|
||||
case "1.2.840.113549.1.7.1": return "PKCS 7 Data";
|
||||
case "1.2.840.113549.1.9.3": return "Content Type";
|
||||
case "1.2.840.113549.1.9.4": return "Message Digest";
|
||||
case "1.2.840.113549.1.9.5": return "Signing Time";
|
||||
case "1.2.840.113549.1.9.16.3.3": return "id-smime-alg-3DESwrap";
|
||||
case "2.5.29.14": return "Subject Key Identifier";
|
||||
case "2.5.29.15": return "Key Usage";
|
||||
case "2.5.29.17": return "Subject Alternative Name";
|
||||
case "2.5.29.19": return "Basic Constraints";
|
||||
case "2.5.29.37": return "Extended Key Usage";
|
||||
case "2.16.840.1.113730.1.1": return "Netscape Cert Type";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string NativeFriendlyNameToOid(string friendlyName, OidGroup oidGroup, bool fallBackToAllGroups)
|
||||
{
|
||||
switch (friendlyName) {
|
||||
case "PKCS 7 Data": return "1.2.840.113549.1.7.1";
|
||||
case "Content Type": return "1.2.840.113549.1.9.3";
|
||||
case "Message Digest": return "1.2.840.113549.1.9.4";
|
||||
case "Signing Time": return "1.2.840.113549.1.9.5";
|
||||
case "id-smime-alg-3DESwrap": return "1.2.840.113549.1.9.16.3.3";
|
||||
case "Subject Key Identifier": return "2.5.29.14";
|
||||
case "Key Usage": return "2.5.29.15";
|
||||
case "Subject Alternative Name": return "2.5.29.17";
|
||||
case "Basic Constraints": return "2.5.29.19";
|
||||
case "Extended Key Usage": return "2.5.29.37";
|
||||
case "Netscape Cert Type": return "2.16.840.1.113730.1.1";
|
||||
};
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -29,7 +29,8 @@ RESX_RESOURCE_STRING = \
|
||||
../../../external/corefx/src/System.Net.Http/src/Resources/Strings.resx \
|
||||
../../../external/corefx/src/System.Text.RegularExpressions/src/Resources/Strings.resx \
|
||||
../../../external/corefx/src/System.IO.FileSystem.Watcher/src/Resources/Strings.resx \
|
||||
../../../external/corefx/src/System.ComponentModel.TypeConverter/src/Resources/Strings.resx
|
||||
../../../external/corefx/src/System.ComponentModel.TypeConverter/src/Resources/Strings.resx \
|
||||
../../../external/corefx/src/System.Security.Cryptography.Encoding/src/Resources/Strings.resx
|
||||
|
||||
TEST_RESOURCES = \
|
||||
Test/System/test-uri-props.txt \
|
||||
@@ -110,7 +111,7 @@ endif
|
||||
TXT_RESOURCE_STRINGS = ../referencesource/System/System.txt
|
||||
|
||||
|
||||
API_BIN_REFS := System.Net.Http System.Xml
|
||||
API_BIN_REFS := System.Net.Http System.Xml System.Core
|
||||
|
||||
ifndef MOBILE_PROFILE
|
||||
API_BIN_REFS += System.Configuration
|
||||
@@ -118,9 +119,6 @@ LIB_MCS_FLAGS += -d:CONFIGURATION_DEP
|
||||
endif
|
||||
|
||||
EXTRA_DISTFILES = \
|
||||
common.sources \
|
||||
common_networking.sources \
|
||||
corefx.unix.sources \
|
||||
Test/test-config-file \
|
||||
Test/System.Security.Cryptography.X509Certificates/pkits/Makefile \
|
||||
Test/System.Security.Cryptography.X509Certificates/pkits/README \
|
||||
|
@@ -1,5 +1,4 @@
|
||||
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
|
||||
//
|
||||
//
|
||||
// AppleCertificateHelper.cs
|
||||
//
|
||||
// Author:
|
||||
@@ -28,7 +27,7 @@ namespace Mono.AppleTls
|
||||
{
|
||||
static class AppleCertificateHelper
|
||||
{
|
||||
public static SecIdentity GetIdentity (X509Certificate certificate)
|
||||
public static SafeSecIdentityHandle GetIdentity (X509Certificate certificate)
|
||||
{
|
||||
/*
|
||||
* If we got an 'X509Certificate2', then we require it to have a private key
|
||||
@@ -36,11 +35,7 @@ namespace Mono.AppleTls
|
||||
*/
|
||||
var certificate2 = certificate as X509Certificate2;
|
||||
if (certificate2 != null)
|
||||
#if MONOTOUCH
|
||||
return SecIdentity.Import (certificate2);
|
||||
#else
|
||||
return SecImportExport.ItemImport (certificate2);
|
||||
#endif
|
||||
return MonoCertificatePal.ImportIdentity (certificate2);
|
||||
|
||||
/*
|
||||
* Reading Certificates from the Mac Keychain
|
||||
@@ -87,32 +82,35 @@ namespace Mono.AppleTls
|
||||
*/
|
||||
|
||||
#if MOBILE
|
||||
using (var secCert = new SecCertificate (certificate)) {
|
||||
return SecKeyChain.FindIdentity (secCert, true);
|
||||
}
|
||||
using (var secCert = MonoCertificatePal.FromOtherCertificate (certificate))
|
||||
return MonoCertificatePal.FindIdentity (secCert, true);
|
||||
#else
|
||||
return null;
|
||||
return new SafeSecIdentityHandle ();
|
||||
#endif
|
||||
}
|
||||
|
||||
public static SecIdentity GetIdentity (X509Certificate certificate, out SecCertificate[] intermediateCerts)
|
||||
public static SafeSecIdentityHandle GetIdentity (X509Certificate certificate, out SafeSecCertificateHandle[] intermediateCerts)
|
||||
{
|
||||
var identity = GetIdentity (certificate);
|
||||
|
||||
var impl2 = certificate.Impl as X509Certificate2Impl;
|
||||
if (impl2 == null || impl2.IntermediateCertificates == null) {
|
||||
intermediateCerts = new SecCertificate [0];
|
||||
intermediateCerts = new SafeSecCertificateHandle [0];
|
||||
return identity;
|
||||
}
|
||||
|
||||
intermediateCerts = new SafeSecCertificateHandle [impl2.IntermediateCertificates.Count];
|
||||
|
||||
try {
|
||||
intermediateCerts = new SecCertificate [impl2.IntermediateCertificates.Count];
|
||||
for (int i = 0; i < intermediateCerts.Length; i++)
|
||||
intermediateCerts [i] = new SecCertificate (impl2.IntermediateCertificates [i]);
|
||||
intermediateCerts [i] = MonoCertificatePal.FromOtherCertificate (impl2.IntermediateCertificates[i]);
|
||||
|
||||
return identity;
|
||||
} catch {
|
||||
identity.Dispose ();
|
||||
for (int i = 0; i < intermediateCerts.Length; i++) {
|
||||
intermediateCerts [i]?.Dispose ();
|
||||
}
|
||||
identity?.Dispose ();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -158,4 +156,3 @@ namespace Mono.AppleTls
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,4 +1,3 @@
|
||||
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
|
||||
//
|
||||
// AppleTlsContext.cs
|
||||
//
|
||||
@@ -48,8 +47,8 @@ namespace Mono.AppleTls
|
||||
SslReadFunc readFunc;
|
||||
SslWriteFunc writeFunc;
|
||||
|
||||
SecIdentity serverIdentity;
|
||||
SecIdentity clientIdentity;
|
||||
SafeSecIdentityHandle serverIdentity;
|
||||
SafeSecIdentityHandle clientIdentity;
|
||||
|
||||
X509Certificate remoteCertificate;
|
||||
X509Certificate localClientCertificate;
|
||||
@@ -168,9 +167,9 @@ namespace Mono.AppleTls
|
||||
SetSessionOption (SslSessionOption.BreakOnServerAuth, true);
|
||||
|
||||
if (IsServer) {
|
||||
SecCertificate[] intermediateCerts;
|
||||
SafeSecCertificateHandle[] intermediateCerts;
|
||||
serverIdentity = AppleCertificateHelper.GetIdentity (LocalServerCertificate, out intermediateCerts);
|
||||
if (serverIdentity == null)
|
||||
if (serverIdentity.IsInvalid)
|
||||
throw new SSA.AuthenticationException ("Unable to get server certificate from keychain.");
|
||||
|
||||
SetCertificate (serverIdentity, intermediateCerts);
|
||||
@@ -225,9 +224,9 @@ namespace Mono.AppleTls
|
||||
if (localClientCertificate == null)
|
||||
return;
|
||||
clientIdentity = AppleCertificateHelper.GetIdentity (localClientCertificate);
|
||||
if (clientIdentity == null)
|
||||
if (clientIdentity.IsInvalid)
|
||||
throw new TlsException (AlertDescription.CertificateUnknown);
|
||||
SetCertificate (clientIdentity, new SecCertificate [0]);
|
||||
SetCertificate (clientIdentity, new SafeSecCertificateHandle [0]);
|
||||
}
|
||||
|
||||
void EvaluateTrust ()
|
||||
@@ -662,26 +661,21 @@ namespace Mono.AppleTls
|
||||
[DllImport (SecurityLibrary)]
|
||||
extern unsafe static /* OSStatus */ SslStatus SSLSetCertificate (/* SSLContextRef */ IntPtr context, /* CFArrayRef */ IntPtr certRefs);
|
||||
|
||||
CFArray Bundle (SecIdentity identity, IEnumerable<SecCertificate> certificates)
|
||||
CFArray Bundle (SafeSecIdentityHandle identity, IList<SafeSecCertificateHandle> certificates)
|
||||
{
|
||||
if (identity == null)
|
||||
throw new ArgumentNullException ("identity");
|
||||
int i = 0;
|
||||
if (identity == null || identity.IsInvalid)
|
||||
throw new ArgumentNullException (nameof (identity));
|
||||
if (certificates == null)
|
||||
throw new ArgumentNullException (nameof (certificates));
|
||||
|
||||
int n = 0;
|
||||
if (certificates != null) {
|
||||
foreach (var obj in certificates)
|
||||
n++;
|
||||
}
|
||||
|
||||
var ptrs = new IntPtr [n + 1];
|
||||
ptrs [0] = identity.Handle;
|
||||
foreach (var certificate in certificates)
|
||||
ptrs [++i] = certificate.Handle;
|
||||
var ptrs = new IntPtr [certificates.Count + 1];
|
||||
ptrs [0] = identity.DangerousGetHandle ();
|
||||
for (int i = 0; i < certificates.Count; i++)
|
||||
ptrs [i + 1] = certificates [i].DangerousGetHandle ();
|
||||
return CFArray.CreateArray (ptrs);
|
||||
}
|
||||
|
||||
public void SetCertificate (SecIdentity identify, IEnumerable<SecCertificate> certificates)
|
||||
void SetCertificate (SafeSecIdentityHandle identify, IList<SafeSecCertificateHandle> certificates)
|
||||
{
|
||||
using (var array = Bundle (identify, certificates)) {
|
||||
var result = SSLSetCertificate (Handle, array.Handle);
|
||||
@@ -1020,4 +1014,3 @@ namespace Mono.AppleTls
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,5 +1,4 @@
|
||||
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
|
||||
//
|
||||
//
|
||||
// AppleTlsProvider.cs
|
||||
//
|
||||
// Author:
|
||||
@@ -84,4 +83,3 @@ namespace Mono.AppleTls
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,4 +1,3 @@
|
||||
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
|
||||
//
|
||||
// AppleTlsStream.cs
|
||||
//
|
||||
@@ -43,4 +42,3 @@ namespace Mono.AppleTls
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,450 +0,0 @@
|
||||
//
|
||||
// Certificate.cs: Implements the managed SecCertificate wrapper.
|
||||
//
|
||||
// Authors:
|
||||
// Miguel de Icaza
|
||||
// Sebastien Pouliot <sebastien@xamarin.com>
|
||||
//
|
||||
// Copyright 2010 Novell, Inc
|
||||
// Copyright 2012-2013 Xamarin Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Mono.Net;
|
||||
|
||||
using ObjCRuntimeInternal;
|
||||
|
||||
namespace Mono.AppleTls {
|
||||
|
||||
partial class SecCertificate : INativeObject, IDisposable {
|
||||
internal IntPtr handle;
|
||||
|
||||
internal SecCertificate (IntPtr handle, bool owns = false)
|
||||
{
|
||||
if (handle == IntPtr.Zero)
|
||||
throw new Exception ("Invalid handle");
|
||||
|
||||
this.handle = handle;
|
||||
if (!owns)
|
||||
CFObject.CFRetain (handle);
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary, EntryPoint="SecCertificateGetTypeID")]
|
||||
public extern static IntPtr GetTypeID ();
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static IntPtr SecCertificateCreateWithData (IntPtr allocator, IntPtr cfData);
|
||||
|
||||
public SecCertificate (X509Certificate certificate)
|
||||
{
|
||||
if (certificate == null)
|
||||
throw new ArgumentNullException ("certificate");
|
||||
|
||||
handle = certificate.Impl.GetNativeAppleCertificate ();
|
||||
if (handle != IntPtr.Zero) {
|
||||
CFObject.CFRetain (handle);
|
||||
return;
|
||||
}
|
||||
|
||||
using (CFData cert = CFData.FromData (certificate.GetRawCertData ())) {
|
||||
Initialize (cert);
|
||||
}
|
||||
}
|
||||
|
||||
internal SecCertificate (X509CertificateImpl impl)
|
||||
{
|
||||
handle = impl.GetNativeAppleCertificate ();
|
||||
if (handle != IntPtr.Zero) {
|
||||
CFObject.CFRetain (handle);
|
||||
return;
|
||||
}
|
||||
|
||||
using (CFData cert = CFData.FromData (impl.GetRawCertData ())) {
|
||||
Initialize (cert);
|
||||
}
|
||||
}
|
||||
|
||||
void Initialize (CFData data)
|
||||
{
|
||||
handle = SecCertificateCreateWithData (IntPtr.Zero, data.Handle);
|
||||
if (handle == IntPtr.Zero)
|
||||
throw new ArgumentException ("Not a valid DER-encoded X.509 certificate");
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static IntPtr SecCertificateCopySubjectSummary (IntPtr cert);
|
||||
|
||||
public string SubjectSummary {
|
||||
get {
|
||||
if (handle == IntPtr.Zero)
|
||||
throw new ObjectDisposedException ("SecCertificate");
|
||||
|
||||
IntPtr subjectSummaryHandle = IntPtr.Zero;
|
||||
try {
|
||||
subjectSummaryHandle = SecCertificateCopySubjectSummary (handle);
|
||||
CFString subjectSummary = CFString.AsString (subjectSummaryHandle);
|
||||
return subjectSummary;
|
||||
}
|
||||
finally {
|
||||
if (subjectSummaryHandle != IntPtr.Zero)
|
||||
CFObject.CFRelease (subjectSummaryHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static /* CFDataRef */ IntPtr SecCertificateCopyData (/* SecCertificateRef */ IntPtr cert);
|
||||
|
||||
public CFData DerData {
|
||||
get {
|
||||
if (handle == IntPtr.Zero)
|
||||
throw new ObjectDisposedException ("SecCertificate");
|
||||
|
||||
IntPtr data = SecCertificateCopyData (handle);
|
||||
if (data == IntPtr.Zero)
|
||||
throw new ArgumentException ("Not a valid certificate");
|
||||
return new CFData (data, true);
|
||||
}
|
||||
}
|
||||
|
||||
public X509Certificate ToX509Certificate ()
|
||||
{
|
||||
if (handle == IntPtr.Zero)
|
||||
throw new ObjectDisposedException ("SecCertificate");
|
||||
|
||||
return new X509Certificate (handle);
|
||||
}
|
||||
|
||||
internal static bool Equals (SecCertificate first, SecCertificate second)
|
||||
{
|
||||
/*
|
||||
* This is a little bit expensive, but unfortunately there is no better API to compare two
|
||||
* SecCertificateRef's for equality.
|
||||
*/
|
||||
if (first == null)
|
||||
throw new ArgumentNullException ("first");
|
||||
if (second == null)
|
||||
throw new ArgumentNullException ("second");
|
||||
if (first.Handle == second.Handle)
|
||||
return true;
|
||||
|
||||
using (var firstData = first.DerData)
|
||||
using (var secondData = second.DerData) {
|
||||
if (firstData.Handle == secondData.Handle)
|
||||
return true;
|
||||
|
||||
if (firstData.Length != secondData.Length)
|
||||
return false;
|
||||
IntPtr length = (IntPtr)firstData.Length;
|
||||
for (long i = 0; i < (long)length; i++) {
|
||||
if (firstData [i] != secondData [i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
~SecCertificate ()
|
||||
{
|
||||
Dispose (false);
|
||||
}
|
||||
|
||||
public IntPtr Handle {
|
||||
get {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (handle != IntPtr.Zero){
|
||||
CFObject.CFRelease (handle);
|
||||
handle = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial class SecIdentity : INativeObject, IDisposable {
|
||||
|
||||
static readonly CFString ImportExportPassphase;
|
||||
static readonly CFString ImportItemIdentity;
|
||||
static readonly CFString ImportExportAccess;
|
||||
static readonly CFString ImportExportKeychain;
|
||||
|
||||
static SecIdentity ()
|
||||
{
|
||||
var handle = CFObject.dlopen (AppleTlsContext.SecurityLibrary, 0);
|
||||
if (handle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
try {
|
||||
ImportExportPassphase = CFObject.GetStringConstant (handle, "kSecImportExportPassphrase");
|
||||
ImportItemIdentity = CFObject.GetStringConstant (handle, "kSecImportItemIdentity");
|
||||
ImportExportAccess = CFObject.GetStringConstant (handle, "kSecImportExportAccess");
|
||||
ImportExportKeychain = CFObject.GetStringConstant (handle, "kSecImportExportKeychain");
|
||||
} finally {
|
||||
CFObject.dlclose (handle);
|
||||
}
|
||||
}
|
||||
|
||||
internal IntPtr handle;
|
||||
|
||||
internal SecIdentity (IntPtr handle, bool owns = false)
|
||||
{
|
||||
this.handle = handle;
|
||||
if (!owns)
|
||||
CFObject.CFRetain (handle);
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary, EntryPoint="SecIdentityGetTypeID")]
|
||||
public extern static IntPtr GetTypeID ();
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static /* OSStatus */ SecStatusCode SecIdentityCopyCertificate (/* SecIdentityRef */ IntPtr identityRef, /* SecCertificateRef* */ out IntPtr certificateRef);
|
||||
|
||||
public SecCertificate Certificate {
|
||||
get {
|
||||
if (handle == IntPtr.Zero)
|
||||
throw new ObjectDisposedException ("SecIdentity");
|
||||
IntPtr cert;
|
||||
SecStatusCode result = SecIdentityCopyCertificate (handle, out cert);
|
||||
if (result != SecStatusCode.Success)
|
||||
throw new InvalidOperationException (result.ToString ());
|
||||
return new SecCertificate (cert, true);
|
||||
}
|
||||
}
|
||||
|
||||
internal class ImportOptions
|
||||
{
|
||||
#if !MONOTOUCH
|
||||
public SecAccess Access {
|
||||
get; set;
|
||||
}
|
||||
public SecKeyChain KeyChain {
|
||||
get; set;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static CFDictionary CreateImportOptions (CFString password, ImportOptions options = null)
|
||||
{
|
||||
if (options == null)
|
||||
return CFDictionary.FromObjectAndKey (password.Handle, ImportExportPassphase.Handle);
|
||||
|
||||
var items = new List<Tuple<IntPtr, IntPtr>> ();
|
||||
items.Add (new Tuple<IntPtr, IntPtr> (ImportExportPassphase.Handle, password.Handle));
|
||||
|
||||
#if !MONOTOUCH
|
||||
if (options.KeyChain != null)
|
||||
items.Add (new Tuple<IntPtr, IntPtr> (ImportExportKeychain.Handle, options.KeyChain.Handle));
|
||||
if (options.Access != null)
|
||||
items.Add (new Tuple<IntPtr, IntPtr> (ImportExportAccess.Handle, options.Access.Handle));
|
||||
#endif
|
||||
|
||||
return CFDictionary.FromKeysAndObjects (items);
|
||||
}
|
||||
|
||||
public static SecIdentity Import (byte[] data, string password, ImportOptions options = null)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException ("data");
|
||||
if (string.IsNullOrEmpty (password)) // SecPKCS12Import() doesn't allow empty passwords.
|
||||
throw new ArgumentException ("password");
|
||||
using (var pwstring = CFString.Create (password))
|
||||
using (var optionDict = CreateImportOptions (pwstring, options)) {
|
||||
CFDictionary [] array;
|
||||
SecStatusCode result = SecImportExport.ImportPkcs12 (data, optionDict, out array);
|
||||
if (result != SecStatusCode.Success)
|
||||
throw new InvalidOperationException (result.ToString ());
|
||||
|
||||
return new SecIdentity (array [0].GetValue (ImportItemIdentity.Handle));
|
||||
}
|
||||
}
|
||||
|
||||
public static SecIdentity Import (X509Certificate2 certificate, ImportOptions options = null)
|
||||
{
|
||||
if (certificate == null)
|
||||
throw new ArgumentNullException ("certificate");
|
||||
if (!certificate.HasPrivateKey)
|
||||
throw new InvalidOperationException ("Need X509Certificate2 with a private key.");
|
||||
|
||||
/*
|
||||
* SecPSK12Import does not allow any empty passwords, so let's generate
|
||||
* a semi-random one here.
|
||||
*/
|
||||
var password = Guid.NewGuid ().ToString ();
|
||||
var pkcs12 = certificate.Export (X509ContentType.Pfx, password);
|
||||
return Import (pkcs12, password, options);
|
||||
}
|
||||
|
||||
~SecIdentity ()
|
||||
{
|
||||
Dispose (false);
|
||||
}
|
||||
|
||||
public IntPtr Handle {
|
||||
get {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (handle != IntPtr.Zero){
|
||||
CFObject.CFRelease (handle);
|
||||
handle = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial class SecKey : INativeObject, IDisposable {
|
||||
internal IntPtr handle;
|
||||
internal IntPtr owner;
|
||||
|
||||
public SecKey (IntPtr handle, bool owns = false)
|
||||
{
|
||||
this.handle = handle;
|
||||
if (!owns)
|
||||
CFObject.CFRetain (handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* SecItemImport() returns a SecArrayRef. We need to free the array, not the items inside it.
|
||||
*
|
||||
*/
|
||||
internal SecKey (IntPtr handle, IntPtr owner)
|
||||
{
|
||||
this.handle = handle;
|
||||
this.owner = owner;
|
||||
CFObject.CFRetain (owner);
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary, EntryPoint="SecKeyGetTypeID")]
|
||||
public extern static IntPtr GetTypeID ();
|
||||
|
||||
~SecKey ()
|
||||
{
|
||||
Dispose (false);
|
||||
}
|
||||
|
||||
public IntPtr Handle {
|
||||
get {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (owner != IntPtr.Zero) {
|
||||
CFObject.CFRelease (owner);
|
||||
owner = handle = IntPtr.Zero;
|
||||
} else if (handle != IntPtr.Zero) {
|
||||
CFObject.CFRelease (handle);
|
||||
handle = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !MONOTOUCH
|
||||
class SecAccess : INativeObject, IDisposable {
|
||||
internal IntPtr handle;
|
||||
|
||||
public SecAccess (IntPtr handle, bool owns = false)
|
||||
{
|
||||
this.handle = handle;
|
||||
if (!owns)
|
||||
CFObject.CFRetain (handle);
|
||||
}
|
||||
|
||||
~SecAccess ()
|
||||
{
|
||||
Dispose (false);
|
||||
}
|
||||
|
||||
public IntPtr Handle {
|
||||
get {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static /* OSStatus */ SecStatusCode SecAccessCreate (/* CFStringRef */ IntPtr descriptor, /* CFArrayRef */ IntPtr trustedList, /* SecAccessRef _Nullable * */ out IntPtr accessRef);
|
||||
|
||||
public static SecAccess Create (string descriptor)
|
||||
{
|
||||
var descriptorHandle = CFString.Create (descriptor);
|
||||
if (descriptorHandle == null)
|
||||
throw new InvalidOperationException ();
|
||||
|
||||
try {
|
||||
IntPtr accessRef;
|
||||
var result = SecAccessCreate (descriptorHandle.Handle, IntPtr.Zero, out accessRef);
|
||||
if (result != SecStatusCode.Success)
|
||||
throw new InvalidOperationException (result.ToString ());
|
||||
|
||||
return new SecAccess (accessRef, true);
|
||||
} finally {
|
||||
descriptorHandle.Dispose ();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (handle != IntPtr.Zero) {
|
||||
CFObject.CFRelease (handle);
|
||||
handle = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
@@ -1,4 +1,3 @@
|
||||
#if MONO_FEATURE_APPLETLS
|
||||
// Copyright 2011-2015 Xamarin Inc. All rights reserved.
|
||||
|
||||
using ObjCRuntimeInternal;
|
||||
@@ -405,4 +404,3 @@ namespace Mono.AppleTls {
|
||||
ResultOtherError,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,356 +0,0 @@
|
||||
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
|
||||
//
|
||||
// Items.cs: Implements the KeyChain query access APIs
|
||||
//
|
||||
// We use strong types and a helper SecQuery class to simplify the
|
||||
// creation of the dictionary used to query the Keychain
|
||||
//
|
||||
// Authors:
|
||||
// Miguel de Icaza
|
||||
// Sebastien Pouliot
|
||||
//
|
||||
// Copyright 2010 Novell, Inc
|
||||
// Copyright 2011-2016 Xamarin Inc
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Runtime.InteropServices;
|
||||
using ObjCRuntimeInternal;
|
||||
using Mono.Net;
|
||||
|
||||
namespace Mono.AppleTls {
|
||||
|
||||
enum SecKind {
|
||||
Identity,
|
||||
Certificate
|
||||
}
|
||||
|
||||
#if MONOTOUCH
|
||||
static class SecKeyChain {
|
||||
#else
|
||||
class SecKeyChain : INativeObject, IDisposable {
|
||||
#endif
|
||||
internal static readonly IntPtr MatchLimitAll;
|
||||
internal static readonly IntPtr MatchLimitOne;
|
||||
internal static readonly IntPtr MatchLimit;
|
||||
|
||||
#if !MONOTOUCH
|
||||
IntPtr handle;
|
||||
|
||||
internal SecKeyChain (IntPtr handle, bool owns = false)
|
||||
{
|
||||
if (handle == IntPtr.Zero)
|
||||
throw new ArgumentException ("Invalid handle");
|
||||
|
||||
this.handle = handle;
|
||||
if (!owns)
|
||||
CFObject.CFRetain (handle);
|
||||
}
|
||||
#endif
|
||||
|
||||
static SecKeyChain ()
|
||||
{
|
||||
var handle = CFObject.dlopen (AppleTlsContext.SecurityLibrary, 0);
|
||||
if (handle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
try {
|
||||
MatchLimit = CFObject.GetIntPtr (handle, "kSecMatchLimit");
|
||||
MatchLimitAll = CFObject.GetIntPtr (handle, "kSecMatchLimitAll");
|
||||
MatchLimitOne = CFObject.GetIntPtr (handle, "kSecMatchLimitOne");
|
||||
} finally {
|
||||
CFObject.dlclose (handle);
|
||||
}
|
||||
}
|
||||
|
||||
public static SecIdentity FindIdentity (SecCertificate certificate, bool throwOnError = false)
|
||||
{
|
||||
if (certificate == null)
|
||||
throw new ArgumentNullException ("certificate");
|
||||
var identity = FindIdentity (cert => SecCertificate.Equals (certificate, cert));
|
||||
if (!throwOnError || identity != null)
|
||||
return identity;
|
||||
|
||||
throw new InvalidOperationException (string.Format ("Could not find SecIdentity for certificate '{0}' in keychain.", certificate.SubjectSummary));
|
||||
}
|
||||
|
||||
static SecIdentity FindIdentity (Predicate<SecCertificate> filter)
|
||||
{
|
||||
/*
|
||||
* Unfortunately, SecItemCopyMatching() does not allow any search
|
||||
* filters when looking up an identity.
|
||||
*
|
||||
* The following lookup will return all identities from the keychain -
|
||||
* we then need need to find the right one.
|
||||
*/
|
||||
using (var record = new SecRecord (SecKind.Identity)) {
|
||||
SecStatusCode status;
|
||||
var result = SecKeyChain.QueryAsReference (record, -1, out status);
|
||||
if (status != SecStatusCode.Success || result == null)
|
||||
return null;
|
||||
|
||||
for (int i = 0; i < result.Length; i++) {
|
||||
var identity = (SecIdentity)result [i];
|
||||
if (filter (identity.Certificate))
|
||||
return identity;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static INativeObject [] QueryAsReference (SecRecord query, int max, out SecStatusCode result)
|
||||
{
|
||||
if (query == null) {
|
||||
result = SecStatusCode.Param;
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var copy = query.QueryDict.MutableCopy ()) {
|
||||
copy.SetValue (CFBoolean.True.Handle, SecItem.ReturnRef);
|
||||
SetLimit (copy, max);
|
||||
return QueryAsReference (copy, out result);
|
||||
}
|
||||
}
|
||||
|
||||
static INativeObject [] QueryAsReference (CFDictionary query, out SecStatusCode result)
|
||||
{
|
||||
if (query == null) {
|
||||
result = SecStatusCode.Param;
|
||||
return null;
|
||||
}
|
||||
|
||||
IntPtr ptr;
|
||||
result = SecItem.SecItemCopyMatching (query.Handle, out ptr);
|
||||
if (result == SecStatusCode.Success && ptr != IntPtr.Zero) {
|
||||
var array = CFArray.ArrayFromHandle<INativeObject> (ptr, p => {
|
||||
IntPtr cfType = CFType.GetTypeID (p);
|
||||
if (cfType == SecCertificate.GetTypeID ())
|
||||
return new SecCertificate (p, true);
|
||||
if (cfType == SecKey.GetTypeID ())
|
||||
return new SecKey (p, true);
|
||||
if (cfType == SecIdentity.GetTypeID ())
|
||||
return new SecIdentity (p, true);
|
||||
throw new Exception (String.Format ("Unexpected type: 0x{0:x}", cfType));
|
||||
});
|
||||
return array;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static CFNumber SetLimit (CFMutableDictionary dict, int max)
|
||||
{
|
||||
CFNumber n = null;
|
||||
IntPtr val;
|
||||
if (max == -1)
|
||||
val = MatchLimitAll;
|
||||
else if (max == 1)
|
||||
val = MatchLimitOne;
|
||||
else {
|
||||
n = CFNumber.FromInt32 (max);
|
||||
val = n.Handle;
|
||||
}
|
||||
|
||||
dict.SetValue (val, SecKeyChain.MatchLimit);
|
||||
return n;
|
||||
}
|
||||
|
||||
#if !MONOTOUCH
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static /* OSStatus */ SecStatusCode SecKeychainCreate (/* const char * */ IntPtr pathName, uint passwordLength, /* const void * */ IntPtr password,
|
||||
bool promptUser, /* SecAccessRef */ IntPtr initialAccess,
|
||||
/* SecKeychainRef _Nullable * */ out IntPtr keychain);
|
||||
|
||||
internal static SecKeyChain Create (string pathName, string password)
|
||||
{
|
||||
IntPtr handle;
|
||||
var pathNamePtr = Marshal.StringToHGlobalAnsi (pathName);
|
||||
var passwordPtr = Marshal.StringToHGlobalAnsi (password);
|
||||
var result = SecKeychainCreate (pathNamePtr, (uint)password.Length, passwordPtr, false, IntPtr.Zero, out handle);
|
||||
if (result != SecStatusCode.Success)
|
||||
throw new InvalidOperationException (result.ToString ());
|
||||
return new SecKeyChain (handle, true);
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static /* OSStatus */ SecStatusCode SecKeychainOpen (/* const char * */ IntPtr pathName, /* SecKeychainRef _Nullable * */ out IntPtr keychain);
|
||||
|
||||
internal static SecKeyChain Open (string pathName)
|
||||
{
|
||||
IntPtr handle;
|
||||
IntPtr pathNamePtr = IntPtr.Zero;
|
||||
try {
|
||||
pathNamePtr = Marshal.StringToHGlobalAnsi (pathName);
|
||||
var result = SecKeychainOpen (pathNamePtr, out handle);
|
||||
if (result != SecStatusCode.Success)
|
||||
throw new InvalidOperationException (result.ToString ());
|
||||
return new SecKeyChain (handle, true);
|
||||
} finally {
|
||||
if (pathNamePtr != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal (pathNamePtr);
|
||||
}
|
||||
}
|
||||
|
||||
internal static SecKeyChain OpenSystemRootCertificates ()
|
||||
{
|
||||
return Open ("/System/Library/Keychains/SystemRootCertificates.keychain");
|
||||
}
|
||||
|
||||
~SecKeyChain ()
|
||||
{
|
||||
Dispose (false);
|
||||
}
|
||||
|
||||
public IntPtr Handle {
|
||||
get {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (handle != IntPtr.Zero) {
|
||||
CFObject.CFRelease (handle);
|
||||
handle = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
class SecRecord : IDisposable {
|
||||
|
||||
internal static readonly IntPtr SecClassKey;
|
||||
static SecRecord ()
|
||||
{
|
||||
var handle = CFObject.dlopen (AppleTlsContext.SecurityLibrary, 0);
|
||||
if (handle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
try {
|
||||
SecClassKey = CFObject.GetIntPtr (handle, "kSecClass");
|
||||
} finally {
|
||||
CFObject.dlclose (handle);
|
||||
}
|
||||
}
|
||||
|
||||
CFMutableDictionary _queryDict;
|
||||
internal CFMutableDictionary QueryDict {
|
||||
get {
|
||||
return _queryDict;
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetValue (IntPtr key, IntPtr value)
|
||||
{
|
||||
_queryDict.SetValue (key, value);
|
||||
}
|
||||
|
||||
public SecRecord (SecKind secKind)
|
||||
{
|
||||
var kind = SecClass.FromSecKind (secKind);
|
||||
_queryDict = CFMutableDictionary.Create ();
|
||||
_queryDict.SetValue (SecClassKey, kind);
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (_queryDict != null){
|
||||
if (disposing){
|
||||
_queryDict.Dispose ();
|
||||
_queryDict = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~SecRecord ()
|
||||
{
|
||||
Dispose (false);
|
||||
}
|
||||
}
|
||||
|
||||
partial class SecItem {
|
||||
public static readonly IntPtr ReturnRef;
|
||||
public static readonly IntPtr MatchSearchList;
|
||||
|
||||
static SecItem ()
|
||||
{
|
||||
var handle = CFObject.dlopen (AppleTlsContext.SecurityLibrary, 0);
|
||||
if (handle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
try {
|
||||
ReturnRef = CFObject.GetIntPtr (handle, "kSecReturnRef");
|
||||
MatchSearchList = CFObject.GetIntPtr (handle, "kSecMatchSearchList");
|
||||
} finally {
|
||||
CFObject.dlclose (handle);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
internal extern static SecStatusCode SecItemCopyMatching (/* CFDictionaryRef */ IntPtr query, /* CFTypeRef* */ out IntPtr result);
|
||||
}
|
||||
|
||||
static partial class SecClass {
|
||||
|
||||
public static readonly IntPtr Identity;
|
||||
public static readonly IntPtr Certificate;
|
||||
|
||||
static SecClass ()
|
||||
{
|
||||
var handle = CFObject.dlopen (AppleTlsContext.SecurityLibrary, 0);
|
||||
if (handle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
try {
|
||||
Identity = CFObject.GetIntPtr (handle, "kSecClassIdentity");
|
||||
Certificate = CFObject.GetIntPtr (handle, "kSecClassCertificate");
|
||||
} finally {
|
||||
CFObject.dlclose (handle);
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr FromSecKind (SecKind secKind)
|
||||
{
|
||||
switch (secKind){
|
||||
case SecKind.Identity:
|
||||
return Identity;
|
||||
case SecKind.Certificate:
|
||||
return Certificate;
|
||||
default:
|
||||
throw new ArgumentException ("secKind");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
189
mcs/class/System/Mono.AppleTls/MonoCertificatePal.Mobile.cs
Normal file
189
mcs/class/System/Mono.AppleTls/MonoCertificatePal.Mobile.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
//
|
||||
// MonoCertificatePal.Mobile.cs
|
||||
//
|
||||
// Authors:
|
||||
// Miguel de Icaza
|
||||
// Sebastien Pouliot <sebastien@xamarin.com>
|
||||
// Martin Baulig <mabaul@microsoft.com>
|
||||
//
|
||||
// Copyright 2010 Novell, Inc
|
||||
// Copyright 2011-2014 Xamarin Inc.
|
||||
// Copyright (c) 2018 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.Apple;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using Mono.Net;
|
||||
|
||||
namespace Mono.AppleTls
|
||||
{
|
||||
static partial class MonoCertificatePal
|
||||
{
|
||||
static int initialized;
|
||||
static CFString ImportExportPassphase;
|
||||
static CFString ImportItemIdentity;
|
||||
static IntPtr MatchLimitAll;
|
||||
static IntPtr MatchLimitOne;
|
||||
static IntPtr MatchLimit;
|
||||
static IntPtr SecClassKey;
|
||||
static IntPtr SecClassIdentity;
|
||||
static IntPtr SecClassCertificate;
|
||||
static IntPtr ReturnRef;
|
||||
static IntPtr MatchSearchList;
|
||||
|
||||
static void Initialize ()
|
||||
{
|
||||
if (Interlocked.CompareExchange (ref initialized, 1, 0) != 0)
|
||||
return;
|
||||
|
||||
var handle = CFObject.dlopen (AppleTlsContext.SecurityLibrary, 0);
|
||||
if (handle == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
try {
|
||||
ImportExportPassphase = CFObject.GetStringConstant (handle, "kSecImportExportPassphrase");
|
||||
ImportItemIdentity = CFObject.GetStringConstant (handle, "kSecImportItemIdentity");
|
||||
MatchLimit = CFObject.GetIntPtr (handle, "kSecMatchLimit");
|
||||
MatchLimitAll = CFObject.GetIntPtr (handle, "kSecMatchLimitAll");
|
||||
MatchLimitOne = CFObject.GetIntPtr (handle, "kSecMatchLimitOne");
|
||||
SecClassKey = CFObject.GetIntPtr (handle, "kSecClass");
|
||||
SecClassIdentity = CFObject.GetIntPtr (handle, "kSecClassIdentity");
|
||||
SecClassCertificate = CFObject.GetIntPtr (handle, "kSecClassCertificate");
|
||||
ReturnRef = CFObject.GetIntPtr (handle, "kSecReturnRef");
|
||||
MatchSearchList = CFObject.GetIntPtr (handle, "kSecMatchSearchList");
|
||||
} finally {
|
||||
CFObject.dlclose (handle);
|
||||
}
|
||||
}
|
||||
|
||||
static SafeSecIdentityHandle ImportIdentity (byte[] data, string password)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException (nameof (data));
|
||||
if (string.IsNullOrEmpty (password)) // SecPKCS12Import() doesn't allow empty passwords.
|
||||
throw new ArgumentException (nameof (password));
|
||||
Initialize ();
|
||||
using (var pwstring = CFString.Create (password))
|
||||
using (var optionDict = CFDictionary.FromObjectAndKey (pwstring.Handle, ImportExportPassphase.Handle)) {
|
||||
var result = ImportPkcs12 (data, optionDict, out var array);
|
||||
if (result != SecStatusCode.Success)
|
||||
throw new InvalidOperationException (result.ToString ());
|
||||
|
||||
return new SafeSecIdentityHandle (array [0].GetValue (ImportItemIdentity.Handle));
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static SecStatusCode SecPKCS12Import (IntPtr pkcs12_data, IntPtr options, out IntPtr items);
|
||||
|
||||
static SecStatusCode ImportPkcs12 (byte[] buffer, CFDictionary options, out CFDictionary[] array)
|
||||
{
|
||||
using (CFData data = CFData.FromData (buffer)) {
|
||||
return ImportPkcs12 (data, options, out array);
|
||||
}
|
||||
}
|
||||
|
||||
static SecStatusCode ImportPkcs12 (CFData data, CFDictionary options, out CFDictionary[] array)
|
||||
{
|
||||
if (options == null)
|
||||
throw new ArgumentNullException (nameof (options));
|
||||
|
||||
var code = SecPKCS12Import (data.Handle, options.Handle, out var handle);
|
||||
array = CFArray.ArrayFromHandle<CFDictionary> (handle, h => new CFDictionary (h, false));
|
||||
if (handle != IntPtr.Zero)
|
||||
CFObject.CFRelease (handle);
|
||||
return code;
|
||||
}
|
||||
|
||||
public static SafeSecIdentityHandle ImportIdentity (X509Certificate2 certificate)
|
||||
{
|
||||
if (certificate == null)
|
||||
throw new ArgumentNullException (nameof (certificate));
|
||||
if (!certificate.HasPrivateKey)
|
||||
throw new InvalidOperationException ("Need X509Certificate2 with a private key.");
|
||||
|
||||
SafeSecIdentityHandle identity;
|
||||
/*
|
||||
* SecPSK12Import does not allow any empty passwords, so let's generate
|
||||
* a semi-random one here.
|
||||
*/
|
||||
Initialize ();
|
||||
var password = Guid.NewGuid ().ToString ();
|
||||
var pkcs12 = certificate.Export (X509ContentType.Pfx, password);
|
||||
identity = ImportIdentity (pkcs12, password);
|
||||
return identity ?? new SafeSecIdentityHandle ();
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static SecStatusCode SecItemCopyMatching (/* CFDictionaryRef */ IntPtr query, /* CFTypeRef* */ out IntPtr result);
|
||||
|
||||
public static SafeSecIdentityHandle FindIdentity (SafeSecCertificateHandle certificate, bool throwOnError = false)
|
||||
{
|
||||
if (certificate == null || certificate.IsInvalid)
|
||||
throw new ObjectDisposedException (nameof (certificate));
|
||||
var identity = FindIdentity (cert => MonoCertificatePal.Equals (certificate, cert)) ?? new SafeSecIdentityHandle ();
|
||||
if (!throwOnError || identity.IsInvalid)
|
||||
return identity;
|
||||
|
||||
var subject = MonoCertificatePal.GetSubjectSummary (certificate);
|
||||
throw new InvalidOperationException ($"Could not find SecIdentity for certificate '{subject}' in keychain.");
|
||||
}
|
||||
|
||||
static SafeSecIdentityHandle FindIdentity (Predicate<SafeSecCertificateHandle> filter)
|
||||
{
|
||||
Initialize ();
|
||||
|
||||
/*
|
||||
* Unfortunately, SecItemCopyMatching() does not allow any search
|
||||
* filters when looking up an identity.
|
||||
*
|
||||
* The following lookup will return all identities from the keychain -
|
||||
* we then need need to find the right one.
|
||||
*/
|
||||
using (var query = CFMutableDictionary.Create ()) {
|
||||
query.SetValue (SecClassKey, SecClassIdentity);
|
||||
query.SetValue (CFBoolean.True.Handle, ReturnRef);
|
||||
query.SetValue (MatchLimitAll, MatchLimit);
|
||||
|
||||
var status = SecItemCopyMatching (query.Handle, out var ptr);
|
||||
if (status != SecStatusCode.Success || ptr == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
using (var array = new CFArray (ptr, false)) {
|
||||
for (int i = 0; i < array.Count; i++) {
|
||||
var item = array[i];
|
||||
if (!MonoCertificatePal.IsSecIdentity (item))
|
||||
throw new InvalidOperationException ();
|
||||
using (var identity = new SafeSecIdentityHandle (item))
|
||||
using (var certificate = MonoCertificatePal.GetCertificate (identity)) {
|
||||
if (filter (certificate))
|
||||
return new SafeSecIdentityHandle (item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,37 +1,39 @@
|
||||
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
|
||||
//
|
||||
// ImportExport.cs
|
||||
//
|
||||
// MonoCertificatePal.OSX.cs
|
||||
//
|
||||
// Authors:
|
||||
// Sebastien Pouliot <sebastien@xamarin.com>
|
||||
//
|
||||
// Miguel de Icaza
|
||||
// Sebastien Pouliot <sebastien@xamarin.com>
|
||||
// Martin Baulig <mabaul@microsoft.com>
|
||||
//
|
||||
// Copyright 2010 Novell, Inc
|
||||
// Copyright 2011-2014 Xamarin Inc.
|
||||
// Copyright (c) 2018 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.Apple;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using ObjCRuntimeInternal;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using Mono.Net;
|
||||
|
||||
#if MONO_FEATURE_BTLS
|
||||
@@ -40,34 +42,20 @@ using Mono.Btls;
|
||||
using Mono.Security.Cryptography;
|
||||
#endif
|
||||
|
||||
namespace Mono.AppleTls {
|
||||
|
||||
internal partial class SecImportExport {
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static SecStatusCode SecPKCS12Import (IntPtr pkcs12_data, IntPtr options, out IntPtr items);
|
||||
|
||||
static public SecStatusCode ImportPkcs12 (byte[] buffer, CFDictionary options, out CFDictionary[] array)
|
||||
namespace Mono.AppleTls
|
||||
{
|
||||
static partial class MonoCertificatePal
|
||||
{
|
||||
public static SafeSecIdentityHandle ImportIdentity (X509Certificate2 certificate)
|
||||
{
|
||||
using (CFData data = CFData.FromData (buffer)) {
|
||||
return ImportPkcs12 (data, options, out array);
|
||||
}
|
||||
if (certificate == null)
|
||||
throw new ArgumentNullException (nameof (certificate));
|
||||
if (!certificate.HasPrivateKey)
|
||||
throw new InvalidOperationException ("Need X509Certificate2 with a private key.");
|
||||
|
||||
return ItemImport (certificate) ?? new SafeSecIdentityHandle ();
|
||||
}
|
||||
|
||||
static public SecStatusCode ImportPkcs12 (CFData data, CFDictionary options, out CFDictionary [] array)
|
||||
{
|
||||
if (options == null)
|
||||
throw new ArgumentNullException ("options");
|
||||
|
||||
IntPtr handle;
|
||||
SecStatusCode code = SecPKCS12Import (data.Handle, options.Handle, out handle);
|
||||
array = CFArray.ArrayFromHandle <CFDictionary> (handle, h => new CFDictionary (h, false));
|
||||
if (handle != IntPtr.Zero)
|
||||
CFObject.CFRelease (handle);
|
||||
return code;
|
||||
}
|
||||
|
||||
#if !MONOTOUCH
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static SecStatusCode SecItemImport (
|
||||
/* CFDataRef */ IntPtr importedData,
|
||||
@@ -91,15 +79,15 @@ namespace Mono.AppleTls {
|
||||
}
|
||||
|
||||
static CFArray ItemImport (CFData data, SecExternalFormat format, SecExternalItemType itemType,
|
||||
SecItemImportExportFlags flags = SecItemImportExportFlags.None,
|
||||
SecItemImportExportKeyParameters? keyParams = null)
|
||||
SecItemImportExportFlags flags = SecItemImportExportFlags.None,
|
||||
SecItemImportExportKeyParameters? keyParams = null)
|
||||
{
|
||||
return ItemImport (data, ref format, ref itemType, flags, keyParams);
|
||||
}
|
||||
|
||||
static CFArray ItemImport (CFData data, ref SecExternalFormat format, ref SecExternalItemType itemType,
|
||||
SecItemImportExportFlags flags = SecItemImportExportFlags.None,
|
||||
SecItemImportExportKeyParameters? keyParams = null)
|
||||
SecItemImportExportFlags flags = SecItemImportExportFlags.None,
|
||||
SecItemImportExportKeyParameters? keyParams = null)
|
||||
{
|
||||
IntPtr keyParamsPtr = IntPtr.Zero;
|
||||
if (keyParams != null) {
|
||||
@@ -127,18 +115,18 @@ namespace Mono.AppleTls {
|
||||
/* SecCertificateRef */ IntPtr certificate,
|
||||
/* SecKeyRef */ IntPtr privateKey);
|
||||
|
||||
static public SecIdentity ItemImport (X509Certificate2 certificate)
|
||||
static public SafeSecIdentityHandle ItemImport (X509Certificate2 certificate)
|
||||
{
|
||||
if (!certificate.HasPrivateKey)
|
||||
throw new NotSupportedException ();
|
||||
|
||||
using (var key = ImportPrivateKey (certificate))
|
||||
using (var cert = new SecCertificate (certificate)) {
|
||||
var identity = SecIdentityCreate (IntPtr.Zero, cert.Handle, key.Handle);
|
||||
if (CFType.GetTypeID (identity) != SecIdentity.GetTypeID ())
|
||||
using (var cert = MonoCertificatePal.FromOtherCertificate (certificate)) {
|
||||
var identity = SecIdentityCreate (IntPtr.Zero, cert.DangerousGetHandle (), key.DangerousGetHandle ());
|
||||
if (!MonoCertificatePal.IsSecIdentity (identity))
|
||||
throw new InvalidOperationException ();
|
||||
|
||||
return new SecIdentity (identity, true);
|
||||
return new SafeSecIdentityHandle (identity, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +140,7 @@ namespace Mono.AppleTls {
|
||||
#endif
|
||||
}
|
||||
|
||||
static SecKey ImportPrivateKey (X509Certificate2 certificate)
|
||||
static SafeSecKeyRefHandle ImportPrivateKey (X509Certificate2 certificate)
|
||||
{
|
||||
if (!certificate.HasPrivateKey)
|
||||
throw new NotSupportedException ();
|
||||
@@ -166,10 +154,10 @@ namespace Mono.AppleTls {
|
||||
throw new InvalidOperationException ("Private key import failed.");
|
||||
|
||||
var imported = items[0];
|
||||
if (CFType.GetTypeID (imported) != SecKey.GetTypeID ())
|
||||
if (!MonoCertificatePal.IsSecKey (imported))
|
||||
throw new InvalidOperationException ("Private key import doesn't return SecKey.");
|
||||
|
||||
return new SecKey (imported, items.Handle);
|
||||
return new SafeSecKeyRefHandle (imported, items.Handle);
|
||||
} finally {
|
||||
items.Dispose ();
|
||||
}
|
||||
@@ -178,7 +166,8 @@ namespace Mono.AppleTls {
|
||||
const int SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION = 0;
|
||||
|
||||
// Native enum; don't change.
|
||||
enum SecExternalFormat : int {
|
||||
enum SecExternalFormat : int
|
||||
{
|
||||
Unknown = 0,
|
||||
OpenSSL = 1,
|
||||
X509Cert = 9,
|
||||
@@ -188,7 +177,8 @@ namespace Mono.AppleTls {
|
||||
}
|
||||
|
||||
// Native enum; don't change.
|
||||
enum SecExternalItemType : int {
|
||||
enum SecExternalItemType : int
|
||||
{
|
||||
Unknown = 0,
|
||||
PrivateKey = 1,
|
||||
PublicKey = 2,
|
||||
@@ -198,14 +188,16 @@ namespace Mono.AppleTls {
|
||||
}
|
||||
|
||||
// Native enum; don't change
|
||||
enum SecItemImportExportFlags : int {
|
||||
enum SecItemImportExportFlags : int
|
||||
{
|
||||
None,
|
||||
PemArmour = 0x00000001, /* exported blob is PEM formatted */
|
||||
}
|
||||
|
||||
// Native struct; don't change
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
struct SecItemImportExportKeyParameters {
|
||||
struct SecItemImportExportKeyParameters
|
||||
{
|
||||
public int version; /* SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION */
|
||||
public int flags; /* SecKeyImportExportFlags bits */
|
||||
public IntPtr passphrase; /* SecExternalFormat.PKCS12 only. Legal types are CFStringRef and CFDataRef. */
|
||||
@@ -218,7 +210,5 @@ namespace Mono.AppleTls {
|
||||
IntPtr keyUsage;
|
||||
IntPtr keyAttributes;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
190
mcs/class/System/Mono.AppleTls/MonoCertificatePal.cs
Normal file
190
mcs/class/System/Mono.AppleTls/MonoCertificatePal.cs
Normal file
@@ -0,0 +1,190 @@
|
||||
//
|
||||
// MonoCertificatePal.cs
|
||||
//
|
||||
// Authors:
|
||||
// Miguel de Icaza
|
||||
// Sebastien Pouliot <sebastien@xamarin.com>
|
||||
// Martin Baulig <mabaul@microsoft.com>
|
||||
//
|
||||
// Copyright 2010 Novell, Inc
|
||||
// Copyright 2011-2014 Xamarin Inc.
|
||||
// Copyright (c) 2018 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.Apple;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using Mono.Net;
|
||||
|
||||
namespace Mono.AppleTls
|
||||
{
|
||||
static partial class MonoCertificatePal
|
||||
{
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static IntPtr SecCertificateCreateWithData (IntPtr allocator, IntPtr cfData);
|
||||
|
||||
public static SafeSecCertificateHandle FromOtherCertificate (X509Certificate certificate)
|
||||
{
|
||||
if (certificate == null)
|
||||
throw new ArgumentNullException (nameof (certificate));
|
||||
return FromOtherCertificate (certificate.Impl);
|
||||
}
|
||||
|
||||
public static SafeSecCertificateHandle FromOtherCertificate (X509CertificateImpl impl)
|
||||
{
|
||||
X509Helper.ThrowIfContextInvalid (impl);
|
||||
|
||||
var handle = impl.GetNativeAppleCertificate ();
|
||||
if (handle != IntPtr.Zero)
|
||||
return new SafeSecCertificateHandle (handle, false);
|
||||
|
||||
using (var data = CFData.FromData (impl.RawData)) {
|
||||
handle = SecCertificateCreateWithData (IntPtr.Zero, data.Handle);
|
||||
if (handle == IntPtr.Zero)
|
||||
throw new ArgumentException ("Not a valid DER-encoded X.509 certificate");
|
||||
|
||||
return new SafeSecCertificateHandle (handle, true);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static IntPtr SecIdentityGetTypeID ();
|
||||
|
||||
public static bool IsSecIdentity (IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
return false;
|
||||
return CFType.GetTypeID (ptr) == SecIdentityGetTypeID ();
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
public extern static IntPtr SecKeyGetTypeID ();
|
||||
|
||||
public static bool IsSecKey (IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
return false;
|
||||
return CFType.GetTypeID (ptr) == SecKeyGetTypeID ();
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static /* OSStatus */ SecStatusCode SecIdentityCopyCertificate (/* SecIdentityRef */ IntPtr identityRef, /* SecCertificateRef* */ out IntPtr certificateRef);
|
||||
|
||||
public static SafeSecCertificateHandle GetCertificate (SafeSecIdentityHandle identity)
|
||||
{
|
||||
if (identity == null || identity.IsInvalid)
|
||||
throw new ArgumentNullException (nameof (identity));
|
||||
var result = SecIdentityCopyCertificate (identity.DangerousGetHandle (), out var cert);
|
||||
if (result != SecStatusCode.Success)
|
||||
throw new InvalidOperationException (result.ToString ());
|
||||
return new SafeSecCertificateHandle (cert, true);
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static IntPtr SecCertificateCopySubjectSummary (IntPtr cert);
|
||||
|
||||
public static string GetSubjectSummary (SafeSecCertificateHandle certificate)
|
||||
{
|
||||
if (certificate == null || certificate.IsInvalid)
|
||||
throw new ArgumentNullException (nameof (certificate));
|
||||
|
||||
var subjectSummaryHandle = IntPtr.Zero;
|
||||
try {
|
||||
subjectSummaryHandle = SecCertificateCopySubjectSummary (certificate.DangerousGetHandle ());
|
||||
return CFString.AsString (subjectSummaryHandle);
|
||||
} finally {
|
||||
if (subjectSummaryHandle != IntPtr.Zero)
|
||||
CFObject.CFRelease (subjectSummaryHandle);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static /* CFDataRef */ IntPtr SecCertificateCopyData (/* SecCertificateRef */ IntPtr cert);
|
||||
|
||||
public static byte[] GetRawData (SafeSecCertificateHandle certificate)
|
||||
{
|
||||
if (certificate == null || certificate.IsInvalid)
|
||||
throw new ArgumentNullException (nameof (certificate));
|
||||
|
||||
var dataPtr = SecCertificateCopyData (certificate.DangerousGetHandle ());
|
||||
if (dataPtr == IntPtr.Zero)
|
||||
throw new ArgumentException ("Not a valid certificate");
|
||||
|
||||
using (var data = new CFData (dataPtr, true)) {
|
||||
var buffer = new byte[(int)data.Length];
|
||||
Marshal.Copy (data.Bytes, buffer, 0, buffer.Length);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static bool Equals (SafeSecCertificateHandle first, SafeSecCertificateHandle second)
|
||||
{
|
||||
/*
|
||||
* This is a little bit expensive, but unfortunately there is no better API to compare two
|
||||
* SecCertificateRef's for equality.
|
||||
*/
|
||||
if (first == null || first.IsInvalid)
|
||||
throw new ArgumentNullException (nameof (first));
|
||||
if (second == null || second.IsInvalid)
|
||||
throw new ArgumentNullException (nameof (second));
|
||||
if (first.DangerousGetHandle () == second.DangerousGetHandle ())
|
||||
return true;
|
||||
|
||||
var firstDataPtr = SecCertificateCopyData (first.DangerousGetHandle ());
|
||||
var secondDataPtr = SecCertificateCopyData (first.DangerousGetHandle ());
|
||||
|
||||
try {
|
||||
if (firstDataPtr == IntPtr.Zero || secondDataPtr == IntPtr.Zero)
|
||||
throw new ArgumentException ("Not a valid certificate.");
|
||||
if (firstDataPtr == secondDataPtr)
|
||||
return true;
|
||||
|
||||
var firstLength = (int)CFData.CFDataGetLength (firstDataPtr);
|
||||
var secondLength = (int)CFData.CFDataGetLength (secondDataPtr);
|
||||
if (firstLength != secondLength)
|
||||
return false;
|
||||
|
||||
var firstBytePtr = CFData.CFDataGetBytePtr (firstDataPtr);
|
||||
var secondBytePtr = CFData.CFDataGetBytePtr (secondDataPtr);
|
||||
if (firstBytePtr == secondBytePtr)
|
||||
return true;
|
||||
|
||||
var firstBuffer = new byte[firstLength];
|
||||
var secondBuffer = new byte[secondLength];
|
||||
Marshal.Copy (firstBytePtr, firstBuffer, 0, firstBuffer.Length);
|
||||
Marshal.Copy (secondBytePtr, secondBuffer, 0, secondBuffer.Length);
|
||||
|
||||
for (int i = 0; i < firstBuffer.Length; i++)
|
||||
if (firstBuffer[i] != secondBuffer[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
if (firstDataPtr != IntPtr.Zero)
|
||||
CFObject.CFRelease (firstDataPtr);
|
||||
if (secondDataPtr != IntPtr.Zero)
|
||||
CFObject.CFRelease (secondDataPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,3 @@
|
||||
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
|
||||
//
|
||||
// Policy.cs: Implements the managed SecPolicy wrapper.
|
||||
//
|
||||
@@ -84,4 +83,3 @@ namespace Mono.AppleTls {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
94
mcs/class/System/Mono.AppleTls/SafeHandles.Mono.cs
Normal file
94
mcs/class/System/Mono.AppleTls/SafeHandles.Mono.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
//
|
||||
// SafeHandles.cs
|
||||
//
|
||||
// Author:
|
||||
// Martin Baulig <mabaul@microsoft.com>
|
||||
//
|
||||
// Copyright (c) 2018 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.Apple;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using Mono.Net;
|
||||
|
||||
namespace System.Security.Cryptography.X509Certificates
|
||||
{
|
||||
partial class SafeSecIdentityHandle
|
||||
{
|
||||
public SafeSecIdentityHandle (IntPtr handle, bool ownsHandle = false)
|
||||
: base (handle, ownsHandle)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
partial class SafeSecCertificateHandle
|
||||
{
|
||||
public SafeSecCertificateHandle (IntPtr handle, bool ownsHandle = false)
|
||||
: base (handle, ownsHandle)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace System.Security.Cryptography.Apple
|
||||
{
|
||||
partial class SafeKeychainItemHandle
|
||||
{
|
||||
public SafeKeychainItemHandle (IntPtr handle, bool ownsHandle)
|
||||
: base (handle, ownsHandle)
|
||||
{
|
||||
if (!ownsHandle)
|
||||
CFObject.CFRetain (handle);
|
||||
}
|
||||
}
|
||||
|
||||
partial class SafeSecKeyRefHandle
|
||||
{
|
||||
public SafeSecKeyRefHandle (IntPtr handle, bool ownsHandle = false)
|
||||
: base (handle, ownsHandle)
|
||||
{
|
||||
}
|
||||
|
||||
IntPtr owner;
|
||||
|
||||
/*
|
||||
* SecItemImport() returns a SecArrayRef. We need to free the array, not the items inside it.
|
||||
*
|
||||
*/
|
||||
public SafeSecKeyRefHandle (IntPtr handle, IntPtr owner)
|
||||
: base (handle, false)
|
||||
{
|
||||
this.owner = owner;
|
||||
CFObject.CFRetain (owner);
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle ()
|
||||
{
|
||||
if (owner != IntPtr.Zero) {
|
||||
CFObject.CFRelease (owner);
|
||||
owner = IntPtr.Zero;
|
||||
SetHandle (IntPtr.Zero);
|
||||
return true;
|
||||
}
|
||||
return base.ReleaseHandle ();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
71
mcs/class/System/Mono.AppleTls/SafeHandles.cs
Normal file
71
mcs/class/System/Mono.AppleTls/SafeHandles.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// SafeHandles.Mono.cs
|
||||
//
|
||||
// Author:
|
||||
// Martin Baulig <mabaul@microsoft.com>
|
||||
//
|
||||
// Copyright (c) 2018 Xamarin Inc. (http://www.xamarin.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.Apple;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using Mono.Net;
|
||||
|
||||
namespace System.Security.Cryptography.X509Certificates
|
||||
{
|
||||
sealed partial class SafeSecIdentityHandle : SafeKeychainItemHandle
|
||||
{
|
||||
public SafeSecIdentityHandle ()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
sealed partial class SafeSecCertificateHandle : SafeKeychainItemHandle
|
||||
{
|
||||
public SafeSecCertificateHandle ()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace System.Security.Cryptography.Apple
|
||||
{
|
||||
partial class SafeKeychainItemHandle : SafeHandle
|
||||
{
|
||||
internal SafeKeychainItemHandle ()
|
||||
: base (IntPtr.Zero, ownsHandle: true)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle ()
|
||||
{
|
||||
if (handle != IntPtr.Zero)
|
||||
CFObject.CFRelease (handle);
|
||||
SetHandle (IntPtr.Zero);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool IsInvalid => handle == IntPtr.Zero;
|
||||
}
|
||||
|
||||
partial class SafeSecKeyRefHandle : SafeKeychainItemHandle
|
||||
{
|
||||
}
|
||||
}
|
@@ -1,4 +1,3 @@
|
||||
#if MONO_FEATURE_APPLETLS
|
||||
// Copyright 2014 Xamarin Inc. All rights reserved.
|
||||
|
||||
namespace Mono.AppleTls {
|
||||
@@ -248,4 +247,3 @@ namespace Mono.AppleTls {
|
||||
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032, // iOS 9+
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,4 +1,3 @@
|
||||
#if MONO_FEATURE_APPLETLS
|
||||
//
|
||||
// SslConnection
|
||||
//
|
||||
@@ -15,4 +14,3 @@ namespace Mono.AppleTls
|
||||
delegate SslStatus SslReadFunc (IntPtr connection, IntPtr data, /* size_t* */ ref IntPtr dataLength);
|
||||
delegate SslStatus SslWriteFunc (IntPtr connection, IntPtr data, /* size_t* */ ref IntPtr dataLength);
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,4 +1,3 @@
|
||||
#if SECURITY_DEP && MONO_FEATURE_APPLETLS
|
||||
//
|
||||
// Trust.cs: Implements the managed SecTrust wrapper.
|
||||
//
|
||||
@@ -61,18 +60,21 @@ namespace Mono.AppleTls {
|
||||
if (certificates == null)
|
||||
throw new ArgumentNullException ("certificates");
|
||||
|
||||
SecCertificate[] array = new SecCertificate [certificates.Count];
|
||||
var array = new SafeSecCertificateHandle [certificates.Count];
|
||||
int i = 0;
|
||||
foreach (var certificate in certificates)
|
||||
array [i++] = new SecCertificate (certificate);
|
||||
array [i++] = MonoCertificatePal.FromOtherCertificate (certificate);
|
||||
Initialize (array, policy);
|
||||
for (i = 0; i < array.Length; i++)
|
||||
array [i].Dispose ();
|
||||
}
|
||||
|
||||
void Initialize (SecCertificate[] array, SecPolicy policy)
|
||||
void Initialize (SafeSecCertificateHandle[] array, SecPolicy policy)
|
||||
{
|
||||
using (var certs = CFArray.CreateArray (array)) {
|
||||
var handles = new IntPtr [array.Length];
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
handles [i] = array [i].DangerousGetHandle ();
|
||||
using (var certs = CFArray.CreateArray (handles)) {
|
||||
Initialize (certs.Handle, policy);
|
||||
}
|
||||
}
|
||||
@@ -113,17 +115,6 @@ namespace Mono.AppleTls {
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
extern static IntPtr /* SecCertificateRef */ SecTrustGetCertificateAtIndex (IntPtr /* SecTrustRef */ trust, IntPtr /* CFIndex */ ix);
|
||||
|
||||
public SecCertificate this [IntPtr index] {
|
||||
get {
|
||||
if (handle == IntPtr.Zero)
|
||||
throw new ObjectDisposedException ("SecTrust");
|
||||
if (((long)index < 0) || ((long)index >= Count))
|
||||
throw new ArgumentOutOfRangeException ("index");
|
||||
|
||||
return new SecCertificate (SecTrustGetCertificateAtIndex (handle, index));
|
||||
}
|
||||
}
|
||||
|
||||
internal X509Certificate GetCertificate (int index)
|
||||
{
|
||||
if (handle == IntPtr.Zero)
|
||||
@@ -132,7 +123,8 @@ namespace Mono.AppleTls {
|
||||
throw new ArgumentOutOfRangeException ("index");
|
||||
|
||||
var ptr = SecTrustGetCertificateAtIndex (handle, (IntPtr)index);
|
||||
return new X509Certificate (ptr);
|
||||
var impl = new X509CertificateImplApple (ptr, false);
|
||||
return new X509Certificate (impl);
|
||||
}
|
||||
|
||||
[DllImport (AppleTlsContext.SecurityLibrary)]
|
||||
@@ -145,18 +137,21 @@ namespace Mono.AppleTls {
|
||||
if (certificates == null)
|
||||
return SecTrustSetAnchorCertificates (handle, IntPtr.Zero);
|
||||
|
||||
SecCertificate[] array = new SecCertificate [certificates.Count];
|
||||
var array = new SafeSecCertificateHandle [certificates.Count];
|
||||
int i = 0;
|
||||
foreach (var certificate in certificates)
|
||||
array [i++] = new SecCertificate (certificate);
|
||||
array [i++] = MonoCertificatePal.FromOtherCertificate (certificate);
|
||||
return SetAnchorCertificates (array);
|
||||
}
|
||||
|
||||
public SecStatusCode SetAnchorCertificates (SecCertificate[] array)
|
||||
public SecStatusCode SetAnchorCertificates (SafeSecCertificateHandle[] array)
|
||||
{
|
||||
if (array == null)
|
||||
return SecTrustSetAnchorCertificates (handle, IntPtr.Zero);
|
||||
using (var certs = CFArray.FromNativeObjects (array)) {
|
||||
var handles = new IntPtr [array.Length];
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
handles [i] = array [i].DangerousGetHandle ();
|
||||
using (var certs = CFArray.CreateArray (handles)) {
|
||||
return SecTrustSetAnchorCertificates (handle, certs.Handle);
|
||||
}
|
||||
}
|
||||
@@ -205,4 +200,3 @@ namespace Mono.AppleTls {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
173
mcs/class/System/Mono.AppleTls/X509CertificateImplApple.cs
Normal file
173
mcs/class/System/Mono.AppleTls/X509CertificateImplApple.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
#if MONO_FEATURE_APPLETLS || MONO_FEATURE_APPLE_X509
|
||||
#if MONO_SECURITY_ALIAS
|
||||
extern alias MonoSecurity;
|
||||
#endif
|
||||
|
||||
#if MONO_SECURITY_ALIAS
|
||||
using MX = MonoSecurity::Mono.Security.X509;
|
||||
#else
|
||||
using MX = Mono.Security.X509;
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using XamMac.CoreFoundation;
|
||||
|
||||
namespace Mono.AppleTls
|
||||
{
|
||||
class X509CertificateImplApple : X509CertificateImpl
|
||||
{
|
||||
IntPtr handle;
|
||||
X509CertificateImpl fallback;
|
||||
|
||||
public X509CertificateImplApple (IntPtr handle, bool owns)
|
||||
{
|
||||
this.handle = handle;
|
||||
if (!owns)
|
||||
CFHelpers.CFRetain (handle);
|
||||
}
|
||||
|
||||
public override bool IsValid {
|
||||
get { return handle != IntPtr.Zero; }
|
||||
}
|
||||
|
||||
public override IntPtr Handle {
|
||||
get { return handle; }
|
||||
}
|
||||
|
||||
public override IntPtr GetNativeAppleCertificate ()
|
||||
{
|
||||
ThrowIfContextInvalid ();
|
||||
return handle;
|
||||
}
|
||||
|
||||
public override X509CertificateImpl Clone ()
|
||||
{
|
||||
ThrowIfContextInvalid ();
|
||||
return new X509CertificateImplApple (handle, false);
|
||||
}
|
||||
|
||||
[DllImport (CFHelpers.SecurityLibrary)]
|
||||
extern static IntPtr SecCertificateCopySubjectSummary (IntPtr cert);
|
||||
|
||||
[DllImport (CFHelpers.SecurityLibrary)]
|
||||
extern static IntPtr SecCertificateCopyData (IntPtr cert);
|
||||
|
||||
public override byte[] RawData {
|
||||
get {
|
||||
ThrowIfContextInvalid ();
|
||||
var data = SecCertificateCopyData (handle);
|
||||
if (data == IntPtr.Zero)
|
||||
throw new ArgumentException ("Not a valid certificate");
|
||||
|
||||
try {
|
||||
return CFHelpers.FetchDataBuffer (data);
|
||||
} finally {
|
||||
CFHelpers.CFRelease (data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string GetSubjectSummary ()
|
||||
{
|
||||
ThrowIfContextInvalid ();
|
||||
IntPtr cfstr = SecCertificateCopySubjectSummary (handle);
|
||||
string ret = CFHelpers.FetchString (cfstr);
|
||||
CFHelpers.CFRelease (cfstr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public override byte[] Thumbprint {
|
||||
get {
|
||||
// FIXME: might just return 'null' when 'lazy' is true.
|
||||
ThrowIfContextInvalid ();
|
||||
SHA1 sha = SHA1.Create ();
|
||||
return sha.ComputeHash (RawData);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals (X509CertificateImpl other, out bool result)
|
||||
{
|
||||
var otherAppleImpl = other as X509CertificateImplApple;
|
||||
if (otherAppleImpl != null && otherAppleImpl.handle == handle) {
|
||||
result = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
result = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void MustFallback ()
|
||||
{
|
||||
ThrowIfContextInvalid ();
|
||||
if (fallback != null)
|
||||
return;
|
||||
var mxCert = new MX.X509Certificate (RawData);
|
||||
fallback = new X509Certificate2ImplMono (mxCert);
|
||||
}
|
||||
|
||||
public X509CertificateImpl FallbackImpl {
|
||||
get {
|
||||
MustFallback ();
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Subject => FallbackImpl.Subject;
|
||||
|
||||
public override string Issuer => FallbackImpl.Issuer;
|
||||
|
||||
public override string LegacySubject => FallbackImpl.LegacySubject;
|
||||
|
||||
public override string LegacyIssuer => FallbackImpl.LegacyIssuer;
|
||||
|
||||
public override DateTime NotAfter => FallbackImpl.NotAfter;
|
||||
|
||||
public override DateTime NotBefore => FallbackImpl.NotBefore;
|
||||
|
||||
public override string KeyAlgorithm => FallbackImpl.KeyAlgorithm;
|
||||
|
||||
public override byte[] KeyAlgorithmParameters => FallbackImpl.KeyAlgorithmParameters;
|
||||
|
||||
public override byte[] PublicKeyValue => FallbackImpl.PublicKeyValue;
|
||||
|
||||
public override byte[] SerialNumber => FallbackImpl.SerialNumber;
|
||||
|
||||
public override byte[] Export (X509ContentType contentType, SafePasswordHandle password)
|
||||
{
|
||||
ThrowIfContextInvalid ();
|
||||
|
||||
switch (contentType) {
|
||||
case X509ContentType.Cert:
|
||||
return RawData;
|
||||
case X509ContentType.Pfx: // this includes Pkcs12
|
||||
// TODO
|
||||
throw new NotSupportedException ();
|
||||
case X509ContentType.SerializedCert:
|
||||
// TODO
|
||||
throw new NotSupportedException ();
|
||||
default:
|
||||
string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
|
||||
throw new CryptographicException (msg);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (handle != IntPtr.Zero){
|
||||
CFHelpers.CFRelease (handle);
|
||||
handle = IntPtr.Zero;
|
||||
}
|
||||
if (fallback != null) {
|
||||
fallback.Dispose ();
|
||||
fallback = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user