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