1 /* 2 * Copyright (c) 2006, 2012, 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 30 import javax.net.ssl.SSLProtocolException; 31 32 /* 33 * For secure renegotiation, RFC5746 defines a new TLS extension, 34 * "renegotiation_info" (with extension type 0xff01), which contains a 35 * cryptographic binding to the enclosing TLS connection (if any) for 36 * which the renegotiation is being performed. The "extension data" 37 * field of this extension contains a "RenegotiationInfo" structure: 38 * 39 * struct { 40 * opaque renegotiated_connection<0..255>; 41 * } RenegotiationInfo; 42 */ 43 final class RenegotiationInfoExtension extends HelloExtension { 44 private final byte[] renegotiated_connection; 45 46 RenegotiationInfoExtension(byte[] clientVerifyData, 47 byte[] serverVerifyData) { 48 super(ExtensionType.EXT_RENEGOTIATION_INFO); 49 50 if (clientVerifyData.length != 0) { 51 renegotiated_connection = 52 new byte[clientVerifyData.length + serverVerifyData.length]; 53 System.arraycopy(clientVerifyData, 0, renegotiated_connection, 54 0, clientVerifyData.length); 55 56 if (serverVerifyData.length != 0) { 57 System.arraycopy(serverVerifyData, 0, renegotiated_connection, 58 clientVerifyData.length, serverVerifyData.length); 59 } 60 } else { 61 // ignore both the client and server verify data. 62 renegotiated_connection = new byte[0]; 63 } 64 } 65 66 RenegotiationInfoExtension(HandshakeInStream s, int len) 67 throws IOException { 68 super(ExtensionType.EXT_RENEGOTIATION_INFO); 69 70 // check the extension length 71 if (len < 1) { 72 throw new SSLProtocolException("Invalid " + type + " extension"); 73 } 74 75 int renegoInfoDataLen = s.getInt8(); 76 if (renegoInfoDataLen + 1 != len) { // + 1 = the byte we just read 77 throw new SSLProtocolException("Invalid " + type + " extension"); 78 } 79 80 renegotiated_connection = new byte[renegoInfoDataLen]; 81 if (renegoInfoDataLen != 0) { 82 s.read(renegotiated_connection, 0, renegoInfoDataLen); 83 } 84 } 85 86 87 // Length of the encoded extension, including the type and length fields 88 @Override 89 int length() { 90 return 5 + renegotiated_connection.length; 91 } 92 93 @Override 94 void send(HandshakeOutStream s) throws IOException { 95 s.putInt16(type.id); 96 s.putInt16(renegotiated_connection.length + 1); 97 s.putBytes8(renegotiated_connection); 98 } 99 100 boolean isEmpty() { 101 return renegotiated_connection.length == 0; 102 } 103 104 byte[] getRenegotiatedConnection() { 105 return renegotiated_connection; 106 } 107 108 @Override 109 public String toString() { 110 return "Extension " + type + ", renegotiated_connection: " + 111 (renegotiated_connection.length == 0 ? "<empty>" : 112 Debug.toString(renegotiated_connection)); 113 } 114 115 } | 1 /* 2 * Copyright (c) 2015, 2018, 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.text.MessageFormat; 31 import java.util.Arrays; 32 import java.util.Locale; 33 import javax.net.ssl.SSLProtocolException; 34 import sun.security.ssl.ClientHello.ClientHelloMessage; 35 import static sun.security.ssl.SSLExtension.CH_RENEGOTIATION_INFO; 36 import sun.security.ssl.SSLExtension.ExtensionConsumer; 37 import static sun.security.ssl.SSLExtension.SH_RENEGOTIATION_INFO; 38 import sun.security.ssl.SSLExtension.SSLExtensionSpec; 39 import sun.security.ssl.SSLHandshake.HandshakeMessage; 40 41 /** 42 * Pack of the "renegotiation_info" extensions [RFC 5746]. 43 */ 44 final class RenegoInfoExtension { 45 static final HandshakeProducer chNetworkProducer = 46 new CHRenegotiationInfoProducer(); 47 static final ExtensionConsumer chOnLoadConcumer = 48 new CHRenegotiationInfoConsumer(); 49 static final HandshakeAbsence chOnLoadAbsence = 50 new CHRenegotiationInfoAbsence(); 51 52 static final HandshakeProducer shNetworkProducer = 53 new SHRenegotiationInfoProducer(); 54 static final ExtensionConsumer shOnLoadConcumer = 55 new SHRenegotiationInfoConsumer(); 56 static final HandshakeAbsence shOnLoadAbsence = 57 new SHRenegotiationInfoAbsence(); 58 59 static final SSLStringize rniStringize = 60 new RenegotiationInfoStringize(); 61 62 /** 63 * The "renegotiation_info" extension. 64 */ 65 static final class RenegotiationInfoSpec implements SSLExtensionSpec { 66 // A nominal object that does not holding any real renegotiation info. 67 static final RenegotiationInfoSpec NOMINAL = 68 new RenegotiationInfoSpec(new byte[0]); 69 70 private final byte[] renegotiatedConnection; 71 72 private RenegotiationInfoSpec(byte[] renegotiatedConnection) { 73 this.renegotiatedConnection = Arrays.copyOf( 74 renegotiatedConnection, renegotiatedConnection.length); 75 } 76 77 private RenegotiationInfoSpec(ByteBuffer m) throws IOException { 78 // Parse the extension. 79 if (!m.hasRemaining() || m.remaining() < 1) { 80 throw new SSLProtocolException( 81 "Invalid renegotiation_info extension data: " + 82 "insufficient data"); 83 } 84 this.renegotiatedConnection = Record.getBytes8(m); 85 } 86 87 @Override 88 public String toString() { 89 MessageFormat messageFormat = new MessageFormat( 90 "\"renegotiated connection\": '['{0}']'", Locale.ENGLISH); 91 if (renegotiatedConnection.length == 0) { 92 Object[] messageFields = { 93 "<no renegotiated connection>" 94 }; 95 return messageFormat.format(messageFields); 96 } else { 97 Object[] messageFields = { 98 Utilities.toHexString(renegotiatedConnection) 99 }; 100 return messageFormat.format(messageFields); 101 } 102 } 103 } 104 105 private static final 106 class RenegotiationInfoStringize implements SSLStringize { 107 @Override 108 public String toString(ByteBuffer buffer) { 109 try { 110 return (new RenegotiationInfoSpec(buffer)).toString(); 111 } catch (IOException ioe) { 112 // For debug logging only, so please swallow exceptions. 113 return ioe.getMessage(); 114 } 115 } 116 } 117 118 /** 119 * Network data producer of a "renegotiation_info" extension in 120 * the ClientHello handshake message. 121 */ 122 private static final 123 class CHRenegotiationInfoProducer implements HandshakeProducer { 124 // Prevent instantiation of this class. 125 private CHRenegotiationInfoProducer() { 126 // blank 127 } 128 129 @Override 130 public byte[] produce(ConnectionContext context, 131 HandshakeMessage message) throws IOException { 132 // The producing happens in client side only. 133 ClientHandshakeContext chc = (ClientHandshakeContext)context; 134 135 // Is it a supported and enabled extension? 136 if (!chc.sslConfig.isAvailable(CH_RENEGOTIATION_INFO)) { 137 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 138 SSLLogger.fine( 139 "Ignore unavailable renegotiation_info extension"); 140 } 141 142 return null; 143 } 144 145 if (!chc.conContext.isNegotiated) { 146 if (chc.activeCipherSuites.contains( 147 CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { 148 // Using the the TLS_EMPTY_RENEGOTIATION_INFO_SCSV instead. 149 return null; 150 } 151 152 // initial handshaking. 153 // 154 // If this is the initial handshake for a connection, then the 155 // "renegotiated_connection" field is of zero length in both 156 // the ClientHello and the ServerHello. [RFC 5746] 157 byte[] extData = new byte[] { 0x00 }; 158 chc.handshakeExtensions.put( 159 CH_RENEGOTIATION_INFO, RenegotiationInfoSpec.NOMINAL); 160 161 return extData; 162 } else if (chc.conContext.secureRenegotiation) { 163 // secure renegotiation 164 // 165 // For ClientHello handshake message in renegotiation, this 166 // field contains the "client_verify_data". 167 byte[] extData = 168 new byte[chc.conContext.clientVerifyData.length + 1]; 169 ByteBuffer m = ByteBuffer.wrap(extData); 170 Record.putBytes8(m, chc.conContext.clientVerifyData); 171 172 // The conContext.clientVerifyData will be used for further 173 // processing, so it does not matter to save whatever in the 174 // RenegotiationInfoSpec object. 175 chc.handshakeExtensions.put( 176 CH_RENEGOTIATION_INFO, RenegotiationInfoSpec.NOMINAL); 177 178 return extData; 179 } else { // not secure renegotiation 180 if (HandshakeContext.allowUnsafeRenegotiation) { 181 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 182 SSLLogger.warning("Using insecure renegotiation"); 183 } 184 185 return null; 186 } else { 187 // terminate the session. 188 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 189 "insecure renegotiation is not allowed"); 190 } 191 } 192 193 return null; 194 } 195 } 196 197 /** 198 * Network data producer of a "renegotiation_info" extension in 199 * the ServerHello handshake message. 200 */ 201 private static final 202 class CHRenegotiationInfoConsumer implements ExtensionConsumer { 203 // Prevent instantiation of this class. 204 private CHRenegotiationInfoConsumer() { 205 // blank 206 } 207 208 @Override 209 public void consume(ConnectionContext context, 210 HandshakeMessage message, ByteBuffer buffer) throws IOException { 211 212 // The comsuming happens in server side only. 213 ServerHandshakeContext shc = (ServerHandshakeContext)context; 214 215 // Is it a supported and enabled extension? 216 if (!shc.sslConfig.isAvailable(CH_RENEGOTIATION_INFO)) { 217 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 218 SSLLogger.fine("Ignore unavailable extension: " + 219 CH_RENEGOTIATION_INFO.name); 220 } 221 return; // ignore the extension 222 } 223 224 // Parse the extension. 225 RenegotiationInfoSpec spec; 226 try { 227 spec = new RenegotiationInfoSpec(buffer); 228 } catch (IOException ioe) { 229 shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe); 230 return; // fatal() always throws, make the compiler happy. 231 } 232 233 if (!shc.conContext.isNegotiated) { 234 // initial handshaking. 235 if (spec.renegotiatedConnection.length != 0) { 236 shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, 237 "Invalid renegotiation_info extension data: not empty"); 238 } 239 shc.conContext.secureRenegotiation = true; 240 } else { 241 if (!shc.conContext.secureRenegotiation) { 242 // Unexpected RI extension for insecure renegotiation, 243 // abort the handshake with a fatal handshake_failure alert. 244 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 245 "The renegotiation_info is present in a insecure " + 246 "renegotiation"); 247 } else { 248 // verify the client_verify_data value 249 if (!Arrays.equals(shc.conContext.clientVerifyData, 250 spec.renegotiatedConnection)) { 251 shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, 252 "Invalid renegotiation_info extension data: " + 253 "incorrect verify data in ClientHello"); 254 } 255 } 256 } 257 258 // Update the context. 259 // 260 // The conContext.clientVerifyData will be used for further 261 // processing, so it does not matter to save whatever in the 262 // RenegotiationInfoSpec object. 263 shc.handshakeExtensions.put( 264 CH_RENEGOTIATION_INFO, RenegotiationInfoSpec.NOMINAL); 265 266 // No impact on session resumption. 267 } 268 } 269 270 /** 271 * The absence processing if a "renegotiation_info" extension is 272 * not present in the ClientHello handshake message. 273 */ 274 private static final 275 class CHRenegotiationInfoAbsence implements HandshakeAbsence { 276 @Override 277 public void absent(ConnectionContext context, 278 HandshakeMessage message) throws IOException { 279 // The producing happens in server side only. 280 ServerHandshakeContext shc = (ServerHandshakeContext)context; 281 ClientHelloMessage clientHello = (ClientHelloMessage)message; 282 283 if (!shc.conContext.isNegotiated) { 284 // initial handshaking. 285 for (int id : clientHello.cipherSuiteIds) { 286 if (id == 287 CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV.id) { 288 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 289 SSLLogger.finest( 290 "Safe renegotiation, using the SCSV signgling"); 291 } 292 shc.conContext.secureRenegotiation = true; 293 return; 294 } 295 } 296 297 if (!HandshakeContext.allowLegacyHelloMessages) { 298 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 299 "Failed to negotiate the use of secure renegotiation"); 300 } // otherwise, allow legacy hello message 301 302 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 303 SSLLogger.warning("Warning: No renegotiation " + 304 "indication in ClientHello, allow legacy ClientHello"); 305 } 306 307 shc.conContext.secureRenegotiation = false; 308 } else if (shc.conContext.secureRenegotiation) { 309 // Require secure renegotiation, terminate the connection. 310 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 311 "Inconsistent secure renegotiation indication"); 312 } else { // renegotiation, not secure 313 if (HandshakeContext.allowUnsafeRenegotiation) { 314 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 315 SSLLogger.warning("Using insecure renegotiation"); 316 } 317 } else { 318 // Unsafe renegotiation should have been aborted in 319 // ealier processes. 320 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 321 SSLLogger.fine("Terminate insecure renegotiation"); 322 } 323 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 324 "Unsafe renegotiation is not allowed"); 325 } 326 } 327 } 328 } 329 330 /** 331 * Network data producer of a "renegotiation_info" extension in 332 * the ServerHello handshake message. 333 */ 334 private static final 335 class SHRenegotiationInfoProducer implements HandshakeProducer { 336 // Prevent instantiation of this class. 337 private SHRenegotiationInfoProducer() { 338 // blank 339 } 340 341 @Override 342 public byte[] produce(ConnectionContext context, 343 HandshakeMessage message) throws IOException { 344 // The producing happens in server side only. 345 ServerHandshakeContext shc = (ServerHandshakeContext)context; 346 347 // In response to "renegotiation_info" extension request only. 348 RenegotiationInfoSpec requestedSpec = (RenegotiationInfoSpec) 349 shc.handshakeExtensions.get(CH_RENEGOTIATION_INFO); 350 if (requestedSpec == null && !shc.conContext.secureRenegotiation) { 351 // Ignore, no renegotiation_info extension or SCSV signgling 352 // requested. 353 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 354 SSLLogger.finest( 355 "Ignore unavailable renegotiation_info extension"); 356 } 357 return null; // ignore the extension 358 } 359 360 if (!shc.conContext.secureRenegotiation) { 361 // Ignore, no secure renegotiation is negotiated. 362 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 363 SSLLogger.finest( 364 "No secure renegotiation has been negotiated"); 365 } 366 return null; // ignore the extension 367 } 368 369 if (!shc.conContext.isNegotiated) { 370 // initial handshaking. 371 // 372 // If this is the initial handshake for a connection, then the 373 // "renegotiated_connection" field is of zero length in both 374 // the ClientHello and the ServerHello. [RFC 5746] 375 byte[] extData = new byte[] { 0x00 }; 376 377 // The conContext.client/serverVerifyData will be used for 378 // further processing, so it does not matter to save whatever 379 // in the RenegotiationInfoSpec object. 380 shc.handshakeExtensions.put( 381 SH_RENEGOTIATION_INFO, RenegotiationInfoSpec.NOMINAL); 382 383 return extData; 384 } else { 385 // secure renegotiation 386 // 387 // For secure renegotiation, the server MUST include a 388 // "renegotiation_info" extension containing the saved 389 // client_verify_data and server_verify_data in the ServerHello. 390 int infoLen = shc.conContext.clientVerifyData.length + 391 shc.conContext.serverVerifyData.length; 392 byte[] extData = new byte[infoLen + 1]; 393 ByteBuffer m = ByteBuffer.wrap(extData); 394 Record.putInt8(m, infoLen); 395 m.put(shc.conContext.clientVerifyData); 396 m.put(shc.conContext.serverVerifyData); 397 398 // The conContext.client/serverVerifyData will be used for 399 // further processing, so it does not matter to save whatever 400 // in the RenegotiationInfoSpec object. 401 shc.handshakeExtensions.put( 402 SH_RENEGOTIATION_INFO, RenegotiationInfoSpec.NOMINAL); 403 404 return extData; 405 } 406 } 407 } 408 409 /** 410 * Network data consumer of a "renegotiation_info" extension in 411 * the ServerHello handshake message. 412 */ 413 private static final 414 class SHRenegotiationInfoConsumer implements ExtensionConsumer { 415 // Prevent instantiation of this class. 416 private SHRenegotiationInfoConsumer() { 417 // blank 418 } 419 420 @Override 421 public void consume(ConnectionContext context, 422 HandshakeMessage message, ByteBuffer buffer) throws IOException { 423 // The producing happens in client side only. 424 ClientHandshakeContext chc = (ClientHandshakeContext)context; 425 426 // In response to the client renegotiation_info extension request 427 // or SCSV signling, which is mandatory for ClientHello message. 428 RenegotiationInfoSpec requestedSpec = (RenegotiationInfoSpec) 429 chc.handshakeExtensions.get(CH_RENEGOTIATION_INFO); 430 if (requestedSpec == null && 431 !chc.activeCipherSuites.contains( 432 CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { 433 chc.conContext.fatal(Alert.INTERNAL_ERROR, 434 "Missing renegotiation_info and SCSV detected in " + 435 "ClientHello"); 436 } 437 438 // Parse the extension. 439 RenegotiationInfoSpec spec; 440 try { 441 spec = new RenegotiationInfoSpec(buffer); 442 } catch (IOException ioe) { 443 chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe); 444 return; // fatal() always throws, make the compiler happy. 445 } 446 447 448 if (!chc.conContext.isNegotiated) { // initial handshake 449 // If the extension is present, set the secure_renegotiation 450 // flag to TRUE. The client MUST then verify that the 451 // length of the "renegotiated_connection" field is zero, 452 // and if it is not, MUST abort the handshake (by sending 453 // a fatal handshake_failure alert). [RFC 5746] 454 if (spec.renegotiatedConnection.length != 0) { 455 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 456 "Invalid renegotiation_info in ServerHello: " + 457 "not empty renegotiated_connection"); 458 } 459 460 chc.conContext.secureRenegotiation = true; 461 } else { // renegotiation 462 // The client MUST then verify that the first half of the 463 // "renegotiated_connection" field is equal to the saved 464 // client_verify_data value, and the second half is equal to the 465 // saved server_verify_data value. If they are not, the client 466 // MUST abort the handshake. [RFC 5746] 467 int infoLen = chc.conContext.clientVerifyData.length + 468 chc.conContext.serverVerifyData.length; 469 if (spec.renegotiatedConnection.length != infoLen) { 470 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 471 "Invalid renegotiation_info in ServerHello: " + 472 "invalid renegotiated_connection length (" + 473 spec.renegotiatedConnection.length + ")"); 474 } 475 476 byte[] cvd = chc.conContext.clientVerifyData; 477 if (!Arrays.equals(spec.renegotiatedConnection, 478 0, cvd.length, cvd, 0, cvd.length)) { 479 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 480 "Invalid renegotiation_info in ServerHello: " + 481 "unmatched client_verify_data value"); 482 } 483 byte[] svd = chc.conContext.serverVerifyData; 484 if (!Arrays.equals(spec.renegotiatedConnection, 485 cvd.length, infoLen, svd, 0, svd.length)) { 486 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 487 "Invalid renegotiation_info in ServerHello: " + 488 "unmatched server_verify_data value"); 489 } 490 } 491 492 // Update the context. 493 chc.handshakeExtensions.put( 494 SH_RENEGOTIATION_INFO, RenegotiationInfoSpec.NOMINAL); 495 496 // No impact on session resumption. 497 } 498 } 499 500 /** 501 * The absence processing if a "renegotiation_info" extension is 502 * not present in the ServerHello handshake message. 503 */ 504 private static final 505 class SHRenegotiationInfoAbsence implements HandshakeAbsence { 506 @Override 507 public void absent(ConnectionContext context, 508 HandshakeMessage message) throws IOException { 509 // The producing happens in client side only. 510 ClientHandshakeContext chc = (ClientHandshakeContext)context; 511 512 // In response to the client renegotiation_info extension request 513 // or SCSV signling, which is mandatory for ClientHello message. 514 RenegotiationInfoSpec requestedSpec = (RenegotiationInfoSpec) 515 chc.handshakeExtensions.get(CH_RENEGOTIATION_INFO); 516 if (requestedSpec == null && 517 !chc.activeCipherSuites.contains( 518 CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { 519 chc.conContext.fatal(Alert.INTERNAL_ERROR, 520 "Missing renegotiation_info and SCSV detected in " + 521 "ClientHello"); 522 } 523 524 if (!chc.conContext.isNegotiated) { 525 // initial handshaking. 526 if (!HandshakeContext.allowLegacyHelloMessages) { 527 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 528 "Failed to negotiate the use of secure renegotiation"); 529 } // otherwise, allow legacy hello message 530 531 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 532 SSLLogger.warning("Warning: No renegotiation " + 533 "indication in ServerHello, allow legacy ServerHello"); 534 } 535 536 chc.conContext.secureRenegotiation = false; 537 } else if (chc.conContext.secureRenegotiation) { 538 // Require secure renegotiation, terminate the connection. 539 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 540 "Inconsistent secure renegotiation indication"); 541 } else { // renegotiation, not secure 542 if (HandshakeContext.allowUnsafeRenegotiation) { 543 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 544 SSLLogger.warning("Using insecure renegotiation"); 545 } 546 } else { 547 // Unsafe renegotiation should have been aborted in 548 // ealier processes. 549 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 550 SSLLogger.fine("Terminate insecure renegotiation"); 551 } 552 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 553 "Unsafe renegotiation is not allowed"); 554 } 555 } 556 } 557 } 558 } |