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