< prev index next >

src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java

Print this page




  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.GeneralSecurityException;
  31 import java.security.InvalidAlgorithmParameterException;
  32 import java.security.InvalidKeyException;
  33 import java.security.Key;

  34 import java.security.NoSuchAlgorithmException;
  35 import java.security.PrivateKey;
  36 import java.security.PublicKey;
  37 import java.security.Signature;
  38 import java.security.SignatureException;





  39 import java.text.MessageFormat;

  40 import java.util.Locale;


  41 import sun.security.ssl.SSLHandshake.HandshakeMessage;

  42 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
  43 import sun.security.ssl.X509Authentication.X509Credentials;
  44 import sun.security.ssl.X509Authentication.X509Possession;

  45 import sun.security.util.HexDumpEncoder;
  46 
  47 /**
  48  * Pack of the ServerKeyExchange handshake message.
  49  */
  50 final class ECDHServerKeyExchange {
  51     static final SSLConsumer ecdheHandshakeConsumer =
  52             new ECDHServerKeyExchangeConsumer();
  53     static final HandshakeProducer ecdheHandshakeProducer =
  54             new ECDHServerKeyExchangeProducer();
  55 
  56     /**
  57      * The ECDH ServerKeyExchange handshake message.
  58      */
  59     private static final
  60             class ECDHServerKeyExchangeMessage extends HandshakeMessage {
  61         private static final byte CURVE_NAMED_CURVE = (byte)0x03;
  62 
  63         // id of the named curve
  64         private final NamedGroup namedGroup;
  65 
  66         // encoded public point
  67         private final byte[] publicPoint;
  68 
  69         // signature bytes, or null if anonymous
  70         private final byte[] paramsSignature;
  71 



  72         private final boolean useExplicitSigAlgorithm;
  73 
  74         // the signature algorithm used by this ServerKeyExchange message
  75         private final SignatureScheme signatureScheme;
  76 
  77         // the parsed credential object
  78         private SSLCredentials sslCredentials;
  79 
  80         ECDHServerKeyExchangeMessage(
  81                 HandshakeContext handshakeContext) throws IOException {
  82             super(handshakeContext);
  83 
  84             // This happens in server side only.
  85             ServerHandshakeContext shc =
  86                     (ServerHandshakeContext)handshakeContext;
  87 
  88             // Find the Possessions needed
  89             NamedGroupPossession namedGroupPossession = null;
  90             X509Possession x509Possession = null;
  91             for (SSLPossession possession : shc.handshakePossessions) {
  92                 if (possession instanceof NamedGroupPossession) {
  93                     namedGroupPossession = (NamedGroupPossession)possession;
  94                     if (x509Possession != null) {
  95                         break;
  96                     }
  97                 } else if (possession instanceof X509Possession) {
  98                     x509Possession = (X509Possession)possession;
  99                     if (namedGroupPossession != null) {
 100                         break;
 101                     }
 102                 }
 103             }
 104 
 105             if (namedGroupPossession == null) {
 106                 // unlikely
 107                 throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 108                     "No ECDHE credentials negotiated for server key exchange");
 109             }
 110 
 111             // Find the NamedGroup used for the ephemeral keys.
 112             namedGroup = namedGroupPossession.getNamedGroup();
 113             publicPoint = namedGroup.encodePossessionPublicKey(
 114                     namedGroupPossession);
 115 

 116             if ((namedGroup == null) || (namedGroup.oid == null) ) {
 117                 // unlikely
 118                 throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 119                     "Missing Named Group");
 120             }
 121 
 122             if (x509Possession == null) {
 123                 // anonymous, no authentication, no signature
 124                 paramsSignature = null;
 125                 signatureScheme = null;
 126                 useExplicitSigAlgorithm = false;
 127             } else {
 128                 useExplicitSigAlgorithm =
 129                         shc.negotiatedProtocol.useTLS12PlusSpec();
 130                 Signature signer = null;
 131                 if (useExplicitSigAlgorithm) {
 132                     signatureScheme = SignatureScheme.getPreferableAlgorithm(
 133                             shc.peerRequestedSignatureSchemes,
 134                             x509Possession,
 135                             shc.negotiatedProtocol);
 136                     if (signatureScheme == null) {
 137                         // Unlikely, the credentials generator should have
 138                         // selected the preferable signature algorithm properly.
 139                         throw shc.conContext.fatal(Alert.INTERNAL_ERROR,


 188 
 189             byte curveType = (byte)Record.getInt8(m);
 190             if (curveType != CURVE_NAMED_CURVE) {
 191                 // Unlikely as only the named curves should be negotiated.
 192                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 193                     "Unsupported ECCurveType: " + curveType);
 194             }
 195 
 196             int namedGroupId = Record.getInt16(m);
 197             this.namedGroup = NamedGroup.valueOf(namedGroupId);
 198             if (namedGroup == null) {
 199                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 200                     "Unknown named group ID: " + namedGroupId);
 201             }
 202 
 203             if (!SupportedGroups.isSupported(namedGroup)) {
 204                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 205                     "Unsupported named group: " + namedGroup);
 206             }
 207 












 208             publicPoint = Record.getBytes8(m);
 209             if (publicPoint.length == 0) {
 210                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 211                     "Insufficient Point data: " + namedGroup);
 212             }
 213 

 214             try {
 215                 sslCredentials = namedGroup.decodeCredentials(
 216                     publicPoint, handshakeContext.algorithmConstraints,
 217                      s -> chc.conContext.fatal(Alert.INSUFFICIENT_SECURITY,
 218                      "ServerKeyExchange " + namedGroup + ": " + (s)));
 219             } catch (GeneralSecurityException ex) {
 220                 throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
 221                         "Cannot decode named group: " +
 222                         NamedGroup.nameOf(namedGroupId));

 223             }
 224 


 225             X509Credentials x509Credentials = null;
 226             for (SSLCredentials cd : chc.handshakeCredentials) {
 227                 if (cd instanceof X509Credentials) {
 228                     x509Credentials = (X509Credentials)cd;
 229                     break;
 230                 }
 231             }
 232 
 233             if (x509Credentials == null) {
 234                 // anonymous, no authentication, no signature
 235                 if (m.hasRemaining()) {
 236                     throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 237                         "Invalid DH ServerKeyExchange: unknown extra data");
 238                 }
 239                 this.signatureScheme = null;
 240                 this.paramsSignature = null;
 241                 this.useExplicitSigAlgorithm = false;
 242 
 243                 return;
 244             }


 485             return null;
 486         }
 487     }
 488 
 489     /**
 490      * The ECDH "ServerKeyExchange" handshake message consumer.
 491      */
 492     private static final
 493             class ECDHServerKeyExchangeConsumer implements SSLConsumer {
 494         // Prevent instantiation of this class.
 495         private ECDHServerKeyExchangeConsumer() {
 496             // blank
 497         }
 498 
 499         @Override
 500         public void consume(ConnectionContext context,
 501                 ByteBuffer message) throws IOException {
 502             // The consuming happens in client side only.
 503             ClientHandshakeContext chc = (ClientHandshakeContext)context;
 504 
 505             // AlgorithmConstraints are checked during decoding
 506             ECDHServerKeyExchangeMessage skem =
 507                     new ECDHServerKeyExchangeMessage(chc, message);
 508             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 509                 SSLLogger.fine(
 510                     "Consuming ECDH ServerKeyExchange handshake message", skem);
 511             }
 512 
 513             //












 514             // update
 515             //
 516             chc.handshakeCredentials.add(skem.sslCredentials);

 517 
 518             //
 519             // produce
 520             //
 521             // Need no new handshake message producers here.
 522         }
 523     }
 524 }
 525 


  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.Key;
  34 import java.security.KeyFactory;
  35 import java.security.NoSuchAlgorithmException;
  36 import java.security.PrivateKey;
  37 import java.security.PublicKey;
  38 import java.security.Signature;
  39 import java.security.SignatureException;
  40 import java.security.interfaces.ECPublicKey;
  41 import java.security.spec.ECParameterSpec;
  42 import java.security.spec.ECPoint;
  43 import java.security.spec.ECPublicKeySpec;
  44 import java.security.spec.InvalidKeySpecException;
  45 import java.text.MessageFormat;
  46 import java.util.EnumSet;
  47 import java.util.Locale;
  48 import sun.security.ssl.ECDHKeyExchange.ECDHECredentials;
  49 import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
  50 import sun.security.ssl.SSLHandshake.HandshakeMessage;
  51 import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
  52 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
  53 import sun.security.ssl.X509Authentication.X509Credentials;
  54 import sun.security.ssl.X509Authentication.X509Possession;
  55 import sun.security.util.ECUtil;
  56 import sun.security.util.HexDumpEncoder;
  57 
  58 /**
  59  * Pack of the ServerKeyExchange handshake message.
  60  */
  61 final class ECDHServerKeyExchange {
  62     static final SSLConsumer ecdheHandshakeConsumer =
  63             new ECDHServerKeyExchangeConsumer();
  64     static final HandshakeProducer ecdheHandshakeProducer =
  65             new ECDHServerKeyExchangeProducer();
  66 
  67     /**
  68      * The ECDH ServerKeyExchange handshake message.
  69      */
  70     private static final
  71             class ECDHServerKeyExchangeMessage extends HandshakeMessage {
  72         private static final byte CURVE_NAMED_CURVE = (byte)0x03;
  73 
  74         // id of the named curve
  75         private final NamedGroup namedGroup;
  76 
  77         // encoded public point
  78         private final byte[] publicPoint;
  79 
  80         // signature bytes, or null if anonymous
  81         private final byte[] paramsSignature;
  82 
  83         // public key object encapsulated in this message
  84         private final ECPublicKey publicKey;
  85 
  86         private final boolean useExplicitSigAlgorithm;
  87 
  88         // the signature algorithm used by this ServerKeyExchange message
  89         private final SignatureScheme signatureScheme;
  90 



  91         ECDHServerKeyExchangeMessage(
  92                 HandshakeContext handshakeContext) throws IOException {
  93             super(handshakeContext);
  94 
  95             // This happens in server side only.
  96             ServerHandshakeContext shc =
  97                     (ServerHandshakeContext)handshakeContext;
  98 
  99             ECDHEPossession ecdhePossession = null;

 100             X509Possession x509Possession = null;
 101             for (SSLPossession possession : shc.handshakePossessions) {
 102                 if (possession instanceof ECDHEPossession) {
 103                     ecdhePossession = (ECDHEPossession)possession;
 104                     if (x509Possession != null) {
 105                         break;
 106                     }
 107                 } else if (possession instanceof X509Possession) {
 108                     x509Possession = (X509Possession)possession;
 109                     if (ecdhePossession != null) {
 110                         break;
 111                     }
 112                 }
 113             }
 114 
 115             if (ecdhePossession == null) {
 116                 // unlikely
 117                 throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 118                     "No ECDHE credentials negotiated for server key exchange");
 119             }
 120 
 121             publicKey = ecdhePossession.publicKey;
 122             ECParameterSpec params = publicKey.getParams();
 123             ECPoint point = publicKey.getW();
 124             publicPoint = ECUtil.encodePoint(point, params.getCurve());
 125 
 126             this.namedGroup = NamedGroup.valueOf(params);
 127             if ((namedGroup == null) || (namedGroup.oid == null) ) {
 128                 // unlikely
 129                 throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 130                     "Unnamed EC parameter spec: " + params);
 131             }
 132 
 133             if (x509Possession == null) {
 134                 // anonymous, no authentication, no signature
 135                 paramsSignature = null;
 136                 signatureScheme = null;
 137                 useExplicitSigAlgorithm = false;
 138             } else {
 139                 useExplicitSigAlgorithm =
 140                         shc.negotiatedProtocol.useTLS12PlusSpec();
 141                 Signature signer = null;
 142                 if (useExplicitSigAlgorithm) {
 143                     signatureScheme = SignatureScheme.getPreferableAlgorithm(
 144                             shc.peerRequestedSignatureSchemes,
 145                             x509Possession,
 146                             shc.negotiatedProtocol);
 147                     if (signatureScheme == null) {
 148                         // Unlikely, the credentials generator should have
 149                         // selected the preferable signature algorithm properly.
 150                         throw shc.conContext.fatal(Alert.INTERNAL_ERROR,


 199 
 200             byte curveType = (byte)Record.getInt8(m);
 201             if (curveType != CURVE_NAMED_CURVE) {
 202                 // Unlikely as only the named curves should be negotiated.
 203                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 204                     "Unsupported ECCurveType: " + curveType);
 205             }
 206 
 207             int namedGroupId = Record.getInt16(m);
 208             this.namedGroup = NamedGroup.valueOf(namedGroupId);
 209             if (namedGroup == null) {
 210                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 211                     "Unknown named group ID: " + namedGroupId);
 212             }
 213 
 214             if (!SupportedGroups.isSupported(namedGroup)) {
 215                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 216                     "Unsupported named group: " + namedGroup);
 217             }
 218 
 219             if (namedGroup.oid == null) {
 220                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 221                     "Unknown named EC curve: " + namedGroup);
 222             }
 223 
 224             ECParameterSpec parameters =
 225                     ECUtil.getECParameterSpec(null, namedGroup.oid);
 226             if (parameters == null) {
 227                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 228                     "No supported EC parameter: " + namedGroup);
 229             }
 230 
 231             publicPoint = Record.getBytes8(m);
 232             if (publicPoint.length == 0) {
 233                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 234                     "Insufficient ECPoint data: " + namedGroup);
 235             }
 236 
 237             ECPublicKey ecPublicKey = null;
 238             try {
 239                 ECPoint point =
 240                         ECUtil.decodePoint(publicPoint, parameters.getCurve());
 241                 KeyFactory factory = KeyFactory.getInstance("EC");
 242                 ecPublicKey = (ECPublicKey)factory.generatePublic(
 243                     new ECPublicKeySpec(point, parameters));
 244             } catch (NoSuchAlgorithmException |
 245                     InvalidKeySpecException | IOException ex) {
 246                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 247                     "Invalid ECPoint: " + namedGroup, ex);
 248             }
 249 
 250             publicKey = ecPublicKey;
 251 
 252             X509Credentials x509Credentials = null;
 253             for (SSLCredentials cd : chc.handshakeCredentials) {
 254                 if (cd instanceof X509Credentials) {
 255                     x509Credentials = (X509Credentials)cd;
 256                     break;
 257                 }
 258             }
 259 
 260             if (x509Credentials == null) {
 261                 // anonymous, no authentication, no signature
 262                 if (m.hasRemaining()) {
 263                     throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 264                         "Invalid DH ServerKeyExchange: unknown extra data");
 265                 }
 266                 this.signatureScheme = null;
 267                 this.paramsSignature = null;
 268                 this.useExplicitSigAlgorithm = false;
 269 
 270                 return;
 271             }


 512             return null;
 513         }
 514     }
 515 
 516     /**
 517      * The ECDH "ServerKeyExchange" handshake message consumer.
 518      */
 519     private static final
 520             class ECDHServerKeyExchangeConsumer implements SSLConsumer {
 521         // Prevent instantiation of this class.
 522         private ECDHServerKeyExchangeConsumer() {
 523             // blank
 524         }
 525 
 526         @Override
 527         public void consume(ConnectionContext context,
 528                 ByteBuffer message) throws IOException {
 529             // The consuming happens in client side only.
 530             ClientHandshakeContext chc = (ClientHandshakeContext)context;
 531 

 532             ECDHServerKeyExchangeMessage skem =
 533                     new ECDHServerKeyExchangeMessage(chc, message);
 534             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 535                 SSLLogger.fine(
 536                     "Consuming ECDH ServerKeyExchange handshake message", skem);
 537             }
 538 
 539             //
 540             // validate
 541             //
 542             // check constraints of EC PublicKey
 543             if (!chc.algorithmConstraints.permits(
 544                     EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
 545                     skem.publicKey)) {
 546                 throw chc.conContext.fatal(Alert.INSUFFICIENT_SECURITY,
 547                         "ECDH ServerKeyExchange does not comply " +
 548                         "to algorithm constraints");
 549             }
 550 
 551             //
 552             // update
 553             //
 554             chc.handshakeCredentials.add(
 555                     new ECDHECredentials(skem.publicKey, skem.namedGroup));
 556 
 557             //
 558             // produce
 559             //
 560             // Need no new handshake message producers here.
 561         }
 562     }
 563 }
 564 
< prev index next >