aboutsummaryrefslogtreecommitdiffstats
path: root/signaling-server/node_modules/socket.io/node_modules/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/TLSSecurityParameters.as
blob: 2637811f10996111793e8e8c08c026a8fc1c0513 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/**
 * TLSSecurityParameters
 * 
 * This class encapsulates all the security parameters that get negotiated
 * during the TLS handshake. It also holds all the key derivation methods.
 * Copyright (c) 2007 Henri Torgemane
 * 
 * Patched by Bobby Parker (sh0rtwave@gmail.com)
 * 
 * See LICENSE.txt for full license information.
 */
package com.hurlant.crypto.tls {
	import com.hurlant.crypto.hash.MD5;
	import com.hurlant.crypto.hash.SHA1;
	import com.hurlant.crypto.prng.TLSPRF;
	import com.hurlant.util.Hex;
	
	import flash.utils.ByteArray;
	import com.hurlant.crypto.rsa.RSAKey;
	
	public class TLSSecurityParameters implements ISecurityParameters {
		
		// COMPRESSION
		public static const COMPRESSION_NULL:uint = 0;
		
		// This is probably not smart. Revise this to use all settings from TLSConfig, since this shouldn't really know about
		// user settings, those are best handled from the engine at a session level.
		public static var IGNORE_CN_MISMATCH:Boolean = true;
		public static var ENABLE_USER_CLIENT_CERTIFICATE:Boolean = false;
		public static var USER_CERTIFICATE:String;
		
		
		private var cert:ByteArray; // Local Cert
		private var key:RSAKey; // local key
		private var entity:uint; // SERVER | CLIENT
		private var bulkCipher:uint; // BULK_CIPHER_*
		private var cipherType:uint; // STREAM_CIPHER | BLOCK_CIPHER
		private var keySize:uint;
		private var keyMaterialLength:uint;
		private var IVSize:uint;
		private var macAlgorithm:uint; // MAC_*
		private var hashSize:uint;
		private var compression:uint; // COMPRESSION_NULL
		private var masterSecret:ByteArray; // 48 bytes
		private var clientRandom:ByteArray; // 32 bytes
		private var serverRandom:ByteArray; // 32 bytes
		private var ignoreCNMismatch:Boolean = true;
		private var trustAllCerts:Boolean = false;
		private var trustSelfSigned:Boolean = false;
		public static const PROTOCOL_VERSION:uint = 0x0301; 
		private var tlsDebug:Boolean = false;

		
		// not strictly speaking part of this, but yeah.
		public var keyExchange:uint;
		public function TLSSecurityParameters(entity:uint, localCert:ByteArray = null, localKey:RSAKey = null) {
			this.entity = entity;
			reset();
			key = localKey;
			cert = localCert;
		}
		
		public function get version() : uint {
			return PROTOCOL_VERSION;
		}
		
		public function reset():void {
			bulkCipher = BulkCiphers.NULL;
			cipherType = BulkCiphers.BLOCK_CIPHER;
			macAlgorithm = MACs.NULL;
			compression = COMPRESSION_NULL;
			masterSecret = null;
		}
		
		public function getBulkCipher():uint {
			return bulkCipher;
		}
		public function getCipherType():uint {
			return cipherType;
		}
		public function getMacAlgorithm():uint {
			return macAlgorithm;
		}
		
		public function setCipher(cipher:uint):void {
			bulkCipher = CipherSuites.getBulkCipher(cipher);
			cipherType = BulkCiphers.getType(bulkCipher);
			keySize = BulkCiphers.getExpandedKeyBytes(bulkCipher);   // 8
			keyMaterialLength = BulkCiphers.getKeyBytes(bulkCipher); // 5
			IVSize = BulkCiphers.getIVSize(bulkCipher);
			
			keyExchange = CipherSuites.getKeyExchange(cipher);
			
			macAlgorithm = CipherSuites.getMac(cipher);
			hashSize = MACs.getHashSize(macAlgorithm);
		}
		public function setCompression(algo:uint):void {
			compression = algo;
		}
		public function setPreMasterSecret(secret:ByteArray):void {
			// compute master_secret
			var seed:ByteArray = new ByteArray;
			seed.writeBytes(clientRandom, 0, clientRandom.length);
			seed.writeBytes(serverRandom, 0, serverRandom.length);
			var prf:TLSPRF = new TLSPRF(secret, "master secret", seed);
			masterSecret = new ByteArray;
			prf.nextBytes(masterSecret, 48);
			if (tlsDebug)
				trace("Master Secret: " + Hex.fromArray( masterSecret, true ));
		}
		public function setClientRandom(secret:ByteArray):void {
			clientRandom = secret;
		}
		public function setServerRandom(secret:ByteArray):void { 
			serverRandom = secret;
		}
		
		public function get useRSA():Boolean {
			return KeyExchanges.useRSA(keyExchange);
		}
		
		public function computeVerifyData(side:uint, handshakeMessages:ByteArray):ByteArray {
			var seed:ByteArray = new ByteArray;
			var md5:MD5 = new MD5;
			if (tlsDebug)
				trace("Handshake value: " + Hex.fromArray(handshakeMessages, true ));
			seed.writeBytes(md5.hash(handshakeMessages),0,md5.getHashSize());
			var sha:SHA1 = new SHA1;
			seed.writeBytes(sha.hash(handshakeMessages),0,sha.getHashSize());
			if (tlsDebug)
				trace("Seed in: " + Hex.fromArray(seed, true ));
			var prf:TLSPRF = new TLSPRF(masterSecret, (side==TLSEngine.CLIENT) ? "client finished" : "server finished", seed);
			var out:ByteArray = new ByteArray;
			prf.nextBytes(out, 12);
			if (tlsDebug)
				trace("Finished out: " + Hex.fromArray(out, true ));
			out.position = 0;
			return out;
		}
		
		// client side certficate check - This is probably incorrect somehow
		public function computeCertificateVerify( side:uint, handshakeMessages:ByteArray ):ByteArray {
			var seed:ByteArray = new ByteArray;
			var md5:MD5 = new MD5;
			seed.writeBytes(md5.hash(handshakeMessages),0,md5.getHashSize());
			var sha:SHA1 = new SHA1;
			seed.writeBytes(sha.hash(handshakeMessages),0,sha.getHashSize());
			
			// Now that I have my hashes of existing handshake messages (which I'm not sure about the length of yet) then 
			// Sign that with my private key
			seed.position = 0;
			var out:ByteArray = new ByteArray();
			key.sign( seed, out, seed.bytesAvailable);
			out.position = 0;
			return out;	
		}
		
		public function getConnectionStates():Object {
			if (masterSecret != null) {
				var seed:ByteArray = new ByteArray;
				seed.writeBytes(serverRandom, 0, serverRandom.length);
				seed.writeBytes(clientRandom, 0, clientRandom.length);
				var prf:TLSPRF = new TLSPRF(masterSecret, "key expansion", seed);
				
				var client_write_MAC:ByteArray = new ByteArray;
				prf.nextBytes(client_write_MAC, hashSize);
				var server_write_MAC:ByteArray = new ByteArray;
				prf.nextBytes(server_write_MAC, hashSize);
				var client_write_key:ByteArray = new ByteArray;
				prf.nextBytes(client_write_key, keyMaterialLength);
				var server_write_key:ByteArray = new ByteArray;
				prf.nextBytes(server_write_key, keyMaterialLength);
				var client_write_IV:ByteArray = new ByteArray;
				prf.nextBytes(client_write_IV, IVSize);
				var server_write_IV:ByteArray = new ByteArray;
				prf.nextBytes(server_write_IV, IVSize);

				var client_write:TLSConnectionState = new TLSConnectionState(
						bulkCipher, cipherType, macAlgorithm,
						client_write_MAC, client_write_key, client_write_IV);
				var server_write:TLSConnectionState = new TLSConnectionState(
						bulkCipher, cipherType, macAlgorithm,
						server_write_MAC, server_write_key, server_write_IV);
				
				if (entity == TLSEngine.CLIENT) {
					return {read:server_write, write:client_write};
				} else {
					return {read:client_write, write:server_write};
				}

			} else {
				return {read:new TLSConnectionState, write:new TLSConnectionState};
			}
		}
		
	}
}