summaryrefslogtreecommitdiffstats
path: root/bcprov/src/main/java/org/bouncycastle/crypto/tls/AbstractTlsKeyExchange.java
blob: 43e80e64b773685d17c4cd201e1e6970edc80da8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package org.bouncycastle.crypto.tls;

import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;

public abstract class AbstractTlsKeyExchange
    implements TlsKeyExchange
{
    protected int keyExchange;
    protected Vector supportedSignatureAlgorithms;

    protected TlsContext context;

    protected AbstractTlsKeyExchange(int keyExchange, Vector supportedSignatureAlgorithms)
    {
        this.keyExchange = keyExchange;
        this.supportedSignatureAlgorithms = supportedSignatureAlgorithms;
    }

    public void init(TlsContext context)
    {
        this.context = context;

        ProtocolVersion clientVersion = context.getClientVersion();

        if (TlsUtils.isSignatureAlgorithmsExtensionAllowed(clientVersion))
        {
            /*
             * RFC 5264 7.4.1.4.1. If the client does not send the signature_algorithms extension,
             * the server MUST do the following:
             * 
             * - If the negotiated key exchange algorithm is one of (RSA, DHE_RSA, DH_RSA, RSA_PSK,
             * ECDH_RSA, ECDHE_RSA), behave as if client had sent the value {sha1,rsa}.
             * 
             * - If the negotiated key exchange algorithm is one of (DHE_DSS, DH_DSS), behave as if
             * the client had sent the value {sha1,dsa}.
             * 
             * - If the negotiated key exchange algorithm is one of (ECDH_ECDSA, ECDHE_ECDSA),
             * behave as if the client had sent value {sha1,ecdsa}.
             */
            if (this.supportedSignatureAlgorithms == null)
            {
                switch (keyExchange)
                {
                case KeyExchangeAlgorithm.DH_DSS:
                case KeyExchangeAlgorithm.DHE_DSS:
                case KeyExchangeAlgorithm.SRP_DSS:
                {
                    this.supportedSignatureAlgorithms = TlsUtils.getDefaultDSSSignatureAlgorithms();
                    break;
                }

                case KeyExchangeAlgorithm.ECDH_ECDSA:
                case KeyExchangeAlgorithm.ECDHE_ECDSA:
                {
                    this.supportedSignatureAlgorithms = TlsUtils.getDefaultECDSASignatureAlgorithms();
                    break;
                }

                case KeyExchangeAlgorithm.DH_RSA:
                case KeyExchangeAlgorithm.DHE_RSA:
                case KeyExchangeAlgorithm.ECDH_RSA:
                case KeyExchangeAlgorithm.ECDHE_RSA:
                case KeyExchangeAlgorithm.RSA:
                case KeyExchangeAlgorithm.RSA_PSK:
                case KeyExchangeAlgorithm.SRP_RSA:
                {
                    this.supportedSignatureAlgorithms = TlsUtils.getDefaultRSASignatureAlgorithms();
                    break;
                }

                case KeyExchangeAlgorithm.DHE_PSK:
                case KeyExchangeAlgorithm.ECDHE_PSK:
                case KeyExchangeAlgorithm.PSK:
                case KeyExchangeAlgorithm.SRP:
                    break;

                default:
                    throw new IllegalStateException("unsupported key exchange algorithm");
                }
            }

        }
        else if (this.supportedSignatureAlgorithms != null)
        {
            throw new IllegalStateException("supported_signature_algorithms not allowed for " + clientVersion);
        }
    }

    public void processServerCertificate(Certificate serverCertificate)
        throws IOException
    {
        if (supportedSignatureAlgorithms == null)
        {
            /*
             * TODO RFC 2264 7.4.2. Unless otherwise specified, the signing algorithm for the
             * certificate must be the same as the algorithm for the certificate key.
             */
        }
        else
        {
            /*
             * TODO RFC 5264 7.4.2. If the client provided a "signature_algorithms" extension, then
             * all certificates provided by the server MUST be signed by a hash/signature algorithm
             * pair that appears in that extension.
             */
        }
    }

    public void processServerCredentials(TlsCredentials serverCredentials)
        throws IOException
    {
        processServerCertificate(serverCredentials.getCertificate());
    }

    public boolean requiresServerKeyExchange()
    {
        return false;
    }

    public byte[] generateServerKeyExchange()
        throws IOException
    {
        if (requiresServerKeyExchange())
        {
            throw new TlsFatalAlert(AlertDescription.internal_error);
        }
        return null;
    }

    public void skipServerKeyExchange()
        throws IOException
    {
        if (requiresServerKeyExchange())
        {
            throw new TlsFatalAlert(AlertDescription.unexpected_message);
        }
    }

    public void processServerKeyExchange(InputStream input)
        throws IOException
    {
        if (!requiresServerKeyExchange())
        {
            throw new TlsFatalAlert(AlertDescription.unexpected_message);
        }
    }

    public void skipClientCredentials()
        throws IOException
    {
    }

    public void processClientCertificate(Certificate clientCertificate)
        throws IOException
    {
    }

    public void processClientKeyExchange(InputStream input)
        throws IOException
    {
        // Key exchange implementation MUST support client key exchange
        throw new TlsFatalAlert(AlertDescription.internal_error);
    }
}