1 /*
   2  * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.security.ssl;
  27 
  28 import java.security.*;
  29 import java.security.interfaces.ECPrivateKey;
  30 import java.security.spec.AlgorithmParameterSpec;
  31 import java.security.spec.ECParameterSpec;
  32 import java.security.spec.MGF1ParameterSpec;
  33 import java.security.spec.PSSParameterSpec;
  34 import java.util.ArrayList;
  35 import java.util.Arrays;
  36 import java.util.Collection;
  37 import java.util.Collections;
  38 import java.util.EnumSet;
  39 import java.util.LinkedList;
  40 import java.util.List;
  41 import java.util.Set;
  42 import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
  43 import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
  44 import sun.security.ssl.X509Authentication.X509Possession;
  45 import sun.security.util.KeyUtil;

  46 
  47 enum SignatureScheme {
  48     // EdDSA algorithms
  49     ED25519                 (0x0807, "ed25519", "ed25519",
  50                                     "ed25519",
  51                                     ProtocolVersion.PROTOCOLS_OF_13),
  52     ED448                   (0x0808, "ed448", "ed448",
  53                                     "ed448",
  54                                     ProtocolVersion.PROTOCOLS_OF_13),
  55 
  56     // ECDSA algorithms
  57     ECDSA_SECP256R1_SHA256  (0x0403, "ecdsa_secp256r1_sha256",
  58                                     "SHA256withECDSA",
  59                                     "EC",
  60                                     NamedGroup.SECP256_R1,
  61                                     ProtocolVersion.PROTOCOLS_TO_13),
  62     ECDSA_SECP384R1_SHA384  (0x0503, "ecdsa_secp384r1_sha384",
  63                                     "SHA384withECDSA",
  64                                     "EC",
  65                                     NamedGroup.SECP384_R1,
  66                                     ProtocolVersion.PROTOCOLS_TO_13),
  67     ECDSA_SECP521R1_SHA512  (0x0603, "ecdsa_secp521r1_sha512",
  68                                     "SHA512withECDSA",
  69                                     "EC",
  70                                     NamedGroup.SECP521_R1,
  71                                     ProtocolVersion.PROTOCOLS_TO_13),
  72 
  73     // RSASSA-PSS algorithms with public key OID rsaEncryption
  74     //
  75     // The minimalKeySize is calculated as (See RFC 8017 for details):
  76     //     hash length + salt length + 16
  77     RSA_PSS_RSAE_SHA256     (0x0804, "rsa_pss_rsae_sha256",
  78                                     "RSASSA-PSS", "RSA",
  79                                     SigAlgParamSpec.RSA_PSS_SHA256, 528,
  80                                     ProtocolVersion.PROTOCOLS_12_13),
  81     RSA_PSS_RSAE_SHA384     (0x0805, "rsa_pss_rsae_sha384",
  82                                     "RSASSA-PSS", "RSA",
  83                                     SigAlgParamSpec.RSA_PSS_SHA384, 784,
  84                                     ProtocolVersion.PROTOCOLS_12_13),
  85     RSA_PSS_RSAE_SHA512     (0x0806, "rsa_pss_rsae_sha512",
  86                                     "RSASSA-PSS", "RSA",
  87                                     SigAlgParamSpec.RSA_PSS_SHA512, 1040,
  88                                     ProtocolVersion.PROTOCOLS_12_13),
  89 
  90     // RSASSA-PSS algorithms with public key OID RSASSA-PSS
  91     //
  92     // The minimalKeySize is calculated as (See RFC 8017 for details):
  93     //     hash length + salt length + 16
  94     RSA_PSS_PSS_SHA256      (0x0809, "rsa_pss_pss_sha256",
  95                                     "RSASSA-PSS", "RSASSA-PSS",
  96                                     SigAlgParamSpec.RSA_PSS_SHA256, 528,
  97                                     ProtocolVersion.PROTOCOLS_12_13),
  98     RSA_PSS_PSS_SHA384      (0x080A, "rsa_pss_pss_sha384",
  99                                     "RSASSA-PSS", "RSASSA-PSS",
 100                                     SigAlgParamSpec.RSA_PSS_SHA384, 784,
 101                                     ProtocolVersion.PROTOCOLS_12_13),
 102     RSA_PSS_PSS_SHA512      (0x080B, "rsa_pss_pss_sha512",
 103                                     "RSASSA-PSS", "RSASSA-PSS",
 104                                     SigAlgParamSpec.RSA_PSS_SHA512, 1040,
 105                                     ProtocolVersion.PROTOCOLS_12_13),
 106 
 107     // RSASSA-PKCS1-v1_5 algorithms
 108     RSA_PKCS1_SHA256        (0x0401, "rsa_pkcs1_sha256", "SHA256withRSA",
 109                                     "RSA", null, null, 511,
 110                                     ProtocolVersion.PROTOCOLS_TO_13,
 111                                     ProtocolVersion.PROTOCOLS_TO_12),
 112     RSA_PKCS1_SHA384        (0x0501, "rsa_pkcs1_sha384", "SHA384withRSA",
 113                                     "RSA", null, null, 768,
 114                                     ProtocolVersion.PROTOCOLS_TO_13,
 115                                     ProtocolVersion.PROTOCOLS_TO_12),
 116     RSA_PKCS1_SHA512        (0x0601, "rsa_pkcs1_sha512", "SHA512withRSA",
 117                                     "RSA", null, null, 768,
 118                                     ProtocolVersion.PROTOCOLS_TO_13,
 119                                     ProtocolVersion.PROTOCOLS_TO_12),
 120 
 121     // Legacy algorithms
 122     DSA_SHA256              (0x0402, "dsa_sha256", "SHA256withDSA",
 123                                     "DSA",
 124                                     ProtocolVersion.PROTOCOLS_TO_12),
 125     ECDSA_SHA224            (0x0303, "ecdsa_sha224", "SHA224withECDSA",
 126                                     "EC",
 127                                     ProtocolVersion.PROTOCOLS_TO_12),
 128     RSA_SHA224              (0x0301, "rsa_sha224", "SHA224withRSA",
 129                                     "RSA", 511,
 130                                     ProtocolVersion.PROTOCOLS_TO_12),
 131     DSA_SHA224              (0x0302, "dsa_sha224", "SHA224withDSA",
 132                                     "DSA",
 133                                     ProtocolVersion.PROTOCOLS_TO_12),
 134     ECDSA_SHA1              (0x0203, "ecdsa_sha1", "SHA1withECDSA",
 135                                     "EC",
 136                                     ProtocolVersion.PROTOCOLS_TO_13),
 137     RSA_PKCS1_SHA1          (0x0201, "rsa_pkcs1_sha1", "SHA1withRSA",
 138                                     "RSA", null, null, 511,
 139                                     ProtocolVersion.PROTOCOLS_TO_13,
 140                                     ProtocolVersion.PROTOCOLS_TO_12),
 141     DSA_SHA1                (0x0202, "dsa_sha1", "SHA1withDSA",
 142                                     "DSA",
 143                                     ProtocolVersion.PROTOCOLS_TO_12),
 144     RSA_MD5                 (0x0101, "rsa_md5", "MD5withRSA",
 145                                     "RSA", 511,
 146                                     ProtocolVersion.PROTOCOLS_TO_12);
 147 
 148     final int id;                       // hash + signature
 149     final String name;                  // literal name
 150     private final String algorithm;     // signature algorithm
 151     final String keyAlgorithm;          // signature key algorithm
 152     private final AlgorithmParameterSpec signAlgParameter;
 153     private final NamedGroup namedGroup;    // associated named group
 154 
 155     // The minimal required key size in bits.
 156     //
 157     // Only need to check RSA algorithm at present. RSA keys of 512 bits
 158     // have been shown to be practically breakable, it does not make much
 159     // sense to use the strong hash algorithm for keys whose key size less
 160     // than 512 bits.  So it is not necessary to calculate the minimal
 161     // required key size exactly for a hash algorithm.
 162     //
 163     // Note that some provider may use 511 bits for 512-bit strength RSA keys.
 164     final int minimalKeySize;
 165     final List<ProtocolVersion> supportedProtocols;
 166 
 167     // Some signature schemes are supported in different versions for handshake
 168     // messages and certificates. This field holds the supported protocols
 169     // for handshake messages.
 170     final List<ProtocolVersion> handshakeSupportedProtocols;
 171     final boolean isAvailable;
 172 
 173     private static final String[] hashAlgorithms = new String[] {
 174             "none",         "md5",      "sha1",     "sha224",
 175             "sha256",       "sha384",   "sha512"
 176         };
 177 
 178     private static final String[] signatureAlgorithms = new String[] {
 179             "anonymous",    "rsa",      "dsa",      "ecdsa",
 180         };
 181 
 182     static enum SigAlgParamSpec {   // support RSASSA-PSS only now
 183         RSA_PSS_SHA256 ("SHA-256", 32),
 184         RSA_PSS_SHA384 ("SHA-384", 48),
 185         RSA_PSS_SHA512 ("SHA-512", 64);
 186 
 187         final private AlgorithmParameterSpec parameterSpec;
 188         final boolean isAvailable;
 189 
 190         SigAlgParamSpec(String hash, int saltLength) {
 191             // See RFC 8017
 192             PSSParameterSpec pssParamSpec =
 193                     new PSSParameterSpec(hash, "MGF1",
 194                             new MGF1ParameterSpec(hash), saltLength, 1);
 195 
 196             boolean mediator = true;
 197             try {
 198                 Signature signer = Signature.getInstance("RSASSA-PSS");
 199                 signer.setParameter(pssParamSpec);
 200             } catch (InvalidAlgorithmParameterException |
 201                     NoSuchAlgorithmException exp) {
 202                 mediator = false;
 203                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 204                     SSLLogger.warning(
 205                         "RSASSA-PSS signature with " + hash +
 206                         " is not supported by the underlying providers", exp);
 207                 }
 208             }
 209 
 210             this.isAvailable = mediator;
 211             this.parameterSpec = mediator ? pssParamSpec : null;
 212         }
 213 
 214         AlgorithmParameterSpec getParameterSpec() {
 215             return parameterSpec;
 216         }
 217     }
 218 
 219     // performance optimization
 220     private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
 221         Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
 222 
 223 
 224     private SignatureScheme(int id, String name,
 225             String algorithm, String keyAlgorithm,
 226             ProtocolVersion[] supportedProtocols) {
 227         this(id, name, algorithm, keyAlgorithm, -1, supportedProtocols);
 228     }
 229 
 230     private SignatureScheme(int id, String name,
 231             String algorithm, String keyAlgorithm,
 232             int minimalKeySize,
 233             ProtocolVersion[] supportedProtocols) {
 234         this(id, name, algorithm, keyAlgorithm,
 235                 null, minimalKeySize, supportedProtocols);
 236     }
 237 
 238     private SignatureScheme(int id, String name,
 239             String algorithm, String keyAlgorithm,
 240             SigAlgParamSpec signAlgParamSpec, int minimalKeySize,
 241             ProtocolVersion[] supportedProtocols) {
 242         this(id, name, algorithm, keyAlgorithm,
 243                 signAlgParamSpec, null, minimalKeySize,
 244                 supportedProtocols, supportedProtocols);
 245     }
 246 
 247     private SignatureScheme(int id, String name,
 248             String algorithm, String keyAlgorithm,
 249             NamedGroup namedGroup,
 250             ProtocolVersion[] supportedProtocols) {
 251         this(id, name, algorithm, keyAlgorithm,
 252                 null, namedGroup, -1,
 253                 supportedProtocols, supportedProtocols);
 254     }
 255 
 256     private SignatureScheme(int id, String name,
 257             String algorithm, String keyAlgorithm,
 258             SigAlgParamSpec signAlgParamSpec,
 259             NamedGroup namedGroup, int minimalKeySize,
 260             ProtocolVersion[] supportedProtocols,
 261             ProtocolVersion[] handshakeSupportedProtocols) {
 262         this.id = id;
 263         this.name = name;
 264         this.algorithm = algorithm;
 265         this.keyAlgorithm = keyAlgorithm;
 266         this.signAlgParameter =
 267             signAlgParamSpec != null ? signAlgParamSpec.parameterSpec : null;
 268         this.namedGroup = namedGroup;
 269         this.minimalKeySize = minimalKeySize;
 270         this.supportedProtocols = Arrays.asList(supportedProtocols);
 271         this.handshakeSupportedProtocols =
 272                 Arrays.asList(handshakeSupportedProtocols);
 273 
 274         boolean mediator = true;
 275         if (signAlgParamSpec != null) {
 276             mediator = signAlgParamSpec.isAvailable;
 277         } else {
 278             try {
 279                 Signature.getInstance(algorithm);
 280             } catch (Exception e) {
 281                 mediator = false;
 282                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 283                     SSLLogger.warning(
 284                         "Signature algorithm, " + algorithm +
 285                         ", is not supported by the underlying providers");
 286                 }
 287             }
 288         }
 289 
 290         if (mediator && ((id >> 8) & 0xFF) == 0x03) {   // SHA224
 291             // There are some problems to use SHA224 on Windows.
 292             if (Security.getProvider("SunMSCAPI") != null) {
 293                 mediator = false;
 294             }
 295         }
 296 
 297         this.isAvailable = mediator;
 298     }
 299 
 300     static SignatureScheme valueOf(int id) {
 301         for (SignatureScheme ss: SignatureScheme.values()) {
 302             if (ss.id == id) {
 303                 return ss;
 304             }
 305         }
 306 
 307         return null;
 308     }
 309 
 310     static String nameOf(int id) {
 311         for (SignatureScheme ss: SignatureScheme.values()) {
 312             if (ss.id == id) {
 313                 return ss.name;
 314             }
 315         }
 316 
 317         // Use TLS 1.2 style name for unknown signature scheme.
 318         int hashId = ((id >> 8) & 0xFF);
 319         int signId = (id & 0xFF);
 320         String hashName = (hashId >= hashAlgorithms.length) ?
 321             "UNDEFINED-HASH(" + hashId + ")" : hashAlgorithms[hashId];
 322         String signName = (signId >= signatureAlgorithms.length) ?
 323             "UNDEFINED-SIGNATURE(" + signId + ")" :
 324             signatureAlgorithms[signId];
 325 
 326         return signName + "_" + hashName;
 327     }
 328 
 329     // Return the size of a SignatureScheme structure in TLS record
 330     static int sizeInRecord() {
 331         return 2;
 332     }
 333 
 334     // Get local supported algorithm collection complying to algorithm
 335     // constraints.
 336     static List<SignatureScheme> getSupportedAlgorithms(
 337             AlgorithmConstraints constraints,
 338             List<ProtocolVersion> activeProtocols) {
 339         List<SignatureScheme> supported = new LinkedList<>();
 340         for (SignatureScheme ss: SignatureScheme.values()) {
 341             if (!ss.isAvailable) {
 342                 continue;
 343             }
 344 
 345             boolean isMatch = false;
 346             for (ProtocolVersion pv : activeProtocols) {
 347                 if (ss.supportedProtocols.contains(pv)) {
 348                     isMatch = true;
 349                     break;
 350                 }
 351             }
 352 
 353             if (isMatch) {
 354                 if (constraints.permits(
 355                         SIGNATURE_PRIMITIVE_SET, ss.algorithm, null)) {
 356                     supported.add(ss);
 357                 } else if (SSLLogger.isOn &&
 358                         SSLLogger.isOn("ssl,handshake,verbose")) {
 359                     SSLLogger.finest(
 360                         "Ignore disabled signature scheme: " + ss.name);
 361                 }
 362             } else if (SSLLogger.isOn &&
 363                     SSLLogger.isOn("ssl,handshake,verbose")) {
 364                 SSLLogger.finest(
 365                     "Ignore inactive signature scheme: " + ss.name);
 366             }
 367         }
 368 
 369         return supported;
 370     }
 371 
 372     static List<SignatureScheme> getSupportedAlgorithms(
 373             AlgorithmConstraints constraints,
 374             ProtocolVersion protocolVersion, int[] algorithmIds) {
 375         List<SignatureScheme> supported = new LinkedList<>();
 376         for (int ssid : algorithmIds) {
 377             SignatureScheme ss = SignatureScheme.valueOf(ssid);
 378             if (ss == null) {
 379                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 380                     SSLLogger.warning(
 381                             "Unsupported signature scheme: " +
 382                             SignatureScheme.nameOf(ssid));
 383                 }
 384             } else if (ss.isAvailable &&
 385                     ss.supportedProtocols.contains(protocolVersion) &&
 386                     constraints.permits(SIGNATURE_PRIMITIVE_SET,
 387                            ss.algorithm, null)) {
 388                 supported.add(ss);
 389             } else {
 390                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 391                     SSLLogger.warning(
 392                             "Unsupported signature scheme: " + ss.name);
 393                 }
 394             }
 395         }
 396 
 397         return supported;
 398     }
 399 
 400     static SignatureScheme getPreferableAlgorithm(
 401             List<SignatureScheme> schemes,
 402             SignatureScheme certScheme,
 403             ProtocolVersion version) {
 404 
 405         for (SignatureScheme ss : schemes) {
 406             if (ss.isAvailable &&
 407                     ss.handshakeSupportedProtocols.contains(version) &&
 408                     certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) {
 409 
 410                 return ss;
 411             }
 412         }
 413 
 414         return null;
 415     }
 416 
 417     static SignatureScheme getPreferableAlgorithm(
 418             List<SignatureScheme> schemes,
 419             X509Possession x509Possession,
 420             ProtocolVersion version) {
 421 
 422         PrivateKey signingKey = x509Possession.popPrivateKey;
 423         String keyAlgorithm = signingKey.getAlgorithm();
 424         int keySize;
 425         // Only need to check RSA algorithm at present.
 426         if (keyAlgorithm.equalsIgnoreCase("RSA") ||
 427                 keyAlgorithm.equalsIgnoreCase("RSASSA-PSS")) {
 428             keySize = KeyUtil.getKeySize(signingKey);
 429         } else {
 430             keySize = Integer.MAX_VALUE;
 431         }
 432         for (SignatureScheme ss : schemes) {
 433             if (ss.isAvailable && (keySize >= ss.minimalKeySize) &&
 434                 ss.handshakeSupportedProtocols.contains(version) &&
 435                 keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) {
 436                 if (ss.namedGroup != null &&
 437                     ss.namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) {
 438                     ECParameterSpec params =
 439                             x509Possession.getECParameterSpec();
 440                     if (params != null &&
 441                             ss.namedGroup == NamedGroup.valueOf(params)) {
 442                         return ss;
 443                     }
 444                 } else {
 445                     return ss;
 446                 }
 447             }
 448         }
 449 
 450         return null;
 451     }
 452 
 453     static String[] getAlgorithmNames(Collection<SignatureScheme> schemes) {
 454         if (schemes != null) {
 455             ArrayList<String> names = new ArrayList<>(schemes.size());
 456             for (SignatureScheme scheme : schemes) {
 457                 names.add(scheme.algorithm);
 458             }
 459 
 460             return names.toArray(new String[0]);
 461         }
 462 
 463         return new String[0];
 464     }
 465 
 466     Signature getSignature(Key key) throws NoSuchAlgorithmException,
 467             InvalidAlgorithmParameterException, InvalidKeyException {
 468         if (!isAvailable) {
 469             return null;
 470         }
 471 
 472         Signature signer = Signature.getInstance(algorithm);
 473         if (key instanceof PublicKey) {
 474             signer.initVerify((PublicKey)(key));

 475         } else {
 476             signer.initSign((PrivateKey)key);
 477         }
 478 
 479         // Important note:  Please don't set the parameters before signature
 480         // or verification initialization, so that the crypto provider can
 481         // be selected properly.
 482         if (signAlgParameter != null) {
 483             signer.setParameter(signAlgParameter);
 484         }
 485 
 486         return signer;
 487     }
 488 }
--- EOF ---