/js/lib/Socket.IO-node/support/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/tls/SSLConnectionState.as
ActionScript | 171 lines | 114 code | 23 blank | 34 comment | 24 complexity | 02301bb3725990f16ecb8c67e1fb5693 MD5 | raw file
1/** 2 * TLSConnectionState 3 * 4 * This class encapsulates the read or write state of a TLS connection, 5 * and implementes the encrypting and hashing of packets. 6 * Copyright (c) 2007 Henri Torgemane 7 * 8 * See LICENSE.txt for full license information. 9 */ 10package com.hurlant.crypto.tls { 11 import flash.utils.IDataInput; 12 import flash.utils.ByteArray; 13 import com.hurlant.crypto.hash.MD5; 14 import com.hurlant.crypto.hash.MAC; 15 import com.hurlant.crypto.hash.IHash; 16 import com.hurlant.crypto.symmetric.ICipher; 17 import com.hurlant.crypto.symmetric.IVMode; 18 import com.hurlant.util.Hex; 19 import com.hurlant.util.ArrayUtil; 20 21 public class SSLConnectionState implements IConnectionState { 22 23 // compression state 24 25 // cipher state 26 private var bulkCipher:uint; 27 private var cipherType:uint; 28 private var CIPHER_key:ByteArray; 29 private var CIPHER_IV:ByteArray; 30 private var cipher:ICipher; 31 private var ivmode:IVMode; 32 33 // mac secret 34 private var macAlgorithm:uint; 35 private var MAC_write_secret:ByteArray; 36 private var mac:MAC; 37 38 // sequence number. uint64 39 40 private var seq_lo:uint = 0x0; 41 private var seq_hi:uint = 0x0; 42 43 public function SSLConnectionState( 44 bulkCipher:uint=0, cipherType:uint=0, macAlgorithm:uint=0, 45 mac_enc:ByteArray=null, key:ByteArray=null, IV:ByteArray=null) { 46 this.bulkCipher = bulkCipher; 47 this.cipherType = cipherType; 48 this.macAlgorithm = macAlgorithm; 49 MAC_write_secret = mac_enc; 50 mac = MACs.getMAC(macAlgorithm); 51 52 CIPHER_key = key; 53 CIPHER_IV = IV; 54 cipher = BulkCiphers.getCipher(bulkCipher, key, 0x0300); 55 if (cipher is IVMode) { 56 ivmode = cipher as IVMode; 57 ivmode.IV = IV; 58 } 59 60 } 61 62 public function decrypt(type:uint, length:uint, p:ByteArray):ByteArray { 63 // decompression is a nop. 64 65 if (cipherType == BulkCiphers.STREAM_CIPHER) { 66 if (bulkCipher == BulkCiphers.NULL) { 67 // no-op 68 } else { 69 cipher.decrypt(p); 70 } 71 } else { 72 p.position = 0; 73 // block cipher 74 if (bulkCipher == BulkCiphers.NULL) { 75 76 } else { 77 var nextIV:ByteArray = new ByteArray; 78 nextIV.writeBytes(p, p.length-CIPHER_IV.length, CIPHER_IV.length); 79 p.position = 0; 80 cipher.decrypt(p); 81 82 CIPHER_IV = nextIV; 83 ivmode.IV = nextIV; 84 } 85 } 86 87 if (macAlgorithm!=MACs.NULL) { 88 // there will be CTX delay here as well, 89 // I should probably optmize the hell out of it 90 var data:ByteArray = new ByteArray; 91 var len:uint = p.length - mac.getHashSize(); 92 data.writeUnsignedInt(seq_hi); 93 data.writeUnsignedInt(seq_lo); 94 95 data.writeByte(type); 96 data.writeShort(len); 97 if (len!=0) { 98 data.writeBytes(p, 0, len); 99 } 100 var mac_enc:ByteArray = mac.compute(MAC_write_secret, data); 101 // compare "mac" with the last X bytes of p. 102 var mac_received:ByteArray = new ByteArray; 103 mac_received.writeBytes(p, len, mac.getHashSize()); 104 if (ArrayUtil.equals(mac_enc, mac_received)) { 105 // happy happy joy joy 106 } else { 107 throw new TLSError("Bad Mac Data", TLSError.bad_record_mac); 108 } 109 p.length = len; 110 p.position = 0; 111 } 112 // increment seq 113 seq_lo++; 114 if (seq_lo==0) seq_hi++; 115 return p; 116 } 117 public function encrypt(type:uint, p:ByteArray):ByteArray { 118 var mac_enc:ByteArray = null; 119 if (macAlgorithm!=MACs.NULL) { 120 var data:ByteArray = new ByteArray; 121 // data.writeUnsignedInt(seq); 122 123 // Sequence 124 data.writeUnsignedInt(seq_hi); 125 data.writeUnsignedInt(seq_lo); 126 127 // Type 128 data.writeByte(type); 129 130 // Length 131 data.writeShort(p.length); 132 133 // The data 134 if (p.length!=0) { 135 data.writeBytes(p); 136 } 137 138 // trace("data for the MAC: " + Hex.fromArray(data)); 139 mac_enc = mac.compute(MAC_write_secret, data); 140 // trace("MAC: " + Hex.fromArray( mac_enc )); 141 p.position = p.length; 142 p.writeBytes(mac_enc); 143 } 144 145 // trace("Record to encrypt: " + Hex.fromArray(p)); 146 147 p.position = 0; 148 if (cipherType == BulkCiphers.STREAM_CIPHER) { 149 // stream cipher 150 if (bulkCipher == BulkCiphers.NULL) { 151 // no-op 152 } else { 153 cipher.encrypt(p); 154 } 155 } else { 156 // block cipher 157 cipher.encrypt(p); 158 // adjust IV 159 var nextIV:ByteArray = new ByteArray; 160 nextIV.writeBytes(p, p.length-CIPHER_IV.length, CIPHER_IV.length); 161 CIPHER_IV = nextIV; 162 ivmode.IV = nextIV; 163 } 164 // increment seq 165 seq_lo++; 166 if (seq_lo==0) seq_hi++; 167 return p; 168 } 169 170 } 171}