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
8 * See LICENSE.txt for full license information.
10 package 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;
21 public class SSLConnectionState implements IConnectionState {
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;
34 private var macAlgorithm:uint;
35 private var MAC_write_secret:ByteArray;
38 // sequence number. uint64
40 private var seq_lo:uint = 0x0;
41 private var seq_hi:uint = 0x0;
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);
54 cipher = BulkCiphers.getCipher(bulkCipher, key, 0x0300);
55 if (cipher is IVMode) {
56 ivmode = cipher as IVMode;
62 public function decrypt(type:uint, length:uint, p:ByteArray):ByteArray {
63 // decompression is a nop.
65 if (cipherType == BulkCiphers.STREAM_CIPHER) {
66 if (bulkCipher == BulkCiphers.NULL) {
74 if (bulkCipher == BulkCiphers.NULL) {
77 var nextIV:ByteArray = new ByteArray;
78 nextIV.writeBytes(p, p.length-CIPHER_IV.length, CIPHER_IV.length);
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);
98 data.writeBytes(p, 0, len);
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
107 throw new TLSError("Bad Mac Data", TLSError.bad_record_mac);
114 if (seq_lo==0) seq_hi++;
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);
124 data.writeUnsignedInt(seq_hi);
125 data.writeUnsignedInt(seq_lo);
128 data.writeByte(type);
131 data.writeShort(p.length);
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);
145 // trace("Record to encrypt: " + Hex.fromArray(p));
148 if (cipherType == BulkCiphers.STREAM_CIPHER) {
150 if (bulkCipher == BulkCiphers.NULL) {
159 var nextIV:ByteArray = new ByteArray;
160 nextIV.writeBytes(p, p.length-CIPHER_IV.length, CIPHER_IV.length);
166 if (seq_lo==0) seq_hi++;