Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / socket.io-client / lib / vendor / web-socket-js / flash-src / com / hurlant / crypto / tls / SSLSecurityParameters.as
1 /**\r
2  * TLSSecurityParameters\r
3  * \r
4  * This class encapsulates all the security parameters that get negotiated\r
5  * during the TLS handshake. It also holds all the key derivation methods.\r
6  * Copyright (c) 2007 Henri Torgemane\r
7  * \r
8  * See LICENSE.txt for full license information.\r
9  */\r
10 package com.hurlant.crypto.tls {\r
11         import com.hurlant.crypto.hash.MD5;\r
12         import com.hurlant.crypto.hash.SHA1;\r
13         import com.hurlant.util.Hex;\r
14         \r
15         import flash.utils.ByteArray;\r
16         \r
17         public class SSLSecurityParameters implements ISecurityParameters {\r
18                 \r
19                 // COMPRESSION\r
20                 public static const COMPRESSION_NULL:uint = 0;\r
21                 \r
22                 private var entity:uint; // SERVER | CLIENT\r
23                 private var bulkCipher:uint; // BULK_CIPHER_*\r
24                 private var cipherType:uint; // STREAM_CIPHER | BLOCK_CIPHER\r
25                 private var keySize:uint;\r
26                 private var keyMaterialLength:uint;\r
27                 private var keyBlock:ByteArray;\r
28                 private var IVSize:uint;\r
29                 private var MAC_length:uint;\r
30                 private var macAlgorithm:uint; // MAC_*\r
31                 private var hashSize:uint;\r
32                 private var compression:uint; // COMPRESSION_NULL\r
33                 private var masterSecret:ByteArray; // 48 bytes\r
34                 private var clientRandom:ByteArray; // 32 bytes\r
35                 private var serverRandom:ByteArray; // 32 bytes\r
36                 private var pad_1:ByteArray; // varies\r
37                 private var pad_2:ByteArray; // varies\r
38                 private var ignoreCNMismatch:Boolean = true;\r
39                 private var trustAllCerts:Boolean = false;\r
40                 private var trustSelfSigned:Boolean = false;\r
41                 public static const PROTOCOL_VERSION:uint = 0x0300;\r
42                 \r
43                 // not strictly speaking part of this, but yeah.\r
44                 public var keyExchange:uint;\r
45                 \r
46                 public function get version() : uint { \r
47                         return PROTOCOL_VERSION;\r
48                 }\r
49                 public function SSLSecurityParameters(entity:uint, localCert:ByteArray = null, localKey:ByteArray = null) {\r
50                         this.entity = entity;\r
51                         reset();\r
52                 }\r
53                 \r
54                 public function reset():void {\r
55                         bulkCipher = BulkCiphers.NULL;\r
56                         cipherType = BulkCiphers.BLOCK_CIPHER;\r
57                         macAlgorithm = MACs.NULL;\r
58                         compression = COMPRESSION_NULL;\r
59                         masterSecret = null;\r
60                 }\r
61                 \r
62                 public function getBulkCipher():uint {\r
63                         return bulkCipher;\r
64                 }\r
65                 public function getCipherType():uint {\r
66                         return cipherType;\r
67                 }\r
68                 public function getMacAlgorithm():uint {\r
69                         return macAlgorithm;\r
70                 }\r
71                 \r
72                 public function setCipher(cipher:uint):void {\r
73                         bulkCipher = CipherSuites.getBulkCipher(cipher);\r
74                         cipherType = BulkCiphers.getType(bulkCipher);\r
75                         keySize = BulkCiphers.getExpandedKeyBytes(bulkCipher);   // 8\r
76                         keyMaterialLength = BulkCiphers.getKeyBytes(bulkCipher); // 5\r
77                         IVSize = BulkCiphers.getIVSize(bulkCipher);\r
78 \r
79 \r
80                         keyExchange = CipherSuites.getKeyExchange(cipher);\r
81                         \r
82                         macAlgorithm = CipherSuites.getMac(cipher);\r
83                         hashSize = MACs.getHashSize(macAlgorithm);\r
84                         pad_1 = new ByteArray();\r
85                         pad_2 = new ByteArray();\r
86                         for (var x:int = 0; x < 48; x++) {\r
87                                 pad_1.writeByte(0x36);\r
88                                 pad_2.writeByte(0x5c);\r
89                         }                       \r
90                 }\r
91                 public function setCompression(algo:uint):void {\r
92                         compression = algo;\r
93                 }\r
94                 \r
95                 public function setPreMasterSecret(secret:ByteArray):void {\r
96                         /* Warning! Following code may cause madness\r
97                                  Tread not here, unless ye be men of valor.\r
98                         \r
99                         ***** Official Prophylactic Comment ******\r
100                                 (to protect the unwary...this code actually works, that's all you need to know)\r
101                         \r
102                         This does two things, computes the master secret, and generates the keyBlock\r
103                         \r
104                         \r
105                         To compute the master_secret, the following algorithm is used.\r
106                          for SSL 3, this means\r
107                          master = MD5( premaster + SHA1('A' + premaster + client_random + server_random ) ) +\r
108                                                 MD5( premaster + SHA1('BB' + premaster + client_random + server_random ) ) +\r
109                                                 MD5( premaster + SHA1('CCC' + premaster + client_random + server_random ) )\r
110                         */              \r
111                         var tempHashA:ByteArray = new ByteArray(); // temporary hash, gets reused a lot\r
112                         var tempHashB:ByteArray = new ByteArray(); // temporary hash, gets reused a lot\r
113                         \r
114                         var shaHash:ByteArray;\r
115                         var mdHash:ByteArray;\r
116                         \r
117                         var i:int;\r
118                         var j:int;\r
119                         \r
120                         var sha:SHA1 = new SHA1();\r
121                         var md:MD5 = new MD5();\r
122                                         \r
123                         var k:ByteArray = new ByteArray();\r
124                         \r
125                         k.writeBytes(secret);\r
126                         k.writeBytes(clientRandom);\r
127                         k.writeBytes(serverRandom);\r
128                         \r
129                         masterSecret = new ByteArray();\r
130                         var pad_char:uint = 0x41;\r
131                         \r
132                         for ( i = 0; i < 3; i++) {\r
133                                 // SHA portion\r
134                                 tempHashA.position = 0;\r
135                                                                 \r
136                                 for ( j = 0; j < i + 1; j++) {\r
137                                         tempHashA.writeByte(pad_char);\r
138                                 }\r
139                                 pad_char++;\r
140                                 \r
141                                 tempHashA.writeBytes(k);\r
142                                 shaHash = sha.hash(tempHashA);\r
143                                 \r
144                                 // MD5 portion\r
145                                 tempHashB.position = 0;\r
146                                 tempHashB.writeBytes(secret); \r
147                                 tempHashB.writeBytes(shaHash); \r
148                                 mdHash = md.hash(tempHashB);\r
149                                 \r
150                                 // copy into my key\r
151                                 masterSecret.writeBytes(mdHash);\r
152                         }\r
153                         \r
154                         // *************** END MASTER SECRET **************\r
155                         \r
156                         // More prophylactic comments\r
157                         // *************** START KEY BLOCK ****************\r
158                         \r
159                         // So here, I'm setting up the keyBlock array that I will derive MACs, keys, and IVs from.\r
160                         // Rebuild k (hash seed)\r
161                          \r
162                         k.position = 0; \r
163                         k.writeBytes(masterSecret);\r
164                         k.writeBytes(serverRandom);\r
165                         k.writeBytes(clientRandom);\r
166                         \r
167                         keyBlock = new ByteArray(); \r
168                         \r
169                         tempHashA = new ByteArray();\r
170                         tempHashB = new ByteArray();\r
171                         // now for 16 iterations to get 256 bytes (16 * 16), better to have more than not enough\r
172                         pad_char = 0x41;\r
173                         for ( i = 0; i < 16; i++) {\r
174                                 tempHashA.position = 0; \r
175                                 \r
176                                 for ( j = 0; j < i + 1; j++) {\r
177                                         tempHashA.writeByte(pad_char);\r
178                                 }\r
179                                 pad_char++;\r
180                                 tempHashA.writeBytes(k);\r
181                                 shaHash = sha.hash(tempHashA);  \r
182                                 \r
183                                 tempHashB.position = 0; \r
184                                 tempHashB.writeBytes(masterSecret);\r
185                                 tempHashB.writeBytes(shaHash, 0);\r
186                                 mdHash = md.hash(tempHashB);\r
187                                 \r
188                                 keyBlock.writeBytes(mdHash); \r
189                         }\r
190                 }\r
191                 \r
192                 public function setClientRandom(secret:ByteArray):void {\r
193                         clientRandom = secret;\r
194                 }\r
195                 public function setServerRandom(secret:ByteArray):void {\r
196                         serverRandom = secret;\r
197                 }\r
198                 \r
199                 public function get useRSA():Boolean {\r
200                         return KeyExchanges.useRSA(keyExchange);\r
201                 }\r
202                 \r
203                 // This is the Finished message\r
204                 // if you value your sanity, stay away...far away\r
205                 public function computeVerifyData(side:uint, handshakeMessages:ByteArray):ByteArray {\r
206                         // for SSL 3.0, this consists of\r
207                         //      finished = md5( masterSecret + pad2 + md5( handshake + sender + masterSecret + pad1 ) ) +\r
208                         //                         sha1( masterSecret + pad2 + sha1( handshake + sender + masterSecret + pad1 ) )\r
209                         \r
210                         // trace("Handshake messages: " + Hex.fromArray(handshakeMessages));\r
211                         var sha:SHA1 = new SHA1();\r
212                         var md:MD5 = new MD5();\r
213                         var k:ByteArray = new ByteArray(); // handshake + sender + masterSecret + pad1\r
214                         var j:ByteArray = new ByteArray(); // masterSecret + pad2 + k\r
215                         \r
216                         var innerKey:ByteArray;\r
217                         var outerKey:ByteArray = new ByteArray();\r
218                         \r
219                         var hashSha:ByteArray;\r
220                         var hashMD:ByteArray;\r
221                         \r
222                         var sideBytes:ByteArray = new ByteArray();\r
223                         if (side == TLSEngine.CLIENT) {\r
224                                 sideBytes.writeUnsignedInt(0x434C4E54);\r
225                          } else {\r
226                                 sideBytes.writeUnsignedInt(0x53525652);\r
227                         }\r
228                         \r
229                         // Do the SHA1 part of the routine first\r
230                         masterSecret.position = 0;\r
231                         k.writeBytes(handshakeMessages);\r
232                         k.writeBytes(sideBytes);\r
233                         k.writeBytes(masterSecret);\r
234                         k.writeBytes(pad_1, 0, 40); // limited to 40 chars for SHA1\r
235                                 \r
236                         innerKey = sha.hash(k);\r
237                         // trace("Inner SHA Key: " + Hex.fromArray(innerKey));\r
238                         \r
239                         j.writeBytes(masterSecret);\r
240                         j.writeBytes(pad_2, 0, 40); // limited to 40 chars for SHA1\r
241                         j.writeBytes(innerKey);\r
242                         \r
243                         hashSha = sha.hash(j);\r
244                         // trace("Outer SHA Key: " + Hex.fromArray(hashSha));\r
245                         \r
246                         // Rebuild k for MD5\r
247                         k = new ByteArray();\r
248                         \r
249                         k.writeBytes(handshakeMessages);\r
250                         k.writeBytes(sideBytes);\r
251                         k.writeBytes(masterSecret);\r
252                         k.writeBytes(pad_1); // Take the whole length of pad_1 & pad_2 for MD5\r
253                         \r
254                         innerKey = md.hash(k);\r
255                         // trace("Inner MD5 Key: " + Hex.fromArray(innerKey));\r
256                         \r
257                         j = new ByteArray();\r
258                         j.writeBytes(masterSecret);\r
259                         j.writeBytes(pad_2); // see above re: 48 byte pad\r
260                         j.writeBytes(innerKey); \r
261                         \r
262                         hashMD = md.hash(j);\r
263                         // trace("Outer MD5 Key: " + Hex.fromArray(hashMD));\r
264                         \r
265                         outerKey.writeBytes(hashMD, 0, hashMD.length);\r
266                         outerKey.writeBytes(hashSha, 0, hashSha.length);\r
267                         var out:String = Hex.fromArray(outerKey);\r
268                         // trace("Finished Message: " + out);\r
269                         outerKey.position = 0;\r
270                         \r
271                         return outerKey;\r
272                 \r
273                 }\r
274                 \r
275                 public function computeCertificateVerify( side:uint, handshakeMessages:ByteArray ):ByteArray {\r
276                         // TODO: Implement this, but I don't forsee it being necessary at this point in time, since for purposes\r
277                         // of the override, I'm only going to use TLS\r
278                         return null;  \r
279                 }\r
280                 \r
281                 public function getConnectionStates():Object {\r
282                         \r
283                         if (masterSecret != null) {\r
284                                 // so now, I have to derive the actual keys from the keyblock that I generated in setPremasterSecret.\r
285                                 // for MY purposes, I need RSA-AES 128/256 + SHA\r
286                                 // so I'm gonna have keylen = 32, minlen = 32, mac_length = 20, iv_length = 16\r
287                                 // but...I can get this data from the settings returned in the constructor when this object is \r
288                                 // It strikes me that TLS does this more elegantly...\r
289                                 \r
290                                 var mac_length:int = hashSize as Number;\r
291                                 var key_length:int = keySize as Number;\r
292                                 var iv_length:int = IVSize as Number;\r
293                                 \r
294                                 var client_write_MAC:ByteArray = new ByteArray();\r
295                                 var server_write_MAC:ByteArray = new ByteArray();\r
296                                 var client_write_key:ByteArray = new ByteArray();\r
297                                 var server_write_key:ByteArray = new ByteArray();\r
298                                 var client_write_IV:ByteArray = new ByteArray();\r
299                                 var server_write_IV:ByteArray = new ByteArray();\r
300                 \r
301                                 // Derive the keys from the keyblock\r
302                                 // Get the MACs first\r
303                                 keyBlock.position = 0;\r
304                                 keyBlock.readBytes(client_write_MAC, 0, mac_length);\r
305                                 keyBlock.readBytes(server_write_MAC, 0, mac_length);\r
306                                 \r
307                                 // keyBlock.position is now at MAC_length * 2\r
308                                 // then get the keys\r
309                                 keyBlock.readBytes(client_write_key, 0, key_length);\r
310                                 keyBlock.readBytes(server_write_key, 0, key_length);\r
311                                 \r
312                                 // keyBlock.position is now at (MAC_length * 2) + (keySize * 2) \r
313                                 // and then the IVs\r
314                                 keyBlock.readBytes(client_write_IV, 0, iv_length);\r
315                                 keyBlock.readBytes(server_write_IV, 0, iv_length);\r
316                                 \r
317                                 // reset this in case it's needed, for some reason or another, but I doubt it\r
318                                 keyBlock.position = 0;\r
319                                 \r
320                                 var client_write:SSLConnectionState = new SSLConnectionState(\r
321                                                 bulkCipher, cipherType, macAlgorithm,\r
322                                                 client_write_MAC, client_write_key, client_write_IV);\r
323                                 var server_write:SSLConnectionState = new SSLConnectionState(\r
324                                                 bulkCipher, cipherType, macAlgorithm,\r
325                                                 server_write_MAC, server_write_key, server_write_IV);\r
326                                 \r
327                                 if (entity == TLSEngine.CLIENT) {\r
328                                         return {read:server_write, write:client_write};\r
329                                 } else {\r
330                                         return {read:client_write, write:server_write};\r
331                                 }\r
332 \r
333 \r
334                         } else {\r
335                                 return {read:new SSLConnectionState, write:new SSLConnectionState};\r
336                         }\r
337                 }\r
338                 \r
339         }\r
340 }