in modules/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java [349:630]
void processClientHello() {
CipherSuite cipher_suite;
// check that clientHello contains CompressionMethod.null
checkCompression: {
for (int i = 0; i < clientHello.compression_methods.length; i++) {
if (clientHello.compression_methods[i] == 0) {
break checkCompression;
}
}
fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
"HANDSHAKE FAILURE. Incorrect client hello message");
}
if (!ProtocolVersion.isSupported(clientHello.client_version)) {
fatalAlert(AlertProtocol.PROTOCOL_VERSION,
"PROTOCOL VERSION. Unsupported client version "
+ clientHello.client_version[0]
+ clientHello.client_version[1]);
}
isResuming = false;
FIND: if (clientHello.session_id.length != 0) {
// client wishes to reuse session
SSLSessionImpl sessionToResume;
boolean reuseCurrent = false;
// reuse current session
if (session != null
&& Arrays.equals(session.id, clientHello.session_id)) {
if (session.isValid()) {
isResuming = true;
break FIND;
}
reuseCurrent = true;
}
// find session in cash
sessionToResume = findSessionToResume(clientHello.session_id);
if (sessionToResume == null || !sessionToResume.isValid()) {
if (!parameters.getEnableSessionCreation()) {
if (reuseCurrent) {
// we can continue current session
sendWarningAlert(AlertProtocol.NO_RENEGOTIATION);
status = NOT_HANDSHAKING;
clearMessages();
return;
}
// throw AlertException
fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "SSL Session may not be created");
}
session = null;
} else {
session = (SSLSessionImpl)sessionToResume.clone();
isResuming = true;
}
}
if (isResuming) {
cipher_suite = session.cipherSuite;
// clientHello.cipher_suites must include at least cipher_suite from the session
checkCipherSuite: {
for (int i = 0; i < clientHello.cipher_suites.length; i++) {
if (cipher_suite.equals(clientHello.cipher_suites[i])) {
break checkCipherSuite;
}
}
fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
"HANDSHAKE FAILURE. Incorrect client hello message");
}
} else {
cipher_suite = selectSuite(clientHello.cipher_suites);
if (cipher_suite == null) {
fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "HANDSHAKE FAILURE. NO COMMON SUITE");
}
if (!parameters.getEnableSessionCreation()) {
fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
"SSL Session may not be created");
}
session = new SSLSessionImpl(cipher_suite, parameters
.getSecureRandom());
}
recordProtocol.setVersion(clientHello.client_version);
session.protocol = ProtocolVersion.getByVersion(clientHello.client_version);
session.clientRandom = clientHello.random;
// create server hello message
serverHello = new ServerHello(parameters.getSecureRandom(),
clientHello.client_version,
session.getId(), cipher_suite, (byte) 0); //CompressionMethod.null
session.serverRandom = serverHello.random;
send(serverHello);
if (isResuming) {
sendChangeCipherSpec();
return;
}
// create and send server certificate message if needed
if (!cipher_suite.isAnonymous()) { // need to send server certificate
X509Certificate[] certs = null;
String certType = null;
if (cipher_suite.keyExchange == CipherSuite.KeyExchange_RSA
|| cipher_suite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT
|| cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_RSA
|| cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_RSA_EXPORT) {
certType = "RSA";
} else if (cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_DSS
|| cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_DSS_EXPORT) {
certType = "DSA";
} else if (cipher_suite.keyExchange == CipherSuite.KeyExchange_DH_DSS) {
certType = "DH_DSA";
} else if (cipher_suite.keyExchange == CipherSuite.KeyExchange_DH_RSA) {
certType = "DH_RSA";
}
// obtain certificates from key manager
String alias = null;
X509KeyManager km = parameters.getKeyManager();
if (km instanceof X509ExtendedKeyManager) {
X509ExtendedKeyManager ekm = (X509ExtendedKeyManager)km;
if (this.socketOwner != null) {
alias = ekm.chooseServerAlias(certType, null,
this.socketOwner);
} else {
alias = ekm.chooseEngineServerAlias(certType, null,
this.engineOwner);
}
if (alias != null) {
certs = ekm.getCertificateChain(alias);
}
} else {
alias = km.chooseServerAlias(certType, null, this.socketOwner);
if (alias != null) {
certs = km.getCertificateChain(alias);
}
}
if (certs == null) {
fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "NO SERVER CERTIFICATE FOUND");
return;
}
session.localCertificates = certs;
serverCert = new CertificateMessage(certs);
privKey = parameters.getKeyManager().getPrivateKey(alias);
send(serverCert);
}
// create and send server key exchange message if needed
RSAPublicKey rsakey = null;
DHPublicKeySpec dhkeySpec = null;
byte[] hash = null;
BigInteger p = null;
BigInteger g = null;
KeyPairGenerator kpg = null;
try {
if (cipher_suite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT) {
PublicKey pk = serverCert.certs[0].getPublicKey();
if (getRSAKeyLength(pk) > 512) {
// key is longer than 512 bits
kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
}
} else if (cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_DSS
|| cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_DSS_EXPORT
|| cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_RSA
|| cipher_suite.keyExchange == CipherSuite.KeyExchange_DHE_RSA_EXPORT
|| cipher_suite.keyExchange == CipherSuite.KeyExchange_DH_anon
|| cipher_suite.keyExchange == CipherSuite.KeyExchange_DH_anon_EXPORT) {
try {
kpg = KeyPairGenerator.getInstance("DH");
} catch (NoSuchAlgorithmException ee) {
kpg = KeyPairGenerator.getInstance("DiffieHellman");
}
p = new BigInteger(1, DHParameters.getPrime());
g = new BigInteger("2");
DHParameterSpec spec = new DHParameterSpec(p, g);
kpg.initialize(spec);
}
} catch (Exception e) {
fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR", e);
}
if (kpg != null) {
// need to send server key exchange message
DigitalSignature ds = new DigitalSignature(cipher_suite.keyExchange);
KeyPair kp = null;
try {
kp = kpg.genKeyPair();
if (cipher_suite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT) {
rsakey = (RSAPublicKey) kp.getPublic();
} else {
DHPublicKey dhkey = (DHPublicKey) kp.getPublic();
KeyFactory kf = null;
try {
kf = KeyFactory.getInstance("DH");
} catch (NoSuchAlgorithmException e) {
kf = KeyFactory.getInstance("DiffieHellman");
}
dhkeySpec = kf.getKeySpec(dhkey,
DHPublicKeySpec.class);
}
if (!cipher_suite.isAnonymous()) { // calculate signed_params
// init by private key which correspond to
// server certificate
ds.init(privKey);
// use emphemeral key for key exchange
privKey = kp.getPrivate();
ds.update(clientHello.getRandom());
ds.update(serverHello.getRandom());
byte[] tmp;
byte[] tmpLength = new byte[2];
//FIXME 1_byte==0x00
if (cipher_suite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT) {
tmp = rsakey.getModulus().toByteArray();
tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
tmpLength[1] = (byte) (tmp.length & 0xFF);
ds.update(tmpLength);
ds.update(tmp);
tmp = rsakey.getPublicExponent().toByteArray();
tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
tmpLength[1] = (byte) (tmp.length & 0xFF);
ds.update(tmp);
} else {
tmp = dhkeySpec.getP().toByteArray();
tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
tmpLength[1] = (byte) (tmp.length & 0xFF);
ds.update(tmp);
tmp = dhkeySpec.getG().toByteArray();
tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
tmpLength[1] = (byte) (tmp.length & 0xFF);
ds.update(tmp);
tmp = dhkeySpec.getY().toByteArray();
tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
tmpLength[1] = (byte) (tmp.length & 0xFF);
ds.update(tmp);
}
hash = ds.sign();
} else {
privKey = kp.getPrivate(); // use emphemeral key for key exchange
}
} catch (Exception e) {
fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR", e);
}
if (cipher_suite.keyExchange == CipherSuite.KeyExchange_RSA_EXPORT) {
serverKeyExchange = new ServerKeyExchange(rsakey.getModulus(),
rsakey.getPublicExponent(), null, hash);
} else {
serverKeyExchange = new ServerKeyExchange(p,
g, dhkeySpec.getY(), hash);
}
send(serverKeyExchange);
}
// CERTIFICATE_REQUEST
certRequest: if (parameters.getWantClientAuth()
|| parameters.getNeedClientAuth()) {
X509Certificate[] accepted;
try {
X509TrustManager tm = parameters.getTrustManager();
accepted = tm.getAcceptedIssuers();
} catch (ClassCastException e) {
// don't send certificateRequest
break certRequest;
}
byte[] requestedClientCertTypes = {1, 2}; // rsa sign, dsa sign
certificateRequest = new CertificateRequest(
requestedClientCertTypes, accepted);
send(certificateRequest);
}
// SERVER_HELLO_DONE
serverHelloDone = new ServerHelloDone();
send(serverHelloDone);
status = NEED_UNWRAP;
}