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