Bug 15572. Lookup KnownTypeCollection element types in MSSimpleNamespace
[mono.git] / mcs / class / System.IdentityModel / System.IdentityModel.Tokens / InMemorySymmetricSecurityKey.cs
1 //
2 // InMemorySymmetricSecurityKey.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2006-2007 Novell, Inc.  http://www.novell.com
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.Collections.Generic;
30 using System.IO;
31 using System.Xml;
32 using System.IdentityModel.Policy;
33 using System.Security.Cryptography;
34 using System.Security.Cryptography.Xml;
35
36 using M = Mono.Security.Cryptography;
37 using AES = System.Security.Cryptography.RijndaelManaged;
38
39 namespace System.IdentityModel.Tokens
40 {
41         public class InMemorySymmetricSecurityKey : SymmetricSecurityKey
42         {
43                 byte [] key;
44
45                 public InMemorySymmetricSecurityKey (byte [] key)
46                         : this (key, true)
47                 {
48                 }
49
50                 public InMemorySymmetricSecurityKey (byte [] key, bool clone)
51                 {
52                         if (key == null)
53                                 throw new ArgumentNullException ("key");
54                         this.key = clone ? (byte []) key.Clone() : key;
55                 }
56
57                 // SymmetricSecurityKey implementation
58
59                 public override byte [] GenerateDerivedKey (
60                         string algorithm, byte [] label, byte [] nonce,
61                         int derivedKeyLength, int offset)
62                 {
63                         if (derivedKeyLength < 0)
64                                 throw new ArgumentOutOfRangeException ("derivedKeyLength");
65                         if (offset < 0)
66                                 throw new ArgumentOutOfRangeException ("offset");
67                         if (label == null)
68                                 throw new ArgumentNullException ("label");
69                         if (nonce == null)
70                                 throw new ArgumentNullException ("nonce");
71                         if (algorithm != SecurityAlgorithms.Psha1KeyDerivation)
72                                 throw new InvalidOperationException (String.Format ("Key derivation algorithm '{0}' is not supported", algorithm));
73                         byte [] seed = new byte [label.Length + nonce.Length];
74                         Array.Copy (label, seed, label.Length);
75                         Array.Copy (nonce, 0, seed, label.Length, nonce.Length);
76
77                         byte [] p_sha = Expand ("SHA1", key, seed, derivedKeyLength / 8);
78
79                         return p_sha;
80                 }
81
82                 // from Mono.Security.Protocol.Tls.CipherSuite.Expand() with
83                 // a bit of modification ...
84                 byte [] Expand (string hashName, byte[] secret, byte[] seed, int length)
85                 {
86                         int hashLength  = hashName == "MD5" ? 16 : 20;
87                         int     iterations      = (int)(length / hashLength);
88                         if ((length % hashLength) > 0)
89                         {
90                                 iterations++;
91                         }
92                         
93                         M.HMAC          hmac    = new M.HMAC(hashName, secret);
94                         MemoryStream    resMacs = new MemoryStream ();
95                         
96                         byte[][] hmacs = new byte[iterations + 1][];
97                         hmacs[0] = seed;
98                         for (int i = 1; i <= iterations; i++)
99                         {                               
100                                 MemoryStream hcseed = new MemoryStream ();
101                                 hmac.TransformFinalBlock(hmacs[i-1], 0, hmacs[i-1].Length);
102                                 hmacs[i] = hmac.Hash;
103                                 hcseed.Write(hmacs[i], 0, hmacs [i].Length);
104                                 hcseed.Write(seed, 0, seed.Length);
105                                 hmac.TransformFinalBlock(hcseed.ToArray(), 0, (int)hcseed.Length);
106                                 resMacs.Write(hmac.Hash, 0, hmac.Hash.Length);
107                         }
108
109                         byte[] res = new byte[length];
110                         
111                         Buffer.BlockCopy(resMacs.ToArray(), 0, res, 0, res.Length);
112
113                         return res;
114                 }
115
116                 public override byte [] GetSymmetricKey ()
117                 {
118                         return (byte []) key.Clone ();
119                 }
120
121                 public override KeyedHashAlgorithm GetKeyedHashAlgorithm (
122                         string algorithm)
123                 {
124                         if (algorithm == SecurityAlgorithms.HmacSha1Signature)
125                                 return new HMACSHA1 (key);
126                         //if (algorithm == SecurityAlgorithms.HmacSha256Signature)
127                         //      return new HMACSHA256 (key);
128                         throw new NotSupportedException ();
129                 }
130
131                 public override SymmetricAlgorithm GetSymmetricAlgorithm (string algorithm)
132                 {
133                         SymmetricAlgorithm s = null;
134                         switch (algorithm) {
135                         case SecurityAlgorithms.Aes128Encryption:
136                         case SecurityAlgorithms.Aes192Encryption:
137                         case SecurityAlgorithms.Aes256Encryption:
138                         case SecurityAlgorithms.Aes128KeyWrap:
139                         case SecurityAlgorithms.Aes192KeyWrap:
140                         case SecurityAlgorithms.Aes256KeyWrap:
141                                 s = new AES ();
142                                 break;
143                         case SecurityAlgorithms.TripleDesEncryption:
144                         case SecurityAlgorithms.TripleDesKeyWrap:
145                                 if (key.Length == 24)
146                                         throw new CryptographicException ("The key size is 24 bytes, which known as vulnerable and thus not allowed.");
147                                 s = TripleDES.Create ();
148                                 break;
149                         default:
150                                 throw new NotSupportedException (String.Format ("This symmetric security key does not support specified algorithm '{0}'", algorithm));
151                         }
152                         s.Mode = CipherMode.CBC;
153                         s.GenerateIV ();
154                         s.Key = key;
155                         return s;
156                 }
157
158                 public override ICryptoTransform GetDecryptionTransform (string algorithm, byte [] iv)
159                 {
160                         if (iv == null)
161                                 throw new ArgumentNullException ("iv");
162                         SymmetricAlgorithm alg = GetSymmetricAlgorithm (algorithm);
163                         alg.IV = iv;
164                         return alg.CreateDecryptor ();
165                 }
166
167                 public override ICryptoTransform GetEncryptionTransform (string algorithm, byte [] iv)
168                 {
169                         if (iv == null)
170                                 throw new ArgumentNullException ("iv");
171                         SymmetricAlgorithm alg = GetSymmetricAlgorithm (algorithm);
172                         alg.IV = iv;
173                         return alg.CreateEncryptor ();
174                 }
175
176                 [MonoTODO]
177                 public override int GetIVSize (string algorithm)
178                 {
179                         throw new NotImplementedException ();
180                 }
181
182                 // SecurityKey implementation
183
184                 public override int KeySize {
185                         get { return key.Length << 3; }
186                 }
187
188                 public override byte [] DecryptKey (string algorithm, byte [] keyData)
189                 {
190                         if (algorithm == null)
191                                 throw new ArgumentNullException ("algorithm");
192                         if (keyData == null)
193                                 throw new ArgumentNullException ("keyData");
194                         return EncryptedXml.DecryptKey (keyData, GetSymmetricAlgorithm (algorithm));
195                 }
196
197                 public override byte [] EncryptKey (string algorithm, byte [] keyData)
198                 {
199                         if (algorithm == null)
200                                 throw new ArgumentNullException ("algorithm");
201                         if (keyData == null)
202                                 throw new ArgumentNullException ("keyData");
203                         return EncryptedXml.EncryptKey (keyData, GetSymmetricAlgorithm (algorithm));
204                 }
205
206                 public override bool IsAsymmetricAlgorithm (string algorithm)
207                 {
208                         return GetAlgorithmSupportType (algorithm) == AlgorithmSupportType.Asymmetric;
209                 }
210
211                 public override bool IsSupportedAlgorithm (string algorithm)
212                 {
213                         switch (algorithm) {
214                         case SecurityAlgorithms.HmacSha1Signature:
215                         case SecurityAlgorithms.Psha1KeyDerivation:
216                         case SecurityAlgorithms.Aes128Encryption:
217                         case SecurityAlgorithms.Aes128KeyWrap:
218                         case SecurityAlgorithms.Aes192Encryption:
219                         case SecurityAlgorithms.Aes192KeyWrap:
220                         case SecurityAlgorithms.Aes256Encryption:
221                         case SecurityAlgorithms.Aes256KeyWrap:
222                         case SecurityAlgorithms.TripleDesEncryption:
223                         case SecurityAlgorithms.TripleDesKeyWrap:
224                                 return true;
225                         default:
226                                 return false;
227                         }
228                 }
229
230                 public override bool IsSymmetricAlgorithm (string algorithm)
231                 {
232                         return GetAlgorithmSupportType (algorithm) == AlgorithmSupportType.Symmetric;
233                 }
234         }
235 }