jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java
changeset 31689 1201792aa3a3
parent 28974 71fe221460f5
child 32649 2ee9017c7597
equal deleted inserted replaced
31688:42c9b194a469 31689:1201792aa3a3
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package sun.security.util;
    26 package sun.security.util;
    27 
    27 
    28 import java.security.AlgorithmConstraints;
       
    29 import java.security.CryptoPrimitive;
    28 import java.security.CryptoPrimitive;
    30 import java.security.AlgorithmParameters;
    29 import java.security.AlgorithmParameters;
    31 
       
    32 import java.security.Key;
    30 import java.security.Key;
    33 import java.security.Security;
       
    34 import java.security.PrivilegedAction;
       
    35 import java.security.AccessController;
       
    36 
       
    37 import java.util.Locale;
    31 import java.util.Locale;
    38 import java.util.Set;
    32 import java.util.Set;
    39 import java.util.Collections;
    33 import java.util.Collections;
    40 import java.util.HashSet;
    34 import java.util.HashSet;
    41 import java.util.Map;
    35 import java.util.Map;
    47  * Algorithm constraints for disabled algorithms property
    41  * Algorithm constraints for disabled algorithms property
    48  *
    42  *
    49  * See the "jdk.certpath.disabledAlgorithms" specification in java.security
    43  * See the "jdk.certpath.disabledAlgorithms" specification in java.security
    50  * for the syntax of the disabled algorithm string.
    44  * for the syntax of the disabled algorithm string.
    51  */
    45  */
    52 public class DisabledAlgorithmConstraints implements AlgorithmConstraints {
    46 public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
    53 
    47 
    54     // the known security property, jdk.certpath.disabledAlgorithms
    48     // the known security property, jdk.certpath.disabledAlgorithms
    55     public final static String PROPERTY_CERTPATH_DISABLED_ALGS =
    49     public final static String PROPERTY_CERTPATH_DISABLED_ALGS =
    56             "jdk.certpath.disabledAlgorithms";
    50             "jdk.certpath.disabledAlgorithms";
    57 
    51 
    62     private final static Map<String, String[]> disabledAlgorithmsMap =
    56     private final static Map<String, String[]> disabledAlgorithmsMap =
    63                                                             new HashMap<>();
    57                                                             new HashMap<>();
    64     private final static Map<String, KeySizeConstraints> keySizeConstraintsMap =
    58     private final static Map<String, KeySizeConstraints> keySizeConstraintsMap =
    65                                                             new HashMap<>();
    59                                                             new HashMap<>();
    66 
    60 
    67     private String[] disabledAlgorithms;
    61     private final String[] disabledAlgorithms;
    68     private KeySizeConstraints keySizeConstraints;
    62     private final KeySizeConstraints keySizeConstraints;
    69 
    63 
    70     /**
    64     /**
    71      * Initialize algorithm constraints with the specified security property.
    65      * Initialize algorithm constraints with the specified security property.
    72      *
    66      *
    73      * @param propertyName the security property name that define the disabled
    67      * @param propertyName the security property name that define the disabled
    74      *        algorithm constraints
    68      *        algorithm constraints
    75      */
    69      */
    76     public DisabledAlgorithmConstraints(String propertyName) {
    70     public DisabledAlgorithmConstraints(String propertyName) {
    77         // Both disabledAlgorithmsMap and keySizeConstraintsMap are
    71         this(propertyName, new AlgorithmDecomposer());
    78         // synchronized with the lock of disabledAlgorithmsMap.
    72     }
    79         synchronized (disabledAlgorithmsMap) {
    73 
    80             if(!disabledAlgorithmsMap.containsKey(propertyName)) {
    74     public DisabledAlgorithmConstraints(String propertyName,
    81                 loadDisabledAlgorithmsMap(propertyName);
    75             AlgorithmDecomposer decomposer) {
    82             }
    76         super(decomposer);
    83 
    77         disabledAlgorithms = getAlgorithms(disabledAlgorithmsMap, propertyName);
    84             disabledAlgorithms = disabledAlgorithmsMap.get(propertyName);
    78         keySizeConstraints = getKeySizeConstraints(disabledAlgorithms,
    85             keySizeConstraints = keySizeConstraintsMap.get(propertyName);
    79                 propertyName);
    86         }
       
    87     }
    80     }
    88 
    81 
    89     @Override
    82     @Override
    90     final public boolean permits(Set<CryptoPrimitive> primitives,
    83     final public boolean permits(Set<CryptoPrimitive> primitives,
    91             String algorithm, AlgorithmParameters parameters) {
    84             String algorithm, AlgorithmParameters parameters) {
    92 
    85 
    93         if (algorithm == null || algorithm.length() == 0) {
       
    94             throw new IllegalArgumentException("No algorithm name specified");
       
    95         }
       
    96 
       
    97         if (primitives == null || primitives.isEmpty()) {
    86         if (primitives == null || primitives.isEmpty()) {
    98             throw new IllegalArgumentException(
    87             throw new IllegalArgumentException(
    99                         "No cryptographic primitive specified");
    88                         "No cryptographic primitive specified");
   100         }
    89         }
   101 
    90 
   102         Set<String> elements = null;
    91         return checkAlgorithm(disabledAlgorithms, algorithm, decomposer);
   103         for (String disabled : disabledAlgorithms) {
       
   104             if (disabled == null || disabled.isEmpty()) {
       
   105                 continue;
       
   106             }
       
   107 
       
   108             // check the full name
       
   109             if (disabled.equalsIgnoreCase(algorithm)) {
       
   110                 return false;
       
   111             }
       
   112 
       
   113             // decompose the algorithm into sub-elements
       
   114             if (elements == null) {
       
   115                 elements = decomposes(algorithm);
       
   116             }
       
   117 
       
   118             // check the items of the algorithm
       
   119             for (String element : elements) {
       
   120                 if (disabled.equalsIgnoreCase(element)) {
       
   121                     return false;
       
   122                 }
       
   123             }
       
   124         }
       
   125 
       
   126         return true;
       
   127     }
    92     }
   128 
    93 
   129     @Override
    94     @Override
   130     final public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
    95     final public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
   131         return checkConstraints(primitives, "", key, null);
    96         return checkConstraints(primitives, "", key, null);
   138         if (algorithm == null || algorithm.length() == 0) {
   103         if (algorithm == null || algorithm.length() == 0) {
   139             throw new IllegalArgumentException("No algorithm name specified");
   104             throw new IllegalArgumentException("No algorithm name specified");
   140         }
   105         }
   141 
   106 
   142         return checkConstraints(primitives, algorithm, key, parameters);
   107         return checkConstraints(primitives, algorithm, key, parameters);
   143     }
       
   144 
       
   145     /**
       
   146      * Decompose the standard algorithm name into sub-elements.
       
   147      * <p>
       
   148      * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA"
       
   149      * so that we can check the "SHA1" and "RSA" algorithm constraints
       
   150      * separately.
       
   151      * <p>
       
   152      * Please override the method if need to support more name pattern.
       
   153      */
       
   154     protected Set<String> decomposes(String algorithm) {
       
   155         if (algorithm == null || algorithm.length() == 0) {
       
   156             return new HashSet<String>();
       
   157         }
       
   158 
       
   159         // algorithm/mode/padding
       
   160         Pattern transPattern = Pattern.compile("/");
       
   161         String[] transTockens = transPattern.split(algorithm);
       
   162 
       
   163         Set<String> elements = new HashSet<String>();
       
   164         for (String transTocken : transTockens) {
       
   165             if (transTocken == null || transTocken.length() == 0) {
       
   166                 continue;
       
   167             }
       
   168 
       
   169             // PBEWith<digest>And<encryption>
       
   170             // PBEWith<prf>And<encryption>
       
   171             // OAEPWith<digest>And<mgf>Padding
       
   172             // <digest>with<encryption>
       
   173             // <digest>with<encryption>and<mgf>
       
   174             // <digest>with<encryption>in<format>
       
   175             Pattern pattern =
       
   176                     Pattern.compile("with|and|in", Pattern.CASE_INSENSITIVE);
       
   177             String[] tokens = pattern.split(transTocken);
       
   178 
       
   179             for (String token : tokens) {
       
   180                 if (token == null || token.length() == 0) {
       
   181                     continue;
       
   182                 }
       
   183 
       
   184                 elements.add(token);
       
   185             }
       
   186         }
       
   187 
       
   188         // In Java standard algorithm name specification, for different
       
   189         // purpose, the SHA-1 and SHA-2 algorithm names are different. For
       
   190         // example, for MessageDigest, the standard name is "SHA-256", while
       
   191         // for Signature, the digest algorithm component is "SHA256" for
       
   192         // signature algorithm "SHA256withRSA". So we need to check both
       
   193         // "SHA-256" and "SHA256" to make the right constraint checking.
       
   194 
       
   195         // handle special name: SHA-1 and SHA1
       
   196         if (elements.contains("SHA1") && !elements.contains("SHA-1")) {
       
   197             elements.add("SHA-1");
       
   198         }
       
   199         if (elements.contains("SHA-1") && !elements.contains("SHA1")) {
       
   200             elements.add("SHA1");
       
   201         }
       
   202 
       
   203         // handle special name: SHA-224 and SHA224
       
   204         if (elements.contains("SHA224") && !elements.contains("SHA-224")) {
       
   205             elements.add("SHA-224");
       
   206         }
       
   207         if (elements.contains("SHA-224") && !elements.contains("SHA224")) {
       
   208             elements.add("SHA224");
       
   209         }
       
   210 
       
   211         // handle special name: SHA-256 and SHA256
       
   212         if (elements.contains("SHA256") && !elements.contains("SHA-256")) {
       
   213             elements.add("SHA-256");
       
   214         }
       
   215         if (elements.contains("SHA-256") && !elements.contains("SHA256")) {
       
   216             elements.add("SHA256");
       
   217         }
       
   218 
       
   219         // handle special name: SHA-384 and SHA384
       
   220         if (elements.contains("SHA384") && !elements.contains("SHA-384")) {
       
   221             elements.add("SHA-384");
       
   222         }
       
   223         if (elements.contains("SHA-384") && !elements.contains("SHA384")) {
       
   224             elements.add("SHA384");
       
   225         }
       
   226 
       
   227         // handle special name: SHA-512 and SHA512
       
   228         if (elements.contains("SHA512") && !elements.contains("SHA-512")) {
       
   229             elements.add("SHA-512");
       
   230         }
       
   231         if (elements.contains("SHA-512") && !elements.contains("SHA512")) {
       
   232             elements.add("SHA512");
       
   233         }
       
   234 
       
   235         return elements;
       
   236     }
   108     }
   237 
   109 
   238     // Check algorithm constraints
   110     // Check algorithm constraints
   239     private boolean checkConstraints(Set<CryptoPrimitive> primitives,
   111     private boolean checkConstraints(Set<CryptoPrimitive> primitives,
   240             String algorithm, Key key, AlgorithmParameters parameters) {
   112             String algorithm, Key key, AlgorithmParameters parameters) {
   262         }
   134         }
   263 
   135 
   264         return true;
   136         return true;
   265     }
   137     }
   266 
   138 
   267     // Get disabled algorithm constraints from the specified security property.
   139     private static KeySizeConstraints getKeySizeConstraints(
   268     private static void loadDisabledAlgorithmsMap(
   140             String[] disabledAlgorithms, String propertyName) {
   269             final String propertyName) {
   141         synchronized (keySizeConstraintsMap) {
   270 
   142             if(!keySizeConstraintsMap.containsKey(propertyName)) {
   271         String property = AccessController.doPrivileged(
   143                 // map the key constraints
   272             new PrivilegedAction<String>() {
   144                 KeySizeConstraints keySizeConstraints =
   273                 public String run() {
   145                         new KeySizeConstraints(disabledAlgorithms);
   274                     return Security.getProperty(propertyName);
   146                 keySizeConstraintsMap.put(propertyName, keySizeConstraints);
   275                 }
   147             }
   276             });
   148 
   277 
   149             return keySizeConstraintsMap.get(propertyName);
   278         String[] algorithmsInProperty = null;
   150         }
   279 
       
   280         if (property != null && !property.isEmpty()) {
       
   281 
       
   282             // remove double quote marks from beginning/end of the property
       
   283             if (property.charAt(0) == '"' &&
       
   284                     property.charAt(property.length() - 1) == '"') {
       
   285                 property = property.substring(1, property.length() - 1);
       
   286             }
       
   287 
       
   288             algorithmsInProperty = property.split(",");
       
   289             for (int i = 0; i < algorithmsInProperty.length; i++) {
       
   290                 algorithmsInProperty[i] = algorithmsInProperty[i].trim();
       
   291             }
       
   292         }
       
   293 
       
   294         // map the disabled algorithms
       
   295         if (algorithmsInProperty == null) {
       
   296             algorithmsInProperty = new String[0];
       
   297         }
       
   298         disabledAlgorithmsMap.put(propertyName, algorithmsInProperty);
       
   299 
       
   300         // map the key constraints
       
   301         KeySizeConstraints keySizeConstraints =
       
   302             new KeySizeConstraints(algorithmsInProperty);
       
   303         keySizeConstraintsMap.put(propertyName, keySizeConstraints);
       
   304     }
   151     }
   305 
   152 
   306     /**
   153     /**
   307      * key constraints
   154      * key constraints
   308      */
   155      */