1 package org.bouncycastle.tls; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.io.OutputStream; 6 7 import org.bouncycastle.tls.crypto.TlsAgreement; 8 import org.bouncycastle.tls.crypto.TlsCertificate; 9 import org.bouncycastle.tls.crypto.TlsDHConfig; 10 import org.bouncycastle.tls.crypto.TlsSecret; 11 import org.bouncycastle.util.io.TeeInputStream; 12 13 public class TlsDHEKeyExchange 14 extends AbstractTlsKeyExchange 15 { checkKeyExchange(int keyExchange)16 private static int checkKeyExchange(int keyExchange) 17 { 18 switch (keyExchange) 19 { 20 case KeyExchangeAlgorithm.DHE_DSS: 21 case KeyExchangeAlgorithm.DHE_RSA: 22 return keyExchange; 23 default: 24 throw new IllegalArgumentException("unsupported key exchange algorithm"); 25 } 26 } 27 28 protected TlsDHGroupVerifier dhGroupVerifier; 29 protected TlsDHConfig dhConfig; 30 31 protected TlsCredentialedSigner serverCredentials = null; 32 protected TlsCertificate serverCertificate = null; 33 protected TlsAgreement agreement; 34 TlsDHEKeyExchange(int keyExchange, TlsDHGroupVerifier dhGroupVerifier)35 public TlsDHEKeyExchange(int keyExchange, TlsDHGroupVerifier dhGroupVerifier) 36 { 37 this(keyExchange, dhGroupVerifier, null); 38 } 39 TlsDHEKeyExchange(int keyExchange, TlsDHConfig dhConfig)40 public TlsDHEKeyExchange(int keyExchange, TlsDHConfig dhConfig) 41 { 42 this(keyExchange, null, dhConfig); 43 } 44 TlsDHEKeyExchange(int keyExchange, TlsDHGroupVerifier dhGroupVerifier, TlsDHConfig dhConfig)45 private TlsDHEKeyExchange(int keyExchange, TlsDHGroupVerifier dhGroupVerifier, TlsDHConfig dhConfig) 46 { 47 super(checkKeyExchange(keyExchange)); 48 49 this.dhGroupVerifier = dhGroupVerifier; 50 this.dhConfig = dhConfig; 51 } 52 skipServerCredentials()53 public void skipServerCredentials() throws IOException 54 { 55 throw new TlsFatalAlert(AlertDescription.internal_error); 56 } 57 processServerCredentials(TlsCredentials serverCredentials)58 public void processServerCredentials(TlsCredentials serverCredentials) throws IOException 59 { 60 this.serverCredentials = TlsUtils.requireSignerCredentials(serverCredentials); 61 } 62 processServerCertificate(Certificate serverCertificate)63 public void processServerCertificate(Certificate serverCertificate) throws IOException 64 { 65 this.serverCertificate = serverCertificate.getCertificateAt(0); 66 } 67 requiresServerKeyExchange()68 public boolean requiresServerKeyExchange() 69 { 70 return true; 71 } 72 generateServerKeyExchange()73 public byte[] generateServerKeyExchange() throws IOException 74 { 75 DigestInputBuffer digestBuffer = new DigestInputBuffer(); 76 77 TlsDHUtils.writeDHConfig(dhConfig, digestBuffer); 78 79 this.agreement = context.getCrypto().createDHDomain(dhConfig).createDH(); 80 81 byte[] y = agreement.generateEphemeral(); 82 83 TlsUtils.writeOpaque16(y, digestBuffer); 84 85 TlsUtils.generateServerKeyExchangeSignature(context, serverCredentials, digestBuffer); 86 87 return digestBuffer.toByteArray(); 88 } 89 processServerKeyExchange(InputStream input)90 public void processServerKeyExchange(InputStream input) throws IOException 91 { 92 DigestInputBuffer digestBuffer = new DigestInputBuffer(); 93 InputStream teeIn = new TeeInputStream(input, digestBuffer); 94 95 this.dhConfig = TlsDHUtils.receiveDHConfig(context, dhGroupVerifier, teeIn); 96 97 byte[] y = TlsUtils.readOpaque16(teeIn, 1); 98 99 TlsUtils.verifyServerKeyExchangeSignature(context, input, serverCertificate, digestBuffer); 100 101 this.agreement = context.getCrypto().createDHDomain(dhConfig).createDH(); 102 103 agreement.receivePeerValue(y); 104 } 105 getClientCertificateTypes()106 public short[] getClientCertificateTypes() 107 { 108 return new short[]{ ClientCertificateType.dss_sign, ClientCertificateType.ecdsa_sign, 109 ClientCertificateType.rsa_sign }; 110 } 111 processClientCredentials(TlsCredentials clientCredentials)112 public void processClientCredentials(TlsCredentials clientCredentials) throws IOException 113 { 114 TlsUtils.requireSignerCredentials(clientCredentials); 115 } 116 generateClientKeyExchange(OutputStream output)117 public void generateClientKeyExchange(OutputStream output) throws IOException 118 { 119 byte[] y = agreement.generateEphemeral(); 120 121 TlsUtils.writeOpaque16(y, output); 122 } 123 processClientKeyExchange(InputStream input)124 public void processClientKeyExchange(InputStream input) throws IOException 125 { 126 agreement.receivePeerValue(TlsUtils.readOpaque16(input, 1)); 127 } 128 generatePreMasterSecret()129 public TlsSecret generatePreMasterSecret() throws IOException 130 { 131 return agreement.calculateSecret(); 132 } 133 } 134