📄 tlsprotocolhandler.java
字号:
case HP_SERVER_HELLO: switch (connection_state) { case CS_CLIENT_HELLO_SEND: /* * Read the server hello message */ TlsUtils.checkVersion(is, this); /* * Read the server random */ this.serverRandom = new byte[32]; TlsUtils.readFully(this.serverRandom, is); /* * Currenty, we don't support session ids */ short sessionIdLength = TlsUtils.readUint8(is); byte[] sessionId = new byte[sessionIdLength]; TlsUtils.readFully(sessionId, is); /* * Find out which ciphersuite the server has * choosen. If we don't support this ciphersuite, * the TlsCipherSuiteManager will throw an * exception. */ this.choosenCipherSuite = TlsCipherSuiteManager.getCipherSuite(TlsUtils.readUint16(is), this); /* * We support only the null compression which * means no compression. */ short compressionMethod = TlsUtils.readUint8(is); if (compressionMethod != 0) { this.failWithError(TlsProtocolHandler.AL_fatal, TlsProtocolHandler.AP_illegal_parameter); } assertEmpty(is); connection_state = CS_SERVER_HELLO_RECEIVED; read = true; break; default: this.failWithError(AL_fatal, AP_unexpected_message); } break; case HP_SERVER_HELLO_DONE: switch (connection_state) { case CS_SERVER_CERTIFICATE_RECEIVED: /* * There was no server key exchange message, check * that we are doing RSA key exchange. */ if (this.choosenCipherSuite.getKeyExchangeAlgorithm() != TlsCipherSuite.KE_RSA) { this.failWithError(AL_fatal, AP_unexpected_message); } /* * NB: Fall through to next case label to continue RSA key exchange */ case CS_SERVER_KEY_EXCHANGE_RECEIVED: assertEmpty(is); connection_state = CS_SERVER_HELLO_DONE_RECEIVED; /* * Send the client key exchange message, depending * on the key exchange we are using in our * ciphersuite. */ short ke = this.choosenCipherSuite.getKeyExchangeAlgorithm(); switch (ke) { case TlsCipherSuite.KE_RSA: /* * We are doing RSA key exchange. We will * choose a pre master secret and send it * rsa encrypted to the server. * * Prepare pre master secret. */ pms = new byte[48]; pms[0] = 3; pms[1] = 1; for (int i = 2; i < 48; i++) { pms[i] = (byte)random.nextInt(); } /* * Encode the pms and send it to the server. * * Prepare an PKCS1Encoding with good random * padding. */ RSABlindedEngine rsa = new RSABlindedEngine(); PKCS1Encoding encoding = new PKCS1Encoding(rsa); encoding.init(true, new ParametersWithRandom(this.serverRsaKey, this.random)); byte[] encrypted = null; try { encrypted = encoding.processBlock(pms, 0, pms.length); } catch (InvalidCipherTextException e) { /* * This should never happen, only during decryption. */ this.failWithError(AL_fatal, AP_internal_error); } /* * Send the encrypted pms. */ ByteArrayOutputStream bos = new ByteArrayOutputStream(); TlsUtils.writeUint8(HP_CLIENT_KEY_EXCHANGE, bos); TlsUtils.writeUint24(encrypted.length + 2, bos); TlsUtils.writeUint16(encrypted.length, bos); bos.write(encrypted); byte[] message = bos.toByteArray(); rs.writeMessage((short)RL_HANDSHAKE, message, 0, message.length); break; case TlsCipherSuite.KE_DHE_RSA: /* * Send the Client Key Exchange message for * DHE key exchange. */ byte[] YcByte = this.Yc.toByteArray(); ByteArrayOutputStream DHbos = new ByteArrayOutputStream(); TlsUtils.writeUint8(HP_CLIENT_KEY_EXCHANGE, DHbos); TlsUtils.writeUint24(YcByte.length + 2, DHbos); TlsUtils.writeUint16(YcByte.length, DHbos); DHbos.write(YcByte); byte[] DHmessage = DHbos.toByteArray(); rs.writeMessage((short)RL_HANDSHAKE, DHmessage, 0, DHmessage.length); break; default: /* * Proble during handshake, we don't know * how to thandle this key exchange method. */ this.failWithError(AL_fatal, AP_unexpected_message); } connection_state = CS_CLIENT_KEY_EXCHANGE_SEND; /* * Now, we send change cipher state */ byte[] cmessage = new byte[1]; cmessage[0] = 1; rs.writeMessage((short)RL_CHANGE_CIPHER_SPEC, cmessage, 0, cmessage.length); connection_state = CS_CLIENT_CHANGE_CIPHER_SPEC_SEND; /* * Calculate the ms */ this.ms = new byte[48]; byte[] random = new byte[clientRandom.length + serverRandom.length]; System.arraycopy(clientRandom, 0, random, 0, clientRandom.length); System.arraycopy(serverRandom, 0, random, clientRandom.length, serverRandom.length); TlsUtils.PRF(pms, "master secret".getBytes(), random, this.ms); /* * Initialize our cipher suite */ rs.writeSuite = this.choosenCipherSuite; rs.writeSuite.init(this.ms, clientRandom, serverRandom); /* * Send our finished message. */ byte[] checksum = new byte[12]; byte[] md5andsha1 = new byte[16 + 20]; rs.hash1.doFinal(md5andsha1, 0); TlsUtils.PRF(this.ms, "client finished".getBytes(), md5andsha1, checksum); ByteArrayOutputStream bos = new ByteArrayOutputStream(); TlsUtils.writeUint8(HP_FINISHED, bos); TlsUtils.writeUint24(12, bos); bos.write(checksum); byte[] message = bos.toByteArray(); rs.writeMessage((short)RL_HANDSHAKE, message, 0, message.length); this.connection_state = CS_CLIENT_FINISHED_SEND; read = true; break; default: this.failWithError(AL_fatal, AP_handshake_failure); } break; case HP_SERVER_KEY_EXCHANGE: switch (connection_state) { case CS_SERVER_CERTIFICATE_RECEIVED: /* * Check that we are doing DHE key exchange */ if (this.choosenCipherSuite.getKeyExchangeAlgorithm() != TlsCipherSuite.KE_DHE_RSA) { this.failWithError(AL_fatal, AP_unexpected_message); } /* * Parse the Structure */ int pLength = TlsUtils.readUint16(is); byte[] pByte = new byte[pLength]; TlsUtils.readFully(pByte, is); int gLength = TlsUtils.readUint16(is); byte[] gByte = new byte[gLength]; TlsUtils.readFully(gByte, is); int YsLength = TlsUtils.readUint16(is); byte[] YsByte = new byte[YsLength]; TlsUtils.readFully(YsByte, is); int sigLength = TlsUtils.readUint16(is); byte[] sigByte = new byte[sigLength]; TlsUtils.readFully(sigByte, is); this.assertEmpty(is); /* * Verify the Signature. * * First, calculate the hash. */ CombinedHash sigDigest = new CombinedHash(); ByteArrayOutputStream signedData = new ByteArrayOutputStream(); TlsUtils.writeUint16(pLength, signedData); signedData.write(pByte); TlsUtils.writeUint16(gLength, signedData); signedData.write(gByte); TlsUtils.writeUint16(YsLength, signedData); signedData.write(YsByte); byte[] signed = signedData.toByteArray(); sigDigest.update(this.clientRandom, 0, this.clientRandom.length); sigDigest.update(this.serverRandom, 0, this.serverRandom.length); sigDigest.update(signed, 0, signed.length); byte[] hash = new byte[sigDigest.getDigestSize()]; sigDigest.doFinal(hash, 0); /* * Now, do the RSA operation */ RSABlindedEngine rsa = new RSABlindedEngine(); PKCS1Encoding encoding = new PKCS1Encoding(rsa); encoding.init(false, this.serverRsaKey); /* * The data which was signed */ byte[] sigHash = null; try { sigHash = encoding.processBlock(sigByte, 0, sigByte.length); } catch (InvalidCipherTextException e) { this.failWithError(AL_fatal, AP_bad_certificate); } /* * Check if the data which was signed is equal to * the hash we calculated. */ if (sigHash.length != hash.length) { this.failWithError(AL_fatal, AP_bad_certificate); } for (int i = 0; i < sigHash.length; i++) { if (sigHash[i] != hash[i]) { this.failWithError(AL_fatal, AP_bad_certificate); } } /* * OK, Signature was correct. * * Do the DH calculation. */ BigInteger p = new BigInteger(1, pByte); BigInteger g = new BigInteger(1, gByte); BigInteger Ys = new BigInteger(1, YsByte); BigInteger x = new BigInteger(p.bitLength() - 1, this.random); Yc = g.modPow(x, p); this.pms = (Ys.modPow(x, p)).toByteArray(); /* * Remove leading zero byte, if present. */ if (this.pms[0] == 0) { byte[] tmp = new byte[this.pms.length - 1]; System.arraycopy(this.pms, 1, tmp, 0, tmp.length); this.pms = tmp; } this.connection_state = CS_SERVER_KEY_EXCHANGE_RECEIVED; read = true; break; default: this.failWithError(AL_fatal, AP_unexpected_message); } break; case HP_HELLO_REQUEST: case HP_CLIENT_KEY_EXCHANGE: case HP_CERTIFICATE_REQUEST: case HP_CERTIFICATE_VERIFY: case HP_CLIENT_HELLO: default: // We do not support this! this.failWithError(AL_fatal, AP_unexpected_message); break; } } } } while (read); } private void processApplicationData() { /* * There is nothing we need to do here. * * This function could be used for callbacks when application * data arrives in the future. */ } private void processAlert() throws IOException { while (alertQueue.size() >= 2) { /* * An alert is always 2 bytes. Read the alert. */ byte[] tmp = new byte[2]; alertQueue.read(tmp, 0, 2, 0); alertQueue.removeData(2); short level = tmp[0]; short description = tmp[1]; if (level == AL_fatal) { /* * This is a fatal error. */ this.failedWithError = true; this.closed = true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -