1 /* 2 * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 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 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 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 23 * questions. 24 */ 25 26 27 package sun.security.ssl; 28 29 import java.io.*; 30 import java.security.*; 31 32 import javax.crypto.*; 33 34 import javax.net.ssl.*; 35 36 import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec; 37 import sun.security.util.KeyUtil; 38 39 /** 40 * This is the client key exchange message (CLIENT --> SERVER) used with 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 */ 49 final class RSAClientKeyExchange extends HandshakeMessage { 50 51 /* 52 * The following field values were encrypted with the server's public 53 * key (or temp key from server key exchange msg) and are presented 54 * here in DECRYPTED form. 55 */ 56 private ProtocolVersion protocolVersion; // preMaster [0,1] 57 SecretKey preMaster; 58 private byte[] encrypted; // same size as public modulus 59 60 /* 61 * Client randomly creates a pre-master secret and encrypts it 62 * using the server's RSA public key; only the server can decrypt 63 * it, using its RSA private key. Result is the same size as the 64 * server's public key, and uses PKCS #1 block format 02. 65 */ 66 @SuppressWarnings("deprecation") 67 RSAClientKeyExchange(ProtocolVersion protocolVersion, 68 ProtocolVersion maxVersion, 69 SecureRandom generator, PublicKey publicKey) throws IOException { 70 if (publicKey.getAlgorithm().equals("RSA") == false) { 71 throw new SSLKeyException("Public key not of type RSA"); 72 } 73 this.protocolVersion = protocolVersion; 74 75 try { 76 String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ? 77 "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"); 78 KeyGenerator kg = JsseJce.getKeyGenerator(s); 79 kg.init(new TlsRsaPremasterSecretParameterSpec( 80 maxVersion.v, protocolVersion.v), generator); 81 preMaster = kg.generateKey(); 82 83 Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); 84 cipher.init(Cipher.WRAP_MODE, publicKey, generator); 85 encrypted = cipher.wrap(preMaster); 86 } catch (GeneralSecurityException e) { 87 throw (SSLKeyException)new SSLKeyException 88 ("RSA premaster secret error").initCause(e); 89 } 90 } 91 92 /* 93 * Server gets the PKCS #1 (block format 02) data, decrypts 94 * it with its private key. 95 */ 96 @SuppressWarnings("deprecation") 97 RSAClientKeyExchange(ProtocolVersion currentVersion, 98 ProtocolVersion maxVersion, 99 SecureRandom generator, HandshakeInStream input, 100 int messageSize, PrivateKey privateKey) throws IOException { 101 102 if (privateKey.getAlgorithm().equals("RSA") == false) { 103 throw new SSLKeyException("Private key not of type RSA"); 104 } 105 106 if (currentVersion.v >= ProtocolVersion.TLS10.v) { 107 encrypted = input.getBytes16(); 108 } else { 109 encrypted = new byte [messageSize]; 110 if (input.read(encrypted) != messageSize) { 111 throw new SSLProtocolException( 112 "SSL: read PreMasterSecret: short read"); 113 } 114 } 115 116 try { 117 Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); 118 cipher.init(Cipher.UNWRAP_MODE, privateKey, 119 new TlsRsaPremasterSecretParameterSpec( 120 maxVersion.v, currentVersion.v), 121 generator); 122 preMaster = (SecretKey)cipher.unwrap(encrypted, 123 "TlsRsaPremasterSecret", Cipher.SECRET_KEY); 124 } catch (InvalidKeyException ibk) { 125 // the message is too big to process with RSA 126 throw new SSLProtocolException( 127 "Unable to process PreMasterSecret, may be too big"); 128 } catch (Exception e) { 129 // unlikely to happen, otherwise, must be a provider exception 130 if (debug != null && Debug.isOn("handshake")) { 131 System.out.println("RSA premaster secret decryption error:"); 132 e.printStackTrace(System.out); 133 } 134 throw new RuntimeException("Could not generate dummy secret", e); 135 } 136 } 137 138 @Override 139 int messageType() { 140 return ht_client_key_exchange; 141 } 142 143 @Override 144 int messageLength() { 145 if (protocolVersion.v >= ProtocolVersion.TLS10.v) { 146 return encrypted.length + 2; 147 } else { 148 return encrypted.length; 149 } 150 } 151 152 @Override 153 void send(HandshakeOutStream s) throws IOException { 154 if (protocolVersion.v >= ProtocolVersion.TLS10.v) { 155 s.putBytes16(encrypted); 156 } else { 157 s.write(encrypted); 158 } 159 } 160 161 @Override 162 void print(PrintStream s) throws IOException { 163 s.println("*** ClientKeyExchange, RSA PreMasterSecret, " + 164 protocolVersion); 165 } 166 }