2009-04-29 Marek Habersack <mhabersack@novell.com>
[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 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 #if !NET_2_1
33
34 using System.Collections;
35 using System.Globalization;
36 using System.IO;
37 using System.Reflection;
38 using System.Runtime.CompilerServices;
39 using System.Runtime.InteropServices;
40 using System.Security.Permissions;
41 using System.Text;
42
43 using Mono.Xml;
44
45 namespace System.Security.Cryptography {
46
47 #if NET_2_0
48 [ComVisible (true)]
49 #endif
50 public partial      class CryptoConfig {
51
52         static private object lockObject;
53         static private Hashtable algorithms;
54         static private Hashtable oid;
55
56         private const string defaultNamespace = "System.Security.Cryptography.";
57         private const string defaultSHA1 = defaultNamespace + "SHA1CryptoServiceProvider";
58         private const string defaultMD5 = defaultNamespace + "MD5CryptoServiceProvider";
59         private const string defaultSHA256 = defaultNamespace + "SHA256Managed";
60         private const string defaultSHA384 = defaultNamespace + "SHA384Managed";
61         private const string defaultSHA512 = defaultNamespace + "SHA512Managed";
62         private const string defaultRSA = defaultNamespace + "RSACryptoServiceProvider";
63         private const string defaultDSA = defaultNamespace + "DSACryptoServiceProvider";
64         private const string defaultDES = defaultNamespace + "DESCryptoServiceProvider";
65         private const string default3DES = defaultNamespace + "TripleDESCryptoServiceProvider";
66         private const string defaultRC2 = defaultNamespace + "RC2CryptoServiceProvider";
67         private const string defaultAES = defaultNamespace + "RijndaelManaged";
68         // LAMESPEC: undocumented names in CryptoConfig
69         private const string defaultRNG = defaultNamespace + "RNGCryptoServiceProvider";
70         private const string defaultHMAC = defaultNamespace + "HMACSHA1";
71         private const string defaultMAC3DES = defaultNamespace + "MACTripleDES";
72         // LAMESPEC: undocumented classes (also undocumented in CryptoConfig ;-)
73         private const string defaultDSASigDesc = defaultNamespace + "DSASignatureDescription";
74         private const string defaultRSASigDesc = defaultNamespace + "RSAPKCS1SHA1SignatureDescription";
75 #if NET_2_0
76         private const string defaultRIPEMD160 = defaultNamespace + "RIPEMD160Managed";
77         private const string defaultHMACMD5 = defaultNamespace + "HMACMD5";
78         private const string defaultHMACRIPEMD160 = defaultNamespace + "HMACRIPEMD160";
79         private const string defaultHMACSHA256 = defaultNamespace + "HMACSHA256";
80         private const string defaultHMACSHA384 = defaultNamespace + "HMACSHA384";
81         private const string defaultHMACSHA512 = defaultNamespace + "HMACSHA512";
82 #endif
83
84         // LAMESPEC: undocumented names in CryptoConfig
85         private const string defaultC14N = defaultNamespace + "Xml.XmlDsigC14NTransform, " + Consts.AssemblySystem_Security;
86         private const string defaultC14NWithComments = defaultNamespace + "Xml.XmlDsigC14NWithCommentsTransform, " + Consts.AssemblySystem_Security;
87         private const string defaultBase64 = defaultNamespace + "Xml.XmlDsigBase64Transform, " + Consts.AssemblySystem_Security;
88         private const string defaultXPath = defaultNamespace + "Xml.XmlDsigXPathTransform, " + Consts.AssemblySystem_Security;
89         private const string defaultXslt = defaultNamespace + "Xml.XmlDsigXsltTransform, " + Consts.AssemblySystem_Security;
90         private const string defaultEnveloped = defaultNamespace + "Xml.XmlDsigEnvelopedSignatureTransform, " + Consts.AssemblySystem_Security;
91 #if NET_2_0
92         private const string defaultXmlDecryption = defaultNamespace + "Xml.XmlDecryptionTransform, " + Consts.AssemblySystem_Security;
93         private const string defaultExcC14N = defaultNamespace + "Xml.XmlDsigExcC14NTransform, " + Consts.AssemblySystem_Security;
94         private const string defaultExcC14NWithComments = defaultNamespace + "Xml.XmlDsigExcC14NWithCommentsTransform, " + Consts.AssemblySystem_Security;
95 #endif
96
97         // LAMESPEC: only documentated in ".NET Framework Security" book
98         private const string defaultX509Data = defaultNamespace + "Xml.KeyInfoX509Data, " + Consts.AssemblySystem_Security;
99         private const string defaultKeyName = defaultNamespace + "Xml.KeyInfoName, " + Consts.AssemblySystem_Security;
100         private const string defaultKeyValueDSA = defaultNamespace + "Xml.DSAKeyValue, " + Consts.AssemblySystem_Security;
101         private const string defaultKeyValueRSA = defaultNamespace + "Xml.RSAKeyValue, " + Consts.AssemblySystem_Security;
102         private const string defaultRetrievalMethod = defaultNamespace + "Xml.KeyInfoRetrievalMethod, " + Consts.AssemblySystem_Security;
103
104         private const string managedSHA1 = defaultNamespace + "SHA1Managed";
105
106         // Oddly OID seems only available for hash algorithms
107         private const string oidSHA1 = "1.3.14.3.2.26";
108         private const string oidMD5 = "1.2.840.113549.2.5";
109 #if NET_2_0
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         // new in 2.0
115 //      private const string oidRSA = "1.2.840.113549.1.1.1";
116         private const string oidDSA = "1.2.840.10040.4.1";
117         private const string oidDES = "1.3.14.3.2.7";
118         private const string oid3DES = "1.2.840.113549.3.7";
119         private const string oidRC2 = "1.2.840.113549.3.2";
120 #else
121         private const string oidSHA256 = "2.16.840.1.101.3.4.1";
122         private const string oidSHA384 = "2.16.840.1.101.3.4.2";
123         private const string oidSHA512 = "2.16.840.1.101.3.4.3";
124 #endif
125         // LAMESPEC: only documentated in ".NET Framework Security" book
126         private const string oid3DESKeyWrap = "1.2.840.113549.1.9.16.3.6";
127
128         private const string nameSHA1a = "SHA";
129         private const string nameSHA1b = "SHA1";
130         private const string nameSHA1c = "System.Security.Cryptography.SHA1";
131         private const string nameSHA1d = "System.Security.Cryptography.HashAlgorithm";
132         private const string nameMD5a = "MD5";
133         private const string nameMD5b = "System.Security.Cryptography.MD5";
134         private const string nameSHA256a = "SHA256";
135         private const string nameSHA256b = "SHA-256";
136         private const string nameSHA256c = "System.Security.Cryptography.SHA256";
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 nameSHA512a = "SHA512";
141         private const string nameSHA512b = "SHA-512";
142         private const string nameSHA512c = "System.Security.Cryptography.SHA512";
143         private const string nameRSAa = "RSA";
144         private const string nameRSAb = "System.Security.Cryptography.RSA";
145         private const string nameRSAc = "System.Security.Cryptography.AsymmetricAlgorithm";
146         private const string nameDSAa = "DSA";
147         private const string nameDSAb = "System.Security.Cryptography.DSA";
148         private const string nameDESa = "DES";
149         private const string nameDESb = "System.Security.Cryptography.DES";
150         private const string name3DESa = "3DES";
151         private const string name3DESb = "TripleDES";
152         private const string name3DESc = "Triple DES";
153         private const string name3DESd = "System.Security.Cryptography.TripleDES";
154         private const string nameRC2a = "RC2";
155         private const string nameRC2b = "System.Security.Cryptography.RC2";
156         private const string nameAESa = "Rijndael";
157         private const string nameAESb = "System.Security.Cryptography.Rijndael";
158         private const string nameAESc = "System.Security.Cryptography.SymmetricAlgorithm";
159         // LAMESPEC: undocumented names in CryptoConfig
160         private const string nameRNGa = "RandomNumberGenerator";
161         private const string nameRNGb = "System.Security.Cryptography.RandomNumberGenerator";
162         private const string nameKeyHasha = "System.Security.Cryptography.KeyedHashAlgorithm";
163         private const string nameHMACSHA1a = "HMACSHA1";
164         private const string nameHMACSHA1b = "System.Security.Cryptography.HMACSHA1";
165         private const string nameMAC3DESa = "MACTripleDES";
166         private const string nameMAC3DESb = "System.Security.Cryptography.MACTripleDES";
167         // LAMESPEC: only documentated in ".NET Framework Security" book
168         private const string name3DESKeyWrap = "TripleDESKeyWrap";
169 #if NET_2_0
170         private const string nameRIPEMD160a = "RIPEMD160";
171         private const string nameRIPEMD160b = "RIPEMD-160";
172         private const string nameRIPEMD160c = "System.Security.Cryptography.RIPEMD160";
173         private const string nameHMACa = "HMAC";
174         private const string nameHMACb = "System.Security.Cryptography.HMAC";
175         private const string nameHMACMD5a = "HMACMD5";
176         private const string nameHMACMD5b = "System.Security.Cryptography.HMACMD5";
177         private const string nameHMACRIPEMD160a = "HMACRIPEMD160";
178         private const string nameHMACRIPEMD160b = "System.Security.Cryptography.HMACRIPEMD160";
179         private const string nameHMACSHA256a = "HMACSHA256";
180         private const string nameHMACSHA256b = "System.Security.Cryptography.HMACSHA256";
181         private const string nameHMACSHA384a = "HMACSHA384";
182         private const string nameHMACSHA384b = "System.Security.Cryptography.HMACSHA384";
183         private const string nameHMACSHA512a = "HMACSHA512";
184         private const string nameHMACSHA512b = "System.Security.Cryptography.HMACSHA512";
185 #endif
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 urlSHA1 = urlXmlDsig + "sha1";                             // no space
192         private const string urlC14N = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"; 
193         private const string urlC14NWithComments = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments";
194         private const string urlBase64 = "http://www.w3.org/2000/09/xmldsig#base64";
195         private const string urlXPath = "http://www.w3.org/TR/1999/REC-xpath-19991116";
196         private const string urlXslt = "http://www.w3.org/TR/1999/REC-xslt-19991116";
197         private const string urlEnveloped = urlXmlDsig + "enveloped-signature";         // no space
198 #if NET_2_0
199         private const string urlXmlDecryption = "http://www.w3.org/2002/07/decrypt#XML";
200         private const string urlExcC14NWithComments = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments";
201         private const string urlExcC14N = "http://www.w3.org/2001/10/xml-exc-c14n#";
202         private const string urlSHA256 = "http://www.w3.org/2001/04/xmlenc#sha256";
203         private const string urlSHA512 = "http://www.w3.org/2001/04/xmlenc#sha512";
204         private const string urlHMACSHA256 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256";
205         private const string urlHMACSHA384 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384";
206         private const string urlHMACSHA512 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha512";
207         private const string urlHMACRIPEMD160 = "http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160";
208 #endif
209
210         // LAMESPEC: only documentated in ".NET Framework Security" book
211         private const string urlX509Data = urlXmlDsig + " X509Data";                    // space is required
212         private const string urlKeyName = urlXmlDsig + " KeyName";                      // space is required
213         private const string urlKeyValueDSA = urlXmlDsig + " KeyValue/DSAKeyValue";     // space is required
214         private const string urlKeyValueRSA = urlXmlDsig + " KeyValue/RSAKeyValue";     // space is required
215         private const string urlRetrievalMethod = urlXmlDsig + " RetrievalMethod";      // space is required
216
217 #if NET_2_0
218         // new (2.0) X509 certificate extensions
219         private const string oidX509SubjectKeyIdentifier = "2.5.29.14";
220         private const string oidX509KeyUsage = "2.5.29.15";
221         private const string oidX509BasicConstraints = "2.5.29.19";
222         private const string oidX509EnhancedKeyUsage = "2.5.29.37";
223
224         private const string nameX509SubjectKeyIdentifier = defaultNamespace + "X509Certificates.X509SubjectKeyIdentifierExtension, " + Consts.AssemblySystem;
225         private const string nameX509KeyUsage = defaultNamespace + "X509Certificates.X509KeyUsageExtension, " + Consts.AssemblySystem;
226         private const string nameX509BasicConstraints = defaultNamespace + "X509Certificates.X509BasicConstraintsExtension, " + Consts.AssemblySystem;
227         private const string nameX509EnhancedKeyUsage = defaultNamespace + "X509Certificates.X509EnhancedKeyUsageExtension, " + Consts.AssemblySystem;
228
229         // new (2.0) X509 Chain
230         private const string nameX509Chain = "X509Chain";
231         private const string defaultX509Chain = defaultNamespace + "X509Certificates.X509Chain, " + Consts.AssemblySystem;
232 #endif
233
234         static CryptoConfig () 
235         {
236                 // lock(this) is bad
237                 // http://msdn.microsoft.com/library/en-us/dnaskdr/html/askgui06032003.asp?frame=true
238                 lockObject = new object ();
239         }
240
241         private static void Initialize () 
242         {
243 #if NET_2_0
244                 Hashtable algorithms = new Hashtable (new CaseInsensitiveHashCodeProvider (), new CaseInsensitiveComparer ());
245 #else
246                 Hashtable algorithms = new Hashtable ();
247 #endif
248                 // see list @ http://msdn.microsoft.com/library/en-us/cpref/html/
249                 // frlrfSystemSecurityCryptographyCryptoConfigClassTopic.asp
250                 algorithms.Add (nameSHA1a, defaultSHA1);
251                 algorithms.Add (nameSHA1b, defaultSHA1);
252                 algorithms.Add (nameSHA1c, defaultSHA1);
253                 algorithms.Add (nameSHA1d, defaultSHA1);
254
255                 algorithms.Add (nameMD5a, defaultMD5);
256                 algorithms.Add (nameMD5b, defaultMD5);
257
258                 algorithms.Add (nameSHA256a, defaultSHA256);
259                 algorithms.Add (nameSHA256b, defaultSHA256);
260                 algorithms.Add (nameSHA256c, defaultSHA256);
261
262                 algorithms.Add (nameSHA384a, defaultSHA384);
263                 algorithms.Add (nameSHA384b, defaultSHA384);
264                 algorithms.Add (nameSHA384c, defaultSHA384);
265
266                 algorithms.Add (nameSHA512a, defaultSHA512);
267                 algorithms.Add (nameSHA512b, defaultSHA512);
268                 algorithms.Add (nameSHA512c, defaultSHA512);
269
270                 algorithms.Add (nameRSAa, defaultRSA);
271                 algorithms.Add (nameRSAb, defaultRSA); 
272                 algorithms.Add (nameRSAc, defaultRSA);
273
274                 algorithms.Add (nameDSAa, defaultDSA);  
275                 algorithms.Add (nameDSAb, defaultDSA);  
276
277                 algorithms.Add (nameDESa, defaultDES);
278                 algorithms.Add (nameDESb, defaultDES);
279
280                 algorithms.Add (name3DESa, default3DES);
281                 algorithms.Add (name3DESb, default3DES);
282                 algorithms.Add (name3DESc, default3DES);
283                 algorithms.Add (name3DESd, default3DES);
284
285                 algorithms.Add (nameRC2a, defaultRC2);
286                 algorithms.Add (nameRC2b, defaultRC2);
287
288                 algorithms.Add (nameAESa, defaultAES);  
289                 algorithms.Add (nameAESb, defaultAES);
290                 // LAMESPEC SymmetricAlgorithm documented as TripleDESCryptoServiceProvider
291                 algorithms.Add (nameAESc, defaultAES);
292
293                 // LAMESPEC These names aren't documented but (hint) the classes also have
294                 // static Create methods. So logically they should (and are) here.
295                 algorithms.Add (nameRNGa, defaultRNG);
296                 algorithms.Add (nameRNGb, defaultRNG);
297                 algorithms.Add (nameKeyHasha, defaultHMAC);
298                 algorithms.Add (nameHMACSHA1a, defaultHMAC);
299                 algorithms.Add (nameHMACSHA1b, defaultHMAC);
300                 algorithms.Add (nameMAC3DESa, defaultMAC3DES);
301                 algorithms.Add (nameMAC3DESb, defaultMAC3DES);
302 #if NET_2_0
303                 algorithms.Add (nameRIPEMD160a, defaultRIPEMD160);
304                 algorithms.Add (nameRIPEMD160b, defaultRIPEMD160);
305                 algorithms.Add (nameRIPEMD160c, defaultRIPEMD160);
306                 algorithms.Add (nameHMACb, defaultHMAC);
307                 algorithms.Add (nameHMACMD5a, defaultHMACMD5);
308                 algorithms.Add (nameHMACMD5b, defaultHMACMD5);
309                 algorithms.Add (nameHMACRIPEMD160a, defaultHMACRIPEMD160);
310                 algorithms.Add (nameHMACRIPEMD160b, defaultHMACRIPEMD160);
311                 algorithms.Add (nameHMACSHA256a, defaultHMACSHA256);
312                 algorithms.Add (nameHMACSHA256b, defaultHMACSHA256);
313                 algorithms.Add (nameHMACSHA384a, defaultHMACSHA384);
314                 algorithms.Add (nameHMACSHA384b, defaultHMACSHA384);
315                 algorithms.Add (nameHMACSHA512a, defaultHMACSHA512);
316                 algorithms.Add (nameHMACSHA512b, defaultHMACSHA512);
317 #endif
318
319                 // LAMESPEC These URLs aren't documented but (hint) installing the WSDK
320                 // add some of the XMLDSIG urls into machine.config (and they make a LOT
321                 // of sense for implementing XMLDSIG in System.Security.Cryptography.Xml)
322                 algorithms.Add (urlDSASHA1, defaultDSASigDesc); 
323                 algorithms.Add (urlRSASHA1, defaultRSASigDesc);
324                 algorithms.Add (urlSHA1, defaultSHA1);
325                 algorithms.Add (urlC14N, defaultC14N);
326                 algorithms.Add (urlC14NWithComments, defaultC14NWithComments);
327                 algorithms.Add (urlBase64, defaultBase64);
328                 algorithms.Add (urlXPath, defaultXPath);
329                 algorithms.Add (urlXslt, defaultXslt);
330                 algorithms.Add (urlEnveloped, defaultEnveloped);
331 #if NET_2_0
332                 algorithms.Add (urlExcC14N, defaultExcC14N);
333                 algorithms.Add (urlExcC14NWithComments, defaultExcC14NWithComments);
334                 algorithms.Add (urlXmlDecryption, defaultXmlDecryption);
335                 algorithms.Add (urlSHA256, defaultSHA256);
336                 // xmlenc does not include a definition for SHA384
337                 algorithms.Add (urlSHA512, defaultSHA512);
338                 algorithms.Add (urlHMACSHA256, defaultHMACSHA256);
339                 algorithms.Add (urlHMACSHA384, defaultHMACSHA384);
340                 algorithms.Add (urlHMACSHA512, defaultHMACSHA512);
341                 algorithms.Add (urlHMACRIPEMD160, defaultHMACRIPEMD160);
342 #endif
343                 // LAMESPEC: only documentated in ".NET Framework Security" book
344                 algorithms.Add (urlX509Data, defaultX509Data);
345                 algorithms.Add (urlKeyName, defaultKeyName);
346                 algorithms.Add (urlKeyValueDSA, defaultKeyValueDSA);
347                 algorithms.Add (urlKeyValueRSA, defaultKeyValueRSA);
348                 algorithms.Add (urlRetrievalMethod, defaultRetrievalMethod);
349
350 #if NET_2_0
351                 // note: X.509 extensions aren't part of OID but names
352                 algorithms.Add (oidX509SubjectKeyIdentifier, nameX509SubjectKeyIdentifier);
353                 algorithms.Add (oidX509KeyUsage, nameX509KeyUsage);
354                 algorithms.Add (oidX509BasicConstraints, nameX509BasicConstraints);
355                 algorithms.Add (oidX509EnhancedKeyUsage, nameX509EnhancedKeyUsage);
356                 // note: the default X.509Chain can also be created this way
357                 algorithms.Add (nameX509Chain, defaultX509Chain);
358
359                 Hashtable oid = new Hashtable (new CaseInsensitiveHashCodeProvider (), new CaseInsensitiveComparer ());
360 #else
361                 Hashtable oid = new Hashtable ();
362 #endif
363
364                 // comments here are to match with MS implementation (but not with doc)
365                 // LAMESPEC: only HashAlgorithm seems to have their OID included
366                 oid.Add (defaultSHA1, oidSHA1);
367                 oid.Add (managedSHA1, oidSHA1);
368                 oid.Add (nameSHA1b, oidSHA1);
369                 oid.Add (nameSHA1c, oidSHA1);
370
371                 oid.Add (defaultMD5, oidMD5);
372                 oid.Add (nameMD5a, oidMD5);
373                 oid.Add (nameMD5b, oidMD5);
374
375                 oid.Add (defaultSHA256, oidSHA256);
376                 oid.Add (nameSHA256a, oidSHA256);
377                 oid.Add (nameSHA256c, oidSHA256);
378
379                 oid.Add (defaultSHA384, oidSHA384);
380                 oid.Add (nameSHA384a, oidSHA384);
381                 oid.Add (nameSHA384c, oidSHA384);
382
383                 oid.Add (defaultSHA512, oidSHA512);
384                 oid.Add (nameSHA512a, oidSHA512);
385                 oid.Add (nameSHA512c, oidSHA512);
386
387                 // surprise! documented in ".NET Framework Security" book
388                 oid.Add (name3DESKeyWrap, oid3DESKeyWrap);
389
390 #if NET_2_0
391                 oid.Add (nameDESa, oidDES);
392                 oid.Add (name3DESb, oid3DES);
393                 oid.Add (nameRC2a, oidRC2);
394 #endif
395
396                 // Add/modify the config as specified by machine.config
397                 string config = Environment.GetMachineConfigPath ();
398                 LoadConfig (config, algorithms, oid);
399
400                 // update
401                 CryptoConfig.algorithms = algorithms;
402                 CryptoConfig.oid = oid;
403         }
404
405         [FileIOPermission (SecurityAction.Assert, Unrestricted = true)]
406         private static void LoadConfig (string filename, Hashtable algorithms, Hashtable oid)
407         {
408                 if (!File.Exists (filename))
409                         return;
410
411                 try {
412                         using (TextReader reader = new StreamReader (filename)) {
413                                 CryptoHandler handler = new CryptoHandler (algorithms, oid);
414                                 SmallXmlParser parser = new SmallXmlParser ();
415                                 parser.Parse (reader, handler);
416                         }
417                 }
418                 catch {
419                 }
420         }
421
422         public static object CreateFromName (string name)
423         {
424                 return CreateFromName (name, null);
425         }
426
427         [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]
428 #if NET_2_0
429         public static object CreateFromName (string name, params object[] args)
430 #else
431         public static object CreateFromName (string name, object[] args)
432 #endif
433         {
434                 if (name == null)
435                         throw new ArgumentNullException ("name");
436
437                 lock (lockObject) {
438                         if (algorithms == null) {
439                                 Initialize ();
440                         }
441                 }
442         
443                 try {
444                         Type algoClass = null;
445                         string algo = (string) algorithms [name];
446                         // do we have an entry
447                         if (algo == null)
448                                 algo = name;
449                         algoClass = Type.GetType (algo);
450                         // call the constructor for the type
451                         return Activator.CreateInstance (algoClass, args);
452                 }
453                 catch {
454                         // method doesn't throw any exception
455                         return null;
456                 }
457         }
458
459         public static string MapNameToOID (string name)
460         {
461                 if (name == null)
462                         throw new ArgumentNullException ("name");
463
464                 lock (lockObject) {
465                         if (oid == null) {
466                                 Initialize ();
467                         }
468                 }
469
470                 return (string)oid [name];
471         }
472
473         class CryptoHandler: SmallXmlParser.IContentHandler {
474
475                 private Hashtable algorithms;
476                 private Hashtable oid;
477                 private Hashtable names;
478                 private Hashtable classnames;
479                 int level;
480
481                 public CryptoHandler (Hashtable algorithms, Hashtable oid)
482                 {
483                         this.algorithms = algorithms;
484                         this.oid = oid;
485                         // temporary tables to reconstruct algorithms
486                         names = new Hashtable ();
487                         classnames = new Hashtable ();
488                 }
489
490                 public void OnStartParsing (SmallXmlParser parser)
491                 {
492                         // don't care
493                 }
494
495                 public void OnEndParsing (SmallXmlParser parser)
496                 {
497                         foreach (DictionaryEntry de in names) {
498                                 try {
499                                         algorithms.Add (de.Key, classnames[de.Value]);
500                                 }
501                                 catch {
502                                 }
503                         }
504                         // matching is done, data no more required
505                         names.Clear ();
506                         classnames.Clear ();
507                 }
508
509                 private string Get (SmallXmlParser.IAttrList attrs, string name)
510                 {
511                         for (int i = 0; i < attrs.Names.Length; i++) {
512                                 if (attrs.Names[i] == name)
513                                         return attrs.Values[i];
514                         }
515                         return String.Empty;
516                 }
517
518                 public void OnStartElement (string name, SmallXmlParser.IAttrList attrs)
519                 {
520                         switch (level) {
521                         case 0:
522                                 if (name == "configuration")
523                                         level++;
524                                 break;
525                         case 1:
526                                 if (name == "mscorlib")
527                                         level++;
528                                 break;
529                         case 2:
530                                 if (name == "cryptographySettings")
531                                         level++;
532                                 break;
533                         case 3:
534                                 if (name == "oidMap")
535                                         level++;
536                                 else if (name == "cryptoNameMapping")
537                                         level++;
538                                 break;
539                         case 4:
540                                 if (name == "oidEntry") {
541                                         oid.Add (Get (attrs, "name"), Get (attrs, "OID"));
542                                 } else if (name == "nameEntry") {
543                                         names.Add (Get (attrs, "name"), Get (attrs, "class"));
544                                 } else if (name == "cryptoClasses") {
545                                         level++;
546                                 }
547                                 break;
548                         case 5:
549                                 if (name == "cryptoClass")
550                                         classnames.Add (attrs.Names[0], attrs.Values[0]);
551                                 break;
552                         }
553                 }
554
555                 public void OnEndElement (string name)
556                 {
557                         // parser will make sure the XML structure is respected
558                         switch (level) {
559                         case 1:
560                                 if (name == "configuration")
561                                         level--;
562                                 break;
563                         case 2:
564                                 if (name == "mscorlib")
565                                         level--;
566                                 break;
567                         case 3:
568                                 if (name == "cryptographySettings")
569                                         level--;
570                                 break;
571                         case 4:
572                                 if ((name == "oidMap") || (name == "cryptoNameMapping"))
573                                         level--;
574                                 break;
575                         case 5:
576                                 if (name == "cryptoClasses")
577                                         level--;
578                                 break;
579                         }
580                 }
581
582                 public void OnProcessingInstruction (string name, string text)
583                 {
584                         // don't care
585                 }
586
587                 public void OnChars (string text)
588                 {
589                         // don't care
590                 }
591
592                 public void OnIgnorableWhitespace (string text)
593                 {
594                         // don't care
595                 }
596         }
597 }
598 }
599
600 #endif
601