protected void generateEphemeralClientKeyExchange(DHParameters dhParams, OutputStream os) throws IOException { AsymmetricCipherKeyPair dhAgreeClientKeyPair = generateDHKeyPair(dhParams); this.dhAgreeClientPrivateKey = (DHPrivateKeyParameters) dhAgreeClientKeyPair.getPrivate(); BigInteger Yc = ((DHPublicKeyParameters) dhAgreeClientKeyPair.getPublic()).getY(); byte[] keData = BigIntegers.asUnsignedByteArray(Yc); TlsUtils.writeUint24(keData.length + 2, os); TlsUtils.writeOpaque16(keData, os); }
private void sendCertificateVerify(byte[] data) throws IOException { /* * Send signature of handshake messages so far to prove we are the owner of the * cert See RFC 2246 sections 4.7, 7.4.3 and 7.4.8 */ ByteArrayOutputStream bos = new ByteArrayOutputStream(); TlsUtils.writeUint8(HandshakeType.certificate_verify, bos); TlsUtils.writeUint24(data.length + 2, bos); TlsUtils.writeOpaque16(data, bos); byte[] message = bos.toByteArray(); rs.writeMessage(ContentType.handshake, message, 0, message.length); }
public void generateClientKeyExchange(OutputStream os) throws IOException { /* * Choose a PremasterSecret and send it encrypted to the server */ premasterSecret = new byte[48]; context.getSecureRandom().nextBytes(premasterSecret); TlsUtils.writeVersion(premasterSecret, 0); PKCS1Encoding encoding = new PKCS1Encoding(new RSABlindedEngine()); encoding.init( true, new ParametersWithRandom(this.rsaServerPublicKey, context.getSecureRandom())); try { byte[] keData = encoding.processBlock(premasterSecret, 0, premasterSecret.length); TlsUtils.writeUint24(keData.length + 2, os); TlsUtils.writeOpaque16(keData, os); } catch (InvalidCipherTextException e) { /* * This should never happen, only during decryption. */ throw new TlsFatalAlert(AlertDescription.internal_error); } }
/** * Encode this {@link OCSPStatusRequest} to an {@link OutputStream}. * * @param output the {@link OutputStream} to encode to. * @throws IOException */ public void encode(OutputStream output) throws IOException { if (responderIDList == null || responderIDList.isEmpty()) { TlsUtils.writeUint16(0, output); } else { ByteArrayOutputStream buf = new ByteArrayOutputStream(); for (int i = 0; i < responderIDList.size(); ++i) { ResponderID responderID = (ResponderID) responderIDList.elementAt(i); byte[] derEncoding = responderID.getEncoded(ASN1Encoding.DER); TlsUtils.writeOpaque16(derEncoding, buf); } TlsUtils.checkUint16(buf.size()); TlsUtils.writeUint16(buf.size(), output); buf.writeTo(output); } if (requestExtensions == null) { TlsUtils.writeUint16(0, output); } else { byte[] derEncoding = requestExtensions.getEncoded(ASN1Encoding.DER); TlsUtils.checkUint16(derEncoding.length); TlsUtils.writeUint16(derEncoding.length, output); output.write(derEncoding); } }
/** * Encode this {@link DigitallySigned} to an {@link OutputStream}. * * @param output the {@link OutputStream} to encode to. * @throws IOException */ public void encode(OutputStream output) throws IOException { if (algorithm != null) { algorithm.encode(output); } TlsUtils.writeOpaque16(signature, output); }
/** * Connects to the remote system using client authentication * * @param tlsClient * @throws IOException If handshake was not successful. */ public void connect(TlsClient tlsClient) throws IOException { if (tlsClient == null) { throw new IllegalArgumentException("'tlsClient' cannot be null"); } if (this.tlsClient != null) { throw new IllegalStateException("connect can only be called once"); } /* * Send Client hello * * First, generate some random data. */ this.securityParameters = new SecurityParameters(); this.securityParameters.clientRandom = new byte[32]; random.nextBytes(securityParameters.clientRandom); TlsUtils.writeGMTUnixTime(securityParameters.clientRandom, 0); this.tlsClientContext = new TlsClientContextImpl(random, securityParameters); this.rs.init(tlsClientContext); this.tlsClient = tlsClient; this.tlsClient.init(tlsClientContext); ByteArrayOutputStream os = new ByteArrayOutputStream(); ProtocolVersion client_version = this.tlsClient.getClientVersion(); this.tlsClientContext.setClientVersion(client_version); // TODO For SSLv3 support, server version needs to be set to ProtocolVersion.SSLv3 this.tlsClientContext.setServerVersion(client_version); TlsUtils.writeVersion(client_version, os); os.write(securityParameters.clientRandom); /* * Length of Session id */ TlsUtils.writeUint8((short) 0, os); /* * Cipher suites */ this.offeredCipherSuites = this.tlsClient.getCipherSuites(); // Integer -> byte[] this.clientExtensions = this.tlsClient.getClientExtensions(); // Cipher Suites (and SCSV) { /* * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" * extension, or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite * value in the ClientHello. Including both is NOT RECOMMENDED. */ boolean noRenegExt = clientExtensions == null || clientExtensions.get(EXT_RenegotiationInfo) == null; int count = offeredCipherSuites.length; if (noRenegExt) { // Note: 1 extra slot for TLS_EMPTY_RENEGOTIATION_INFO_SCSV ++count; } TlsUtils.writeUint16(2 * count, os); TlsUtils.writeUint16Array(offeredCipherSuites, os); if (noRenegExt) { TlsUtils.writeUint16(CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV, os); } } // Compression methods this.offeredCompressionMethods = this.tlsClient.getCompressionMethods(); TlsUtils.writeUint8((short) offeredCompressionMethods.length, os); TlsUtils.writeUint8Array(offeredCompressionMethods, os); // Extensions if (clientExtensions != null) { ByteArrayOutputStream ext = new ByteArrayOutputStream(); Enumeration keys = clientExtensions.keys(); while (keys.hasMoreElements()) { Integer extType = (Integer) keys.nextElement(); writeExtension(ext, extType, (byte[]) clientExtensions.get(extType)); } TlsUtils.writeOpaque16(ext.toByteArray(), os); } ByteArrayOutputStream bos = new ByteArrayOutputStream(); TlsUtils.writeUint8(HandshakeType.client_hello, bos); TlsUtils.writeUint24(os.size(), bos); bos.write(os.toByteArray()); byte[] message = bos.toByteArray(); safeWriteMessage(ContentType.handshake, message, 0, message.length); connection_state = CS_CLIENT_HELLO_SEND; /* * We will now read data, until we have completed the handshake. */ while (connection_state != CS_DONE) { safeReadData(); } this.tlsInputStream = new TlsInputStream(this); this.tlsOutputStream = new TlsOutputStream(this); }
private static void writeExtension(OutputStream output, Integer extType, byte[] extValue) throws IOException { TlsUtils.writeUint16(extType.intValue(), output); TlsUtils.writeOpaque16(extValue, output); }