Initial commit from SVN.
This commit is contained in:
32
TLS Test/src/com/de22/tls/TlsApp.java
Normal file
32
TLS Test/src/com/de22/tls/TlsApp.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package com.de22.tls;
|
||||
|
||||
import java.security.KeyStore;
|
||||
|
||||
/**
|
||||
* The pairing of a keystore and the domain name it applies to.
|
||||
*/
|
||||
public class TlsApp {
|
||||
private KeyStore keyStore;
|
||||
private String domain;
|
||||
/**
|
||||
* TlsApp constructor.
|
||||
* @param domain
|
||||
* @param keyStore
|
||||
*/
|
||||
public TlsApp(String domain, KeyStore keyStore) {
|
||||
this.domain = domain;
|
||||
this.keyStore = keyStore;
|
||||
}//TlsApp()//
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getDomain() {
|
||||
return domain;
|
||||
}//getDomain()//
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public KeyStore getKeyStore() {
|
||||
return keyStore;
|
||||
}//getKeyStore()//
|
||||
}//TlsApp//
|
||||
688
TLS Test/src/com/de22/tls/TlsEngine.java
Normal file
688
TLS Test/src/com/de22/tls/TlsEngine.java
Normal file
@@ -0,0 +1,688 @@
|
||||
package com.de22.tls;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.io.StreamSupport;
|
||||
import com.common.security.IAsymmetricAlgorithm;
|
||||
import com.common.security.IHashAlgorithm;
|
||||
import com.common.security.ISymmetricAlgorithm;
|
||||
import com.common.util.StreamBuffer;
|
||||
|
||||
public class TlsEngine {
|
||||
//The identifiers for the single byte handshake type.//
|
||||
private static final int HANDSHAKE_TYPE_HELLO_REQUEST = 0; //Sent by the server at any time, indicating the handshake should begin anew.//
|
||||
private static final int HANDSHAKE_TYPE_CLIENT_HELLO = 1; //Sent by the client to initiate the handshake.//
|
||||
private static final int HANDSHAKE_TYPE_SERVER_HELLO = 2;
|
||||
private static final int HANDSHAKE_TYPE_CERTIFICATE = 11;
|
||||
private static final int HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE = 12;
|
||||
private static final int HANDSHAKE_TYPE_CERTIFICATE_REQUEST = 13;
|
||||
private static final int HANDSHAKE_TYPE_SERVER_HELLO_DONE = 14;
|
||||
private static final int HANDSHAKE_TYPE_CERTIFICATE_VERIFY = 15;
|
||||
private static final int HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE = 16;
|
||||
private static final int HANDSHAKE_TYPE_FINISHED = 20;
|
||||
|
||||
private static final int CIPHER_SUITE_TLS_NULL_WITH_NULL_NULL = 0x0000; //{ 0x00,0x00 };
|
||||
|
||||
private static final int CIPHER_SUITE_TLS_RSA_WITH_NULL_MD5 = 0x0001; //{ 0x00,0x01 };
|
||||
private static final int CIPHER_SUITE_TLS_RSA_WITH_NULL_SHA = 0x0002; //{ 0x00,0x02 };
|
||||
private static final int CIPHER_SUITE_TLS_RSA_WITH_NULL_SHA256 = 0x003B; //{ 0x00,0x3B };
|
||||
private static final int CIPHER_SUITE_TLS_RSA_WITH_RC4_128_MD5 = 0x0004; //{ 0x00,0x04 };
|
||||
private static final int CIPHER_SUITE_TLS_RSA_WITH_RC4_128_SHA = 0x0005; //{ 0x00,0x05 };
|
||||
private static final int CIPHER_SUITE_TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A; //{ 0x00,0x0A };
|
||||
private static final int CIPHER_SUITE_TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F; //{ 0x00,0x2F };
|
||||
private static final int CIPHER_SUITE_TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035; //{ 0x00,0x35 };
|
||||
private static final int CIPHER_SUITE_TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C; //{ 0x00,0x3C };
|
||||
private static final int CIPHER_SUITE_TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D; //{ 0x00,0x3D };
|
||||
|
||||
private static final int CIPHER_SUITE_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D; //{ 0x00,0x0D };
|
||||
private static final int CIPHER_SUITE_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010; //{ 0x00,0x10 };
|
||||
private static final int CIPHER_SUITE_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013; //{ 0x00,0x13 };
|
||||
private static final int CIPHER_SUITE_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016; //{ 0x00,0x16 };
|
||||
private static final int CIPHER_SUITE_TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030; //{ 0x00,0x30 };
|
||||
private static final int CIPHER_SUITE_TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031; //{ 0x00,0x31 };
|
||||
private static final int CIPHER_SUITE_TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032; //{ 0x00,0x32 };
|
||||
private static final int CIPHER_SUITE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033; //{ 0x00,0x33 };
|
||||
private static final int CIPHER_SUITE_TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036; //{ 0x00,0x36 };
|
||||
private static final int CIPHER_SUITE_TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037; //{ 0x00,0x37 };
|
||||
private static final int CIPHER_SUITE_TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038; //{ 0x00,0x38 };
|
||||
private static final int CIPHER_SUITE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039; //{ 0x00,0x39 };
|
||||
private static final int CIPHER_SUITE_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E; //{ 0x00,0x3E };
|
||||
private static final int CIPHER_SUITE_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F; //{ 0x00,0x3F };
|
||||
private static final int CIPHER_SUITE_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040; //{ 0x00,0x40 };
|
||||
private static final int CIPHER_SUITE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067; //{ 0x00,0x67 };
|
||||
private static final int CIPHER_SUITE_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068; //{ 0x00,0x68 };
|
||||
private static final int CIPHER_SUITE_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069; //{ 0x00,0x69 };
|
||||
private static final int CIPHER_SUITE_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A; //{ 0x00,0x6A };
|
||||
private static final int CIPHER_SUITE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B; //{ 0x00,0x6B };
|
||||
|
||||
//Anonymous Algorithms//
|
||||
private static final int CIPHER_SUITE_TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018; //{ 0x00,0x18 };
|
||||
private static final int CIPHER_SUITE_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B; //{ 0x00,0x1B };
|
||||
private static final int CIPHER_SUITE_TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034; //{ 0x00,0x34 };
|
||||
private static final int CIPHER_SUITE_TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A; //{ 0x00,0x3A };
|
||||
private static final int CIPHER_SUITE_TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C; //{ 0x00,0x6C };
|
||||
private static final int CIPHER_SUITE_TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D; //{ 0x00,0x6D };
|
||||
|
||||
//RFC 5469 - DES & IDEA Cipher Suites//
|
||||
private static final int TLS_RSA_WITH_IDEA_CBC_SHA = 0x0007; //{ 0x00,0x07 }
|
||||
private static final int TLS_RSA_WITH_DES_CBC_SHA = 0x0009; //{ 0x00,0x09 };
|
||||
private static final int TLS_DH_DSS_WITH_DES_CBC_SHA = 0x000C; //{ 0x00,0x0C };
|
||||
private static final int TLS_DH_RSA_WITH_DES_CBC_SHA = 0x000F; //{ 0x00,0x0F };
|
||||
private static final int TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x0012; //{ 0x00,0x12 };
|
||||
private static final int TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x0015; //{ 0x00,0x15 };
|
||||
private static final int TLS_DH_anon_WITH_DES_CBC_SHA = 0x001A; //{ 0x00,0x1A };
|
||||
|
||||
//RFC 2712 - Kerberos Cipher Suites//
|
||||
private static final int TLS_KRB5_WITH_DES_CBC_SHA = 0x001E; //{ 0x00,0x1E };
|
||||
private static final int TLS_KRB5_WITH_3DES_EDE_CBC_SHA = 0x001F; //{ 0x00,0x1F };
|
||||
private static final int TLS_KRB5_WITH_RC4_128_SHA = 0x0020; //{ 0x00,0x20 };
|
||||
private static final int TLS_KRB5_WITH_IDEA_CBC_SHA = 0x0021; //{ 0x00,0x21 };
|
||||
private static final int TLS_KRB5_WITH_DES_CBC_MD5 = 0x0022; //{ 0x00,0x22 };
|
||||
private static final int TLS_KRB5_WITH_3DES_EDE_CBC_MD5 = 0x0023; //{ 0x00,0x23 };
|
||||
private static final int TLS_KRB5_WITH_RC4_128_MD5 = 0x0024; //{ 0x00,0x24 };
|
||||
private static final int TLS_KRB5_WITH_IDEA_CBC_MD5 = 0x0025; //{ 0x00,0x25 };
|
||||
|
||||
private static final int TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA = 0x0026; //{ 0x00,0x26 };
|
||||
private static final int TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA = 0x0027; //{ 0x00,0x27 };
|
||||
private static final int TLS_KRB5_EXPORT_WITH_RC4_40_SHA = 0x0028; //{ 0x00,0x28 };
|
||||
private static final int TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 = 0x0029; //{ 0x00,0x29 };
|
||||
private static final int TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 = 0x002A; //{ 0x00,0x2A };
|
||||
private static final int TLS_KRB5_EXPORT_WITH_RC4_40_MD5 = 0x002B; //{ 0x00,0x2B };
|
||||
|
||||
//RFC 4132 - Camellia Cipher Suites//
|
||||
private static final int TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0041; //{ 0x00,0x41 };
|
||||
private static final int TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0042; //{ 0x00,0x42 };
|
||||
private static final int TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0043; //{ 0x00,0x43 };
|
||||
private static final int TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0044; //{ 0x00,0x44 };
|
||||
private static final int TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0045; //{ 0x00,0x45 };
|
||||
private static final int TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA = 0x0046; //{ 0x00,0x46 };
|
||||
|
||||
private static final int TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0084; //{ 0x00,0x84 };
|
||||
private static final int TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0085; //{ 0x00,0x85 };
|
||||
private static final int TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0086; //{ 0x00,0x86 };
|
||||
private static final int TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0087; //{ 0x00,0x87 };
|
||||
private static final int TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0088; //{ 0x00,0x88 };
|
||||
private static final int TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA = 0x0089; //{ 0x00,0x89 };
|
||||
|
||||
//RFC 4162 - SEED Cipher Suites
|
||||
private static final int TLS_RSA_WITH_SEED_CBC_SHA = 0x0096; //{ 0x00, 0x96};
|
||||
private static final int TLS_DH_DSS_WITH_SEED_CBC_SHA = 0x0097; //{ 0x00, 0x97};
|
||||
private static final int TLS_DH_RSA_WITH_SEED_CBC_SHA = 0x0098; //{ 0x00, 0x98};
|
||||
private static final int TLS_DHE_DSS_WITH_SEED_CBC_SHA = 0x0099; //{ 0x00, 0x99};
|
||||
private static final int TLS_DHE_RSA_WITH_SEED_CBC_SHA = 0x009A; //{ 0x00, 0x9A};
|
||||
private static final int TLS_DH_anon_WITH_SEED_CBC_SHA = 0x009B; //{ 0x00, 0x9B};
|
||||
|
||||
//RFC 5288 - AES Galois Counter Mode (GCM) Cipher Suites
|
||||
private static final int TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C; //{0x00,0x9C}
|
||||
private static final int TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D; //{0x00,0x9D}
|
||||
private static final int TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E; //{0x00,0x9E}
|
||||
private static final int TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F; //{0x00,0x9F}
|
||||
private static final int TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0; //{0x00,0xA0}
|
||||
private static final int TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1; //{0x00,0xA1}
|
||||
private static final int TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2; //{0x00,0xA2}
|
||||
private static final int TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3; //{0x00,0xA3}
|
||||
private static final int TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4; //{0x00,0xA4}
|
||||
private static final int TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5; //{0x00,0xA5}
|
||||
private static final int TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6; //{0x00,0xA6}
|
||||
private static final int TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7; //{0x00,0xA7}
|
||||
|
||||
//RFC 5487 - Pre-Shared Key Cipher Suites w/ SHA-256/384 & AES Galois Counter Mode
|
||||
private static final int TLS_PSK_WITH_AES_128_GCM_SHA256 = 0x00A8; //{0x00,0xA8};
|
||||
private static final int TLS_PSK_WITH_AES_256_GCM_SHA384 = 0x00A9; //{0x00,0xA9};
|
||||
private static final int TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AA; //{0x00,0xAA};
|
||||
private static final int TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00AB; //{0x00,0xAB};
|
||||
private static final int TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 = 0x00AC; //{0x00,0xAC};
|
||||
private static final int TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 = 0x00AD; //{0x00,0xAD};
|
||||
private static final int TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE; //{0x00,0xAE};
|
||||
private static final int TLS_PSK_WITH_AES_256_CBC_SHA384 = 0x00AF; //{0x00,0xAF};
|
||||
private static final int TLS_PSK_WITH_NULL_SHA256 = 0x00B0; //{0x00,0xB0};
|
||||
private static final int TLS_PSK_WITH_NULL_SHA384 = 0x00B1; //{0x00,0xB1};
|
||||
private static final int TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0x00B2; //{0x00,0xB2};
|
||||
private static final int TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0x00B3; //{0x00,0xB3};
|
||||
private static final int TLS_DHE_PSK_WITH_NULL_SHA256 = 0x00B4; //{0x00,0xB4};
|
||||
private static final int TLS_DHE_PSK_WITH_NULL_SHA384 = 0x00B5; //{0x00,0xB5};
|
||||
private static final int TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 = 0x00B6; //{0x00,0xB6};
|
||||
private static final int TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 = 0x00B7; //{0x00,0xB7};
|
||||
private static final int TLS_RSA_PSK_WITH_NULL_SHA256 = 0x00B8; //{0x00,0xB8};
|
||||
private static final int TLS_RSA_PSK_WITH_NULL_SHA384 = 0x00B9; //{0x00,0xB9};
|
||||
|
||||
//RFC 4492 - Elliptic Curve Cipher Suites
|
||||
private static final int TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001; //{ 0xC0, 0x01 }
|
||||
private static final int TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002; //{ 0xC0, 0x02 }
|
||||
private static final int TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003; //{ 0xC0, 0x03 }
|
||||
private static final int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004; //{ 0xC0, 0x04 }
|
||||
private static final int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005; //{ 0xC0, 0x05 }
|
||||
|
||||
private static final int TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006; //{ 0xC0, 0x06 }
|
||||
private static final int TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007; //{ 0xC0, 0x07 }
|
||||
private static final int TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008; //{ 0xC0, 0x08 }
|
||||
private static final int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009; //{ 0xC0, 0x09 }
|
||||
private static final int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A; //{ 0xC0, 0x0A }
|
||||
|
||||
private static final int TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B; //{ 0xC0, 0x0B }
|
||||
private static final int TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C; //{ 0xC0, 0x0C }
|
||||
private static final int TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D; //{ 0xC0, 0x0D }
|
||||
private static final int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E; //{ 0xC0, 0x0E }
|
||||
private static final int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F; //{ 0xC0, 0x0F }
|
||||
|
||||
private static final int TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010; //{ 0xC0, 0x10 }
|
||||
private static final int TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011; //{ 0xC0, 0x11 }
|
||||
private static final int TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012; //{ 0xC0, 0x12 }
|
||||
private static final int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013; //{ 0xC0, 0x13 }
|
||||
private static final int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014; //{ 0xC0, 0x14 }
|
||||
|
||||
private static final int TLS_ECDH_anon_WITH_NULL_SHA = 0xC015; //{ 0xC0, 0x15 }
|
||||
private static final int TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016; //{ 0xC0, 0x16 }
|
||||
private static final int TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017; //{ 0xC0, 0x17 }
|
||||
private static final int TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018; //{ 0xC0, 0x18 }
|
||||
private static final int TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019; //{ 0xC0, 0x19 }
|
||||
|
||||
//RFC 5289 - Elliptic Curve Cipher Suites
|
||||
private static final int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023; //{0xC0,0x23};
|
||||
private static final int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024; //{0xC0,0x24};
|
||||
private static final int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025; //{0xC0,0x25};
|
||||
private static final int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026; //{0xC0,0x26};
|
||||
private static final int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027; //{0xC0,0x27};
|
||||
private static final int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028; //{0xC0,0x28};
|
||||
private static final int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029; //{0xC0,0x29};
|
||||
private static final int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A; //{0xC0,0x2A};
|
||||
|
||||
private static final int TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B; //{0xC0,0x2B};
|
||||
private static final int TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C; //{0xC0,0x2C};
|
||||
private static final int TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D; //{0xC0,0x2D};
|
||||
private static final int TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E; //{0xC0,0x2E};
|
||||
private static final int TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F; //{0xC0,0x2F};
|
||||
private static final int TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030; //{0xC0,0x30};
|
||||
private static final int TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031; //{0xC0,0x31};
|
||||
private static final int TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032; //{0xC0,0x32};
|
||||
|
||||
//RFC 5489 - ECDHE/PSK Cipher Suites//
|
||||
private static final int TLS_ECDHE_PSK_WITH_RC4_128_SHA = 0xC033; //{0xC0,0x33};
|
||||
private static final int TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA = 0xC034; //{0xC0,0x34};
|
||||
private static final int TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA = 0xC035; //{0xC0,0x35};
|
||||
private static final int TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA = 0xC036; //{0xC0,0x36};
|
||||
private static final int TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = 0xC037; //{0xC0,0x37};
|
||||
private static final int TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 = 0xC038; //{0xC0,0x38};
|
||||
private static final int TLS_ECDHE_PSK_WITH_NULL_SHA = 0xC039; //{0xC0,0x39};
|
||||
private static final int TLS_ECDHE_PSK_WITH_NULL_SHA256 = 0xC03A; //{0xC0,0x3A};
|
||||
private static final int TLS_ECDHE_PSK_WITH_NULL_SHA384 = 0xC03B; //{0xC0,0x3B};
|
||||
|
||||
|
||||
|
||||
//Valid content types that preceed any message.//
|
||||
private static final int CONTENT_TYPE_CHANGE_CIPHER_SPEC = 0x14;
|
||||
private static final int CONTENT_TYPE_ALERT = 0x15;
|
||||
private static final int CONTENT_TYPE_HANDSHAKE = 0x16;
|
||||
private static final int CONTENT_TYPE_APPLICATION = 0x17;
|
||||
|
||||
//Alert Levels//
|
||||
private static final int ALERT_LEVEL_WARNING = 0x01;
|
||||
private static final int ALERT_LEVEL_FATAL = 0x02;
|
||||
|
||||
//Alert Descriptions//
|
||||
private static final int ALERT_DESCRIPTION_CLOSE_NOTIFY = 0;
|
||||
private static final int ALERT_DESCRIPTION_UNEXPECTED_MESSAGE = 10;
|
||||
private static final int ALERT_DESCRIPTION_BAD_RECORD_MAC = 20;
|
||||
private static final int ALERT_DESCRIPTION_DECRYPTION_FAILED = 21;
|
||||
private static final int ALERT_DESCRIPTION_RECORD_OVERFLOW = 22;
|
||||
private static final int ALERT_DESCRIPTION_DECOMPRESSION_FAILURE = 30;
|
||||
private static final int ALERT_DESCRIPTION_HANDSHAKE_FAILURE = 40;
|
||||
private static final int ALERT_DESCRIPTION_NO_CERTIFICATE = 41; //SSL v3 only//
|
||||
private static final int ALERT_DESCRIPTION_BAD_CERTIFICATE = 42;
|
||||
private static final int ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE = 43;
|
||||
private static final int ALERT_DESCRIPTION_CERTIFICATE_REVOKED = 44;
|
||||
private static final int ALERT_DESCRIPTION_CERTIFICATE_EXPIRED = 45;
|
||||
private static final int ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN = 46;
|
||||
private static final int ALERT_DESCRIPTION_ILLEGAL_PARAMETER = 47;
|
||||
private static final int ALERT_DESCRIPTION_UNKNOWN_CA = 48;
|
||||
private static final int ALERT_DESCRIPTION_ACCESS_DENIED = 49;
|
||||
private static final int ALERT_DESCRIPTION_DECODE_ERROR = 50;
|
||||
private static final int ALERT_DESCRIPTION_DECRYPT_ERROR = 51;
|
||||
private static final int ALERT_DESCRIPTION_EXPORT_RESTRICTION = 60;
|
||||
private static final int ALERT_DESCRIPTION_PROTOCOL_VERSION = 70;
|
||||
private static final int ALERT_DESCRIPTION_INSUFFICIENT_SECURITY = 71;
|
||||
private static final int ALERT_DESCRIPTION_INTERNAL_ERROR = 80;
|
||||
private static final int ALERT_DESCRIPTION_USER_CANCLELLED = 90;
|
||||
private static final int ALERT_DESCRIPTION_NO_RENEGOTIATION = 100;
|
||||
private static final int ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION = 110;
|
||||
|
||||
//Extensions//
|
||||
private static final int EXT_SERVER_NAME = 0x0000;
|
||||
private static final int EXT_MAX_FRAGMENT_LENGTH = 0x0001;
|
||||
private static final int EXT_CLIENT_CERTIFICATE_URL = 0x0002;
|
||||
private static final int EXT_TRUSTED_CA_KEYS = 0x0003;
|
||||
private static final int EXT_TRUNCATED_HMAC = 0x0004;
|
||||
private static final int EXT_STATUS_REQUEST = 0x0005;
|
||||
private static final int EXT_USER_MAPPING = 0x0006;
|
||||
private static final int EXT_CLIENT_AUTHZ = 0x0007;
|
||||
private static final int EXT_SERVER_AUTHZ = 0x0008;
|
||||
private static final int EXT_CERT_TYPE = 0x0009;
|
||||
private static final int EXT_ELLIPTIC_CURVES = 0x000A;
|
||||
private static final int EXT_EC_POINT_FORMATS = 0x000B;
|
||||
private static final int EXT_SRP = 0x000C;
|
||||
private static final int EXT_SIGNATURE_ALGORITHMS = 0x000D;
|
||||
private static final int EXT_USE_SRTP = 0x000F;
|
||||
private static final int EXT_SESSION_TICKET_TLS = 0x0023;
|
||||
private static final int EXT_RENEGOTIATION_INFO = 0xFF01;
|
||||
|
||||
//EXT_SERVER_NAME Options//
|
||||
private static final int NAME_TYPE_HOST_NAME = 0x00;
|
||||
|
||||
//The states the server will be in during a handshake.//
|
||||
private static final int HANDSHAKE_STATE_NONE = 0;
|
||||
private static final int HANDSHAKE_STATE_CLIENT_HELLO = 1;
|
||||
private static final int HANDSHAKE_STATE_ = 2;
|
||||
|
||||
private int handshakeState = HANDSHAKE_STATE_CLIENT_HELLO;
|
||||
private ISymmetricAlgorithm encryption = null;
|
||||
private IHashAlgorithm hash = null;
|
||||
// private ICompressionAlgorithm compression = null;
|
||||
/**
|
||||
* TlsEngine constructor.
|
||||
*/
|
||||
public TlsEngine() {
|
||||
}//TlsEngine()//
|
||||
/**
|
||||
* Reports a broken stream.
|
||||
*/
|
||||
private void handleBrokenStream() {
|
||||
throw new RuntimeException("Broken stream message.");
|
||||
}//handleBrokenStream()//
|
||||
/**
|
||||
* Processes the input bytes and fills the output buffer with out bound bytes (a response to any handshake messages), and returns any bytes destined for the application.
|
||||
* @param input The input bytes from the peer. Only one record (containing one or more messages) will be read from the input stream. Additional bytes may be left on the input stream after this call.
|
||||
* @param output The bytes to be sent back to the peer.
|
||||
* @param result The application bytes post processing.
|
||||
* @return Whether a record (containing messages) could be read from the input stream. This will be false only if there were not enough input buffer bytes available to read the next record.
|
||||
*/
|
||||
public boolean process(StreamBuffer input, StreamBuffer output, StreamBuffer result) {
|
||||
boolean canReadRecord = false;
|
||||
|
||||
if(input.getSize() > 4) {
|
||||
int contentType = input.getByte(0) & 0xFF;
|
||||
int highVersion = input.getByte(1) & 0xFF;
|
||||
int lowVersion = input.getByte(2) & 0xFF;
|
||||
int length = input.getShort(3, StreamBuffer.NUMBER_MSF) & 0xFFFF;
|
||||
|
||||
//Check the version.//
|
||||
if(highVersion != 3 || lowVersion > 3 || lowVersion < 1) {
|
||||
handleBrokenStream();
|
||||
}//if//
|
||||
|
||||
//Validate we have enough bytes for the whole message.//
|
||||
if(input.getSize() > 4 + length) {
|
||||
//A full record will be read.//
|
||||
canReadRecord = true;
|
||||
//Skip the record header bytes.//
|
||||
input.skipBytes(5);
|
||||
|
||||
//To simplify validation, make sure that there are no trailing bytes not part of the record in the input buffer.//
|
||||
if(input.getSize() != length) {
|
||||
StreamBuffer temp = new StreamBuffer(input.getBufferPool());
|
||||
|
||||
temp.writeBytes(input, length);
|
||||
input = temp;
|
||||
}//if//
|
||||
|
||||
//Read each message in this record.//
|
||||
switch(contentType) {
|
||||
case CONTENT_TYPE_CHANGE_CIPHER_SPEC: {
|
||||
processChangeCipherSpec(input);
|
||||
break;
|
||||
}//case//
|
||||
case CONTENT_TYPE_ALERT: {
|
||||
//Only one alert may exist in the message.//
|
||||
processAlert(input);
|
||||
break;
|
||||
}//case//
|
||||
case CONTENT_TYPE_HANDSHAKE: {
|
||||
//Multiple handshake messages may be contained in the single record.//
|
||||
while(input.getSize() > 0) {
|
||||
processHandshakeMessage(input, output);
|
||||
}//while//
|
||||
break;
|
||||
}//case//
|
||||
case CONTENT_TYPE_APPLICATION: {
|
||||
//TODO: Decrypt / Validate the message.
|
||||
//TODO: Place the decrypted bytes in the result buffer.
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
handleBrokenStream();
|
||||
}//default//
|
||||
}//switch//
|
||||
|
||||
//Ignore any padding or mac bytes. There will not be any for handshake messages.//
|
||||
if(input.getSize() > 0) {
|
||||
input.skipBytes(input.getSize());
|
||||
}//if//
|
||||
}//if//
|
||||
}//if//
|
||||
|
||||
return canReadRecord;
|
||||
}//process()//
|
||||
/**
|
||||
* Processes the out bound data and places it in the result buffer.
|
||||
* @param output The buffer containing out bound bytes.
|
||||
* @param result The buffer filled with encrypted bytes.
|
||||
*/
|
||||
public void process(StreamBuffer output, StreamBuffer result) {
|
||||
if(handshakeState == HANDSHAKE_STATE_NONE) {
|
||||
|
||||
}//if//
|
||||
else {
|
||||
throw new RuntimeException("Handshaking - can't send yet.");
|
||||
}//else//
|
||||
}//process()//
|
||||
/**
|
||||
* Processes a single handshake message in the input stream.
|
||||
* @param input The stream containing the full handshake message. No testing is performed to validate the whole message is in the stream.
|
||||
*/
|
||||
private void processHandshakeMessage(StreamBuffer input, StreamBuffer output) {
|
||||
int messageType = input.readByte() & 0xFF;
|
||||
int messageSize = input.readMediumInt(StreamBuffer.NUMBER_MSF, false);
|
||||
int postMessageStreamSize = input.getSize() - messageSize;
|
||||
|
||||
switch(messageType) {
|
||||
case HANDSHAKE_TYPE_HELLO_REQUEST: {
|
||||
throw new RuntimeException("Shouldn't be sent by the client.");
|
||||
}//case//
|
||||
case HANDSHAKE_TYPE_CLIENT_HELLO: {
|
||||
//Validate the message ordering.//
|
||||
if(handshakeState != HANDSHAKE_STATE_CLIENT_HELLO) {
|
||||
handleBrokenStream();
|
||||
}//if//
|
||||
|
||||
processClientHello(input, output, postMessageStreamSize);
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
throw new RuntimeException("Broken handshake message.");
|
||||
}//default//
|
||||
}//switch//
|
||||
|
||||
//Verify we read exactly the number of bytes in the message.//
|
||||
if(input.getSize() != postMessageStreamSize) {
|
||||
handleBrokenStream();
|
||||
}//if//
|
||||
}//processHandshakeMessage()//
|
||||
/**
|
||||
* Processes a client hello message. The message type and size has already been read at the time of this method's execution.
|
||||
* @param input The input buffer containing the client's message.
|
||||
* @param output The buffer to be filled with the out bound message.
|
||||
* @param postMessageStreamSize The size of the stream at the end of the message.
|
||||
*/
|
||||
private void processClientHello(StreamBuffer input, StreamBuffer output, int postMessageStreamSize) {
|
||||
long time;
|
||||
byte[] randomClientBytes = new byte[28];
|
||||
int sessionIdSize;
|
||||
byte[] sessionId = null;
|
||||
int cipherSuiteCount;
|
||||
int[] cipherSuites;
|
||||
int compressionMethodCount;
|
||||
int[] compressionMethods;
|
||||
String hostName = null;
|
||||
int protocolVersionHigh = input.readByte() & 0xFF; //Note: This should be the same as when it was read as part of the record earlier - this is redundant.//
|
||||
int protocolVersionLow = input.readByte() & 0xFF;
|
||||
|
||||
time = input.readInt(StreamBuffer.NUMBER_MSF) & 0x00000000FFFFFFFFL;
|
||||
input.readBytes(randomClientBytes);
|
||||
sessionIdSize = input.readByte() & 0xFF;
|
||||
|
||||
if(sessionIdSize > 0) {
|
||||
sessionId = new byte[sessionIdSize];
|
||||
input.readBytes(sessionId);
|
||||
}//if//
|
||||
|
||||
cipherSuiteCount = (input.readShort(StreamBuffer.NUMBER_MSF) & 0xFFFF) / 2;
|
||||
cipherSuites = new int[cipherSuiteCount];
|
||||
|
||||
for(int index = 0; index < cipherSuites.length; index++) {
|
||||
cipherSuites[index] = input.readShort(StreamBuffer.NUMBER_MSF) & 0xFFFF;
|
||||
}//for//
|
||||
|
||||
compressionMethodCount = input.readByte() & 0xFF;
|
||||
compressionMethods = new int[compressionMethodCount];
|
||||
|
||||
for(int index = 0; index < compressionMethods.length; index++) {
|
||||
compressionMethods[index] = input.readByte() & 0xFF;
|
||||
}//for//
|
||||
|
||||
//Read extensions until the end of the stream is reached.//
|
||||
if(input.getSize() != postMessageStreamSize) {
|
||||
int extensionArraySize = input.readShort(StreamBuffer.NUMBER_MSF) & 0xFFFF;
|
||||
|
||||
//Read each extension.//
|
||||
//for(int index = 0; index < extensionCount; index++) { //Note: No way of knowning the extension count due to netscape stupidity. Arrays are prefixed with the number of bytes instead of the count of elements.//
|
||||
while(input.getSize() != postMessageStreamSize) {
|
||||
int extensionType = input.readShort(StreamBuffer.NUMBER_MSF) & 0xFFFF;
|
||||
int extensionDataSize = input.readShort(StreamBuffer.NUMBER_MSF) & 0xFFFF;
|
||||
int expectedStreamSize = input.getSize() - extensionDataSize;
|
||||
|
||||
//Read the extension data if it is known, otherwise skip the data.//
|
||||
switch(extensionType) {
|
||||
case EXT_SERVER_NAME: {
|
||||
//The ServerName extension always starts with a ServerNameList structure.//
|
||||
int serverNameListByteCount = input.readShort(StreamBuffer.NUMBER_MSF) & 0xFFFF;
|
||||
int postServerNamesExpectedStreamSize = input.getSize() - serverNameListByteCount;
|
||||
|
||||
//Read each of the server names (no idea how many there will be - <kicking netscape>).//
|
||||
while(input.getSize() != postServerNamesExpectedStreamSize) {
|
||||
int nameType = input.readByte() & 0xFF;
|
||||
|
||||
switch(nameType) {
|
||||
case 0x00: { //NAME_TYPE_HOST_NAME
|
||||
int nameByteCount = input.readShort(StreamBuffer.NUMBER_MSF) & 0xFFFF;
|
||||
String name;
|
||||
|
||||
try {
|
||||
name = input.readText(nameByteCount, "UTF8").toLowerCase();
|
||||
Debug.log(name);
|
||||
|
||||
if(hostName == null) {
|
||||
hostName = name;
|
||||
}//if//
|
||||
}//try//
|
||||
catch(UnsupportedEncodingException e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
break;
|
||||
}//default//
|
||||
}//switch//
|
||||
}//while//
|
||||
break;
|
||||
}//case//
|
||||
/* Not currently used.
|
||||
case EXT_MAX_FRAGMENT_LENGTH: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_CLIENT_CERTIFICATE_URL: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_TRUSTED_CA_KEYS: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_TRUNCATED_HMAC: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_STATUS_REQUEST: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_USER_MAPPING: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_CLIENT_AUTHZ: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_SERVER_AUTHZ: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_CERT_TYPE: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_ELLIPTIC_CURVES: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_EC_POINT_FORMATS: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_SRP: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_SIGNATURE_ALGORITHMS: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_USE_SRTP: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_SESSION_TICKET_TLS: {
|
||||
break;
|
||||
}//case//
|
||||
case EXT_RENEGOTIATION_INFO: {
|
||||
break;
|
||||
}//case//
|
||||
*/
|
||||
default: {
|
||||
input.skipBytes(extensionDataSize);
|
||||
break;
|
||||
}//default//
|
||||
}//switch//
|
||||
|
||||
//Ignore any unused bytes.//
|
||||
if(input.getSize() != expectedStreamSize) {
|
||||
input.skipBytes(input.getSize() - expectedStreamSize);
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
|
||||
if(hostName == null) {
|
||||
//TODO: Send an alert?
|
||||
handleBrokenStream();
|
||||
}//if//
|
||||
|
||||
//Write TLS v1.0.//
|
||||
output.writeByte(0x03);
|
||||
output.writeByte(0x01);
|
||||
//Write the number of seconds since Jan 1, 1970 UTC (w/o leap seconds).//
|
||||
output.writeInt((int) (System.currentTimeMillis() / 1000), StreamBuffer.NUMBER_MSF);
|
||||
byte[] serverRandomBytes = new byte[28];
|
||||
new SecureRandom().nextBytes(serverRandomBytes);
|
||||
//Write the server's random bytes.//
|
||||
output.writeBytes(serverRandomBytes);
|
||||
//Write the server's session (32 bytes) - for now we are not saving a session so write zero.//
|
||||
output.writeByte(0);
|
||||
//Write the chosen cipher suite (2 bytes).//
|
||||
|
||||
}//processClientHello()//
|
||||
/**
|
||||
* Reads an alert off the stream.
|
||||
* @param input The input stream to read the message from.
|
||||
*/
|
||||
private void processAlert(StreamBuffer input) {
|
||||
int level = input.readByte() & 0xFF;
|
||||
int description = input.readByte() & 0xFF;
|
||||
|
||||
Debug.log("Received " + (level == ALERT_LEVEL_FATAL ? "fatal error: " : " warning: ") + description);
|
||||
|
||||
switch(description) {
|
||||
case ALERT_DESCRIPTION_CLOSE_NOTIFY: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_UNEXPECTED_MESSAGE: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_BAD_RECORD_MAC: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_DECRYPTION_FAILED: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_RECORD_OVERFLOW: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_DECOMPRESSION_FAILURE: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_HANDSHAKE_FAILURE: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_NO_CERTIFICATE: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_BAD_CERTIFICATE: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_CERTIFICATE_REVOKED: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_CERTIFICATE_EXPIRED: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_ILLEGAL_PARAMETER: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_UNKNOWN_CA: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_ACCESS_DENIED: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_DECODE_ERROR: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_DECRYPT_ERROR: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_EXPORT_RESTRICTION: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_PROTOCOL_VERSION: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_INSUFFICIENT_SECURITY: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_INTERNAL_ERROR: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_USER_CANCLELLED: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_NO_RENEGOTIATION: {
|
||||
break;
|
||||
}//case//
|
||||
case ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION: {
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
break;
|
||||
}//case//
|
||||
}//switch//
|
||||
}//processAlert()//
|
||||
/**
|
||||
* Reads an a change cipher spec message from the stream.
|
||||
* @param input The input stream to read the message from.
|
||||
*/
|
||||
private void processChangeCipherSpec(StreamBuffer input) {
|
||||
int ccsProtocolType = input.readByte() & 0xFF;
|
||||
|
||||
if(ccsProtocolType == 1) {
|
||||
//TODO: Start the handshake.
|
||||
}//if//
|
||||
else {
|
||||
handleBrokenStream();
|
||||
}//else//
|
||||
}//processChangeCipherSpec()//
|
||||
}//TlsEngine//
|
||||
100
TLS Test/src/com/de22/tls/test/Main.java
Normal file
100
TLS Test/src/com/de22/tls/test/Main.java
Normal file
@@ -0,0 +1,100 @@
|
||||
package com.de22.tls.test;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.*;
|
||||
import java.security.KeyStore;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.thread.ThreadService;
|
||||
import com.common.util.StreamBuffer;
|
||||
import com.de22.tls.*;
|
||||
|
||||
public class Main {
|
||||
/**
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
KeyStore keystore1 = KeyStore.getInstance("JKS");
|
||||
KeyStore keystore2 = KeyStore.getInstance("JKS");
|
||||
final TlsApp[] tlsApps = new TlsApp[2];
|
||||
ServerSocket serverSocket = new ServerSocket(443);
|
||||
|
||||
keystore1.load(new FileInputStream("./key1"), "123store".toCharArray());
|
||||
keystore2.load(new FileInputStream("./key2"), "123store".toCharArray());
|
||||
tlsApps[0] = new TlsApp("domain1.com", keystore1);
|
||||
tlsApps[1] = new TlsApp("domain2.com", keystore2);
|
||||
|
||||
while(true) {
|
||||
final Socket socket = serverSocket.accept();
|
||||
|
||||
ThreadService.run(new Runnable() {
|
||||
public void run() {
|
||||
connect(socket, tlsApps);
|
||||
}//run()//
|
||||
});
|
||||
}//while//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
}//main()//
|
||||
/**
|
||||
* Connects via the socket, performs the TLS handshake, and sends/receives data.
|
||||
* @param socket
|
||||
* @param tlsApps
|
||||
*/
|
||||
private static void connect(Socket socket, TlsApp[] tlsApps) {
|
||||
try {
|
||||
TlsEngine engine = new TlsEngine();
|
||||
StreamBuffer input = new StreamBuffer();
|
||||
StreamBuffer output = new StreamBuffer();
|
||||
StreamBuffer result = new StreamBuffer();
|
||||
InputStream in = socket.getInputStream();
|
||||
boolean isRunning = true;
|
||||
|
||||
try {
|
||||
//Read data from the socket until it closes.//
|
||||
while(isRunning) {
|
||||
int next = in.read();
|
||||
|
||||
if(next != -1) {
|
||||
input.writeByte((byte) next);
|
||||
|
||||
while(in.available() > 0) {
|
||||
input.writeBytes(in, in.available());
|
||||
}//while//
|
||||
|
||||
engine.process(input, output, result);
|
||||
|
||||
if(output.getSize() > 0) {
|
||||
//TODO: Send the output.
|
||||
}//if//
|
||||
|
||||
if(result.getSize() > 0) {
|
||||
//TODO: Forward the result up the food chain.
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
//Socket closed.//
|
||||
isRunning = false;
|
||||
}//else//
|
||||
}//while//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
|
||||
try {
|
||||
socket.close();
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
//Ignored.//
|
||||
}//catch//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
}//connect()//
|
||||
}//Main//
|
||||
Reference in New Issue
Block a user