corrade-nucleus-nucleons – Blame information for rev 26
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
22 | office | 1 | /** |
2 | * A Javascript implementation of Transport Layer Security (TLS). |
||
3 | * |
||
4 | * @author Dave Longley |
||
5 | * |
||
6 | * Copyright (c) 2009-2014 Digital Bazaar, Inc. |
||
7 | * |
||
8 | * The TLS Handshake Protocol involves the following steps: |
||
9 | * |
||
10 | * - Exchange hello messages to agree on algorithms, exchange random values, |
||
11 | * and check for session resumption. |
||
12 | * |
||
13 | * - Exchange the necessary cryptographic parameters to allow the client and |
||
14 | * server to agree on a premaster secret. |
||
15 | * |
||
16 | * - Exchange certificates and cryptographic information to allow the client |
||
17 | * and server to authenticate themselves. |
||
18 | * |
||
19 | * - Generate a master secret from the premaster secret and exchanged random |
||
20 | * values. |
||
21 | * |
||
22 | * - Provide security parameters to the record layer. |
||
23 | * |
||
24 | * - Allow the client and server to verify that their peer has calculated the |
||
25 | * same security parameters and that the handshake occurred without tampering |
||
26 | * by an attacker. |
||
27 | * |
||
28 | * Up to 4 different messages may be sent during a key exchange. The server |
||
29 | * certificate, the server key exchange, the client certificate, and the |
||
30 | * client key exchange. |
||
31 | * |
||
32 | * A typical handshake (from the client's perspective). |
||
33 | * |
||
34 | * 1. Client sends ClientHello. |
||
35 | * 2. Client receives ServerHello. |
||
36 | * 3. Client receives optional Certificate. |
||
37 | * 4. Client receives optional ServerKeyExchange. |
||
38 | * 5. Client receives ServerHelloDone. |
||
39 | * 6. Client sends optional Certificate. |
||
40 | * 7. Client sends ClientKeyExchange. |
||
41 | * 8. Client sends optional CertificateVerify. |
||
42 | * 9. Client sends ChangeCipherSpec. |
||
43 | * 10. Client sends Finished. |
||
44 | * 11. Client receives ChangeCipherSpec. |
||
45 | * 12. Client receives Finished. |
||
46 | * 13. Client sends/receives application data. |
||
47 | * |
||
48 | * To reuse an existing session: |
||
49 | * |
||
50 | * 1. Client sends ClientHello with session ID for reuse. |
||
51 | * 2. Client receives ServerHello with same session ID if reusing. |
||
52 | * 3. Client receives ChangeCipherSpec message if reusing. |
||
53 | * 4. Client receives Finished. |
||
54 | * 5. Client sends ChangeCipherSpec. |
||
55 | * 6. Client sends Finished. |
||
56 | * |
||
57 | * Note: Client ignores HelloRequest if in the middle of a handshake. |
||
58 | * |
||
59 | * Record Layer: |
||
60 | * |
||
61 | * The record layer fragments information blocks into TLSPlaintext records |
||
62 | * carrying data in chunks of 2^14 bytes or less. Client message boundaries are |
||
63 | * not preserved in the record layer (i.e., multiple client messages of the |
||
64 | * same ContentType MAY be coalesced into a single TLSPlaintext record, or a |
||
65 | * single message MAY be fragmented across several records). |
||
66 | * |
||
67 | * struct { |
||
68 | * uint8 major; |
||
69 | * uint8 minor; |
||
70 | * } ProtocolVersion; |
||
71 | * |
||
72 | * struct { |
||
73 | * ContentType type; |
||
74 | * ProtocolVersion version; |
||
75 | * uint16 length; |
||
76 | * opaque fragment[TLSPlaintext.length]; |
||
77 | * } TLSPlaintext; |
||
78 | * |
||
79 | * type: |
||
80 | * The higher-level protocol used to process the enclosed fragment. |
||
81 | * |
||
82 | * version: |
||
83 | * The version of the protocol being employed. TLS Version 1.2 uses version |
||
84 | * {3, 3}. TLS Version 1.0 uses version {3, 1}. Note that a client that |
||
85 | * supports multiple versions of TLS may not know what version will be |
||
86 | * employed before it receives the ServerHello. |
||
87 | * |
||
88 | * length: |
||
89 | * The length (in bytes) of the following TLSPlaintext.fragment. The length |
||
90 | * MUST NOT exceed 2^14 = 16384 bytes. |
||
91 | * |
||
92 | * fragment: |
||
93 | * The application data. This data is transparent and treated as an |
||
94 | * independent block to be dealt with by the higher-level protocol specified |
||
95 | * by the type field. |
||
96 | * |
||
97 | * Implementations MUST NOT send zero-length fragments of Handshake, Alert, or |
||
98 | * ChangeCipherSpec content types. Zero-length fragments of Application data |
||
99 | * MAY be sent as they are potentially useful as a traffic analysis |
||
100 | * countermeasure. |
||
101 | * |
||
102 | * Note: Data of different TLS record layer content types MAY be interleaved. |
||
103 | * Application data is generally of lower precedence for transmission than |
||
104 | * other content types. However, records MUST be delivered to the network in |
||
105 | * the same order as they are protected by the record layer. Recipients MUST |
||
106 | * receive and process interleaved application layer traffic during handshakes |
||
107 | * subsequent to the first one on a connection. |
||
108 | * |
||
109 | * struct { |
||
110 | * ContentType type; // same as TLSPlaintext.type |
||
111 | * ProtocolVersion version;// same as TLSPlaintext.version |
||
112 | * uint16 length; |
||
113 | * opaque fragment[TLSCompressed.length]; |
||
114 | * } TLSCompressed; |
||
115 | * |
||
116 | * length: |
||
117 | * The length (in bytes) of the following TLSCompressed.fragment. |
||
118 | * The length MUST NOT exceed 2^14 + 1024. |
||
119 | * |
||
120 | * fragment: |
||
121 | * The compressed form of TLSPlaintext.fragment. |
||
122 | * |
||
123 | * Note: A CompressionMethod.null operation is an identity operation; no fields |
||
124 | * are altered. In this implementation, since no compression is supported, |
||
125 | * uncompressed records are always the same as compressed records. |
||
126 | * |
||
127 | * Encryption Information: |
||
128 | * |
||
129 | * The encryption and MAC functions translate a TLSCompressed structure into a |
||
130 | * TLSCiphertext. The decryption functions reverse the process. The MAC of the |
||
131 | * record also includes a sequence number so that missing, extra, or repeated |
||
132 | * messages are detectable. |
||
133 | * |
||
134 | * struct { |
||
135 | * ContentType type; |
||
136 | * ProtocolVersion version; |
||
137 | * uint16 length; |
||
138 | * select (SecurityParameters.cipher_type) { |
||
139 | * case stream: GenericStreamCipher; |
||
140 | * case block: GenericBlockCipher; |
||
141 | * case aead: GenericAEADCipher; |
||
142 | * } fragment; |
||
143 | * } TLSCiphertext; |
||
144 | * |
||
145 | * type: |
||
146 | * The type field is identical to TLSCompressed.type. |
||
147 | * |
||
148 | * version: |
||
149 | * The version field is identical to TLSCompressed.version. |
||
150 | * |
||
151 | * length: |
||
152 | * The length (in bytes) of the following TLSCiphertext.fragment. |
||
153 | * The length MUST NOT exceed 2^14 + 2048. |
||
154 | * |
||
155 | * fragment: |
||
156 | * The encrypted form of TLSCompressed.fragment, with the MAC. |
||
157 | * |
||
158 | * Note: Only CBC Block Ciphers are supported by this implementation. |
||
159 | * |
||
160 | * The TLSCompressed.fragment structures are converted to/from block |
||
161 | * TLSCiphertext.fragment structures. |
||
162 | * |
||
163 | * struct { |
||
164 | * opaque IV[SecurityParameters.record_iv_length]; |
||
165 | * block-ciphered struct { |
||
166 | * opaque content[TLSCompressed.length]; |
||
167 | * opaque MAC[SecurityParameters.mac_length]; |
||
168 | * uint8 padding[GenericBlockCipher.padding_length]; |
||
169 | * uint8 padding_length; |
||
170 | * }; |
||
171 | * } GenericBlockCipher; |
||
172 | * |
||
173 | * The MAC is generated as described in Section 6.2.3.1. |
||
174 | * |
||
175 | * IV: |
||
176 | * The Initialization Vector (IV) SHOULD be chosen at random, and MUST be |
||
177 | * unpredictable. Note that in versions of TLS prior to 1.1, there was no |
||
178 | * IV field, and the last ciphertext block of the previous record (the "CBC |
||
179 | * residue") was used as the IV. This was changed to prevent the attacks |
||
180 | * described in [CBCATT]. For block ciphers, the IV length is of length |
||
181 | * SecurityParameters.record_iv_length, which is equal to the |
||
182 | * SecurityParameters.block_size. |
||
183 | * |
||
184 | * padding: |
||
185 | * Padding that is added to force the length of the plaintext to be an |
||
186 | * integral multiple of the block cipher's block length. The padding MAY be |
||
187 | * any length up to 255 bytes, as long as it results in the |
||
188 | * TLSCiphertext.length being an integral multiple of the block length. |
||
189 | * Lengths longer than necessary might be desirable to frustrate attacks on |
||
190 | * a protocol that are based on analysis of the lengths of exchanged |
||
191 | * messages. Each uint8 in the padding data vector MUST be filled with the |
||
192 | * padding length value. The receiver MUST check this padding and MUST use |
||
193 | * the bad_record_mac alert to indicate padding errors. |
||
194 | * |
||
195 | * padding_length: |
||
196 | * The padding length MUST be such that the total size of the |
||
197 | * GenericBlockCipher structure is a multiple of the cipher's block length. |
||
198 | * Legal values range from zero to 255, inclusive. This length specifies the |
||
199 | * length of the padding field exclusive of the padding_length field itself. |
||
200 | * |
||
201 | * The encrypted data length (TLSCiphertext.length) is one more than the sum of |
||
202 | * SecurityParameters.block_length, TLSCompressed.length, |
||
203 | * SecurityParameters.mac_length, and padding_length. |
||
204 | * |
||
205 | * Example: If the block length is 8 bytes, the content length |
||
206 | * (TLSCompressed.length) is 61 bytes, and the MAC length is 20 bytes, then the |
||
207 | * length before padding is 82 bytes (this does not include the IV. Thus, the |
||
208 | * padding length modulo 8 must be equal to 6 in order to make the total length |
||
209 | * an even multiple of 8 bytes (the block length). The padding length can be |
||
210 | * 6, 14, 22, and so on, through 254. If the padding length were the minimum |
||
211 | * necessary, 6, the padding would be 6 bytes, each containing the value 6. |
||
212 | * Thus, the last 8 octets of the GenericBlockCipher before block encryption |
||
213 | * would be xx 06 06 06 06 06 06 06, where xx is the last octet of the MAC. |
||
214 | * |
||
215 | * Note: With block ciphers in CBC mode (Cipher Block Chaining), it is critical |
||
216 | * that the entire plaintext of the record be known before any ciphertext is |
||
217 | * transmitted. Otherwise, it is possible for the attacker to mount the attack |
||
218 | * described in [CBCATT]. |
||
219 | * |
||
220 | * Implementation note: Canvel et al. [CBCTIME] have demonstrated a timing |
||
221 | * attack on CBC padding based on the time required to compute the MAC. In |
||
222 | * order to defend against this attack, implementations MUST ensure that |
||
223 | * record processing time is essentially the same whether or not the padding |
||
224 | * is correct. In general, the best way to do this is to compute the MAC even |
||
225 | * if the padding is incorrect, and only then reject the packet. For instance, |
||
226 | * if the pad appears to be incorrect, the implementation might assume a |
||
227 | * zero-length pad and then compute the MAC. This leaves a small timing |
||
228 | * channel, since MAC performance depends, to some extent, on the size of the |
||
229 | * data fragment, but it is not believed to be large enough to be exploitable, |
||
230 | * due to the large block size of existing MACs and the small size of the |
||
231 | * timing signal. |
||
232 | */ |
||
233 | var forge = require('./forge'); |
||
234 | require('./asn1'); |
||
235 | require('./hmac'); |
||
236 | require('./md5'); |
||
237 | require('./pem'); |
||
238 | require('./pki'); |
||
239 | require('./random'); |
||
240 | require('./sha1'); |
||
241 | require('./util'); |
||
242 | |||
243 | /** |
||
244 | * Generates pseudo random bytes by mixing the result of two hash functions, |
||
245 | * MD5 and SHA-1. |
||
246 | * |
||
247 | * prf_TLS1(secret, label, seed) = |
||
248 | * P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed); |
||
249 | * |
||
250 | * Each P_hash function functions as follows: |
||
251 | * |
||
252 | * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + |
||
253 | * HMAC_hash(secret, A(2) + seed) + |
||
254 | * HMAC_hash(secret, A(3) + seed) + ... |
||
255 | * A() is defined as: |
||
256 | * A(0) = seed |
||
257 | * A(i) = HMAC_hash(secret, A(i-1)) |
||
258 | * |
||
259 | * The '+' operator denotes concatenation. |
||
260 | * |
||
261 | * As many iterations A(N) as are needed are performed to generate enough |
||
262 | * pseudo random byte output. If an iteration creates more data than is |
||
263 | * necessary, then it is truncated. |
||
264 | * |
||
265 | * Therefore: |
||
266 | * A(1) = HMAC_hash(secret, A(0)) |
||
267 | * = HMAC_hash(secret, seed) |
||
268 | * A(2) = HMAC_hash(secret, A(1)) |
||
269 | * = HMAC_hash(secret, HMAC_hash(secret, seed)) |
||
270 | * |
||
271 | * Therefore: |
||
272 | * P_hash(secret, seed) = |
||
273 | * HMAC_hash(secret, HMAC_hash(secret, A(0)) + seed) + |
||
274 | * HMAC_hash(secret, HMAC_hash(secret, A(1)) + seed) + |
||
275 | * ... |
||
276 | * |
||
277 | * Therefore: |
||
278 | * P_hash(secret, seed) = |
||
279 | * HMAC_hash(secret, HMAC_hash(secret, seed) + seed) + |
||
280 | * HMAC_hash(secret, HMAC_hash(secret, HMAC_hash(secret, seed)) + seed) + |
||
281 | * ... |
||
282 | * |
||
283 | * @param secret the secret to use. |
||
284 | * @param label the label to use. |
||
285 | * @param seed the seed value to use. |
||
286 | * @param length the number of bytes to generate. |
||
287 | * |
||
288 | * @return the pseudo random bytes in a byte buffer. |
||
289 | */ |
||
290 | var prf_TLS1 = function(secret, label, seed, length) { |
||
291 | var rval = forge.util.createBuffer(); |
||
292 | |||
293 | /* For TLS 1.0, the secret is split in half, into two secrets of equal |
||
294 | length. If the secret has an odd length then the last byte of the first |
||
295 | half will be the same as the first byte of the second. The length of the |
||
296 | two secrets is half of the secret rounded up. */ |
||
297 | var idx = (secret.length >> 1); |
||
298 | var slen = idx + (secret.length & 1); |
||
299 | var s1 = secret.substr(0, slen); |
||
300 | var s2 = secret.substr(idx, slen); |
||
301 | var ai = forge.util.createBuffer(); |
||
302 | var hmac = forge.hmac.create(); |
||
303 | seed = label + seed; |
||
304 | |||
305 | // determine the number of iterations that must be performed to generate |
||
306 | // enough output bytes, md5 creates 16 byte hashes, sha1 creates 20 |
||
307 | var md5itr = Math.ceil(length / 16); |
||
308 | var sha1itr = Math.ceil(length / 20); |
||
309 | |||
310 | // do md5 iterations |
||
311 | hmac.start('MD5', s1); |
||
312 | var md5bytes = forge.util.createBuffer(); |
||
313 | ai.putBytes(seed); |
||
314 | for(var i = 0; i < md5itr; ++i) { |
||
315 | // HMAC_hash(secret, A(i-1)) |
||
316 | hmac.start(null, null); |
||
317 | hmac.update(ai.getBytes()); |
||
318 | ai.putBuffer(hmac.digest()); |
||
319 | |||
320 | // HMAC_hash(secret, A(i) + seed) |
||
321 | hmac.start(null, null); |
||
322 | hmac.update(ai.bytes() + seed); |
||
323 | md5bytes.putBuffer(hmac.digest()); |
||
324 | } |
||
325 | |||
326 | // do sha1 iterations |
||
327 | hmac.start('SHA1', s2); |
||
328 | var sha1bytes = forge.util.createBuffer(); |
||
329 | ai.clear(); |
||
330 | ai.putBytes(seed); |
||
331 | for(var i = 0; i < sha1itr; ++i) { |
||
332 | // HMAC_hash(secret, A(i-1)) |
||
333 | hmac.start(null, null); |
||
334 | hmac.update(ai.getBytes()); |
||
335 | ai.putBuffer(hmac.digest()); |
||
336 | |||
337 | // HMAC_hash(secret, A(i) + seed) |
||
338 | hmac.start(null, null); |
||
339 | hmac.update(ai.bytes() + seed); |
||
340 | sha1bytes.putBuffer(hmac.digest()); |
||
341 | } |
||
342 | |||
343 | // XOR the md5 bytes with the sha1 bytes |
||
344 | rval.putBytes(forge.util.xorBytes( |
||
345 | md5bytes.getBytes(), sha1bytes.getBytes(), length)); |
||
346 | |||
347 | return rval; |
||
348 | }; |
||
349 | |||
350 | /** |
||
351 | * Generates pseudo random bytes using a SHA256 algorithm. For TLS 1.2. |
||
352 | * |
||
353 | * @param secret the secret to use. |
||
354 | * @param label the label to use. |
||
355 | * @param seed the seed value to use. |
||
356 | * @param length the number of bytes to generate. |
||
357 | * |
||
358 | * @return the pseudo random bytes in a byte buffer. |
||
359 | */ |
||
360 | var prf_sha256 = function(secret, label, seed, length) { |
||
361 | // FIXME: implement me for TLS 1.2 |
||
362 | }; |
||
363 | |||
364 | /** |
||
365 | * Gets a MAC for a record using the SHA-1 hash algorithm. |
||
366 | * |
||
367 | * @param key the mac key. |
||
368 | * @param state the sequence number (array of two 32-bit integers). |
||
369 | * @param record the record. |
||
370 | * |
||
371 | * @return the sha-1 hash (20 bytes) for the given record. |
||
372 | */ |
||
373 | var hmac_sha1 = function(key, seqNum, record) { |
||
374 | /* MAC is computed like so: |
||
375 | HMAC_hash( |
||
376 | key, seqNum + |
||
377 | TLSCompressed.type + |
||
378 | TLSCompressed.version + |
||
379 | TLSCompressed.length + |
||
380 | TLSCompressed.fragment) |
||
381 | */ |
||
382 | var hmac = forge.hmac.create(); |
||
383 | hmac.start('SHA1', key); |
||
384 | var b = forge.util.createBuffer(); |
||
385 | b.putInt32(seqNum[0]); |
||
386 | b.putInt32(seqNum[1]); |
||
387 | b.putByte(record.type); |
||
388 | b.putByte(record.version.major); |
||
389 | b.putByte(record.version.minor); |
||
390 | b.putInt16(record.length); |
||
391 | b.putBytes(record.fragment.bytes()); |
||
392 | hmac.update(b.getBytes()); |
||
393 | return hmac.digest().getBytes(); |
||
394 | }; |
||
395 | |||
396 | /** |
||
397 | * Compresses the TLSPlaintext record into a TLSCompressed record using the |
||
398 | * deflate algorithm. |
||
399 | * |
||
400 | * @param c the TLS connection. |
||
401 | * @param record the TLSPlaintext record to compress. |
||
402 | * @param s the ConnectionState to use. |
||
403 | * |
||
404 | * @return true on success, false on failure. |
||
405 | */ |
||
406 | var deflate = function(c, record, s) { |
||
407 | var rval = false; |
||
408 | |||
409 | try { |
||
410 | var bytes = c.deflate(record.fragment.getBytes()); |
||
411 | record.fragment = forge.util.createBuffer(bytes); |
||
412 | record.length = bytes.length; |
||
413 | rval = true; |
||
414 | } catch(ex) { |
||
415 | // deflate error, fail out |
||
416 | } |
||
417 | |||
418 | return rval; |
||
419 | }; |
||
420 | |||
421 | /** |
||
422 | * Decompresses the TLSCompressed record into a TLSPlaintext record using the |
||
423 | * deflate algorithm. |
||
424 | * |
||
425 | * @param c the TLS connection. |
||
426 | * @param record the TLSCompressed record to decompress. |
||
427 | * @param s the ConnectionState to use. |
||
428 | * |
||
429 | * @return true on success, false on failure. |
||
430 | */ |
||
431 | var inflate = function(c, record, s) { |
||
432 | var rval = false; |
||
433 | |||
434 | try { |
||
435 | var bytes = c.inflate(record.fragment.getBytes()); |
||
436 | record.fragment = forge.util.createBuffer(bytes); |
||
437 | record.length = bytes.length; |
||
438 | rval = true; |
||
439 | } catch(ex) { |
||
440 | // inflate error, fail out |
||
441 | } |
||
442 | |||
443 | return rval; |
||
444 | }; |
||
445 | |||
446 | /** |
||
447 | * Reads a TLS variable-length vector from a byte buffer. |
||
448 | * |
||
449 | * Variable-length vectors are defined by specifying a subrange of legal |
||
450 | * lengths, inclusively, using the notation <floor..ceiling>. When these are |
||
451 | * encoded, the actual length precedes the vector's contents in the byte |
||
452 | * stream. The length will be in the form of a number consuming as many bytes |
||
453 | * as required to hold the vector's specified maximum (ceiling) length. A |
||
454 | * variable-length vector with an actual length field of zero is referred to |
||
455 | * as an empty vector. |
||
456 | * |
||
457 | * @param b the byte buffer. |
||
458 | * @param lenBytes the number of bytes required to store the length. |
||
459 | * |
||
460 | * @return the resulting byte buffer. |
||
461 | */ |
||
462 | var readVector = function(b, lenBytes) { |
||
463 | var len = 0; |
||
464 | switch(lenBytes) { |
||
465 | case 1: |
||
466 | len = b.getByte(); |
||
467 | break; |
||
468 | case 2: |
||
469 | len = b.getInt16(); |
||
470 | break; |
||
471 | case 3: |
||
472 | len = b.getInt24(); |
||
473 | break; |
||
474 | case 4: |
||
475 | len = b.getInt32(); |
||
476 | break; |
||
477 | } |
||
478 | |||
479 | // read vector bytes into a new buffer |
||
480 | return forge.util.createBuffer(b.getBytes(len)); |
||
481 | }; |
||
482 | |||
483 | /** |
||
484 | * Writes a TLS variable-length vector to a byte buffer. |
||
485 | * |
||
486 | * @param b the byte buffer. |
||
487 | * @param lenBytes the number of bytes required to store the length. |
||
488 | * @param v the byte buffer vector. |
||
489 | */ |
||
490 | var writeVector = function(b, lenBytes, v) { |
||
491 | // encode length at the start of the vector, where the number of bytes for |
||
492 | // the length is the maximum number of bytes it would take to encode the |
||
493 | // vector's ceiling |
||
494 | b.putInt(v.length(), lenBytes << 3); |
||
495 | b.putBuffer(v); |
||
496 | }; |
||
497 | |||
498 | /** |
||
499 | * The tls implementation. |
||
500 | */ |
||
501 | var tls = {}; |
||
502 | |||
503 | /** |
||
504 | * Version: TLS 1.2 = 3.3, TLS 1.1 = 3.2, TLS 1.0 = 3.1. Both TLS 1.1 and |
||
505 | * TLS 1.2 were still too new (ie: openSSL didn't implement them) at the time |
||
506 | * of this implementation so TLS 1.0 was implemented instead. |
||
507 | */ |
||
508 | tls.Versions = { |
||
509 | TLS_1_0: {major: 3, minor: 1}, |
||
510 | TLS_1_1: {major: 3, minor: 2}, |
||
511 | TLS_1_2: {major: 3, minor: 3} |
||
512 | }; |
||
513 | tls.SupportedVersions = [ |
||
514 | tls.Versions.TLS_1_1, |
||
515 | tls.Versions.TLS_1_0 |
||
516 | ]; |
||
517 | tls.Version = tls.SupportedVersions[0]; |
||
518 | |||
519 | /** |
||
520 | * Maximum fragment size. True maximum is 16384, but we fragment before that |
||
521 | * to allow for unusual small increases during compression. |
||
522 | */ |
||
523 | tls.MaxFragment = 16384 - 1024; |
||
524 | |||
525 | /** |
||
526 | * Whether this entity is considered the "client" or "server". |
||
527 | * enum { server, client } ConnectionEnd; |
||
528 | */ |
||
529 | tls.ConnectionEnd = { |
||
530 | server: 0, |
||
531 | client: 1 |
||
532 | }; |
||
533 | |||
534 | /** |
||
535 | * Pseudo-random function algorithm used to generate keys from the master |
||
536 | * secret. |
||
537 | * enum { tls_prf_sha256 } PRFAlgorithm; |
||
538 | */ |
||
539 | tls.PRFAlgorithm = { |
||
540 | tls_prf_sha256: 0 |
||
541 | }; |
||
542 | |||
543 | /** |
||
544 | * Bulk encryption algorithms. |
||
545 | * enum { null, rc4, des3, aes } BulkCipherAlgorithm; |
||
546 | */ |
||
547 | tls.BulkCipherAlgorithm = { |
||
548 | none: null, |
||
549 | rc4: 0, |
||
550 | des3: 1, |
||
551 | aes: 2 |
||
552 | }; |
||
553 | |||
554 | /** |
||
555 | * Cipher types. |
||
556 | * enum { stream, block, aead } CipherType; |
||
557 | */ |
||
558 | tls.CipherType = { |
||
559 | stream: 0, |
||
560 | block: 1, |
||
561 | aead: 2 |
||
562 | }; |
||
563 | |||
564 | /** |
||
565 | * MAC (Message Authentication Code) algorithms. |
||
566 | * enum { null, hmac_md5, hmac_sha1, hmac_sha256, |
||
567 | * hmac_sha384, hmac_sha512} MACAlgorithm; |
||
568 | */ |
||
569 | tls.MACAlgorithm = { |
||
570 | none: null, |
||
571 | hmac_md5: 0, |
||
572 | hmac_sha1: 1, |
||
573 | hmac_sha256: 2, |
||
574 | hmac_sha384: 3, |
||
575 | hmac_sha512: 4 |
||
576 | }; |
||
577 | |||
578 | /** |
||
579 | * Compression algorithms. |
||
580 | * enum { null(0), deflate(1), (255) } CompressionMethod; |
||
581 | */ |
||
582 | tls.CompressionMethod = { |
||
583 | none: 0, |
||
584 | deflate: 1 |
||
585 | }; |
||
586 | |||
587 | /** |
||
588 | * TLS record content types. |
||
589 | * enum { |
||
590 | * change_cipher_spec(20), alert(21), handshake(22), |
||
591 | * application_data(23), (255) |
||
592 | * } ContentType; |
||
593 | */ |
||
594 | tls.ContentType = { |
||
595 | change_cipher_spec: 20, |
||
596 | alert: 21, |
||
597 | handshake: 22, |
||
598 | application_data: 23, |
||
599 | heartbeat: 24 |
||
600 | }; |
||
601 | |||
602 | /** |
||
603 | * TLS handshake types. |
||
604 | * enum { |
||
605 | * hello_request(0), client_hello(1), server_hello(2), |
||
606 | * certificate(11), server_key_exchange (12), |
||
607 | * certificate_request(13), server_hello_done(14), |
||
608 | * certificate_verify(15), client_key_exchange(16), |
||
609 | * finished(20), (255) |
||
610 | * } HandshakeType; |
||
611 | */ |
||
612 | tls.HandshakeType = { |
||
613 | hello_request: 0, |
||
614 | client_hello: 1, |
||
615 | server_hello: 2, |
||
616 | certificate: 11, |
||
617 | server_key_exchange: 12, |
||
618 | certificate_request: 13, |
||
619 | server_hello_done: 14, |
||
620 | certificate_verify: 15, |
||
621 | client_key_exchange: 16, |
||
622 | finished: 20 |
||
623 | }; |
||
624 | |||
625 | /** |
||
626 | * TLS Alert Protocol. |
||
627 | * |
||
628 | * enum { warning(1), fatal(2), (255) } AlertLevel; |
||
629 | * |
||
630 | * enum { |
||
631 | * close_notify(0), |
||
632 | * unexpected_message(10), |
||
633 | * bad_record_mac(20), |
||
634 | * decryption_failed(21), |
||
635 | * record_overflow(22), |
||
636 | * decompression_failure(30), |
||
637 | * handshake_failure(40), |
||
638 | * bad_certificate(42), |
||
639 | * unsupported_certificate(43), |
||
640 | * certificate_revoked(44), |
||
641 | * certificate_expired(45), |
||
642 | * certificate_unknown(46), |
||
643 | * illegal_parameter(47), |
||
644 | * unknown_ca(48), |
||
645 | * access_denied(49), |
||
646 | * decode_error(50), |
||
647 | * decrypt_error(51), |
||
648 | * export_restriction(60), |
||
649 | * protocol_version(70), |
||
650 | * insufficient_security(71), |
||
651 | * internal_error(80), |
||
652 | * user_canceled(90), |
||
653 | * no_renegotiation(100), |
||
654 | * (255) |
||
655 | * } AlertDescription; |
||
656 | * |
||
657 | * struct { |
||
658 | * AlertLevel level; |
||
659 | * AlertDescription description; |
||
660 | * } Alert; |
||
661 | */ |
||
662 | tls.Alert = {}; |
||
663 | tls.Alert.Level = { |
||
664 | warning: 1, |
||
665 | fatal: 2 |
||
666 | }; |
||
667 | tls.Alert.Description = { |
||
668 | close_notify: 0, |
||
669 | unexpected_message: 10, |
||
670 | bad_record_mac: 20, |
||
671 | decryption_failed: 21, |
||
672 | record_overflow: 22, |
||
673 | decompression_failure: 30, |
||
674 | handshake_failure: 40, |
||
675 | bad_certificate: 42, |
||
676 | unsupported_certificate: 43, |
||
677 | certificate_revoked: 44, |
||
678 | certificate_expired: 45, |
||
679 | certificate_unknown: 46, |
||
680 | illegal_parameter: 47, |
||
681 | unknown_ca: 48, |
||
682 | access_denied: 49, |
||
683 | decode_error: 50, |
||
684 | decrypt_error: 51, |
||
685 | export_restriction: 60, |
||
686 | protocol_version: 70, |
||
687 | insufficient_security: 71, |
||
688 | internal_error: 80, |
||
689 | user_canceled: 90, |
||
690 | no_renegotiation: 100 |
||
691 | }; |
||
692 | |||
693 | /** |
||
694 | * TLS Heartbeat Message types. |
||
695 | * enum { |
||
696 | * heartbeat_request(1), |
||
697 | * heartbeat_response(2), |
||
698 | * (255) |
||
699 | * } HeartbeatMessageType; |
||
700 | */ |
||
701 | tls.HeartbeatMessageType = { |
||
702 | heartbeat_request: 1, |
||
703 | heartbeat_response: 2 |
||
704 | }; |
||
705 | |||
706 | /** |
||
707 | * Supported cipher suites. |
||
708 | */ |
||
709 | tls.CipherSuites = {}; |
||
710 | |||
711 | /** |
||
712 | * Gets a supported cipher suite from its 2 byte ID. |
||
713 | * |
||
714 | * @param twoBytes two bytes in a string. |
||
715 | * |
||
716 | * @return the matching supported cipher suite or null. |
||
717 | */ |
||
718 | tls.getCipherSuite = function(twoBytes) { |
||
719 | var rval = null; |
||
720 | for(var key in tls.CipherSuites) { |
||
721 | var cs = tls.CipherSuites[key]; |
||
722 | if(cs.id[0] === twoBytes.charCodeAt(0) && |
||
723 | cs.id[1] === twoBytes.charCodeAt(1)) { |
||
724 | rval = cs; |
||
725 | break; |
||
726 | } |
||
727 | } |
||
728 | return rval; |
||
729 | }; |
||
730 | |||
731 | /** |
||
732 | * Called when an unexpected record is encountered. |
||
733 | * |
||
734 | * @param c the connection. |
||
735 | * @param record the record. |
||
736 | */ |
||
737 | tls.handleUnexpected = function(c, record) { |
||
738 | // if connection is client and closed, ignore unexpected messages |
||
739 | var ignore = (!c.open && c.entity === tls.ConnectionEnd.client); |
||
740 | if(!ignore) { |
||
741 | c.error(c, { |
||
742 | message: 'Unexpected message. Received TLS record out of order.', |
||
743 | send: true, |
||
744 | alert: { |
||
745 | level: tls.Alert.Level.fatal, |
||
746 | description: tls.Alert.Description.unexpected_message |
||
747 | } |
||
748 | }); |
||
749 | } |
||
750 | }; |
||
751 | |||
752 | /** |
||
753 | * Called when a client receives a HelloRequest record. |
||
754 | * |
||
755 | * @param c the connection. |
||
756 | * @param record the record. |
||
757 | * @param length the length of the handshake message. |
||
758 | */ |
||
759 | tls.handleHelloRequest = function(c, record, length) { |
||
760 | // ignore renegotiation requests from the server during a handshake, but |
||
761 | // if handshaking, send a warning alert that renegotation is denied |
||
762 | if(!c.handshaking && c.handshakes > 0) { |
||
763 | // send alert warning |
||
764 | tls.queue(c, tls.createAlert(c, { |
||
765 | level: tls.Alert.Level.warning, |
||
766 | description: tls.Alert.Description.no_renegotiation |
||
767 | })); |
||
768 | tls.flush(c); |
||
769 | } |
||
770 | |||
771 | // continue |
||
772 | c.process(); |
||
773 | }; |
||
774 | |||
775 | /** |
||
776 | * Parses a hello message from a ClientHello or ServerHello record. |
||
777 | * |
||
778 | * @param record the record to parse. |
||
779 | * |
||
780 | * @return the parsed message. |
||
781 | */ |
||
782 | tls.parseHelloMessage = function(c, record, length) { |
||
783 | var msg = null; |
||
784 | |||
785 | var client = (c.entity === tls.ConnectionEnd.client); |
||
786 | |||
787 | // minimum of 38 bytes in message |
||
788 | if(length < 38) { |
||
789 | c.error(c, { |
||
790 | message: client ? |
||
791 | 'Invalid ServerHello message. Message too short.' : |
||
792 | 'Invalid ClientHello message. Message too short.', |
||
793 | send: true, |
||
794 | alert: { |
||
795 | level: tls.Alert.Level.fatal, |
||
796 | description: tls.Alert.Description.illegal_parameter |
||
797 | } |
||
798 | }); |
||
799 | } else { |
||
800 | // use 'remaining' to calculate # of remaining bytes in the message |
||
801 | var b = record.fragment; |
||
802 | var remaining = b.length(); |
||
803 | msg = { |
||
804 | version: { |
||
805 | major: b.getByte(), |
||
806 | minor: b.getByte() |
||
807 | }, |
||
808 | random: forge.util.createBuffer(b.getBytes(32)), |
||
809 | session_id: readVector(b, 1), |
||
810 | extensions: [] |
||
811 | }; |
||
812 | if(client) { |
||
813 | msg.cipher_suite = b.getBytes(2); |
||
814 | msg.compression_method = b.getByte(); |
||
815 | } else { |
||
816 | msg.cipher_suites = readVector(b, 2); |
||
817 | msg.compression_methods = readVector(b, 1); |
||
818 | } |
||
819 | |||
820 | // read extensions if there are any bytes left in the message |
||
821 | remaining = length - (remaining - b.length()); |
||
822 | if(remaining > 0) { |
||
823 | // parse extensions |
||
824 | var exts = readVector(b, 2); |
||
825 | while(exts.length() > 0) { |
||
826 | msg.extensions.push({ |
||
827 | type: [exts.getByte(), exts.getByte()], |
||
828 | data: readVector(exts, 2) |
||
829 | }); |
||
830 | } |
||
831 | |||
832 | // TODO: make extension support modular |
||
833 | if(!client) { |
||
834 | for(var i = 0; i < msg.extensions.length; ++i) { |
||
835 | var ext = msg.extensions[i]; |
||
836 | |||
837 | // support SNI extension |
||
838 | if(ext.type[0] === 0x00 && ext.type[1] === 0x00) { |
||
839 | // get server name list |
||
840 | var snl = readVector(ext.data, 2); |
||
841 | while(snl.length() > 0) { |
||
842 | // read server name type |
||
843 | var snType = snl.getByte(); |
||
844 | |||
845 | // only HostName type (0x00) is known, break out if |
||
846 | // another type is detected |
||
847 | if(snType !== 0x00) { |
||
848 | break; |
||
849 | } |
||
850 | |||
851 | // add host name to server name list |
||
852 | c.session.extensions.server_name.serverNameList.push( |
||
853 | readVector(snl, 2).getBytes()); |
||
854 | } |
||
855 | } |
||
856 | } |
||
857 | } |
||
858 | } |
||
859 | |||
860 | // version already set, do not allow version change |
||
861 | if(c.session.version) { |
||
862 | if(msg.version.major !== c.session.version.major || |
||
863 | msg.version.minor !== c.session.version.minor) { |
||
864 | return c.error(c, { |
||
865 | message: 'TLS version change is disallowed during renegotiation.', |
||
866 | send: true, |
||
867 | alert: { |
||
868 | level: tls.Alert.Level.fatal, |
||
869 | description: tls.Alert.Description.protocol_version |
||
870 | } |
||
871 | }); |
||
872 | } |
||
873 | } |
||
874 | |||
875 | // get the chosen (ServerHello) cipher suite |
||
876 | if(client) { |
||
877 | // FIXME: should be checking configured acceptable cipher suites |
||
878 | c.session.cipherSuite = tls.getCipherSuite(msg.cipher_suite); |
||
879 | } else { |
||
880 | // get a supported preferred (ClientHello) cipher suite |
||
881 | // choose the first supported cipher suite |
||
882 | var tmp = forge.util.createBuffer(msg.cipher_suites.bytes()); |
||
883 | while(tmp.length() > 0) { |
||
884 | // FIXME: should be checking configured acceptable suites |
||
885 | // cipher suites take up 2 bytes |
||
886 | c.session.cipherSuite = tls.getCipherSuite(tmp.getBytes(2)); |
||
887 | if(c.session.cipherSuite !== null) { |
||
888 | break; |
||
889 | } |
||
890 | } |
||
891 | } |
||
892 | |||
893 | // cipher suite not supported |
||
894 | if(c.session.cipherSuite === null) { |
||
895 | return c.error(c, { |
||
896 | message: 'No cipher suites in common.', |
||
897 | send: true, |
||
898 | alert: { |
||
899 | level: tls.Alert.Level.fatal, |
||
900 | description: tls.Alert.Description.handshake_failure |
||
901 | }, |
||
902 | cipherSuite: forge.util.bytesToHex(msg.cipher_suite) |
||
903 | }); |
||
904 | } |
||
905 | |||
906 | // TODO: handle compression methods |
||
907 | if(client) { |
||
908 | c.session.compressionMethod = msg.compression_method; |
||
909 | } else { |
||
910 | // no compression |
||
911 | c.session.compressionMethod = tls.CompressionMethod.none; |
||
912 | } |
||
913 | } |
||
914 | |||
915 | return msg; |
||
916 | }; |
||
917 | |||
918 | /** |
||
919 | * Creates security parameters for the given connection based on the given |
||
920 | * hello message. |
||
921 | * |
||
922 | * @param c the TLS connection. |
||
923 | * @param msg the hello message. |
||
924 | */ |
||
925 | tls.createSecurityParameters = function(c, msg) { |
||
926 | /* Note: security params are from TLS 1.2, some values like prf_algorithm |
||
927 | are ignored for TLS 1.0/1.1 and the builtin as specified in the spec is |
||
928 | used. */ |
||
929 | |||
930 | // TODO: handle other options from server when more supported |
||
931 | |||
932 | // get client and server randoms |
||
933 | var client = (c.entity === tls.ConnectionEnd.client); |
||
934 | var msgRandom = msg.random.bytes(); |
||
935 | var cRandom = client ? c.session.sp.client_random : msgRandom; |
||
936 | var sRandom = client ? msgRandom : tls.createRandom().getBytes(); |
||
937 | |||
938 | // create new security parameters |
||
939 | c.session.sp = { |
||
940 | entity: c.entity, |
||
941 | prf_algorithm: tls.PRFAlgorithm.tls_prf_sha256, |
||
942 | bulk_cipher_algorithm: null, |
||
943 | cipher_type: null, |
||
944 | enc_key_length: null, |
||
945 | block_length: null, |
||
946 | fixed_iv_length: null, |
||
947 | record_iv_length: null, |
||
948 | mac_algorithm: null, |
||
949 | mac_length: null, |
||
950 | mac_key_length: null, |
||
951 | compression_algorithm: c.session.compressionMethod, |
||
952 | pre_master_secret: null, |
||
953 | master_secret: null, |
||
954 | client_random: cRandom, |
||
955 | server_random: sRandom |
||
956 | }; |
||
957 | }; |
||
958 | |||
959 | /** |
||
960 | * Called when a client receives a ServerHello record. |
||
961 | * |
||
962 | * When a ServerHello message will be sent: |
||
963 | * The server will send this message in response to a client hello message |
||
964 | * when it was able to find an acceptable set of algorithms. If it cannot |
||
965 | * find such a match, it will respond with a handshake failure alert. |
||
966 | * |
||
967 | * uint24 length; |
||
968 | * struct { |
||
969 | * ProtocolVersion server_version; |
||
970 | * Random random; |
||
971 | * SessionID session_id; |
||
972 | * CipherSuite cipher_suite; |
||
973 | * CompressionMethod compression_method; |
||
974 | * select(extensions_present) { |
||
975 | * case false: |
||
976 | * struct {}; |
||
977 | * case true: |
||
978 | * Extension extensions<0..2^16-1>; |
||
979 | * }; |
||
980 | * } ServerHello; |
||
981 | * |
||
982 | * @param c the connection. |
||
983 | * @param record the record. |
||
984 | * @param length the length of the handshake message. |
||
985 | */ |
||
986 | tls.handleServerHello = function(c, record, length) { |
||
987 | var msg = tls.parseHelloMessage(c, record, length); |
||
988 | if(c.fail) { |
||
989 | return; |
||
990 | } |
||
991 | |||
992 | // ensure server version is compatible |
||
993 | if(msg.version.minor <= c.version.minor) { |
||
994 | c.version.minor = msg.version.minor; |
||
995 | } else { |
||
996 | return c.error(c, { |
||
997 | message: 'Incompatible TLS version.', |
||
998 | send: true, |
||
999 | alert: { |
||
1000 | level: tls.Alert.Level.fatal, |
||
1001 | description: tls.Alert.Description.protocol_version |
||
1002 | } |
||
1003 | }); |
||
1004 | } |
||
1005 | |||
1006 | // indicate session version has been set |
||
1007 | c.session.version = c.version; |
||
1008 | |||
1009 | // get the session ID from the message |
||
1010 | var sessionId = msg.session_id.bytes(); |
||
1011 | |||
1012 | // if the session ID is not blank and matches the cached one, resume |
||
1013 | // the session |
||
1014 | if(sessionId.length > 0 && sessionId === c.session.id) { |
||
1015 | // resuming session, expect a ChangeCipherSpec next |
||
1016 | c.expect = SCC; |
||
1017 | c.session.resuming = true; |
||
1018 | |||
1019 | // get new server random |
||
1020 | c.session.sp.server_random = msg.random.bytes(); |
||
1021 | } else { |
||
1022 | // not resuming, expect a server Certificate message next |
||
1023 | c.expect = SCE; |
||
1024 | c.session.resuming = false; |
||
1025 | |||
1026 | // create new security parameters |
||
1027 | tls.createSecurityParameters(c, msg); |
||
1028 | } |
||
1029 | |||
1030 | // set new session ID |
||
1031 | c.session.id = sessionId; |
||
1032 | |||
1033 | // continue |
||
1034 | c.process(); |
||
1035 | }; |
||
1036 | |||
1037 | /** |
||
1038 | * Called when a server receives a ClientHello record. |
||
1039 | * |
||
1040 | * When a ClientHello message will be sent: |
||
1041 | * When a client first connects to a server it is required to send the |
||
1042 | * client hello as its first message. The client can also send a client |
||
1043 | * hello in response to a hello request or on its own initiative in order |
||
1044 | * to renegotiate the security parameters in an existing connection. |
||
1045 | * |
||
1046 | * @param c the connection. |
||
1047 | * @param record the record. |
||
1048 | * @param length the length of the handshake message. |
||
1049 | */ |
||
1050 | tls.handleClientHello = function(c, record, length) { |
||
1051 | var msg = tls.parseHelloMessage(c, record, length); |
||
1052 | if(c.fail) { |
||
1053 | return; |
||
1054 | } |
||
1055 | |||
1056 | // get the session ID from the message |
||
1057 | var sessionId = msg.session_id.bytes(); |
||
1058 | |||
1059 | // see if the given session ID is in the cache |
||
1060 | var session = null; |
||
1061 | if(c.sessionCache) { |
||
1062 | session = c.sessionCache.getSession(sessionId); |
||
1063 | if(session === null) { |
||
1064 | // session ID not found |
||
1065 | sessionId = ''; |
||
1066 | } else if(session.version.major !== msg.version.major || |
||
1067 | session.version.minor > msg.version.minor) { |
||
1068 | // if session version is incompatible with client version, do not resume |
||
1069 | session = null; |
||
1070 | sessionId = ''; |
||
1071 | } |
||
1072 | } |
||
1073 | |||
1074 | // no session found to resume, generate a new session ID |
||
1075 | if(sessionId.length === 0) { |
||
1076 | sessionId = forge.random.getBytes(32); |
||
1077 | } |
||
1078 | |||
1079 | // update session |
||
1080 | c.session.id = sessionId; |
||
1081 | c.session.clientHelloVersion = msg.version; |
||
1082 | c.session.sp = {}; |
||
1083 | if(session) { |
||
1084 | // use version and security parameters from resumed session |
||
1085 | c.version = c.session.version = session.version; |
||
1086 | c.session.sp = session.sp; |
||
1087 | } else { |
||
1088 | // use highest compatible minor version |
||
1089 | var version; |
||
1090 | for(var i = 1; i < tls.SupportedVersions.length; ++i) { |
||
1091 | version = tls.SupportedVersions[i]; |
||
1092 | if(version.minor <= msg.version.minor) { |
||
1093 | break; |
||
1094 | } |
||
1095 | } |
||
1096 | c.version = {major: version.major, minor: version.minor}; |
||
1097 | c.session.version = c.version; |
||
1098 | } |
||
1099 | |||
1100 | // if a session is set, resume it |
||
1101 | if(session !== null) { |
||
1102 | // resuming session, expect a ChangeCipherSpec next |
||
1103 | c.expect = CCC; |
||
1104 | c.session.resuming = true; |
||
1105 | |||
1106 | // get new client random |
||
1107 | c.session.sp.client_random = msg.random.bytes(); |
||
1108 | } else { |
||
1109 | // not resuming, expect a Certificate or ClientKeyExchange |
||
1110 | c.expect = (c.verifyClient !== false) ? CCE : CKE; |
||
1111 | c.session.resuming = false; |
||
1112 | |||
1113 | // create new security parameters |
||
1114 | tls.createSecurityParameters(c, msg); |
||
1115 | } |
||
1116 | |||
1117 | // connection now open |
||
1118 | c.open = true; |
||
1119 | |||
1120 | // queue server hello |
||
1121 | tls.queue(c, tls.createRecord(c, { |
||
1122 | type: tls.ContentType.handshake, |
||
1123 | data: tls.createServerHello(c) |
||
1124 | })); |
||
1125 | |||
1126 | if(c.session.resuming) { |
||
1127 | // queue change cipher spec message |
||
1128 | tls.queue(c, tls.createRecord(c, { |
||
1129 | type: tls.ContentType.change_cipher_spec, |
||
1130 | data: tls.createChangeCipherSpec() |
||
1131 | })); |
||
1132 | |||
1133 | // create pending state |
||
1134 | c.state.pending = tls.createConnectionState(c); |
||
1135 | |||
1136 | // change current write state to pending write state |
||
1137 | c.state.current.write = c.state.pending.write; |
||
1138 | |||
1139 | // queue finished |
||
1140 | tls.queue(c, tls.createRecord(c, { |
||
1141 | type: tls.ContentType.handshake, |
||
1142 | data: tls.createFinished(c) |
||
1143 | })); |
||
1144 | } else { |
||
1145 | // queue server certificate |
||
1146 | tls.queue(c, tls.createRecord(c, { |
||
1147 | type: tls.ContentType.handshake, |
||
1148 | data: tls.createCertificate(c) |
||
1149 | })); |
||
1150 | |||
1151 | if(!c.fail) { |
||
1152 | // queue server key exchange |
||
1153 | tls.queue(c, tls.createRecord(c, { |
||
1154 | type: tls.ContentType.handshake, |
||
1155 | data: tls.createServerKeyExchange(c) |
||
1156 | })); |
||
1157 | |||
1158 | // request client certificate if set |
||
1159 | if(c.verifyClient !== false) { |
||
1160 | // queue certificate request |
||
1161 | tls.queue(c, tls.createRecord(c, { |
||
1162 | type: tls.ContentType.handshake, |
||
1163 | data: tls.createCertificateRequest(c) |
||
1164 | })); |
||
1165 | } |
||
1166 | |||
1167 | // queue server hello done |
||
1168 | tls.queue(c, tls.createRecord(c, { |
||
1169 | type: tls.ContentType.handshake, |
||
1170 | data: tls.createServerHelloDone(c) |
||
1171 | })); |
||
1172 | } |
||
1173 | } |
||
1174 | |||
1175 | // send records |
||
1176 | tls.flush(c); |
||
1177 | |||
1178 | // continue |
||
1179 | c.process(); |
||
1180 | }; |
||
1181 | |||
1182 | /** |
||
1183 | * Called when a client receives a Certificate record. |
||
1184 | * |
||
1185 | * When this message will be sent: |
||
1186 | * The server must send a certificate whenever the agreed-upon key exchange |
||
1187 | * method is not an anonymous one. This message will always immediately |
||
1188 | * follow the server hello message. |
||
1189 | * |
||
1190 | * Meaning of this message: |
||
1191 | * The certificate type must be appropriate for the selected cipher suite's |
||
1192 | * key exchange algorithm, and is generally an X.509v3 certificate. It must |
||
1193 | * contain a key which matches the key exchange method, as follows. Unless |
||
1194 | * otherwise specified, the signing algorithm for the certificate must be |
||
1195 | * the same as the algorithm for the certificate key. Unless otherwise |
||
1196 | * specified, the public key may be of any length. |
||
1197 | * |
||
1198 | * opaque ASN.1Cert<1..2^24-1>; |
||
1199 | * struct { |
||
1200 | * ASN.1Cert certificate_list<1..2^24-1>; |
||
1201 | * } Certificate; |
||
1202 | * |
||
1203 | * @param c the connection. |
||
1204 | * @param record the record. |
||
1205 | * @param length the length of the handshake message. |
||
1206 | */ |
||
1207 | tls.handleCertificate = function(c, record, length) { |
||
1208 | // minimum of 3 bytes in message |
||
1209 | if(length < 3) { |
||
1210 | return c.error(c, { |
||
1211 | message: 'Invalid Certificate message. Message too short.', |
||
1212 | send: true, |
||
1213 | alert: { |
||
1214 | level: tls.Alert.Level.fatal, |
||
1215 | description: tls.Alert.Description.illegal_parameter |
||
1216 | } |
||
1217 | }); |
||
1218 | } |
||
1219 | |||
1220 | var b = record.fragment; |
||
1221 | var msg = { |
||
1222 | certificate_list: readVector(b, 3) |
||
1223 | }; |
||
1224 | |||
1225 | /* The sender's certificate will be first in the list (chain), each |
||
1226 | subsequent one that follows will certify the previous one, but root |
||
1227 | certificates (self-signed) that specify the certificate authority may |
||
1228 | be omitted under the assumption that clients must already possess it. */ |
||
1229 | var cert, asn1; |
||
1230 | var certs = []; |
||
1231 | try { |
||
1232 | while(msg.certificate_list.length() > 0) { |
||
1233 | // each entry in msg.certificate_list is a vector with 3 len bytes |
||
1234 | cert = readVector(msg.certificate_list, 3); |
||
1235 | asn1 = forge.asn1.fromDer(cert); |
||
1236 | cert = forge.pki.certificateFromAsn1(asn1, true); |
||
1237 | certs.push(cert); |
||
1238 | } |
||
1239 | } catch(ex) { |
||
1240 | return c.error(c, { |
||
1241 | message: 'Could not parse certificate list.', |
||
1242 | cause: ex, |
||
1243 | send: true, |
||
1244 | alert: { |
||
1245 | level: tls.Alert.Level.fatal, |
||
1246 | description: tls.Alert.Description.bad_certificate |
||
1247 | } |
||
1248 | }); |
||
1249 | } |
||
1250 | |||
1251 | // ensure at least 1 certificate was provided if in client-mode |
||
1252 | // or if verifyClient was set to true to require a certificate |
||
1253 | // (as opposed to 'optional') |
||
1254 | var client = (c.entity === tls.ConnectionEnd.client); |
||
1255 | if((client || c.verifyClient === true) && certs.length === 0) { |
||
1256 | // error, no certificate |
||
1257 | c.error(c, { |
||
1258 | message: client ? |
||
1259 | 'No server certificate provided.' : |
||
1260 | 'No client certificate provided.', |
||
1261 | send: true, |
||
1262 | alert: { |
||
1263 | level: tls.Alert.Level.fatal, |
||
1264 | description: tls.Alert.Description.illegal_parameter |
||
1265 | } |
||
1266 | }); |
||
1267 | } else if(certs.length === 0) { |
||
1268 | // no certs to verify |
||
1269 | // expect a ServerKeyExchange or ClientKeyExchange message next |
||
1270 | c.expect = client ? SKE : CKE; |
||
1271 | } else { |
||
1272 | // save certificate in session |
||
1273 | if(client) { |
||
1274 | c.session.serverCertificate = certs[0]; |
||
1275 | } else { |
||
1276 | c.session.clientCertificate = certs[0]; |
||
1277 | } |
||
1278 | |||
1279 | if(tls.verifyCertificateChain(c, certs)) { |
||
1280 | // expect a ServerKeyExchange or ClientKeyExchange message next |
||
1281 | c.expect = client ? SKE : CKE; |
||
1282 | } |
||
1283 | } |
||
1284 | |||
1285 | // continue |
||
1286 | c.process(); |
||
1287 | }; |
||
1288 | |||
1289 | /** |
||
1290 | * Called when a client receives a ServerKeyExchange record. |
||
1291 | * |
||
1292 | * When this message will be sent: |
||
1293 | * This message will be sent immediately after the server certificate |
||
1294 | * message (or the server hello message, if this is an anonymous |
||
1295 | * negotiation). |
||
1296 | * |
||
1297 | * The server key exchange message is sent by the server only when the |
||
1298 | * server certificate message (if sent) does not contain enough data to |
||
1299 | * allow the client to exchange a premaster secret. |
||
1300 | * |
||
1301 | * Meaning of this message: |
||
1302 | * This message conveys cryptographic information to allow the client to |
||
1303 | * communicate the premaster secret: either an RSA public key to encrypt |
||
1304 | * the premaster secret with, or a Diffie-Hellman public key with which the |
||
1305 | * client can complete a key exchange (with the result being the premaster |
||
1306 | * secret.) |
||
1307 | * |
||
1308 | * enum { |
||
1309 | * dhe_dss, dhe_rsa, dh_anon, rsa, dh_dss, dh_rsa |
||
1310 | * } KeyExchangeAlgorithm; |
||
1311 | * |
||
1312 | * struct { |
||
1313 | * opaque dh_p<1..2^16-1>; |
||
1314 | * opaque dh_g<1..2^16-1>; |
||
1315 | * opaque dh_Ys<1..2^16-1>; |
||
1316 | * } ServerDHParams; |
||
1317 | * |
||
1318 | * struct { |
||
1319 | * select(KeyExchangeAlgorithm) { |
||
1320 | * case dh_anon: |
||
1321 | * ServerDHParams params; |
||
1322 | * case dhe_dss: |
||
1323 | * case dhe_rsa: |
||
1324 | * ServerDHParams params; |
||
1325 | * digitally-signed struct { |
||
1326 | * opaque client_random[32]; |
||
1327 | * opaque server_random[32]; |
||
1328 | * ServerDHParams params; |
||
1329 | * } signed_params; |
||
1330 | * case rsa: |
||
1331 | * case dh_dss: |
||
1332 | * case dh_rsa: |
||
1333 | * struct {}; |
||
1334 | * }; |
||
1335 | * } ServerKeyExchange; |
||
1336 | * |
||
1337 | * @param c the connection. |
||
1338 | * @param record the record. |
||
1339 | * @param length the length of the handshake message. |
||
1340 | */ |
||
1341 | tls.handleServerKeyExchange = function(c, record, length) { |
||
1342 | // this implementation only supports RSA, no Diffie-Hellman support |
||
1343 | // so any length > 0 is invalid |
||
1344 | if(length > 0) { |
||
1345 | return c.error(c, { |
||
1346 | message: 'Invalid key parameters. Only RSA is supported.', |
||
1347 | send: true, |
||
1348 | alert: { |
||
1349 | level: tls.Alert.Level.fatal, |
||
1350 | description: tls.Alert.Description.unsupported_certificate |
||
1351 | } |
||
1352 | }); |
||
1353 | } |
||
1354 | |||
1355 | // expect an optional CertificateRequest message next |
||
1356 | c.expect = SCR; |
||
1357 | |||
1358 | // continue |
||
1359 | c.process(); |
||
1360 | }; |
||
1361 | |||
1362 | /** |
||
1363 | * Called when a client receives a ClientKeyExchange record. |
||
1364 | * |
||
1365 | * @param c the connection. |
||
1366 | * @param record the record. |
||
1367 | * @param length the length of the handshake message. |
||
1368 | */ |
||
1369 | tls.handleClientKeyExchange = function(c, record, length) { |
||
1370 | // this implementation only supports RSA, no Diffie-Hellman support |
||
1371 | // so any length < 48 is invalid |
||
1372 | if(length < 48) { |
||
1373 | return c.error(c, { |
||
1374 | message: 'Invalid key parameters. Only RSA is supported.', |
||
1375 | send: true, |
||
1376 | alert: { |
||
1377 | level: tls.Alert.Level.fatal, |
||
1378 | description: tls.Alert.Description.unsupported_certificate |
||
1379 | } |
||
1380 | }); |
||
1381 | } |
||
1382 | |||
1383 | var b = record.fragment; |
||
1384 | var msg = { |
||
1385 | enc_pre_master_secret: readVector(b, 2).getBytes() |
||
1386 | }; |
||
1387 | |||
1388 | // do rsa decryption |
||
1389 | var privateKey = null; |
||
1390 | if(c.getPrivateKey) { |
||
1391 | try { |
||
1392 | privateKey = c.getPrivateKey(c, c.session.serverCertificate); |
||
1393 | privateKey = forge.pki.privateKeyFromPem(privateKey); |
||
1394 | } catch(ex) { |
||
1395 | c.error(c, { |
||
1396 | message: 'Could not get private key.', |
||
1397 | cause: ex, |
||
1398 | send: true, |
||
1399 | alert: { |
||
1400 | level: tls.Alert.Level.fatal, |
||
1401 | description: tls.Alert.Description.internal_error |
||
1402 | } |
||
1403 | }); |
||
1404 | } |
||
1405 | } |
||
1406 | |||
1407 | if(privateKey === null) { |
||
1408 | return c.error(c, { |
||
1409 | message: 'No private key set.', |
||
1410 | send: true, |
||
1411 | alert: { |
||
1412 | level: tls.Alert.Level.fatal, |
||
1413 | description: tls.Alert.Description.internal_error |
||
1414 | } |
||
1415 | }); |
||
1416 | } |
||
1417 | |||
1418 | try { |
||
1419 | // decrypt 48-byte pre-master secret |
||
1420 | var sp = c.session.sp; |
||
1421 | sp.pre_master_secret = privateKey.decrypt(msg.enc_pre_master_secret); |
||
1422 | |||
1423 | // ensure client hello version matches first 2 bytes |
||
1424 | var version = c.session.clientHelloVersion; |
||
1425 | if(version.major !== sp.pre_master_secret.charCodeAt(0) || |
||
1426 | version.minor !== sp.pre_master_secret.charCodeAt(1)) { |
||
1427 | // error, do not send alert (see BLEI attack below) |
||
1428 | throw new Error('TLS version rollback attack detected.'); |
||
1429 | } |
||
1430 | } catch(ex) { |
||
1431 | /* Note: Daniel Bleichenbacher [BLEI] can be used to attack a |
||
1432 | TLS server which is using PKCS#1 encoded RSA, so instead of |
||
1433 | failing here, we generate 48 random bytes and use that as |
||
1434 | the pre-master secret. */ |
||
1435 | sp.pre_master_secret = forge.random.getBytes(48); |
||
1436 | } |
||
1437 | |||
1438 | // expect a CertificateVerify message if a Certificate was received that |
||
1439 | // does not have fixed Diffie-Hellman params, otherwise expect |
||
1440 | // ChangeCipherSpec |
||
1441 | c.expect = CCC; |
||
1442 | if(c.session.clientCertificate !== null) { |
||
1443 | // only RSA support, so expect CertificateVerify |
||
1444 | // TODO: support Diffie-Hellman |
||
1445 | c.expect = CCV; |
||
1446 | } |
||
1447 | |||
1448 | // continue |
||
1449 | c.process(); |
||
1450 | }; |
||
1451 | |||
1452 | /** |
||
1453 | * Called when a client receives a CertificateRequest record. |
||
1454 | * |
||
1455 | * When this message will be sent: |
||
1456 | * A non-anonymous server can optionally request a certificate from the |
||
1457 | * client, if appropriate for the selected cipher suite. This message, if |
||
1458 | * sent, will immediately follow the Server Key Exchange message (if it is |
||
1459 | * sent; otherwise, the Server Certificate message). |
||
1460 | * |
||
1461 | * enum { |
||
1462 | * rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4), |
||
1463 | * rsa_ephemeral_dh_RESERVED(5), dss_ephemeral_dh_RESERVED(6), |
||
1464 | * fortezza_dms_RESERVED(20), (255) |
||
1465 | * } ClientCertificateType; |
||
1466 | * |
||
1467 | * opaque DistinguishedName<1..2^16-1>; |
||
1468 | * |
||
1469 | * struct { |
||
1470 | * ClientCertificateType certificate_types<1..2^8-1>; |
||
1471 | * SignatureAndHashAlgorithm supported_signature_algorithms<2^16-1>; |
||
1472 | * DistinguishedName certificate_authorities<0..2^16-1>; |
||
1473 | * } CertificateRequest; |
||
1474 | * |
||
1475 | * @param c the connection. |
||
1476 | * @param record the record. |
||
1477 | * @param length the length of the handshake message. |
||
1478 | */ |
||
1479 | tls.handleCertificateRequest = function(c, record, length) { |
||
1480 | // minimum of 3 bytes in message |
||
1481 | if(length < 3) { |
||
1482 | return c.error(c, { |
||
1483 | message: 'Invalid CertificateRequest. Message too short.', |
||
1484 | send: true, |
||
1485 | alert: { |
||
1486 | level: tls.Alert.Level.fatal, |
||
1487 | description: tls.Alert.Description.illegal_parameter |
||
1488 | } |
||
1489 | }); |
||
1490 | } |
||
1491 | |||
1492 | // TODO: TLS 1.2+ has different format including |
||
1493 | // SignatureAndHashAlgorithm after cert types |
||
1494 | var b = record.fragment; |
||
1495 | var msg = { |
||
1496 | certificate_types: readVector(b, 1), |
||
1497 | certificate_authorities: readVector(b, 2) |
||
1498 | }; |
||
1499 | |||
1500 | // save certificate request in session |
||
1501 | c.session.certificateRequest = msg; |
||
1502 | |||
1503 | // expect a ServerHelloDone message next |
||
1504 | c.expect = SHD; |
||
1505 | |||
1506 | // continue |
||
1507 | c.process(); |
||
1508 | }; |
||
1509 | |||
1510 | /** |
||
1511 | * Called when a server receives a CertificateVerify record. |
||
1512 | * |
||
1513 | * @param c the connection. |
||
1514 | * @param record the record. |
||
1515 | * @param length the length of the handshake message. |
||
1516 | */ |
||
1517 | tls.handleCertificateVerify = function(c, record, length) { |
||
1518 | if(length < 2) { |
||
1519 | return c.error(c, { |
||
1520 | message: 'Invalid CertificateVerify. Message too short.', |
||
1521 | send: true, |
||
1522 | alert: { |
||
1523 | level: tls.Alert.Level.fatal, |
||
1524 | description: tls.Alert.Description.illegal_parameter |
||
1525 | } |
||
1526 | }); |
||
1527 | } |
||
1528 | |||
1529 | // rewind to get full bytes for message so it can be manually |
||
1530 | // digested below (special case for CertificateVerify messages because |
||
1531 | // they must be digested *after* handling as opposed to all others) |
||
1532 | var b = record.fragment; |
||
1533 | b.read -= 4; |
||
1534 | var msgBytes = b.bytes(); |
||
1535 | b.read += 4; |
||
1536 | |||
1537 | var msg = { |
||
1538 | signature: readVector(b, 2).getBytes() |
||
1539 | }; |
||
1540 | |||
1541 | // TODO: add support for DSA |
||
1542 | |||
1543 | // generate data to verify |
||
1544 | var verify = forge.util.createBuffer(); |
||
1545 | verify.putBuffer(c.session.md5.digest()); |
||
1546 | verify.putBuffer(c.session.sha1.digest()); |
||
1547 | verify = verify.getBytes(); |
||
1548 | |||
1549 | try { |
||
1550 | var cert = c.session.clientCertificate; |
||
1551 | /*b = forge.pki.rsa.decrypt( |
||
1552 | msg.signature, cert.publicKey, true, verify.length); |
||
1553 | if(b !== verify) {*/ |
||
1554 | if(!cert.publicKey.verify(verify, msg.signature, 'NONE')) { |
||
1555 | throw new Error('CertificateVerify signature does not match.'); |
||
1556 | } |
||
1557 | |||
1558 | // digest message now that it has been handled |
||
1559 | c.session.md5.update(msgBytes); |
||
1560 | c.session.sha1.update(msgBytes); |
||
1561 | } catch(ex) { |
||
1562 | return c.error(c, { |
||
1563 | message: 'Bad signature in CertificateVerify.', |
||
1564 | send: true, |
||
1565 | alert: { |
||
1566 | level: tls.Alert.Level.fatal, |
||
1567 | description: tls.Alert.Description.handshake_failure |
||
1568 | } |
||
1569 | }); |
||
1570 | } |
||
1571 | |||
1572 | // expect ChangeCipherSpec |
||
1573 | c.expect = CCC; |
||
1574 | |||
1575 | // continue |
||
1576 | c.process(); |
||
1577 | }; |
||
1578 | |||
1579 | /** |
||
1580 | * Called when a client receives a ServerHelloDone record. |
||
1581 | * |
||
1582 | * When this message will be sent: |
||
1583 | * The server hello done message is sent by the server to indicate the end |
||
1584 | * of the server hello and associated messages. After sending this message |
||
1585 | * the server will wait for a client response. |
||
1586 | * |
||
1587 | * Meaning of this message: |
||
1588 | * This message means that the server is done sending messages to support |
||
1589 | * the key exchange, and the client can proceed with its phase of the key |
||
1590 | * exchange. |
||
1591 | * |
||
1592 | * Upon receipt of the server hello done message the client should verify |
||
1593 | * that the server provided a valid certificate if required and check that |
||
1594 | * the server hello parameters are acceptable. |
||
1595 | * |
||
1596 | * struct {} ServerHelloDone; |
||
1597 | * |
||
1598 | * @param c the connection. |
||
1599 | * @param record the record. |
||
1600 | * @param length the length of the handshake message. |
||
1601 | */ |
||
1602 | tls.handleServerHelloDone = function(c, record, length) { |
||
1603 | // len must be 0 bytes |
||
1604 | if(length > 0) { |
||
1605 | return c.error(c, { |
||
1606 | message: 'Invalid ServerHelloDone message. Invalid length.', |
||
1607 | send: true, |
||
1608 | alert: { |
||
1609 | level: tls.Alert.Level.fatal, |
||
1610 | description: tls.Alert.Description.record_overflow |
||
1611 | } |
||
1612 | }); |
||
1613 | } |
||
1614 | |||
1615 | if(c.serverCertificate === null) { |
||
1616 | // no server certificate was provided |
||
1617 | var error = { |
||
1618 | message: 'No server certificate provided. Not enough security.', |
||
1619 | send: true, |
||
1620 | alert: { |
||
1621 | level: tls.Alert.Level.fatal, |
||
1622 | description: tls.Alert.Description.insufficient_security |
||
1623 | } |
||
1624 | }; |
||
1625 | |||
1626 | // call application callback |
||
1627 | var depth = 0; |
||
1628 | var ret = c.verify(c, error.alert.description, depth, []); |
||
1629 | if(ret !== true) { |
||
1630 | // check for custom alert info |
||
1631 | if(ret || ret === 0) { |
||
1632 | // set custom message and alert description |
||
1633 | if(typeof ret === 'object' && !forge.util.isArray(ret)) { |
||
1634 | if(ret.message) { |
||
1635 | error.message = ret.message; |
||
1636 | } |
||
1637 | if(ret.alert) { |
||
1638 | error.alert.description = ret.alert; |
||
1639 | } |
||
1640 | } else if(typeof ret === 'number') { |
||
1641 | // set custom alert description |
||
1642 | error.alert.description = ret; |
||
1643 | } |
||
1644 | } |
||
1645 | |||
1646 | // send error |
||
1647 | return c.error(c, error); |
||
1648 | } |
||
1649 | } |
||
1650 | |||
1651 | // create client certificate message if requested |
||
1652 | if(c.session.certificateRequest !== null) { |
||
1653 | record = tls.createRecord(c, { |
||
1654 | type: tls.ContentType.handshake, |
||
1655 | data: tls.createCertificate(c) |
||
1656 | }); |
||
1657 | tls.queue(c, record); |
||
1658 | } |
||
1659 | |||
1660 | // create client key exchange message |
||
1661 | record = tls.createRecord(c, { |
||
1662 | type: tls.ContentType.handshake, |
||
1663 | data: tls.createClientKeyExchange(c) |
||
1664 | }); |
||
1665 | tls.queue(c, record); |
||
1666 | |||
1667 | // expect no messages until the following callback has been called |
||
1668 | c.expect = SER; |
||
1669 | |||
1670 | // create callback to handle client signature (for client-certs) |
||
1671 | var callback = function(c, signature) { |
||
1672 | if(c.session.certificateRequest !== null && |
||
1673 | c.session.clientCertificate !== null) { |
||
1674 | // create certificate verify message |
||
1675 | tls.queue(c, tls.createRecord(c, { |
||
1676 | type: tls.ContentType.handshake, |
||
1677 | data: tls.createCertificateVerify(c, signature) |
||
1678 | })); |
||
1679 | } |
||
1680 | |||
1681 | // create change cipher spec message |
||
1682 | tls.queue(c, tls.createRecord(c, { |
||
1683 | type: tls.ContentType.change_cipher_spec, |
||
1684 | data: tls.createChangeCipherSpec() |
||
1685 | })); |
||
1686 | |||
1687 | // create pending state |
||
1688 | c.state.pending = tls.createConnectionState(c); |
||
1689 | |||
1690 | // change current write state to pending write state |
||
1691 | c.state.current.write = c.state.pending.write; |
||
1692 | |||
1693 | // create finished message |
||
1694 | tls.queue(c, tls.createRecord(c, { |
||
1695 | type: tls.ContentType.handshake, |
||
1696 | data: tls.createFinished(c) |
||
1697 | })); |
||
1698 | |||
1699 | // expect a server ChangeCipherSpec message next |
||
1700 | c.expect = SCC; |
||
1701 | |||
1702 | // send records |
||
1703 | tls.flush(c); |
||
1704 | |||
1705 | // continue |
||
1706 | c.process(); |
||
1707 | }; |
||
1708 | |||
1709 | // if there is no certificate request or no client certificate, do |
||
1710 | // callback immediately |
||
1711 | if(c.session.certificateRequest === null || |
||
1712 | c.session.clientCertificate === null) { |
||
1713 | return callback(c, null); |
||
1714 | } |
||
1715 | |||
1716 | // otherwise get the client signature |
||
1717 | tls.getClientSignature(c, callback); |
||
1718 | }; |
||
1719 | |||
1720 | /** |
||
1721 | * Called when a ChangeCipherSpec record is received. |
||
1722 | * |
||
1723 | * @param c the connection. |
||
1724 | * @param record the record. |
||
1725 | */ |
||
1726 | tls.handleChangeCipherSpec = function(c, record) { |
||
1727 | if(record.fragment.getByte() !== 0x01) { |
||
1728 | return c.error(c, { |
||
1729 | message: 'Invalid ChangeCipherSpec message received.', |
||
1730 | send: true, |
||
1731 | alert: { |
||
1732 | level: tls.Alert.Level.fatal, |
||
1733 | description: tls.Alert.Description.illegal_parameter |
||
1734 | } |
||
1735 | }); |
||
1736 | } |
||
1737 | |||
1738 | // create pending state if: |
||
1739 | // 1. Resuming session in client mode OR |
||
1740 | // 2. NOT resuming session in server mode |
||
1741 | var client = (c.entity === tls.ConnectionEnd.client); |
||
1742 | if((c.session.resuming && client) || (!c.session.resuming && !client)) { |
||
1743 | c.state.pending = tls.createConnectionState(c); |
||
1744 | } |
||
1745 | |||
1746 | // change current read state to pending read state |
||
1747 | c.state.current.read = c.state.pending.read; |
||
1748 | |||
1749 | // clear pending state if: |
||
1750 | // 1. NOT resuming session in client mode OR |
||
1751 | // 2. resuming a session in server mode |
||
1752 | if((!c.session.resuming && client) || (c.session.resuming && !client)) { |
||
1753 | c.state.pending = null; |
||
1754 | } |
||
1755 | |||
1756 | // expect a Finished record next |
||
1757 | c.expect = client ? SFI : CFI; |
||
1758 | |||
1759 | // continue |
||
1760 | c.process(); |
||
1761 | }; |
||
1762 | |||
1763 | /** |
||
1764 | * Called when a Finished record is received. |
||
1765 | * |
||
1766 | * When this message will be sent: |
||
1767 | * A finished message is always sent immediately after a change |
||
1768 | * cipher spec message to verify that the key exchange and |
||
1769 | * authentication processes were successful. It is essential that a |
||
1770 | * change cipher spec message be received between the other |
||
1771 | * handshake messages and the Finished message. |
||
1772 | * |
||
1773 | * Meaning of this message: |
||
1774 | * The finished message is the first protected with the just- |
||
1775 | * negotiated algorithms, keys, and secrets. Recipients of finished |
||
1776 | * messages must verify that the contents are correct. Once a side |
||
1777 | * has sent its Finished message and received and validated the |
||
1778 | * Finished message from its peer, it may begin to send and receive |
||
1779 | * application data over the connection. |
||
1780 | * |
||
1781 | * struct { |
||
1782 | * opaque verify_data[verify_data_length]; |
||
1783 | * } Finished; |
||
1784 | * |
||
1785 | * verify_data |
||
1786 | * PRF(master_secret, finished_label, Hash(handshake_messages)) |
||
1787 | * [0..verify_data_length-1]; |
||
1788 | * |
||
1789 | * finished_label |
||
1790 | * For Finished messages sent by the client, the string |
||
1791 | * "client finished". For Finished messages sent by the server, the |
||
1792 | * string "server finished". |
||
1793 | * |
||
1794 | * verify_data_length depends on the cipher suite. If it is not specified |
||
1795 | * by the cipher suite, then it is 12. Versions of TLS < 1.2 always used |
||
1796 | * 12 bytes. |
||
1797 | * |
||
1798 | * @param c the connection. |
||
1799 | * @param record the record. |
||
1800 | * @param length the length of the handshake message. |
||
1801 | */ |
||
1802 | tls.handleFinished = function(c, record, length) { |
||
1803 | // rewind to get full bytes for message so it can be manually |
||
1804 | // digested below (special case for Finished messages because they |
||
1805 | // must be digested *after* handling as opposed to all others) |
||
1806 | var b = record.fragment; |
||
1807 | b.read -= 4; |
||
1808 | var msgBytes = b.bytes(); |
||
1809 | b.read += 4; |
||
1810 | |||
1811 | // message contains only verify_data |
||
1812 | var vd = record.fragment.getBytes(); |
||
1813 | |||
1814 | // ensure verify data is correct |
||
1815 | b = forge.util.createBuffer(); |
||
1816 | b.putBuffer(c.session.md5.digest()); |
||
1817 | b.putBuffer(c.session.sha1.digest()); |
||
1818 | |||
1819 | // set label based on entity type |
||
1820 | var client = (c.entity === tls.ConnectionEnd.client); |
||
1821 | var label = client ? 'server finished' : 'client finished'; |
||
1822 | |||
1823 | // TODO: determine prf function and verify length for TLS 1.2 |
||
1824 | var sp = c.session.sp; |
||
1825 | var vdl = 12; |
||
1826 | var prf = prf_TLS1; |
||
1827 | b = prf(sp.master_secret, label, b.getBytes(), vdl); |
||
1828 | if(b.getBytes() !== vd) { |
||
1829 | return c.error(c, { |
||
1830 | message: 'Invalid verify_data in Finished message.', |
||
1831 | send: true, |
||
1832 | alert: { |
||
1833 | level: tls.Alert.Level.fatal, |
||
1834 | description: tls.Alert.Description.decrypt_error |
||
1835 | } |
||
1836 | }); |
||
1837 | } |
||
1838 | |||
1839 | // digest finished message now that it has been handled |
||
1840 | c.session.md5.update(msgBytes); |
||
1841 | c.session.sha1.update(msgBytes); |
||
1842 | |||
1843 | // resuming session as client or NOT resuming session as server |
||
1844 | if((c.session.resuming && client) || (!c.session.resuming && !client)) { |
||
1845 | // create change cipher spec message |
||
1846 | tls.queue(c, tls.createRecord(c, { |
||
1847 | type: tls.ContentType.change_cipher_spec, |
||
1848 | data: tls.createChangeCipherSpec() |
||
1849 | })); |
||
1850 | |||
1851 | // change current write state to pending write state, clear pending |
||
1852 | c.state.current.write = c.state.pending.write; |
||
1853 | c.state.pending = null; |
||
1854 | |||
1855 | // create finished message |
||
1856 | tls.queue(c, tls.createRecord(c, { |
||
1857 | type: tls.ContentType.handshake, |
||
1858 | data: tls.createFinished(c) |
||
1859 | })); |
||
1860 | } |
||
1861 | |||
1862 | // expect application data next |
||
1863 | c.expect = client ? SAD : CAD; |
||
1864 | |||
1865 | // handshake complete |
||
1866 | c.handshaking = false; |
||
1867 | ++c.handshakes; |
||
1868 | |||
1869 | // save access to peer certificate |
||
1870 | c.peerCertificate = client ? |
||
1871 | c.session.serverCertificate : c.session.clientCertificate; |
||
1872 | |||
1873 | // send records |
||
1874 | tls.flush(c); |
||
1875 | |||
1876 | // now connected |
||
1877 | c.isConnected = true; |
||
1878 | c.connected(c); |
||
1879 | |||
1880 | // continue |
||
1881 | c.process(); |
||
1882 | }; |
||
1883 | |||
1884 | /** |
||
1885 | * Called when an Alert record is received. |
||
1886 | * |
||
1887 | * @param c the connection. |
||
1888 | * @param record the record. |
||
1889 | */ |
||
1890 | tls.handleAlert = function(c, record) { |
||
1891 | // read alert |
||
1892 | var b = record.fragment; |
||
1893 | var alert = { |
||
1894 | level: b.getByte(), |
||
1895 | description: b.getByte() |
||
1896 | }; |
||
1897 | |||
1898 | // TODO: consider using a table? |
||
1899 | // get appropriate message |
||
1900 | var msg; |
||
1901 | switch(alert.description) { |
||
1902 | case tls.Alert.Description.close_notify: |
||
1903 | msg = 'Connection closed.'; |
||
1904 | break; |
||
1905 | case tls.Alert.Description.unexpected_message: |
||
1906 | msg = 'Unexpected message.'; |
||
1907 | break; |
||
1908 | case tls.Alert.Description.bad_record_mac: |
||
1909 | msg = 'Bad record MAC.'; |
||
1910 | break; |
||
1911 | case tls.Alert.Description.decryption_failed: |
||
1912 | msg = 'Decryption failed.'; |
||
1913 | break; |
||
1914 | case tls.Alert.Description.record_overflow: |
||
1915 | msg = 'Record overflow.'; |
||
1916 | break; |
||
1917 | case tls.Alert.Description.decompression_failure: |
||
1918 | msg = 'Decompression failed.'; |
||
1919 | break; |
||
1920 | case tls.Alert.Description.handshake_failure: |
||
1921 | msg = 'Handshake failure.'; |
||
1922 | break; |
||
1923 | case tls.Alert.Description.bad_certificate: |
||
1924 | msg = 'Bad certificate.'; |
||
1925 | break; |
||
1926 | case tls.Alert.Description.unsupported_certificate: |
||
1927 | msg = 'Unsupported certificate.'; |
||
1928 | break; |
||
1929 | case tls.Alert.Description.certificate_revoked: |
||
1930 | msg = 'Certificate revoked.'; |
||
1931 | break; |
||
1932 | case tls.Alert.Description.certificate_expired: |
||
1933 | msg = 'Certificate expired.'; |
||
1934 | break; |
||
1935 | case tls.Alert.Description.certificate_unknown: |
||
1936 | msg = 'Certificate unknown.'; |
||
1937 | break; |
||
1938 | case tls.Alert.Description.illegal_parameter: |
||
1939 | msg = 'Illegal parameter.'; |
||
1940 | break; |
||
1941 | case tls.Alert.Description.unknown_ca: |
||
1942 | msg = 'Unknown certificate authority.'; |
||
1943 | break; |
||
1944 | case tls.Alert.Description.access_denied: |
||
1945 | msg = 'Access denied.'; |
||
1946 | break; |
||
1947 | case tls.Alert.Description.decode_error: |
||
1948 | msg = 'Decode error.'; |
||
1949 | break; |
||
1950 | case tls.Alert.Description.decrypt_error: |
||
1951 | msg = 'Decrypt error.'; |
||
1952 | break; |
||
1953 | case tls.Alert.Description.export_restriction: |
||
1954 | msg = 'Export restriction.'; |
||
1955 | break; |
||
1956 | case tls.Alert.Description.protocol_version: |
||
1957 | msg = 'Unsupported protocol version.'; |
||
1958 | break; |
||
1959 | case tls.Alert.Description.insufficient_security: |
||
1960 | msg = 'Insufficient security.'; |
||
1961 | break; |
||
1962 | case tls.Alert.Description.internal_error: |
||
1963 | msg = 'Internal error.'; |
||
1964 | break; |
||
1965 | case tls.Alert.Description.user_canceled: |
||
1966 | msg = 'User canceled.'; |
||
1967 | break; |
||
1968 | case tls.Alert.Description.no_renegotiation: |
||
1969 | msg = 'Renegotiation not supported.'; |
||
1970 | break; |
||
1971 | default: |
||
1972 | msg = 'Unknown error.'; |
||
1973 | break; |
||
1974 | } |
||
1975 | |||
1976 | // close connection on close_notify, not an error |
||
1977 | if(alert.description === tls.Alert.Description.close_notify) { |
||
1978 | return c.close(); |
||
1979 | } |
||
1980 | |||
1981 | // call error handler |
||
1982 | c.error(c, { |
||
1983 | message: msg, |
||
1984 | send: false, |
||
1985 | // origin is the opposite end |
||
1986 | origin: (c.entity === tls.ConnectionEnd.client) ? 'server' : 'client', |
||
1987 | alert: alert |
||
1988 | }); |
||
1989 | |||
1990 | // continue |
||
1991 | c.process(); |
||
1992 | }; |
||
1993 | |||
1994 | /** |
||
1995 | * Called when a Handshake record is received. |
||
1996 | * |
||
1997 | * @param c the connection. |
||
1998 | * @param record the record. |
||
1999 | */ |
||
2000 | tls.handleHandshake = function(c, record) { |
||
2001 | // get the handshake type and message length |
||
2002 | var b = record.fragment; |
||
2003 | var type = b.getByte(); |
||
2004 | var length = b.getInt24(); |
||
2005 | |||
2006 | // see if the record fragment doesn't yet contain the full message |
||
2007 | if(length > b.length()) { |
||
2008 | // cache the record, clear its fragment, and reset the buffer read |
||
2009 | // pointer before the type and length were read |
||
2010 | c.fragmented = record; |
||
2011 | record.fragment = forge.util.createBuffer(); |
||
2012 | b.read -= 4; |
||
2013 | |||
2014 | // continue |
||
2015 | return c.process(); |
||
2016 | } |
||
2017 | |||
2018 | // full message now available, clear cache, reset read pointer to |
||
2019 | // before type and length |
||
2020 | c.fragmented = null; |
||
2021 | b.read -= 4; |
||
2022 | |||
2023 | // save the handshake bytes for digestion after handler is found |
||
2024 | // (include type and length of handshake msg) |
||
2025 | var bytes = b.bytes(length + 4); |
||
2026 | |||
2027 | // restore read pointer |
||
2028 | b.read += 4; |
||
2029 | |||
2030 | // handle expected message |
||
2031 | if(type in hsTable[c.entity][c.expect]) { |
||
2032 | // initialize server session |
||
2033 | if(c.entity === tls.ConnectionEnd.server && !c.open && !c.fail) { |
||
2034 | c.handshaking = true; |
||
2035 | c.session = { |
||
2036 | version: null, |
||
2037 | extensions: { |
||
2038 | server_name: { |
||
2039 | serverNameList: [] |
||
2040 | } |
||
2041 | }, |
||
2042 | cipherSuite: null, |
||
2043 | compressionMethod: null, |
||
2044 | serverCertificate: null, |
||
2045 | clientCertificate: null, |
||
2046 | md5: forge.md.md5.create(), |
||
2047 | sha1: forge.md.sha1.create() |
||
2048 | }; |
||
2049 | } |
||
2050 | |||
2051 | /* Update handshake messages digest. Finished and CertificateVerify |
||
2052 | messages are not digested here. They can't be digested as part of |
||
2053 | the verify_data that they contain. These messages are manually |
||
2054 | digested in their handlers. HelloRequest messages are simply never |
||
2055 | included in the handshake message digest according to spec. */ |
||
2056 | if(type !== tls.HandshakeType.hello_request && |
||
2057 | type !== tls.HandshakeType.certificate_verify && |
||
2058 | type !== tls.HandshakeType.finished) { |
||
2059 | c.session.md5.update(bytes); |
||
2060 | c.session.sha1.update(bytes); |
||
2061 | } |
||
2062 | |||
2063 | // handle specific handshake type record |
||
2064 | hsTable[c.entity][c.expect][type](c, record, length); |
||
2065 | } else { |
||
2066 | // unexpected record |
||
2067 | tls.handleUnexpected(c, record); |
||
2068 | } |
||
2069 | }; |
||
2070 | |||
2071 | /** |
||
2072 | * Called when an ApplicationData record is received. |
||
2073 | * |
||
2074 | * @param c the connection. |
||
2075 | * @param record the record. |
||
2076 | */ |
||
2077 | tls.handleApplicationData = function(c, record) { |
||
2078 | // buffer data, notify that its ready |
||
2079 | c.data.putBuffer(record.fragment); |
||
2080 | c.dataReady(c); |
||
2081 | |||
2082 | // continue |
||
2083 | c.process(); |
||
2084 | }; |
||
2085 | |||
2086 | /** |
||
2087 | * Called when a Heartbeat record is received. |
||
2088 | * |
||
2089 | * @param c the connection. |
||
2090 | * @param record the record. |
||
2091 | */ |
||
2092 | tls.handleHeartbeat = function(c, record) { |
||
2093 | // get the heartbeat type and payload |
||
2094 | var b = record.fragment; |
||
2095 | var type = b.getByte(); |
||
2096 | var length = b.getInt16(); |
||
2097 | var payload = b.getBytes(length); |
||
2098 | |||
2099 | if(type === tls.HeartbeatMessageType.heartbeat_request) { |
||
2100 | // discard request during handshake or if length is too large |
||
2101 | if(c.handshaking || length > payload.length) { |
||
2102 | // continue |
||
2103 | return c.process(); |
||
2104 | } |
||
2105 | // retransmit payload |
||
2106 | tls.queue(c, tls.createRecord(c, { |
||
2107 | type: tls.ContentType.heartbeat, |
||
2108 | data: tls.createHeartbeat( |
||
2109 | tls.HeartbeatMessageType.heartbeat_response, payload) |
||
2110 | })); |
||
2111 | tls.flush(c); |
||
2112 | } else if(type === tls.HeartbeatMessageType.heartbeat_response) { |
||
2113 | // check payload against expected payload, discard heartbeat if no match |
||
2114 | if(payload !== c.expectedHeartbeatPayload) { |
||
2115 | // continue |
||
2116 | return c.process(); |
||
2117 | } |
||
2118 | |||
2119 | // notify that a valid heartbeat was received |
||
2120 | if(c.heartbeatReceived) { |
||
2121 | c.heartbeatReceived(c, forge.util.createBuffer(payload)); |
||
2122 | } |
||
2123 | } |
||
2124 | |||
2125 | // continue |
||
2126 | c.process(); |
||
2127 | }; |
||
2128 | |||
2129 | /** |
||
2130 | * The transistional state tables for receiving TLS records. It maps the |
||
2131 | * current TLS engine state and a received record to a function to handle the |
||
2132 | * record and update the state. |
||
2133 | * |
||
2134 | * For instance, if the current state is SHE, then the TLS engine is expecting |
||
2135 | * a ServerHello record. Once a record is received, the handler function is |
||
2136 | * looked up using the state SHE and the record's content type. |
||
2137 | * |
||
2138 | * The resulting function will either be an error handler or a record handler. |
||
2139 | * The function will take whatever action is appropriate and update the state |
||
2140 | * for the next record. |
||
2141 | * |
||
2142 | * The states are all based on possible server record types. Note that the |
||
2143 | * client will never specifically expect to receive a HelloRequest or an alert |
||
2144 | * from the server so there is no state that reflects this. These messages may |
||
2145 | * occur at any time. |
||
2146 | * |
||
2147 | * There are two tables for mapping states because there is a second tier of |
||
2148 | * types for handshake messages. Once a record with a content type of handshake |
||
2149 | * is received, the handshake record handler will look up the handshake type in |
||
2150 | * the secondary map to get its appropriate handler. |
||
2151 | * |
||
2152 | * Valid message orders are as follows: |
||
2153 | * |
||
2154 | * =======================FULL HANDSHAKE====================== |
||
2155 | * Client Server |
||
2156 | * |
||
2157 | * ClientHello --------> |
||
2158 | * ServerHello |
||
2159 | * Certificate* |
||
2160 | * ServerKeyExchange* |
||
2161 | * CertificateRequest* |
||
2162 | * <-------- ServerHelloDone |
||
2163 | * Certificate* |
||
2164 | * ClientKeyExchange |
||
2165 | * CertificateVerify* |
||
2166 | * [ChangeCipherSpec] |
||
2167 | * Finished --------> |
||
2168 | * [ChangeCipherSpec] |
||
2169 | * <-------- Finished |
||
2170 | * Application Data <-------> Application Data |
||
2171 | * |
||
2172 | * =====================SESSION RESUMPTION===================== |
||
2173 | * Client Server |
||
2174 | * |
||
2175 | * ClientHello --------> |
||
2176 | * ServerHello |
||
2177 | * [ChangeCipherSpec] |
||
2178 | * <-------- Finished |
||
2179 | * [ChangeCipherSpec] |
||
2180 | * Finished --------> |
||
2181 | * Application Data <-------> Application Data |
||
2182 | */ |
||
2183 | // client expect states (indicate which records are expected to be received) |
||
2184 | var SHE = 0; // rcv server hello |
||
2185 | var SCE = 1; // rcv server certificate |
||
2186 | var SKE = 2; // rcv server key exchange |
||
2187 | var SCR = 3; // rcv certificate request |
||
2188 | var SHD = 4; // rcv server hello done |
||
2189 | var SCC = 5; // rcv change cipher spec |
||
2190 | var SFI = 6; // rcv finished |
||
2191 | var SAD = 7; // rcv application data |
||
2192 | var SER = 8; // not expecting any messages at this point |
||
2193 | |||
2194 | // server expect states |
||
2195 | var CHE = 0; // rcv client hello |
||
2196 | var CCE = 1; // rcv client certificate |
||
2197 | var CKE = 2; // rcv client key exchange |
||
2198 | var CCV = 3; // rcv certificate verify |
||
2199 | var CCC = 4; // rcv change cipher spec |
||
2200 | var CFI = 5; // rcv finished |
||
2201 | var CAD = 6; // rcv application data |
||
2202 | var CER = 7; // not expecting any messages at this point |
||
2203 | |||
2204 | // map client current expect state and content type to function |
||
2205 | var __ = tls.handleUnexpected; |
||
2206 | var R0 = tls.handleChangeCipherSpec; |
||
2207 | var R1 = tls.handleAlert; |
||
2208 | var R2 = tls.handleHandshake; |
||
2209 | var R3 = tls.handleApplicationData; |
||
2210 | var R4 = tls.handleHeartbeat; |
||
2211 | var ctTable = []; |
||
2212 | ctTable[tls.ConnectionEnd.client] = [ |
||
2213 | // CC,AL,HS,AD,HB |
||
2214 | /*SHE*/[__,R1,R2,__,R4], |
||
2215 | /*SCE*/[__,R1,R2,__,R4], |
||
2216 | /*SKE*/[__,R1,R2,__,R4], |
||
2217 | /*SCR*/[__,R1,R2,__,R4], |
||
2218 | /*SHD*/[__,R1,R2,__,R4], |
||
2219 | /*SCC*/[R0,R1,__,__,R4], |
||
2220 | /*SFI*/[__,R1,R2,__,R4], |
||
2221 | /*SAD*/[__,R1,R2,R3,R4], |
||
2222 | /*SER*/[__,R1,R2,__,R4] |
||
2223 | ]; |
||
2224 | |||
2225 | // map server current expect state and content type to function |
||
2226 | ctTable[tls.ConnectionEnd.server] = [ |
||
2227 | // CC,AL,HS,AD |
||
2228 | /*CHE*/[__,R1,R2,__,R4], |
||
2229 | /*CCE*/[__,R1,R2,__,R4], |
||
2230 | /*CKE*/[__,R1,R2,__,R4], |
||
2231 | /*CCV*/[__,R1,R2,__,R4], |
||
2232 | /*CCC*/[R0,R1,__,__,R4], |
||
2233 | /*CFI*/[__,R1,R2,__,R4], |
||
2234 | /*CAD*/[__,R1,R2,R3,R4], |
||
2235 | /*CER*/[__,R1,R2,__,R4] |
||
2236 | ]; |
||
2237 | |||
2238 | // map client current expect state and handshake type to function |
||
2239 | var H0 = tls.handleHelloRequest; |
||
2240 | var H1 = tls.handleServerHello; |
||
2241 | var H2 = tls.handleCertificate; |
||
2242 | var H3 = tls.handleServerKeyExchange; |
||
2243 | var H4 = tls.handleCertificateRequest; |
||
2244 | var H5 = tls.handleServerHelloDone; |
||
2245 | var H6 = tls.handleFinished; |
||
2246 | var hsTable = []; |
||
2247 | hsTable[tls.ConnectionEnd.client] = [ |
||
2248 | // HR,01,SH,03,04,05,06,07,08,09,10,SC,SK,CR,HD,15,CK,17,18,19,FI |
||
2249 | /*SHE*/[__,__,H1,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__], |
||
2250 | /*SCE*/[H0,__,__,__,__,__,__,__,__,__,__,H2,H3,H4,H5,__,__,__,__,__,__], |
||
2251 | /*SKE*/[H0,__,__,__,__,__,__,__,__,__,__,__,H3,H4,H5,__,__,__,__,__,__], |
||
2252 | /*SCR*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,H4,H5,__,__,__,__,__,__], |
||
2253 | /*SHD*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,H5,__,__,__,__,__,__], |
||
2254 | /*SCC*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__], |
||
2255 | /*SFI*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,H6], |
||
2256 | /*SAD*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__], |
||
2257 | /*SER*/[H0,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__] |
||
2258 | ]; |
||
2259 | |||
2260 | // map server current expect state and handshake type to function |
||
2261 | // Note: CAD[CH] does not map to FB because renegotation is prohibited |
||
2262 | var H7 = tls.handleClientHello; |
||
2263 | var H8 = tls.handleClientKeyExchange; |
||
2264 | var H9 = tls.handleCertificateVerify; |
||
2265 | hsTable[tls.ConnectionEnd.server] = [ |
||
2266 | // 01,CH,02,03,04,05,06,07,08,09,10,CC,12,13,14,CV,CK,17,18,19,FI |
||
2267 | /*CHE*/[__,H7,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__], |
||
2268 | /*CCE*/[__,__,__,__,__,__,__,__,__,__,__,H2,__,__,__,__,__,__,__,__,__], |
||
2269 | /*CKE*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,H8,__,__,__,__], |
||
2270 | /*CCV*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,H9,__,__,__,__,__], |
||
2271 | /*CCC*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__], |
||
2272 | /*CFI*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,H6], |
||
2273 | /*CAD*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__], |
||
2274 | /*CER*/[__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__] |
||
2275 | ]; |
||
2276 | |||
2277 | /** |
||
2278 | * Generates the master_secret and keys using the given security parameters. |
||
2279 | * |
||
2280 | * The security parameters for a TLS connection state are defined as such: |
||
2281 | * |
||
2282 | * struct { |
||
2283 | * ConnectionEnd entity; |
||
2284 | * PRFAlgorithm prf_algorithm; |
||
2285 | * BulkCipherAlgorithm bulk_cipher_algorithm; |
||
2286 | * CipherType cipher_type; |
||
2287 | * uint8 enc_key_length; |
||
2288 | * uint8 block_length; |
||
2289 | * uint8 fixed_iv_length; |
||
2290 | * uint8 record_iv_length; |
||
2291 | * MACAlgorithm mac_algorithm; |
||
2292 | * uint8 mac_length; |
||
2293 | * uint8 mac_key_length; |
||
2294 | * CompressionMethod compression_algorithm; |
||
2295 | * opaque master_secret[48]; |
||
2296 | * opaque client_random[32]; |
||
2297 | * opaque server_random[32]; |
||
2298 | * } SecurityParameters; |
||
2299 | * |
||
2300 | * Note that this definition is from TLS 1.2. In TLS 1.0 some of these |
||
2301 | * parameters are ignored because, for instance, the PRFAlgorithm is a |
||
2302 | * builtin-fixed algorithm combining iterations of MD5 and SHA-1 in TLS 1.0. |
||
2303 | * |
||
2304 | * The Record Protocol requires an algorithm to generate keys required by the |
||
2305 | * current connection state. |
||
2306 | * |
||
2307 | * The master secret is expanded into a sequence of secure bytes, which is then |
||
2308 | * split to a client write MAC key, a server write MAC key, a client write |
||
2309 | * encryption key, and a server write encryption key. In TLS 1.0 a client write |
||
2310 | * IV and server write IV are also generated. Each of these is generated from |
||
2311 | * the byte sequence in that order. Unused values are empty. In TLS 1.2, some |
||
2312 | * AEAD ciphers may additionally require a client write IV and a server write |
||
2313 | * IV (see Section 6.2.3.3). |
||
2314 | * |
||
2315 | * When keys, MAC keys, and IVs are generated, the master secret is used as an |
||
2316 | * entropy source. |
||
2317 | * |
||
2318 | * To generate the key material, compute: |
||
2319 | * |
||
2320 | * master_secret = PRF(pre_master_secret, "master secret", |
||
2321 | * ClientHello.random + ServerHello.random) |
||
2322 | * |
||
2323 | * key_block = PRF(SecurityParameters.master_secret, |
||
2324 | * "key expansion", |
||
2325 | * SecurityParameters.server_random + |
||
2326 | * SecurityParameters.client_random); |
||
2327 | * |
||
2328 | * until enough output has been generated. Then, the key_block is |
||
2329 | * partitioned as follows: |
||
2330 | * |
||
2331 | * client_write_MAC_key[SecurityParameters.mac_key_length] |
||
2332 | * server_write_MAC_key[SecurityParameters.mac_key_length] |
||
2333 | * client_write_key[SecurityParameters.enc_key_length] |
||
2334 | * server_write_key[SecurityParameters.enc_key_length] |
||
2335 | * client_write_IV[SecurityParameters.fixed_iv_length] |
||
2336 | * server_write_IV[SecurityParameters.fixed_iv_length] |
||
2337 | * |
||
2338 | * In TLS 1.2, the client_write_IV and server_write_IV are only generated for |
||
2339 | * implicit nonce techniques as described in Section 3.2.1 of [AEAD]. This |
||
2340 | * implementation uses TLS 1.0 so IVs are generated. |
||
2341 | * |
||
2342 | * Implementation note: The currently defined cipher suite which requires the |
||
2343 | * most material is AES_256_CBC_SHA256. It requires 2 x 32 byte keys and 2 x 32 |
||
2344 | * byte MAC keys, for a total 128 bytes of key material. In TLS 1.0 it also |
||
2345 | * requires 2 x 16 byte IVs, so it actually takes 160 bytes of key material. |
||
2346 | * |
||
2347 | * @param c the connection. |
||
2348 | * @param sp the security parameters to use. |
||
2349 | * |
||
2350 | * @return the security keys. |
||
2351 | */ |
||
2352 | tls.generateKeys = function(c, sp) { |
||
2353 | // TLS_RSA_WITH_AES_128_CBC_SHA (required to be compliant with TLS 1.2) & |
||
2354 | // TLS_RSA_WITH_AES_256_CBC_SHA are the only cipher suites implemented |
||
2355 | // at present |
||
2356 | |||
2357 | // TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA is required to be compliant with |
||
2358 | // TLS 1.0 but we don't care right now because AES is better and we have |
||
2359 | // an implementation for it |
||
2360 | |||
2361 | // TODO: TLS 1.2 implementation |
||
2362 | /* |
||
2363 | // determine the PRF |
||
2364 | var prf; |
||
2365 | switch(sp.prf_algorithm) { |
||
2366 | case tls.PRFAlgorithm.tls_prf_sha256: |
||
2367 | prf = prf_sha256; |
||
2368 | break; |
||
2369 | default: |
||
2370 | // should never happen |
||
2371 | throw new Error('Invalid PRF'); |
||
2372 | } |
||
2373 | */ |
||
2374 | |||
2375 | // TLS 1.0/1.1 implementation |
||
2376 | var prf = prf_TLS1; |
||
2377 | |||
2378 | // concatenate server and client random |
||
2379 | var random = sp.client_random + sp.server_random; |
||
2380 | |||
2381 | // only create master secret if session is new |
||
2382 | if(!c.session.resuming) { |
||
2383 | // create master secret, clean up pre-master secret |
||
2384 | sp.master_secret = prf( |
||
2385 | sp.pre_master_secret, 'master secret', random, 48).bytes(); |
||
2386 | sp.pre_master_secret = null; |
||
2387 | } |
||
2388 | |||
2389 | // generate the amount of key material needed |
||
2390 | random = sp.server_random + sp.client_random; |
||
2391 | var length = 2 * sp.mac_key_length + 2 * sp.enc_key_length; |
||
2392 | |||
2393 | // include IV for TLS/1.0 |
||
2394 | var tls10 = (c.version.major === tls.Versions.TLS_1_0.major && |
||
2395 | c.version.minor === tls.Versions.TLS_1_0.minor); |
||
2396 | if(tls10) { |
||
2397 | length += 2 * sp.fixed_iv_length; |
||
2398 | } |
||
2399 | var km = prf(sp.master_secret, 'key expansion', random, length); |
||
2400 | |||
2401 | // split the key material into the MAC and encryption keys |
||
2402 | var rval = { |
||
2403 | client_write_MAC_key: km.getBytes(sp.mac_key_length), |
||
2404 | server_write_MAC_key: km.getBytes(sp.mac_key_length), |
||
2405 | client_write_key: km.getBytes(sp.enc_key_length), |
||
2406 | server_write_key: km.getBytes(sp.enc_key_length) |
||
2407 | }; |
||
2408 | |||
2409 | // include TLS 1.0 IVs |
||
2410 | if(tls10) { |
||
2411 | rval.client_write_IV = km.getBytes(sp.fixed_iv_length); |
||
2412 | rval.server_write_IV = km.getBytes(sp.fixed_iv_length); |
||
2413 | } |
||
2414 | |||
2415 | return rval; |
||
2416 | }; |
||
2417 | |||
2418 | /** |
||
2419 | * Creates a new initialized TLS connection state. A connection state has |
||
2420 | * a read mode and a write mode. |
||
2421 | * |
||
2422 | * compression state: |
||
2423 | * The current state of the compression algorithm. |
||
2424 | * |
||
2425 | * cipher state: |
||
2426 | * The current state of the encryption algorithm. This will consist of the |
||
2427 | * scheduled key for that connection. For stream ciphers, this will also |
||
2428 | * contain whatever state information is necessary to allow the stream to |
||
2429 | * continue to encrypt or decrypt data. |
||
2430 | * |
||
2431 | * MAC key: |
||
2432 | * The MAC key for the connection. |
||
2433 | * |
||
2434 | * sequence number: |
||
2435 | * Each connection state contains a sequence number, which is maintained |
||
2436 | * separately for read and write states. The sequence number MUST be set to |
||
2437 | * zero whenever a connection state is made the active state. Sequence |
||
2438 | * numbers are of type uint64 and may not exceed 2^64-1. Sequence numbers do |
||
2439 | * not wrap. If a TLS implementation would need to wrap a sequence number, |
||
2440 | * it must renegotiate instead. A sequence number is incremented after each |
||
2441 | * record: specifically, the first record transmitted under a particular |
||
2442 | * connection state MUST use sequence number 0. |
||
2443 | * |
||
2444 | * @param c the connection. |
||
2445 | * |
||
2446 | * @return the new initialized TLS connection state. |
||
2447 | */ |
||
2448 | tls.createConnectionState = function(c) { |
||
2449 | var client = (c.entity === tls.ConnectionEnd.client); |
||
2450 | |||
2451 | var createMode = function() { |
||
2452 | var mode = { |
||
2453 | // two 32-bit numbers, first is most significant |
||
2454 | sequenceNumber: [0, 0], |
||
2455 | macKey: null, |
||
2456 | macLength: 0, |
||
2457 | macFunction: null, |
||
2458 | cipherState: null, |
||
2459 | cipherFunction: function(record) {return true;}, |
||
2460 | compressionState: null, |
||
2461 | compressFunction: function(record) {return true;}, |
||
2462 | updateSequenceNumber: function() { |
||
2463 | if(mode.sequenceNumber[1] === 0xFFFFFFFF) { |
||
2464 | mode.sequenceNumber[1] = 0; |
||
2465 | ++mode.sequenceNumber[0]; |
||
2466 | } else { |
||
2467 | ++mode.sequenceNumber[1]; |
||
2468 | } |
||
2469 | } |
||
2470 | }; |
||
2471 | return mode; |
||
2472 | }; |
||
2473 | var state = { |
||
2474 | read: createMode(), |
||
2475 | write: createMode() |
||
2476 | }; |
||
2477 | |||
2478 | // update function in read mode will decrypt then decompress a record |
||
2479 | state.read.update = function(c, record) { |
||
2480 | if(!state.read.cipherFunction(record, state.read)) { |
||
2481 | c.error(c, { |
||
2482 | message: 'Could not decrypt record or bad MAC.', |
||
2483 | send: true, |
||
2484 | alert: { |
||
2485 | level: tls.Alert.Level.fatal, |
||
2486 | // doesn't matter if decryption failed or MAC was |
||
2487 | // invalid, return the same error so as not to reveal |
||
2488 | // which one occurred |
||
2489 | description: tls.Alert.Description.bad_record_mac |
||
2490 | } |
||
2491 | }); |
||
2492 | } else if(!state.read.compressFunction(c, record, state.read)) { |
||
2493 | c.error(c, { |
||
2494 | message: 'Could not decompress record.', |
||
2495 | send: true, |
||
2496 | alert: { |
||
2497 | level: tls.Alert.Level.fatal, |
||
2498 | description: tls.Alert.Description.decompression_failure |
||
2499 | } |
||
2500 | }); |
||
2501 | } |
||
2502 | return !c.fail; |
||
2503 | }; |
||
2504 | |||
2505 | // update function in write mode will compress then encrypt a record |
||
2506 | state.write.update = function(c, record) { |
||
2507 | if(!state.write.compressFunction(c, record, state.write)) { |
||
2508 | // error, but do not send alert since it would require |
||
2509 | // compression as well |
||
2510 | c.error(c, { |
||
2511 | message: 'Could not compress record.', |
||
2512 | send: false, |
||
2513 | alert: { |
||
2514 | level: tls.Alert.Level.fatal, |
||
2515 | description: tls.Alert.Description.internal_error |
||
2516 | } |
||
2517 | }); |
||
2518 | } else if(!state.write.cipherFunction(record, state.write)) { |
||
2519 | // error, but do not send alert since it would require |
||
2520 | // encryption as well |
||
2521 | c.error(c, { |
||
2522 | message: 'Could not encrypt record.', |
||
2523 | send: false, |
||
2524 | alert: { |
||
2525 | level: tls.Alert.Level.fatal, |
||
2526 | description: tls.Alert.Description.internal_error |
||
2527 | } |
||
2528 | }); |
||
2529 | } |
||
2530 | return !c.fail; |
||
2531 | }; |
||
2532 | |||
2533 | // handle security parameters |
||
2534 | if(c.session) { |
||
2535 | var sp = c.session.sp; |
||
2536 | c.session.cipherSuite.initSecurityParameters(sp); |
||
2537 | |||
2538 | // generate keys |
||
2539 | sp.keys = tls.generateKeys(c, sp); |
||
2540 | state.read.macKey = client ? |
||
2541 | sp.keys.server_write_MAC_key : sp.keys.client_write_MAC_key; |
||
2542 | state.write.macKey = client ? |
||
2543 | sp.keys.client_write_MAC_key : sp.keys.server_write_MAC_key; |
||
2544 | |||
2545 | // cipher suite setup |
||
2546 | c.session.cipherSuite.initConnectionState(state, c, sp); |
||
2547 | |||
2548 | // compression setup |
||
2549 | switch(sp.compression_algorithm) { |
||
2550 | case tls.CompressionMethod.none: |
||
2551 | break; |
||
2552 | case tls.CompressionMethod.deflate: |
||
2553 | state.read.compressFunction = inflate; |
||
2554 | state.write.compressFunction = deflate; |
||
2555 | break; |
||
2556 | default: |
||
2557 | throw new Error('Unsupported compression algorithm.'); |
||
2558 | } |
||
2559 | } |
||
2560 | |||
2561 | return state; |
||
2562 | }; |
||
2563 | |||
2564 | /** |
||
2565 | * Creates a Random structure. |
||
2566 | * |
||
2567 | * struct { |
||
2568 | * uint32 gmt_unix_time; |
||
2569 | * opaque random_bytes[28]; |
||
2570 | * } Random; |
||
2571 | * |
||
2572 | * gmt_unix_time: |
||
2573 | * The current time and date in standard UNIX 32-bit format (seconds since |
||
2574 | * the midnight starting Jan 1, 1970, UTC, ignoring leap seconds) according |
||
2575 | * to the sender's internal clock. Clocks are not required to be set |
||
2576 | * correctly by the basic TLS protocol; higher-level or application |
||
2577 | * protocols may define additional requirements. Note that, for historical |
||
2578 | * reasons, the data element is named using GMT, the predecessor of the |
||
2579 | * current worldwide time base, UTC. |
||
2580 | * random_bytes: |
||
2581 | * 28 bytes generated by a secure random number generator. |
||
2582 | * |
||
2583 | * @return the Random structure as a byte array. |
||
2584 | */ |
||
2585 | tls.createRandom = function() { |
||
2586 | // get UTC milliseconds |
||
2587 | var d = new Date(); |
||
2588 | var utc = +d + d.getTimezoneOffset() * 60000; |
||
2589 | var rval = forge.util.createBuffer(); |
||
2590 | rval.putInt32(utc); |
||
2591 | rval.putBytes(forge.random.getBytes(28)); |
||
2592 | return rval; |
||
2593 | }; |
||
2594 | |||
2595 | /** |
||
2596 | * Creates a TLS record with the given type and data. |
||
2597 | * |
||
2598 | * @param c the connection. |
||
2599 | * @param options: |
||
2600 | * type: the record type. |
||
2601 | * data: the plain text data in a byte buffer. |
||
2602 | * |
||
2603 | * @return the created record. |
||
2604 | */ |
||
2605 | tls.createRecord = function(c, options) { |
||
2606 | if(!options.data) { |
||
2607 | return null; |
||
2608 | } |
||
2609 | var record = { |
||
2610 | type: options.type, |
||
2611 | version: { |
||
2612 | major: c.version.major, |
||
2613 | minor: c.version.minor |
||
2614 | }, |
||
2615 | length: options.data.length(), |
||
2616 | fragment: options.data |
||
2617 | }; |
||
2618 | return record; |
||
2619 | }; |
||
2620 | |||
2621 | /** |
||
2622 | * Creates a TLS alert record. |
||
2623 | * |
||
2624 | * @param c the connection. |
||
2625 | * @param alert: |
||
2626 | * level: the TLS alert level. |
||
2627 | * description: the TLS alert description. |
||
2628 | * |
||
2629 | * @return the created alert record. |
||
2630 | */ |
||
2631 | tls.createAlert = function(c, alert) { |
||
2632 | var b = forge.util.createBuffer(); |
||
2633 | b.putByte(alert.level); |
||
2634 | b.putByte(alert.description); |
||
2635 | return tls.createRecord(c, { |
||
2636 | type: tls.ContentType.alert, |
||
2637 | data: b |
||
2638 | }); |
||
2639 | }; |
||
2640 | |||
2641 | /* The structure of a TLS handshake message. |
||
2642 | * |
||
2643 | * struct { |
||
2644 | * HandshakeType msg_type; // handshake type |
||
2645 | * uint24 length; // bytes in message |
||
2646 | * select(HandshakeType) { |
||
2647 | * case hello_request: HelloRequest; |
||
2648 | * case client_hello: ClientHello; |
||
2649 | * case server_hello: ServerHello; |
||
2650 | * case certificate: Certificate; |
||
2651 | * case server_key_exchange: ServerKeyExchange; |
||
2652 | * case certificate_request: CertificateRequest; |
||
2653 | * case server_hello_done: ServerHelloDone; |
||
2654 | * case certificate_verify: CertificateVerify; |
||
2655 | * case client_key_exchange: ClientKeyExchange; |
||
2656 | * case finished: Finished; |
||
2657 | * } body; |
||
2658 | * } Handshake; |
||
2659 | */ |
||
2660 | |||
2661 | /** |
||
2662 | * Creates a ClientHello message. |
||
2663 | * |
||
2664 | * opaque SessionID<0..32>; |
||
2665 | * enum { null(0), deflate(1), (255) } CompressionMethod; |
||
2666 | * uint8 CipherSuite[2]; |
||
2667 | * |
||
2668 | * struct { |
||
2669 | * ProtocolVersion client_version; |
||
2670 | * Random random; |
||
2671 | * SessionID session_id; |
||
2672 | * CipherSuite cipher_suites<2..2^16-2>; |
||
2673 | * CompressionMethod compression_methods<1..2^8-1>; |
||
2674 | * select(extensions_present) { |
||
2675 | * case false: |
||
2676 | * struct {}; |
||
2677 | * case true: |
||
2678 | * Extension extensions<0..2^16-1>; |
||
2679 | * }; |
||
2680 | * } ClientHello; |
||
2681 | * |
||
2682 | * The extension format for extended client hellos and server hellos is: |
||
2683 | * |
||
2684 | * struct { |
||
2685 | * ExtensionType extension_type; |
||
2686 | * opaque extension_data<0..2^16-1>; |
||
2687 | * } Extension; |
||
2688 | * |
||
2689 | * Here: |
||
2690 | * |
||
2691 | * - "extension_type" identifies the particular extension type. |
||
2692 | * - "extension_data" contains information specific to the particular |
||
2693 | * extension type. |
||
2694 | * |
||
2695 | * The extension types defined in this document are: |
||
2696 | * |
||
2697 | * enum { |
||
2698 | * server_name(0), max_fragment_length(1), |
||
2699 | * client_certificate_url(2), trusted_ca_keys(3), |
||
2700 | * truncated_hmac(4), status_request(5), (65535) |
||
2701 | * } ExtensionType; |
||
2702 | * |
||
2703 | * @param c the connection. |
||
2704 | * |
||
2705 | * @return the ClientHello byte buffer. |
||
2706 | */ |
||
2707 | tls.createClientHello = function(c) { |
||
2708 | // save hello version |
||
2709 | c.session.clientHelloVersion = { |
||
2710 | major: c.version.major, |
||
2711 | minor: c.version.minor |
||
2712 | }; |
||
2713 | |||
2714 | // create supported cipher suites |
||
2715 | var cipherSuites = forge.util.createBuffer(); |
||
2716 | for(var i = 0; i < c.cipherSuites.length; ++i) { |
||
2717 | var cs = c.cipherSuites[i]; |
||
2718 | cipherSuites.putByte(cs.id[0]); |
||
2719 | cipherSuites.putByte(cs.id[1]); |
||
2720 | } |
||
2721 | var cSuites = cipherSuites.length(); |
||
2722 | |||
2723 | // create supported compression methods, null always supported, but |
||
2724 | // also support deflate if connection has inflate and deflate methods |
||
2725 | var compressionMethods = forge.util.createBuffer(); |
||
2726 | compressionMethods.putByte(tls.CompressionMethod.none); |
||
2727 | // FIXME: deflate support disabled until issues with raw deflate data |
||
2728 | // without zlib headers are resolved |
||
2729 | /* |
||
2730 | if(c.inflate !== null && c.deflate !== null) { |
||
2731 | compressionMethods.putByte(tls.CompressionMethod.deflate); |
||
2732 | } |
||
2733 | */ |
||
2734 | var cMethods = compressionMethods.length(); |
||
2735 | |||
2736 | // create TLS SNI (server name indication) extension if virtual host |
||
2737 | // has been specified, see RFC 3546 |
||
2738 | var extensions = forge.util.createBuffer(); |
||
2739 | if(c.virtualHost) { |
||
2740 | // create extension struct |
||
2741 | var ext = forge.util.createBuffer(); |
||
2742 | ext.putByte(0x00); // type server_name (ExtensionType is 2 bytes) |
||
2743 | ext.putByte(0x00); |
||
2744 | |||
2745 | /* In order to provide the server name, clients MAY include an |
||
2746 | * extension of type "server_name" in the (extended) client hello. |
||
2747 | * The "extension_data" field of this extension SHALL contain |
||
2748 | * "ServerNameList" where: |
||
2749 | * |
||
2750 | * struct { |
||
2751 | * NameType name_type; |
||
2752 | * select(name_type) { |
||
2753 | * case host_name: HostName; |
||
2754 | * } name; |
||
2755 | * } ServerName; |
||
2756 | * |
||
2757 | * enum { |
||
2758 | * host_name(0), (255) |
||
2759 | * } NameType; |
||
2760 | * |
||
2761 | * opaque HostName<1..2^16-1>; |
||
2762 | * |
||
2763 | * struct { |
||
2764 | * ServerName server_name_list<1..2^16-1> |
||
2765 | * } ServerNameList; |
||
2766 | */ |
||
2767 | var serverName = forge.util.createBuffer(); |
||
2768 | serverName.putByte(0x00); // type host_name |
||
2769 | writeVector(serverName, 2, forge.util.createBuffer(c.virtualHost)); |
||
2770 | |||
2771 | // ServerNameList is in extension_data |
||
2772 | var snList = forge.util.createBuffer(); |
||
2773 | writeVector(snList, 2, serverName); |
||
2774 | writeVector(ext, 2, snList); |
||
2775 | extensions.putBuffer(ext); |
||
2776 | } |
||
2777 | var extLength = extensions.length(); |
||
2778 | if(extLength > 0) { |
||
2779 | // add extension vector length |
||
2780 | extLength += 2; |
||
2781 | } |
||
2782 | |||
2783 | // determine length of the handshake message |
||
2784 | // cipher suites and compression methods size will need to be |
||
2785 | // updated if more get added to the list |
||
2786 | var sessionId = c.session.id; |
||
2787 | var length = |
||
2788 | sessionId.length + 1 + // session ID vector |
||
2789 | 2 + // version (major + minor) |
||
2790 | 4 + 28 + // random time and random bytes |
||
2791 | 2 + cSuites + // cipher suites vector |
||
2792 | 1 + cMethods + // compression methods vector |
||
2793 | extLength; // extensions vector |
||
2794 | |||
2795 | // build record fragment |
||
2796 | var rval = forge.util.createBuffer(); |
||
2797 | rval.putByte(tls.HandshakeType.client_hello); |
||
2798 | rval.putInt24(length); // handshake length |
||
2799 | rval.putByte(c.version.major); // major version |
||
2800 | rval.putByte(c.version.minor); // minor version |
||
2801 | rval.putBytes(c.session.sp.client_random); // random time + bytes |
||
2802 | writeVector(rval, 1, forge.util.createBuffer(sessionId)); |
||
2803 | writeVector(rval, 2, cipherSuites); |
||
2804 | writeVector(rval, 1, compressionMethods); |
||
2805 | if(extLength > 0) { |
||
2806 | writeVector(rval, 2, extensions); |
||
2807 | } |
||
2808 | return rval; |
||
2809 | }; |
||
2810 | |||
2811 | /** |
||
2812 | * Creates a ServerHello message. |
||
2813 | * |
||
2814 | * @param c the connection. |
||
2815 | * |
||
2816 | * @return the ServerHello byte buffer. |
||
2817 | */ |
||
2818 | tls.createServerHello = function(c) { |
||
2819 | // determine length of the handshake message |
||
2820 | var sessionId = c.session.id; |
||
2821 | var length = |
||
2822 | sessionId.length + 1 + // session ID vector |
||
2823 | 2 + // version (major + minor) |
||
2824 | 4 + 28 + // random time and random bytes |
||
2825 | 2 + // chosen cipher suite |
||
2826 | 1; // chosen compression method |
||
2827 | |||
2828 | // build record fragment |
||
2829 | var rval = forge.util.createBuffer(); |
||
2830 | rval.putByte(tls.HandshakeType.server_hello); |
||
2831 | rval.putInt24(length); // handshake length |
||
2832 | rval.putByte(c.version.major); // major version |
||
2833 | rval.putByte(c.version.minor); // minor version |
||
2834 | rval.putBytes(c.session.sp.server_random); // random time + bytes |
||
2835 | writeVector(rval, 1, forge.util.createBuffer(sessionId)); |
||
2836 | rval.putByte(c.session.cipherSuite.id[0]); |
||
2837 | rval.putByte(c.session.cipherSuite.id[1]); |
||
2838 | rval.putByte(c.session.compressionMethod); |
||
2839 | return rval; |
||
2840 | }; |
||
2841 | |||
2842 | /** |
||
2843 | * Creates a Certificate message. |
||
2844 | * |
||
2845 | * When this message will be sent: |
||
2846 | * This is the first message the client can send after receiving a server |
||
2847 | * hello done message and the first message the server can send after |
||
2848 | * sending a ServerHello. This client message is only sent if the server |
||
2849 | * requests a certificate. If no suitable certificate is available, the |
||
2850 | * client should send a certificate message containing no certificates. If |
||
2851 | * client authentication is required by the server for the handshake to |
||
2852 | * continue, it may respond with a fatal handshake failure alert. |
||
2853 | * |
||
2854 | * opaque ASN.1Cert<1..2^24-1>; |
||
2855 | * |
||
2856 | * struct { |
||
2857 | * ASN.1Cert certificate_list<0..2^24-1>; |
||
2858 | * } Certificate; |
||
2859 | * |
||
2860 | * @param c the connection. |
||
2861 | * |
||
2862 | * @return the Certificate byte buffer. |
||
2863 | */ |
||
2864 | tls.createCertificate = function(c) { |
||
2865 | // TODO: check certificate request to ensure types are supported |
||
2866 | |||
2867 | // get a certificate (a certificate as a PEM string) |
||
2868 | var client = (c.entity === tls.ConnectionEnd.client); |
||
2869 | var cert = null; |
||
2870 | if(c.getCertificate) { |
||
2871 | var hint; |
||
2872 | if(client) { |
||
2873 | hint = c.session.certificateRequest; |
||
2874 | } else { |
||
2875 | hint = c.session.extensions.server_name.serverNameList; |
||
2876 | } |
||
2877 | cert = c.getCertificate(c, hint); |
||
2878 | } |
||
2879 | |||
2880 | // buffer to hold certificate list |
||
2881 | var certList = forge.util.createBuffer(); |
||
2882 | if(cert !== null) { |
||
2883 | try { |
||
2884 | // normalize cert to a chain of certificates |
||
2885 | if(!forge.util.isArray(cert)) { |
||
2886 | cert = [cert]; |
||
2887 | } |
||
2888 | var asn1 = null; |
||
2889 | for(var i = 0; i < cert.length; ++i) { |
||
2890 | var msg = forge.pem.decode(cert[i])[0]; |
||
2891 | if(msg.type !== 'CERTIFICATE' && |
||
2892 | msg.type !== 'X509 CERTIFICATE' && |
||
2893 | msg.type !== 'TRUSTED CERTIFICATE') { |
||
2894 | var error = new Error('Could not convert certificate from PEM; PEM ' + |
||
2895 | 'header type is not "CERTIFICATE", "X509 CERTIFICATE", or ' + |
||
2896 | '"TRUSTED CERTIFICATE".'); |
||
2897 | error.headerType = msg.type; |
||
2898 | throw error; |
||
2899 | } |
||
2900 | if(msg.procType && msg.procType.type === 'ENCRYPTED') { |
||
2901 | throw new Error('Could not convert certificate from PEM; PEM is encrypted.'); |
||
2902 | } |
||
2903 | |||
2904 | var der = forge.util.createBuffer(msg.body); |
||
2905 | if(asn1 === null) { |
||
2906 | asn1 = forge.asn1.fromDer(der.bytes(), false); |
||
2907 | } |
||
2908 | |||
2909 | // certificate entry is itself a vector with 3 length bytes |
||
2910 | var certBuffer = forge.util.createBuffer(); |
||
2911 | writeVector(certBuffer, 3, der); |
||
2912 | |||
2913 | // add cert vector to cert list vector |
||
2914 | certList.putBuffer(certBuffer); |
||
2915 | } |
||
2916 | |||
2917 | // save certificate |
||
2918 | cert = forge.pki.certificateFromAsn1(asn1); |
||
2919 | if(client) { |
||
2920 | c.session.clientCertificate = cert; |
||
2921 | } else { |
||
2922 | c.session.serverCertificate = cert; |
||
2923 | } |
||
2924 | } catch(ex) { |
||
2925 | return c.error(c, { |
||
2926 | message: 'Could not send certificate list.', |
||
2927 | cause: ex, |
||
2928 | send: true, |
||
2929 | alert: { |
||
2930 | level: tls.Alert.Level.fatal, |
||
2931 | description: tls.Alert.Description.bad_certificate |
||
2932 | } |
||
2933 | }); |
||
2934 | } |
||
2935 | } |
||
2936 | |||
2937 | // determine length of the handshake message |
||
2938 | var length = 3 + certList.length(); // cert list vector |
||
2939 | |||
2940 | // build record fragment |
||
2941 | var rval = forge.util.createBuffer(); |
||
2942 | rval.putByte(tls.HandshakeType.certificate); |
||
2943 | rval.putInt24(length); |
||
2944 | writeVector(rval, 3, certList); |
||
2945 | return rval; |
||
2946 | }; |
||
2947 | |||
2948 | /** |
||
2949 | * Creates a ClientKeyExchange message. |
||
2950 | * |
||
2951 | * When this message will be sent: |
||
2952 | * This message is always sent by the client. It will immediately follow the |
||
2953 | * client certificate message, if it is sent. Otherwise it will be the first |
||
2954 | * message sent by the client after it receives the server hello done |
||
2955 | * message. |
||
2956 | * |
||
2957 | * Meaning of this message: |
||
2958 | * With this message, the premaster secret is set, either though direct |
||
2959 | * transmission of the RSA-encrypted secret, or by the transmission of |
||
2960 | * Diffie-Hellman parameters which will allow each side to agree upon the |
||
2961 | * same premaster secret. When the key exchange method is DH_RSA or DH_DSS, |
||
2962 | * client certification has been requested, and the client was able to |
||
2963 | * respond with a certificate which contained a Diffie-Hellman public key |
||
2964 | * whose parameters (group and generator) matched those specified by the |
||
2965 | * server in its certificate, this message will not contain any data. |
||
2966 | * |
||
2967 | * Meaning of this message: |
||
2968 | * If RSA is being used for key agreement and authentication, the client |
||
2969 | * generates a 48-byte premaster secret, encrypts it using the public key |
||
2970 | * from the server's certificate or the temporary RSA key provided in a |
||
2971 | * server key exchange message, and sends the result in an encrypted |
||
2972 | * premaster secret message. This structure is a variant of the client |
||
2973 | * key exchange message, not a message in itself. |
||
2974 | * |
||
2975 | * struct { |
||
2976 | * select(KeyExchangeAlgorithm) { |
||
2977 | * case rsa: EncryptedPreMasterSecret; |
||
2978 | * case diffie_hellman: ClientDiffieHellmanPublic; |
||
2979 | * } exchange_keys; |
||
2980 | * } ClientKeyExchange; |
||
2981 | * |
||
2982 | * struct { |
||
2983 | * ProtocolVersion client_version; |
||
2984 | * opaque random[46]; |
||
2985 | * } PreMasterSecret; |
||
2986 | * |
||
2987 | * struct { |
||
2988 | * public-key-encrypted PreMasterSecret pre_master_secret; |
||
2989 | * } EncryptedPreMasterSecret; |
||
2990 | * |
||
2991 | * A public-key-encrypted element is encoded as a vector <0..2^16-1>. |
||
2992 | * |
||
2993 | * @param c the connection. |
||
2994 | * |
||
2995 | * @return the ClientKeyExchange byte buffer. |
||
2996 | */ |
||
2997 | tls.createClientKeyExchange = function(c) { |
||
2998 | // create buffer to encrypt |
||
2999 | var b = forge.util.createBuffer(); |
||
3000 | |||
3001 | // add highest client-supported protocol to help server avoid version |
||
3002 | // rollback attacks |
||
3003 | b.putByte(c.session.clientHelloVersion.major); |
||
3004 | b.putByte(c.session.clientHelloVersion.minor); |
||
3005 | |||
3006 | // generate and add 46 random bytes |
||
3007 | b.putBytes(forge.random.getBytes(46)); |
||
3008 | |||
3009 | // save pre-master secret |
||
3010 | var sp = c.session.sp; |
||
3011 | sp.pre_master_secret = b.getBytes(); |
||
3012 | |||
3013 | // RSA-encrypt the pre-master secret |
||
3014 | var key = c.session.serverCertificate.publicKey; |
||
3015 | b = key.encrypt(sp.pre_master_secret); |
||
3016 | |||
3017 | /* Note: The encrypted pre-master secret will be stored in a |
||
3018 | public-key-encrypted opaque vector that has the length prefixed using |
||
3019 | 2 bytes, so include those 2 bytes in the handshake message length. This |
||
3020 | is done as a minor optimization instead of calling writeVector(). */ |
||
3021 | |||
3022 | // determine length of the handshake message |
||
3023 | var length = b.length + 2; |
||
3024 | |||
3025 | // build record fragment |
||
3026 | var rval = forge.util.createBuffer(); |
||
3027 | rval.putByte(tls.HandshakeType.client_key_exchange); |
||
3028 | rval.putInt24(length); |
||
3029 | // add vector length bytes |
||
3030 | rval.putInt16(b.length); |
||
3031 | rval.putBytes(b); |
||
3032 | return rval; |
||
3033 | }; |
||
3034 | |||
3035 | /** |
||
3036 | * Creates a ServerKeyExchange message. |
||
3037 | * |
||
3038 | * @param c the connection. |
||
3039 | * |
||
3040 | * @return the ServerKeyExchange byte buffer. |
||
3041 | */ |
||
3042 | tls.createServerKeyExchange = function(c) { |
||
3043 | // this implementation only supports RSA, no Diffie-Hellman support, |
||
3044 | // so this record is empty |
||
3045 | |||
3046 | // determine length of the handshake message |
||
3047 | var length = 0; |
||
3048 | |||
3049 | // build record fragment |
||
3050 | var rval = forge.util.createBuffer(); |
||
3051 | if(length > 0) { |
||
3052 | rval.putByte(tls.HandshakeType.server_key_exchange); |
||
3053 | rval.putInt24(length); |
||
3054 | } |
||
3055 | return rval; |
||
3056 | }; |
||
3057 | |||
3058 | /** |
||
3059 | * Gets the signed data used to verify a client-side certificate. See |
||
3060 | * tls.createCertificateVerify() for details. |
||
3061 | * |
||
3062 | * @param c the connection. |
||
3063 | * @param callback the callback to call once the signed data is ready. |
||
3064 | */ |
||
3065 | tls.getClientSignature = function(c, callback) { |
||
3066 | // generate data to RSA encrypt |
||
3067 | var b = forge.util.createBuffer(); |
||
3068 | b.putBuffer(c.session.md5.digest()); |
||
3069 | b.putBuffer(c.session.sha1.digest()); |
||
3070 | b = b.getBytes(); |
||
3071 | |||
3072 | // create default signing function as necessary |
||
3073 | c.getSignature = c.getSignature || function(c, b, callback) { |
||
3074 | // do rsa encryption, call callback |
||
3075 | var privateKey = null; |
||
3076 | if(c.getPrivateKey) { |
||
3077 | try { |
||
3078 | privateKey = c.getPrivateKey(c, c.session.clientCertificate); |
||
3079 | privateKey = forge.pki.privateKeyFromPem(privateKey); |
||
3080 | } catch(ex) { |
||
3081 | c.error(c, { |
||
3082 | message: 'Could not get private key.', |
||
3083 | cause: ex, |
||
3084 | send: true, |
||
3085 | alert: { |
||
3086 | level: tls.Alert.Level.fatal, |
||
3087 | description: tls.Alert.Description.internal_error |
||
3088 | } |
||
3089 | }); |
||
3090 | } |
||
3091 | } |
||
3092 | if(privateKey === null) { |
||
3093 | c.error(c, { |
||
3094 | message: 'No private key set.', |
||
3095 | send: true, |
||
3096 | alert: { |
||
3097 | level: tls.Alert.Level.fatal, |
||
3098 | description: tls.Alert.Description.internal_error |
||
3099 | } |
||
3100 | }); |
||
3101 | } else { |
||
3102 | b = privateKey.sign(b, null); |
||
3103 | } |
||
3104 | callback(c, b); |
||
3105 | }; |
||
3106 | |||
3107 | // get client signature |
||
3108 | c.getSignature(c, b, callback); |
||
3109 | }; |
||
3110 | |||
3111 | /** |
||
3112 | * Creates a CertificateVerify message. |
||
3113 | * |
||
3114 | * Meaning of this message: |
||
3115 | * This structure conveys the client's Diffie-Hellman public value |
||
3116 | * (Yc) if it was not already included in the client's certificate. |
||
3117 | * The encoding used for Yc is determined by the enumerated |
||
3118 | * PublicValueEncoding. This structure is a variant of the client |
||
3119 | * key exchange message, not a message in itself. |
||
3120 | * |
||
3121 | * When this message will be sent: |
||
3122 | * This message is used to provide explicit verification of a client |
||
3123 | * certificate. This message is only sent following a client |
||
3124 | * certificate that has signing capability (i.e. all certificates |
||
3125 | * except those containing fixed Diffie-Hellman parameters). When |
||
3126 | * sent, it will immediately follow the client key exchange message. |
||
3127 | * |
||
3128 | * struct { |
||
3129 | * Signature signature; |
||
3130 | * } CertificateVerify; |
||
3131 | * |
||
3132 | * CertificateVerify.signature.md5_hash |
||
3133 | * MD5(handshake_messages); |
||
3134 | * |
||
3135 | * Certificate.signature.sha_hash |
||
3136 | * SHA(handshake_messages); |
||
3137 | * |
||
3138 | * Here handshake_messages refers to all handshake messages sent or |
||
3139 | * received starting at client hello up to but not including this |
||
3140 | * message, including the type and length fields of the handshake |
||
3141 | * messages. |
||
3142 | * |
||
3143 | * select(SignatureAlgorithm) { |
||
3144 | * case anonymous: struct { }; |
||
3145 | * case rsa: |
||
3146 | * digitally-signed struct { |
||
3147 | * opaque md5_hash[16]; |
||
3148 | * opaque sha_hash[20]; |
||
3149 | * }; |
||
3150 | * case dsa: |
||
3151 | * digitally-signed struct { |
||
3152 | * opaque sha_hash[20]; |
||
3153 | * }; |
||
3154 | * } Signature; |
||
3155 | * |
||
3156 | * In digital signing, one-way hash functions are used as input for a |
||
3157 | * signing algorithm. A digitally-signed element is encoded as an opaque |
||
3158 | * vector <0..2^16-1>, where the length is specified by the signing |
||
3159 | * algorithm and key. |
||
3160 | * |
||
3161 | * In RSA signing, a 36-byte structure of two hashes (one SHA and one |
||
3162 | * MD5) is signed (encrypted with the private key). It is encoded with |
||
3163 | * PKCS #1 block type 0 or type 1 as described in [PKCS1]. |
||
3164 | * |
||
3165 | * In DSS, the 20 bytes of the SHA hash are run directly through the |
||
3166 | * Digital Signing Algorithm with no additional hashing. |
||
3167 | * |
||
3168 | * @param c the connection. |
||
3169 | * @param signature the signature to include in the message. |
||
3170 | * |
||
3171 | * @return the CertificateVerify byte buffer. |
||
3172 | */ |
||
3173 | tls.createCertificateVerify = function(c, signature) { |
||
3174 | /* Note: The signature will be stored in a "digitally-signed" opaque |
||
3175 | vector that has the length prefixed using 2 bytes, so include those |
||
3176 | 2 bytes in the handshake message length. This is done as a minor |
||
3177 | optimization instead of calling writeVector(). */ |
||
3178 | |||
3179 | // determine length of the handshake message |
||
3180 | var length = signature.length + 2; |
||
3181 | |||
3182 | // build record fragment |
||
3183 | var rval = forge.util.createBuffer(); |
||
3184 | rval.putByte(tls.HandshakeType.certificate_verify); |
||
3185 | rval.putInt24(length); |
||
3186 | // add vector length bytes |
||
3187 | rval.putInt16(signature.length); |
||
3188 | rval.putBytes(signature); |
||
3189 | return rval; |
||
3190 | }; |
||
3191 | |||
3192 | /** |
||
3193 | * Creates a CertificateRequest message. |
||
3194 | * |
||
3195 | * @param c the connection. |
||
3196 | * |
||
3197 | * @return the CertificateRequest byte buffer. |
||
3198 | */ |
||
3199 | tls.createCertificateRequest = function(c) { |
||
3200 | // TODO: support other certificate types |
||
3201 | var certTypes = forge.util.createBuffer(); |
||
3202 | |||
3203 | // common RSA certificate type |
||
3204 | certTypes.putByte(0x01); |
||
3205 | |||
3206 | // add distinguished names from CA store |
||
3207 | var cAs = forge.util.createBuffer(); |
||
3208 | for(var key in c.caStore.certs) { |
||
3209 | var cert = c.caStore.certs[key]; |
||
3210 | var dn = forge.pki.distinguishedNameToAsn1(cert.subject); |
||
3211 | var byteBuffer = forge.asn1.toDer(dn); |
||
3212 | cAs.putInt16(byteBuffer.length()); |
||
3213 | cAs.putBuffer(byteBuffer); |
||
3214 | } |
||
3215 | |||
3216 | // TODO: TLS 1.2+ has a different format |
||
3217 | |||
3218 | // determine length of the handshake message |
||
3219 | var length = |
||
3220 | 1 + certTypes.length() + |
||
3221 | 2 + cAs.length(); |
||
3222 | |||
3223 | // build record fragment |
||
3224 | var rval = forge.util.createBuffer(); |
||
3225 | rval.putByte(tls.HandshakeType.certificate_request); |
||
3226 | rval.putInt24(length); |
||
3227 | writeVector(rval, 1, certTypes); |
||
3228 | writeVector(rval, 2, cAs); |
||
3229 | return rval; |
||
3230 | }; |
||
3231 | |||
3232 | /** |
||
3233 | * Creates a ServerHelloDone message. |
||
3234 | * |
||
3235 | * @param c the connection. |
||
3236 | * |
||
3237 | * @return the ServerHelloDone byte buffer. |
||
3238 | */ |
||
3239 | tls.createServerHelloDone = function(c) { |
||
3240 | // build record fragment |
||
3241 | var rval = forge.util.createBuffer(); |
||
3242 | rval.putByte(tls.HandshakeType.server_hello_done); |
||
3243 | rval.putInt24(0); |
||
3244 | return rval; |
||
3245 | }; |
||
3246 | |||
3247 | /** |
||
3248 | * Creates a ChangeCipherSpec message. |
||
3249 | * |
||
3250 | * The change cipher spec protocol exists to signal transitions in |
||
3251 | * ciphering strategies. The protocol consists of a single message, |
||
3252 | * which is encrypted and compressed under the current (not the pending) |
||
3253 | * connection state. The message consists of a single byte of value 1. |
||
3254 | * |
||
3255 | * struct { |
||
3256 | * enum { change_cipher_spec(1), (255) } type; |
||
3257 | * } ChangeCipherSpec; |
||
3258 | * |
||
3259 | * @return the ChangeCipherSpec byte buffer. |
||
3260 | */ |
||
3261 | tls.createChangeCipherSpec = function() { |
||
3262 | var rval = forge.util.createBuffer(); |
||
3263 | rval.putByte(0x01); |
||
3264 | return rval; |
||
3265 | }; |
||
3266 | |||
3267 | /** |
||
3268 | * Creates a Finished message. |
||
3269 | * |
||
3270 | * struct { |
||
3271 | * opaque verify_data[12]; |
||
3272 | * } Finished; |
||
3273 | * |
||
3274 | * verify_data |
||
3275 | * PRF(master_secret, finished_label, MD5(handshake_messages) + |
||
3276 | * SHA-1(handshake_messages)) [0..11]; |
||
3277 | * |
||
3278 | * finished_label |
||
3279 | * For Finished messages sent by the client, the string "client |
||
3280 | * finished". For Finished messages sent by the server, the |
||
3281 | * string "server finished". |
||
3282 | * |
||
3283 | * handshake_messages |
||
3284 | * All of the data from all handshake messages up to but not |
||
3285 | * including this message. This is only data visible at the |
||
3286 | * handshake layer and does not include record layer headers. |
||
3287 | * This is the concatenation of all the Handshake structures as |
||
3288 | * defined in 7.4 exchanged thus far. |
||
3289 | * |
||
3290 | * @param c the connection. |
||
3291 | * |
||
3292 | * @return the Finished byte buffer. |
||
3293 | */ |
||
3294 | tls.createFinished = function(c) { |
||
3295 | // generate verify_data |
||
3296 | var b = forge.util.createBuffer(); |
||
3297 | b.putBuffer(c.session.md5.digest()); |
||
3298 | b.putBuffer(c.session.sha1.digest()); |
||
3299 | |||
3300 | // TODO: determine prf function and verify length for TLS 1.2 |
||
3301 | var client = (c.entity === tls.ConnectionEnd.client); |
||
3302 | var sp = c.session.sp; |
||
3303 | var vdl = 12; |
||
3304 | var prf = prf_TLS1; |
||
3305 | var label = client ? 'client finished' : 'server finished'; |
||
3306 | b = prf(sp.master_secret, label, b.getBytes(), vdl); |
||
3307 | |||
3308 | // build record fragment |
||
3309 | var rval = forge.util.createBuffer(); |
||
3310 | rval.putByte(tls.HandshakeType.finished); |
||
3311 | rval.putInt24(b.length()); |
||
3312 | rval.putBuffer(b); |
||
3313 | return rval; |
||
3314 | }; |
||
3315 | |||
3316 | /** |
||
3317 | * Creates a HeartbeatMessage (See RFC 6520). |
||
3318 | * |
||
3319 | * struct { |
||
3320 | * HeartbeatMessageType type; |
||
3321 | * uint16 payload_length; |
||
3322 | * opaque payload[HeartbeatMessage.payload_length]; |
||
3323 | * opaque padding[padding_length]; |
||
3324 | * } HeartbeatMessage; |
||
3325 | * |
||
3326 | * The total length of a HeartbeatMessage MUST NOT exceed 2^14 or |
||
3327 | * max_fragment_length when negotiated as defined in [RFC6066]. |
||
3328 | * |
||
3329 | * type: The message type, either heartbeat_request or heartbeat_response. |
||
3330 | * |
||
3331 | * payload_length: The length of the payload. |
||
3332 | * |
||
3333 | * payload: The payload consists of arbitrary content. |
||
3334 | * |
||
3335 | * padding: The padding is random content that MUST be ignored by the |
||
3336 | * receiver. The length of a HeartbeatMessage is TLSPlaintext.length |
||
3337 | * for TLS and DTLSPlaintext.length for DTLS. Furthermore, the |
||
3338 | * length of the type field is 1 byte, and the length of the |
||
3339 | * payload_length is 2. Therefore, the padding_length is |
||
3340 | * TLSPlaintext.length - payload_length - 3 for TLS and |
||
3341 | * DTLSPlaintext.length - payload_length - 3 for DTLS. The |
||
3342 | * padding_length MUST be at least 16. |
||
3343 | * |
||
3344 | * The sender of a HeartbeatMessage MUST use a random padding of at |
||
3345 | * least 16 bytes. The padding of a received HeartbeatMessage message |
||
3346 | * MUST be ignored. |
||
3347 | * |
||
3348 | * If the payload_length of a received HeartbeatMessage is too large, |
||
3349 | * the received HeartbeatMessage MUST be discarded silently. |
||
3350 | * |
||
3351 | * @param c the connection. |
||
3352 | * @param type the tls.HeartbeatMessageType. |
||
3353 | * @param payload the heartbeat data to send as the payload. |
||
3354 | * @param [payloadLength] the payload length to use, defaults to the |
||
3355 | * actual payload length. |
||
3356 | * |
||
3357 | * @return the HeartbeatRequest byte buffer. |
||
3358 | */ |
||
3359 | tls.createHeartbeat = function(type, payload, payloadLength) { |
||
3360 | if(typeof payloadLength === 'undefined') { |
||
3361 | payloadLength = payload.length; |
||
3362 | } |
||
3363 | // build record fragment |
||
3364 | var rval = forge.util.createBuffer(); |
||
3365 | rval.putByte(type); // heartbeat message type |
||
3366 | rval.putInt16(payloadLength); // payload length |
||
3367 | rval.putBytes(payload); // payload |
||
3368 | // padding |
||
3369 | var plaintextLength = rval.length(); |
||
3370 | var paddingLength = Math.max(16, plaintextLength - payloadLength - 3); |
||
3371 | rval.putBytes(forge.random.getBytes(paddingLength)); |
||
3372 | return rval; |
||
3373 | }; |
||
3374 | |||
3375 | /** |
||
3376 | * Fragments, compresses, encrypts, and queues a record for delivery. |
||
3377 | * |
||
3378 | * @param c the connection. |
||
3379 | * @param record the record to queue. |
||
3380 | */ |
||
3381 | tls.queue = function(c, record) { |
||
3382 | // error during record creation |
||
3383 | if(!record) { |
||
3384 | return; |
||
3385 | } |
||
3386 | |||
3387 | if(record.fragment.length() === 0) { |
||
3388 | if(record.type === tls.ContentType.handshake || |
||
3389 | record.type === tls.ContentType.alert || |
||
3390 | record.type === tls.ContentType.change_cipher_spec) { |
||
3391 | // Empty handshake, alert of change cipher spec messages are not allowed per the TLS specification and should not be sent. |
||
3392 | return; |
||
3393 | } |
||
3394 | } |
||
3395 | |||
3396 | // if the record is a handshake record, update handshake hashes |
||
3397 | if(record.type === tls.ContentType.handshake) { |
||
3398 | var bytes = record.fragment.bytes(); |
||
3399 | c.session.md5.update(bytes); |
||
3400 | c.session.sha1.update(bytes); |
||
3401 | bytes = null; |
||
3402 | } |
||
3403 | |||
3404 | // handle record fragmentation |
||
3405 | var records; |
||
3406 | if(record.fragment.length() <= tls.MaxFragment) { |
||
3407 | records = [record]; |
||
3408 | } else { |
||
3409 | // fragment data as long as it is too long |
||
3410 | records = []; |
||
3411 | var data = record.fragment.bytes(); |
||
3412 | while(data.length > tls.MaxFragment) { |
||
3413 | records.push(tls.createRecord(c, { |
||
3414 | type: record.type, |
||
3415 | data: forge.util.createBuffer(data.slice(0, tls.MaxFragment)) |
||
3416 | })); |
||
3417 | data = data.slice(tls.MaxFragment); |
||
3418 | } |
||
3419 | // add last record |
||
3420 | if(data.length > 0) { |
||
3421 | records.push(tls.createRecord(c, { |
||
3422 | type: record.type, |
||
3423 | data: forge.util.createBuffer(data) |
||
3424 | })); |
||
3425 | } |
||
3426 | } |
||
3427 | |||
3428 | // compress and encrypt all fragmented records |
||
3429 | for(var i = 0; i < records.length && !c.fail; ++i) { |
||
3430 | // update the record using current write state |
||
3431 | var rec = records[i]; |
||
3432 | var s = c.state.current.write; |
||
3433 | if(s.update(c, rec)) { |
||
3434 | // store record |
||
3435 | c.records.push(rec); |
||
3436 | } |
||
3437 | } |
||
3438 | }; |
||
3439 | |||
3440 | /** |
||
3441 | * Flushes all queued records to the output buffer and calls the |
||
3442 | * tlsDataReady() handler on the given connection. |
||
3443 | * |
||
3444 | * @param c the connection. |
||
3445 | * |
||
3446 | * @return true on success, false on failure. |
||
3447 | */ |
||
3448 | tls.flush = function(c) { |
||
3449 | for(var i = 0; i < c.records.length; ++i) { |
||
3450 | var record = c.records[i]; |
||
3451 | |||
3452 | // add record header and fragment |
||
3453 | c.tlsData.putByte(record.type); |
||
3454 | c.tlsData.putByte(record.version.major); |
||
3455 | c.tlsData.putByte(record.version.minor); |
||
3456 | c.tlsData.putInt16(record.fragment.length()); |
||
3457 | c.tlsData.putBuffer(c.records[i].fragment); |
||
3458 | } |
||
3459 | c.records = []; |
||
3460 | return c.tlsDataReady(c); |
||
3461 | }; |
||
3462 | |||
3463 | /** |
||
3464 | * Maps a pki.certificateError to a tls.Alert.Description. |
||
3465 | * |
||
3466 | * @param error the error to map. |
||
3467 | * |
||
3468 | * @return the alert description. |
||
3469 | */ |
||
3470 | var _certErrorToAlertDesc = function(error) { |
||
3471 | switch(error) { |
||
3472 | case true: |
||
3473 | return true; |
||
3474 | case forge.pki.certificateError.bad_certificate: |
||
3475 | return tls.Alert.Description.bad_certificate; |
||
3476 | case forge.pki.certificateError.unsupported_certificate: |
||
3477 | return tls.Alert.Description.unsupported_certificate; |
||
3478 | case forge.pki.certificateError.certificate_revoked: |
||
3479 | return tls.Alert.Description.certificate_revoked; |
||
3480 | case forge.pki.certificateError.certificate_expired: |
||
3481 | return tls.Alert.Description.certificate_expired; |
||
3482 | case forge.pki.certificateError.certificate_unknown: |
||
3483 | return tls.Alert.Description.certificate_unknown; |
||
3484 | case forge.pki.certificateError.unknown_ca: |
||
3485 | return tls.Alert.Description.unknown_ca; |
||
3486 | default: |
||
3487 | return tls.Alert.Description.bad_certificate; |
||
3488 | } |
||
3489 | }; |
||
3490 | |||
3491 | /** |
||
3492 | * Maps a tls.Alert.Description to a pki.certificateError. |
||
3493 | * |
||
3494 | * @param desc the alert description. |
||
3495 | * |
||
3496 | * @return the certificate error. |
||
3497 | */ |
||
3498 | var _alertDescToCertError = function(desc) { |
||
3499 | switch(desc) { |
||
3500 | case true: |
||
3501 | return true; |
||
3502 | case tls.Alert.Description.bad_certificate: |
||
3503 | return forge.pki.certificateError.bad_certificate; |
||
3504 | case tls.Alert.Description.unsupported_certificate: |
||
3505 | return forge.pki.certificateError.unsupported_certificate; |
||
3506 | case tls.Alert.Description.certificate_revoked: |
||
3507 | return forge.pki.certificateError.certificate_revoked; |
||
3508 | case tls.Alert.Description.certificate_expired: |
||
3509 | return forge.pki.certificateError.certificate_expired; |
||
3510 | case tls.Alert.Description.certificate_unknown: |
||
3511 | return forge.pki.certificateError.certificate_unknown; |
||
3512 | case tls.Alert.Description.unknown_ca: |
||
3513 | return forge.pki.certificateError.unknown_ca; |
||
3514 | default: |
||
3515 | return forge.pki.certificateError.bad_certificate; |
||
3516 | } |
||
3517 | }; |
||
3518 | |||
3519 | /** |
||
3520 | * Verifies a certificate chain against the given connection's |
||
3521 | * Certificate Authority store. |
||
3522 | * |
||
3523 | * @param c the TLS connection. |
||
3524 | * @param chain the certificate chain to verify, with the root or highest |
||
3525 | * authority at the end. |
||
3526 | * |
||
3527 | * @return true if successful, false if not. |
||
3528 | */ |
||
3529 | tls.verifyCertificateChain = function(c, chain) { |
||
3530 | try { |
||
3531 | // verify chain |
||
3532 | forge.pki.verifyCertificateChain(c.caStore, chain, |
||
3533 | function verify(vfd, depth, chain) { |
||
3534 | // convert pki.certificateError to tls alert description |
||
3535 | var desc = _certErrorToAlertDesc(vfd); |
||
3536 | |||
3537 | // call application callback |
||
3538 | var ret = c.verify(c, vfd, depth, chain); |
||
3539 | if(ret !== true) { |
||
3540 | if(typeof ret === 'object' && !forge.util.isArray(ret)) { |
||
3541 | // throw custom error |
||
3542 | var error = new Error('The application rejected the certificate.'); |
||
3543 | error.send = true; |
||
3544 | error.alert = { |
||
3545 | level: tls.Alert.Level.fatal, |
||
3546 | description: tls.Alert.Description.bad_certificate |
||
3547 | }; |
||
3548 | if(ret.message) { |
||
3549 | error.message = ret.message; |
||
3550 | } |
||
3551 | if(ret.alert) { |
||
3552 | error.alert.description = ret.alert; |
||
3553 | } |
||
3554 | throw error; |
||
3555 | } |
||
3556 | |||
3557 | // convert tls alert description to pki.certificateError |
||
3558 | if(ret !== vfd) { |
||
3559 | ret = _alertDescToCertError(ret); |
||
3560 | } |
||
3561 | } |
||
3562 | |||
3563 | return ret; |
||
3564 | }); |
||
3565 | } catch(ex) { |
||
3566 | // build tls error if not already customized |
||
3567 | var err = ex; |
||
3568 | if(typeof err !== 'object' || forge.util.isArray(err)) { |
||
3569 | err = { |
||
3570 | send: true, |
||
3571 | alert: { |
||
3572 | level: tls.Alert.Level.fatal, |
||
3573 | description: _certErrorToAlertDesc(ex) |
||
3574 | } |
||
3575 | }; |
||
3576 | } |
||
3577 | if(!('send' in err)) { |
||
3578 | err.send = true; |
||
3579 | } |
||
3580 | if(!('alert' in err)) { |
||
3581 | err.alert = { |
||
3582 | level: tls.Alert.Level.fatal, |
||
3583 | description: _certErrorToAlertDesc(err.error) |
||
3584 | }; |
||
3585 | } |
||
3586 | |||
3587 | // send error |
||
3588 | c.error(c, err); |
||
3589 | } |
||
3590 | |||
3591 | return !c.fail; |
||
3592 | }; |
||
3593 | |||
3594 | /** |
||
3595 | * Creates a new TLS session cache. |
||
3596 | * |
||
3597 | * @param cache optional map of session ID to cached session. |
||
3598 | * @param capacity the maximum size for the cache (default: 100). |
||
3599 | * |
||
3600 | * @return the new TLS session cache. |
||
3601 | */ |
||
3602 | tls.createSessionCache = function(cache, capacity) { |
||
3603 | var rval = null; |
||
3604 | |||
3605 | // assume input is already a session cache object |
||
3606 | if(cache && cache.getSession && cache.setSession && cache.order) { |
||
3607 | rval = cache; |
||
3608 | } else { |
||
3609 | // create cache |
||
3610 | rval = {}; |
||
3611 | rval.cache = cache || {}; |
||
3612 | rval.capacity = Math.max(capacity || 100, 1); |
||
3613 | rval.order = []; |
||
3614 | |||
3615 | // store order for sessions, delete session overflow |
||
3616 | for(var key in cache) { |
||
3617 | if(rval.order.length <= capacity) { |
||
3618 | rval.order.push(key); |
||
3619 | } else { |
||
3620 | delete cache[key]; |
||
3621 | } |
||
3622 | } |
||
3623 | |||
3624 | // get a session from a session ID (or get any session) |
||
3625 | rval.getSession = function(sessionId) { |
||
3626 | var session = null; |
||
3627 | var key = null; |
||
3628 | |||
3629 | // if session ID provided, use it |
||
3630 | if(sessionId) { |
||
3631 | key = forge.util.bytesToHex(sessionId); |
||
3632 | } else if(rval.order.length > 0) { |
||
3633 | // get first session from cache |
||
3634 | key = rval.order[0]; |
||
3635 | } |
||
3636 | |||
3637 | if(key !== null && key in rval.cache) { |
||
3638 | // get cached session and remove from cache |
||
3639 | session = rval.cache[key]; |
||
3640 | delete rval.cache[key]; |
||
3641 | for(var i in rval.order) { |
||
3642 | if(rval.order[i] === key) { |
||
3643 | rval.order.splice(i, 1); |
||
3644 | break; |
||
3645 | } |
||
3646 | } |
||
3647 | } |
||
3648 | |||
3649 | return session; |
||
3650 | }; |
||
3651 | |||
3652 | // set a session in the cache |
||
3653 | rval.setSession = function(sessionId, session) { |
||
3654 | // remove session from cache if at capacity |
||
3655 | if(rval.order.length === rval.capacity) { |
||
3656 | var key = rval.order.shift(); |
||
3657 | delete rval.cache[key]; |
||
3658 | } |
||
3659 | // add session to cache |
||
3660 | var key = forge.util.bytesToHex(sessionId); |
||
3661 | rval.order.push(key); |
||
3662 | rval.cache[key] = session; |
||
3663 | }; |
||
3664 | } |
||
3665 | |||
3666 | return rval; |
||
3667 | }; |
||
3668 | |||
3669 | /** |
||
3670 | * Creates a new TLS connection. |
||
3671 | * |
||
3672 | * See public createConnection() docs for more details. |
||
3673 | * |
||
3674 | * @param options the options for this connection. |
||
3675 | * |
||
3676 | * @return the new TLS connection. |
||
3677 | */ |
||
3678 | tls.createConnection = function(options) { |
||
3679 | var caStore = null; |
||
3680 | if(options.caStore) { |
||
3681 | // if CA store is an array, convert it to a CA store object |
||
3682 | if(forge.util.isArray(options.caStore)) { |
||
3683 | caStore = forge.pki.createCaStore(options.caStore); |
||
3684 | } else { |
||
3685 | caStore = options.caStore; |
||
3686 | } |
||
3687 | } else { |
||
3688 | // create empty CA store |
||
3689 | caStore = forge.pki.createCaStore(); |
||
3690 | } |
||
3691 | |||
3692 | // setup default cipher suites |
||
3693 | var cipherSuites = options.cipherSuites || null; |
||
3694 | if(cipherSuites === null) { |
||
3695 | cipherSuites = []; |
||
3696 | for(var key in tls.CipherSuites) { |
||
3697 | cipherSuites.push(tls.CipherSuites[key]); |
||
3698 | } |
||
3699 | } |
||
3700 | |||
3701 | // set default entity |
||
3702 | var entity = (options.server || false) ? |
||
3703 | tls.ConnectionEnd.server : tls.ConnectionEnd.client; |
||
3704 | |||
3705 | // create session cache if requested |
||
3706 | var sessionCache = options.sessionCache ? |
||
3707 | tls.createSessionCache(options.sessionCache) : null; |
||
3708 | |||
3709 | // create TLS connection |
||
3710 | var c = { |
||
3711 | version: {major: tls.Version.major, minor: tls.Version.minor}, |
||
3712 | entity: entity, |
||
3713 | sessionId: options.sessionId, |
||
3714 | caStore: caStore, |
||
3715 | sessionCache: sessionCache, |
||
3716 | cipherSuites: cipherSuites, |
||
3717 | connected: options.connected, |
||
3718 | virtualHost: options.virtualHost || null, |
||
3719 | verifyClient: options.verifyClient || false, |
||
3720 | verify: options.verify || function(cn, vfd, dpth, cts) {return vfd;}, |
||
3721 | getCertificate: options.getCertificate || null, |
||
3722 | getPrivateKey: options.getPrivateKey || null, |
||
3723 | getSignature: options.getSignature || null, |
||
3724 | input: forge.util.createBuffer(), |
||
3725 | tlsData: forge.util.createBuffer(), |
||
3726 | data: forge.util.createBuffer(), |
||
3727 | tlsDataReady: options.tlsDataReady, |
||
3728 | dataReady: options.dataReady, |
||
3729 | heartbeatReceived: options.heartbeatReceived, |
||
3730 | closed: options.closed, |
||
3731 | error: function(c, ex) { |
||
3732 | // set origin if not set |
||
3733 | ex.origin = ex.origin || |
||
3734 | ((c.entity === tls.ConnectionEnd.client) ? 'client' : 'server'); |
||
3735 | |||
3736 | // send TLS alert |
||
3737 | if(ex.send) { |
||
3738 | tls.queue(c, tls.createAlert(c, ex.alert)); |
||
3739 | tls.flush(c); |
||
3740 | } |
||
3741 | |||
3742 | // error is fatal by default |
||
3743 | var fatal = (ex.fatal !== false); |
||
3744 | if(fatal) { |
||
3745 | // set fail flag |
||
3746 | c.fail = true; |
||
3747 | } |
||
3748 | |||
3749 | // call error handler first |
||
3750 | options.error(c, ex); |
||
3751 | |||
3752 | if(fatal) { |
||
3753 | // fatal error, close connection, do not clear fail |
||
3754 | c.close(false); |
||
3755 | } |
||
3756 | }, |
||
3757 | deflate: options.deflate || null, |
||
3758 | inflate: options.inflate || null |
||
3759 | }; |
||
3760 | |||
3761 | /** |
||
3762 | * Resets a closed TLS connection for reuse. Called in c.close(). |
||
3763 | * |
||
3764 | * @param clearFail true to clear the fail flag (default: true). |
||
3765 | */ |
||
3766 | c.reset = function(clearFail) { |
||
3767 | c.version = {major: tls.Version.major, minor: tls.Version.minor}; |
||
3768 | c.record = null; |
||
3769 | c.session = null; |
||
3770 | c.peerCertificate = null; |
||
3771 | c.state = { |
||
3772 | pending: null, |
||
3773 | current: null |
||
3774 | }; |
||
3775 | c.expect = (c.entity === tls.ConnectionEnd.client) ? SHE : CHE; |
||
3776 | c.fragmented = null; |
||
3777 | c.records = []; |
||
3778 | c.open = false; |
||
3779 | c.handshakes = 0; |
||
3780 | c.handshaking = false; |
||
3781 | c.isConnected = false; |
||
3782 | c.fail = !(clearFail || typeof(clearFail) === 'undefined'); |
||
3783 | c.input.clear(); |
||
3784 | c.tlsData.clear(); |
||
3785 | c.data.clear(); |
||
3786 | c.state.current = tls.createConnectionState(c); |
||
3787 | }; |
||
3788 | |||
3789 | // do initial reset of connection |
||
3790 | c.reset(); |
||
3791 | |||
3792 | /** |
||
3793 | * Updates the current TLS engine state based on the given record. |
||
3794 | * |
||
3795 | * @param c the TLS connection. |
||
3796 | * @param record the TLS record to act on. |
||
3797 | */ |
||
3798 | var _update = function(c, record) { |
||
3799 | // get record handler (align type in table by subtracting lowest) |
||
3800 | var aligned = record.type - tls.ContentType.change_cipher_spec; |
||
3801 | var handlers = ctTable[c.entity][c.expect]; |
||
3802 | if(aligned in handlers) { |
||
3803 | handlers[aligned](c, record); |
||
3804 | } else { |
||
3805 | // unexpected record |
||
3806 | tls.handleUnexpected(c, record); |
||
3807 | } |
||
3808 | }; |
||
3809 | |||
3810 | /** |
||
3811 | * Reads the record header and initializes the next record on the given |
||
3812 | * connection. |
||
3813 | * |
||
3814 | * @param c the TLS connection with the next record. |
||
3815 | * |
||
3816 | * @return 0 if the input data could be processed, otherwise the |
||
3817 | * number of bytes required for data to be processed. |
||
3818 | */ |
||
3819 | var _readRecordHeader = function(c) { |
||
3820 | var rval = 0; |
||
3821 | |||
3822 | // get input buffer and its length |
||
3823 | var b = c.input; |
||
3824 | var len = b.length(); |
||
3825 | |||
3826 | // need at least 5 bytes to initialize a record |
||
3827 | if(len < 5) { |
||
3828 | rval = 5 - len; |
||
3829 | } else { |
||
3830 | // enough bytes for header |
||
3831 | // initialize record |
||
3832 | c.record = { |
||
3833 | type: b.getByte(), |
||
3834 | version: { |
||
3835 | major: b.getByte(), |
||
3836 | minor: b.getByte() |
||
3837 | }, |
||
3838 | length: b.getInt16(), |
||
3839 | fragment: forge.util.createBuffer(), |
||
3840 | ready: false |
||
3841 | }; |
||
3842 | |||
3843 | // check record version |
||
3844 | var compatibleVersion = (c.record.version.major === c.version.major); |
||
3845 | if(compatibleVersion && c.session && c.session.version) { |
||
3846 | // session version already set, require same minor version |
||
3847 | compatibleVersion = (c.record.version.minor === c.version.minor); |
||
3848 | } |
||
3849 | if(!compatibleVersion) { |
||
3850 | c.error(c, { |
||
3851 | message: 'Incompatible TLS version.', |
||
3852 | send: true, |
||
3853 | alert: { |
||
3854 | level: tls.Alert.Level.fatal, |
||
3855 | description: tls.Alert.Description.protocol_version |
||
3856 | } |
||
3857 | }); |
||
3858 | } |
||
3859 | } |
||
3860 | |||
3861 | return rval; |
||
3862 | }; |
||
3863 | |||
3864 | /** |
||
3865 | * Reads the next record's contents and appends its message to any |
||
3866 | * previously fragmented message. |
||
3867 | * |
||
3868 | * @param c the TLS connection with the next record. |
||
3869 | * |
||
3870 | * @return 0 if the input data could be processed, otherwise the |
||
3871 | * number of bytes required for data to be processed. |
||
3872 | */ |
||
3873 | var _readRecord = function(c) { |
||
3874 | var rval = 0; |
||
3875 | |||
3876 | // ensure there is enough input data to get the entire record |
||
3877 | var b = c.input; |
||
3878 | var len = b.length(); |
||
3879 | if(len < c.record.length) { |
||
3880 | // not enough data yet, return how much is required |
||
3881 | rval = c.record.length - len; |
||
3882 | } else { |
||
3883 | // there is enough data to parse the pending record |
||
3884 | // fill record fragment and compact input buffer |
||
3885 | c.record.fragment.putBytes(b.getBytes(c.record.length)); |
||
3886 | b.compact(); |
||
3887 | |||
3888 | // update record using current read state |
||
3889 | var s = c.state.current.read; |
||
3890 | if(s.update(c, c.record)) { |
||
3891 | // see if there is a previously fragmented message that the |
||
3892 | // new record's message fragment should be appended to |
||
3893 | if(c.fragmented !== null) { |
||
3894 | // if the record type matches a previously fragmented |
||
3895 | // record, append the record fragment to it |
||
3896 | if(c.fragmented.type === c.record.type) { |
||
3897 | // concatenate record fragments |
||
3898 | c.fragmented.fragment.putBuffer(c.record.fragment); |
||
3899 | c.record = c.fragmented; |
||
3900 | } else { |
||
3901 | // error, invalid fragmented record |
||
3902 | c.error(c, { |
||
3903 | message: 'Invalid fragmented record.', |
||
3904 | send: true, |
||
3905 | alert: { |
||
3906 | level: tls.Alert.Level.fatal, |
||
3907 | description: |
||
3908 | tls.Alert.Description.unexpected_message |
||
3909 | } |
||
3910 | }); |
||
3911 | } |
||
3912 | } |
||
3913 | |||
3914 | // record is now ready |
||
3915 | c.record.ready = true; |
||
3916 | } |
||
3917 | } |
||
3918 | |||
3919 | return rval; |
||
3920 | }; |
||
3921 | |||
3922 | /** |
||
3923 | * Performs a handshake using the TLS Handshake Protocol, as a client. |
||
3924 | * |
||
3925 | * This method should only be called if the connection is in client mode. |
||
3926 | * |
||
3927 | * @param sessionId the session ID to use, null to start a new one. |
||
3928 | */ |
||
3929 | c.handshake = function(sessionId) { |
||
3930 | // error to call this in non-client mode |
||
3931 | if(c.entity !== tls.ConnectionEnd.client) { |
||
3932 | // not fatal error |
||
3933 | c.error(c, { |
||
3934 | message: 'Cannot initiate handshake as a server.', |
||
3935 | fatal: false |
||
3936 | }); |
||
3937 | } else if(c.handshaking) { |
||
3938 | // handshake is already in progress, fail but not fatal error |
||
3939 | c.error(c, { |
||
3940 | message: 'Handshake already in progress.', |
||
3941 | fatal: false |
||
3942 | }); |
||
3943 | } else { |
||
3944 | // clear fail flag on reuse |
||
3945 | if(c.fail && !c.open && c.handshakes === 0) { |
||
3946 | c.fail = false; |
||
3947 | } |
||
3948 | |||
3949 | // now handshaking |
||
3950 | c.handshaking = true; |
||
3951 | |||
3952 | // default to blank (new session) |
||
3953 | sessionId = sessionId || ''; |
||
3954 | |||
3955 | // if a session ID was specified, try to find it in the cache |
||
3956 | var session = null; |
||
3957 | if(sessionId.length > 0) { |
||
3958 | if(c.sessionCache) { |
||
3959 | session = c.sessionCache.getSession(sessionId); |
||
3960 | } |
||
3961 | |||
3962 | // matching session not found in cache, clear session ID |
||
3963 | if(session === null) { |
||
3964 | sessionId = ''; |
||
3965 | } |
||
3966 | } |
||
3967 | |||
3968 | // no session given, grab a session from the cache, if available |
||
3969 | if(sessionId.length === 0 && c.sessionCache) { |
||
3970 | session = c.sessionCache.getSession(); |
||
3971 | if(session !== null) { |
||
3972 | sessionId = session.id; |
||
3973 | } |
||
3974 | } |
||
3975 | |||
3976 | // set up session |
||
3977 | c.session = { |
||
3978 | id: sessionId, |
||
3979 | version: null, |
||
3980 | cipherSuite: null, |
||
3981 | compressionMethod: null, |
||
3982 | serverCertificate: null, |
||
3983 | certificateRequest: null, |
||
3984 | clientCertificate: null, |
||
3985 | sp: {}, |
||
3986 | md5: forge.md.md5.create(), |
||
3987 | sha1: forge.md.sha1.create() |
||
3988 | }; |
||
3989 | |||
3990 | // use existing session information |
||
3991 | if(session) { |
||
3992 | // only update version on connection, session version not yet set |
||
3993 | c.version = session.version; |
||
3994 | c.session.sp = session.sp; |
||
3995 | } |
||
3996 | |||
3997 | // generate new client random |
||
3998 | c.session.sp.client_random = tls.createRandom().getBytes(); |
||
3999 | |||
4000 | // connection now open |
||
4001 | c.open = true; |
||
4002 | |||
4003 | // send hello |
||
4004 | tls.queue(c, tls.createRecord(c, { |
||
4005 | type: tls.ContentType.handshake, |
||
4006 | data: tls.createClientHello(c) |
||
4007 | })); |
||
4008 | tls.flush(c); |
||
4009 | } |
||
4010 | }; |
||
4011 | |||
4012 | /** |
||
4013 | * Called when TLS protocol data has been received from somewhere and should |
||
4014 | * be processed by the TLS engine. |
||
4015 | * |
||
4016 | * @param data the TLS protocol data, as a string, to process. |
||
4017 | * |
||
4018 | * @return 0 if the data could be processed, otherwise the number of bytes |
||
4019 | * required for data to be processed. |
||
4020 | */ |
||
4021 | c.process = function(data) { |
||
4022 | var rval = 0; |
||
4023 | |||
4024 | // buffer input data |
||
4025 | if(data) { |
||
4026 | c.input.putBytes(data); |
||
4027 | } |
||
4028 | |||
4029 | // process next record if no failure, process will be called after |
||
4030 | // each record is handled (since handling can be asynchronous) |
||
4031 | if(!c.fail) { |
||
4032 | // reset record if ready and now empty |
||
4033 | if(c.record !== null && |
||
4034 | c.record.ready && c.record.fragment.isEmpty()) { |
||
4035 | c.record = null; |
||
4036 | } |
||
4037 | |||
4038 | // if there is no pending record, try to read record header |
||
4039 | if(c.record === null) { |
||
4040 | rval = _readRecordHeader(c); |
||
4041 | } |
||
4042 | |||
4043 | // read the next record (if record not yet ready) |
||
4044 | if(!c.fail && c.record !== null && !c.record.ready) { |
||
4045 | rval = _readRecord(c); |
||
4046 | } |
||
4047 | |||
4048 | // record ready to be handled, update engine state |
||
4049 | if(!c.fail && c.record !== null && c.record.ready) { |
||
4050 | _update(c, c.record); |
||
4051 | } |
||
4052 | } |
||
4053 | |||
4054 | return rval; |
||
4055 | }; |
||
4056 | |||
4057 | /** |
||
4058 | * Requests that application data be packaged into a TLS record. The |
||
4059 | * tlsDataReady handler will be called when the TLS record(s) have been |
||
4060 | * prepared. |
||
4061 | * |
||
4062 | * @param data the application data, as a raw 'binary' encoded string, to |
||
4063 | * be sent; to send utf-16/utf-8 string data, use the return value |
||
4064 | * of util.encodeUtf8(str). |
||
4065 | * |
||
4066 | * @return true on success, false on failure. |
||
4067 | */ |
||
4068 | c.prepare = function(data) { |
||
4069 | tls.queue(c, tls.createRecord(c, { |
||
4070 | type: tls.ContentType.application_data, |
||
4071 | data: forge.util.createBuffer(data) |
||
4072 | })); |
||
4073 | return tls.flush(c); |
||
4074 | }; |
||
4075 | |||
4076 | /** |
||
4077 | * Requests that a heartbeat request be packaged into a TLS record for |
||
4078 | * transmission. The tlsDataReady handler will be called when TLS record(s) |
||
4079 | * have been prepared. |
||
4080 | * |
||
4081 | * When a heartbeat response has been received, the heartbeatReceived |
||
4082 | * handler will be called with the matching payload. This handler can |
||
4083 | * be used to clear a retransmission timer, etc. |
||
4084 | * |
||
4085 | * @param payload the heartbeat data to send as the payload in the message. |
||
4086 | * @param [payloadLength] the payload length to use, defaults to the |
||
4087 | * actual payload length. |
||
4088 | * |
||
4089 | * @return true on success, false on failure. |
||
4090 | */ |
||
4091 | c.prepareHeartbeatRequest = function(payload, payloadLength) { |
||
4092 | if(payload instanceof forge.util.ByteBuffer) { |
||
4093 | payload = payload.bytes(); |
||
4094 | } |
||
4095 | if(typeof payloadLength === 'undefined') { |
||
4096 | payloadLength = payload.length; |
||
4097 | } |
||
4098 | c.expectedHeartbeatPayload = payload; |
||
4099 | tls.queue(c, tls.createRecord(c, { |
||
4100 | type: tls.ContentType.heartbeat, |
||
4101 | data: tls.createHeartbeat( |
||
4102 | tls.HeartbeatMessageType.heartbeat_request, payload, payloadLength) |
||
4103 | })); |
||
4104 | return tls.flush(c); |
||
4105 | }; |
||
4106 | |||
4107 | /** |
||
4108 | * Closes the connection (sends a close_notify alert). |
||
4109 | * |
||
4110 | * @param clearFail true to clear the fail flag (default: true). |
||
4111 | */ |
||
4112 | c.close = function(clearFail) { |
||
4113 | // save session if connection didn't fail |
||
4114 | if(!c.fail && c.sessionCache && c.session) { |
||
4115 | // only need to preserve session ID, version, and security params |
||
4116 | var session = { |
||
4117 | id: c.session.id, |
||
4118 | version: c.session.version, |
||
4119 | sp: c.session.sp |
||
4120 | }; |
||
4121 | session.sp.keys = null; |
||
4122 | c.sessionCache.setSession(session.id, session); |
||
4123 | } |
||
4124 | |||
4125 | if(c.open) { |
||
4126 | // connection no longer open, clear input |
||
4127 | c.open = false; |
||
4128 | c.input.clear(); |
||
4129 | |||
4130 | // if connected or handshaking, send an alert |
||
4131 | if(c.isConnected || c.handshaking) { |
||
4132 | c.isConnected = c.handshaking = false; |
||
4133 | |||
4134 | // send close_notify alert |
||
4135 | tls.queue(c, tls.createAlert(c, { |
||
4136 | level: tls.Alert.Level.warning, |
||
4137 | description: tls.Alert.Description.close_notify |
||
4138 | })); |
||
4139 | tls.flush(c); |
||
4140 | } |
||
4141 | |||
4142 | // call handler |
||
4143 | c.closed(c); |
||
4144 | } |
||
4145 | |||
4146 | // reset TLS connection, do not clear fail flag |
||
4147 | c.reset(clearFail); |
||
4148 | }; |
||
4149 | |||
4150 | return c; |
||
4151 | }; |
||
4152 | |||
4153 | /* TLS API */ |
||
4154 | module.exports = forge.tls = forge.tls || {}; |
||
4155 | |||
4156 | // expose non-functions |
||
4157 | for(var key in tls) { |
||
4158 | if(typeof tls[key] !== 'function') { |
||
4159 | forge.tls[key] = tls[key]; |
||
4160 | } |
||
4161 | } |
||
4162 | |||
4163 | // expose prf_tls1 for testing |
||
4164 | forge.tls.prf_tls1 = prf_TLS1; |
||
4165 | |||
4166 | // expose sha1 hmac method |
||
4167 | forge.tls.hmac_sha1 = hmac_sha1; |
||
4168 | |||
4169 | // expose session cache creation |
||
4170 | forge.tls.createSessionCache = tls.createSessionCache; |
||
4171 | |||
4172 | /** |
||
4173 | * Creates a new TLS connection. This does not make any assumptions about the |
||
4174 | * transport layer that TLS is working on top of, ie: it does not assume there |
||
4175 | * is a TCP/IP connection or establish one. A TLS connection is totally |
||
4176 | * abstracted away from the layer is runs on top of, it merely establishes a |
||
4177 | * secure channel between a client" and a "server". |
||
4178 | * |
||
4179 | * A TLS connection contains 4 connection states: pending read and write, and |
||
4180 | * current read and write. |
||
4181 | * |
||
4182 | * At initialization, the current read and write states will be null. Only once |
||
4183 | * the security parameters have been set and the keys have been generated can |
||
4184 | * the pending states be converted into current states. Current states will be |
||
4185 | * updated for each record processed. |
||
4186 | * |
||
4187 | * A custom certificate verify callback may be provided to check information |
||
4188 | * like the common name on the server's certificate. It will be called for |
||
4189 | * every certificate in the chain. It has the following signature: |
||
4190 | * |
||
4191 | * variable func(c, certs, index, preVerify) |
||
4192 | * Where: |
||
4193 | * c The TLS connection |
||
4194 | * verified Set to true if certificate was verified, otherwise the alert |
||
4195 | * tls.Alert.Description for why the certificate failed. |
||
4196 | * depth The current index in the chain, where 0 is the server's cert. |
||
4197 | * certs The certificate chain, *NOTE* if the server was anonymous then |
||
4198 | * the chain will be empty. |
||
4199 | * |
||
4200 | * The function returns true on success and on failure either the appropriate |
||
4201 | * tls.Alert.Description or an object with 'alert' set to the appropriate |
||
4202 | * tls.Alert.Description and 'message' set to a custom error message. If true |
||
4203 | * is not returned then the connection will abort using, in order of |
||
4204 | * availability, first the returned alert description, second the preVerify |
||
4205 | * alert description, and lastly the default 'bad_certificate'. |
||
4206 | * |
||
4207 | * There are three callbacks that can be used to make use of client-side |
||
4208 | * certificates where each takes the TLS connection as the first parameter: |
||
4209 | * |
||
4210 | * getCertificate(conn, hint) |
||
4211 | * The second parameter is a hint as to which certificate should be |
||
4212 | * returned. If the connection entity is a client, then the hint will be |
||
4213 | * the CertificateRequest message from the server that is part of the |
||
4214 | * TLS protocol. If the connection entity is a server, then it will be |
||
4215 | * the servername list provided via an SNI extension the ClientHello, if |
||
4216 | * one was provided (empty array if not). The hint can be examined to |
||
4217 | * determine which certificate to use (advanced). Most implementations |
||
4218 | * will just return a certificate. The return value must be a |
||
4219 | * PEM-formatted certificate or an array of PEM-formatted certificates |
||
4220 | * that constitute a certificate chain, with the first in the array/chain |
||
4221 | * being the client's certificate. |
||
4222 | * getPrivateKey(conn, certificate) |
||
4223 | * The second parameter is an forge.pki X.509 certificate object that |
||
4224 | * is associated with the requested private key. The return value must |
||
4225 | * be a PEM-formatted private key. |
||
4226 | * getSignature(conn, bytes, callback) |
||
4227 | * This callback can be used instead of getPrivateKey if the private key |
||
4228 | * is not directly accessible in javascript or should not be. For |
||
4229 | * instance, a secure external web service could provide the signature |
||
4230 | * in exchange for appropriate credentials. The second parameter is a |
||
4231 | * string of bytes to be signed that are part of the TLS protocol. These |
||
4232 | * bytes are used to verify that the private key for the previously |
||
4233 | * provided client-side certificate is accessible to the client. The |
||
4234 | * callback is a function that takes 2 parameters, the TLS connection |
||
4235 | * and the RSA encrypted (signed) bytes as a string. This callback must |
||
4236 | * be called once the signature is ready. |
||
4237 | * |
||
4238 | * @param options the options for this connection: |
||
4239 | * server: true if the connection is server-side, false for client. |
||
4240 | * sessionId: a session ID to reuse, null for a new connection. |
||
4241 | * caStore: an array of certificates to trust. |
||
4242 | * sessionCache: a session cache to use. |
||
4243 | * cipherSuites: an optional array of cipher suites to use, |
||
4244 | * see tls.CipherSuites. |
||
4245 | * connected: function(conn) called when the first handshake completes. |
||
4246 | * virtualHost: the virtual server name to use in a TLS SNI extension. |
||
4247 | * verifyClient: true to require a client certificate in server mode, |
||
4248 | * 'optional' to request one, false not to (default: false). |
||
4249 | * verify: a handler used to custom verify certificates in the chain. |
||
4250 | * getCertificate: an optional callback used to get a certificate or |
||
4251 | * a chain of certificates (as an array). |
||
4252 | * getPrivateKey: an optional callback used to get a private key. |
||
4253 | * getSignature: an optional callback used to get a signature. |
||
4254 | * tlsDataReady: function(conn) called when TLS protocol data has been |
||
4255 | * prepared and is ready to be used (typically sent over a socket |
||
4256 | * connection to its destination), read from conn.tlsData buffer. |
||
4257 | * dataReady: function(conn) called when application data has |
||
4258 | * been parsed from a TLS record and should be consumed by the |
||
4259 | * application, read from conn.data buffer. |
||
4260 | * closed: function(conn) called when the connection has been closed. |
||
4261 | * error: function(conn, error) called when there was an error. |
||
4262 | * deflate: function(inBytes) if provided, will deflate TLS records using |
||
4263 | * the deflate algorithm if the server supports it. |
||
4264 | * inflate: function(inBytes) if provided, will inflate TLS records using |
||
4265 | * the deflate algorithm if the server supports it. |
||
4266 | * |
||
4267 | * @return the new TLS connection. |
||
4268 | */ |
||
4269 | forge.tls.createConnection = tls.createConnection; |