| /* | |
| * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| package javax.crypto; | |
| import java.io.Serial; | |
| import java.security.*; | |
| import java.security.spec.AlgorithmParameterSpec; | |
| import java.io.Serializable; | |
| import java.util.Enumeration; | |
| import java.util.Objects; | |
| import java.util.Vector; | |
| import javax.crypto.spec.*; | |
| /** | |
| * The {@code CryptoPermission} class extends the | |
| * {@code java.security.Permission} class. A | |
| * {@code CryptoPermission} object is used to represent | |
| * the ability of an application to use certain | |
| * algorithms with certain key sizes and other | |
| * restrictions in certain environments. | |
| * | |
| * @see java.security.Permission | |
| * | |
| * @author Jan Luehe | |
| * @author Sharon Liu | |
| * @since 1.4 | |
| */ | |
| class CryptoPermission extends java.security.Permission { | |
| @java.io.Serial | |
| private static final long serialVersionUID = 8987399626114087514L; | |
| private final String alg; | |
| private int maxKeySize = Integer.MAX_VALUE; // no restriction on maxKeySize | |
| private String exemptionMechanism = null; | |
| @SuppressWarnings("serial") // Not statically typed as Serializable | |
| private AlgorithmParameterSpec algParamSpec = null; | |
| private boolean checkParam = false; // no restriction on param | |
| static final String ALG_NAME_WILDCARD = "*"; | |
| /** | |
| * Constructor that takes an algorithm name. | |
| * | |
| * This constructor implies that the given algorithm can be | |
| * used without any restrictions. | |
| * | |
| * @param alg the algorithm name. | |
| */ | |
| CryptoPermission(String alg) { | |
| super(null); | |
| this.alg = alg; | |
| } | |
| /** | |
| * Constructor that takes an algorithm name and a maximum | |
| * key size. | |
| * | |
| * This constructor implies that the given algorithm can be | |
| * used with a key size up to {@code maxKeySize}. | |
| * | |
| * @param alg the algorithm name. | |
| * | |
| * @param maxKeySize the maximum allowable key size, | |
| * specified in number of bits. | |
| */ | |
| CryptoPermission(String alg, int maxKeySize) { | |
| super(null); | |
| this.alg = alg; | |
| this.maxKeySize = maxKeySize; | |
| } | |
| /** | |
| * Constructor that takes an algorithm name, a maximum | |
| * key size, and an {@code AlgorithmParameterSpec} object. | |
| * | |
| * This constructor implies that the given algorithm can be | |
| * used with a key size up to {@code maxKeySize}, and | |
| * algorithm | |
| * parameters up to the limits set in {@code algParamSpec}. | |
| * | |
| * @param alg the algorithm name. | |
| * | |
| * @param maxKeySize the maximum allowable key size, | |
| * specified in number of bits. | |
| * | |
| * @param algParamSpec the limits for allowable algorithm | |
| * parameters. | |
| */ | |
| CryptoPermission(String alg, | |
| int maxKeySize, | |
| AlgorithmParameterSpec algParamSpec) { | |
| super(null); | |
| this.alg = alg; | |
| this.maxKeySize = maxKeySize; | |
| this.checkParam = true; | |
| this.algParamSpec = algParamSpec; | |
| } | |
| /** | |
| * Constructor that takes an algorithm name and the name of | |
| * an exemption mechanism. | |
| * | |
| * This constructor implies that the given algorithm can be | |
| * used without any key size or algorithm parameter restrictions | |
| * provided that the specified exemption mechanism is enforced. | |
| * | |
| * @param alg the algorithm name. | |
| * | |
| * @param exemptionMechanism the name of the exemption mechanism. | |
| */ | |
| CryptoPermission(String alg, | |
| String exemptionMechanism) { | |
| super(null); | |
| this.alg = alg; | |
| this.exemptionMechanism = exemptionMechanism; | |
| } | |
| /** | |
| * Constructor that takes an algorithm name, a maximum key | |
| * size, and the name of an exemption mechanism. | |
| * | |
| * This constructor implies that the given algorithm can be | |
| * used with a key size up to {@code maxKeySize} | |
| * provided that the | |
| * specified exemption mechanism is enforced. | |
| * | |
| * @param alg the algorithm name. | |
| * @param maxKeySize the maximum allowable key size, | |
| * specified in number of bits. | |
| * @param exemptionMechanism the name of the exemption | |
| * mechanism. | |
| */ | |
| CryptoPermission(String alg, | |
| int maxKeySize, | |
| String exemptionMechanism) { | |
| super(null); | |
| this.alg = alg; | |
| this.exemptionMechanism = exemptionMechanism; | |
| this.maxKeySize = maxKeySize; | |
| } | |
| /** | |
| * Constructor that takes an algorithm name, a maximum key | |
| * size, the name of an exemption mechanism, and an | |
| * {@code AlgorithmParameterSpec} object. | |
| * | |
| * This constructor implies that the given algorithm can be | |
| * used with a key size up to {@code maxKeySize} | |
| * and algorithm | |
| * parameters up to the limits set in {@code algParamSpec} | |
| * provided that | |
| * the specified exemption mechanism is enforced. | |
| * | |
| * @param alg the algorithm name. | |
| * @param maxKeySize the maximum allowable key size, | |
| * specified in number of bits. | |
| * @param algParamSpec the limit for allowable algorithm | |
| * parameter spec. | |
| * @param exemptionMechanism the name of the exemption | |
| * mechanism. | |
| */ | |
| CryptoPermission(String alg, | |
| int maxKeySize, | |
| AlgorithmParameterSpec algParamSpec, | |
| String exemptionMechanism) { | |
| super(null); | |
| this.alg = alg; | |
| this.exemptionMechanism = exemptionMechanism; | |
| this.maxKeySize = maxKeySize; | |
| this.checkParam = true; | |
| this.algParamSpec = algParamSpec; | |
| } | |
| /** | |
| * Checks if the specified permission is "implied" by | |
| * this object. | |
| * <p> | |
| * More specifically, this method returns {@code true} if: | |
| * <ul> | |
| * <li> <i>p</i> is an instance of {@code CryptoPermission}, and</li> | |
| * <li> <i>p</i>'s algorithm name equals or (in the case of wildcards) | |
| * is implied by this permission's algorithm name, and</li> | |
| * <li> <i>p</i>'s maximum allowable key size is less or | |
| * equal to this permission's maximum allowable key size, and</li> | |
| * <li> <i>p</i>'s algorithm parameter spec equals or is | |
| * implied by this permission's algorithm parameter spec, and</li> | |
| * <li> <i>p</i>'s exemptionMechanism equals or | |
| * is implied by this permission's | |
| * exemptionMechanism (a {@code null} exemption mechanism | |
| * implies any other exemption mechanism).</li> | |
| * </ul> | |
| * | |
| * @param p the permission to check against. | |
| * | |
| * @return {@code true} if the specified permission is equal to or | |
| * implied by this permission, {@code false} otherwise. | |
| */ | |
| public boolean implies(Permission p) { | |
| if (!(p instanceof CryptoPermission cp)) | |
| return false; | |
| if ((!alg.equalsIgnoreCase(cp.alg)) && | |
| (!alg.equalsIgnoreCase(ALG_NAME_WILDCARD))) { | |
| return false; | |
| } | |
| // alg is the same as cp's alg or | |
| // alg is a wildcard. | |
| if (cp.maxKeySize <= this.maxKeySize) { | |
| // check algParamSpec. | |
| if (!impliesParameterSpec(cp.checkParam, cp.algParamSpec)) { | |
| return false; | |
| } | |
| // check exemptionMechanism. | |
| return impliesExemptionMechanism(cp.exemptionMechanism); | |
| } | |
| return false; | |
| } | |
| /** | |
| * Checks two {@code CryptoPermission} objects for equality. | |
| * Checks that {@code obj} is a {@code CryptoPermission} | |
| * object, and has the same algorithm name, | |
| * exemption mechanism name, maximum allowable key size and | |
| * algorithm parameter spec as this object. | |
| * @param obj the object to test for equality with this object. | |
| * @return {@code true} if {@code obj} is equal to this object. | |
| */ | |
| @Override | |
| public boolean equals(Object obj) { | |
| if (obj == this) | |
| return true; | |
| if (!(obj instanceof CryptoPermission that)) | |
| return false; | |
| if (!(alg.equalsIgnoreCase(that.alg)) || | |
| (maxKeySize != that.maxKeySize)) { | |
| return false; | |
| } | |
| if (this.checkParam != that.checkParam) { | |
| return false; | |
| } | |
| return Objects.equals(this.exemptionMechanism, that.exemptionMechanism) | |
| && Objects.equals(this.algParamSpec, that.algParamSpec); | |
| } | |
| /** | |
| * {@return the hash code value for this object} | |
| */ | |
| @Override | |
| public int hashCode() { | |
| return alg.hashCode() | |
| ^ maxKeySize | |
| ^ Objects.hashCode(exemptionMechanism) | |
| ^ (checkParam ? 100 : 0) | |
| ^ Objects.hashCode(algParamSpec); | |
| } | |
| /** | |
| * There is no action defined for a {@code CryptoPermission} | |
| * object. | |
| */ | |
| public String getActions() | |
| { | |
| return null; | |
| } | |
| /** | |
| * Returns a new {@code PermissionCollection} object for storing | |
| * {@code CryptoPermission} objects. | |
| * | |
| * @return a new {@code PermissionCollection} object suitable for storing | |
| * CryptoPermissions. | |
| */ | |
| public PermissionCollection newPermissionCollection() { | |
| return new CryptoPermissionCollection(); | |
| } | |
| /** | |
| * Returns the algorithm name associated with | |
| * this {@code CryptoPermission} object. | |
| */ | |
| final String getAlgorithm() { | |
| return alg; | |
| } | |
| /** | |
| * Returns the exemption mechanism name | |
| * associated with this {@code CryptoPermission} | |
| * object. | |
| */ | |
| final String getExemptionMechanism() { | |
| return exemptionMechanism; | |
| } | |
| /** | |
| * Returns the maximum allowable key size associated | |
| * with this {@code CryptoPermission} object. | |
| */ | |
| final int getMaxKeySize() { | |
| return maxKeySize; | |
| } | |
| /** | |
| * Returns {@code true} if there is a limitation on the | |
| * {@code AlgorithmParameterSpec} associated with this | |
| * {@code CryptoPermission} object and {@code false} if otherwise. | |
| */ | |
| final boolean getCheckParam() { | |
| return checkParam; | |
| } | |
| /** | |
| * Returns the AlgorithmParameterSpec | |
| * associated with this CryptoPermission | |
| * object. | |
| */ | |
| final AlgorithmParameterSpec getAlgorithmParameterSpec() { | |
| return algParamSpec; | |
| } | |
| /** | |
| * Returns a string describing this {@code CryptoPermission} object. | |
| * The convention is to specify the class name, the algorithm name, | |
| * the maximum allowable key size, and the name of the exemption mechanism, | |
| * in the following | |
| * format: '("ClassName" "algorithm" "keysize" "exemption_mechanism")'. | |
| * | |
| * @return information about this {@code CryptoPermission} object. | |
| */ | |
| public String toString() { | |
| StringBuilder buf = new StringBuilder(100); | |
| buf.append("(CryptoPermission " + alg + " " + maxKeySize); | |
| if (algParamSpec != null) { | |
| if (algParamSpec instanceof RC2ParameterSpec) { | |
| buf.append(" , effective " + | |
| ((RC2ParameterSpec)algParamSpec).getEffectiveKeyBits()); | |
| } else if (algParamSpec instanceof RC5ParameterSpec) { | |
| buf.append(" , rounds " + | |
| ((RC5ParameterSpec)algParamSpec).getRounds()); | |
| } | |
| } | |
| if (exemptionMechanism != null) { // OPTIONAL | |
| buf.append(" " + exemptionMechanism); | |
| } | |
| buf.append(")"); | |
| return buf.toString(); | |
| } | |
| private boolean impliesExemptionMechanism(String exemptionMechanism) { | |
| if (this.exemptionMechanism == null) { | |
| return true; | |
| } | |
| if (exemptionMechanism == null) { | |
| return false; | |
| } | |
| return this.exemptionMechanism.equals(exemptionMechanism); | |
| } | |
| private boolean impliesParameterSpec(boolean checkParam, | |
| AlgorithmParameterSpec algParamSpec) { | |
| if ((this.checkParam) && checkParam) { | |
| if (algParamSpec == null) { | |
| return true; | |
| } else if (this.algParamSpec == null) { | |
| return false; | |
| } | |
| if (this.algParamSpec.getClass() != algParamSpec.getClass()) { | |
| return false; | |
| } | |
| if (algParamSpec instanceof RC2ParameterSpec) { | |
| if (((RC2ParameterSpec)algParamSpec).getEffectiveKeyBits() <= | |
| ((RC2ParameterSpec) | |
| (this.algParamSpec)).getEffectiveKeyBits()) { | |
| return true; | |
| } | |
| } | |
| if (algParamSpec instanceof RC5ParameterSpec) { | |
| if (((RC5ParameterSpec)algParamSpec).getRounds() <= | |
| ((RC5ParameterSpec)this.algParamSpec).getRounds()) { | |
| return true; | |
| } | |
| } | |
| if (algParamSpec instanceof PBEParameterSpec) { | |
| if (((PBEParameterSpec)algParamSpec).getIterationCount() <= | |
| ((PBEParameterSpec)this.algParamSpec).getIterationCount()) { | |
| return true; | |
| } | |
| } | |
| // For classes we don't know, the following | |
| // may be the best try. | |
| return this.algParamSpec.equals(algParamSpec); | |
| } else { | |
| return !this.checkParam; | |
| } | |
| } | |
| } | |
| /** | |
| * A {@code CryptoPermissionCollection} object stores a set of | |
| * {@code CryptoPermission} objects. | |
| * | |
| * @see java.security.Permission | |
| * @see java.security.Permissions | |
| * @see java.security.PermissionCollection | |
| * | |
| * @author Sharon Liu | |
| */ | |
| final class CryptoPermissionCollection extends PermissionCollection | |
| implements Serializable | |
| { | |
| @Serial | |
| private static final long serialVersionUID = -511215555898802763L; | |
| private final Vector<Permission> permissions; | |
| /** | |
| * Creates an empty CryptoPermissionCollection | |
| * object. | |
| */ | |
| CryptoPermissionCollection() { | |
| permissions = new Vector<>(3); | |
| } | |
| /** | |
| * Adds a permission to the {@code CryptoPermissionCollection} object. | |
| * | |
| * @param permission the {@code Permission} object to add. | |
| * | |
| * @exception SecurityException if this | |
| * {@code CryptoPermissionCollection} object has been marked | |
| * <i>readOnly</i>. | |
| */ | |
| public void add(Permission permission) { | |
| if (isReadOnly()) | |
| throw new SecurityException("attempt to add a Permission " + | |
| "to a readonly PermissionCollection"); | |
| if (!(permission instanceof CryptoPermission)) | |
| return; | |
| permissions.addElement(permission); | |
| } | |
| /** | |
| * Check and see if this {@code CryptoPermission} object implies | |
| * the given {@code Permission} object. | |
| * | |
| * @param permission the {@code Permission} object to compare | |
| * | |
| * @return {@code true} if the given permission is implied by this | |
| * {@code CryptoPermissionCollection}, {@code false} if not. | |
| */ | |
| public boolean implies(Permission permission) { | |
| if (!(permission instanceof CryptoPermission cp)) | |
| return false; | |
| for (Permission p : permissions) { | |
| CryptoPermission x = (CryptoPermission) p; | |
| if (x.implies(cp)) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| /** | |
| * Returns an enumeration of all the {@code CryptoPermission} objects | |
| * in the container. | |
| * | |
| * @return an enumeration of all the {@code CryptoPermission} objects. | |
| */ | |
| public Enumeration<Permission> elements() { | |
| return permissions.elements(); | |
| } | |
| } |