src/java.base/share/classes/sun/security/ssl/ECDHClientKeyExchange.java
changeset 50768 68fa3d4026ea
parent 47216 71c04702a3d5
child 53064 103ed9569fc8
equal deleted inserted replaced
50767:356eaea05bf0 50768:68fa3d4026ea
     1 /*
     1 /*
     2  * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    24  */
    24  */
    25 
    25 
    26 package sun.security.ssl;
    26 package sun.security.ssl;
    27 
    27 
    28 import java.io.IOException;
    28 import java.io.IOException;
    29 import java.io.PrintStream;
    29 import java.nio.ByteBuffer;
    30 
    30 import java.security.AlgorithmConstraints;
       
    31 import java.security.CryptoPrimitive;
       
    32 import java.security.GeneralSecurityException;
       
    33 import java.security.KeyFactory;
       
    34 import java.security.PrivateKey;
    31 import java.security.PublicKey;
    35 import java.security.PublicKey;
       
    36 import java.security.interfaces.ECPrivateKey;
    32 import java.security.interfaces.ECPublicKey;
    37 import java.security.interfaces.ECPublicKey;
    33 import java.security.spec.*;
    38 import java.security.spec.ECParameterSpec;
       
    39 import java.security.spec.ECPoint;
       
    40 import java.security.spec.ECPublicKeySpec;
       
    41 import java.text.MessageFormat;
       
    42 import java.util.EnumSet;
       
    43 import java.util.Locale;
       
    44 import javax.crypto.SecretKey;
       
    45 import javax.net.ssl.SSLHandshakeException;
       
    46 import sun.security.ssl.ECDHKeyExchange.ECDHECredentials;
       
    47 import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
       
    48 import sun.security.ssl.SSLHandshake.HandshakeMessage;
       
    49 import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
       
    50 import sun.security.ssl.X509Authentication.X509Credentials;
       
    51 import sun.security.ssl.X509Authentication.X509Possession;
       
    52 import sun.security.util.HexDumpEncoder;
    34 
    53 
    35 /**
    54 /**
    36  * ClientKeyExchange message for all ECDH based key exchange methods. It
    55  * Pack of the "ClientKeyExchange" handshake message.
    37  * contains the client's ephemeral public value.
       
    38  *
       
    39  * @since   1.6
       
    40  * @author  Andreas Sterbenz
       
    41  */
    56  */
    42 final class ECDHClientKeyExchange extends HandshakeMessage {
    57 final class ECDHClientKeyExchange {
    43 
    58     static final SSLConsumer ecdhHandshakeConsumer =
    44     @Override
    59             new ECDHClientKeyExchangeConsumer();
    45     int messageType() {
    60     static final HandshakeProducer ecdhHandshakeProducer =
    46         return ht_client_key_exchange;
    61             new ECDHClientKeyExchangeProducer();
       
    62 
       
    63     static final SSLConsumer ecdheHandshakeConsumer =
       
    64             new ECDHEClientKeyExchangeConsumer();
       
    65     static final HandshakeProducer ecdheHandshakeProducer =
       
    66             new ECDHEClientKeyExchangeProducer();
       
    67 
       
    68     /**
       
    69      * The ECDH/ECDHE ClientKeyExchange handshake message.
       
    70      */
       
    71     private static final
       
    72             class ECDHClientKeyExchangeMessage extends HandshakeMessage {
       
    73         private final byte[] encodedPoint;
       
    74 
       
    75         ECDHClientKeyExchangeMessage(HandshakeContext handshakeContext,
       
    76                 ECPublicKey publicKey) {
       
    77             super(handshakeContext);
       
    78 
       
    79             ECPoint point = publicKey.getW();
       
    80             ECParameterSpec params = publicKey.getParams();
       
    81             encodedPoint = JsseJce.encodePoint(point, params.getCurve());
       
    82         }
       
    83 
       
    84         ECDHClientKeyExchangeMessage(HandshakeContext handshakeContext,
       
    85                 ByteBuffer m) throws IOException {
       
    86             super(handshakeContext);
       
    87             if (m.remaining() != 0) {       // explicit PublicValueEncoding
       
    88                 this.encodedPoint = Record.getBytes8(m);
       
    89             } else {
       
    90                 this.encodedPoint = new byte[0];
       
    91             }
       
    92         }
       
    93 
       
    94         // Check constraints of the specified EC public key.
       
    95         static void checkConstraints(AlgorithmConstraints constraints,
       
    96                 ECPublicKey publicKey,
       
    97                 byte[] encodedPoint) throws SSLHandshakeException {
       
    98 
       
    99             try {
       
   100                 ECParameterSpec params = publicKey.getParams();
       
   101                 ECPoint point =
       
   102                         JsseJce.decodePoint(encodedPoint, params.getCurve());
       
   103                 ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
       
   104 
       
   105                 KeyFactory kf = JsseJce.getKeyFactory("EC");
       
   106                 ECPublicKey peerPublicKey =
       
   107                         (ECPublicKey)kf.generatePublic(spec);
       
   108 
       
   109                 // check constraints of ECPublicKey
       
   110                 if (!constraints.permits(
       
   111                         EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   112                         peerPublicKey)) {
       
   113                     throw new SSLHandshakeException(
       
   114                         "ECPublicKey does not comply to algorithm constraints");
       
   115                 }
       
   116             } catch (GeneralSecurityException | java.io.IOException e) {
       
   117                 throw (SSLHandshakeException) new SSLHandshakeException(
       
   118                         "Could not generate ECPublicKey").initCause(e);
       
   119             }
       
   120         }
       
   121 
       
   122         @Override
       
   123         public SSLHandshake handshakeType() {
       
   124             return SSLHandshake.CLIENT_KEY_EXCHANGE;
       
   125         }
       
   126 
       
   127         @Override
       
   128         public int messageLength() {
       
   129             if (encodedPoint == null || encodedPoint.length == 0) {
       
   130                 return 0;
       
   131             } else {
       
   132                 return 1 + encodedPoint.length;
       
   133             }
       
   134         }
       
   135 
       
   136         @Override
       
   137         public void send(HandshakeOutStream hos) throws IOException {
       
   138             if (encodedPoint != null && encodedPoint.length != 0) {
       
   139                 hos.putBytes8(encodedPoint);
       
   140             }
       
   141         }
       
   142 
       
   143         @Override
       
   144         public String toString() {
       
   145             MessageFormat messageFormat = new MessageFormat(
       
   146                 "\"ECDH ClientKeyExchange\": '{'\n" +
       
   147                 "  \"ecdh public\": '{'\n" +
       
   148                 "{0}\n" +
       
   149                 "  '}',\n" +
       
   150                 "'}'",
       
   151                 Locale.ENGLISH);
       
   152             if (encodedPoint == null || encodedPoint.length == 0) {
       
   153                 Object[] messageFields = {
       
   154                     "    <implicit>"
       
   155                 };
       
   156                 return messageFormat.format(messageFields);
       
   157             } else {
       
   158                 HexDumpEncoder hexEncoder = new HexDumpEncoder();
       
   159                 Object[] messageFields = {
       
   160                     Utilities.indent(
       
   161                             hexEncoder.encodeBuffer(encodedPoint), "    "),
       
   162                 };
       
   163                 return messageFormat.format(messageFields);
       
   164             }
       
   165         }
    47     }
   166     }
    48 
   167 
    49     private byte[] encodedPoint;
   168     /**
    50 
   169      * The ECDH "ClientKeyExchange" handshake message producer.
    51     byte[] getEncodedPoint() {
   170      */
    52         return encodedPoint;
   171     private static final
       
   172             class ECDHClientKeyExchangeProducer implements HandshakeProducer {
       
   173         // Prevent instantiation of this class.
       
   174         private ECDHClientKeyExchangeProducer() {
       
   175             // blank
       
   176         }
       
   177 
       
   178         @Override
       
   179         public byte[] produce(ConnectionContext context,
       
   180                 HandshakeMessage message) throws IOException {
       
   181             // The producing happens in client side only.
       
   182             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   183 
       
   184             X509Credentials x509Credentials = null;
       
   185             for (SSLCredentials credential : chc.handshakeCredentials) {
       
   186                 if (credential instanceof X509Credentials) {
       
   187                     x509Credentials = (X509Credentials)credential;
       
   188                     break;
       
   189                 }
       
   190             }
       
   191 
       
   192             if (x509Credentials == null) {
       
   193                 chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   194                     "No server certificate for ECDH client key exchange");
       
   195             }
       
   196 
       
   197             PublicKey publicKey = x509Credentials.popPublicKey;
       
   198             if (!publicKey.getAlgorithm().equals("EC")) {
       
   199                 chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   200                     "Not EC server certificate for ECDH client key exchange");
       
   201             }
       
   202 
       
   203             ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
       
   204             NamedGroup namedGroup = NamedGroup.valueOf(params);
       
   205             if (namedGroup == null) {
       
   206                 chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   207                     "Unsupported EC server cert for ECDH client key exchange");
       
   208             }
       
   209 
       
   210             ECDHEPossession ecdhePossession = new ECDHEPossession(
       
   211                     namedGroup, chc.sslContext.getSecureRandom());
       
   212             chc.handshakePossessions.add(ecdhePossession);
       
   213             ECDHClientKeyExchangeMessage cke =
       
   214                     new ECDHClientKeyExchangeMessage(
       
   215                             chc, ecdhePossession.publicKey);
       
   216             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   217                 SSLLogger.fine(
       
   218                     "Produced ECDH ClientKeyExchange handshake message", cke);
       
   219             }
       
   220 
       
   221             // Output the handshake message.
       
   222             cke.write(chc.handshakeOutput);
       
   223             chc.handshakeOutput.flush();
       
   224 
       
   225             // update the states
       
   226             SSLKeyExchange ke = SSLKeyExchange.valueOf(
       
   227                     chc.negotiatedCipherSuite.keyExchange,
       
   228                     chc.negotiatedProtocol);
       
   229             if (ke == null) {
       
   230                 // unlikely
       
   231                 chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   232                         "Not supported key exchange type");
       
   233             } else {
       
   234                 SSLKeyDerivation masterKD = ke.createKeyDerivation(chc);
       
   235                 SecretKey masterSecret =
       
   236                         masterKD.deriveKey("MasterSecret", null);
       
   237                 chc.handshakeSession.setMasterSecret(masterSecret);
       
   238 
       
   239                 SSLTrafficKeyDerivation kd =
       
   240                         SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
       
   241                 if (kd == null) {
       
   242                     // unlikely
       
   243                     chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   244                             "Not supported key derivation: " +
       
   245                             chc.negotiatedProtocol);
       
   246                 } else {
       
   247                     chc.handshakeKeyDerivation =
       
   248                         kd.createKeyDerivation(chc, masterSecret);
       
   249                 }
       
   250             }
       
   251 
       
   252             // The handshake message has been delivered.
       
   253             return null;
       
   254         }
    53     }
   255     }
    54 
   256 
    55     // Called by the client with its ephemeral public key.
   257     /**
    56     ECDHClientKeyExchange(PublicKey publicKey) {
   258      * The ECDH "ClientKeyExchange" handshake message consumer.
    57         ECPublicKey ecKey = (ECPublicKey)publicKey;
   259      */
    58         ECPoint point = ecKey.getW();
   260     private static final
    59         ECParameterSpec params = ecKey.getParams();
   261             class ECDHClientKeyExchangeConsumer implements SSLConsumer {
    60         encodedPoint = JsseJce.encodePoint(point, params.getCurve());
   262         // Prevent instantiation of this class.
       
   263         private ECDHClientKeyExchangeConsumer() {
       
   264             // blank
       
   265         }
       
   266 
       
   267         @Override
       
   268         public void consume(ConnectionContext context,
       
   269                 ByteBuffer message) throws IOException {
       
   270             // The consuming happens in server side only.
       
   271             ServerHandshakeContext shc = (ServerHandshakeContext)context;
       
   272 
       
   273             X509Possession x509Possession = null;
       
   274             for (SSLPossession possession : shc.handshakePossessions) {
       
   275                 if (possession instanceof X509Possession) {
       
   276                     x509Possession = (X509Possession)possession;
       
   277                     break;
       
   278                 }
       
   279             }
       
   280 
       
   281             if (x509Possession == null) {
       
   282                 // unlikely, have been checked during cipher suite negotiation.
       
   283                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   284                     "No expected EC server cert for ECDH client key exchange");
       
   285                 return;     // make the compiler happy
       
   286             }
       
   287 
       
   288             PrivateKey privateKey = x509Possession.popPrivateKey;
       
   289             if (!privateKey.getAlgorithm().equals("EC")) {
       
   290                 // unlikely, have been checked during cipher suite negotiation.
       
   291                 shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   292                     "Not EC server cert for ECDH client key exchange");
       
   293             }
       
   294 
       
   295             ECParameterSpec params = ((ECPrivateKey)privateKey).getParams();
       
   296             NamedGroup namedGroup = NamedGroup.valueOf(params);
       
   297             if (namedGroup == null) {
       
   298                 // unlikely, have been checked during cipher suite negotiation.
       
   299                 shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   300                     "Unsupported EC server cert for ECDH client key exchange");
       
   301             }
       
   302 
       
   303             SSLKeyExchange ke = SSLKeyExchange.valueOf(
       
   304                     shc.negotiatedCipherSuite.keyExchange,
       
   305                     shc.negotiatedProtocol);
       
   306             if (ke == null) {
       
   307                 // unlikely
       
   308                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   309                         "Not supported key exchange type");
       
   310                 return;     // make the compiler happy
       
   311             }
       
   312 
       
   313             // parse the handshake message
       
   314             ECDHClientKeyExchangeMessage cke =
       
   315                     new ECDHClientKeyExchangeMessage(shc, message);
       
   316             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   317                 SSLLogger.fine(
       
   318                     "Consuming ECDH ClientKeyExchange handshake message", cke);
       
   319             }
       
   320 
       
   321             // create the credentials
       
   322             try {
       
   323                 ECPoint point =
       
   324                     JsseJce.decodePoint(cke.encodedPoint, params.getCurve());
       
   325                 ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
       
   326 
       
   327                 KeyFactory kf = JsseJce.getKeyFactory("EC");
       
   328                 ECPublicKey peerPublicKey =
       
   329                         (ECPublicKey)kf.generatePublic(spec);
       
   330 
       
   331                 // check constraints of peer ECPublicKey
       
   332                 if (!shc.algorithmConstraints.permits(
       
   333                         EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   334                         peerPublicKey)) {
       
   335                     throw new SSLHandshakeException(
       
   336                         "ECPublicKey does not comply to algorithm constraints");
       
   337                 }
       
   338 
       
   339                 shc.handshakeCredentials.add(new ECDHECredentials(
       
   340                         peerPublicKey, namedGroup));
       
   341             } catch (GeneralSecurityException | java.io.IOException e) {
       
   342                 throw (SSLHandshakeException)(new SSLHandshakeException(
       
   343                         "Could not generate ECPublicKey").initCause(e));
       
   344             }
       
   345 
       
   346             // update the states
       
   347             SSLKeyDerivation masterKD = ke.createKeyDerivation(shc);
       
   348             SecretKey masterSecret =
       
   349                     masterKD.deriveKey("MasterSecret", null);
       
   350             shc.handshakeSession.setMasterSecret(masterSecret);
       
   351 
       
   352             SSLTrafficKeyDerivation kd =
       
   353                     SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
       
   354             if (kd == null) {
       
   355                 // unlikely
       
   356                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   357                     "Not supported key derivation: " + shc.negotiatedProtocol);
       
   358             } else {
       
   359                 shc.handshakeKeyDerivation =
       
   360                     kd.createKeyDerivation(shc, masterSecret);
       
   361             }
       
   362         }
    61     }
   363     }
    62 
   364 
    63     ECDHClientKeyExchange(HandshakeInStream input) throws IOException {
   365     /**
    64         encodedPoint = input.getBytes8();
   366      * The ECDHE "ClientKeyExchange" handshake message producer.
       
   367      */
       
   368     private static final
       
   369             class ECDHEClientKeyExchangeProducer implements HandshakeProducer {
       
   370         // Prevent instantiation of this class.
       
   371         private ECDHEClientKeyExchangeProducer() {
       
   372             // blank
       
   373         }
       
   374 
       
   375         @Override
       
   376         public byte[] produce(ConnectionContext context,
       
   377                 HandshakeMessage message) throws IOException {
       
   378             // The producing happens in client side only.
       
   379             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   380 
       
   381             ECDHECredentials ecdheCredentials = null;
       
   382             for (SSLCredentials cd : chc.handshakeCredentials) {
       
   383                 if (cd instanceof ECDHECredentials) {
       
   384                     ecdheCredentials = (ECDHECredentials)cd;
       
   385                     break;
       
   386                 }
       
   387             }
       
   388 
       
   389             if (ecdheCredentials == null) {
       
   390                 chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   391                     "No ECDHE credentials negotiated for client key exchange");
       
   392             }
       
   393 
       
   394             ECDHEPossession ecdhePossession = new ECDHEPossession(
       
   395                     ecdheCredentials, chc.sslContext.getSecureRandom());
       
   396             chc.handshakePossessions.add(ecdhePossession);
       
   397             ECDHClientKeyExchangeMessage cke =
       
   398                     new ECDHClientKeyExchangeMessage(
       
   399                             chc, ecdhePossession.publicKey);
       
   400             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   401                 SSLLogger.fine(
       
   402                     "Produced ECDHE ClientKeyExchange handshake message", cke);
       
   403             }
       
   404 
       
   405             // Output the handshake message.
       
   406             cke.write(chc.handshakeOutput);
       
   407             chc.handshakeOutput.flush();
       
   408 
       
   409             // update the states
       
   410             SSLKeyExchange ke = SSLKeyExchange.valueOf(
       
   411                     chc.negotiatedCipherSuite.keyExchange,
       
   412                     chc.negotiatedProtocol);
       
   413             if (ke == null) {
       
   414                 // unlikely
       
   415                 chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   416                         "Not supported key exchange type");
       
   417             } else {
       
   418                 SSLKeyDerivation masterKD = ke.createKeyDerivation(chc);
       
   419                 SecretKey masterSecret =
       
   420                         masterKD.deriveKey("MasterSecret", null);
       
   421                 chc.handshakeSession.setMasterSecret(masterSecret);
       
   422 
       
   423                 SSLTrafficKeyDerivation kd =
       
   424                         SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
       
   425                 if (kd == null) {
       
   426                     // unlikely
       
   427                     chc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   428                             "Not supported key derivation: " +
       
   429                             chc.negotiatedProtocol);
       
   430                 } else {
       
   431                     chc.handshakeKeyDerivation =
       
   432                         kd.createKeyDerivation(chc, masterSecret);
       
   433                 }
       
   434             }
       
   435 
       
   436             // The handshake message has been delivered.
       
   437             return null;
       
   438         }
    65     }
   439     }
    66 
   440 
    67     @Override
   441     /**
    68     int messageLength() {
   442      * The ECDHE "ClientKeyExchange" handshake message consumer.
    69         return encodedPoint.length + 1;
   443      */
    70     }
   444     private static final
    71 
   445             class ECDHEClientKeyExchangeConsumer implements SSLConsumer {
    72     @Override
   446         // Prevent instantiation of this class.
    73     void send(HandshakeOutStream s) throws IOException {
   447         private ECDHEClientKeyExchangeConsumer() {
    74         s.putBytes8(encodedPoint);
   448             // blank
    75     }
   449         }
    76 
   450 
    77     @Override
   451         @Override
    78     void print(PrintStream s) throws IOException {
   452         public void consume(ConnectionContext context,
    79         s.println("*** ECDHClientKeyExchange");
   453                 ByteBuffer message) throws IOException {
    80 
   454             // The consuming happens in server side only.
    81         if (debug != null && Debug.isOn("verbose")) {
   455             ServerHandshakeContext shc = (ServerHandshakeContext)context;
    82             Debug.println(s, "ECDH Public value", encodedPoint);
   456 
       
   457             ECDHEPossession ecdhePossession = null;
       
   458             for (SSLPossession possession : shc.handshakePossessions) {
       
   459                 if (possession instanceof ECDHEPossession) {
       
   460                     ecdhePossession = (ECDHEPossession)possession;
       
   461                     break;
       
   462                 }
       
   463             }
       
   464             if (ecdhePossession == null) {
       
   465                 // unlikely
       
   466                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   467                     "No expected ECDHE possessions for client key exchange");
       
   468                 return;     // make the compiler happy
       
   469             }
       
   470 
       
   471             ECParameterSpec params = ecdhePossession.publicKey.getParams();
       
   472             NamedGroup namedGroup = NamedGroup.valueOf(params);
       
   473             if (namedGroup == null) {
       
   474                 // unlikely, have been checked during cipher suite negotiation.
       
   475                 shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   476                     "Unsupported EC server cert for ECDHE client key exchange");
       
   477             }
       
   478 
       
   479             SSLKeyExchange ke = SSLKeyExchange.valueOf(
       
   480                     shc.negotiatedCipherSuite.keyExchange,
       
   481                     shc.negotiatedProtocol);
       
   482             if (ke == null) {
       
   483                 // unlikely
       
   484                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   485                         "Not supported key exchange type");
       
   486                 return;     // make the compiler happy
       
   487             }
       
   488 
       
   489             // parse the handshake message
       
   490             ECDHClientKeyExchangeMessage cke =
       
   491                     new ECDHClientKeyExchangeMessage(shc, message);
       
   492             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   493                 SSLLogger.fine(
       
   494                     "Consuming ECDHE ClientKeyExchange handshake message", cke);
       
   495             }
       
   496 
       
   497             // create the credentials
       
   498             try {
       
   499                 ECPoint point =
       
   500                     JsseJce.decodePoint(cke.encodedPoint, params.getCurve());
       
   501                 ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
       
   502 
       
   503                 KeyFactory kf = JsseJce.getKeyFactory("EC");
       
   504                 ECPublicKey peerPublicKey =
       
   505                         (ECPublicKey)kf.generatePublic(spec);
       
   506 
       
   507                 // check constraints of peer ECPublicKey
       
   508                 if (!shc.algorithmConstraints.permits(
       
   509                         EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   510                         peerPublicKey)) {
       
   511                     throw new SSLHandshakeException(
       
   512                         "ECPublicKey does not comply to algorithm constraints");
       
   513                 }
       
   514 
       
   515                 shc.handshakeCredentials.add(new ECDHECredentials(
       
   516                         peerPublicKey, namedGroup));
       
   517             } catch (GeneralSecurityException | java.io.IOException e) {
       
   518                 throw (SSLHandshakeException)(new SSLHandshakeException(
       
   519                         "Could not generate ECPublicKey").initCause(e));
       
   520             }
       
   521 
       
   522             // update the states
       
   523             SSLKeyDerivation masterKD = ke.createKeyDerivation(shc);
       
   524             SecretKey masterSecret =
       
   525                     masterKD.deriveKey("MasterSecret", null);
       
   526             shc.handshakeSession.setMasterSecret(masterSecret);
       
   527 
       
   528             SSLTrafficKeyDerivation kd =
       
   529                     SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
       
   530             if (kd == null) {
       
   531                 // unlikely
       
   532                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   533                     "Not supported key derivation: " + shc.negotiatedProtocol);
       
   534             } else {
       
   535                 shc.handshakeKeyDerivation =
       
   536                     kd.createKeyDerivation(shc, masterSecret);
       
   537             }
    83         }
   538         }
    84     }
   539     }
    85 }
   540 }