< prev index next >

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

Print this page
rev 54061 : 8226374: Restrict TLS signature schemes and named groups
Reviewed-by: mullan


  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.security.AlgorithmConstraints;
  30 import java.security.CryptoPrimitive;
  31 import java.security.GeneralSecurityException;
  32 import java.security.KeyFactory;
  33 import java.security.KeyPair;
  34 import java.security.KeyPairGenerator;
  35 import java.security.PrivateKey;
  36 import java.security.PublicKey;
  37 import java.security.SecureRandom;
  38 import java.security.interfaces.ECPublicKey;
  39 import java.security.spec.ECGenParameterSpec;
  40 import java.security.spec.ECParameterSpec;
  41 import java.security.spec.ECPoint;
  42 import java.security.spec.ECPublicKeySpec;
  43 import java.util.EnumSet;
  44 import javax.crypto.KeyAgreement;
  45 import javax.crypto.SecretKey;
  46 import javax.net.ssl.SSLHandshakeException;
  47 import sun.security.ssl.NamedGroup.NamedGroupType;
  48 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
  49 import sun.security.ssl.X509Authentication.X509Credentials;
  50 import sun.security.ssl.X509Authentication.X509Possession;
  51 import sun.security.ssl.XDHKeyExchange.XDHECredentials;
  52 import sun.security.ssl.XDHKeyExchange.XDHEPossession;
  53 import sun.security.util.ECUtil;
  54 
  55 final class ECDHKeyExchange {
  56     static final SSLPossessionGenerator poGenerator =
  57             new ECDHEPossessionGenerator();
  58     static final SSLKeyAgreementGenerator ecdhKAGenerator =
  59             new ECDHKAGenerator();
  60 
  61     // TLSv1.3
  62     static final SSLKeyAgreementGenerator ecdheKAGenerator =
  63             new ECDHEKAGenerator();
  64 
  65     // TLSv1-1.2, the KA gets more difficult with EC/XEC keys
  66     static final SSLKeyAgreementGenerator ecdheXdhKAGenerator =
  67             new ECDHEXDHKAGenerator();


  71         final NamedGroup namedGroup;
  72 
  73         ECDHECredentials(ECPublicKey popPublicKey, NamedGroup namedGroup) {
  74             this.popPublicKey = popPublicKey;
  75             this.namedGroup = namedGroup;
  76         }
  77 
  78         @Override
  79         public PublicKey getPublicKey() {
  80             return popPublicKey;
  81         }
  82 
  83         @Override
  84         public NamedGroup getNamedGroup() {
  85             return namedGroup;
  86         }
  87 
  88         static ECDHECredentials valueOf(NamedGroup namedGroup,
  89             byte[] encodedPoint) throws IOException, GeneralSecurityException {
  90 
  91             if (namedGroup.type != NamedGroupType.NAMED_GROUP_ECDHE) {
  92                 throw new RuntimeException(
  93                     "Credentials decoding:  Not ECDHE named group");
  94             }
  95 
  96             if (encodedPoint == null || encodedPoint.length == 0) {
  97                 return null;
  98             }
  99 
 100             ECParameterSpec parameters =
 101                     JsseJce.getECParameterSpec(namedGroup.oid);
 102             if (parameters == null) {
 103                 return null;
 104             }
 105 
 106             ECPoint point = JsseJce.decodePoint(
 107                     encodedPoint, parameters.getCurve());
 108             KeyFactory factory = JsseJce.getKeyFactory("EC");
 109             ECPublicKey publicKey = (ECPublicKey)factory.generatePublic(
 110                     new ECPublicKeySpec(point, parameters));
 111             return new ECDHECredentials(publicKey, namedGroup);
 112         }
 113     }
 114 
 115     static final class ECDHEPossession implements NamedGroupPossession {
 116         final PrivateKey privateKey;
 117         final ECPublicKey publicKey;
 118         final NamedGroup namedGroup;
 119 
 120         ECDHEPossession(NamedGroup namedGroup, SecureRandom random) {
 121             try {
 122                 KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
 123                 ECGenParameterSpec params =
 124                         (ECGenParameterSpec)namedGroup.getParameterSpec();
 125                 kpg.initialize(params, random);
 126                 KeyPair kp = kpg.generateKeyPair();
 127                 privateKey = kp.getPrivate();
 128                 publicKey = (ECPublicKey)kp.getPublic();
 129             } catch (GeneralSecurityException e) {
 130                 throw new RuntimeException(
 131                     "Could not generate ECDH keypair", e);
 132             }
 133 
 134             this.namedGroup = namedGroup;
 135         }
 136 
 137         ECDHEPossession(ECDHECredentials credentials, SecureRandom random) {
 138             ECParameterSpec params = credentials.popPublicKey.getParams();
 139             try {
 140                 KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
 141                 kpg.initialize(params, random);
 142                 KeyPair kp = kpg.generateKeyPair();
 143                 privateKey = kp.getPrivate();
 144                 publicKey = (ECPublicKey)kp.getPublic();
 145             } catch (GeneralSecurityException e) {


 231     }
 232 
 233     private static final
 234             class ECDHEPossessionGenerator implements SSLPossessionGenerator {
 235         // Prevent instantiation of this class.
 236         private ECDHEPossessionGenerator() {
 237             // blank
 238         }
 239 
 240         @Override
 241         public SSLPossession createPossession(HandshakeContext context) {
 242 
 243             NamedGroup preferableNamedGroup;
 244 
 245             // Find most preferred EC or XEC groups
 246             if ((context.clientRequestedNamedGroups != null) &&
 247                     (!context.clientRequestedNamedGroups.isEmpty())) {
 248                 preferableNamedGroup = SupportedGroups.getPreferredGroup(
 249                         context.negotiatedProtocol,
 250                         context.algorithmConstraints,
 251                         new NamedGroupType[] {
 252                             NamedGroupType.NAMED_GROUP_ECDHE,
 253                             NamedGroupType.NAMED_GROUP_XDH },
 254                         context.clientRequestedNamedGroups);
 255             } else {
 256                 preferableNamedGroup = SupportedGroups.getPreferredGroup(
 257                         context.negotiatedProtocol,
 258                         context.algorithmConstraints,
 259                         new NamedGroupType[] {
 260                             NamedGroupType.NAMED_GROUP_ECDHE,
 261                             NamedGroupType.NAMED_GROUP_XDH });
 262             }
 263 
 264             if (preferableNamedGroup != null) {
 265                 return preferableNamedGroup.createPossession(
 266                     context.sslContext.getSecureRandom());
 267             }
 268 
 269             // no match found, cannot use this cipher suite.
 270             //
 271             return null;
 272         }
 273     }
 274 
 275     private static final
 276             class ECDHKAGenerator implements SSLKeyAgreementGenerator {
 277         // Prevent instantiation of this class.
 278         private ECDHKAGenerator() {
 279             // blank
 280         }
 281 


 291             }
 292         }
 293 
 294         private SSLKeyDerivation createServerKeyDerivation(
 295                 ServerHandshakeContext shc) throws IOException {
 296             X509Possession x509Possession = null;
 297             ECDHECredentials ecdheCredentials = null;
 298             for (SSLPossession poss : shc.handshakePossessions) {
 299                 if (!(poss instanceof X509Possession)) {
 300                     continue;
 301                 }
 302 
 303                 ECParameterSpec params =
 304                         ((X509Possession)poss).getECParameterSpec();
 305                 if (params == null) {
 306                     continue;
 307                 }
 308 
 309                 NamedGroup ng = NamedGroup.valueOf(params);
 310                 if (ng == null) {
 311                     // unlikely, have been checked during cipher suite negotiation.

 312                     throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 313                         "Unsupported EC server cert for ECDH key exchange");
 314                 }
 315 
 316                 for (SSLCredentials cred : shc.handshakeCredentials) {
 317                     if (!(cred instanceof ECDHECredentials)) {
 318                         continue;
 319                     }
 320                     if (ng.equals(((ECDHECredentials)cred).namedGroup)) {
 321                         ecdheCredentials = (ECDHECredentials)cred;
 322                         break;
 323                     }
 324                 }
 325 
 326                 if (ecdheCredentials != null) {
 327                     x509Possession = (X509Possession)poss;
 328                     break;
 329                 }
 330             }
 331 


 463                         NamedGroupCredentials c = (NamedGroupCredentials)cred;
 464                         if (p.getNamedGroup() != c.getNamedGroup()) {
 465                             continue;
 466                         } else {
 467                             namedGroup = p.getNamedGroup();
 468                         }
 469                         namedGroupPossession = p;
 470                         namedGroupCredentials = c;
 471                         break search;
 472                     }
 473                 }
 474             }
 475 
 476             if (namedGroupPossession == null || namedGroupCredentials == null) {
 477                 throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 478                     "No sufficient ECDHE/XDH key agreement " +
 479                             "parameters negotiated");
 480             }
 481 
 482             String alg;
 483             switch (namedGroup.type) {
 484                 case NAMED_GROUP_ECDHE:
 485                     alg = "ECDH";
 486                     break;
 487                 case NAMED_GROUP_XDH:
 488                     alg = "XDH";
 489                     break;
 490                 default:
 491                     throw new RuntimeException("Unexpected named group type");
 492             }
 493 
 494             return new KAKeyDerivation(alg, context,
 495                     namedGroupPossession.getPrivateKey(),
 496                     namedGroupCredentials.getPublicKey());
 497         }
 498     }
 499 }


  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.security.AlgorithmConstraints;
  30 import java.security.CryptoPrimitive;
  31 import java.security.GeneralSecurityException;
  32 import java.security.KeyFactory;
  33 import java.security.KeyPair;
  34 import java.security.KeyPairGenerator;
  35 import java.security.PrivateKey;
  36 import java.security.PublicKey;
  37 import java.security.SecureRandom;
  38 import java.security.interfaces.ECPublicKey;

  39 import java.security.spec.ECParameterSpec;
  40 import java.security.spec.ECPoint;
  41 import java.security.spec.ECPublicKeySpec;
  42 import java.util.EnumSet;
  43 import javax.crypto.KeyAgreement;
  44 import javax.crypto.SecretKey;
  45 import javax.net.ssl.SSLHandshakeException;
  46 import sun.security.ssl.NamedGroup.NamedGroupSpec;
  47 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
  48 import sun.security.ssl.X509Authentication.X509Credentials;
  49 import sun.security.ssl.X509Authentication.X509Possession;
  50 import sun.security.ssl.XDHKeyExchange.XDHECredentials;
  51 import sun.security.ssl.XDHKeyExchange.XDHEPossession;
  52 import sun.security.util.ECUtil;
  53 
  54 final class ECDHKeyExchange {
  55     static final SSLPossessionGenerator poGenerator =
  56             new ECDHEPossessionGenerator();
  57     static final SSLKeyAgreementGenerator ecdhKAGenerator =
  58             new ECDHKAGenerator();
  59 
  60     // TLSv1.3
  61     static final SSLKeyAgreementGenerator ecdheKAGenerator =
  62             new ECDHEKAGenerator();
  63 
  64     // TLSv1-1.2, the KA gets more difficult with EC/XEC keys
  65     static final SSLKeyAgreementGenerator ecdheXdhKAGenerator =
  66             new ECDHEXDHKAGenerator();


  70         final NamedGroup namedGroup;
  71 
  72         ECDHECredentials(ECPublicKey popPublicKey, NamedGroup namedGroup) {
  73             this.popPublicKey = popPublicKey;
  74             this.namedGroup = namedGroup;
  75         }
  76 
  77         @Override
  78         public PublicKey getPublicKey() {
  79             return popPublicKey;
  80         }
  81 
  82         @Override
  83         public NamedGroup getNamedGroup() {
  84             return namedGroup;
  85         }
  86 
  87         static ECDHECredentials valueOf(NamedGroup namedGroup,
  88             byte[] encodedPoint) throws IOException, GeneralSecurityException {
  89 
  90             if (namedGroup.spec != NamedGroupSpec.NAMED_GROUP_ECDHE) {
  91                 throw new RuntimeException(
  92                     "Credentials decoding:  Not ECDHE named group");
  93             }
  94 
  95             if (encodedPoint == null || encodedPoint.length == 0) {
  96                 return null;
  97             }
  98 
  99             ECParameterSpec parameters =
 100                     (ECParameterSpec)namedGroup.keAlgParamSpec;



 101 
 102             ECPoint point = JsseJce.decodePoint(
 103                     encodedPoint, parameters.getCurve());
 104             KeyFactory factory = JsseJce.getKeyFactory("EC");
 105             ECPublicKey publicKey = (ECPublicKey)factory.generatePublic(
 106                     new ECPublicKeySpec(point, parameters));
 107             return new ECDHECredentials(publicKey, namedGroup);
 108         }
 109     }
 110 
 111     static final class ECDHEPossession implements NamedGroupPossession {
 112         final PrivateKey privateKey;
 113         final ECPublicKey publicKey;
 114         final NamedGroup namedGroup;
 115 
 116         ECDHEPossession(NamedGroup namedGroup, SecureRandom random) {
 117             try {
 118                 KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
 119                 kpg.initialize(namedGroup.keAlgParamSpec, random);


 120                 KeyPair kp = kpg.generateKeyPair();
 121                 privateKey = kp.getPrivate();
 122                 publicKey = (ECPublicKey)kp.getPublic();
 123             } catch (GeneralSecurityException e) {
 124                 throw new RuntimeException(
 125                     "Could not generate ECDH keypair", e);
 126             }
 127 
 128             this.namedGroup = namedGroup;
 129         }
 130 
 131         ECDHEPossession(ECDHECredentials credentials, SecureRandom random) {
 132             ECParameterSpec params = credentials.popPublicKey.getParams();
 133             try {
 134                 KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
 135                 kpg.initialize(params, random);
 136                 KeyPair kp = kpg.generateKeyPair();
 137                 privateKey = kp.getPrivate();
 138                 publicKey = (ECPublicKey)kp.getPublic();
 139             } catch (GeneralSecurityException e) {


 225     }
 226 
 227     private static final
 228             class ECDHEPossessionGenerator implements SSLPossessionGenerator {
 229         // Prevent instantiation of this class.
 230         private ECDHEPossessionGenerator() {
 231             // blank
 232         }
 233 
 234         @Override
 235         public SSLPossession createPossession(HandshakeContext context) {
 236 
 237             NamedGroup preferableNamedGroup;
 238 
 239             // Find most preferred EC or XEC groups
 240             if ((context.clientRequestedNamedGroups != null) &&
 241                     (!context.clientRequestedNamedGroups.isEmpty())) {
 242                 preferableNamedGroup = SupportedGroups.getPreferredGroup(
 243                         context.negotiatedProtocol,
 244                         context.algorithmConstraints,
 245                         new NamedGroupSpec[] {
 246                             NamedGroupSpec.NAMED_GROUP_ECDHE,
 247                             NamedGroupSpec.NAMED_GROUP_XDH },
 248                         context.clientRequestedNamedGroups);
 249             } else {
 250                 preferableNamedGroup = SupportedGroups.getPreferredGroup(
 251                         context.negotiatedProtocol,
 252                         context.algorithmConstraints,
 253                         new NamedGroupSpec[] {
 254                             NamedGroupSpec.NAMED_GROUP_ECDHE,
 255                             NamedGroupSpec.NAMED_GROUP_XDH });
 256             }
 257 
 258             if (preferableNamedGroup != null) {
 259                 return preferableNamedGroup.createPossession(
 260                     context.sslContext.getSecureRandom());
 261             }
 262 
 263             // no match found, cannot use this cipher suite.
 264             //
 265             return null;
 266         }
 267     }
 268 
 269     private static final
 270             class ECDHKAGenerator implements SSLKeyAgreementGenerator {
 271         // Prevent instantiation of this class.
 272         private ECDHKAGenerator() {
 273             // blank
 274         }
 275 


 285             }
 286         }
 287 
 288         private SSLKeyDerivation createServerKeyDerivation(
 289                 ServerHandshakeContext shc) throws IOException {
 290             X509Possession x509Possession = null;
 291             ECDHECredentials ecdheCredentials = null;
 292             for (SSLPossession poss : shc.handshakePossessions) {
 293                 if (!(poss instanceof X509Possession)) {
 294                     continue;
 295                 }
 296 
 297                 ECParameterSpec params =
 298                         ((X509Possession)poss).getECParameterSpec();
 299                 if (params == null) {
 300                     continue;
 301                 }
 302 
 303                 NamedGroup ng = NamedGroup.valueOf(params);
 304                 if (ng == null) {
 305                     // unlikely, have been checked during cipher suite
 306                     // negotiation.
 307                     throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 308                         "Unsupported EC server cert for ECDH key exchange");
 309                 }
 310 
 311                 for (SSLCredentials cred : shc.handshakeCredentials) {
 312                     if (!(cred instanceof ECDHECredentials)) {
 313                         continue;
 314                     }
 315                     if (ng.equals(((ECDHECredentials)cred).namedGroup)) {
 316                         ecdheCredentials = (ECDHECredentials)cred;
 317                         break;
 318                     }
 319                 }
 320 
 321                 if (ecdheCredentials != null) {
 322                     x509Possession = (X509Possession)poss;
 323                     break;
 324                 }
 325             }
 326 


 458                         NamedGroupCredentials c = (NamedGroupCredentials)cred;
 459                         if (p.getNamedGroup() != c.getNamedGroup()) {
 460                             continue;
 461                         } else {
 462                             namedGroup = p.getNamedGroup();
 463                         }
 464                         namedGroupPossession = p;
 465                         namedGroupCredentials = c;
 466                         break search;
 467                     }
 468                 }
 469             }
 470 
 471             if (namedGroupPossession == null || namedGroupCredentials == null) {
 472                 throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 473                     "No sufficient ECDHE/XDH key agreement " +
 474                             "parameters negotiated");
 475             }
 476 
 477             String alg;
 478             switch (namedGroup.spec) {
 479                 case NAMED_GROUP_ECDHE:
 480                     alg = "ECDH";
 481                     break;
 482                 case NAMED_GROUP_XDH:
 483                     alg = "XDH";
 484                     break;
 485                 default:
 486                     throw new RuntimeException("Unexpected named group type");
 487             }
 488 
 489             return new KAKeyDerivation(alg, context,
 490                     namedGroupPossession.getPrivateKey(),
 491                     namedGroupCredentials.getPublicKey());
 492         }
 493     }
 494 }
< prev index next >