24 */ |
25 */ |
25 |
26 |
26 package sun.security.ssl; |
27 package sun.security.ssl; |
27 |
28 |
28 import java.io.IOException; |
29 import java.io.IOException; |
|
30 import java.nio.ByteBuffer; |
29 import javax.net.ssl.SSLProtocolException; |
31 import javax.net.ssl.SSLProtocolException; |
|
32 import static sun.security.ssl.SSLExtension.CH_EXTENDED_MASTER_SECRET; |
|
33 import sun.security.ssl.SSLExtension.ExtensionConsumer; |
|
34 import static sun.security.ssl.SSLExtension.SH_EXTENDED_MASTER_SECRET; |
|
35 import sun.security.ssl.SSLExtension.SSLExtensionSpec; |
|
36 import sun.security.ssl.SSLHandshake.HandshakeMessage; |
30 |
37 |
31 /** |
38 /** |
32 * Extended Master Secret TLS extension (TLS 1.0+). This extension |
39 * Pack of the "extended_master_secret" extensions [RFC 7627]. |
33 * defines how to calculate the TLS connection master secret and |
|
34 * mitigates some types of man-in-the-middle attacks. |
|
35 * |
|
36 * See further information in |
|
37 * <a href="https://tools.ietf.org/html/rfc7627">RFC 7627</a>. |
|
38 * |
|
39 * @author Martin Balao (mbalao@redhat.com) |
|
40 */ |
40 */ |
41 final class ExtendedMasterSecretExtension extends HelloExtension { |
41 final class ExtendedMasterSecretExtension { |
42 ExtendedMasterSecretExtension() { |
42 static final HandshakeProducer chNetworkProducer = |
43 super(ExtensionType.EXT_EXTENDED_MASTER_SECRET); |
43 new CHExtendedMasterSecretProducer(); |
44 } |
44 static final ExtensionConsumer chOnLoadConsumer = |
45 |
45 new CHExtendedMasterSecretConsumer(); |
46 ExtendedMasterSecretExtension(HandshakeInStream s, |
46 static final HandshakeAbsence chOnLoadAbsence = |
47 int len) throws IOException { |
47 new CHExtendedMasterSecretAbsence(); |
48 super(ExtensionType.EXT_EXTENDED_MASTER_SECRET); |
48 |
49 |
49 static final HandshakeProducer shNetworkProducer = |
50 if (len != 0) { |
50 new SHExtendedMasterSecretProducer(); |
51 throw new SSLProtocolException("Invalid " + type + " extension"); |
51 static final ExtensionConsumer shOnLoadConsumer = |
52 } |
52 new SHExtendedMasterSecretConsumer(); |
53 } |
53 static final HandshakeAbsence shOnLoadAbsence = |
54 |
54 new SHExtendedMasterSecretAbsence(); |
55 @Override |
55 |
56 int length() { |
56 static final SSLStringizer emsStringizer = |
57 return 4; // 4: extension type and length fields |
57 new ExtendedMasterSecretStringizer(); |
58 } |
58 |
59 |
59 /** |
60 @Override |
60 * The "extended_master_secret" extension. |
61 void send(HandshakeOutStream s) throws IOException { |
61 */ |
62 s.putInt16(type.id); // ExtensionType extension_type; |
62 static final class ExtendedMasterSecretSpec implements SSLExtensionSpec { |
63 s.putInt16(0); // extension_data length |
63 // A nominal object that does not holding any real renegotiation info. |
64 } |
64 static final ExtendedMasterSecretSpec NOMINAL = |
65 |
65 new ExtendedMasterSecretSpec(); |
66 @Override |
66 |
67 public String toString() { |
67 private ExtendedMasterSecretSpec() { |
68 return "Extension " + type; |
68 // blank |
|
69 } |
|
70 |
|
71 private ExtendedMasterSecretSpec(ByteBuffer m) throws IOException { |
|
72 // Parse the extension. |
|
73 if (m.hasRemaining()) { |
|
74 throw new SSLProtocolException( |
|
75 "Invalid extended_master_secret extension data: " + |
|
76 "not empty"); |
|
77 } |
|
78 } |
|
79 |
|
80 @Override |
|
81 public String toString() { |
|
82 return "<empty>"; |
|
83 } |
|
84 } |
|
85 |
|
86 private static final |
|
87 class ExtendedMasterSecretStringizer implements SSLStringizer { |
|
88 @Override |
|
89 public String toString(ByteBuffer buffer) { |
|
90 try { |
|
91 return (new ExtendedMasterSecretSpec(buffer)).toString(); |
|
92 } catch (IOException ioe) { |
|
93 // For debug logging only, so please swallow exceptions. |
|
94 return ioe.getMessage(); |
|
95 } |
|
96 } |
|
97 } |
|
98 |
|
99 /** |
|
100 * Network data producer of a "extended_master_secret" extension in |
|
101 * the ClientHello handshake message. |
|
102 */ |
|
103 private static final |
|
104 class CHExtendedMasterSecretProducer implements HandshakeProducer { |
|
105 // Prevent instantiation of this class. |
|
106 private CHExtendedMasterSecretProducer() { |
|
107 // blank |
|
108 } |
|
109 |
|
110 @Override |
|
111 public byte[] produce(ConnectionContext context, |
|
112 HandshakeMessage message) throws IOException { |
|
113 // The producing happens in client side only. |
|
114 ClientHandshakeContext chc = (ClientHandshakeContext)context; |
|
115 |
|
116 // Is it a supported and enabled extension? |
|
117 if (!chc.sslConfig.isAvailable(CH_EXTENDED_MASTER_SECRET) || |
|
118 !SSLConfiguration.useExtendedMasterSecret || |
|
119 !chc.conContext.protocolVersion.useTLS10PlusSpec()) { |
|
120 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
121 SSLLogger.fine( |
|
122 "Ignore unavailable extended_master_secret extension"); |
|
123 } |
|
124 |
|
125 return null; |
|
126 } |
|
127 |
|
128 if (chc.handshakeSession == null || |
|
129 chc.handshakeSession.useExtendedMasterSecret) { |
|
130 byte[] extData = new byte[0]; |
|
131 chc.handshakeExtensions.put(CH_EXTENDED_MASTER_SECRET, |
|
132 ExtendedMasterSecretSpec.NOMINAL); |
|
133 |
|
134 return extData; |
|
135 } |
|
136 |
|
137 return null; |
|
138 } |
|
139 } |
|
140 |
|
141 /** |
|
142 * Network data producer of a "extended_master_secret" extension in |
|
143 * the ServerHello handshake message. |
|
144 */ |
|
145 private static final |
|
146 class CHExtendedMasterSecretConsumer implements ExtensionConsumer { |
|
147 // Prevent instantiation of this class. |
|
148 private CHExtendedMasterSecretConsumer() { |
|
149 // blank |
|
150 } |
|
151 |
|
152 @Override |
|
153 public void consume(ConnectionContext context, |
|
154 HandshakeMessage message, ByteBuffer buffer) throws IOException { |
|
155 |
|
156 // The consuming happens in server side only. |
|
157 ServerHandshakeContext shc = (ServerHandshakeContext)context; |
|
158 |
|
159 // Is it a supported and enabled extension? |
|
160 if (!shc.sslConfig.isAvailable(CH_EXTENDED_MASTER_SECRET) || |
|
161 !SSLConfiguration.useExtendedMasterSecret || |
|
162 !shc.negotiatedProtocol.useTLS10PlusSpec()) { |
|
163 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
164 SSLLogger.fine("Ignore unavailable extension: " + |
|
165 CH_EXTENDED_MASTER_SECRET.name); |
|
166 } |
|
167 return; // ignore the extension |
|
168 } |
|
169 |
|
170 // Parse the extension. |
|
171 ExtendedMasterSecretSpec spec; |
|
172 try { |
|
173 spec = new ExtendedMasterSecretSpec(buffer); |
|
174 } catch (IOException ioe) { |
|
175 shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe); |
|
176 return; // fatal() always throws, make the compiler happy. |
|
177 } |
|
178 |
|
179 if (shc.isResumption && shc.resumingSession != null && |
|
180 !shc.resumingSession.useExtendedMasterSecret) { |
|
181 // For abbreviated handshake request, If the original |
|
182 // session did not use the "extended_master_secret" |
|
183 // extension but the new ClientHello contains the |
|
184 // extension, then the server MUST NOT perform the |
|
185 // abbreviated handshake. Instead, it SHOULD continue |
|
186 // with a full handshake. |
|
187 shc.isResumption = false; |
|
188 shc.resumingSession = null; |
|
189 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
190 SSLLogger.fine( |
|
191 "abort session resumption which did not use " + |
|
192 "Extended Master Secret extension"); |
|
193 } |
|
194 } |
|
195 |
|
196 // Update the context. |
|
197 // |
|
198 shc.handshakeExtensions.put( |
|
199 CH_EXTENDED_MASTER_SECRET, ExtendedMasterSecretSpec.NOMINAL); |
|
200 |
|
201 // No impact on session resumption. |
|
202 } |
|
203 } |
|
204 |
|
205 /** |
|
206 * The absence processing if a "extended_master_secret" extension is |
|
207 * not present in the ClientHello handshake message. |
|
208 */ |
|
209 private static final |
|
210 class CHExtendedMasterSecretAbsence implements HandshakeAbsence { |
|
211 @Override |
|
212 public void absent(ConnectionContext context, |
|
213 HandshakeMessage message) throws IOException { |
|
214 // The producing happens in server side only. |
|
215 ServerHandshakeContext shc = (ServerHandshakeContext)context; |
|
216 |
|
217 // Is it a supported and enabled extension? |
|
218 if (!shc.sslConfig.isAvailable(CH_EXTENDED_MASTER_SECRET) || |
|
219 !SSLConfiguration.useExtendedMasterSecret) { |
|
220 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
221 SSLLogger.fine("Ignore unavailable extension: " + |
|
222 CH_EXTENDED_MASTER_SECRET.name); |
|
223 } |
|
224 return; // ignore the extension |
|
225 } |
|
226 |
|
227 if (shc.negotiatedProtocol.useTLS10PlusSpec() && |
|
228 !SSLConfiguration.allowLegacyMasterSecret) { |
|
229 // For full handshake, if the server receives a ClientHello |
|
230 // without the extension, it SHOULD abort the handshake if |
|
231 // it does not wish to interoperate with legacy clients. |
|
232 // |
|
233 // As if extended master extension is required for full |
|
234 // handshake, it MUST be used in abbreviated handshake too. |
|
235 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, |
|
236 "Extended Master Secret extension is required"); |
|
237 } |
|
238 |
|
239 if (shc.isResumption && shc.resumingSession != null) { |
|
240 if (shc.resumingSession.useExtendedMasterSecret) { |
|
241 // For abbreviated handshake request, if the original |
|
242 // session used the "extended_master_secret" extension |
|
243 // but the new ClientHello does not contain it, the |
|
244 // server MUST abort the abbreviated handshake. |
|
245 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, |
|
246 "Missing Extended Master Secret extension " + |
|
247 "on session resumption"); |
|
248 } else { |
|
249 // For abbreviated handshake request, if neither the |
|
250 // original session nor the new ClientHello uses the |
|
251 // extension, the server SHOULD abort the handshake. |
|
252 if (!SSLConfiguration.allowLegacyResumption) { |
|
253 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, |
|
254 "Missing Extended Master Secret extension " + |
|
255 "on session resumption"); |
|
256 } else { // Otherwise, continue with a full handshake. |
|
257 shc.isResumption = false; |
|
258 shc.resumingSession = null; |
|
259 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
|
260 SSLLogger.fine( |
|
261 "abort session resumption, " + |
|
262 "missing Extended Master Secret extension"); |
|
263 } |
|
264 } |
|
265 } |
|
266 } |
|
267 } |
|
268 } |
|
269 |
|
270 /** |
|
271 * Network data producer of a "extended_master_secret" extension in |
|
272 * the ServerHello handshake message. |
|
273 */ |
|
274 private static final |
|
275 class SHExtendedMasterSecretProducer implements HandshakeProducer { |
|
276 // Prevent instantiation of this class. |
|
277 private SHExtendedMasterSecretProducer() { |
|
278 // blank |
|
279 } |
|
280 |
|
281 @Override |
|
282 public byte[] produce(ConnectionContext context, |
|
283 HandshakeMessage message) throws IOException { |
|
284 // The producing happens in server side only. |
|
285 ServerHandshakeContext shc = (ServerHandshakeContext)context; |
|
286 |
|
287 if (shc.handshakeSession.useExtendedMasterSecret) { |
|
288 byte[] extData = new byte[0]; |
|
289 shc.handshakeExtensions.put(SH_EXTENDED_MASTER_SECRET, |
|
290 ExtendedMasterSecretSpec.NOMINAL); |
|
291 |
|
292 return extData; |
|
293 } |
|
294 |
|
295 return null; |
|
296 } |
|
297 } |
|
298 |
|
299 /** |
|
300 * Network data consumer of a "extended_master_secret" extension in |
|
301 * the ServerHello handshake message. |
|
302 */ |
|
303 private static final |
|
304 class SHExtendedMasterSecretConsumer implements ExtensionConsumer { |
|
305 // Prevent instantiation of this class. |
|
306 private SHExtendedMasterSecretConsumer() { |
|
307 // blank |
|
308 } |
|
309 |
|
310 @Override |
|
311 public void consume(ConnectionContext context, |
|
312 HandshakeMessage message, ByteBuffer buffer) throws IOException { |
|
313 // The producing happens in client side only. |
|
314 ClientHandshakeContext chc = (ClientHandshakeContext)context; |
|
315 |
|
316 // In response to the client extended_master_secret extension |
|
317 // request, which is mandatory for ClientHello message. |
|
318 ExtendedMasterSecretSpec requstedSpec = (ExtendedMasterSecretSpec) |
|
319 chc.handshakeExtensions.get(CH_EXTENDED_MASTER_SECRET); |
|
320 if (requstedSpec == null) { |
|
321 chc.conContext.fatal(Alert.UNSUPPORTED_EXTENSION, |
|
322 "Server sent the extended_master_secret " + |
|
323 "extension improperly"); |
|
324 } |
|
325 |
|
326 // Parse the extension. |
|
327 ExtendedMasterSecretSpec spec; |
|
328 try { |
|
329 spec = new ExtendedMasterSecretSpec(buffer); |
|
330 } catch (IOException ioe) { |
|
331 chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe); |
|
332 return; // fatal() always throws, make the compiler happy. |
|
333 } |
|
334 |
|
335 if (chc.isResumption && chc.resumingSession != null && |
|
336 !chc.resumingSession.useExtendedMasterSecret) { |
|
337 chc.conContext.fatal(Alert.UNSUPPORTED_EXTENSION, |
|
338 "Server sent an unexpected extended_master_secret " + |
|
339 "extension on session resumption"); |
|
340 } |
|
341 |
|
342 // Update the context. |
|
343 chc.handshakeExtensions.put( |
|
344 SH_EXTENDED_MASTER_SECRET, ExtendedMasterSecretSpec.NOMINAL); |
|
345 |
|
346 // No impact on session resumption. |
|
347 } |
|
348 } |
|
349 |
|
350 /** |
|
351 * The absence processing if a "extended_master_secret" extension is |
|
352 * not present in the ServerHello handshake message. |
|
353 */ |
|
354 private static final |
|
355 class SHExtendedMasterSecretAbsence implements HandshakeAbsence { |
|
356 @Override |
|
357 public void absent(ConnectionContext context, |
|
358 HandshakeMessage message) throws IOException { |
|
359 // The producing happens in client side only. |
|
360 ClientHandshakeContext chc = (ClientHandshakeContext)context; |
|
361 |
|
362 if (SSLConfiguration.useExtendedMasterSecret && |
|
363 !SSLConfiguration.allowLegacyMasterSecret) { |
|
364 // For full handshake, if a client receives a ServerHello |
|
365 // without the extension, it SHOULD abort the handshake if |
|
366 // it does not wish to interoperate with legacy servers. |
|
367 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, |
|
368 "Extended Master Secret extension is required"); |
|
369 } |
|
370 |
|
371 if (chc.isResumption && chc.resumingSession != null) { |
|
372 if (chc.resumingSession.useExtendedMasterSecret) { |
|
373 // For abbreviated handshake, if the original session used |
|
374 // the "extended_master_secret" extension but the new |
|
375 // ServerHello does not contain the extension, the client |
|
376 // MUST abort the handshake. |
|
377 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, |
|
378 "Missing Extended Master Secret extension " + |
|
379 "on session resumption"); |
|
380 } else if (SSLConfiguration.useExtendedMasterSecret && |
|
381 !SSLConfiguration.allowLegacyResumption && |
|
382 chc.negotiatedProtocol.useTLS10PlusSpec()) { |
|
383 // Unlikely, abbreviated handshake should be discarded. |
|
384 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, |
|
385 "Extended Master Secret extension is required"); |
|
386 } |
|
387 } |
|
388 } |
69 } |
389 } |
70 } |
390 } |
71 |
391 |