~brian-thomason/+junk/bouncycastle

« back to all changes in this revision

Viewing changes to src/org/bouncycastle/crypto/tls/TlsRSAKeyExchange.java

  • Committer: Brian Thomason
  • Date: 2011-12-20 17:20:32 UTC
  • Revision ID: brian.thomason@canonical.com-20111220172032-rdtm13jgdxtksacr
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.bouncycastle.crypto.tls;
 
2
 
 
3
import java.io.IOException;
 
4
import java.io.InputStream;
 
5
import java.io.OutputStream;
 
6
 
 
7
import org.bouncycastle.asn1.x509.KeyUsage;
 
8
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
 
9
import org.bouncycastle.asn1.x509.X509CertificateStructure;
 
10
import org.bouncycastle.crypto.InvalidCipherTextException;
 
11
import org.bouncycastle.crypto.encodings.PKCS1Encoding;
 
12
import org.bouncycastle.crypto.engines.RSABlindedEngine;
 
13
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
 
14
import org.bouncycastle.crypto.params.ParametersWithRandom;
 
15
import org.bouncycastle.crypto.params.RSAKeyParameters;
 
16
import org.bouncycastle.crypto.util.PublicKeyFactory;
 
17
 
 
18
/**
 
19
 * TLS 1.0 RSA key exchange.
 
20
 */
 
21
class TlsRSAKeyExchange implements TlsKeyExchange
 
22
{
 
23
    protected TlsClientContext context;
 
24
 
 
25
    protected AsymmetricKeyParameter serverPublicKey = null;
 
26
 
 
27
    protected RSAKeyParameters rsaServerPublicKey = null;
 
28
 
 
29
    protected byte[] premasterSecret;
 
30
 
 
31
    TlsRSAKeyExchange(TlsClientContext context)
 
32
    {
 
33
        this.context = context;
 
34
    }
 
35
 
 
36
    public void skipServerCertificate() throws IOException
 
37
    {
 
38
        throw new TlsFatalAlert(AlertDescription.unexpected_message);
 
39
    }
 
40
 
 
41
    public void processServerCertificate(Certificate serverCertificate) throws IOException
 
42
    {
 
43
        X509CertificateStructure x509Cert = serverCertificate.certs[0];
 
44
        SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo();
 
45
 
 
46
        try
 
47
        {
 
48
            this.serverPublicKey = PublicKeyFactory.createKey(keyInfo);
 
49
        }
 
50
        catch (RuntimeException e)
 
51
        {
 
52
            throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
 
53
        }
 
54
 
 
55
        // Sanity check the PublicKeyFactory
 
56
        if (this.serverPublicKey.isPrivate())
 
57
        {
 
58
            throw new TlsFatalAlert(AlertDescription.internal_error);
 
59
        }
 
60
 
 
61
        this.rsaServerPublicKey = validateRSAPublicKey((RSAKeyParameters)this.serverPublicKey);
 
62
 
 
63
        TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyEncipherment);
 
64
 
 
65
        // TODO 
 
66
        /*
 
67
         * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the
 
68
         * signing algorithm for the certificate must be the same as the algorithm for the
 
69
         * certificate key."
 
70
         */
 
71
    }
 
72
 
 
73
    public void skipServerKeyExchange() throws IOException
 
74
    {
 
75
        // OK
 
76
    }
 
77
 
 
78
    public void processServerKeyExchange(InputStream is)
 
79
        throws IOException
 
80
    {
 
81
        // TODO
 
82
        throw new TlsFatalAlert(AlertDescription.unexpected_message);
 
83
    }
 
84
 
 
85
    public void validateCertificateRequest(CertificateRequest certificateRequest)
 
86
        throws IOException
 
87
    {
 
88
        short[] types = certificateRequest.getCertificateTypes();
 
89
        for (int i = 0; i < types.length; ++i)
 
90
        {
 
91
            switch (types[i])
 
92
            {
 
93
                case ClientCertificateType.rsa_sign:
 
94
                case ClientCertificateType.dss_sign:
 
95
                case ClientCertificateType.ecdsa_sign:
 
96
                    break;
 
97
                default:
 
98
                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
 
99
            }
 
100
        }
 
101
    }
 
102
 
 
103
    public void skipClientCredentials() throws IOException
 
104
    {
 
105
        // OK
 
106
    }
 
107
 
 
108
    public void processClientCredentials(TlsCredentials clientCredentials) throws IOException
 
109
    {
 
110
        if (!(clientCredentials instanceof TlsSignerCredentials))
 
111
        {
 
112
            throw new TlsFatalAlert(AlertDescription.internal_error);
 
113
        }
 
114
    }
 
115
 
 
116
    public void generateClientKeyExchange(OutputStream os) throws IOException
 
117
    {
 
118
        /*
 
119
         * Choose a PremasterSecret and send it encrypted to the server
 
120
         */
 
121
        premasterSecret = new byte[48];
 
122
        context.getSecureRandom().nextBytes(premasterSecret);
 
123
        TlsUtils.writeVersion(premasterSecret, 0);
 
124
 
 
125
        PKCS1Encoding encoding = new PKCS1Encoding(new RSABlindedEngine());
 
126
        encoding.init(true, new ParametersWithRandom(this.rsaServerPublicKey, context.getSecureRandom()));
 
127
 
 
128
        try
 
129
        {
 
130
            byte[] keData = encoding.processBlock(premasterSecret, 0, premasterSecret.length);
 
131
            TlsUtils.writeUint24(keData.length + 2, os);
 
132
            TlsUtils.writeOpaque16(keData, os);
 
133
        }
 
134
        catch (InvalidCipherTextException e)
 
135
        {
 
136
            /*
 
137
             * This should never happen, only during decryption.
 
138
             */
 
139
            throw new TlsFatalAlert(AlertDescription.internal_error);
 
140
        }
 
141
    }
 
142
 
 
143
    public byte[] generatePremasterSecret() throws IOException
 
144
    {
 
145
        byte[] tmp = this.premasterSecret;
 
146
        this.premasterSecret = null;
 
147
        return tmp;
 
148
    }
 
149
 
 
150
    // Would be needed to process RSA_EXPORT server key exchange
 
151
//    protected void processRSAServerKeyExchange(InputStream is, Signer signer) throws IOException
 
152
//    {
 
153
//        InputStream sigIn = is;
 
154
//        if (signer != null)
 
155
//        {
 
156
//            sigIn = new SignerInputStream(is, signer);
 
157
//        }
 
158
//
 
159
//        byte[] modulusBytes = TlsUtils.readOpaque16(sigIn);
 
160
//        byte[] exponentBytes = TlsUtils.readOpaque16(sigIn);
 
161
//
 
162
//        if (signer != null)
 
163
//        {
 
164
//            byte[] sigByte = TlsUtils.readOpaque16(is);
 
165
//
 
166
//            if (!signer.verifySignature(sigByte))
 
167
//            {
 
168
//                handler.failWithError(AlertLevel.fatal, AlertDescription.bad_certificate);
 
169
//            }
 
170
//        }
 
171
//
 
172
//        BigInteger modulus = new BigInteger(1, modulusBytes);
 
173
//        BigInteger exponent = new BigInteger(1, exponentBytes);
 
174
//
 
175
//        this.rsaServerPublicKey = validateRSAPublicKey(new RSAKeyParameters(false, modulus,
 
176
//            exponent));
 
177
//    }
 
178
 
 
179
    protected RSAKeyParameters validateRSAPublicKey(RSAKeyParameters key) throws IOException
 
180
    {
 
181
        // TODO What is the minimum bit length required?
 
182
//        key.getModulus().bitLength();
 
183
 
 
184
        if (!key.getExponent().isProbablePrime(2))
 
185
        {
 
186
            throw new TlsFatalAlert(AlertDescription.illegal_parameter);
 
187
        }
 
188
 
 
189
        return key;
 
190
    }
 
191
}