Merge pull request #2874 from lateralusX/jlorenss/win-x64-support
[mono.git] / mcs / class / corlib / System.Security.Cryptography.X509Certificates / X509CertificateImplApple.cs
1 using System;
2 using System.Text;
3 using System.Runtime.InteropServices;
4 using XamMac.CoreFoundation;
5 using MX = Mono.Security.X509;
6
7 namespace System.Security.Cryptography.X509Certificates
8 {
9         class X509CertificateImplApple : X509CertificateImpl
10         {
11                 IntPtr handle;
12                 X509CertificateImpl fallback;
13
14                 public X509CertificateImplApple (IntPtr handle, bool owns)
15                 {
16                         this.handle = handle;
17                         if (!owns)
18                                 CFHelpers.CFRetain (handle);
19                 }
20
21                 public override bool IsValid {
22                         get { return handle != IntPtr.Zero; }
23                 }
24
25                 public override IntPtr Handle {
26                         get { return handle; }
27                 }
28
29                 public override IntPtr GetNativeAppleCertificate ()
30                 {
31                         ThrowIfContextInvalid ();
32                         return handle;
33                 }
34
35                 public override X509CertificateImpl Clone ()
36                 {
37                         ThrowIfContextInvalid ();
38                         return new X509CertificateImplApple (handle, false);
39                 }
40
41                 [DllImport (CFHelpers.SecurityLibrary)]
42                 extern static IntPtr SecCertificateCopySubjectSummary (IntPtr cert);
43
44                 [DllImport (CFHelpers.SecurityLibrary)]
45                 extern static IntPtr SecCertificateCopyData (IntPtr cert);
46
47                 public override byte[] GetRawCertData ()
48                 {
49                         ThrowIfContextInvalid ();
50                         var data = SecCertificateCopyData (handle);
51                         if (data == IntPtr.Zero)
52                                 throw new ArgumentException ("Not a valid certificate");
53
54                         try {
55                                 return CFHelpers.FetchDataBuffer (data);
56                         } finally {
57                                 CFHelpers.CFRelease (data);
58                         }
59                 }
60
61                 public string GetSubjectSummary ()
62                 {
63                         ThrowIfContextInvalid ();
64                         IntPtr cfstr = SecCertificateCopySubjectSummary (handle);
65                         string ret = CFHelpers.FetchString (cfstr);
66                         CFHelpers.CFRelease (cfstr);
67                         return ret;
68                 }
69
70                 protected override byte[] GetCertHash (bool lazy)
71                 {
72                         // FIXME: might just return 'null' when 'lazy' is true.
73                         ThrowIfContextInvalid ();
74                         SHA1 sha = SHA1.Create ();
75                         return sha.ComputeHash (GetRawCertData ());
76                 }
77
78                 public override bool Equals (X509CertificateImpl other, out bool result)
79                 {
80                         var otherAppleImpl = other as X509CertificateImplApple;
81                         if (otherAppleImpl != null && otherAppleImpl.handle == handle) {
82                                 result = true;
83                                 return true;
84                         }
85
86                         result = false;
87                         return false;
88                 }
89
90                 void MustFallback ()
91                 {
92                         ThrowIfContextInvalid ();
93                         if (fallback != null)
94                                 return;
95                         var mxCert = new MX.X509Certificate (GetRawCertData ());
96                         fallback = new X509CertificateImplMono (mxCert);
97                 }
98
99                 public X509CertificateImpl FallbackImpl {
100                         get {
101                                 MustFallback ();
102                                 return fallback;
103                         }
104                 }
105
106                 public override string GetSubjectName (bool legacyV1Mode)
107                 {
108                         return FallbackImpl.GetSubjectName (legacyV1Mode);
109                 }
110
111                 public override string GetIssuerName (bool legacyV1Mode)
112                 {
113                         return FallbackImpl.GetIssuerName (legacyV1Mode);
114                 }
115
116                 public override DateTime GetValidFrom ()
117                 {
118                         return FallbackImpl.GetValidFrom ();
119                 }
120
121                 public override DateTime GetValidUntil ()
122                 {
123                         return FallbackImpl.GetValidUntil ();
124                 }
125
126                 public override string GetKeyAlgorithm ()
127                 {
128                         return FallbackImpl.GetKeyAlgorithm ();
129                 }
130
131                 public override byte[] GetKeyAlgorithmParameters ()
132                 {
133                         return FallbackImpl.GetKeyAlgorithmParameters ();
134                 }
135
136                 public override byte[] GetPublicKey ()
137                 {
138                         return FallbackImpl.GetPublicKey ();
139                 }
140
141                 public override byte[] GetSerialNumber ()
142                 {
143                         return FallbackImpl.GetSerialNumber ();
144                 }
145
146                 public override byte[] Export (X509ContentType contentType, byte[] password)
147                 {
148                         ThrowIfContextInvalid ();
149
150                         switch (contentType) {
151                         case X509ContentType.Cert:
152                                 return GetRawCertData ();
153                         case X509ContentType.Pfx: // this includes Pkcs12
154                                 // TODO
155                                 throw new NotSupportedException ();
156                         case X509ContentType.SerializedCert:
157                                 // TODO
158                                 throw new NotSupportedException ();
159                         default:
160                                 string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
161                                 throw new CryptographicException (msg);
162                         }
163                 }
164
165                 public override string ToString (bool full)
166                 {
167                         ThrowIfContextInvalid ();
168
169                         if (!full || fallback == null) {
170                                 var summary = GetSubjectSummary ();
171                                 return string.Format ("[X509Certificate: {0}]", summary);
172                         }
173
174                         string nl = Environment.NewLine;
175                         StringBuilder sb = new StringBuilder ();
176                         sb.AppendFormat ("[Subject]{0}  {1}{0}{0}", nl, GetSubjectName (false));
177
178                         sb.AppendFormat ("[Issuer]{0}  {1}{0}{0}", nl, GetIssuerName (false));
179                         sb.AppendFormat ("[Not Before]{0}  {1}{0}{0}", nl, GetValidFrom ().ToLocalTime ());
180                         sb.AppendFormat ("[Not After]{0}  {1}{0}{0}", nl, GetValidUntil ().ToLocalTime ());
181                         sb.AppendFormat ("[Thumbprint]{0}  {1}{0}", nl, X509Helper.ToHexString (GetCertHash ()));
182
183                         sb.Append (nl);
184                         return sb.ToString ();
185                 }
186
187                 protected override void Dispose (bool disposing)
188                 {
189                         if (handle != IntPtr.Zero){
190                                 CFHelpers.CFRelease (handle);
191                                 handle = IntPtr.Zero;
192                         }
193                         if (fallback != null) {
194                                 fallback.Dispose ();
195                                 fallback = null;
196                         }
197                 }
198         }
199 }