36 import java.util.Collections; |
36 import java.util.Collections; |
37 import java.util.EnumSet; |
37 import java.util.EnumSet; |
38 import java.util.LinkedList; |
38 import java.util.LinkedList; |
39 import java.util.List; |
39 import java.util.List; |
40 import java.util.Set; |
40 import java.util.Set; |
41 import sun.security.ssl.NamedGroup.NamedGroupType; |
41 import sun.security.ssl.NamedGroup.NamedGroupSpec; |
42 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; |
42 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; |
43 import sun.security.ssl.X509Authentication.X509Possession; |
43 import sun.security.ssl.X509Authentication.X509Possession; |
44 import sun.security.util.KeyUtil; |
44 import sun.security.util.KeyUtil; |
45 import sun.security.util.SignatureUtil; |
45 import sun.security.util.SignatureUtil; |
46 |
46 |
147 |
147 |
148 final int id; // hash + signature |
148 final int id; // hash + signature |
149 final String name; // literal name |
149 final String name; // literal name |
150 private final String algorithm; // signature algorithm |
150 private final String algorithm; // signature algorithm |
151 final String keyAlgorithm; // signature key algorithm |
151 final String keyAlgorithm; // signature key algorithm |
152 private final AlgorithmParameterSpec signAlgParameter; |
152 private final SigAlgParamSpec signAlgParams; // signature parameters |
153 private final NamedGroup namedGroup; // associated named group |
153 private final NamedGroup namedGroup; // associated named group |
154 |
154 |
155 // The minimal required key size in bits. |
155 // The minimal required key size in bits. |
156 // |
156 // |
157 // Only need to check RSA algorithm at present. RSA keys of 512 bits |
157 // Only need to check RSA algorithm at present. RSA keys of 512 bits |
182 static enum SigAlgParamSpec { // support RSASSA-PSS only now |
182 static enum SigAlgParamSpec { // support RSASSA-PSS only now |
183 RSA_PSS_SHA256 ("SHA-256", 32), |
183 RSA_PSS_SHA256 ("SHA-256", 32), |
184 RSA_PSS_SHA384 ("SHA-384", 48), |
184 RSA_PSS_SHA384 ("SHA-384", 48), |
185 RSA_PSS_SHA512 ("SHA-512", 64); |
185 RSA_PSS_SHA512 ("SHA-512", 64); |
186 |
186 |
187 final private AlgorithmParameterSpec parameterSpec; |
187 private final AlgorithmParameterSpec parameterSpec; |
188 final boolean isAvailable; |
188 private final AlgorithmParameters parameters; |
|
189 private final boolean isAvailable; |
189 |
190 |
190 SigAlgParamSpec(String hash, int saltLength) { |
191 SigAlgParamSpec(String hash, int saltLength) { |
191 // See RFC 8017 |
192 // See RFC 8017 |
192 PSSParameterSpec pssParamSpec = |
193 PSSParameterSpec pssParamSpec = |
193 new PSSParameterSpec(hash, "MGF1", |
194 new PSSParameterSpec(hash, "MGF1", |
194 new MGF1ParameterSpec(hash), saltLength, 1); |
195 new MGF1ParameterSpec(hash), saltLength, 1); |
|
196 AlgorithmParameters pssParams = null; |
195 |
197 |
196 boolean mediator = true; |
198 boolean mediator = true; |
197 try { |
199 try { |
198 Signature signer = Signature.getInstance("RSASSA-PSS"); |
200 Signature signer = Signature.getInstance("RSASSA-PSS"); |
199 signer.setParameter(pssParamSpec); |
201 signer.setParameter(pssParamSpec); |
|
202 pssParams = signer.getParameters(); |
200 } catch (InvalidAlgorithmParameterException | |
203 } catch (InvalidAlgorithmParameterException | |
201 NoSuchAlgorithmException exp) { |
204 NoSuchAlgorithmException | RuntimeException exp) { |
|
205 // Signature.getParameters() may throw RuntimeException. |
202 mediator = false; |
206 mediator = false; |
203 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
207 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
204 SSLLogger.warning( |
208 SSLLogger.warning( |
205 "RSASSA-PSS signature with " + hash + |
209 "RSASSA-PSS signature with " + hash + |
206 " is not supported by the underlying providers", exp); |
210 " is not supported by the underlying providers", exp); |
207 } |
211 } |
208 } |
212 } |
209 |
213 |
210 this.isAvailable = mediator; |
214 this.isAvailable = mediator; |
211 this.parameterSpec = mediator ? pssParamSpec : null; |
215 this.parameterSpec = mediator ? pssParamSpec : null; |
212 } |
216 this.parameters = mediator ? pssParams : null; |
213 |
|
214 AlgorithmParameterSpec getParameterSpec() { |
|
215 return parameterSpec; |
|
216 } |
217 } |
217 } |
218 } |
218 |
219 |
219 // performance optimization |
220 // performance optimization |
220 private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET = |
221 private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET = |
253 supportedProtocols, supportedProtocols); |
254 supportedProtocols, supportedProtocols); |
254 } |
255 } |
255 |
256 |
256 private SignatureScheme(int id, String name, |
257 private SignatureScheme(int id, String name, |
257 String algorithm, String keyAlgorithm, |
258 String algorithm, String keyAlgorithm, |
258 SigAlgParamSpec signAlgParamSpec, |
259 SigAlgParamSpec signAlgParams, |
259 NamedGroup namedGroup, int minimalKeySize, |
260 NamedGroup namedGroup, int minimalKeySize, |
260 ProtocolVersion[] supportedProtocols, |
261 ProtocolVersion[] supportedProtocols, |
261 ProtocolVersion[] handshakeSupportedProtocols) { |
262 ProtocolVersion[] handshakeSupportedProtocols) { |
262 this.id = id; |
263 this.id = id; |
263 this.name = name; |
264 this.name = name; |
264 this.algorithm = algorithm; |
265 this.algorithm = algorithm; |
265 this.keyAlgorithm = keyAlgorithm; |
266 this.keyAlgorithm = keyAlgorithm; |
266 this.signAlgParameter = |
267 this.signAlgParams = signAlgParams; |
267 signAlgParamSpec != null ? signAlgParamSpec.parameterSpec : null; |
|
268 this.namedGroup = namedGroup; |
268 this.namedGroup = namedGroup; |
269 this.minimalKeySize = minimalKeySize; |
269 this.minimalKeySize = minimalKeySize; |
270 this.supportedProtocols = Arrays.asList(supportedProtocols); |
270 this.supportedProtocols = Arrays.asList(supportedProtocols); |
271 this.handshakeSupportedProtocols = |
271 this.handshakeSupportedProtocols = |
272 Arrays.asList(handshakeSupportedProtocols); |
272 Arrays.asList(handshakeSupportedProtocols); |
273 |
273 |
274 boolean mediator = true; |
274 boolean mediator = true; |
275 if (signAlgParamSpec != null) { |
275 if (signAlgParams != null) { |
276 mediator = signAlgParamSpec.isAvailable; |
276 mediator = signAlgParams.isAvailable; |
277 } else { |
277 } else { |
278 try { |
278 try { |
279 Signature.getInstance(algorithm); |
279 Signature.getInstance(algorithm); |
280 } catch (Exception e) { |
280 } catch (Exception e) { |
281 mediator = false; |
281 mediator = false; |
329 // Return the size of a SignatureScheme structure in TLS record |
329 // Return the size of a SignatureScheme structure in TLS record |
330 static int sizeInRecord() { |
330 static int sizeInRecord() { |
331 return 2; |
331 return 2; |
332 } |
332 } |
333 |
333 |
|
334 private boolean isPermitted(AlgorithmConstraints constraints) { |
|
335 return constraints.permits(SIGNATURE_PRIMITIVE_SET, |
|
336 this.name, null) && |
|
337 constraints.permits(SIGNATURE_PRIMITIVE_SET, |
|
338 this.keyAlgorithm, null) && |
|
339 constraints.permits(SIGNATURE_PRIMITIVE_SET, |
|
340 this.algorithm, (signAlgParams != null ? |
|
341 signAlgParams.parameters : null)) && |
|
342 (namedGroup != null ? |
|
343 namedGroup.isPermitted(constraints) : true); |
|
344 } |
|
345 |
334 // Get local supported algorithm collection complying to algorithm |
346 // Get local supported algorithm collection complying to algorithm |
335 // constraints. |
347 // constraints. |
336 static List<SignatureScheme> getSupportedAlgorithms( |
348 static List<SignatureScheme> getSupportedAlgorithms( |
337 AlgorithmConstraints constraints, |
349 AlgorithmConstraints constraints, |
338 List<ProtocolVersion> activeProtocols) { |
350 List<ProtocolVersion> activeProtocols) { |
381 "Unsupported signature scheme: " + |
392 "Unsupported signature scheme: " + |
382 SignatureScheme.nameOf(ssid)); |
393 SignatureScheme.nameOf(ssid)); |
383 } |
394 } |
384 } else if (ss.isAvailable && |
395 } else if (ss.isAvailable && |
385 ss.supportedProtocols.contains(protocolVersion) && |
396 ss.supportedProtocols.contains(protocolVersion) && |
386 constraints.permits(SIGNATURE_PRIMITIVE_SET, |
397 ss.isPermitted(constraints)) { |
387 ss.algorithm, null)) { |
|
388 supported.add(ss); |
398 supported.add(ss); |
389 } else { |
399 } else { |
390 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
400 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { |
391 SSLLogger.warning( |
401 SSLLogger.warning( |
392 "Unsupported signature scheme: " + ss.name); |
402 "Unsupported signature scheme: " + ss.name); |
396 |
406 |
397 return supported; |
407 return supported; |
398 } |
408 } |
399 |
409 |
400 static SignatureScheme getPreferableAlgorithm( |
410 static SignatureScheme getPreferableAlgorithm( |
|
411 AlgorithmConstraints constraints, |
401 List<SignatureScheme> schemes, |
412 List<SignatureScheme> schemes, |
402 SignatureScheme certScheme, |
413 SignatureScheme certScheme, |
403 ProtocolVersion version) { |
414 ProtocolVersion version) { |
404 |
415 |
405 for (SignatureScheme ss : schemes) { |
416 for (SignatureScheme ss : schemes) { |
406 if (ss.isAvailable && |
417 if (ss.isAvailable && |
407 ss.handshakeSupportedProtocols.contains(version) && |
418 ss.handshakeSupportedProtocols.contains(version) && |
408 certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) { |
419 certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) && |
409 |
420 ss.isPermitted(constraints)) { |
410 return ss; |
421 return ss; |
411 } |
422 } |
412 } |
423 } |
413 |
424 |
414 return null; |
425 return null; |
415 } |
426 } |
416 |
427 |
417 static SignatureScheme getPreferableAlgorithm( |
428 static SignatureScheme getPreferableAlgorithm( |
|
429 AlgorithmConstraints constraints, |
418 List<SignatureScheme> schemes, |
430 List<SignatureScheme> schemes, |
419 X509Possession x509Possession, |
431 X509Possession x509Possession, |
420 ProtocolVersion version) { |
432 ProtocolVersion version) { |
421 |
433 |
422 PrivateKey signingKey = x509Possession.popPrivateKey; |
434 PrivateKey signingKey = x509Possession.popPrivateKey; |
430 keySize = Integer.MAX_VALUE; |
442 keySize = Integer.MAX_VALUE; |
431 } |
443 } |
432 for (SignatureScheme ss : schemes) { |
444 for (SignatureScheme ss : schemes) { |
433 if (ss.isAvailable && (keySize >= ss.minimalKeySize) && |
445 if (ss.isAvailable && (keySize >= ss.minimalKeySize) && |
434 ss.handshakeSupportedProtocols.contains(version) && |
446 ss.handshakeSupportedProtocols.contains(version) && |
435 keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) { |
447 keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) && |
436 if ((ss.namedGroup != null) && (ss.namedGroup.type == |
448 ss.isPermitted(constraints)) { |
437 NamedGroupType.NAMED_GROUP_ECDHE)) { |
449 if ((ss.namedGroup != null) && (ss.namedGroup.spec == |
|
450 NamedGroupSpec.NAMED_GROUP_ECDHE)) { |
438 ECParameterSpec params = |
451 ECParameterSpec params = |
439 x509Possession.getECParameterSpec(); |
452 x509Possession.getECParameterSpec(); |
440 if (params != null && |
453 if (params != null && |
441 ss.namedGroup == NamedGroup.valueOf(params)) { |
454 ss.namedGroup == NamedGroup.valueOf(params)) { |
442 return ss; |
455 return ss; |
503 } |
516 } |
504 |
517 |
505 Signature signer = Signature.getInstance(algorithm); |
518 Signature signer = Signature.getInstance(algorithm); |
506 if (key instanceof PublicKey) { |
519 if (key instanceof PublicKey) { |
507 SignatureUtil.initVerifyWithParam(signer, (PublicKey)key, |
520 SignatureUtil.initVerifyWithParam(signer, (PublicKey)key, |
508 signAlgParameter); |
521 (signAlgParams != null ? |
|
522 signAlgParams.parameterSpec : null)); |
509 } else { |
523 } else { |
510 SignatureUtil.initSignWithParam(signer, (PrivateKey)key, |
524 SignatureUtil.initSignWithParam(signer, (PrivateKey)key, |
511 signAlgParameter, null); |
525 (signAlgParams != null ? |
|
526 signAlgParams.parameterSpec : null), |
|
527 null); |
512 } |
528 } |
513 |
529 |
514 return signer; |
530 return signer; |
515 } |
531 } |
516 } |
532 } |