0N/A/*
5408N/A * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A
0N/Apackage sun.security.ssl;
0N/A
0N/Aimport java.io.*;
0N/Aimport java.security.*;
0N/Aimport java.security.interfaces.*;
0N/A
0N/Aimport javax.crypto.*;
0N/Aimport javax.crypto.spec.*;
0N/A
0N/Aimport javax.net.ssl.*;
0N/A
0N/Aimport sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
5690N/Aimport sun.security.util.KeyUtil;
0N/A
0N/A/**
0N/A * This is the client key exchange message (CLIENT --> SERVER) used with
0N/A * all RSA key exchanges; it holds the RSA-encrypted pre-master secret.
0N/A *
0N/A * The message is encrypted using PKCS #1 block type 02 encryption with the
0N/A * server's public key. The padding and resulting message size is a function
0N/A * of this server's public key modulus size, but the pre-master secret is
0N/A * always exactly 48 bytes.
0N/A *
0N/A */
0N/Afinal class RSAClientKeyExchange extends HandshakeMessage {
0N/A
0N/A /**
0N/A * The TLS spec says that the version in the RSA premaster secret must
0N/A * be the maximum version supported by the client (i.e. the version it
0N/A * requested in its client hello version). However, we (and other
0N/A * implementations) used to send the active negotiated version. The
0N/A * system property below allows to toggle the behavior.
0N/A */
0N/A private final static String PROP_NAME =
0N/A "com.sun.net.ssl.rsaPreMasterSecretFix";
0N/A
2998N/A /*
2998N/A * Default is "false" (old behavior) for compatibility reasons in
2998N/A * SSLv3/TLSv1. Later protocols (TLSv1.1+) do not use this property.
2998N/A */
0N/A private final static boolean rsaPreMasterSecretFix =
0N/A Debug.getBooleanProperty(PROP_NAME, false);
0N/A
0N/A /*
0N/A * The following field values were encrypted with the server's public
0N/A * key (or temp key from server key exchange msg) and are presented
0N/A * here in DECRYPTED form.
0N/A */
0N/A private ProtocolVersion protocolVersion; // preMaster [0,1]
0N/A SecretKey preMaster;
0N/A private byte[] encrypted; // same size as public modulus
0N/A
0N/A /*
0N/A * Client randomly creates a pre-master secret and encrypts it
0N/A * using the server's RSA public key; only the server can decrypt
0N/A * it, using its RSA private key. Result is the same size as the
0N/A * server's public key, and uses PKCS #1 block format 02.
0N/A */
2998N/A RSAClientKeyExchange(ProtocolVersion protocolVersion,
2998N/A ProtocolVersion maxVersion,
0N/A SecureRandom generator, PublicKey publicKey) throws IOException {
0N/A if (publicKey.getAlgorithm().equals("RSA") == false) {
0N/A throw new SSLKeyException("Public key not of type RSA");
0N/A }
0N/A this.protocolVersion = protocolVersion;
0N/A
0N/A int major, minor;
0N/A
2998N/A if (rsaPreMasterSecretFix || maxVersion.v >= ProtocolVersion.TLS11.v) {
0N/A major = maxVersion.major;
0N/A minor = maxVersion.minor;
0N/A } else {
0N/A major = protocolVersion.major;
0N/A minor = protocolVersion.minor;
0N/A }
0N/A
0N/A try {
3002N/A String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ?
3002N/A "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
3002N/A KeyGenerator kg = JsseJce.getKeyGenerator(s);
3212N/A kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor),
3212N/A generator);
0N/A preMaster = kg.generateKey();
0N/A
0N/A Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
0N/A cipher.init(Cipher.WRAP_MODE, publicKey, generator);
0N/A encrypted = cipher.wrap(preMaster);
0N/A } catch (GeneralSecurityException e) {
0N/A throw (SSLKeyException)new SSLKeyException
0N/A ("RSA premaster secret error").initCause(e);
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * Server gets the PKCS #1 (block format 02) data, decrypts
0N/A * it with its private key.
0N/A */
2998N/A RSAClientKeyExchange(ProtocolVersion currentVersion,
2998N/A ProtocolVersion maxVersion,
2998N/A SecureRandom generator, HandshakeInStream input,
0N/A int messageSize, PrivateKey privateKey) throws IOException {
0N/A
0N/A if (privateKey.getAlgorithm().equals("RSA") == false) {
0N/A throw new SSLKeyException("Private key not of type RSA");
0N/A }
0N/A
0N/A if (currentVersion.v >= ProtocolVersion.TLS10.v) {
0N/A encrypted = input.getBytes16();
0N/A } else {
0N/A encrypted = new byte [messageSize];
0N/A if (input.read(encrypted) != messageSize) {
0N/A throw new SSLProtocolException
0N/A ("SSL: read PreMasterSecret: short read");
0N/A }
0N/A }
0N/A
0N/A try {
0N/A Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
0N/A cipher.init(Cipher.UNWRAP_MODE, privateKey);
0N/A preMaster = (SecretKey)cipher.unwrap(encrypted,
0N/A "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
2998N/A
2998N/A // polish the premaster secret
2998N/A preMaster = polishPreMasterSecretKey(currentVersion, maxVersion,
2998N/A generator, preMaster, null);
0N/A } catch (Exception e) {
2998N/A // polish the premaster secret
2998N/A preMaster =
2998N/A polishPreMasterSecretKey(currentVersion, maxVersion,
2998N/A generator, null, e);
2998N/A }
2998N/A }
2998N/A
2998N/A /**
2998N/A * To avoid vulnerabilities described by section 7.4.7.1, RFC 5246,
2998N/A * treating incorrectly formatted message blocks and/or mismatched
2998N/A * version numbers in a manner indistinguishable from correctly
2998N/A * formatted RSA blocks.
2998N/A *
2998N/A * RFC 5246 describes the approach as :
2998N/A *
2998N/A * 1. Generate a string R of 46 random bytes
2998N/A *
2998N/A * 2. Decrypt the message to recover the plaintext M
2998N/A *
2998N/A * 3. If the PKCS#1 padding is not correct, or the length of message
2998N/A * M is not exactly 48 bytes:
2998N/A * pre_master_secret = ClientHello.client_version || R
2998N/A * else If ClientHello.client_version <= TLS 1.0, and version
2998N/A * number check is explicitly disabled:
2998N/A * pre_master_secret = M
2998N/A * else:
2998N/A * pre_master_secret = ClientHello.client_version || M[2..47]
2998N/A */
2998N/A private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion,
2998N/A ProtocolVersion clientHelloVersion, SecureRandom generator,
2998N/A SecretKey secretKey, Exception failoverException) {
2998N/A
2998N/A this.protocolVersion = clientHelloVersion;
2998N/A
2998N/A if (failoverException == null && secretKey != null) {
2998N/A // check the length
2998N/A byte[] encoded = secretKey.getEncoded();
2998N/A if (encoded == null) { // unable to get the encoded key
2998N/A if (debug != null && Debug.isOn("handshake")) {
2998N/A System.out.println(
2998N/A "unable to get the plaintext of the premaster secret");
2998N/A }
2998N/A
5690N/A int keySize = KeyUtil.getKeySize(secretKey);
5408N/A if (keySize > 0 && keySize != 384) { // 384 = 48 * 8
5408N/A if (debug != null && Debug.isOn("handshake")) {
5408N/A System.out.println(
5408N/A "incorrect length of premaster secret: " +
5408N/A (keySize/8));
5408N/A }
5408N/A
5408N/A return generateDummySecret(clientHelloVersion);
5408N/A }
5408N/A
5408N/A // The key size is exactly 48 bytes or not accessible.
5408N/A //
5408N/A // Conservatively, pass the checking to master secret
2998N/A // calculation.
2998N/A return secretKey;
2998N/A } else if (encoded.length == 48) {
2998N/A // check the version
2998N/A if (clientHelloVersion.major == encoded[0] &&
2998N/A clientHelloVersion.minor == encoded[1]) {
5408N/A
2998N/A return secretKey;
5408N/A } else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v &&
5408N/A currentVersion.major == encoded[0] &&
5408N/A currentVersion.minor == encoded[1]) {
2998N/A /*
5408N/A * For compatibility, we maintain the behavior that the
5408N/A * version in pre_master_secret can be the negotiated
5408N/A * version for TLS v1.0 and SSL v3.0.
2998N/A */
5408N/A this.protocolVersion = currentVersion;
5408N/A return secretKey;
2998N/A }
2998N/A
2998N/A if (debug != null && Debug.isOn("handshake")) {
2998N/A System.out.println("Mismatching Protocol Versions, " +
2998N/A "ClientHello.client_version is " + clientHelloVersion +
2998N/A ", while PreMasterSecret.client_version is " +
2998N/A ProtocolVersion.valueOf(encoded[0], encoded[1]));
2998N/A }
5408N/A
5408N/A return generateDummySecret(clientHelloVersion);
2998N/A } else {
2998N/A if (debug != null && Debug.isOn("handshake")) {
2998N/A System.out.println(
2998N/A "incorrect length of premaster secret: " +
2998N/A encoded.length);
2998N/A }
5408N/A
5408N/A return generateDummySecret(clientHelloVersion);
2998N/A }
2998N/A }
2998N/A
5408N/A if (debug != null && Debug.isOn("handshake") &&
5408N/A failoverException != null) {
5408N/A System.out.println("Error decrypting premaster secret:");
5408N/A failoverException.printStackTrace(System.out);
0N/A }
2998N/A
2998N/A return generateDummySecret(clientHelloVersion);
0N/A }
0N/A
0N/A // generate a premaster secret with the specified version number
0N/A static SecretKey generateDummySecret(ProtocolVersion version) {
5408N/A if (debug != null && Debug.isOn("handshake")) {
5408N/A System.out.println("Generating a random fake premaster secret");
5408N/A }
5408N/A
0N/A try {
3002N/A String s = ((version.v >= ProtocolVersion.TLS12.v) ?
3002N/A "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
3002N/A KeyGenerator kg = JsseJce.getKeyGenerator(s);
0N/A kg.init(new TlsRsaPremasterSecretParameterSpec
0N/A (version.major, version.minor));
0N/A return kg.generateKey();
0N/A } catch (GeneralSecurityException e) {
0N/A throw new RuntimeException("Could not generate dummy secret", e);
0N/A }
0N/A }
0N/A
2998N/A @Override
2998N/A int messageType() {
2998N/A return ht_client_key_exchange;
2998N/A }
2998N/A
2998N/A @Override
0N/A int messageLength() {
0N/A if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
0N/A return encrypted.length + 2;
0N/A } else {
0N/A return encrypted.length;
0N/A }
0N/A }
0N/A
2998N/A @Override
0N/A void send(HandshakeOutStream s) throws IOException {
0N/A if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
0N/A s.putBytes16(encrypted);
0N/A } else {
0N/A s.write(encrypted);
0N/A }
0N/A }
0N/A
2998N/A @Override
0N/A void print(PrintStream s) throws IOException {
2998N/A s.println("*** ClientKeyExchange, RSA PreMasterSecret, " +
2998N/A protocolVersion);
0N/A }
0N/A}