src/java.base/share/classes/sun/security/ssl/SignatureScheme.java
changeset 57718 a93b7b28f644
parent 55452 1170b6d92d1c
child 58679 9c3209ff7550
child 58951 d6e682e8fcc3
equal deleted inserted replaced
57716:bfcdcd00e4fb 57718:a93b7b28f644
    36 import java.util.Collections;
    36 import java.util.Collections;
    37 import java.util.EnumSet;
    37 import java.util.EnumSet;
    38 import java.util.LinkedList;
    38 import java.util.LinkedList;
    39 import java.util.List;
    39 import java.util.List;
    40 import java.util.Set;
    40 import java.util.Set;
    41 import sun.security.ssl.NamedGroup.NamedGroupType;
    41 import sun.security.ssl.NamedGroup.NamedGroupSpec;
    42 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
    42 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
    43 import sun.security.ssl.X509Authentication.X509Possession;
    43 import sun.security.ssl.X509Authentication.X509Possession;
    44 import sun.security.util.KeyUtil;
    44 import sun.security.util.KeyUtil;
    45 import sun.security.util.SignatureUtil;
    45 import sun.security.util.SignatureUtil;
    46 
    46 
   147 
   147 
   148     final int id;                       // hash + signature
   148     final int id;                       // hash + signature
   149     final String name;                  // literal name
   149     final String name;                  // literal name
   150     private final String algorithm;     // signature algorithm
   150     private final String algorithm;     // signature algorithm
   151     final String keyAlgorithm;          // signature key algorithm
   151     final String keyAlgorithm;          // signature key algorithm
   152     private final AlgorithmParameterSpec signAlgParameter;
   152     private final SigAlgParamSpec signAlgParams;    // signature parameters
   153     private final NamedGroup namedGroup;    // associated named group
   153     private final NamedGroup namedGroup;    // associated named group
   154 
   154 
   155     // The minimal required key size in bits.
   155     // The minimal required key size in bits.
   156     //
   156     //
   157     // Only need to check RSA algorithm at present. RSA keys of 512 bits
   157     // Only need to check RSA algorithm at present. RSA keys of 512 bits
   182     static enum SigAlgParamSpec {   // support RSASSA-PSS only now
   182     static enum SigAlgParamSpec {   // support RSASSA-PSS only now
   183         RSA_PSS_SHA256 ("SHA-256", 32),
   183         RSA_PSS_SHA256 ("SHA-256", 32),
   184         RSA_PSS_SHA384 ("SHA-384", 48),
   184         RSA_PSS_SHA384 ("SHA-384", 48),
   185         RSA_PSS_SHA512 ("SHA-512", 64);
   185         RSA_PSS_SHA512 ("SHA-512", 64);
   186 
   186 
   187         final private AlgorithmParameterSpec parameterSpec;
   187         private final AlgorithmParameterSpec parameterSpec;
   188         final boolean isAvailable;
   188         private final AlgorithmParameters parameters;
       
   189         private final boolean isAvailable;
   189 
   190 
   190         SigAlgParamSpec(String hash, int saltLength) {
   191         SigAlgParamSpec(String hash, int saltLength) {
   191             // See RFC 8017
   192             // See RFC 8017
   192             PSSParameterSpec pssParamSpec =
   193             PSSParameterSpec pssParamSpec =
   193                     new PSSParameterSpec(hash, "MGF1",
   194                     new PSSParameterSpec(hash, "MGF1",
   194                             new MGF1ParameterSpec(hash), saltLength, 1);
   195                             new MGF1ParameterSpec(hash), saltLength, 1);
       
   196             AlgorithmParameters pssParams = null;
   195 
   197 
   196             boolean mediator = true;
   198             boolean mediator = true;
   197             try {
   199             try {
   198                 Signature signer = Signature.getInstance("RSASSA-PSS");
   200                 Signature signer = Signature.getInstance("RSASSA-PSS");
   199                 signer.setParameter(pssParamSpec);
   201                 signer.setParameter(pssParamSpec);
       
   202                 pssParams = signer.getParameters();
   200             } catch (InvalidAlgorithmParameterException |
   203             } catch (InvalidAlgorithmParameterException |
   201                     NoSuchAlgorithmException exp) {
   204                     NoSuchAlgorithmException | RuntimeException exp) {
       
   205                 // Signature.getParameters() may throw RuntimeException.
   202                 mediator = false;
   206                 mediator = false;
   203                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   207                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   204                     SSLLogger.warning(
   208                     SSLLogger.warning(
   205                         "RSASSA-PSS signature with " + hash +
   209                         "RSASSA-PSS signature with " + hash +
   206                         " is not supported by the underlying providers", exp);
   210                         " is not supported by the underlying providers", exp);
   207                 }
   211                 }
   208             }
   212             }
   209 
   213 
   210             this.isAvailable = mediator;
   214             this.isAvailable = mediator;
   211             this.parameterSpec = mediator ? pssParamSpec : null;
   215             this.parameterSpec = mediator ? pssParamSpec : null;
   212         }
   216             this.parameters = mediator ? pssParams : null;
   213 
       
   214         AlgorithmParameterSpec getParameterSpec() {
       
   215             return parameterSpec;
       
   216         }
   217         }
   217     }
   218     }
   218 
   219 
   219     // performance optimization
   220     // performance optimization
   220     private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
   221     private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
   253                 supportedProtocols, supportedProtocols);
   254                 supportedProtocols, supportedProtocols);
   254     }
   255     }
   255 
   256 
   256     private SignatureScheme(int id, String name,
   257     private SignatureScheme(int id, String name,
   257             String algorithm, String keyAlgorithm,
   258             String algorithm, String keyAlgorithm,
   258             SigAlgParamSpec signAlgParamSpec,
   259             SigAlgParamSpec signAlgParams,
   259             NamedGroup namedGroup, int minimalKeySize,
   260             NamedGroup namedGroup, int minimalKeySize,
   260             ProtocolVersion[] supportedProtocols,
   261             ProtocolVersion[] supportedProtocols,
   261             ProtocolVersion[] handshakeSupportedProtocols) {
   262             ProtocolVersion[] handshakeSupportedProtocols) {
   262         this.id = id;
   263         this.id = id;
   263         this.name = name;
   264         this.name = name;
   264         this.algorithm = algorithm;
   265         this.algorithm = algorithm;
   265         this.keyAlgorithm = keyAlgorithm;
   266         this.keyAlgorithm = keyAlgorithm;
   266         this.signAlgParameter =
   267         this.signAlgParams = signAlgParams;
   267             signAlgParamSpec != null ? signAlgParamSpec.parameterSpec : null;
       
   268         this.namedGroup = namedGroup;
   268         this.namedGroup = namedGroup;
   269         this.minimalKeySize = minimalKeySize;
   269         this.minimalKeySize = minimalKeySize;
   270         this.supportedProtocols = Arrays.asList(supportedProtocols);
   270         this.supportedProtocols = Arrays.asList(supportedProtocols);
   271         this.handshakeSupportedProtocols =
   271         this.handshakeSupportedProtocols =
   272                 Arrays.asList(handshakeSupportedProtocols);
   272                 Arrays.asList(handshakeSupportedProtocols);
   273 
   273 
   274         boolean mediator = true;
   274         boolean mediator = true;
   275         if (signAlgParamSpec != null) {
   275         if (signAlgParams != null) {
   276             mediator = signAlgParamSpec.isAvailable;
   276             mediator = signAlgParams.isAvailable;
   277         } else {
   277         } else {
   278             try {
   278             try {
   279                 Signature.getInstance(algorithm);
   279                 Signature.getInstance(algorithm);
   280             } catch (Exception e) {
   280             } catch (Exception e) {
   281                 mediator = false;
   281                 mediator = false;
   329     // Return the size of a SignatureScheme structure in TLS record
   329     // Return the size of a SignatureScheme structure in TLS record
   330     static int sizeInRecord() {
   330     static int sizeInRecord() {
   331         return 2;
   331         return 2;
   332     }
   332     }
   333 
   333 
       
   334     private boolean isPermitted(AlgorithmConstraints constraints) {
       
   335         return constraints.permits(SIGNATURE_PRIMITIVE_SET,
       
   336                         this.name, null) &&
       
   337                constraints.permits(SIGNATURE_PRIMITIVE_SET,
       
   338                         this.keyAlgorithm, null) &&
       
   339                constraints.permits(SIGNATURE_PRIMITIVE_SET,
       
   340                         this.algorithm, (signAlgParams != null ?
       
   341                                 signAlgParams.parameters : null)) &&
       
   342                (namedGroup != null ?
       
   343                         namedGroup.isPermitted(constraints) : true);
       
   344     }
       
   345 
   334     // Get local supported algorithm collection complying to algorithm
   346     // Get local supported algorithm collection complying to algorithm
   335     // constraints.
   347     // constraints.
   336     static List<SignatureScheme> getSupportedAlgorithms(
   348     static List<SignatureScheme> getSupportedAlgorithms(
   337             AlgorithmConstraints constraints,
   349             AlgorithmConstraints constraints,
   338             List<ProtocolVersion> activeProtocols) {
   350             List<ProtocolVersion> activeProtocols) {
   349                     break;
   361                     break;
   350                 }
   362                 }
   351             }
   363             }
   352 
   364 
   353             if (isMatch) {
   365             if (isMatch) {
   354                 if (constraints.permits(
   366                 if (ss.isPermitted(constraints)) {
   355                         SIGNATURE_PRIMITIVE_SET, ss.algorithm, null)) {
       
   356                     supported.add(ss);
   367                     supported.add(ss);
   357                 } else if (SSLLogger.isOn &&
   368                 } else if (SSLLogger.isOn &&
   358                         SSLLogger.isOn("ssl,handshake,verbose")) {
   369                         SSLLogger.isOn("ssl,handshake,verbose")) {
   359                     SSLLogger.finest(
   370                     SSLLogger.finest(
   360                         "Ignore disabled signature scheme: " + ss.name);
   371                         "Ignore disabled signature scheme: " + ss.name);
   381                             "Unsupported signature scheme: " +
   392                             "Unsupported signature scheme: " +
   382                             SignatureScheme.nameOf(ssid));
   393                             SignatureScheme.nameOf(ssid));
   383                 }
   394                 }
   384             } else if (ss.isAvailable &&
   395             } else if (ss.isAvailable &&
   385                     ss.supportedProtocols.contains(protocolVersion) &&
   396                     ss.supportedProtocols.contains(protocolVersion) &&
   386                     constraints.permits(SIGNATURE_PRIMITIVE_SET,
   397                     ss.isPermitted(constraints)) {
   387                            ss.algorithm, null)) {
       
   388                 supported.add(ss);
   398                 supported.add(ss);
   389             } else {
   399             } else {
   390                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   400                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   391                     SSLLogger.warning(
   401                     SSLLogger.warning(
   392                             "Unsupported signature scheme: " + ss.name);
   402                             "Unsupported signature scheme: " + ss.name);
   396 
   406 
   397         return supported;
   407         return supported;
   398     }
   408     }
   399 
   409 
   400     static SignatureScheme getPreferableAlgorithm(
   410     static SignatureScheme getPreferableAlgorithm(
       
   411             AlgorithmConstraints constraints,
   401             List<SignatureScheme> schemes,
   412             List<SignatureScheme> schemes,
   402             SignatureScheme certScheme,
   413             SignatureScheme certScheme,
   403             ProtocolVersion version) {
   414             ProtocolVersion version) {
   404 
   415 
   405         for (SignatureScheme ss : schemes) {
   416         for (SignatureScheme ss : schemes) {
   406             if (ss.isAvailable &&
   417             if (ss.isAvailable &&
   407                     ss.handshakeSupportedProtocols.contains(version) &&
   418                     ss.handshakeSupportedProtocols.contains(version) &&
   408                     certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) {
   419                     certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) &&
   409 
   420                     ss.isPermitted(constraints)) {
   410                 return ss;
   421                 return ss;
   411             }
   422             }
   412         }
   423         }
   413 
   424 
   414         return null;
   425         return null;
   415     }
   426     }
   416 
   427 
   417     static SignatureScheme getPreferableAlgorithm(
   428     static SignatureScheme getPreferableAlgorithm(
       
   429             AlgorithmConstraints constraints,
   418             List<SignatureScheme> schemes,
   430             List<SignatureScheme> schemes,
   419             X509Possession x509Possession,
   431             X509Possession x509Possession,
   420             ProtocolVersion version) {
   432             ProtocolVersion version) {
   421 
   433 
   422         PrivateKey signingKey = x509Possession.popPrivateKey;
   434         PrivateKey signingKey = x509Possession.popPrivateKey;
   430             keySize = Integer.MAX_VALUE;
   442             keySize = Integer.MAX_VALUE;
   431         }
   443         }
   432         for (SignatureScheme ss : schemes) {
   444         for (SignatureScheme ss : schemes) {
   433             if (ss.isAvailable && (keySize >= ss.minimalKeySize) &&
   445             if (ss.isAvailable && (keySize >= ss.minimalKeySize) &&
   434                     ss.handshakeSupportedProtocols.contains(version) &&
   446                     ss.handshakeSupportedProtocols.contains(version) &&
   435                     keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) {
   447                     keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) &&
   436                 if ((ss.namedGroup != null) && (ss.namedGroup.type ==
   448                     ss.isPermitted(constraints)) {
   437                         NamedGroupType.NAMED_GROUP_ECDHE)) {
   449                 if ((ss.namedGroup != null) && (ss.namedGroup.spec ==
       
   450                         NamedGroupSpec.NAMED_GROUP_ECDHE)) {
   438                     ECParameterSpec params =
   451                     ECParameterSpec params =
   439                             x509Possession.getECParameterSpec();
   452                             x509Possession.getECParameterSpec();
   440                     if (params != null &&
   453                     if (params != null &&
   441                             ss.namedGroup == NamedGroup.valueOf(params)) {
   454                             ss.namedGroup == NamedGroup.valueOf(params)) {
   442                         return ss;
   455                         return ss;
   503         }
   516         }
   504 
   517 
   505         Signature signer = Signature.getInstance(algorithm);
   518         Signature signer = Signature.getInstance(algorithm);
   506         if (key instanceof PublicKey) {
   519         if (key instanceof PublicKey) {
   507             SignatureUtil.initVerifyWithParam(signer, (PublicKey)key,
   520             SignatureUtil.initVerifyWithParam(signer, (PublicKey)key,
   508                     signAlgParameter);
   521                     (signAlgParams != null ?
       
   522                             signAlgParams.parameterSpec : null));
   509         } else {
   523         } else {
   510             SignatureUtil.initSignWithParam(signer, (PrivateKey)key,
   524             SignatureUtil.initSignWithParam(signer, (PrivateKey)key,
   511                     signAlgParameter, null);
   525                     (signAlgParams != null ?
       
   526                             signAlgParams.parameterSpec : null),
       
   527                     null);
   512         }
   528         }
   513 
   529 
   514         return signer;
   530         return signer;
   515     }
   531     }
   516 }
   532 }