src/java.base/share/classes/sun/security/ssl/RSAClientKeyExchange.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
parent 47216 71c04702a3d5
child 56603 f103e0c2be1e
equal deleted inserted replaced
56541:92cbbfc996f3 56542:56aaa6cb3693
     1 /*
     1 /*
     2  * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 
       
    27 package sun.security.ssl;
    26 package sun.security.ssl;
    28 
    27 
    29 import java.io.*;
    28 import java.io.IOException;
    30 import java.security.*;
    29 import java.nio.ByteBuffer;
    31 
    30 import java.security.GeneralSecurityException;
    32 import javax.crypto.*;
    31 import java.security.PrivateKey;
    33 
    32 import java.security.PublicKey;
    34 import javax.net.ssl.*;
    33 import java.text.MessageFormat;
    35 
    34 import java.util.Locale;
    36 import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
    35 import javax.crypto.SecretKey;
    37 import sun.security.util.KeyUtil;
    36 import sun.security.ssl.RSAKeyExchange.EphemeralRSACredentials;
       
    37 import sun.security.ssl.RSAKeyExchange.EphemeralRSAPossession;
       
    38 import sun.security.ssl.RSAKeyExchange.RSAPremasterSecret;
       
    39 import sun.security.ssl.SSLHandshake.HandshakeMessage;
       
    40 import sun.security.ssl.X509Authentication.X509Credentials;
       
    41 import sun.security.ssl.X509Authentication.X509Possession;
       
    42 import sun.security.util.HexDumpEncoder;
    38 
    43 
    39 /**
    44 /**
    40  * This is the client key exchange message (CLIENT --> SERVER) used with
    45  * Pack of the "ClientKeyExchange" handshake message.
    41  * all RSA key exchanges; it holds the RSA-encrypted pre-master secret.
       
    42  *
       
    43  * The message is encrypted using PKCS #1 block type 02 encryption with the
       
    44  * server's public key.  The padding and resulting message size is a function
       
    45  * of this server's public key modulus size, but the pre-master secret is
       
    46  * always exactly 48 bytes.
       
    47  *
       
    48  */
    46  */
    49 final class RSAClientKeyExchange extends HandshakeMessage {
    47 final class RSAClientKeyExchange {
    50 
    48     static final SSLConsumer rsaHandshakeConsumer =
    51     /*
    49         new RSAClientKeyExchangeConsumer();
    52      * The following field values were encrypted with the server's public
    50     static final HandshakeProducer rsaHandshakeProducer =
    53      * key (or temp key from server key exchange msg) and are presented
    51         new RSAClientKeyExchangeProducer();
    54      * here in DECRYPTED form.
    52 
       
    53     /**
       
    54      * The RSA ClientKeyExchange handshake message.
    55      */
    55      */
    56     private ProtocolVersion protocolVersion; // preMaster [0,1]
    56     private static final
    57     SecretKey preMaster;
    57             class RSAClientKeyExchangeMessage extends HandshakeMessage {
    58     private byte[] encrypted;           // same size as public modulus
    58         final int protocolVersion;
    59 
    59         final boolean useTLS10PlusSpec;
    60     /*
    60         final byte[] encrypted;
    61      * Client randomly creates a pre-master secret and encrypts it
    61 
    62      * using the server's RSA public key; only the server can decrypt
    62         RSAClientKeyExchangeMessage(HandshakeContext context,
    63      * it, using its RSA private key.  Result is the same size as the
    63                 RSAPremasterSecret premaster,
    64      * server's public key, and uses PKCS #1 block format 02.
    64                 PublicKey publicKey) throws GeneralSecurityException {
       
    65             super(context);
       
    66             this.protocolVersion = context.clientHelloVersion;
       
    67             this.encrypted = premaster.getEncoded(
       
    68                     publicKey, context.sslContext.getSecureRandom());
       
    69             this.useTLS10PlusSpec = ProtocolVersion.useTLS10PlusSpec(
       
    70                     protocolVersion, context.sslContext.isDTLS());
       
    71         }
       
    72 
       
    73         RSAClientKeyExchangeMessage(HandshakeContext context,
       
    74                 ByteBuffer m) throws IOException {
       
    75             super(context);
       
    76             // This happens in server side only.
       
    77             ServerHandshakeContext shc =
       
    78                     (ServerHandshakeContext)handshakeContext;
       
    79 
       
    80             if (m.remaining() < 2) {
       
    81                 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
    82                     "Invalid RSA ClientKeyExchange message: insufficient data");
       
    83             }
       
    84 
       
    85             this.protocolVersion = context.clientHelloVersion;
       
    86             this.useTLS10PlusSpec = ProtocolVersion.useTLS10PlusSpec(
       
    87                     protocolVersion, context.sslContext.isDTLS());
       
    88             if (useTLS10PlusSpec) {
       
    89                 this.encrypted = Record.getBytes16(m);
       
    90             } else {    //  SSL 3.0
       
    91                 this.encrypted = new byte[m.remaining()];
       
    92                 m.get(encrypted);
       
    93             }
       
    94         }
       
    95 
       
    96         @Override
       
    97         public SSLHandshake handshakeType() {
       
    98             return SSLHandshake.CLIENT_KEY_EXCHANGE;
       
    99         }
       
   100 
       
   101         @Override
       
   102         public int messageLength() {
       
   103             if (useTLS10PlusSpec) {
       
   104                 return encrypted.length + 2;
       
   105             } else {
       
   106                 return encrypted.length;
       
   107             }
       
   108         }
       
   109 
       
   110         @Override
       
   111         public void send(HandshakeOutStream hos) throws IOException {
       
   112             if (useTLS10PlusSpec) {
       
   113                 hos.putBytes16(encrypted);
       
   114             } else {
       
   115                 hos.write(encrypted);
       
   116             }
       
   117         }
       
   118 
       
   119         @Override
       
   120         public String toString() {
       
   121             MessageFormat messageFormat = new MessageFormat(
       
   122                 "\"RSA ClientKeyExchange\": '{'\n" +
       
   123                 "  \"client_version\":  {0}\n" +
       
   124                 "  \"encncrypted\": '{'\n" +
       
   125                 "{1}\n" +
       
   126                 "  '}'\n" +
       
   127                 "'}'",
       
   128                 Locale.ENGLISH);
       
   129 
       
   130             HexDumpEncoder hexEncoder = new HexDumpEncoder();
       
   131             Object[] messageFields = {
       
   132                 ProtocolVersion.nameOf(protocolVersion),
       
   133                 Utilities.indent(
       
   134                         hexEncoder.encodeBuffer(encrypted), "    "),
       
   135             };
       
   136             return messageFormat.format(messageFields);
       
   137         }
       
   138     }
       
   139 
       
   140     /**
       
   141      * The RSA "ClientKeyExchange" handshake message producer.
    65      */
   142      */
    66     @SuppressWarnings("deprecation")
   143     private static final
    67     RSAClientKeyExchange(ProtocolVersion protocolVersion,
   144             class RSAClientKeyExchangeProducer implements HandshakeProducer {
    68             ProtocolVersion maxVersion,
   145         // Prevent instantiation of this class.
    69             SecureRandom generator, PublicKey publicKey) throws IOException {
   146         private RSAClientKeyExchangeProducer() {
    70         if (publicKey.getAlgorithm().equals("RSA") == false) {
   147             // blank
    71             throw new SSLKeyException("Public key not of type RSA: " +
   148         }
    72                 publicKey.getAlgorithm());
   149 
    73         }
   150         @Override
    74         this.protocolVersion = protocolVersion;
   151         public byte[] produce(ConnectionContext context,
    75 
   152                 HandshakeMessage message) throws IOException {
    76         try {
   153             // This happens in client side only.
    77             String s = protocolVersion.useTLS12PlusSpec() ?
   154             ClientHandshakeContext chc = (ClientHandshakeContext)context;
    78                 "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret";
   155 
    79             KeyGenerator kg = JsseJce.getKeyGenerator(s);
   156             EphemeralRSACredentials rsaCredentials = null;
    80             kg.init(new TlsRsaPremasterSecretParameterSpec(
   157             X509Credentials x509Credentials = null;
    81                     maxVersion.v, protocolVersion.v), generator);
   158             for (SSLCredentials credential : chc.handshakeCredentials) {
    82             preMaster = kg.generateKey();
   159                 if (credential instanceof EphemeralRSACredentials) {
    83 
   160                     rsaCredentials = (EphemeralRSACredentials)credential;
    84             Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
   161                     if (x509Credentials != null) {
    85             cipher.init(Cipher.WRAP_MODE, publicKey, generator);
   162                         break;
    86             encrypted = cipher.wrap(preMaster);
   163                     }
    87         } catch (GeneralSecurityException e) {
   164                 } else if (credential instanceof X509Credentials) {
    88             throw (SSLKeyException)new SSLKeyException
   165                     x509Credentials = (X509Credentials)credential;
    89                                 ("RSA premaster secret error").initCause(e);
   166                     if (rsaCredentials != null) {
       
   167                         break;
       
   168                     }
       
   169                 }
       
   170             }
       
   171 
       
   172             if (rsaCredentials == null && x509Credentials == null) {
       
   173                 chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   174                     "No RSA credentials negotiated for client key exchange");
       
   175             }
       
   176 
       
   177             PublicKey publicKey = (rsaCredentials != null) ?
       
   178                     rsaCredentials.popPublicKey : x509Credentials.popPublicKey;
       
   179             if (!publicKey.getAlgorithm().equals("RSA")) {      // unlikely
       
   180                 chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   181                     "Not RSA public key for client key exchange");
       
   182             }
       
   183 
       
   184             RSAPremasterSecret premaster;
       
   185             RSAClientKeyExchangeMessage ckem;
       
   186             try {
       
   187                 premaster = RSAPremasterSecret.createPremasterSecret(chc);
       
   188                 chc.handshakePossessions.add(premaster);
       
   189                 ckem = new RSAClientKeyExchangeMessage(
       
   190                         chc, premaster, publicKey);
       
   191             } catch (GeneralSecurityException gse) {
       
   192                 chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   193                     "Cannot generate RSA premaster secret", gse);
       
   194 
       
   195                 return null;    // make the compiler happy
       
   196             }
       
   197             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   198                 SSLLogger.fine(
       
   199                     "Produced RSA ClientKeyExchange handshake message", ckem);
       
   200             }
       
   201 
       
   202             // Output the handshake message.
       
   203             ckem.write(chc.handshakeOutput);
       
   204             chc.handshakeOutput.flush();
       
   205 
       
   206             // update the states
       
   207             SSLKeyExchange ke =
       
   208                 SSLKeyExchange.valueOf(chc.negotiatedCipherSuite.keyExchange);
       
   209             if (ke == null) {   // unlikely
       
   210                 chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   211                         "Not supported key exchange type");
       
   212             } else {
       
   213                 SSLKeyDerivation masterKD = ke.createKeyDerivation(chc);
       
   214                 SecretKey masterSecret = masterKD.deriveKey("TODO", null);
       
   215 
       
   216                 // update the states
       
   217                 chc.handshakeSession.setMasterSecret(masterSecret);
       
   218                 SSLTrafficKeyDerivation kd =
       
   219                         SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
       
   220                 if (kd == null) {   // unlikely
       
   221                     chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   222                             "Not supported key derivation: " +
       
   223                             chc.negotiatedProtocol);
       
   224                 } else {
       
   225                     chc.handshakeKeyDerivation =
       
   226                         kd.createKeyDerivation(chc, masterSecret);
       
   227                 }
       
   228             }
       
   229 
       
   230             // The handshake message has been delivered.
       
   231             return null;
    90         }
   232         }
    91     }
   233     }
    92 
   234 
    93     /*
   235     /**
    94      * Retrieving the cipher's provider name for the debug purposes
   236      * The RSA "ClientKeyExchange" handshake message consumer.
    95      * can throw an exception by itself.
       
    96      */
   237      */
    97     private static String safeProviderName(Cipher cipher) {
   238     private static final
    98         try {
   239             class RSAClientKeyExchangeConsumer implements SSLConsumer {
    99             return cipher.getProvider().toString();
   240         // Prevent instantiation of this class.
   100         } catch (Exception e) {
   241         private RSAClientKeyExchangeConsumer() {
   101             if (debug != null && Debug.isOn("handshake")) {
   242             // blank
   102                 System.out.println("Retrieving The Cipher provider name" +
   243         }
   103                         " caused exception " + e.getMessage());
   244 
   104             }
   245         @Override
   105         }
   246         public void consume(ConnectionContext context,
   106         try {
   247                 ByteBuffer message) throws IOException {
   107             return cipher.toString() + " (provider name not available)";
   248             // The consuming happens in server side only.
   108         } catch (Exception e) {
   249             ServerHandshakeContext shc = (ServerHandshakeContext)context;
   109             if (debug != null && Debug.isOn("handshake")) {
   250 
   110                 System.out.println("Retrieving The Cipher name" +
   251             EphemeralRSAPossession rsaPossession = null;
   111                         " caused exception " + e.getMessage());
   252             X509Possession x509Possession = null;
   112             }
   253             for (SSLPossession possession : shc.handshakePossessions) {
   113         }
   254                 if (possession instanceof EphemeralRSAPossession) {
   114         return "(cipher/provider names not available)";
   255                     rsaPossession = (EphemeralRSAPossession)possession;
   115     }
   256                     break;
   116 
   257                 } else if (possession instanceof X509Possession) {
   117     /*
   258                     x509Possession = (X509Possession)possession;
   118      * Server gets the PKCS #1 (block format 02) data, decrypts
   259                     if (rsaPossession != null) {
   119      * it with its private key.
   260                         break;
   120      */
   261                     }
   121     @SuppressWarnings("deprecation")
   262                 }
   122     RSAClientKeyExchange(ProtocolVersion currentVersion,
   263             }
   123             ProtocolVersion maxVersion,
   264 
   124             SecureRandom generator, HandshakeInStream input,
   265             if (rsaPossession == null && x509Possession == null) {  // unlikely
   125             int messageSize, PrivateKey privateKey) throws IOException {
   266                 shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
   126 
   267                     "No RSA possessions negotiated for client key exchange");
   127         if (privateKey.getAlgorithm().equals("RSA") == false) {
   268             }
   128             throw new SSLKeyException("Private key not of type RSA: " +
   269 
   129                  privateKey.getAlgorithm());
   270             PrivateKey privateKey = (rsaPossession != null) ?
   130         }
   271                     rsaPossession.popPrivateKey : x509Possession.popPrivateKey;
   131 
   272             if (!privateKey.getAlgorithm().equals("RSA")) {     // unlikely
   132         if (currentVersion.useTLS10PlusSpec()) {
   273                 shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
   133             encrypted = input.getBytes16();
   274                     "Not RSA private key for client key exchange");
   134         } else {
   275             }
   135             encrypted = new byte [messageSize];
   276 
   136             if (input.read(encrypted) != messageSize) {
   277             RSAClientKeyExchangeMessage ckem =
   137                 throw new SSLProtocolException(
   278                     new RSAClientKeyExchangeMessage(shc, message);
   138                         "SSL: read PreMasterSecret: short read");
   279             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   139             }
   280                 SSLLogger.fine(
   140         }
   281                     "Consuming RSA ClientKeyExchange handshake message", ckem);
   141 
   282             }
   142         byte[] encoded = null;
   283 
   143         try {
   284             // create the credentials
   144             boolean needFailover = false;
   285             RSAPremasterSecret premaster;
   145             Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
       
   146             try {
   286             try {
   147                 // Try UNWRAP_MODE mode firstly.
   287                 premaster =
   148                 cipher.init(Cipher.UNWRAP_MODE, privateKey,
   288                     RSAPremasterSecret.decode(shc, privateKey, ckem.encrypted);
   149                         new TlsRsaPremasterSecretParameterSpec(
   289                 shc.handshakeCredentials.add(premaster);
   150                                 maxVersion.v, currentVersion.v),
   290             } catch (GeneralSecurityException gse) {
   151                         generator);
   291                 shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
   152 
   292                     "Cannot decode RSA premaster secret", gse);
   153                 // The provider selection can be delayed, please don't call
   293             }
   154                 // any Cipher method before the call to Cipher.init().
   294 
   155                 needFailover = !KeyUtil.isOracleJCEProvider(
   295             // update the states
   156                         cipher.getProvider().getName());
   296             SSLKeyExchange ke =
   157             } catch (InvalidKeyException | UnsupportedOperationException iue) {
   297                 SSLKeyExchange.valueOf(shc.negotiatedCipherSuite.keyExchange);
   158                 if (debug != null && Debug.isOn("handshake")) {
   298             if (ke == null) {   // unlikely
   159                     System.out.println("The Cipher provider "
   299                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
   160                             + safeProviderName(cipher)
   300                         "Not supported key exchange type");
   161                             + " caused exception: " + iue.getMessage());
   301             } else {
       
   302                 SSLKeyDerivation masterKD = ke.createKeyDerivation(shc);
       
   303                 SecretKey masterSecret = masterKD.deriveKey("TODO", null);
       
   304 
       
   305                 // update the states
       
   306                 shc.handshakeSession.setMasterSecret(masterSecret);
       
   307                 SSLTrafficKeyDerivation kd =
       
   308                         SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
       
   309                 if (kd == null) {       // unlikely
       
   310                     shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   311                             "Not supported key derivation: " +
       
   312                             shc.negotiatedProtocol);
       
   313                 } else {
       
   314                     shc.handshakeKeyDerivation =
       
   315                         kd.createKeyDerivation(shc, masterSecret);
   162                 }
   316                 }
   163 
   317             }
   164                 needFailover = true;
   318         }
   165             }
       
   166 
       
   167             if (needFailover) {
       
   168                 // The cipher might be spoiled by unsuccessful call to init(),
       
   169                 // so request a fresh instance
       
   170                 cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
       
   171 
       
   172                 // Use DECRYPT_MODE and dispose the previous initialization.
       
   173                 cipher.init(Cipher.DECRYPT_MODE, privateKey);
       
   174                 boolean failed = false;
       
   175                 try {
       
   176                     encoded = cipher.doFinal(encrypted);
       
   177                 } catch (BadPaddingException bpe) {
       
   178                     // Note: encoded == null
       
   179                     failed = true;
       
   180                 }
       
   181                 encoded = KeyUtil.checkTlsPreMasterSecretKey(
       
   182                                 maxVersion.v, currentVersion.v,
       
   183                                 generator, encoded, failed);
       
   184                 preMaster = generatePreMasterSecret(
       
   185                                 maxVersion.v, currentVersion.v,
       
   186                                 encoded, generator);
       
   187             } else {
       
   188                 // the cipher should have been initialized
       
   189                 preMaster = (SecretKey)cipher.unwrap(encrypted,
       
   190                         "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
       
   191             }
       
   192         } catch (InvalidKeyException ibk) {
       
   193             // the message is too big to process with RSA
       
   194             throw new SSLException(
       
   195                 "Unable to process PreMasterSecret", ibk);
       
   196         } catch (Exception e) {
       
   197             // unlikely to happen, otherwise, must be a provider exception
       
   198             if (debug != null && Debug.isOn("handshake")) {
       
   199                 System.out.println("RSA premaster secret decryption error:");
       
   200                 e.printStackTrace(System.out);
       
   201             }
       
   202             throw new RuntimeException("Could not generate dummy secret", e);
       
   203         }
       
   204     }
       
   205 
       
   206     // generate a premaster secret with the specified version number
       
   207     @SuppressWarnings("deprecation")
       
   208     private static SecretKey generatePreMasterSecret(
       
   209             int clientVersion, int serverVersion,
       
   210             byte[] encodedSecret, SecureRandom generator) {
       
   211 
       
   212         if (debug != null && Debug.isOn("handshake")) {
       
   213             System.out.println("Generating a premaster secret");
       
   214         }
       
   215 
       
   216         try {
       
   217             String s = ((clientVersion >= ProtocolVersion.TLS12.v) ?
       
   218                 "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
       
   219             KeyGenerator kg = JsseJce.getKeyGenerator(s);
       
   220             kg.init(new TlsRsaPremasterSecretParameterSpec(
       
   221                     clientVersion, serverVersion, encodedSecret),
       
   222                     generator);
       
   223             return kg.generateKey();
       
   224         } catch (InvalidAlgorithmParameterException |
       
   225                 NoSuchAlgorithmException iae) {
       
   226             // unlikely to happen, otherwise, must be a provider exception
       
   227             if (debug != null && Debug.isOn("handshake")) {
       
   228                 System.out.println("RSA premaster secret generation error:");
       
   229                 iae.printStackTrace(System.out);
       
   230             }
       
   231             throw new RuntimeException("Could not generate premaster secret", iae);
       
   232         }
       
   233     }
       
   234 
       
   235     @Override
       
   236     int messageType() {
       
   237         return ht_client_key_exchange;
       
   238     }
       
   239 
       
   240     @Override
       
   241     int messageLength() {
       
   242         if (protocolVersion.useTLS10PlusSpec()) {
       
   243             return encrypted.length + 2;
       
   244         } else {
       
   245             return encrypted.length;
       
   246         }
       
   247     }
       
   248 
       
   249     @Override
       
   250     void send(HandshakeOutStream s) throws IOException {
       
   251         if (protocolVersion.useTLS10PlusSpec()) {
       
   252             s.putBytes16(encrypted);
       
   253         } else {
       
   254             s.write(encrypted);
       
   255         }
       
   256     }
       
   257 
       
   258     @Override
       
   259     void print(PrintStream s) throws IOException {
       
   260         String version = "version not available/extractable";
       
   261 
       
   262         byte[] ba = preMaster.getEncoded();
       
   263         if (ba != null && ba.length >= 2) {
       
   264             version = ProtocolVersion.valueOf(ba[0], ba[1]).name;
       
   265         }
       
   266 
       
   267         s.println("*** ClientKeyExchange, RSA PreMasterSecret, " + version);
       
   268     }
   319     }
   269 }
   320 }