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 RSAClientKeyExchange(ProtocolVersion protocolVersion, 67 ProtocolVersion maxVersion, 68 SecureRandom generator, PublicKey publicKey) throws IOException { 69 if (publicKey.getAlgorithm().equals("RSA") == false) { 70 throw new SSLKeyException("Public key not of type RSA"); 71 } 72 this.protocolVersion = protocolVersion; 73 74 try { 75 String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ? 76 "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"); 77 KeyGenerator kg = JsseJce.getKeyGenerator(s); 78 kg.init(new TlsRsaPremasterSecretParameterSpec( 79 maxVersion.v, protocolVersion.v), generator); 80 preMaster = kg.generateKey(); 81 82 Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); 83 cipher.init(Cipher.WRAP_MODE, publicKey, generator); 84 encrypted = cipher.wrap(preMaster); 85 } catch (GeneralSecurityException e) { 86 throw (SSLKeyException)new SSLKeyException 87 ("RSA premaster secret error").initCause(e); 88 } 89 } 90 91 /* 92 * Server gets the PKCS #1 (block format 02) data, decrypts 93 * it with its private key. 94 */ 95 RSAClientKeyExchange(ProtocolVersion currentVersion, 96 ProtocolVersion maxVersion, 97 SecureRandom generator, HandshakeInStream input, 98 int messageSize, PrivateKey privateKey) throws IOException { 99 100 if (privateKey.getAlgorithm().equals("RSA") == false) { 101 throw new SSLKeyException("Private key not of type RSA"); 102 } 103 104 if (currentVersion.v >= ProtocolVersion.TLS10.v) { 105 encrypted = input.getBytes16(); 106 } else { 107 encrypted = new byte [messageSize]; 108 if (input.read(encrypted) != messageSize) { 109 throw new SSLProtocolException( 110 "SSL: read PreMasterSecret: short read"); 111 } 112 } 113 114 try { 115 Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); 116 cipher.init(Cipher.UNWRAP_MODE, privateKey, 117 new TlsRsaPremasterSecretParameterSpec( 118 maxVersion.v, currentVersion.v), 119 generator); 120 preMaster = (SecretKey)cipher.unwrap(encrypted, 121 "TlsRsaPremasterSecret", Cipher.SECRET_KEY); 122 } catch (InvalidKeyException ibk) { 123 // the message is too big to process with RSA 124 throw new SSLProtocolException( 125 "Unable to process PreMasterSecret, may be too big"); 126 } catch (Exception e) { 127 // unlikely to happen, otherwise, must be a provider exception 128 if (debug != null && Debug.isOn("handshake")) { 129 System.out.println("RSA premaster secret decryption error:"); 130 e.printStackTrace(System.out); 131 } 132 throw new RuntimeException("Could not generate dummy secret", e); 133 } 134 } 135 136 @Override 137 int messageType() { 138 return ht_client_key_exchange; 139 } 140 141 @Override 142 int messageLength() { 143 if (protocolVersion.v >= ProtocolVersion.TLS10.v) { 144 return encrypted.length + 2; 145 } else { 146 return encrypted.length; 147 } 148 } 149 150 @Override 151 void send(HandshakeOutStream s) throws IOException { 152 if (protocolVersion.v >= ProtocolVersion.TLS10.v) { 153 s.putBytes16(encrypted); 154 } else { 155 s.write(encrypted); 156 } 157 } 158 159 @Override 160 void print(PrintStream s) throws IOException { 161 s.println("*** ClientKeyExchange, RSA PreMasterSecret, " + 162 protocolVersion); 163 } 164 }