Merge pull request #3528 from BrzVlad/fix-sgen-check-before-collections
[mono.git] / mcs / class / corlib / System.Security.Cryptography / CryptoConfig.cs
1 //
2 // CryptoConfig.cs: Handles cryptographic implementations and OIDs mappings.
3 //
4 // Author:
5 //      Sebastien Pouliot (sebastien@ximian.com)
6 //      Tim Coleman (tim@timcoleman.com)
7 //
8 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
9 // Copyright (C) Tim Coleman, 2004
10 // Copyright (C) 2004-2007,2011 Novell, Inc (http://www.novell.com)
11 // Copyright (C) 2011 Xamarin Inc. http://www.xamarin.com
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 #if !FULL_AOT_RUNTIME
34
35 using System.Collections;
36 using System.Collections.Generic;
37 using System.Globalization;
38 using System.IO;
39 using System.Reflection;
40 using System.Runtime.CompilerServices;
41 using System.Runtime.InteropServices;
42 using System.Security.Permissions;
43 using System.Text;
44 using System.Security.Cryptography.X509Certificates;
45
46 using Mono.Xml;
47
48 namespace System.Security.Cryptography {
49
50 [ComVisible (true)]
51 public partial class CryptoConfig {
52
53         static private object lockObject;
54         static private Dictionary<string,Type> algorithms;
55         static private Dictionary<string,string> unresolved_algorithms;
56         static private Dictionary<string,string> oids;
57
58         private const string defaultNamespace = "System.Security.Cryptography.";
59         static Type defaultSHA1 = typeof (SHA1CryptoServiceProvider);
60         static Type defaultMD5 = typeof (MD5CryptoServiceProvider);
61         static Type defaultSHA256 = typeof (SHA256Managed);
62         static Type defaultSHA384 = typeof (SHA384Managed);
63         static Type defaultSHA512 = typeof (SHA512Managed);
64         static Type defaultRSA = typeof (RSACryptoServiceProvider);
65         static Type defaultDSA = typeof (DSACryptoServiceProvider);
66         static Type defaultDES = typeof (DESCryptoServiceProvider);
67         static Type default3DES = typeof (TripleDESCryptoServiceProvider);
68         static Type defaultRC2 = typeof (RC2CryptoServiceProvider);
69         static Type defaultAES = typeof (RijndaelManaged);
70         // LAMESPEC: undocumented names in CryptoConfig
71         static Type defaultRNG = typeof (RNGCryptoServiceProvider);
72         static Type defaultHMAC = typeof (HMACSHA1);
73         static Type defaultMAC3DES = typeof (MACTripleDES);
74         // LAMESPEC: undocumented classes (also undocumented in CryptoConfig ;-)
75         static Type defaultDSASigDesc = typeof (DSASignatureDescription);
76         static Type defaultRSAPKCS1SHA1SigDesc = typeof (RSAPKCS1SHA1SignatureDescription);
77         static Type defaultRSAPKCS1SHA256SigDesc = typeof (RSAPKCS1SHA256SignatureDescription);
78         static Type defaultRSAPKCS1SHA384SigDesc = typeof (RSAPKCS1SHA384SignatureDescription);
79         static Type defaultRSAPKCS1SHA512SigDesc = typeof (RSAPKCS1SHA512SignatureDescription);
80         static Type defaultRIPEMD160 = typeof (RIPEMD160Managed);
81         static Type defaultHMACMD5 = typeof (HMACMD5);
82         static Type defaultHMACRIPEMD160 = typeof (HMACRIPEMD160);
83         static Type defaultHMACSHA256 = typeof (HMACSHA256);
84         static Type defaultHMACSHA384 = typeof (HMACSHA384);
85         static Type defaultHMACSHA512 = typeof (HMACSHA512);
86
87         // LAMESPEC: undocumented names in CryptoConfig
88         private const string defaultC14N = defaultNamespace + "Xml.XmlDsigC14NTransform, " + Consts.AssemblySystem_Security;
89         private const string defaultC14NWithComments = defaultNamespace + "Xml.XmlDsigC14NWithCommentsTransform, " + Consts.AssemblySystem_Security;
90         private const string defaultBase64 = defaultNamespace + "Xml.XmlDsigBase64Transform, " + Consts.AssemblySystem_Security;
91         private const string defaultXPath = defaultNamespace + "Xml.XmlDsigXPathTransform, " + Consts.AssemblySystem_Security;
92         private const string defaultXslt = defaultNamespace + "Xml.XmlDsigXsltTransform, " + Consts.AssemblySystem_Security;
93         private const string defaultEnveloped = defaultNamespace + "Xml.XmlDsigEnvelopedSignatureTransform, " + Consts.AssemblySystem_Security;
94         private const string defaultXmlDecryption = defaultNamespace + "Xml.XmlDecryptionTransform, " + Consts.AssemblySystem_Security;
95         private const string defaultExcC14N = defaultNamespace + "Xml.XmlDsigExcC14NTransform, " + Consts.AssemblySystem_Security;
96         private const string defaultExcC14NWithComments = defaultNamespace + "Xml.XmlDsigExcC14NWithCommentsTransform, " + Consts.AssemblySystem_Security;
97
98         // LAMESPEC: only documentated in ".NET Framework Security" book
99         private const string defaultX509Data = defaultNamespace + "Xml.KeyInfoX509Data, " + Consts.AssemblySystem_Security;
100         private const string defaultKeyName = defaultNamespace + "Xml.KeyInfoName, " + Consts.AssemblySystem_Security;
101         private const string defaultKeyValueDSA = defaultNamespace + "Xml.DSAKeyValue, " + Consts.AssemblySystem_Security;
102         private const string defaultKeyValueRSA = defaultNamespace + "Xml.RSAKeyValue, " + Consts.AssemblySystem_Security;
103         private const string defaultRetrievalMethod = defaultNamespace + "Xml.KeyInfoRetrievalMethod, " + Consts.AssemblySystem_Security;
104
105         private const string managedSHA1 = defaultNamespace + "SHA1Managed";
106
107         // Oddly OID seems only available for hash algorithms
108         private const string oidSHA1 = "1.3.14.3.2.26";
109         private const string oidMD5 = "1.2.840.113549.2.5";
110         // changed in 2.0
111         private const string oidSHA256 = "2.16.840.1.101.3.4.2.1";
112         private const string oidSHA384 = "2.16.840.1.101.3.4.2.2";
113         private const string oidSHA512 = "2.16.840.1.101.3.4.2.3";
114         private const string oidRIPEMD160 = "1.3.36.3.2.1";
115         // new in 2.0
116 //      private const string oidRSA = "1.2.840.113549.1.1.1";
117 //      private const string oidDSA = "1.2.840.10040.4.1";
118         private const string oidDES = "1.3.14.3.2.7";
119         private const string oid3DES = "1.2.840.113549.3.7";
120         private const string oidRC2 = "1.2.840.113549.3.2";
121         // LAMESPEC: only documentated in ".NET Framework Security" book
122         private const string oid3DESKeyWrap = "1.2.840.113549.1.9.16.3.6";
123
124         private const string nameSHA1 = "System.Security.Cryptography.SHA1CryptoServiceProvider";
125         private const string nameSHA1a = "SHA";
126         private const string nameSHA1b = "SHA1";
127         private const string nameSHA1c = "System.Security.Cryptography.SHA1";
128         private const string nameSHA1d = "System.Security.Cryptography.HashAlgorithm";
129         private const string nameMD5 = "System.Security.Cryptography.MD5CryptoServiceProvider";
130         private const string nameMD5a = "MD5";
131         private const string nameMD5b = "System.Security.Cryptography.MD5";
132         private const string nameSHA256 = "System.Security.Cryptography.SHA256Managed";
133         private const string nameSHA256a = "SHA256";
134         private const string nameSHA256b = "SHA-256";
135         private const string nameSHA256c = "System.Security.Cryptography.SHA256";
136         private const string nameSHA384 = "System.Security.Cryptography.SHA384Managed";
137         private const string nameSHA384a = "SHA384";
138         private const string nameSHA384b = "SHA-384";
139         private const string nameSHA384c = "System.Security.Cryptography.SHA384";
140         private const string nameSHA512 = "System.Security.Cryptography.SHA512Managed";
141         private const string nameSHA512a = "SHA512";
142         private const string nameSHA512b = "SHA-512";
143         private const string nameSHA512c = "System.Security.Cryptography.SHA512";
144         private const string nameRSAa = "RSA";
145         private const string nameRSAb = "System.Security.Cryptography.RSA";
146         private const string nameRSAc = "System.Security.Cryptography.AsymmetricAlgorithm";
147         private const string nameDSAa = "DSA";
148         private const string nameDSAb = "System.Security.Cryptography.DSA";
149         private const string nameDESa = "DES";
150         private const string nameDESb = "System.Security.Cryptography.DES";
151         private const string name3DESa = "3DES";
152         private const string name3DESb = "TripleDES";
153         private const string name3DESc = "Triple DES";
154         private const string name3DESd = "System.Security.Cryptography.TripleDES";
155         private const string nameRC2a = "RC2";
156         private const string nameRC2b = "System.Security.Cryptography.RC2";
157         private const string nameAESa = "Rijndael";
158         private const string nameAESb = "System.Security.Cryptography.Rijndael";
159         private const string nameAESc = "System.Security.Cryptography.SymmetricAlgorithm";
160         // LAMESPEC: undocumented names in CryptoConfig
161         private const string nameRNGa = "RandomNumberGenerator";
162         private const string nameRNGb = "System.Security.Cryptography.RandomNumberGenerator";
163         private const string nameKeyHasha = "System.Security.Cryptography.KeyedHashAlgorithm";
164         private const string nameHMACSHA1a = "HMACSHA1";
165         private const string nameHMACSHA1b = "System.Security.Cryptography.HMACSHA1";
166         private const string nameMAC3DESa = "MACTripleDES";
167         private const string nameMAC3DESb = "System.Security.Cryptography.MACTripleDES";
168         // LAMESPEC: only documentated in ".NET Framework Security" book
169         private const string name3DESKeyWrap = "TripleDESKeyWrap";
170         private const string nameRIPEMD160 = "System.Security.Cryptography.RIPEMD160Managed";
171         private const string nameRIPEMD160a = "RIPEMD160";
172         private const string nameRIPEMD160b = "RIPEMD-160";
173         private const string nameRIPEMD160c = "System.Security.Cryptography.RIPEMD160";
174 //      private const string nameHMACa = "HMAC";
175         private const string nameHMACb = "System.Security.Cryptography.HMAC";
176         private const string nameHMACMD5a = "HMACMD5";
177         private const string nameHMACMD5b = "System.Security.Cryptography.HMACMD5";
178         private const string nameHMACRIPEMD160a = "HMACRIPEMD160";
179         private const string nameHMACRIPEMD160b = "System.Security.Cryptography.HMACRIPEMD160";
180         private const string nameHMACSHA256a = "HMACSHA256";
181         private const string nameHMACSHA256b = "System.Security.Cryptography.HMACSHA256";
182         private const string nameHMACSHA384a = "HMACSHA384";
183         private const string nameHMACSHA384b = "System.Security.Cryptography.HMACSHA384";
184         private const string nameHMACSHA512a = "HMACSHA512";
185         private const string nameHMACSHA512b = "System.Security.Cryptography.HMACSHA512";
186
187         private const string urlXmlDsig = "http://www.w3.org/2000/09/xmldsig#";
188         // LAMESPEC: undocumented URLs in CryptoConfig
189         private const string urlDSASHA1 = urlXmlDsig + "dsa-sha1";                      // no space
190         private const string urlRSASHA1 = urlXmlDsig + "rsa-sha1";                      // no space
191         private const string urlRSASHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";                        // no space
192         private const string urlRSASHA384 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384";                        // no space
193         private const string urlRSASHA512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512";                        // no space
194         private const string urlSHA1 = urlXmlDsig + "sha1";                             // no space
195         private const string urlC14N = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"; 
196         private const string urlC14NWithComments = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments";
197         private const string urlBase64 = "http://www.w3.org/2000/09/xmldsig#base64";
198         private const string urlXPath = "http://www.w3.org/TR/1999/REC-xpath-19991116";
199         private const string urlXslt = "http://www.w3.org/TR/1999/REC-xslt-19991116";
200         private const string urlEnveloped = urlXmlDsig + "enveloped-signature";         // no space
201         private const string urlXmlDecryption = "http://www.w3.org/2002/07/decrypt#XML";
202         private const string urlExcC14NWithComments = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments";
203         private const string urlExcC14N = "http://www.w3.org/2001/10/xml-exc-c14n#";
204         private const string urlSHA256 = "http://www.w3.org/2001/04/xmlenc#sha256";
205         private const string urlSHA384 = "http://www.w3.org/2001/04/xmldsig-more#sha384";
206         private const string urlSHA512 = "http://www.w3.org/2001/04/xmlenc#sha512";
207         private const string urlHMACSHA256 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256";
208         private const string urlHMACSHA384 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384";
209         private const string urlHMACSHA512 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha512";
210         private const string urlHMACRIPEMD160 = "http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160";
211
212         // LAMESPEC: only documentated in ".NET Framework Security" book
213         private const string urlX509Data = urlXmlDsig + " X509Data";                    // space is required
214         private const string urlKeyName = urlXmlDsig + " KeyName";                      // space is required
215         private const string urlKeyValueDSA = urlXmlDsig + " KeyValue/DSAKeyValue";     // space is required
216         private const string urlKeyValueRSA = urlXmlDsig + " KeyValue/RSAKeyValue";     // space is required
217         private const string urlRetrievalMethod = urlXmlDsig + " RetrievalMethod";      // space is required
218
219         // new (2.0) X509 certificate extensions
220         private const string oidX509SubjectKeyIdentifier = "2.5.29.14";
221         private const string oidX509KeyUsage = "2.5.29.15";
222         private const string oidX509BasicConstraints = "2.5.29.19";
223         private const string oidX509EnhancedKeyUsage = "2.5.29.37";
224
225         private const string nameX509SubjectKeyIdentifier = defaultNamespace + "X509Certificates.X509SubjectKeyIdentifierExtension, " + Consts.AssemblySystem;
226         private const string nameX509KeyUsage = defaultNamespace + "X509Certificates.X509KeyUsageExtension, " + Consts.AssemblySystem;
227         private const string nameX509BasicConstraints = defaultNamespace + "X509Certificates.X509BasicConstraintsExtension, " + Consts.AssemblySystem;
228         private const string nameX509EnhancedKeyUsage = defaultNamespace + "X509Certificates.X509EnhancedKeyUsageExtension, " + Consts.AssemblySystem;
229
230         // new (2.0) X509 Chain
231         private const string nameX509Chain = "X509Chain";
232         private const string defaultX509Chain = defaultNamespace + "X509Certificates.X509Chain, " + Consts.AssemblySystem;
233         // AES
234         const string system_core_assembly = ", System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
235         const string nameAES_1 = "AES";
236         const string nameAES_2 = "System.Security.Cryptography.AesCryptoServiceProvider";
237         const string defaultAES_1 = "System.Security.Cryptography.AesCryptoServiceProvider" + system_core_assembly;
238         
239         const string nameAESManaged_1 = "AesManaged";
240         const string nameAESManaged_2 = "System.Security.Cryptography.AesManaged";
241         const string defaultAESManaged = "System.Security.Cryptography.AesManaged" + system_core_assembly;
242
243         // ECDiffieHellman - not implemented in System.Core at the moment
244         const string nameECDiffieHellman_1 = "ECDH";
245         const string nameECDiffieHellman_2 = "ECDiffieHellman";
246         const string nameECDiffieHellman_3 = "ECDiffieHellmanCng";
247         const string nameECDiffieHellman_4 = "System.Security.Cryptography.ECDiffieHellmanCng";
248         const string defaultECDiffieHellman = "System.Security.Cryptography.ECDiffieHellmanCng" + system_core_assembly;
249
250         // ECDsa - not implemented in System.Core at the moment
251         const string nameECDsa_1 = "ECDsa";
252         const string nameECDsa_2 = "ECDsaCng";
253         const string nameECDsa_3 = "System.Security.Cryptography.ECDsaCng";
254         const string defaultECDsa = "System.Security.Cryptography.ECDsaCng" + system_core_assembly;
255
256         // SHA1Cng
257         const string nameSHA1Cng = "System.Security.Cryptography.SHA1Cng";
258         const string defaultSHA1Cng = "System.Security.Cryptography.SHA1Cng" + system_core_assembly;
259
260         // SHA256Cng
261         const string nameSHA256Cng = "System.Security.Cryptography.SHA256Cng";
262         const string defaultSHA256Cng = "System.Security.Cryptography.SHA256Cng" + system_core_assembly;
263
264         // SHA256 provider
265         const string nameSHA256Provider = "System.Security.Cryptography.SHA256CryptoServiceProvider";
266         const string defaultSHA256Provider = "System.Security.Cryptography.SHA256CryptoServiceProvider" + system_core_assembly;
267
268         // SHA384Cng
269         const string nameSHA384Cng = "System.Security.Cryptography.SHA384Cng";
270         const string defaultSHA384Cng = "System.Security.Cryptography.SHA384Cng" + system_core_assembly;
271
272         // SHA384 provider
273         const string nameSHA384Provider = "System.Security.Cryptography.SHA384CryptoServiceProvider";
274         const string defaultSHA384Provider = "System.Security.Cryptography.SHA384CryptoServiceProvider" + system_core_assembly;
275
276         // SHA512Cng
277         const string nameSHA512Cng = "System.Security.Cryptography.SHA512Cng";
278         const string defaultSHA512Cng = "System.Security.Cryptography.SHA512Cng" + system_core_assembly;
279
280         // SHA512 provider
281         const string nameSHA512Provider = "System.Security.Cryptography.SHA512CryptoServiceProvider";
282         const string defaultSHA512Provider = "System.Security.Cryptography.SHA512CryptoServiceProvider" + system_core_assembly;
283         static CryptoConfig () 
284         {
285                 // lock(this) is bad
286                 // http://msdn.microsoft.com/library/en-us/dnaskdr/html/askgui06032003.asp?frame=true
287                 lockObject = new object ();
288         }
289
290         private static void Initialize () 
291         {
292                 Dictionary<string,Type> algorithms = new Dictionary<string, Type> (StringComparer.OrdinalIgnoreCase);
293                 // see list @ http://msdn.microsoft.com/library/en-us/cpref/html/
294                 // frlrfSystemSecurityCryptographyCryptoConfigClassTopic.asp
295                 algorithms.Add (nameSHA1a, defaultSHA1);
296                 algorithms.Add (nameSHA1b, defaultSHA1);
297                 algorithms.Add (nameSHA1c, defaultSHA1);
298                 algorithms.Add (nameSHA1d, defaultSHA1);
299
300                 algorithms.Add (nameMD5a, defaultMD5);
301                 algorithms.Add (nameMD5b, defaultMD5);
302
303                 algorithms.Add (nameSHA256a, defaultSHA256);
304                 algorithms.Add (nameSHA256b, defaultSHA256);
305                 algorithms.Add (nameSHA256c, defaultSHA256);
306
307                 algorithms.Add (nameSHA384a, defaultSHA384);
308                 algorithms.Add (nameSHA384b, defaultSHA384);
309                 algorithms.Add (nameSHA384c, defaultSHA384);
310
311                 algorithms.Add (nameSHA512a, defaultSHA512);
312                 algorithms.Add (nameSHA512b, defaultSHA512);
313                 algorithms.Add (nameSHA512c, defaultSHA512);
314
315                 algorithms.Add (nameRSAa, defaultRSA);
316                 algorithms.Add (nameRSAb, defaultRSA); 
317                 algorithms.Add (nameRSAc, defaultRSA);
318
319                 algorithms.Add (nameDSAa, defaultDSA);  
320                 algorithms.Add (nameDSAb, defaultDSA);  
321
322                 algorithms.Add (nameDESa, defaultDES);
323                 algorithms.Add (nameDESb, defaultDES);
324
325                 algorithms.Add (name3DESa, default3DES);
326                 algorithms.Add (name3DESb, default3DES);
327                 algorithms.Add (name3DESc, default3DES);
328                 algorithms.Add (name3DESd, default3DES);
329
330                 algorithms.Add (nameRC2a, defaultRC2);
331                 algorithms.Add (nameRC2b, defaultRC2);
332
333                 algorithms.Add (nameAESa, defaultAES);  
334                 algorithms.Add (nameAESb, defaultAES);
335                 // LAMESPEC SymmetricAlgorithm documented as TripleDESCryptoServiceProvider
336                 algorithms.Add (nameAESc, defaultAES);
337
338                 // LAMESPEC These names aren't documented but (hint) the classes also have
339                 // static Create methods. So logically they should (and are) here.
340                 algorithms.Add (nameRNGa, defaultRNG);
341                 algorithms.Add (nameRNGb, defaultRNG);
342                 algorithms.Add (nameKeyHasha, defaultHMAC);
343                 algorithms.Add (nameHMACSHA1a, defaultHMAC);
344                 algorithms.Add (nameHMACSHA1b, defaultHMAC);
345                 algorithms.Add (nameMAC3DESa, defaultMAC3DES);
346                 algorithms.Add (nameMAC3DESb, defaultMAC3DES);
347                 algorithms.Add (nameRIPEMD160a, defaultRIPEMD160);
348                 algorithms.Add (nameRIPEMD160b, defaultRIPEMD160);
349                 algorithms.Add (nameRIPEMD160c, defaultRIPEMD160);
350                 algorithms.Add (nameHMACb, defaultHMAC);
351                 algorithms.Add (nameHMACMD5a, defaultHMACMD5);
352                 algorithms.Add (nameHMACMD5b, defaultHMACMD5);
353                 algorithms.Add (nameHMACRIPEMD160a, defaultHMACRIPEMD160);
354                 algorithms.Add (nameHMACRIPEMD160b, defaultHMACRIPEMD160);
355                 algorithms.Add (nameHMACSHA256a, defaultHMACSHA256);
356                 algorithms.Add (nameHMACSHA256b, defaultHMACSHA256);
357                 algorithms.Add (nameHMACSHA384a, defaultHMACSHA384);
358                 algorithms.Add (nameHMACSHA384b, defaultHMACSHA384);
359                 algorithms.Add (nameHMACSHA512a, defaultHMACSHA512);
360                 algorithms.Add (nameHMACSHA512b, defaultHMACSHA512);
361                         
362                 // we do not want to load the types (and assemblies) unless we really need them
363                 // so we keep those names as strings
364                 Dictionary<string,string> unresolved_algorithms = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
365                         
366                 // LAMESPEC These URLs aren't documented but (hint) installing the WSDK
367                 // add some of the XMLDSIG urls into machine.config (and they make a LOT
368                 // of sense for implementing XMLDSIG in System.Security.Cryptography.Xml)
369                 algorithms.Add (urlDSASHA1, defaultDSASigDesc); 
370                 algorithms.Add (urlRSASHA1, defaultRSAPKCS1SHA1SigDesc);
371                 algorithms.Add (urlRSASHA256, defaultRSAPKCS1SHA256SigDesc);
372                 algorithms.Add (urlRSASHA384, defaultRSAPKCS1SHA384SigDesc);
373                 algorithms.Add (urlRSASHA512, defaultRSAPKCS1SHA512SigDesc);
374                 algorithms.Add (urlSHA1, defaultSHA1);
375                 unresolved_algorithms.Add (urlC14N, defaultC14N);
376                 unresolved_algorithms.Add (urlC14NWithComments, defaultC14NWithComments);
377                 unresolved_algorithms.Add (urlBase64, defaultBase64);
378                 unresolved_algorithms.Add (urlXPath, defaultXPath);
379                 unresolved_algorithms.Add (urlXslt, defaultXslt);
380                 unresolved_algorithms.Add (urlEnveloped, defaultEnveloped);
381                 unresolved_algorithms.Add (urlExcC14N, defaultExcC14N);
382                 unresolved_algorithms.Add (urlExcC14NWithComments, defaultExcC14NWithComments);
383                 unresolved_algorithms.Add (urlXmlDecryption, defaultXmlDecryption);
384                 algorithms.Add (urlSHA256, defaultSHA256);
385                 algorithms.Add (urlSHA384, defaultSHA384);
386                 algorithms.Add (urlSHA512, defaultSHA512);
387                 algorithms.Add (urlHMACSHA256, defaultHMACSHA256);
388                 algorithms.Add (urlHMACSHA384, defaultHMACSHA384);
389                 algorithms.Add (urlHMACSHA512, defaultHMACSHA512);
390                 algorithms.Add (urlHMACRIPEMD160, defaultHMACRIPEMD160);
391                 // LAMESPEC: only documentated in ".NET Framework Security" book
392                 unresolved_algorithms.Add (urlX509Data, defaultX509Data);
393                 unresolved_algorithms.Add (urlKeyName, defaultKeyName);
394                 unresolved_algorithms.Add (urlKeyValueDSA, defaultKeyValueDSA);
395                 unresolved_algorithms.Add (urlKeyValueRSA, defaultKeyValueRSA);
396                 unresolved_algorithms.Add (urlRetrievalMethod, defaultRetrievalMethod);
397
398                 // note: X.509 extensions aren't part of OID but names
399                 unresolved_algorithms.Add (oidX509SubjectKeyIdentifier, nameX509SubjectKeyIdentifier);
400                 unresolved_algorithms.Add (oidX509KeyUsage, nameX509KeyUsage);
401                 unresolved_algorithms.Add (oidX509BasicConstraints, nameX509BasicConstraints);
402                 unresolved_algorithms.Add (oidX509EnhancedKeyUsage, nameX509EnhancedKeyUsage);
403                 // note: the default X.509Chain can also be created this way
404                 unresolved_algorithms.Add (nameX509Chain, defaultX509Chain);
405                 unresolved_algorithms.Add (nameAES_1, defaultAES_1);
406                 unresolved_algorithms.Add (nameAES_2, defaultAES_1);
407                 unresolved_algorithms.Add (nameAESManaged_1, defaultAESManaged);
408                 unresolved_algorithms.Add (nameAESManaged_2, defaultAESManaged);
409
410                 unresolved_algorithms.Add (nameECDiffieHellman_1, defaultECDiffieHellman);
411                 unresolved_algorithms.Add (nameECDiffieHellman_2, defaultECDiffieHellman);
412                 unresolved_algorithms.Add (nameECDiffieHellman_3, defaultECDiffieHellman);
413                 unresolved_algorithms.Add (nameECDiffieHellman_4, defaultECDiffieHellman);
414
415                 unresolved_algorithms.Add (nameECDsa_1, defaultECDsa);
416                 unresolved_algorithms.Add (nameECDsa_2, defaultECDsa);
417                 unresolved_algorithms.Add (nameECDsa_3, defaultECDsa);
418
419                 unresolved_algorithms.Add (nameSHA1Cng, defaultSHA1Cng);
420                 unresolved_algorithms.Add (nameSHA256Cng, defaultSHA256Cng);
421                 unresolved_algorithms.Add (nameSHA256Provider, defaultSHA256Provider);
422                 unresolved_algorithms.Add (nameSHA384Cng, defaultSHA384Cng);
423                 unresolved_algorithms.Add (nameSHA384Provider, defaultSHA384Provider);
424                 unresolved_algorithms.Add (nameSHA512Cng, defaultSHA512Cng);
425                 unresolved_algorithms.Add (nameSHA512Provider, defaultSHA512Provider);
426                 Dictionary<string,string> oid = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
427
428                 // comments here are to match with MS implementation (but not with doc)
429                 // LAMESPEC: only HashAlgorithm seems to have their OID included
430                 oid.Add (nameSHA1, oidSHA1);
431                 oid.Add (managedSHA1, oidSHA1);
432                 oid.Add (nameSHA1b, oidSHA1);
433                 oid.Add (nameSHA1c, oidSHA1);
434                 oid.Add (nameSHA1Cng, oidSHA1);
435
436                 oid.Add (nameMD5, oidMD5);
437                 oid.Add (nameMD5a, oidMD5);
438                 oid.Add (nameMD5b, oidMD5);
439
440                 oid.Add (nameSHA256, oidSHA256);
441                 oid.Add (nameSHA256a, oidSHA256);
442                 oid.Add (nameSHA256c, oidSHA256);
443                 oid.Add (nameSHA256Cng, oidSHA256);
444                 oid.Add (nameSHA256Provider, oidSHA256);
445
446                 oid.Add (nameSHA384, oidSHA384);
447                 oid.Add (nameSHA384a, oidSHA384);
448                 oid.Add (nameSHA384c, oidSHA384);
449                 oid.Add (nameSHA384Cng, oidSHA384);
450                 oid.Add (nameSHA384Provider, oidSHA384);
451
452                 oid.Add (nameSHA512, oidSHA512);
453                 oid.Add (nameSHA512a, oidSHA512);
454                 oid.Add (nameSHA512c, oidSHA512);
455                 oid.Add (nameSHA512Cng, oidSHA512);
456                 oid.Add (nameSHA512Provider, oidSHA512);
457
458                 oid.Add (nameRIPEMD160, oidRIPEMD160);
459                 oid.Add (nameRIPEMD160a, oidRIPEMD160);
460                 oid.Add (nameRIPEMD160c, oidRIPEMD160);
461
462                 // surprise! documented in ".NET Framework Security" book
463                 oid.Add (name3DESKeyWrap, oid3DESKeyWrap);
464
465                 oid.Add (nameDESa, oidDES);
466                 oid.Add (name3DESb, oid3DES);
467                 oid.Add (nameRC2a, oidRC2);
468
469                 // Add/modify the config as specified by machine.config
470                 string config = Environment.GetMachineConfigPath ();
471                 LoadConfig (config, algorithms, oid);
472
473                 // update
474                 CryptoConfig.algorithms = algorithms;
475                 CryptoConfig.unresolved_algorithms = unresolved_algorithms;
476                 CryptoConfig.oids = oid;
477         }
478
479         [FileIOPermission (SecurityAction.Assert, Unrestricted = true)]
480         private static void LoadConfig (string filename, IDictionary<string,Type> algorithms, IDictionary<string,string> oid)
481         {
482                 if (!File.Exists (filename))
483                         return;
484
485                 try {
486                         using (TextReader reader = new StreamReader (filename)) {
487                                 CryptoHandler handler = new CryptoHandler (algorithms, oid);
488                                 SmallXmlParser parser = new SmallXmlParser ();
489                                 parser.Parse (reader, handler);
490                         }
491                 }
492                 catch {
493                 }
494         }
495
496         public static object CreateFromName (string name)
497         {
498                 return CreateFromName (name, null);
499         }
500
501         [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]
502         public static object CreateFromName (string name, params object[] args)
503         {
504                 if (name == null)
505                         throw new ArgumentNullException ("name");
506
507                 lock (lockObject) {
508                         if (algorithms == null) {
509                                 Initialize ();
510                         }
511                 }
512         
513                 try {
514                         Type algoClass = null;
515                         if (!algorithms.TryGetValue (name, out algoClass)) {
516                                 string algo = null;
517                                 if (!unresolved_algorithms.TryGetValue (name, out algo))
518                                                 algo = name;
519                                 algoClass = Type.GetType (algo);
520                         }
521                         if (algoClass == null)
522                                 return null;
523                         // call the constructor for the type
524                         return Activator.CreateInstance (algoClass, args);
525                 }
526                 catch {
527                         // method doesn't throw any exception
528                         return null;
529                 }
530         }
531
532         internal static string MapNameToOID (string name, OidGroup oidGroup)
533         {
534                 return MapNameToOID (name);
535         }
536
537         public static string MapNameToOID (string name)
538         {
539                 if (name == null)
540                         throw new ArgumentNullException ("name");
541
542                 lock (lockObject) {
543                         if (oids == null) {
544                                 Initialize ();
545                         }
546                 }
547                         
548                 string result = null;
549                 oids.TryGetValue (name, out result);
550                 return result;
551         }
552
553         public static void AddAlgorithm (Type algorithm, params string[] names)
554         {
555                 if (algorithm == null)
556                                 throw new ArgumentNullException ("algorithm");
557                 if (names  == null)
558                                 throw new ArgumentNullException ("names");
559                         
560                 foreach (string name in names) {
561                                 if (String.IsNullOrWhiteSpace (name))
562                                         throw new ArithmeticException ("names");
563                                 algorithms [name] = algorithm;
564                 }
565         }
566
567         public static void AddOID (string oid, params string[] names)
568         {
569                 if (oid == null)
570                                 throw new ArgumentNullException ("oid");
571                 if (names  == null)
572                                 throw new ArgumentNullException ("names");
573                         
574                 foreach (string name in names) {
575                                 if (String.IsNullOrWhiteSpace (name))
576                                         throw new ArithmeticException ("names");
577                                 oids [oid] = name;
578                 }
579         }
580
581         class CryptoHandler: SmallXmlParser.IContentHandler {
582
583                 IDictionary<string,Type> algorithms;
584                 IDictionary<string,string> oid;
585                 Dictionary<string,string> names;
586                 Dictionary<string,string> classnames;
587                 int level;
588
589                 public CryptoHandler (IDictionary<string,Type> algorithms, IDictionary<string,string> oid)
590                 {
591                         this.algorithms = algorithms;
592                         this.oid = oid;
593                         // temporary tables to reconstruct algorithms
594                         names = new Dictionary<string,string> ();
595                         classnames = new Dictionary<string,string> ();
596                 }
597
598                 public void OnStartParsing (SmallXmlParser parser)
599                 {
600                         // don't care
601                 }
602
603                 public void OnEndParsing (SmallXmlParser parser)
604                 {
605                         foreach (var kpv in names) {
606                                 try {
607                                         algorithms [kpv.Key] = Type.GetType (classnames [kpv.Value]);
608                                 }
609                                 catch {
610                                 }
611                         }
612                         // matching is done, data no more required
613                         names.Clear ();
614                         classnames.Clear ();
615                 }
616
617                 private string Get (SmallXmlParser.IAttrList attrs, string name)
618                 {
619                         for (int i = 0; i < attrs.Names.Length; i++) {
620                                 if (attrs.Names[i] == name)
621                                         return attrs.Values[i];
622                         }
623                         return String.Empty;
624                 }
625
626                 public void OnStartElement (string name, SmallXmlParser.IAttrList attrs)
627                 {
628                         switch (level) {
629                         case 0:
630                                 if (name == "configuration")
631                                         level++;
632                                 break;
633                         case 1:
634                                 if (name == "mscorlib")
635                                         level++;
636                                 break;
637                         case 2:
638                                 if (name == "cryptographySettings")
639                                         level++;
640                                 break;
641                         case 3:
642                                 if (name == "oidMap")
643                                         level++;
644                                 else if (name == "cryptoNameMapping")
645                                         level++;
646                                 break;
647                         case 4:
648                                 if (name == "oidEntry") {
649                                         oid [Get (attrs, "name")] = Get (attrs, "OID");
650                                 } else if (name == "nameEntry") {
651                                         names [Get (attrs, "name")] = Get (attrs, "class");
652                                 } else if (name == "cryptoClasses") {
653                                         level++;
654                                 }
655                                 break;
656                         case 5:
657                                 if (name == "cryptoClass")
658                                         classnames [attrs.Names[0]] = attrs.Values[0];
659                                 break;
660                         }
661                 }
662
663                 public void OnEndElement (string name)
664                 {
665                         // parser will make sure the XML structure is respected
666                         switch (level) {
667                         case 1:
668                                 if (name == "configuration")
669                                         level--;
670                                 break;
671                         case 2:
672                                 if (name == "mscorlib")
673                                         level--;
674                                 break;
675                         case 3:
676                                 if (name == "cryptographySettings")
677                                         level--;
678                                 break;
679                         case 4:
680                                 if ((name == "oidMap") || (name == "cryptoNameMapping"))
681                                         level--;
682                                 break;
683                         case 5:
684                                 if (name == "cryptoClasses")
685                                         level--;
686                                 break;
687                         }
688                 }
689
690                 public void OnProcessingInstruction (string name, string text)
691                 {
692                         // don't care
693                 }
694
695                 public void OnChars (string text)
696                 {
697                         // don't care
698                 }
699
700                 public void OnIgnorableWhitespace (string text)
701                 {
702                         // don't care
703                 }
704         }
705 }
706 }
707
708 #endif
709