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