26 package javax.crypto; |
26 package javax.crypto; |
27 |
27 |
28 import java.util.*; |
28 import java.util.*; |
29 import java.util.regex.*; |
29 import java.util.regex.*; |
30 |
30 |
31 import static java.util.Locale.ENGLISH; |
|
32 |
31 |
33 import java.security.*; |
32 import java.security.*; |
34 import java.security.Provider.Service; |
33 import java.security.Provider.Service; |
35 import java.security.spec.AlgorithmParameterSpec; |
34 import java.security.spec.AlgorithmParameterSpec; |
36 import java.security.spec.InvalidParameterSpecException; |
35 import java.security.spec.InvalidParameterSpecException; |
42 import java.nio.ByteBuffer; |
41 import java.nio.ByteBuffer; |
43 import java.nio.ReadOnlyBufferException; |
42 import java.nio.ReadOnlyBufferException; |
44 |
43 |
45 import sun.security.util.Debug; |
44 import sun.security.util.Debug; |
46 import sun.security.jca.*; |
45 import sun.security.jca.*; |
47 import sun.security.jca.GetInstance.Instance; |
|
48 |
46 |
49 /** |
47 /** |
50 * This class provides the functionality of a cryptographic cipher for |
48 * This class provides the functionality of a cryptographic cipher for |
51 * encryption and decryption. It forms the core of the Java Cryptographic |
49 * encryption and decryption. It forms the core of the Java Cryptographic |
52 * Extension (JCE) framework. |
50 * Extension (JCE) framework. |
225 // null once provider is selected |
223 // null once provider is selected |
226 private Service firstService; |
224 private Service firstService; |
227 |
225 |
228 // remaining services to try in provider selection |
226 // remaining services to try in provider selection |
229 // null once provider is selected |
227 // null once provider is selected |
230 private Iterator serviceIterator; |
228 private Iterator<Service> serviceIterator; |
231 |
229 |
232 // list of transform Strings to lookup in the provider |
230 // list of transform Strings to lookup in the provider |
233 private List transforms; |
231 private List<Transform> transforms; |
234 |
232 |
235 private final Object lock; |
233 private final Object lock; |
236 |
234 |
237 /** |
235 /** |
238 * Creates a Cipher object. |
236 * Creates a Cipher object. |
269 this.cryptoPerm = CryptoAllPermission.INSTANCE; |
267 this.cryptoPerm = CryptoAllPermission.INSTANCE; |
270 this.lock = null; |
268 this.lock = null; |
271 } |
269 } |
272 |
270 |
273 private Cipher(CipherSpi firstSpi, Service firstService, |
271 private Cipher(CipherSpi firstSpi, Service firstService, |
274 Iterator serviceIterator, String transformation, List transforms) { |
272 Iterator<Service> serviceIterator, String transformation, |
|
273 List<Transform> transforms) { |
275 this.firstSpi = firstSpi; |
274 this.firstSpi = firstSpi; |
276 this.firstService = firstService; |
275 this.firstService = firstService; |
277 this.serviceIterator = serviceIterator; |
276 this.serviceIterator = serviceIterator; |
278 this.transforms = transforms; |
277 this.transforms = transforms; |
279 this.transformation = transformation; |
278 this.transformation = transformation; |
390 return matches(regexp, value) ? S_YES : S_NO; |
389 return matches(regexp, value) ? S_YES : S_NO; |
391 } |
390 } |
392 |
391 |
393 // Map<String,Pattern> for previously compiled patterns |
392 // Map<String,Pattern> for previously compiled patterns |
394 // XXX use ConcurrentHashMap once available |
393 // XXX use ConcurrentHashMap once available |
395 private final static Map patternCache = |
394 private final static Map<String, Pattern> patternCache = |
396 Collections.synchronizedMap(new HashMap()); |
395 Collections.synchronizedMap(new HashMap<String, Pattern>()); |
397 |
396 |
398 private static boolean matches(String regexp, String str) { |
397 private static boolean matches(String regexp, String str) { |
399 Pattern pattern = (Pattern)patternCache.get(regexp); |
398 Pattern pattern = patternCache.get(regexp); |
400 if (pattern == null) { |
399 if (pattern == null) { |
401 pattern = Pattern.compile(regexp); |
400 pattern = Pattern.compile(regexp); |
402 patternCache.put(regexp, pattern); |
401 patternCache.put(regexp, pattern); |
403 } |
402 } |
404 return pattern.matcher(str.toUpperCase(Locale.ENGLISH)).matches(); |
403 return pattern.matcher(str.toUpperCase(Locale.ENGLISH)).matches(); |
405 } |
404 } |
406 |
405 |
407 } |
406 } |
408 |
407 |
409 private static List getTransforms(String transformation) |
408 private static List<Transform> getTransforms(String transformation) |
410 throws NoSuchAlgorithmException { |
409 throws NoSuchAlgorithmException { |
411 String[] parts = tokenizeTransformation(transformation); |
410 String[] parts = tokenizeTransformation(transformation); |
412 |
411 |
413 String alg = parts[0]; |
412 String alg = parts[0]; |
414 String mode = parts[1]; |
413 String mode = parts[1]; |
424 // DES |
423 // DES |
425 Transform tr = new Transform(alg, "", null, null); |
424 Transform tr = new Transform(alg, "", null, null); |
426 return Collections.singletonList(tr); |
425 return Collections.singletonList(tr); |
427 } else { // if ((mode != null) && (pad != null)) { |
426 } else { // if ((mode != null) && (pad != null)) { |
428 // DES/CBC/PKCS5Padding |
427 // DES/CBC/PKCS5Padding |
429 List list = new ArrayList(4); |
428 List<Transform> list = new ArrayList<>(4); |
430 list.add(new Transform(alg, "/" + mode + "/" + pad, null, null)); |
429 list.add(new Transform(alg, "/" + mode + "/" + pad, null, null)); |
431 list.add(new Transform(alg, "/" + mode, null, pad)); |
430 list.add(new Transform(alg, "/" + mode, null, pad)); |
432 list.add(new Transform(alg, "//" + pad, mode, null)); |
431 list.add(new Transform(alg, "//" + pad, mode, null)); |
433 list.add(new Transform(alg, "", mode, pad)); |
432 list.add(new Transform(alg, "", mode, pad)); |
434 return list; |
433 return list; |
435 } |
434 } |
436 } |
435 } |
437 |
436 |
438 // get the transform matching the specified service |
437 // get the transform matching the specified service |
439 private static Transform getTransform(Service s, List transforms) { |
438 private static Transform getTransform(Service s, |
|
439 List<Transform> transforms) { |
440 String alg = s.getAlgorithm().toUpperCase(Locale.ENGLISH); |
440 String alg = s.getAlgorithm().toUpperCase(Locale.ENGLISH); |
441 for (Iterator t = transforms.iterator(); t.hasNext(); ) { |
441 for (Transform tr : transforms) { |
442 Transform tr = (Transform)t.next(); |
|
443 if (alg.endsWith(tr.suffix)) { |
442 if (alg.endsWith(tr.suffix)) { |
444 return tr; |
443 return tr; |
445 } |
444 } |
446 } |
445 } |
447 return null; |
446 return null; |
480 * @see java.security.Provider |
479 * @see java.security.Provider |
481 */ |
480 */ |
482 public static final Cipher getInstance(String transformation) |
481 public static final Cipher getInstance(String transformation) |
483 throws NoSuchAlgorithmException, NoSuchPaddingException |
482 throws NoSuchAlgorithmException, NoSuchPaddingException |
484 { |
483 { |
485 List transforms = getTransforms(transformation); |
484 List<Transform> transforms = getTransforms(transformation); |
486 List cipherServices = new ArrayList(transforms.size()); |
485 List<ServiceId> cipherServices = new ArrayList<>(transforms.size()); |
487 for (Iterator t = transforms.iterator(); t.hasNext(); ) { |
486 for (Transform transform : transforms) { |
488 Transform transform = (Transform)t.next(); |
|
489 cipherServices.add(new ServiceId("Cipher", transform.transform)); |
487 cipherServices.add(new ServiceId("Cipher", transform.transform)); |
490 } |
488 } |
491 List services = GetInstance.getServices(cipherServices); |
489 List<Service> services = GetInstance.getServices(cipherServices); |
492 // make sure there is at least one service from a signed provider |
490 // make sure there is at least one service from a signed provider |
493 // and that it can use the specified mode and padding |
491 // and that it can use the specified mode and padding |
494 Iterator t = services.iterator(); |
492 Iterator<Service> t = services.iterator(); |
495 Exception failure = null; |
493 Exception failure = null; |
496 while (t.hasNext()) { |
494 while (t.hasNext()) { |
497 Service s = (Service)t.next(); |
495 Service s = t.next(); |
498 if (JceSecurity.canUseProvider(s.getProvider()) == false) { |
496 if (JceSecurity.canUseProvider(s.getProvider()) == false) { |
499 continue; |
497 continue; |
500 } |
498 } |
501 Transform tr = getTransform(s, transforms); |
499 Transform tr = getTransform(s, transforms); |
502 if (tr == null) { |
500 if (tr == null) { |
618 { |
616 { |
619 if (provider == null) { |
617 if (provider == null) { |
620 throw new IllegalArgumentException("Missing provider"); |
618 throw new IllegalArgumentException("Missing provider"); |
621 } |
619 } |
622 Exception failure = null; |
620 Exception failure = null; |
623 List transforms = getTransforms(transformation); |
621 List<Transform> transforms = getTransforms(transformation); |
624 boolean providerChecked = false; |
622 boolean providerChecked = false; |
625 String paddingError = null; |
623 String paddingError = null; |
626 for (Iterator t = transforms.iterator(); t.hasNext();) { |
624 for (Transform tr : transforms) { |
627 Transform tr = (Transform)t.next(); |
|
628 Service s = provider.getService("Cipher", tr.transform); |
625 Service s = provider.getService("Cipher", tr.transform); |
629 if (s == null) { |
626 if (s == null) { |
630 continue; |
627 continue; |
631 } |
628 } |
632 if (providerChecked == false) { |
629 if (providerChecked == false) { |
1620 // type X.509. |
1617 // type X.509. |
1621 if (certificate instanceof java.security.cert.X509Certificate) { |
1618 if (certificate instanceof java.security.cert.X509Certificate) { |
1622 // Check whether the cert has a key usage extension |
1619 // Check whether the cert has a key usage extension |
1623 // marked as a critical extension. |
1620 // marked as a critical extension. |
1624 X509Certificate cert = (X509Certificate)certificate; |
1621 X509Certificate cert = (X509Certificate)certificate; |
1625 Set critSet = cert.getCriticalExtensionOIDs(); |
1622 Set<String> critSet = cert.getCriticalExtensionOIDs(); |
1626 |
1623 |
1627 if (critSet != null && !critSet.isEmpty() |
1624 if (critSet != null && !critSet.isEmpty() |
1628 && critSet.contains(KEY_USAGE_EXTENSION_OID)) { |
1625 && critSet.contains(KEY_USAGE_EXTENSION_OID)) { |
1629 boolean[] keyUsageInfo = cert.getKeyUsage(); |
1626 boolean[] keyUsageInfo = cert.getKeyUsage(); |
1630 // keyUsageInfo[2] is for keyEncipherment; |
1627 // keyUsageInfo[2] is for keyEncipherment; |