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