1 /* 2 * Copyright (c) 2006, 2007, 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 package sun.security.ssl; 27 28 import java.security.*; 29 import java.security.interfaces.ECPublicKey; 30 import java.security.spec.*; 31 32 import javax.crypto.SecretKey; 33 import javax.crypto.KeyAgreement; 34 import javax.crypto.spec.*; 35 36 /** 37 * Helper class for the ECDH key exchange. It generates the appropriate 38 * ephemeral keys as necessary and performs the actual shared secret derivation. 39 * 40 * @since 1.6 41 * @author Andreas Sterbenz 42 */ 43 final class ECDHCrypt { 44 45 // our private key 46 private PrivateKey privateKey; 47 48 // our public key 49 private ECPublicKey publicKey; 50 51 // Called by ServerHandshaker for static ECDH ECDHCrypt(PrivateKey privateKey, PublicKey publicKey)52 ECDHCrypt(PrivateKey privateKey, PublicKey publicKey) { 53 this.privateKey = privateKey; 54 this.publicKey = (ECPublicKey)publicKey; 55 } 56 57 // Called by ServerHandshaker for ephemeral ECDH ECDHCrypt(String curveName, SecureRandom random)58 ECDHCrypt(String curveName, SecureRandom random) { 59 try { 60 KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC"); 61 ECGenParameterSpec params = new ECGenParameterSpec(curveName); 62 kpg.initialize(params, random); 63 KeyPair kp = kpg.generateKeyPair(); 64 privateKey = kp.getPrivate(); 65 publicKey = (ECPublicKey)kp.getPublic(); 66 } catch (GeneralSecurityException e) { 67 throw new RuntimeException("Could not generate DH keypair", e); 68 } 69 } 70 71 // Called by ClientHandshaker with params it received from the server ECDHCrypt(ECParameterSpec params, SecureRandom random)72 ECDHCrypt(ECParameterSpec params, SecureRandom random) { 73 try { 74 KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC"); 75 kpg.initialize(params, random); 76 KeyPair kp = kpg.generateKeyPair(); 77 privateKey = kp.getPrivate(); 78 publicKey = (ECPublicKey)kp.getPublic(); 79 } catch (GeneralSecurityException e) { 80 throw new RuntimeException("Could not generate DH keypair", e); 81 } 82 } 83 84 /** 85 * Gets the public key of this end of the key exchange. 86 */ getPublicKey()87 PublicKey getPublicKey() { 88 return publicKey; 89 } 90 91 // called by ClientHandshaker with either the server's static or ephemeral public key getAgreedSecret(PublicKey peerPublicKey)92 SecretKey getAgreedSecret(PublicKey peerPublicKey) { 93 try { 94 KeyAgreement ka = JsseJce.getKeyAgreement("ECDH"); 95 ka.init(privateKey); 96 ka.doPhase(peerPublicKey, true); 97 return ka.generateSecret("TlsPremasterSecret"); 98 } catch (GeneralSecurityException e) { 99 throw new RuntimeException("Could not generate secret", e); 100 } 101 } 102 103 // called by ServerHandshaker getAgreedSecret(byte[] encodedPoint)104 SecretKey getAgreedSecret(byte[] encodedPoint) { 105 try { 106 ECParameterSpec params = publicKey.getParams(); 107 ECPoint point = JsseJce.decodePoint(encodedPoint, params.getCurve()); 108 KeyFactory kf = JsseJce.getKeyFactory("EC"); 109 ECPublicKeySpec spec = new ECPublicKeySpec(point, params); 110 PublicKey peerPublicKey = kf.generatePublic(spec); 111 return getAgreedSecret(peerPublicKey); 112 } catch (GeneralSecurityException e) { 113 throw new RuntimeException("Could not generate secret", e); 114 } catch (java.io.IOException e) { 115 throw new RuntimeException("Could not generate secret", e); 116 } 117 } 118 119 } 120