src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java
changeset 50768 68fa3d4026ea
child 53064 103ed9569fc8
equal deleted inserted replaced
50767:356eaea05bf0 50768:68fa3d4026ea
       
     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.math.BigInteger;
       
    30 import java.nio.ByteBuffer;
       
    31 import java.security.CryptoPrimitive;
       
    32 import java.security.GeneralSecurityException;
       
    33 import java.security.InvalidAlgorithmParameterException;
       
    34 import java.security.InvalidKeyException;
       
    35 import java.security.Key;
       
    36 import java.security.KeyFactory;
       
    37 import java.security.NoSuchAlgorithmException;
       
    38 import java.security.PrivateKey;
       
    39 import java.security.PublicKey;
       
    40 import java.security.Signature;
       
    41 import java.security.SignatureException;
       
    42 import java.text.MessageFormat;
       
    43 import java.util.EnumSet;
       
    44 import java.util.Locale;
       
    45 import javax.crypto.interfaces.DHPublicKey;
       
    46 import javax.crypto.spec.DHParameterSpec;
       
    47 import javax.crypto.spec.DHPublicKeySpec;
       
    48 import sun.security.ssl.DHKeyExchange.DHECredentials;
       
    49 import sun.security.ssl.DHKeyExchange.DHEPossession;
       
    50 import sun.security.ssl.SSLHandshake.HandshakeMessage;
       
    51 import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
       
    52 import sun.security.ssl.X509Authentication.X509Credentials;
       
    53 import sun.security.ssl.X509Authentication.X509Possession;
       
    54 import sun.security.util.HexDumpEncoder;
       
    55 import sun.security.util.KeyUtil;
       
    56 
       
    57 /**
       
    58  * Pack of the ServerKeyExchange handshake message.
       
    59  */
       
    60 final class DHServerKeyExchange {
       
    61     static final SSLConsumer dhHandshakeConsumer =
       
    62             new DHServerKeyExchangeConsumer();
       
    63     static final HandshakeProducer dhHandshakeProducer =
       
    64             new DHServerKeyExchangeProducer();
       
    65 
       
    66     /**
       
    67      * The DiffieHellman ServerKeyExchange handshake message.
       
    68      */
       
    69     private static final
       
    70             class DHServerKeyExchangeMessage extends HandshakeMessage {
       
    71         // public key encapsulated in this message
       
    72         private final byte[] p;        // 1 to 2^16 - 1 bytes
       
    73         private final byte[] g;        // 1 to 2^16 - 1 bytes
       
    74         private final byte[] y;        // 1 to 2^16 - 1 bytes
       
    75 
       
    76         // the signature algorithm used by this ServerKeyExchange message
       
    77         private final boolean useExplicitSigAlgorithm;
       
    78         private final SignatureScheme signatureScheme;
       
    79 
       
    80         // signature bytes, or null if anonymous
       
    81         private final byte[] paramsSignature;
       
    82 
       
    83         DHServerKeyExchangeMessage(
       
    84                 HandshakeContext handshakeContext) throws IOException {
       
    85             super(handshakeContext);
       
    86 
       
    87             // This happens in server side only.
       
    88             ServerHandshakeContext shc =
       
    89                     (ServerHandshakeContext)handshakeContext;
       
    90 
       
    91             DHEPossession dhePossession = null;
       
    92             X509Possession x509Possession = null;
       
    93             for (SSLPossession possession : shc.handshakePossessions) {
       
    94                 if (possession instanceof DHEPossession) {
       
    95                     dhePossession = (DHEPossession)possession;
       
    96                     if (x509Possession != null) {
       
    97                         break;
       
    98                     }
       
    99                 } else if (possession instanceof X509Possession) {
       
   100                     x509Possession = (X509Possession)possession;
       
   101                     if (dhePossession != null) {
       
   102                         break;
       
   103                     }
       
   104                 }
       
   105             }
       
   106 
       
   107             if (dhePossession == null) {
       
   108                 // unlikely
       
   109                 shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   110                     "No DHE credentials negotiated for server key exchange");
       
   111             }
       
   112             DHPublicKey publicKey = dhePossession.publicKey;
       
   113             DHParameterSpec params = publicKey.getParams();
       
   114             this.p = Utilities.toByteArray(params.getP());
       
   115             this.g = Utilities.toByteArray(params.getG());
       
   116             this.y = Utilities.toByteArray(publicKey.getY());
       
   117 
       
   118             if (x509Possession == null) {
       
   119                 // anonymous, no authentication, no signature
       
   120                 paramsSignature = null;
       
   121                 signatureScheme = null;
       
   122                 useExplicitSigAlgorithm = false;
       
   123             } else {
       
   124                 useExplicitSigAlgorithm =
       
   125                         shc.negotiatedProtocol.useTLS12PlusSpec();
       
   126                 Signature signer = null;
       
   127                 if (useExplicitSigAlgorithm) {
       
   128                     signatureScheme = SignatureScheme.getPreferableAlgorithm(
       
   129                             shc.peerRequestedSignatureSchemes,
       
   130                             x509Possession.popPrivateKey,
       
   131                             shc.negotiatedProtocol);
       
   132                     if (signatureScheme == null) {
       
   133                         // Unlikely, the credentials generator should have
       
   134                         // selected the preferable signature algorithm properly.
       
   135                         shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   136                             "No preferred signature algorithm");
       
   137                     }
       
   138                     try {
       
   139                         signer = signatureScheme.getSignature(
       
   140                                 x509Possession.popPrivateKey);
       
   141                     } catch (NoSuchAlgorithmException | InvalidKeyException |
       
   142                             InvalidAlgorithmParameterException nsae) {
       
   143                         shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   144                             "Unsupported signature algorithm: " +
       
   145                             signatureScheme.name, nsae);
       
   146                     }
       
   147                 } else {
       
   148                     signatureScheme = null;
       
   149                     try {
       
   150                         signer = getSignature(
       
   151                                 x509Possession.popPrivateKey.getAlgorithm(),
       
   152                                 x509Possession.popPrivateKey);
       
   153                     } catch (NoSuchAlgorithmException | InvalidKeyException e) {
       
   154                         shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   155                             "Unsupported signature algorithm: " +
       
   156                             x509Possession.popPrivateKey.getAlgorithm(), e);
       
   157                     }
       
   158                 }
       
   159 
       
   160                 byte[] signature = null;
       
   161                 try {
       
   162                     updateSignature(signer, shc.clientHelloRandom.randomBytes,
       
   163                             shc.serverHelloRandom.randomBytes);
       
   164                     signature = signer.sign();
       
   165                 } catch (SignatureException ex) {
       
   166                     shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   167                         "Failed to sign dhe parameters: " +
       
   168                         x509Possession.popPrivateKey.getAlgorithm(), ex);
       
   169                 }
       
   170                 paramsSignature = signature;
       
   171             }
       
   172         }
       
   173 
       
   174         DHServerKeyExchangeMessage(HandshakeContext handshakeContext,
       
   175                 ByteBuffer m) throws IOException {
       
   176             super(handshakeContext);
       
   177 
       
   178             // This happens in client side only.
       
   179             ClientHandshakeContext chc =
       
   180                     (ClientHandshakeContext)handshakeContext;
       
   181 
       
   182             this.p = Record.getBytes16(m);
       
   183             this.g = Record.getBytes16(m);
       
   184             this.y = Record.getBytes16(m);
       
   185 
       
   186             try {
       
   187                 KeyUtil.validate(new DHPublicKeySpec(
       
   188                         new BigInteger(1, y),
       
   189                         new BigInteger(1, p),
       
   190                         new BigInteger(1, p)));
       
   191             } catch (InvalidKeyException ike) {
       
   192                 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   193                     "Invalid DH ServerKeyExchange: invalid parameters", ike);
       
   194             }
       
   195 
       
   196             X509Credentials x509Credentials = null;
       
   197             for (SSLCredentials cd : chc.handshakeCredentials) {
       
   198                 if (cd instanceof X509Credentials) {
       
   199                     x509Credentials = (X509Credentials)cd;
       
   200                     break;
       
   201                 }
       
   202             }
       
   203 
       
   204             if (x509Credentials == null) {
       
   205                 // anonymous, no authentication, no signature
       
   206                 if (m.hasRemaining()) {
       
   207                     chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   208                         "Invalid DH ServerKeyExchange: unknown extra data");
       
   209                 }
       
   210 
       
   211                 this.signatureScheme = null;
       
   212                 this.paramsSignature = null;
       
   213                 this.useExplicitSigAlgorithm = false;
       
   214 
       
   215                 return;
       
   216             }
       
   217 
       
   218             this.useExplicitSigAlgorithm =
       
   219                     chc.negotiatedProtocol.useTLS12PlusSpec();
       
   220             if (useExplicitSigAlgorithm) {
       
   221                 int ssid = Record.getInt16(m);
       
   222                 signatureScheme = SignatureScheme.valueOf(ssid);
       
   223                 if (signatureScheme == null) {
       
   224                     chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   225                             "Invalid signature algorithm (" + ssid +
       
   226                             ") used in DH ServerKeyExchange handshake message");
       
   227                 }
       
   228 
       
   229                 if (!chc.localSupportedSignAlgs.contains(signatureScheme)) {
       
   230                     chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   231                             "Unsupported signature algorithm (" +
       
   232                             signatureScheme.name +
       
   233                             ") used in DH ServerKeyExchange handshake message");
       
   234                 }
       
   235             } else {
       
   236                 this.signatureScheme = null;
       
   237             }
       
   238 
       
   239             // read and verify the signature
       
   240             this.paramsSignature = Record.getBytes16(m);
       
   241             Signature signer;
       
   242             if (useExplicitSigAlgorithm) {
       
   243                 try {
       
   244                     signer = signatureScheme.getSignature(
       
   245                             x509Credentials.popPublicKey);
       
   246                 } catch (NoSuchAlgorithmException | InvalidKeyException |
       
   247                         InvalidAlgorithmParameterException nsae) {
       
   248                     chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   249                             "Unsupported signature algorithm: " +
       
   250                             signatureScheme.name, nsae);
       
   251 
       
   252                     return;     // make the compiler happe
       
   253                 }
       
   254             } else {
       
   255                 try {
       
   256                     signer = getSignature(
       
   257                             x509Credentials.popPublicKey.getAlgorithm(),
       
   258                             x509Credentials.popPublicKey);
       
   259                 } catch (NoSuchAlgorithmException | InvalidKeyException e) {
       
   260                     chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   261                             "Unsupported signature algorithm: " +
       
   262                             x509Credentials.popPublicKey.getAlgorithm(), e);
       
   263 
       
   264                     return;     // make the compiler happe
       
   265                 }
       
   266             }
       
   267 
       
   268             try {
       
   269                 updateSignature(signer,
       
   270                         chc.clientHelloRandom.randomBytes,
       
   271                         chc.serverHelloRandom.randomBytes);
       
   272 
       
   273                 if (!signer.verify(paramsSignature)) {
       
   274                     chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   275                         "Invalid signature on DH ServerKeyExchange message");
       
   276                 }
       
   277             } catch (SignatureException ex) {
       
   278                 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   279                         "Cannot verify DH ServerKeyExchange signature", ex);
       
   280             }
       
   281         }
       
   282 
       
   283         @Override
       
   284         public SSLHandshake handshakeType() {
       
   285             return SSLHandshake.SERVER_KEY_EXCHANGE;
       
   286         }
       
   287 
       
   288         @Override
       
   289         public int messageLength() {
       
   290             int sigLen = 0;
       
   291             if (paramsSignature != null) {
       
   292                 sigLen = 2 + paramsSignature.length;
       
   293                 if (useExplicitSigAlgorithm) {
       
   294                     sigLen += SignatureScheme.sizeInRecord();
       
   295                 }
       
   296             }
       
   297 
       
   298             return 6 + p.length + g.length + y.length + sigLen;
       
   299                     // 6: overhead for p, g, y values
       
   300         }
       
   301 
       
   302         @Override
       
   303         public void send(HandshakeOutStream hos) throws IOException {
       
   304             hos.putBytes16(p);
       
   305             hos.putBytes16(g);
       
   306             hos.putBytes16(y);
       
   307 
       
   308             if (paramsSignature != null) {
       
   309                 if (useExplicitSigAlgorithm) {
       
   310                     hos.putInt16(signatureScheme.id);
       
   311                 }
       
   312 
       
   313                 hos.putBytes16(paramsSignature);
       
   314             }
       
   315         }
       
   316 
       
   317         @Override
       
   318         public String toString() {
       
   319             if (paramsSignature == null) {    // anonymous
       
   320                 MessageFormat messageFormat = new MessageFormat(
       
   321                     "\"DH ServerKeyExchange\": '{'\n" +
       
   322                     "  \"parameters\": '{'\n" +
       
   323                     "    \"dh_p\": '{'\n" +
       
   324                     "{0}\n" +
       
   325                     "    '}',\n" +
       
   326                     "    \"dh_g\": '{'\n" +
       
   327                     "{1}\n" +
       
   328                     "    '}',\n" +
       
   329                     "    \"dh_Ys\": '{'\n" +
       
   330                     "{2}\n" +
       
   331                     "    '}',\n" +
       
   332                     "  '}'\n" +
       
   333                     "'}'",
       
   334                     Locale.ENGLISH);
       
   335 
       
   336                 HexDumpEncoder hexEncoder = new HexDumpEncoder();
       
   337                 Object[] messageFields = {
       
   338                     Utilities.indent(
       
   339                             hexEncoder.encodeBuffer(p), "      "),
       
   340                     Utilities.indent(
       
   341                             hexEncoder.encodeBuffer(g), "      "),
       
   342                     Utilities.indent(
       
   343                             hexEncoder.encodeBuffer(y), "      "),
       
   344                 };
       
   345 
       
   346                 return messageFormat.format(messageFields);
       
   347             }
       
   348 
       
   349             if (useExplicitSigAlgorithm) {
       
   350                 MessageFormat messageFormat = new MessageFormat(
       
   351                     "\"DH ServerKeyExchange\": '{'\n" +
       
   352                     "  \"parameters\": '{'\n" +
       
   353                     "    \"dh_p\": '{'\n" +
       
   354                     "{0}\n" +
       
   355                     "    '}',\n" +
       
   356                     "    \"dh_g\": '{'\n" +
       
   357                     "{1}\n" +
       
   358                     "    '}',\n" +
       
   359                     "    \"dh_Ys\": '{'\n" +
       
   360                     "{2}\n" +
       
   361                     "    '}',\n" +
       
   362                     "  '}',\n" +
       
   363                     "  \"digital signature\":  '{'\n" +
       
   364                     "    \"signature algorithm\": \"{3}\"\n" +
       
   365                     "    \"signature\": '{'\n" +
       
   366                     "{4}\n" +
       
   367                     "    '}',\n" +
       
   368                     "  '}'\n" +
       
   369                     "'}'",
       
   370                     Locale.ENGLISH);
       
   371 
       
   372                 HexDumpEncoder hexEncoder = new HexDumpEncoder();
       
   373                 Object[] messageFields = {
       
   374                     Utilities.indent(
       
   375                             hexEncoder.encodeBuffer(p), "      "),
       
   376                     Utilities.indent(
       
   377                             hexEncoder.encodeBuffer(g), "      "),
       
   378                     Utilities.indent(
       
   379                             hexEncoder.encodeBuffer(y), "      "),
       
   380                     signatureScheme.name,
       
   381                     Utilities.indent(
       
   382                             hexEncoder.encodeBuffer(paramsSignature), "      ")
       
   383                 };
       
   384 
       
   385                 return messageFormat.format(messageFields);
       
   386             } else {
       
   387                 MessageFormat messageFormat = new MessageFormat(
       
   388                     "\"DH ServerKeyExchange\": '{'\n" +
       
   389                     "  \"parameters\": '{'\n" +
       
   390                     "    \"dh_p\": '{'\n" +
       
   391                     "{0}\n" +
       
   392                     "    '}',\n" +
       
   393                     "    \"dh_g\": '{'\n" +
       
   394                     "{1}\n" +
       
   395                     "    '}',\n" +
       
   396                     "    \"dh_Ys\": '{'\n" +
       
   397                     "{2}\n" +
       
   398                     "    '}',\n" +
       
   399                     "  '}',\n" +
       
   400                     "  \"signature\": '{'\n" +
       
   401                     "{3}\n" +
       
   402                     "  '}'\n" +
       
   403                     "'}'",
       
   404                     Locale.ENGLISH);
       
   405 
       
   406                 HexDumpEncoder hexEncoder = new HexDumpEncoder();
       
   407                 Object[] messageFields = {
       
   408                     Utilities.indent(
       
   409                             hexEncoder.encodeBuffer(p), "      "),
       
   410                     Utilities.indent(
       
   411                             hexEncoder.encodeBuffer(g), "      "),
       
   412                     Utilities.indent(
       
   413                             hexEncoder.encodeBuffer(y), "      "),
       
   414                     Utilities.indent(
       
   415                             hexEncoder.encodeBuffer(paramsSignature), "    ")
       
   416                 };
       
   417 
       
   418                 return messageFormat.format(messageFields);
       
   419             }
       
   420         }
       
   421 
       
   422         private static Signature getSignature(String keyAlgorithm,
       
   423                 Key key) throws NoSuchAlgorithmException, InvalidKeyException {
       
   424             Signature signer = null;
       
   425             switch (keyAlgorithm) {
       
   426                 case "DSA":
       
   427                     signer = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
       
   428                     break;
       
   429                 case "RSA":
       
   430                     signer = RSASignature.getInstance();
       
   431                     break;
       
   432                 default:
       
   433                     throw new NoSuchAlgorithmException(
       
   434                         "neither an RSA or a DSA key : " + keyAlgorithm);
       
   435             }
       
   436 
       
   437             if (signer != null) {
       
   438                 if (key instanceof PublicKey) {
       
   439                     signer.initVerify((PublicKey)(key));
       
   440                 } else {
       
   441                     signer.initSign((PrivateKey)key);
       
   442                 }
       
   443             }
       
   444 
       
   445             return signer;
       
   446         }
       
   447 
       
   448         /*
       
   449          * Update sig with nonces and Diffie-Hellman public key.
       
   450          */
       
   451         private void updateSignature(Signature sig, byte[] clntNonce,
       
   452                 byte[] svrNonce) throws SignatureException {
       
   453             int tmp;
       
   454 
       
   455             sig.update(clntNonce);
       
   456             sig.update(svrNonce);
       
   457 
       
   458             sig.update((byte)(p.length >> 8));
       
   459             sig.update((byte)(p.length & 0x0ff));
       
   460             sig.update(p);
       
   461 
       
   462             sig.update((byte)(g.length >> 8));
       
   463             sig.update((byte)(g.length & 0x0ff));
       
   464             sig.update(g);
       
   465 
       
   466             sig.update((byte)(y.length >> 8));
       
   467             sig.update((byte)(y.length & 0x0ff));
       
   468             sig.update(y);
       
   469         }
       
   470     }
       
   471 
       
   472     /**
       
   473      * The DiffieHellman "ServerKeyExchange" handshake message producer.
       
   474      */
       
   475     static final class DHServerKeyExchangeProducer
       
   476             implements HandshakeProducer {
       
   477         // Prevent instantiation of this class.
       
   478         private DHServerKeyExchangeProducer() {
       
   479             // blank
       
   480         }
       
   481 
       
   482         @Override
       
   483         public byte[] produce(ConnectionContext context,
       
   484                 HandshakeMessage message) throws IOException {
       
   485             // The producing happens in server side only.
       
   486             ServerHandshakeContext shc = (ServerHandshakeContext)context;
       
   487             DHServerKeyExchangeMessage skem =
       
   488                     new DHServerKeyExchangeMessage(shc);
       
   489             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   490                 SSLLogger.fine(
       
   491                     "Produced DH ServerKeyExchange handshake message", skem);
       
   492             }
       
   493 
       
   494             // Output the handshake message.
       
   495             skem.write(shc.handshakeOutput);
       
   496             shc.handshakeOutput.flush();
       
   497 
       
   498             // The handshake message has been delivered.
       
   499             return null;
       
   500         }
       
   501     }
       
   502 
       
   503     /**
       
   504      * The DiffieHellman "ServerKeyExchange" handshake message consumer.
       
   505      */
       
   506     static final class DHServerKeyExchangeConsumer implements SSLConsumer {
       
   507         // Prevent instantiation of this class.
       
   508         private DHServerKeyExchangeConsumer() {
       
   509             // blank
       
   510         }
       
   511 
       
   512         @Override
       
   513         public void consume(ConnectionContext context,
       
   514                 ByteBuffer message) throws IOException {
       
   515             // The consuming happens in client side only.
       
   516             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   517 
       
   518             DHServerKeyExchangeMessage skem =
       
   519                     new DHServerKeyExchangeMessage(chc, message);
       
   520             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   521                 SSLLogger.fine(
       
   522                     "Consuming DH ServerKeyExchange handshake message", skem);
       
   523             }
       
   524 
       
   525             //
       
   526             // validate
       
   527             //
       
   528             // check constraints of EC PublicKey
       
   529             DHPublicKey publicKey;
       
   530             try {
       
   531                 KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
       
   532                 DHPublicKeySpec spec = new DHPublicKeySpec(
       
   533                         new BigInteger(1, skem.y),
       
   534                         new BigInteger(1, skem.p),
       
   535                         new BigInteger(1, skem.g));
       
   536                 publicKey = (DHPublicKey)kf.generatePublic(spec);
       
   537             } catch (GeneralSecurityException gse) {
       
   538                 chc.conContext.fatal(Alert.INSUFFICIENT_SECURITY,
       
   539                     "Could not generate DHPublicKey", gse);
       
   540 
       
   541                 return;     // make the compiler happy
       
   542             }
       
   543 
       
   544             if (!chc.algorithmConstraints.permits(
       
   545                     EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), publicKey)) {
       
   546                 chc.conContext.fatal(Alert.INSUFFICIENT_SECURITY,
       
   547                         "DH ServerKeyExchange does not comply to " +
       
   548                         "algorithm constraints");
       
   549             }
       
   550 
       
   551             //
       
   552             // update
       
   553             //
       
   554             NamedGroup namedGroup = NamedGroup.valueOf(publicKey.getParams());
       
   555             chc.handshakeCredentials.add(
       
   556                     new DHECredentials(publicKey, namedGroup));
       
   557 
       
   558             //
       
   559             // produce
       
   560             //
       
   561             // Need no new handshake message producers here.
       
   562         }
       
   563     }
       
   564 }
       
   565