[bcl] Remove more NET_2_0 checks from class libs
[mono.git] / mcs / class / System.Security / System.Security.Cryptography.Pkcs / SignedCms.cs
1 //
2 // System.Security.Cryptography.Pkcs.SignedCms class
3 //
4 // Author:
5 //      Sebastien Pouliot  <sebastien@ximian.com>
6 //
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 #if SECURITY_DEP
31
32 using System.Security.Cryptography.X509Certificates;
33 using System.Security.Cryptography.Xml;
34 using System.Text;
35
36 using Mono.Security;
37 using Mono.Security.X509;
38
39 namespace System.Security.Cryptography.Pkcs {
40
41         public sealed class SignedCms {
42
43                 private ContentInfo _content;
44                 private bool _detached;
45                 private SignerInfoCollection _info;
46                 private X509Certificate2Collection _certs;
47                 private SubjectIdentifierType _type;
48                 private int _version;
49
50                 // constructors
51
52                 public SignedCms () 
53                 {
54                         _certs = new X509Certificate2Collection ();
55                         _info = new SignerInfoCollection ();
56                 }
57
58                 public SignedCms (ContentInfo content) 
59                         : this (content, false)
60                 {
61                 }
62
63                 public SignedCms (ContentInfo content, bool detached) 
64                         : this ()
65                 {
66                         if (content == null)
67                                 throw new ArgumentNullException ("content");
68
69                         _content = content;
70                         _detached = detached;
71                 }
72
73                 public SignedCms (SubjectIdentifierType signerIdentifierType) : this ()
74                 {
75                         _type = signerIdentifierType;
76                 }
77
78                 public SignedCms (SubjectIdentifierType signerIdentifierType, ContentInfo content) 
79                         : this (content, false) 
80                 {
81                         _type = signerIdentifierType;
82                 }
83
84                 public SignedCms (SubjectIdentifierType signerIdentifierType, ContentInfo content, bool detached) 
85                         : this (content, detached) 
86                 {
87                         _type = signerIdentifierType;
88                 }
89
90                 // properties
91
92                 public X509Certificate2Collection Certificates { 
93                         get { return _certs; }
94                 }
95
96                 public ContentInfo ContentInfo { 
97                         get { 
98                                 if (_content == null) {
99                                         Oid oid = new Oid (PKCS7.Oid.data);
100                                         _content = new ContentInfo (oid, new byte [0]);
101                                 }
102                                 return _content; 
103                         }
104                 }
105
106                 public bool Detached { 
107                         get { return _detached; }
108                 }
109
110                 public SignerInfoCollection SignerInfos {
111                         get { return _info; }
112                 }
113
114                 public int Version { 
115                         get { return _version; }
116                 }
117
118                 // methods
119
120                 [MonoTODO]
121                 public void CheckSignature (bool verifySignatureOnly)
122                 {
123                         foreach (SignerInfo si in _info) {
124                                 si.CheckSignature (verifySignatureOnly);
125                         }
126                 }
127
128                 [MonoTODO]
129                 public void CheckSignature (X509Certificate2Collection extraStore, bool verifySignatureOnly) 
130                 {
131                         foreach (SignerInfo si in _info) {
132                                 si.CheckSignature (extraStore, verifySignatureOnly);
133                         }
134                 }
135
136                 [MonoTODO]
137                 public void CheckHash () 
138                 {
139                         throw new InvalidOperationException ("");
140                 }
141
142                 [MonoTODO]
143                 public void ComputeSignature () 
144                 {
145                         throw new CryptographicException ("");
146                 }
147
148                 [MonoTODO]
149                 public void ComputeSignature (CmsSigner signer)
150                 {
151                         ComputeSignature ();
152                 }
153
154                 [MonoTODO]
155                 public void ComputeSignature (CmsSigner signer, bool silent)
156                 {
157                         ComputeSignature ();
158                 }
159
160                 private string ToString (byte[] array, bool reverse) 
161                 {
162                         StringBuilder sb = new StringBuilder ();
163                         if (reverse) {
164                                 for (int i=array.Length - 1; i >= 0; i--)
165                                         sb.Append (array [i].ToString ("X2"));
166                         } else {
167                                 for (int i=0; i < array.Length; i++)
168                                         sb.Append (array [i].ToString ("X2"));
169                         }
170                         return sb.ToString ();
171                 }
172
173                 private byte[] GetKeyIdentifier (Mono.Security.X509.X509Certificate x509) 
174                 {
175                         // if present in certificate return value of the SubjectKeyIdentifier
176                         Mono.Security.X509.X509Extension extn = x509.Extensions ["2.5.29.14"];
177                         if (extn != null) {
178                                 ASN1 bs = new ASN1 (extn.Value.Value);
179                                 return bs.Value;
180                         }
181                         // strangely DEPRECATED keyAttributes isn't used here (like KeyUsage)
182
183                         // if not then we must calculate the SubjectKeyIdentifier ourselve
184                         // Note: MS does that hash on the complete subjectPublicKeyInfo (unlike PKIX)
185                         // http://groups.google.ca/groups?selm=e7RqM%24plCHA.1488%40tkmsftngp02&oe=UTF-8&output=gplain
186                         ASN1 subjectPublicKeyInfo = new ASN1 (0x30);
187                         ASN1 algo = subjectPublicKeyInfo.Add (new ASN1 (0x30));
188                         algo.Add (new ASN1 (CryptoConfig.EncodeOID (x509.KeyAlgorithm)));
189                         // FIXME: does it work for DSA certs (without an 2.5.29.14 extension ?)
190                         algo.Add (new ASN1 (x509.KeyAlgorithmParameters)); 
191                         byte[] pubkey = x509.PublicKey;
192                         byte[] bsvalue = new byte [pubkey.Length + 1]; // add unused bits (0) before the public key
193                         Array.Copy (pubkey, 0, bsvalue, 1, pubkey.Length);
194                         subjectPublicKeyInfo.Add (new ASN1 (0x03, bsvalue));
195                         SHA1 sha = SHA1.Create ();
196                         return sha.ComputeHash (subjectPublicKeyInfo.GetBytes ());
197                 }
198
199                 [MonoTODO("incomplete - missing attributes")]
200                 public void Decode (byte[] encodedMessage) 
201                 {
202                         PKCS7.ContentInfo ci = new PKCS7.ContentInfo (encodedMessage);
203                         if (ci.ContentType != PKCS7.Oid.signedData) 
204                                 throw new Exception ("");
205
206                         PKCS7.SignedData sd = new PKCS7.SignedData (ci.Content);
207                         SubjectIdentifierType type = SubjectIdentifierType.Unknown;
208                         object o = null;
209
210                         X509Certificate2 x509 = null;
211                         if (sd.SignerInfo.Certificate != null) {
212                                 x509 = new X509Certificate2 (sd.SignerInfo.Certificate.RawData);
213                         }
214                         else if ((sd.SignerInfo.IssuerName != null) && (sd.SignerInfo.SerialNumber != null)) {
215                                 byte[] serial = sd.SignerInfo.SerialNumber;
216                                 Array.Reverse (serial); // ???
217                                 type = SubjectIdentifierType.IssuerAndSerialNumber;
218                                 X509IssuerSerial xis = new X509IssuerSerial ();
219                                 xis.IssuerName = sd.SignerInfo.IssuerName;
220                                 xis.SerialNumber = ToString (serial, true);
221                                 o = xis;
222                                 // TODO: move to a FindCertificate (issuer, serial, collection)
223                                 foreach (Mono.Security.X509.X509Certificate x in sd.Certificates) {
224                                         if (x.IssuerName == sd.SignerInfo.IssuerName) {
225                                                 if (ToString (x.SerialNumber, true) == xis.SerialNumber) {
226                                                         x509 = new X509Certificate2 (x.RawData);
227                                                         break;
228                                                 }
229                                         }
230                                 }
231                         }
232                         else if (sd.SignerInfo.SubjectKeyIdentifier != null) {
233                                 string ski = ToString (sd.SignerInfo.SubjectKeyIdentifier, false);
234                                 type = SubjectIdentifierType.SubjectKeyIdentifier;
235                                 o = (object) ski;
236                                 // TODO: move to a FindCertificate (ski, collection)
237                                 foreach (Mono.Security.X509.X509Certificate x in sd.Certificates) {
238                                         if (ToString (GetKeyIdentifier (x), false) == ski) {
239                                                 x509 = new X509Certificate2 (x.RawData);
240                                                 break;
241                                         }
242                                 }
243                         }
244
245                         SignerInfo si = new SignerInfo (sd.SignerInfo.HashName, x509, type, o, sd.SignerInfo.Version);
246                         // si.AuthenticatedAttributes
247                         // si.UnauthenticatedAttributes
248                         _info.Add (si);
249
250                         ASN1 content = sd.ContentInfo.Content;
251                         Oid oid = new Oid (sd.ContentInfo.ContentType);
252
253                         if (!_detached || _content == null) {
254                                 if (content[0] == null)
255                                         throw new ArgumentException ("ContentInfo has no content. Detached signature ?");
256
257                                 _content = new ContentInfo (oid, content[0].Value);
258                         }
259
260                         foreach (Mono.Security.X509.X509Certificate x in sd.Certificates) {
261                                 _certs.Add (new X509Certificate2 (x.RawData));
262                         }
263
264                         _version = sd.Version;
265                 }
266
267                 [MonoTODO]
268                 public byte[] Encode ()
269                 {
270 /*                      Mono.Security.X509.X509Certificate x509 = null;
271                         Cms.SignerInfo si = new Cms.SignerInfo ();
272                         switch (_type) {
273                                 case SubjectIdentifierType.SubjectKeyIdentifier:
274                                         si.SubjectKeyIdentifier = GetKeyIdentifier (x509);
275                                         break;
276                                 default: 
277                                         // SubjectIdentifierType.IssuerAndSerialNumber 
278                                         si.IssuerName = x509.IssuerName;
279                                         si.SerialNumber = x509.SerialNumber;
280                                         break;
281                         }
282
283                         Cms.SignedData sd = new Cms.SignedData ();
284                         sd.Version = _version;
285                         sd.SignerInfo = si;
286
287                         Cms.ContentInfo ci = new Cms.ContentInfo (Cms.signedData);
288                         ci.Content = sd.ASN1;
289                         return ci.GetBytes ();*/
290                         return null;
291                 }
292
293                 [MonoTODO]
294                 public void RemoveSignature (SignerInfo signerInfo)
295                 {
296                 }
297
298                 [MonoTODO]
299                 public void RemoveSignature (int index)
300                 {
301                 }
302         }
303 }
304
305 #endif