--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+namespace XamMac.CoreFoundation
+{
+ internal static class CFHelpers
+ {
+ internal const string CoreFoundationLibrary = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation";
+ internal const string SecurityLibrary = "/System/Library/Frameworks/Security.framework/Security";
+
+ [DllImport (CoreFoundationLibrary)]
+ internal extern static void CFRelease (IntPtr obj);
+
+ [DllImport (CoreFoundationLibrary)]
+ internal extern static IntPtr CFRetain (IntPtr obj);
+
+ [StructLayout (LayoutKind.Sequential)]
+ struct CFRange {
+ public IntPtr loc;
+ public IntPtr len;
+
+ public CFRange (int loc, int len)
+ : this ((long) loc, (long) len)
+ {
+ }
+
+ public CFRange (long l, long len)
+ {
+ this.loc = (IntPtr) l;
+ this.len = (IntPtr) len;
+ }
+ }
+
+ [DllImport (CoreFoundationLibrary, CharSet=CharSet.Unicode)]
+ extern static IntPtr CFStringCreateWithCharacters (IntPtr allocator, string str, IntPtr count);
+
+ [DllImport (CoreFoundationLibrary, CharSet=CharSet.Unicode)]
+ extern static IntPtr CFStringGetLength (IntPtr handle);
+
+ [DllImport (CoreFoundationLibrary, CharSet=CharSet.Unicode)]
+ extern static IntPtr CFStringGetCharactersPtr (IntPtr handle);
+
+ [DllImport (CoreFoundationLibrary, CharSet=CharSet.Unicode)]
+ extern static IntPtr CFStringGetCharacters (IntPtr handle, CFRange range, IntPtr buffer);
+
+ internal static string FetchString (IntPtr handle)
+ {
+ if (handle == IntPtr.Zero)
+ return null;
+
+ string str;
+
+ int l = (int)CFStringGetLength (handle);
+ IntPtr u = CFStringGetCharactersPtr (handle);
+ IntPtr buffer = IntPtr.Zero;
+ if (u == IntPtr.Zero){
+ CFRange r = new CFRange (0, l);
+ buffer = Marshal.AllocCoTaskMem (l * 2);
+ CFStringGetCharacters (handle, r, buffer);
+ u = buffer;
+ }
+ unsafe {
+ str = new string ((char *) u, 0, l);
+ }
+
+ if (buffer != IntPtr.Zero)
+ Marshal.FreeCoTaskMem (buffer);
+
+ return str;
+ }
+
+ [DllImport (CoreFoundationLibrary)]
+ extern static IntPtr CFDataGetLength (IntPtr handle);
+
+ [DllImport (CoreFoundationLibrary)]
+ extern static IntPtr CFDataGetBytePtr (IntPtr handle);
+
+ internal static byte[] FetchDataBuffer (IntPtr handle)
+ {
+ var length = (int)CFDataGetLength (handle);
+ var buffer = new byte [length];
+ var ptr = CFDataGetBytePtr (handle);
+ Marshal.Copy (ptr, buffer, 0, buffer.Length);
+ return buffer;
+ }
+
+ [DllImport (CoreFoundationLibrary)]
+ extern static IntPtr CFDataCreateWithBytesNoCopy (IntPtr allocator, IntPtr bytes, IntPtr length, IntPtr bytesDeallocator);
+
+ [DllImport (CoreFoundationLibrary)]
+ extern static IntPtr CFDataCreate (IntPtr allocator, IntPtr bytes, IntPtr length);
+
+ [DllImport (SecurityLibrary)]
+ extern static IntPtr SecCertificateCreateWithData (IntPtr allocator, IntPtr cfData);
+
+ unsafe internal static IntPtr CreateCertificateFromData (byte[] data)
+ {
+ fixed (void *ptr = data) {
+ var cfdata = CFDataCreate (IntPtr.Zero, (IntPtr)ptr, new IntPtr (data.Length));
+ if (cfdata == IntPtr.Zero)
+ return IntPtr.Zero;
+
+ var certificate = SecCertificateCreateWithData (IntPtr.Zero, cfdata);
+ if (cfdata != IntPtr.Zero)
+ CFRelease (cfdata);
+ return certificate;
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Text;
+using System.Runtime.InteropServices;
+using XamMac.CoreFoundation;
+using MX = Mono.Security.X509;
+
+namespace System.Security.Cryptography.X509Certificates
+{
+ 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 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[] GetRawCertData ()
+ {
+ 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 override string GetSubjectSummary ()
+ {
+ ThrowIfContextInvalid ();
+ IntPtr cfstr = SecCertificateCopySubjectSummary (handle);
+ string ret = CFHelpers.FetchString (cfstr);
+ CFHelpers.CFRelease (cfstr);
+ return ret;
+ }
+
+ protected override byte[] GetCertHash (bool lazy)
+ {
+ // FIXME: might just return 'null' when 'lazy' is true.
+ ThrowIfContextInvalid ();
+ SHA1 sha = SHA1.Create ();
+ return sha.ComputeHash (GetRawCertData ());
+ }
+
+ 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 (GetRawCertData ());
+ fallback = new X509CertificateImplMono (mxCert);
+ }
+
+ public X509CertificateImpl FallbackImpl {
+ get {
+ MustFallback ();
+ return fallback;
+ }
+ }
+
+ public override string GetSubjectName (bool legacyV1Mode)
+ {
+ return FallbackImpl.GetSubjectName (legacyV1Mode);
+ }
+
+ public override string GetIssuerName (bool legacyV1Mode)
+ {
+ return FallbackImpl.GetIssuerName (legacyV1Mode);
+ }
+
+ public override DateTime GetEffectiveDateString ()
+ {
+ return FallbackImpl.GetEffectiveDateString ();
+ }
+
+ public override DateTime GetExpirationDateString ()
+ {
+ return FallbackImpl.GetExpirationDateString ();
+ }
+
+ public override string GetKeyAlgorithm ()
+ {
+ return FallbackImpl.GetKeyAlgorithm ();
+ }
+
+ public override byte[] GetKeyAlgorithmParameters ()
+ {
+ return FallbackImpl.GetKeyAlgorithmParameters ();
+ }
+
+ public override byte[] GetPublicKey ()
+ {
+ return FallbackImpl.GetPublicKey ();
+ }
+
+ public override byte[] GetSerialNumber ()
+ {
+ return FallbackImpl.GetSerialNumber ();
+ }
+
+ public override byte[] Export (X509ContentType contentType, byte[] password)
+ {
+ ThrowIfContextInvalid ();
+
+ switch (contentType) {
+ case X509ContentType.Cert:
+ return GetRawCertData ();
+ 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);
+ }
+ }
+
+ public override string ToString (bool full)
+ {
+ ThrowIfContextInvalid ();
+
+ if (!full || fallback == null) {
+ var summary = GetSubjectSummary ();
+ return string.Format ("[X509Certificate: {0}]", summary);
+ }
+
+ string nl = Environment.NewLine;
+ StringBuilder sb = new StringBuilder ();
+ sb.AppendFormat ("[Subject]{0} {1}{0}{0}", nl, GetSubjectName (false));
+
+ sb.AppendFormat ("[Issuer]{0} {1}{0}{0}", nl, GetIssuerName (false));
+ sb.AppendFormat ("[Not Before]{0} {1}{0}{0}", nl, GetEffectiveDateString ());
+ sb.AppendFormat ("[Not After]{0} {1}{0}{0}", nl, GetExpirationDateString ());
+ sb.AppendFormat ("[Thumbprint]{0} {1}{0}", nl, X509Helper.ToHexString (GetCertHash ()));
+
+ sb.Append (nl);
+ return sb.ToString ();
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ if (handle != IntPtr.Zero){
+ CFHelpers.CFRelease (handle);
+ handle = IntPtr.Zero;
+ }
+ if (fallback != null) {
+ fallback.Dispose ();
+ fallback = null;
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+using MX = Mono.Security.X509;
+using XamMac.CoreFoundation;
+
+namespace System.Security.Cryptography.X509Certificates
+{
+ static partial class X509Helper
+ {
+ public static X509CertificateImpl InitFromHandle (IntPtr handle)
+ {
+ return new X509CertificateImplApple (handle, false);
+ }
+
+ public static X509CertificateImpl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
+ {
+ MX.X509Certificate x509;
+ IntPtr handle;
+ if (password == null) {
+ handle = CFHelpers.CreateCertificateFromData (rawData);
+ if (handle != IntPtr.Zero)
+ return new X509CertificateImplApple (handle, true);
+
+ try {
+ x509 = new MX.X509Certificate (rawData);
+ } catch (Exception e) {
+ try {
+ x509 = X509Helper.ImportPkcs12 (rawData, null);
+ } catch {
+ string msg = Locale.GetText ("Unable to decode certificate.");
+ // inner exception is the original (not second) exception
+ throw new CryptographicException (msg, e);
+ }
+ }
+ } else {
+ // try PKCS#12
+ try {
+ x509 = X509Helper.ImportPkcs12 (rawData, password);
+ }
+ catch {
+ // it's possible to supply a (unrequired/unusued) password
+ // fix bug #79028
+ x509 = new MX.X509Certificate (rawData);
+ }
+ }
+
+ return new X509CertificateImplMono (x509);
+ }
+ }
+}
+++ /dev/null
-#if MONOTOUCH || XAMMAC
-
-// this file is a shim to enable compiling monotouch profiles without mono-extensions
-namespace System.Security.Cryptography.X509Certificates
-{
- static partial class X509Helper
- {
- public static X509CertificateImpl InitFromHandle (IntPtr handle)
- {
- throw new NotSupportedException ();
- }
-
- public static X509CertificateImpl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
- {
- throw new NotSupportedException ();
- }
- }
-}
-
-#endif
System/Environment.iOS.cs
System/Guid.MonoTouch.cs
System/NotSupportedException.iOS.cs
+CoreFoundation/CFHelpers.cs
+System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
+System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
System.Text/EncodingHelper.MonoTouch.opt.cs
-System.Security.Cryptography.X509Certificates/X509Helper.MonoTouch.opt.cs
System/Environment.iOS.cs
System/Guid.MonoTouch.cs
System/NotSupportedException.iOS.cs
+CoreFoundation/CFHelpers.cs
+System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
+System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
System/Environment.iOS.cs
System/Guid.MonoTouch.cs
System/NotSupportedException.iOS.cs
+CoreFoundation/CFHelpers.cs
+System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
+System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
System/Environment.iOS.cs
System/Guid.MonoTouch.cs
System/NotSupportedException.iOS.cs
+CoreFoundation/CFHelpers.cs
+System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
+System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
CommonCrypto/RC4CommonCrypto.cs
CommonCrypto/MD2Managed.g.cs
CommonCrypto/MD4Managed.g.cs
+CoreFoundation/CFHelpers.cs
+System.Security.Cryptography.X509Certificates/X509CertificateImplApple.cs
+System.Security.Cryptography.X509Certificates/X509Helper.Apple.cs
+++ /dev/null
-System.Security.Cryptography.X509Certificates/X509Helper.MonoTouch.opt.cs