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.NamedGroupType; 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 AlgorithmParameterSpec signAlgParameter; 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 final private AlgorithmParameterSpec parameterSpec; 190 final boolean isAvailable; 191 192 SigAlgParamSpec(String hash, int saltLength) { 193 // See RFC 8017 194 PSSParameterSpec pssParamSpec = 195 new PSSParameterSpec(hash, "MGF1", 196 new MGF1ParameterSpec(hash), saltLength, 1); 197 198 boolean mediator = true; 199 try { 200 Signature signer = JsseJce.getSignature("RSASSA-PSS"); 201 signer.setParameter(pssParamSpec); 202 } catch (InvalidAlgorithmParameterException | 203 NoSuchAlgorithmException exp) { 204 mediator = false; 205 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 206 SSLLogger.warning( 207 "RSASSA-PSS signature with " + hash + 208 " is not supported by the underlying providers", exp); 209 } 210 } 211 212 this.isAvailable = mediator; 213 this.parameterSpec = mediator ? pssParamSpec : null; 214 } 215 216 AlgorithmParameterSpec getParameterSpec() { 217 return parameterSpec; 218 } 219 } 220 221 // performance optimization 222 private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET = 223 Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE)); 224 225 226 private SignatureScheme(int id, String name, 227 String algorithm, String keyAlgorithm, 228 ProtocolVersion[] supportedProtocols) { 229 this(id, name, algorithm, keyAlgorithm, -1, supportedProtocols); 230 } 231 232 private SignatureScheme(int id, String name, 233 String algorithm, String keyAlgorithm, 234 int minimalKeySize, 235 ProtocolVersion[] supportedProtocols) { 236 this(id, name, algorithm, keyAlgorithm, 237 null, minimalKeySize, supportedProtocols); 238 } 239 240 private SignatureScheme(int id, String name, 241 String algorithm, String keyAlgorithm, 242 SigAlgParamSpec signAlgParamSpec, int minimalKeySize, 243 ProtocolVersion[] supportedProtocols) { 244 this(id, name, algorithm, keyAlgorithm, 245 signAlgParamSpec, null, minimalKeySize, 246 supportedProtocols, supportedProtocols); 247 } 248 249 private SignatureScheme(int id, String name, 250 String algorithm, String keyAlgorithm, 251 NamedGroup namedGroup, 252 ProtocolVersion[] supportedProtocols) { 253 this(id, name, algorithm, keyAlgorithm, 254 null, namedGroup, -1, 255 supportedProtocols, supportedProtocols); 256 } 257 258 private SignatureScheme(int id, String name, 259 String algorithm, String keyAlgorithm, 260 SigAlgParamSpec signAlgParamSpec, 261 NamedGroup namedGroup, int minimalKeySize, 262 ProtocolVersion[] supportedProtocols, 263 ProtocolVersion[] handshakeSupportedProtocols) { 264 this.id = id; 265 this.name = name; 266 this.algorithm = algorithm; 267 this.keyAlgorithm = keyAlgorithm; 268 this.signAlgParameter = 269 signAlgParamSpec != null ? signAlgParamSpec.parameterSpec : null; 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 (signAlgParamSpec != null) { 288 mediator = signAlgParamSpec.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 // Get local supported algorithm collection complying to algorithm 359 // constraints. 360 static List<SignatureScheme> getSupportedAlgorithms( 361 SSLConfiguration config, 362 AlgorithmConstraints constraints, 363 List<ProtocolVersion> activeProtocols) { 364 List<SignatureScheme> supported = new LinkedList<>(); 365 for (SignatureScheme ss: SignatureScheme.values()) { 366 if (!ss.isAvailable || 367 (!config.signatureSchemes.isEmpty() && 368 !config.signatureSchemes.contains(ss))) { 369 if (SSLLogger.isOn && 370 SSLLogger.isOn("ssl,handshake,verbose")) { 371 SSLLogger.finest( 372 "Ignore unsupported signature scheme: " + ss.name); 373 } 374 continue; 375 } 376 377 boolean isMatch = false; 378 for (ProtocolVersion pv : activeProtocols) { 379 if (ss.supportedProtocols.contains(pv)) { 380 isMatch = true; 381 break; 382 } 383 } 384 385 if (isMatch) { 386 if (constraints.permits( 387 SIGNATURE_PRIMITIVE_SET, ss.algorithm, null)) { 388 supported.add(ss); 389 } else if (SSLLogger.isOn && 390 SSLLogger.isOn("ssl,handshake,verbose")) { 391 SSLLogger.finest( 392 "Ignore disabled signature scheme: " + ss.name); 393 } 394 } else if (SSLLogger.isOn && 395 SSLLogger.isOn("ssl,handshake,verbose")) { 396 SSLLogger.finest( 397 "Ignore inactive signature scheme: " + ss.name); 398 } 399 } 400 401 return supported; 402 } 403 404 static List<SignatureScheme> getSupportedAlgorithms( 405 SSLConfiguration config, 406 AlgorithmConstraints constraints, 407 ProtocolVersion protocolVersion, int[] algorithmIds) { 408 List<SignatureScheme> supported = new LinkedList<>(); 409 for (int ssid : algorithmIds) { 410 SignatureScheme ss = SignatureScheme.valueOf(ssid); 411 if (ss == null) { 412 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 413 SSLLogger.warning( 414 "Unsupported signature scheme: " + 415 SignatureScheme.nameOf(ssid)); 416 } 417 } else if (ss.isAvailable && 418 ss.supportedProtocols.contains(protocolVersion) && 419 (config.signatureSchemes.isEmpty() || 420 config.signatureSchemes.contains(ss)) && 421 constraints.permits(SIGNATURE_PRIMITIVE_SET, 422 ss.algorithm, null)) { 423 supported.add(ss); 424 } else { 425 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 426 SSLLogger.warning( 427 "Unsupported signature scheme: " + ss.name); 428 } 429 } 430 } 431 432 return supported; 433 } 434 435 static SignatureScheme getPreferableAlgorithm( 436 List<SignatureScheme> schemes, 437 SignatureScheme certScheme, 438 ProtocolVersion version) { 439 440 for (SignatureScheme ss : schemes) { 441 if (ss.isAvailable && 442 ss.handshakeSupportedProtocols.contains(version) && 443 certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) { 444 445 return ss; 446 } 447 } 448 449 return null; 450 } 451 452 static Map.Entry<SignatureScheme, Signature> getSignerOfPreferableAlgorithm( 453 List<SignatureScheme> schemes, 454 X509Possession x509Possession, 455 ProtocolVersion version) { 456 457 PrivateKey signingKey = x509Possession.popPrivateKey; 458 String keyAlgorithm = signingKey.getAlgorithm(); 459 int keySize; 460 // Only need to check RSA algorithm at present. 461 if (keyAlgorithm.equalsIgnoreCase("RSA") || 462 keyAlgorithm.equalsIgnoreCase("RSASSA-PSS")) { 463 keySize = KeyUtil.getKeySize(signingKey); 464 } else { 465 keySize = Integer.MAX_VALUE; 466 } 467 for (SignatureScheme ss : schemes) { 468 if (ss.isAvailable && (keySize >= ss.minimalKeySize) && 469 ss.handshakeSupportedProtocols.contains(version) && 470 keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) { 471 if ((ss.namedGroup != null) && (ss.namedGroup.type == 472 NamedGroupType.NAMED_GROUP_ECDHE)) { 473 ECParameterSpec params = 474 x509Possession.getECParameterSpec(); 475 if (params != null && 476 ss.namedGroup == NamedGroup.valueOf(params)) { 477 Signature signer = ss.getSigner(signingKey); 478 if (signer != null) { 479 return new SimpleImmutableEntry<>(ss, signer); 480 } 481 } 482 483 if (SSLLogger.isOn && 484 SSLLogger.isOn("ssl,handshake,verbose")) { 485 SSLLogger.finest( 486 "Ignore the signature algorithm (" + ss + 487 "), unsupported EC parameter spec: " + params); 488 } 489 } else if ("EC".equals(ss.keyAlgorithm)) { 490 // Must be a legacy signature algorithm, which does not 491 // specify the associated named groups. The connection 492 // cannot be established if the peer cannot recognize 493 // the named group used for the signature. RFC 8446 494 // does not define countermeasures for the corner cases. 495 // In order to mitigate the impact, we choose to check 496 // against the local supported named groups. The risk 497 // should be minimal as applications should not use 498 // unsupported named groups for its certificates. 499 ECParameterSpec params = 500 x509Possession.getECParameterSpec(); 501 if (params != null) { 502 NamedGroup keyGroup = NamedGroup.valueOf(params); 503 if (keyGroup != null && 504 SupportedGroups.isSupported(keyGroup)) { 505 Signature signer = ss.getSigner(signingKey); 506 if (signer != null) { 507 return new SimpleImmutableEntry<>(ss, signer); 508 } 509 } 510 } 511 512 if (SSLLogger.isOn && 513 SSLLogger.isOn("ssl,handshake,verbose")) { 514 SSLLogger.finest( 515 "Ignore the legacy signature algorithm (" + ss + 516 "), unsupported EC parameter spec: " + params); 517 } 518 } else { 519 Signature signer = ss.getSigner(signingKey); 520 if (signer != null) { 521 return new SimpleImmutableEntry<>(ss, signer); 522 } 523 } 524 } 525 } 526 527 return null; 528 } 529 530 static String[] getAlgorithmNames(Collection<SignatureScheme> schemes) { 531 if (schemes != null) { 532 ArrayList<String> names = new ArrayList<>(schemes.size()); 533 for (SignatureScheme scheme : schemes) { 534 names.add(scheme.algorithm); 535 } 536 537 return names.toArray(new String[0]); 538 } 539 540 return new String[0]; 541 } 542 543 // This method is used to get the signature instance of this signature 544 // scheme for the specific public key. Unlike getSigner(), the exception 545 // is bubbled up. If the public key does not support this signature 546 // scheme, it normally means the TLS handshaking cannot continue and 547 // the connection should be terminated. 548 Signature getVerifier(PublicKey publicKey) throws NoSuchAlgorithmException, 549 InvalidAlgorithmParameterException, InvalidKeyException { 550 if (!isAvailable) { 551 return null; 552 } 553 554 Signature verifier = Signature.getInstance(algorithm); 555 SignatureUtil.initVerifyWithParam(verifier, publicKey, signAlgParameter); 556 557 return verifier; 558 } 559 560 // This method is also used to choose preferable signature scheme for the 561 // specific private key. If the private key does not support the signature 562 // scheme, {@code null} is returned, and the caller may fail back to next 563 // available signature scheme. 564 private Signature getSigner(PrivateKey privateKey) { 565 if (!isAvailable) { 566 return null; 567 } 568 569 try { 570 Signature signer = Signature.getInstance(algorithm); 571 SignatureUtil.initSignWithParam(signer, privateKey, 572 signAlgParameter, 573 null); 574 return signer; 575 } catch (NoSuchAlgorithmException | InvalidKeyException | 576 InvalidAlgorithmParameterException nsae) { 577 if (SSLLogger.isOn && 578 SSLLogger.isOn("ssl,handshake,verbose")) { 579 SSLLogger.finest( 580 "Ignore unsupported signature algorithm (" + 581 this.name + ")", nsae); 582 } 583 } 584 585 return null; 586 } 587 }