jdk/src/share/classes/javax/crypto/Cipher.java
changeset 10336 0bb1999251f8
parent 9275 1df1f7dfab7f
child 11671 60fdf1412864
equal deleted inserted replaced
10335:3c7eda3ab2f5 10336:0bb1999251f8
    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) {
   725                     s = firstService;
   722                     s = firstService;
   726                     thisSpi = firstSpi;
   723                     thisSpi = firstSpi;
   727                     firstService = null;
   724                     firstService = null;
   728                     firstSpi = null;
   725                     firstSpi = null;
   729                 } else {
   726                 } else {
   730                     s = (Service)serviceIterator.next();
   727                     s = serviceIterator.next();
   731                     thisSpi = null;
   728                     thisSpi = null;
   732                 }
   729                 }
   733                 if (JceSecurity.canUseProvider(s.getProvider()) == false) {
   730                 if (JceSecurity.canUseProvider(s.getProvider()) == false) {
   734                     continue;
   731                     continue;
   735                 }
   732                 }
   819                     s = firstService;
   816                     s = firstService;
   820                     thisSpi = firstSpi;
   817                     thisSpi = firstSpi;
   821                     firstService = null;
   818                     firstService = null;
   822                     firstSpi = null;
   819                     firstSpi = null;
   823                 } else {
   820                 } else {
   824                     s = (Service)serviceIterator.next();
   821                     s = serviceIterator.next();
   825                     thisSpi = null;
   822                     thisSpi = null;
   826                 }
   823                 }
   827                 // if provider says it does not support this key, ignore it
   824                 // if provider says it does not support this key, ignore it
   828                 if (s.supportsParameter(key) == false) {
   825                 if (s.supportsParameter(key) == false) {
   829                     continue;
   826                     continue;
  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;