1 /*
2  * Copyright (c) 2018, 2021, 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.io.IOException;
29 import java.nio.ByteBuffer;
30 import java.util.Map;
31 import sun.security.ssl.SSLHandshake.HandshakeMessage;
32 
33 /**
34  * Pack of the ServerKeyExchange handshake message.
35  */
36 final class ServerKeyExchange {
37     static final SSLConsumer handshakeConsumer =
38         new ServerKeyExchangeConsumer();
39     static final HandshakeProducer handshakeProducer =
40         new ServerKeyExchangeProducer();
41 
42     /**
43      * The "ServerKeyExchange" handshake message producer.
44      */
45     private static final
46             class ServerKeyExchangeProducer implements HandshakeProducer {
47         // Prevent instantiation of this class.
ServerKeyExchangeProducer()48         private ServerKeyExchangeProducer() {
49             // blank
50         }
51 
52         @Override
produce(ConnectionContext context, HandshakeMessage message)53         public byte[] produce(ConnectionContext context,
54                 HandshakeMessage message) throws IOException {
55             // The producing happens in server side only.
56             ServerHandshakeContext shc = (ServerHandshakeContext)context;
57 
58             SSLKeyExchange ke = SSLKeyExchange.valueOf(
59                     shc.negotiatedCipherSuite.keyExchange,
60                     shc.negotiatedProtocol);
61             if (ke != null) {
62                 for (Map.Entry<Byte, HandshakeProducer> hc :
63                         ke.getHandshakeProducers(shc)) {
64                     if (hc.getKey() == SSLHandshake.SERVER_KEY_EXCHANGE.id) {
65                         return hc.getValue().produce(context, message);
66                     }
67                 }
68             }
69 
70             // not producer defined.
71             throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
72                     "No ServerKeyExchange handshake message can be produced.");
73         }
74     }
75 
76     /**
77      * The "ServerKeyExchange" handshake message consumer.
78      */
79     private static final
80             class ServerKeyExchangeConsumer implements SSLConsumer {
81         // Prevent instantiation of this class.
ServerKeyExchangeConsumer()82         private ServerKeyExchangeConsumer() {
83             // blank
84         }
85 
86         @Override
consume(ConnectionContext context, ByteBuffer message)87         public void consume(ConnectionContext context,
88                 ByteBuffer message) throws IOException {
89             // The consuming happens in client side only.
90             ClientHandshakeContext chc = (ClientHandshakeContext)context;
91 
92             // clean up this consumer
93             chc.handshakeConsumers.remove(SSLHandshake.SERVER_KEY_EXCHANGE.id);
94 
95             // Any receipt/consumption of the CertificateRequest before
96             // ServerKeyExchange is a state machine violation.  We may not
97             // know for sure if an early CR message is a violation though until
98             // we have reached this point, due to other TLS features and
99             // optional messages.
100             if (chc.receivedCertReq) {
101                 chc.receivedCertReq = false;    // Reset flag
102                 throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
103                         "Unexpected ServerKeyExchange handshake message");
104             }
105 
106             SSLConsumer certStatCons = chc.handshakeConsumers.remove(
107                     SSLHandshake.CERTIFICATE_STATUS.id);
108             if (certStatCons != null) {
109                 // Stapling was active but no certificate status message
110                 // was sent.  We need to run the absence handler which will
111                 // check the certificate chain.
112                 CertificateStatus.handshakeAbsence.absent(context, null);
113             }
114 
115             SSLKeyExchange ke = SSLKeyExchange.valueOf(
116                     chc.negotiatedCipherSuite.keyExchange,
117                     chc.negotiatedProtocol);
118             if (ke != null) {
119                 for (Map.Entry<Byte, SSLConsumer> hc :
120                         ke.getHandshakeConsumers(chc)) {
121                     if (hc.getKey() == SSLHandshake.SERVER_KEY_EXCHANGE.id) {
122                         hc.getValue().consume(context, message);
123                         return;
124                     }
125                 }
126             }
127 
128             // no consumer defined.
129             throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
130                         "Unexpected ServerKeyExchange handshake message.");
131         }
132     }
133 }
134 
135