1 /* 2 * Copyright (c) 2015, 2018, 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.AbstractMap.SimpleImmutableEntry; 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.Map; 42 import java.util.Set; 43 import sun.security.ssl.NamedGroup.NamedGroupSpec; 44 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; 45 import sun.security.ssl.X509Authentication.X509Possession; 46 import sun.security.util.KeyUtil; 47 import sun.security.util.SignatureUtil; 48 49 enum SignatureScheme { 50 // EdDSA algorithms 51 ED25519 (0x0807, "ed25519", "ed25519", 52 "ed25519", 53 ProtocolVersion.PROTOCOLS_OF_13), 54 ED448 (0x0808, "ed448", "ed448", 55 "ed448", 56 ProtocolVersion.PROTOCOLS_OF_13), 57 58 // ECDSA algorithms 59 ECDSA_SECP256R1_SHA256 (0x0403, "ecdsa_secp256r1_sha256", 60 "SHA256withECDSA", 61 "EC", 62 NamedGroup.SECP256_R1, 63 ProtocolVersion.PROTOCOLS_TO_13), 64 ECDSA_SECP384R1_SHA384 (0x0503, "ecdsa_secp384r1_sha384", 65 "SHA384withECDSA", 66 "EC", 67 NamedGroup.SECP384_R1, 68 ProtocolVersion.PROTOCOLS_TO_13), 69 ECDSA_SECP521R1_SHA512 (0x0603, "ecdsa_secp521r1_sha512", 70 "SHA512withECDSA", 71 "EC", 72 NamedGroup.SECP521_R1, 73 ProtocolVersion.PROTOCOLS_TO_13), 74 75 // RSASSA-PSS algorithms with public key OID rsaEncryption 76 // 77 // The minimalKeySize is calculated as (See RFC 8017 for details): 78 // hash length + salt length + 16 79 RSA_PSS_RSAE_SHA256 (0x0804, "rsa_pss_rsae_sha256", 80 "RSASSA-PSS", "RSA", 81 SigAlgParamSpec.RSA_PSS_SHA256, 528, 82 ProtocolVersion.PROTOCOLS_12_13), 83 RSA_PSS_RSAE_SHA384 (0x0805, "rsa_pss_rsae_sha384", 84 "RSASSA-PSS", "RSA", 85 SigAlgParamSpec.RSA_PSS_SHA384, 784, 86 ProtocolVersion.PROTOCOLS_12_13), 87 RSA_PSS_RSAE_SHA512 (0x0806, "rsa_pss_rsae_sha512", 88 "RSASSA-PSS", "RSA", 89 SigAlgParamSpec.RSA_PSS_SHA512, 1040, 90 ProtocolVersion.PROTOCOLS_12_13), 91 92 // RSASSA-PSS algorithms with public key OID RSASSA-PSS 93 // 94 // The minimalKeySize is calculated as (See RFC 8017 for details): 95 // hash length + salt length + 16 96 RSA_PSS_PSS_SHA256 (0x0809, "rsa_pss_pss_sha256", 97 "RSASSA-PSS", "RSASSA-PSS", 98 SigAlgParamSpec.RSA_PSS_SHA256, 528, 99 ProtocolVersion.PROTOCOLS_12_13), 100 RSA_PSS_PSS_SHA384 (0x080A, "rsa_pss_pss_sha384", 101 "RSASSA-PSS", "RSASSA-PSS", 102 SigAlgParamSpec.RSA_PSS_SHA384, 784, 103 ProtocolVersion.PROTOCOLS_12_13), 104 RSA_PSS_PSS_SHA512 (0x080B, "rsa_pss_pss_sha512", 105 "RSASSA-PSS", "RSASSA-PSS", 106 SigAlgParamSpec.RSA_PSS_SHA512, 1040, 107 ProtocolVersion.PROTOCOLS_12_13), 108 109 // RSASSA-PKCS1-v1_5 algorithms 110 RSA_PKCS1_SHA256 (0x0401, "rsa_pkcs1_sha256", "SHA256withRSA", 111 "RSA", null, null, 511, 112 ProtocolVersion.PROTOCOLS_TO_13, 113 ProtocolVersion.PROTOCOLS_TO_12), 114 RSA_PKCS1_SHA384 (0x0501, "rsa_pkcs1_sha384", "SHA384withRSA", 115 "RSA", null, null, 768, 116 ProtocolVersion.PROTOCOLS_TO_13, 117 ProtocolVersion.PROTOCOLS_TO_12), 118 RSA_PKCS1_SHA512 (0x0601, "rsa_pkcs1_sha512", "SHA512withRSA", 119 "RSA", null, null, 768, 120 ProtocolVersion.PROTOCOLS_TO_13, 121 ProtocolVersion.PROTOCOLS_TO_12), 122 123 // Legacy algorithms 124 DSA_SHA256 (0x0402, "dsa_sha256", "SHA256withDSA", 125 "DSA", 126 ProtocolVersion.PROTOCOLS_TO_12), 127 ECDSA_SHA224 (0x0303, "ecdsa_sha224", "SHA224withECDSA", 128 "EC", 129 ProtocolVersion.PROTOCOLS_TO_12), 130 RSA_SHA224 (0x0301, "rsa_sha224", "SHA224withRSA", 131 "RSA", 511, 132 ProtocolVersion.PROTOCOLS_TO_12), 133 DSA_SHA224 (0x0302, "dsa_sha224", "SHA224withDSA", 134 "DSA", 135 ProtocolVersion.PROTOCOLS_TO_12), 136 ECDSA_SHA1 (0x0203, "ecdsa_sha1", "SHA1withECDSA", 137 "EC", 138 ProtocolVersion.PROTOCOLS_TO_13), 139 RSA_PKCS1_SHA1 (0x0201, "rsa_pkcs1_sha1", "SHA1withRSA", 140 "RSA", null, null, 511, 141 ProtocolVersion.PROTOCOLS_TO_13, 142 ProtocolVersion.PROTOCOLS_TO_12), 143 DSA_SHA1 (0x0202, "dsa_sha1", "SHA1withDSA", 144 "DSA", 145 ProtocolVersion.PROTOCOLS_TO_12), 146 RSA_MD5 (0x0101, "rsa_md5", "MD5withRSA", 147 "RSA", 511, 148 ProtocolVersion.PROTOCOLS_TO_12); 149 150 final int id; // hash + signature 151 final String name; // literal name 152 private final String algorithm; // signature algorithm 153 final String keyAlgorithm; // signature key algorithm 154 private final SigAlgParamSpec signAlgParams; // signature parameters 155 private final NamedGroup namedGroup; // associated named group 156 157 // The minimal required key size in bits. 158 // 159 // Only need to check RSA algorithm at present. RSA keys of 512 bits 160 // have been shown to be practically breakable, it does not make much 161 // sense to use the strong hash algorithm for keys whose key size less 162 // than 512 bits. So it is not necessary to calculate the minimal 163 // required key size exactly for a hash algorithm. 164 // 165 // Note that some provider may use 511 bits for 512-bit strength RSA keys. 166 final int minimalKeySize; 167 final List<ProtocolVersion> supportedProtocols; 168 169 // Some signature schemes are supported in different versions for handshake 170 // messages and certificates. This field holds the supported protocols 171 // for handshake messages. 172 final List<ProtocolVersion> handshakeSupportedProtocols; 173 final boolean isAvailable; 174 175 private static final String[] hashAlgorithms = new String[] { 176 "none", "md5", "sha1", "sha224", 177 "sha256", "sha384", "sha512" 178 }; 179 180 private static final String[] signatureAlgorithms = new String[] { 181 "anonymous", "rsa", "dsa", "ecdsa", 182 }; 183 184 static enum SigAlgParamSpec { // support RSASSA-PSS only now 185 RSA_PSS_SHA256 ("SHA-256", 32), 186 RSA_PSS_SHA384 ("SHA-384", 48), 187 RSA_PSS_SHA512 ("SHA-512", 64); 188 189 private final AlgorithmParameterSpec parameterSpec; 190 private final AlgorithmParameters parameters; 191 private final boolean isAvailable; 192 193 SigAlgParamSpec(String hash, int saltLength) { 194 // See RFC 8017 195 PSSParameterSpec pssParamSpec = 196 new PSSParameterSpec(hash, "MGF1", 197 new MGF1ParameterSpec(hash), saltLength, 1); 198 AlgorithmParameters pssParams = null; 199 200 boolean mediator = true; 201 try { 202 Signature signer = JsseJce.getSignature("RSASSA-PSS"); 203 signer.setParameter(pssParamSpec); 204 pssParams = signer.getParameters(); 205 } catch (InvalidAlgorithmParameterException | 206 NoSuchAlgorithmException | RuntimeException exp) { 207 // Signature.getParameters() may throw RuntimeException. 208 mediator = false; 209 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 210 SSLLogger.warning( 211 "RSASSA-PSS signature with " + hash + 212 " is not supported by the underlying providers", exp); 213 } 214 } 215 216 this.isAvailable = mediator; 217 this.parameterSpec = mediator ? pssParamSpec : null; 218 this.parameters = mediator ? pssParams : null; 219 } 220 } 221 222 // performance optimization 223 private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET = 224 Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE)); 225 226 227 private SignatureScheme(int id, String name, 228 String algorithm, String keyAlgorithm, 229 ProtocolVersion[] supportedProtocols) { 230 this(id, name, algorithm, keyAlgorithm, -1, supportedProtocols); 231 } 232 233 private SignatureScheme(int id, String name, 234 String algorithm, String keyAlgorithm, 235 int minimalKeySize, 236 ProtocolVersion[] supportedProtocols) { 237 this(id, name, algorithm, keyAlgorithm, 238 null, minimalKeySize, supportedProtocols); 239 } 240 241 private SignatureScheme(int id, String name, 242 String algorithm, String keyAlgorithm, 243 SigAlgParamSpec signAlgParamSpec, int minimalKeySize, 244 ProtocolVersion[] supportedProtocols) { 245 this(id, name, algorithm, keyAlgorithm, 246 signAlgParamSpec, null, minimalKeySize, 247 supportedProtocols, supportedProtocols); 248 } 249 250 private SignatureScheme(int id, String name, 251 String algorithm, String keyAlgorithm, 252 NamedGroup namedGroup, 253 ProtocolVersion[] supportedProtocols) { 254 this(id, name, algorithm, keyAlgorithm, 255 null, namedGroup, -1, 256 supportedProtocols, supportedProtocols); 257 } 258 259 private SignatureScheme(int id, String name, 260 String algorithm, String keyAlgorithm, 261 SigAlgParamSpec signAlgParams, 262 NamedGroup namedGroup, int minimalKeySize, 263 ProtocolVersion[] supportedProtocols, 264 ProtocolVersion[] handshakeSupportedProtocols) { 265 this.id = id; 266 this.name = name; 267 this.algorithm = algorithm; 268 this.keyAlgorithm = keyAlgorithm; 269 this.signAlgParams = signAlgParams; 270 this.namedGroup = namedGroup; 271 this.minimalKeySize = minimalKeySize; 272 this.supportedProtocols = Arrays.asList(supportedProtocols); 273 this.handshakeSupportedProtocols = 274 Arrays.asList(handshakeSupportedProtocols); 275 276 boolean mediator = true; 277 // An EC provider, for example the SunEC provider, may support 278 // AlgorithmParameters but not KeyPairGenerator or Signature. 279 // 280 // Note: Please be careful if removing this block! 281 if ("EC".equals(keyAlgorithm)) { 282 mediator = JsseJce.isEcAvailable(); 283 } 284 285 // Check the specific algorithm and parameters. 286 if (mediator) { 287 if (signAlgParams != null) { 288 mediator = signAlgParams.isAvailable; 289 } else { 290 try { 291 JsseJce.getSignature(algorithm); 292 } catch (Exception e) { 293 mediator = false; 294 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 295 SSLLogger.warning( 296 "Signature algorithm, " + algorithm + 297 ", is not supported by the underlying providers"); 298 } 299 } 300 } 301 } 302 303 if (mediator && ((id >> 8) & 0xFF) == 0x03) { // SHA224 304 // There are some problems to use SHA224 on Windows. 305 if (Security.getProvider("SunMSCAPI") != null) { 306 mediator = false; 307 } 308 } 309 310 this.isAvailable = mediator; 311 } 312 313 static SignatureScheme valueOf(int id) { 314 for (SignatureScheme ss: SignatureScheme.values()) { 315 if (ss.id == id) { 316 return ss; 317 } 318 } 319 320 return null; 321 } 322 323 static String nameOf(int id) { 324 for (SignatureScheme ss: SignatureScheme.values()) { 325 if (ss.id == id) { 326 return ss.name; 327 } 328 } 329 330 // Use TLS 1.2 style name for unknown signature scheme. 331 int hashId = ((id >> 8) & 0xFF); 332 int signId = (id & 0xFF); 333 String hashName = (hashId >= hashAlgorithms.length) ? 334 "UNDEFINED-HASH(" + hashId + ")" : hashAlgorithms[hashId]; 335 String signName = (signId >= signatureAlgorithms.length) ? 336 "UNDEFINED-SIGNATURE(" + signId + ")" : 337 signatureAlgorithms[signId]; 338 339 return signName + "_" + hashName; 340 } 341 342 // Note: the signatureSchemeName is not case-sensitive. 343 static SignatureScheme nameOf(String signatureSchemeName) { 344 for (SignatureScheme ss: SignatureScheme.values()) { 345 if (ss.name.equalsIgnoreCase(signatureSchemeName)) { 346 return ss; 347 } 348 } 349 350 return null; 351 } 352 353 // Return the size of a SignatureScheme structure in TLS record 354 static int sizeInRecord() { 355 return 2; 356 } 357 358 private boolean isPermitted(AlgorithmConstraints constraints) { 359 return constraints.permits(SIGNATURE_PRIMITIVE_SET, 360 this.name, null) && 361 constraints.permits(SIGNATURE_PRIMITIVE_SET, 362 this.keyAlgorithm, null) && 363 constraints.permits(SIGNATURE_PRIMITIVE_SET, 364 this.algorithm, (signAlgParams != null ? 365 signAlgParams.parameters : null)) && 366 (namedGroup != null ? 367 namedGroup.isPermitted(constraints) : true); 368 } 369 370 // Get local supported algorithm collection complying to algorithm 371 // constraints. 372 static List<SignatureScheme> getSupportedAlgorithms( 373 SSLConfiguration config, 374 AlgorithmConstraints constraints, 375 List<ProtocolVersion> activeProtocols) { 376 List<SignatureScheme> supported = new LinkedList<>(); 377 for (SignatureScheme ss: SignatureScheme.values()) { 378 if (!ss.isAvailable || 379 (!config.signatureSchemes.isEmpty() && 380 !config.signatureSchemes.contains(ss))) { 381 if (SSLLogger.isOn && 382 SSLLogger.isOn("ssl,handshake,verbose")) { 383 SSLLogger.finest( 384 "Ignore unsupported signature scheme: " + ss.name); 385 } 386 continue; 387 } 388 389 boolean isMatch = false; 390 for (ProtocolVersion pv : activeProtocols) { 391 if (ss.supportedProtocols.contains(pv)) { 392 isMatch = true; 393 break; 394 } 395 } 396 397 if (isMatch) { 398 if (ss.isPermitted(constraints)) { 399 supported.add(ss); 400 } else if (SSLLogger.isOn && 401 SSLLogger.isOn("ssl,handshake,verbose")) { 402 SSLLogger.finest( 403 "Ignore disabled signature scheme: " + ss.name); 404 } 405 } else if (SSLLogger.isOn && 406 SSLLogger.isOn("ssl,handshake,verbose")) { 407 SSLLogger.finest( 408 "Ignore inactive signature scheme: " + ss.name); 409 } 410 } 411 412 return supported; 413 } 414 415 static List<SignatureScheme> getSupportedAlgorithms( 416 SSLConfiguration config, 417 AlgorithmConstraints constraints, 418 ProtocolVersion protocolVersion, int[] algorithmIds) { 419 List<SignatureScheme> supported = new LinkedList<>(); 420 for (int ssid : algorithmIds) { 421 SignatureScheme ss = SignatureScheme.valueOf(ssid); 422 if (ss == null) { 423 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 424 SSLLogger.warning( 425 "Unsupported signature scheme: " + 426 SignatureScheme.nameOf(ssid)); 427 } 428 } else if (ss.isAvailable && 429 ss.supportedProtocols.contains(protocolVersion) && 430 (config.signatureSchemes.isEmpty() || 431 config.signatureSchemes.contains(ss)) && 432 ss.isPermitted(constraints)) { 433 supported.add(ss); 434 } else { 435 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 436 SSLLogger.warning( 437 "Unsupported signature scheme: " + ss.name); 438 } 439 } 440 } 441 442 return supported; 443 } 444 445 static SignatureScheme getPreferableAlgorithm( 446 AlgorithmConstraints constraints, 447 List<SignatureScheme> schemes, 448 SignatureScheme certScheme, 449 ProtocolVersion version) { 450 451 for (SignatureScheme ss : schemes) { 452 if (ss.isAvailable && 453 ss.handshakeSupportedProtocols.contains(version) && 454 certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) && 455 ss.isPermitted(constraints)) { 456 return ss; 457 } 458 } 459 460 return null; 461 } 462 463 static Map.Entry<SignatureScheme, Signature> getSignerOfPreferableAlgorithm( 464 AlgorithmConstraints constraints, 465 List<SignatureScheme> schemes, 466 X509Possession x509Possession, 467 ProtocolVersion version) { 468 469 PrivateKey signingKey = x509Possession.popPrivateKey; 470 String keyAlgorithm = signingKey.getAlgorithm(); 471 int keySize; 472 // Only need to check RSA algorithm at present. 473 if (keyAlgorithm.equalsIgnoreCase("RSA") || 474 keyAlgorithm.equalsIgnoreCase("RSASSA-PSS")) { 475 keySize = KeyUtil.getKeySize(signingKey); 476 } else { 477 keySize = Integer.MAX_VALUE; 478 } 479 for (SignatureScheme ss : schemes) { 480 if (ss.isAvailable && (keySize >= ss.minimalKeySize) && 481 ss.handshakeSupportedProtocols.contains(version) && 482 keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) && 483 ss.isPermitted(constraints)) { 484 if ((ss.namedGroup != null) && (ss.namedGroup.spec == 485 NamedGroupSpec.NAMED_GROUP_ECDHE)) { 486 ECParameterSpec params = 487 x509Possession.getECParameterSpec(); 488 if (params != null && 489 ss.namedGroup == NamedGroup.valueOf(params)) { 490 Signature signer = ss.getSigner(signingKey); 491 if (signer != null) { 492 return new SimpleImmutableEntry<>(ss, signer); 493 } 494 } 495 496 if (SSLLogger.isOn && 497 SSLLogger.isOn("ssl,handshake,verbose")) { 498 SSLLogger.finest( 499 "Ignore the signature algorithm (" + ss + 500 "), unsupported EC parameter spec: " + params); 501 } 502 } else if ("EC".equals(ss.keyAlgorithm)) { 503 // Must be a legacy signature algorithm, which does not 504 // specify the associated named groups. The connection 505 // cannot be established if the peer cannot recognize 506 // the named group used for the signature. RFC 8446 507 // does not define countermeasures for the corner cases. 508 // In order to mitigate the impact, we choose to check 509 // against the local supported named groups. The risk 510 // should be minimal as applications should not use 511 // unsupported named groups for its certificates. 512 ECParameterSpec params = 513 x509Possession.getECParameterSpec(); 514 if (params != null) { 515 NamedGroup keyGroup = NamedGroup.valueOf(params); 516 if (keyGroup != null && 517 SupportedGroups.isSupported(keyGroup)) { 518 Signature signer = ss.getSigner(signingKey); 519 if (signer != null) { 520 return new SimpleImmutableEntry<>(ss, signer); 521 } 522 } 523 } 524 525 if (SSLLogger.isOn && 526 SSLLogger.isOn("ssl,handshake,verbose")) { 527 SSLLogger.finest( 528 "Ignore the legacy signature algorithm (" + ss + 529 "), unsupported EC parameter spec: " + params); 530 } 531 } else { 532 Signature signer = ss.getSigner(signingKey); 533 if (signer != null) { 534 return new SimpleImmutableEntry<>(ss, signer); 535 } 536 } 537 } 538 } 539 540 return null; 541 } 542 543 static String[] getAlgorithmNames(Collection<SignatureScheme> schemes) { 544 if (schemes != null) { 545 ArrayList<String> names = new ArrayList<>(schemes.size()); 546 for (SignatureScheme scheme : schemes) { 547 names.add(scheme.algorithm); 548 } 549 550 return names.toArray(new String[0]); 551 } 552 553 return new String[0]; 554 } 555 556 // This method is used to get the signature instance of this signature 557 // scheme for the specific public key. Unlike getSigner(), the exception 558 // is bubbled up. If the public key does not support this signature 559 // scheme, it normally means the TLS handshaking cannot continue and 560 // the connection should be terminated. 561 Signature getVerifier(PublicKey publicKey) throws NoSuchAlgorithmException, 562 InvalidAlgorithmParameterException, InvalidKeyException { 563 if (!isAvailable) { 564 return null; 565 } 566 567 Signature verifier = Signature.getInstance(algorithm); 568 SignatureUtil.initVerifyWithParam(verifier, publicKey, 569 (signAlgParams != null ? 570 signAlgParams.parameterSpec : null)); 571 572 return verifier; 573 } 574 575 // This method is also used to choose preferable signature scheme for the 576 // specific private key. If the private key does not support the signature 577 // scheme, {@code null} is returned, and the caller may fail back to next 578 // available signature scheme. 579 private Signature getSigner(PrivateKey privateKey) { 580 if (!isAvailable) { 581 return null; 582 } 583 584 try { 585 Signature signer = Signature.getInstance(algorithm); 586 SignatureUtil.initSignWithParam(signer, privateKey, 587 (signAlgParams != null ? 588 signAlgParams.parameterSpec : null), 589 null); 590 return signer; 591 } catch (NoSuchAlgorithmException | InvalidKeyException | 592 InvalidAlgorithmParameterException nsae) { 593 if (SSLLogger.isOn && 594 SSLLogger.isOn("ssl,handshake,verbose")) { 595 SSLLogger.finest( 596 "Ignore unsupported signature algorithm (" + 597 this.name + ")", nsae); 598 } 599 } 600 601 return null; 602 } 603 }