1 /* 2 * Copyright (c) 2015, 2019, 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.util.AbstractMap.SimpleImmutableEntry; 30 import java.util.Arrays; 31 import java.util.HashMap; 32 import java.util.Map; 33 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; 34 import sun.security.ssl.X509Authentication.X509Possession; 35 36 final class SSLKeyExchange implements SSLKeyAgreementGenerator, 37 SSLHandshakeBinding { 38 private final SSLAuthentication authentication; 39 private final SSLKeyAgreement keyAgreement; 40 SSLKeyExchange(X509Authentication authentication, SSLKeyAgreement keyAgreement)41 SSLKeyExchange(X509Authentication authentication, 42 SSLKeyAgreement keyAgreement) { 43 this.authentication = authentication; 44 this.keyAgreement = keyAgreement; 45 } 46 createPossessions(HandshakeContext context)47 SSLPossession[] createPossessions(HandshakeContext context) { 48 // authentication 49 SSLPossession authPossession = null; 50 if (authentication != null) { 51 authPossession = authentication.createPossession(context); 52 if (authPossession == null) { 53 return new SSLPossession[0]; 54 } else if (context instanceof ServerHandshakeContext) { 55 // The authentication information may be used further for 56 // key agreement parameters negotiation. 57 ServerHandshakeContext shc = (ServerHandshakeContext)context; 58 shc.interimAuthn = authPossession; 59 } 60 } 61 62 // key agreement 63 SSLPossession kaPossession; 64 if (keyAgreement == T12KeyAgreement.RSA_EXPORT) { 65 // a special case 66 X509Possession x509Possession = (X509Possession)authPossession; 67 if (JsseJce.getRSAKeyLength( 68 x509Possession.popCerts[0].getPublicKey()) > 512) { 69 kaPossession = keyAgreement.createPossession(context); 70 71 if (kaPossession == null) { 72 return new SSLPossession[0]; 73 } else { 74 return authentication != null ? 75 new SSLPossession[] {authPossession, kaPossession} : 76 new SSLPossession[] {kaPossession}; 77 } 78 } else { 79 return authentication != null ? 80 new SSLPossession[] {authPossession} : 81 new SSLPossession[0]; 82 } 83 } else { 84 kaPossession = keyAgreement.createPossession(context); 85 if (kaPossession == null) { 86 // special cases 87 if (keyAgreement == T12KeyAgreement.RSA || 88 keyAgreement == T12KeyAgreement.ECDH) { 89 return authentication != null ? 90 new SSLPossession[] {authPossession} : 91 new SSLPossession[0]; 92 } else { 93 return new SSLPossession[0]; 94 } 95 } else { 96 return authentication != null ? 97 new SSLPossession[] {authPossession, kaPossession} : 98 new SSLPossession[] {kaPossession}; 99 } 100 } 101 } 102 103 @Override createKeyDerivation( HandshakeContext handshakeContext)104 public SSLKeyDerivation createKeyDerivation( 105 HandshakeContext handshakeContext) throws IOException { 106 return keyAgreement.createKeyDerivation(handshakeContext); 107 } 108 109 @Override getRelatedHandshakers( HandshakeContext handshakeContext)110 public SSLHandshake[] getRelatedHandshakers( 111 HandshakeContext handshakeContext) { 112 SSLHandshake[] auHandshakes; 113 if (authentication != null) { 114 auHandshakes = 115 authentication.getRelatedHandshakers(handshakeContext); 116 } else { 117 auHandshakes = null; 118 } 119 120 SSLHandshake[] kaHandshakes = 121 keyAgreement.getRelatedHandshakers(handshakeContext); 122 123 if (auHandshakes == null || auHandshakes.length == 0) { 124 return kaHandshakes; 125 } else if (kaHandshakes == null || kaHandshakes.length == 0) { 126 return auHandshakes; 127 } else { 128 SSLHandshake[] producers = Arrays.copyOf( 129 auHandshakes, auHandshakes.length + kaHandshakes.length); 130 System.arraycopy(kaHandshakes, 0, 131 producers, auHandshakes.length, kaHandshakes.length); 132 return producers; 133 } 134 } 135 136 @Override getHandshakeProducers( HandshakeContext handshakeContext)137 public Map.Entry<Byte, HandshakeProducer>[] getHandshakeProducers( 138 HandshakeContext handshakeContext) { 139 Map.Entry<Byte, HandshakeProducer>[] auProducers; 140 if (authentication != null) { 141 auProducers = 142 authentication.getHandshakeProducers(handshakeContext); 143 } else { 144 auProducers = null; 145 } 146 147 Map.Entry<Byte, HandshakeProducer>[] kaProducers = 148 keyAgreement.getHandshakeProducers(handshakeContext); 149 150 if (auProducers == null || auProducers.length == 0) { 151 return kaProducers; 152 } else if (kaProducers == null || kaProducers.length == 0) { 153 return auProducers; 154 } else { 155 Map.Entry<Byte, HandshakeProducer>[] producers = Arrays.copyOf( 156 auProducers, auProducers.length + kaProducers.length); 157 System.arraycopy(kaProducers, 0, 158 producers, auProducers.length, kaProducers.length); 159 return producers; 160 } 161 } 162 163 @Override getHandshakeConsumers( HandshakeContext handshakeContext)164 public Map.Entry<Byte, SSLConsumer>[] getHandshakeConsumers( 165 HandshakeContext handshakeContext) { 166 Map.Entry<Byte, SSLConsumer>[] auConsumers; 167 if (authentication != null) { 168 auConsumers = 169 authentication.getHandshakeConsumers(handshakeContext); 170 } else { 171 auConsumers = null; 172 } 173 174 Map.Entry<Byte, SSLConsumer>[] kaConsumers = 175 keyAgreement.getHandshakeConsumers(handshakeContext); 176 177 if (auConsumers == null || auConsumers.length == 0) { 178 return kaConsumers; 179 } else if (kaConsumers == null || kaConsumers.length == 0) { 180 return auConsumers; 181 } else { 182 Map.Entry<Byte, SSLConsumer>[] producers = Arrays.copyOf( 183 auConsumers, auConsumers.length + kaConsumers.length); 184 System.arraycopy(kaConsumers, 0, 185 producers, auConsumers.length, kaConsumers.length); 186 return producers; 187 } 188 } 189 190 // SSL 3.0 - (D)TLS 1.2 valueOf( CipherSuite.KeyExchange keyExchange, ProtocolVersion protocolVersion)191 static SSLKeyExchange valueOf( 192 CipherSuite.KeyExchange keyExchange, 193 ProtocolVersion protocolVersion) { 194 if (keyExchange == null || protocolVersion == null) { 195 return null; 196 } 197 198 switch (keyExchange) { 199 case K_RSA: 200 return SSLKeyExRSA.KE; 201 case K_RSA_EXPORT: 202 return SSLKeyExRSAExport.KE; 203 case K_DHE_DSS: 204 return SSLKeyExDHEDSS.KE; 205 case K_DHE_DSS_EXPORT: 206 return SSLKeyExDHEDSSExport.KE; 207 case K_DHE_RSA: 208 if (protocolVersion.useTLS12PlusSpec()) { // (D)TLS 1.2 209 return SSLKeyExDHERSAOrPSS.KE; 210 } else { // SSL 3.0, TLS 1.0/1.1 211 return SSLKeyExDHERSA.KE; 212 } 213 case K_DHE_RSA_EXPORT: 214 return SSLKeyExDHERSAExport.KE; 215 case K_DH_ANON: 216 return SSLKeyExDHANON.KE; 217 case K_DH_ANON_EXPORT: 218 return SSLKeyExDHANONExport.KE; 219 case K_ECDH_ECDSA: 220 return SSLKeyExECDHECDSA.KE; 221 case K_ECDH_RSA: 222 return SSLKeyExECDHRSA.KE; 223 case K_ECDHE_ECDSA: 224 return SSLKeyExECDHEECDSA.KE; 225 case K_ECDHE_RSA: 226 if (protocolVersion.useTLS12PlusSpec()) { // (D)TLS 1.2 227 return SSLKeyExECDHERSAOrPSS.KE; 228 } else { // SSL 3.0, TLS 1.0/1.1 229 return SSLKeyExECDHERSA.KE; 230 } 231 case K_ECDH_ANON: 232 return SSLKeyExECDHANON.KE; 233 } 234 235 return null; 236 } 237 238 // TLS 1.3 valueOf(NamedGroup namedGroup)239 static SSLKeyExchange valueOf(NamedGroup namedGroup) { 240 SSLKeyAgreement ka = T13KeyAgreement.valueOf(namedGroup); 241 if (ka != null) { 242 return new SSLKeyExchange(null, ka); 243 } 244 245 return null; 246 } 247 248 private static class SSLKeyExRSA { 249 private static SSLKeyExchange KE = new SSLKeyExchange( 250 X509Authentication.RSA, T12KeyAgreement.RSA); 251 } 252 253 private static class SSLKeyExRSAExport { 254 private static SSLKeyExchange KE = new SSLKeyExchange( 255 X509Authentication.RSA, T12KeyAgreement.RSA_EXPORT); 256 } 257 258 private static class SSLKeyExDHEDSS { 259 private static SSLKeyExchange KE = new SSLKeyExchange( 260 X509Authentication.DSA, T12KeyAgreement.DHE); 261 } 262 263 private static class SSLKeyExDHEDSSExport { 264 private static SSLKeyExchange KE = new SSLKeyExchange( 265 X509Authentication.DSA, T12KeyAgreement.DHE_EXPORT); 266 } 267 268 private static class SSLKeyExDHERSA { 269 private static SSLKeyExchange KE = new SSLKeyExchange( 270 X509Authentication.RSA, T12KeyAgreement.DHE); 271 } 272 273 private static class SSLKeyExDHERSAOrPSS { 274 private static SSLKeyExchange KE = new SSLKeyExchange( 275 X509Authentication.RSA_OR_PSS, T12KeyAgreement.DHE); 276 } 277 278 private static class SSLKeyExDHERSAExport { 279 private static SSLKeyExchange KE = new SSLKeyExchange( 280 X509Authentication.RSA, T12KeyAgreement.DHE_EXPORT); 281 } 282 283 private static class SSLKeyExDHANON { 284 private static SSLKeyExchange KE = new SSLKeyExchange( 285 null, T12KeyAgreement.DHE); 286 } 287 288 private static class SSLKeyExDHANONExport { 289 private static SSLKeyExchange KE = new SSLKeyExchange( 290 null, T12KeyAgreement.DHE_EXPORT); 291 } 292 293 private static class SSLKeyExECDHECDSA { 294 private static SSLKeyExchange KE = new SSLKeyExchange( 295 X509Authentication.EC, T12KeyAgreement.ECDH); 296 } 297 298 private static class SSLKeyExECDHRSA { 299 private static SSLKeyExchange KE = new SSLKeyExchange( 300 X509Authentication.EC, T12KeyAgreement.ECDH); 301 } 302 303 private static class SSLKeyExECDHEECDSA { 304 private static SSLKeyExchange KE = new SSLKeyExchange( 305 X509Authentication.EC, T12KeyAgreement.ECDHE); 306 } 307 308 private static class SSLKeyExECDHERSA { 309 private static SSLKeyExchange KE = new SSLKeyExchange( 310 X509Authentication.RSA, T12KeyAgreement.ECDHE); 311 } 312 313 private static class SSLKeyExECDHERSAOrPSS { 314 private static SSLKeyExchange KE = new SSLKeyExchange( 315 X509Authentication.RSA_OR_PSS, T12KeyAgreement.ECDHE); 316 } 317 318 private static class SSLKeyExECDHANON { 319 private static SSLKeyExchange KE = new SSLKeyExchange( 320 null, T12KeyAgreement.ECDHE); 321 } 322 323 private enum T12KeyAgreement implements SSLKeyAgreement { 324 RSA ("rsa", null, 325 RSAKeyExchange.kaGenerator), 326 RSA_EXPORT ("rsa_export", RSAKeyExchange.poGenerator, 327 RSAKeyExchange.kaGenerator), 328 DHE ("dhe", DHKeyExchange.poGenerator, 329 DHKeyExchange.kaGenerator), 330 DHE_EXPORT ("dhe_export", DHKeyExchange.poExportableGenerator, 331 DHKeyExchange.kaGenerator), 332 ECDH ("ecdh", null, 333 ECDHKeyExchange.ecdhKAGenerator), 334 ECDHE ("ecdhe", ECDHKeyExchange.poGenerator, 335 ECDHKeyExchange.ecdheXdhKAGenerator); 336 337 final String name; 338 final SSLPossessionGenerator possessionGenerator; 339 final SSLKeyAgreementGenerator keyAgreementGenerator; 340 T12KeyAgreement(String name, SSLPossessionGenerator possessionGenerator, SSLKeyAgreementGenerator keyAgreementGenerator)341 T12KeyAgreement(String name, 342 SSLPossessionGenerator possessionGenerator, 343 SSLKeyAgreementGenerator keyAgreementGenerator) { 344 this.name = name; 345 this.possessionGenerator = possessionGenerator; 346 this.keyAgreementGenerator = keyAgreementGenerator; 347 } 348 349 @Override createPossession(HandshakeContext context)350 public SSLPossession createPossession(HandshakeContext context) { 351 if (possessionGenerator != null) { 352 return possessionGenerator.createPossession(context); 353 } 354 355 return null; 356 } 357 358 @Override createKeyDerivation( HandshakeContext context)359 public SSLKeyDerivation createKeyDerivation( 360 HandshakeContext context) throws IOException { 361 return keyAgreementGenerator.createKeyDerivation(context); 362 } 363 364 @Override getRelatedHandshakers( HandshakeContext handshakeContext)365 public SSLHandshake[] getRelatedHandshakers( 366 HandshakeContext handshakeContext) { 367 if (!handshakeContext.negotiatedProtocol.useTLS13PlusSpec()) { 368 if (this.possessionGenerator != null) { 369 return new SSLHandshake[] { 370 SSLHandshake.SERVER_KEY_EXCHANGE 371 }; 372 } 373 } 374 375 return new SSLHandshake[0]; 376 } 377 378 @Override 379 @SuppressWarnings({"unchecked", "rawtypes"}) getHandshakeProducers( HandshakeContext handshakeContext)380 public Map.Entry<Byte, HandshakeProducer>[] getHandshakeProducers( 381 HandshakeContext handshakeContext) { 382 if (handshakeContext.negotiatedProtocol.useTLS13PlusSpec()) { 383 return (Map.Entry<Byte, HandshakeProducer>[])(new Map.Entry[0]); 384 } 385 386 if (handshakeContext.sslConfig.isClientMode) { 387 switch (this) { 388 case RSA: 389 case RSA_EXPORT: 390 return (Map.Entry<Byte, 391 HandshakeProducer>[])(new Map.Entry[] { 392 new SimpleImmutableEntry<>( 393 SSLHandshake.CLIENT_KEY_EXCHANGE.id, 394 RSAClientKeyExchange.rsaHandshakeProducer 395 ) 396 }); 397 398 case DHE: 399 case DHE_EXPORT: 400 return (Map.Entry<Byte, 401 HandshakeProducer>[])(new Map.Entry[] { 402 new SimpleImmutableEntry<Byte, HandshakeProducer>( 403 SSLHandshake.CLIENT_KEY_EXCHANGE.id, 404 DHClientKeyExchange.dhHandshakeProducer 405 ) 406 }); 407 408 case ECDH: 409 return (Map.Entry<Byte, 410 HandshakeProducer>[])(new Map.Entry[] { 411 new SimpleImmutableEntry<>( 412 SSLHandshake.CLIENT_KEY_EXCHANGE.id, 413 ECDHClientKeyExchange.ecdhHandshakeProducer 414 ) 415 }); 416 417 case ECDHE: 418 return (Map.Entry<Byte, 419 HandshakeProducer>[])(new Map.Entry[] { 420 new SimpleImmutableEntry<>( 421 SSLHandshake.CLIENT_KEY_EXCHANGE.id, 422 ECDHClientKeyExchange.ecdheHandshakeProducer 423 ) 424 }); 425 } 426 } else { 427 switch (this) { 428 case RSA_EXPORT: 429 return (Map.Entry<Byte, 430 HandshakeProducer>[])(new Map.Entry[] { 431 new SimpleImmutableEntry<>( 432 SSLHandshake.SERVER_KEY_EXCHANGE.id, 433 RSAServerKeyExchange.rsaHandshakeProducer 434 ) 435 }); 436 437 case DHE: 438 case DHE_EXPORT: 439 return (Map.Entry<Byte, 440 HandshakeProducer>[])(new Map.Entry[] { 441 new SimpleImmutableEntry<>( 442 SSLHandshake.SERVER_KEY_EXCHANGE.id, 443 DHServerKeyExchange.dhHandshakeProducer 444 ) 445 }); 446 447 case ECDHE: 448 return (Map.Entry<Byte, 449 HandshakeProducer>[])(new Map.Entry[] { 450 new SimpleImmutableEntry<>( 451 SSLHandshake.SERVER_KEY_EXCHANGE.id, 452 ECDHServerKeyExchange.ecdheHandshakeProducer 453 ) 454 }); 455 } 456 } 457 458 return (Map.Entry<Byte, HandshakeProducer>[])(new Map.Entry[0]); 459 } 460 461 @Override 462 @SuppressWarnings({"unchecked", "rawtypes"}) getHandshakeConsumers( HandshakeContext handshakeContext)463 public Map.Entry<Byte, SSLConsumer>[] getHandshakeConsumers( 464 HandshakeContext handshakeContext) { 465 if (handshakeContext.negotiatedProtocol.useTLS13PlusSpec()) { 466 return (Map.Entry<Byte, SSLConsumer>[])(new Map.Entry[0]); 467 } 468 469 if (handshakeContext.sslConfig.isClientMode) { 470 switch (this) { 471 case RSA_EXPORT: 472 return (Map.Entry<Byte, 473 SSLConsumer>[])(new Map.Entry[] { 474 new SimpleImmutableEntry<>( 475 SSLHandshake.SERVER_KEY_EXCHANGE.id, 476 RSAServerKeyExchange.rsaHandshakeConsumer 477 ) 478 }); 479 480 case DHE: 481 case DHE_EXPORT: 482 return (Map.Entry<Byte, 483 SSLConsumer>[])(new Map.Entry[] { 484 new SimpleImmutableEntry<>( 485 SSLHandshake.SERVER_KEY_EXCHANGE.id, 486 DHServerKeyExchange.dhHandshakeConsumer 487 ) 488 }); 489 490 case ECDHE: 491 return (Map.Entry<Byte, 492 SSLConsumer>[])(new Map.Entry[] { 493 new SimpleImmutableEntry<>( 494 SSLHandshake.SERVER_KEY_EXCHANGE.id, 495 ECDHServerKeyExchange.ecdheHandshakeConsumer 496 ) 497 }); 498 } 499 } else { 500 switch (this) { 501 case RSA: 502 case RSA_EXPORT: 503 return (Map.Entry<Byte, 504 SSLConsumer>[])(new Map.Entry[] { 505 new SimpleImmutableEntry<>( 506 SSLHandshake.CLIENT_KEY_EXCHANGE.id, 507 RSAClientKeyExchange.rsaHandshakeConsumer 508 ) 509 }); 510 511 case DHE: 512 case DHE_EXPORT: 513 return (Map.Entry<Byte, 514 SSLConsumer>[])(new Map.Entry[] { 515 new SimpleImmutableEntry<>( 516 SSLHandshake.CLIENT_KEY_EXCHANGE.id, 517 DHClientKeyExchange.dhHandshakeConsumer 518 ) 519 }); 520 521 case ECDH: 522 return (Map.Entry<Byte, 523 SSLConsumer>[])(new Map.Entry[] { 524 new SimpleImmutableEntry<>( 525 SSLHandshake.CLIENT_KEY_EXCHANGE.id, 526 ECDHClientKeyExchange.ecdhHandshakeConsumer 527 ) 528 }); 529 530 case ECDHE: 531 return (Map.Entry<Byte, 532 SSLConsumer>[])(new Map.Entry[] { 533 new SimpleImmutableEntry<>( 534 SSLHandshake.CLIENT_KEY_EXCHANGE.id, 535 ECDHClientKeyExchange.ecdheHandshakeConsumer 536 ) 537 }); 538 } 539 } 540 541 return (Map.Entry<Byte, SSLConsumer>[])(new Map.Entry[0]); 542 } 543 } 544 545 private static final class T13KeyAgreement implements SSLKeyAgreement { 546 private final NamedGroup namedGroup; 547 static final Map<NamedGroup, T13KeyAgreement> 548 supportedKeyShares = new HashMap<>(); 549 550 static { 551 for (NamedGroup namedGroup : 552 SupportedGroups.supportedNamedGroups) { supportedKeyShares.put( namedGroup, new T13KeyAgreement(namedGroup))553 supportedKeyShares.put( 554 namedGroup, new T13KeyAgreement(namedGroup)); 555 } 556 } 557 T13KeyAgreement(NamedGroup namedGroup)558 private T13KeyAgreement(NamedGroup namedGroup) { 559 this.namedGroup = namedGroup; 560 } 561 valueOf(NamedGroup namedGroup)562 static T13KeyAgreement valueOf(NamedGroup namedGroup) { 563 return supportedKeyShares.get(namedGroup); 564 } 565 566 @Override createPossession(HandshakeContext hc)567 public SSLPossession createPossession(HandshakeContext hc) { 568 return namedGroup.createPossession(hc.sslContext.getSecureRandom()); 569 } 570 571 @Override createKeyDerivation( HandshakeContext hc)572 public SSLKeyDerivation createKeyDerivation( 573 HandshakeContext hc) throws IOException { 574 return namedGroup.createKeyDerivation(hc); 575 } 576 } 577 } 578