src/java.base/share/classes/sun/security/ssl/RSAClientKeyExchange.java
changeset 50768 68fa3d4026ea
parent 47216 71c04702a3d5
child 53064 103ed9569fc8
equal deleted inserted replaced
50767:356eaea05bf0 50768:68fa3d4026ea
     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 
       
    77             if (m.remaining() < 2) {
       
    78                 context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
    79                     "Invalid RSA ClientKeyExchange message: insufficient data");
       
    80             }
       
    81 
       
    82             this.protocolVersion = context.clientHelloVersion;
       
    83             this.useTLS10PlusSpec = ProtocolVersion.useTLS10PlusSpec(
       
    84                     protocolVersion, context.sslContext.isDTLS());
       
    85             if (useTLS10PlusSpec) {
       
    86                 this.encrypted = Record.getBytes16(m);
       
    87             } else {    //  SSL 3.0
       
    88                 this.encrypted = new byte[m.remaining()];
       
    89                 m.get(encrypted);
       
    90             }
       
    91         }
       
    92 
       
    93         @Override
       
    94         public SSLHandshake handshakeType() {
       
    95             return SSLHandshake.CLIENT_KEY_EXCHANGE;
       
    96         }
       
    97 
       
    98         @Override
       
    99         public int messageLength() {
       
   100             if (useTLS10PlusSpec) {
       
   101                 return encrypted.length + 2;
       
   102             } else {
       
   103                 return encrypted.length;
       
   104             }
       
   105         }
       
   106 
       
   107         @Override
       
   108         public void send(HandshakeOutStream hos) throws IOException {
       
   109             if (useTLS10PlusSpec) {
       
   110                 hos.putBytes16(encrypted);
       
   111             } else {
       
   112                 hos.write(encrypted);
       
   113             }
       
   114         }
       
   115 
       
   116         @Override
       
   117         public String toString() {
       
   118             MessageFormat messageFormat = new MessageFormat(
       
   119                 "\"RSA ClientKeyExchange\": '{'\n" +
       
   120                 "  \"client_version\":  {0}\n" +
       
   121                 "  \"encncrypted\": '{'\n" +
       
   122                 "{1}\n" +
       
   123                 "  '}'\n" +
       
   124                 "'}'",
       
   125                 Locale.ENGLISH);
       
   126 
       
   127             HexDumpEncoder hexEncoder = new HexDumpEncoder();
       
   128             Object[] messageFields = {
       
   129                 ProtocolVersion.nameOf(protocolVersion),
       
   130                 Utilities.indent(
       
   131                         hexEncoder.encodeBuffer(encrypted), "    "),
       
   132             };
       
   133             return messageFormat.format(messageFields);
       
   134         }
       
   135     }
       
   136 
       
   137     /**
       
   138      * The RSA "ClientKeyExchange" handshake message producer.
    65      */
   139      */
    66     @SuppressWarnings("deprecation")
   140     private static final
    67     RSAClientKeyExchange(ProtocolVersion protocolVersion,
   141             class RSAClientKeyExchangeProducer implements HandshakeProducer {
    68             ProtocolVersion maxVersion,
   142         // Prevent instantiation of this class.
    69             SecureRandom generator, PublicKey publicKey) throws IOException {
   143         private RSAClientKeyExchangeProducer() {
    70         if (publicKey.getAlgorithm().equals("RSA") == false) {
   144             // blank
    71             throw new SSLKeyException("Public key not of type RSA: " +
   145         }
    72                 publicKey.getAlgorithm());
   146 
    73         }
   147         @Override
    74         this.protocolVersion = protocolVersion;
   148         public byte[] produce(ConnectionContext context,
    75 
   149                 HandshakeMessage message) throws IOException {
    76         try {
   150             // This happens in client side only.
    77             String s = protocolVersion.useTLS12PlusSpec() ?
   151             ClientHandshakeContext chc = (ClientHandshakeContext)context;
    78                 "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret";
   152 
    79             KeyGenerator kg = JsseJce.getKeyGenerator(s);
   153             EphemeralRSACredentials rsaCredentials = null;
    80             kg.init(new TlsRsaPremasterSecretParameterSpec(
   154             X509Credentials x509Credentials = null;
    81                     maxVersion.v, protocolVersion.v), generator);
   155             for (SSLCredentials credential : chc.handshakeCredentials) {
    82             preMaster = kg.generateKey();
   156                 if (credential instanceof EphemeralRSACredentials) {
    83 
   157                     rsaCredentials = (EphemeralRSACredentials)credential;
    84             Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
   158                     if (x509Credentials != null) {
    85             cipher.init(Cipher.WRAP_MODE, publicKey, generator);
   159                         break;
    86             encrypted = cipher.wrap(preMaster);
   160                     }
    87         } catch (GeneralSecurityException e) {
   161                 } else if (credential instanceof X509Credentials) {
    88             throw (SSLKeyException)new SSLKeyException
   162                     x509Credentials = (X509Credentials)credential;
    89                                 ("RSA premaster secret error").initCause(e);
   163                     if (rsaCredentials != null) {
       
   164                         break;
       
   165                     }
       
   166                 }
       
   167             }
       
   168 
       
   169             if (rsaCredentials == null && x509Credentials == null) {
       
   170                 chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   171                     "No RSA credentials negotiated for client key exchange");
       
   172             }
       
   173 
       
   174             PublicKey publicKey = (rsaCredentials != null) ?
       
   175                     rsaCredentials.popPublicKey : x509Credentials.popPublicKey;
       
   176             if (!publicKey.getAlgorithm().equals("RSA")) {      // unlikely
       
   177                 chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   178                     "Not RSA public key for client key exchange");
       
   179             }
       
   180 
       
   181             RSAPremasterSecret premaster;
       
   182             RSAClientKeyExchangeMessage ckem;
       
   183             try {
       
   184                 premaster = RSAPremasterSecret.createPremasterSecret(chc);
       
   185                 chc.handshakePossessions.add(premaster);
       
   186                 ckem = new RSAClientKeyExchangeMessage(
       
   187                         chc, premaster, publicKey);
       
   188             } catch (GeneralSecurityException gse) {
       
   189                 chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   190                         "Cannot generate RSA premaster secret", gse);
       
   191 
       
   192                 return null;    // make the compiler happy
       
   193             }
       
   194             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   195                 SSLLogger.fine(
       
   196                     "Produced RSA ClientKeyExchange handshake message", ckem);
       
   197             }
       
   198 
       
   199             // Output the handshake message.
       
   200             ckem.write(chc.handshakeOutput);
       
   201             chc.handshakeOutput.flush();
       
   202 
       
   203             // update the states
       
   204             SSLKeyExchange ke = SSLKeyExchange.valueOf(
       
   205                     chc.negotiatedCipherSuite.keyExchange,
       
   206                     chc.negotiatedProtocol);
       
   207             if (ke == null) {   // unlikely
       
   208                 chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   209                         "Not supported key exchange type");
       
   210             } else {
       
   211                 SSLKeyDerivation masterKD = ke.createKeyDerivation(chc);
       
   212                 SecretKey masterSecret =
       
   213                         masterKD.deriveKey("MasterSecret", null);
       
   214 
       
   215                 // update the states
       
   216                 chc.handshakeSession.setMasterSecret(masterSecret);
       
   217                 SSLTrafficKeyDerivation kd =
       
   218                         SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
       
   219                 if (kd == null) {   // unlikely
       
   220                     chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   221                             "Not supported key derivation: " +
       
   222                             chc.negotiatedProtocol);
       
   223                 } else {
       
   224                     chc.handshakeKeyDerivation =
       
   225                         kd.createKeyDerivation(chc, masterSecret);
       
   226                 }
       
   227             }
       
   228 
       
   229             // The handshake message has been delivered.
       
   230             return null;
    90         }
   231         }
    91     }
   232     }
    92 
   233 
    93     /*
   234     /**
    94      * Retrieving the cipher's provider name for the debug purposes
   235      * The RSA "ClientKeyExchange" handshake message consumer.
    95      * can throw an exception by itself.
       
    96      */
   236      */
    97     private static String safeProviderName(Cipher cipher) {
   237     private static final
    98         try {
   238             class RSAClientKeyExchangeConsumer implements SSLConsumer {
    99             return cipher.getProvider().toString();
   239         // Prevent instantiation of this class.
   100         } catch (Exception e) {
   240         private RSAClientKeyExchangeConsumer() {
   101             if (debug != null && Debug.isOn("handshake")) {
   241             // blank
   102                 System.out.println("Retrieving The Cipher provider name" +
   242         }
   103                         " caused exception " + e.getMessage());
   243 
   104             }
   244         @Override
   105         }
   245         public void consume(ConnectionContext context,
   106         try {
   246                 ByteBuffer message) throws IOException {
   107             return cipher.toString() + " (provider name not available)";
   247             // The consuming happens in server side only.
   108         } catch (Exception e) {
   248             ServerHandshakeContext shc = (ServerHandshakeContext)context;
   109             if (debug != null && Debug.isOn("handshake")) {
   249 
   110                 System.out.println("Retrieving The Cipher name" +
   250             EphemeralRSAPossession rsaPossession = null;
   111                         " caused exception " + e.getMessage());
   251             X509Possession x509Possession = null;
   112             }
   252             for (SSLPossession possession : shc.handshakePossessions) {
   113         }
   253                 if (possession instanceof EphemeralRSAPossession) {
   114         return "(cipher/provider names not available)";
   254                     rsaPossession = (EphemeralRSAPossession)possession;
   115     }
   255                     break;
   116 
   256                 } else if (possession instanceof X509Possession) {
   117     /*
   257                     x509Possession = (X509Possession)possession;
   118      * Server gets the PKCS #1 (block format 02) data, decrypts
   258                     if (rsaPossession != null) {
   119      * it with its private key.
   259                         break;
   120      */
   260                     }
   121     @SuppressWarnings("deprecation")
   261                 }
   122     RSAClientKeyExchange(ProtocolVersion currentVersion,
   262             }
   123             ProtocolVersion maxVersion,
   263 
   124             SecureRandom generator, HandshakeInStream input,
   264             if (rsaPossession == null && x509Possession == null) {  // unlikely
   125             int messageSize, PrivateKey privateKey) throws IOException {
   265                 shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
   126 
   266                     "No RSA possessions negotiated for client key exchange");
   127         if (privateKey.getAlgorithm().equals("RSA") == false) {
   267             }
   128             throw new SSLKeyException("Private key not of type RSA: " +
   268 
   129                  privateKey.getAlgorithm());
   269             PrivateKey privateKey = (rsaPossession != null) ?
   130         }
   270                     rsaPossession.popPrivateKey : x509Possession.popPrivateKey;
   131 
   271             if (!privateKey.getAlgorithm().equals("RSA")) {     // unlikely
   132         if (currentVersion.useTLS10PlusSpec()) {
   272                 shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
   133             encrypted = input.getBytes16();
   273                     "Not RSA private key for client key exchange");
   134         } else {
   274             }
   135             encrypted = new byte [messageSize];
   275 
   136             if (input.read(encrypted) != messageSize) {
   276             RSAClientKeyExchangeMessage ckem =
   137                 throw new SSLProtocolException(
   277                     new RSAClientKeyExchangeMessage(shc, message);
   138                         "SSL: read PreMasterSecret: short read");
   278             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   139             }
   279                 SSLLogger.fine(
   140         }
   280                     "Consuming RSA ClientKeyExchange handshake message", ckem);
   141 
   281             }
   142         byte[] encoded = null;
   282 
   143         try {
   283             // create the credentials
   144             boolean needFailover = false;
   284             RSAPremasterSecret premaster;
   145             Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
       
   146             try {
   285             try {
   147                 // Try UNWRAP_MODE mode firstly.
   286                 premaster =
   148                 cipher.init(Cipher.UNWRAP_MODE, privateKey,
   287                     RSAPremasterSecret.decode(shc, privateKey, ckem.encrypted);
   149                         new TlsRsaPremasterSecretParameterSpec(
   288                 shc.handshakeCredentials.add(premaster);
   150                                 maxVersion.v, currentVersion.v),
   289             } catch (GeneralSecurityException gse) {
   151                         generator);
   290                 shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
   152 
   291                     "Cannot decode RSA premaster secret", gse);
   153                 // The provider selection can be delayed, please don't call
   292             }
   154                 // any Cipher method before the call to Cipher.init().
   293 
   155                 needFailover = !KeyUtil.isOracleJCEProvider(
   294             // update the states
   156                         cipher.getProvider().getName());
   295             SSLKeyExchange ke = SSLKeyExchange.valueOf(
   157             } catch (InvalidKeyException | UnsupportedOperationException iue) {
   296                     shc.negotiatedCipherSuite.keyExchange,
   158                 if (debug != null && Debug.isOn("handshake")) {
   297                     shc.negotiatedProtocol);
   159                     System.out.println("The Cipher provider "
   298             if (ke == null) {   // unlikely
   160                             + safeProviderName(cipher)
   299                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
   161                             + " caused exception: " + iue.getMessage());
   300                         "Not supported key exchange type");
       
   301             } else {
       
   302                 SSLKeyDerivation masterKD = ke.createKeyDerivation(shc);
       
   303                 SecretKey masterSecret =
       
   304                         masterKD.deriveKey("MasterSecret", null);
       
   305 
       
   306                 // update the states
       
   307                 shc.handshakeSession.setMasterSecret(masterSecret);
       
   308                 SSLTrafficKeyDerivation kd =
       
   309                         SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
       
   310                 if (kd == null) {       // unlikely
       
   311                     shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   312                             "Not supported key derivation: " +
       
   313                             shc.negotiatedProtocol);
       
   314                 } else {
       
   315                     shc.handshakeKeyDerivation =
       
   316                         kd.createKeyDerivation(shc, masterSecret);
   162                 }
   317                 }
   163 
   318             }
   164                 needFailover = true;
   319         }
   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     }
   320     }
   269 }
   321 }