1 /* 2 * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.crypto; 27 28 import java.security.*; 29 import java.security.spec.AlgorithmParameterSpec; 30 import java.io.Serializable; 31 import java.util.Enumeration; 32 import java.util.Vector; 33 34 import javax.crypto.spec.*; 35 36 /** 37 * The CryptoPermission class extends the 38 * java.security.Permission class. A 39 * CryptoPermission object is used to represent 40 * the ability of an application/applet to use certain 41 * algorithms with certain key sizes and other 42 * restrictions in certain environments. <p> 43 * 44 * @see java.security.Permission 45 * 46 * @author Jan Luehe 47 * @author Sharon Liu 48 * @since 1.4 49 */ 50 class CryptoPermission extends java.security.Permission { 51 52 private static final long serialVersionUID = 8987399626114087514L; 53 54 private String alg; 55 private int maxKeySize = Integer.MAX_VALUE; // no restriction on maxKeySize 56 private String exemptionMechanism = null; 57 private AlgorithmParameterSpec algParamSpec = null; 58 private boolean checkParam = false; // no restriction on param 59 60 static final String ALG_NAME_WILDCARD = "*"; 61 62 /** 63 * Constructor that takes an algorithm name. 64 * 65 * This constructor implies that the given algorithm can be 66 * used without any restrictions. 67 * 68 * @param alg the algorithm name. 69 */ 70 CryptoPermission(String alg) { 71 super(null); 72 this.alg = alg; 73 } 74 75 /** 76 * Constructor that takes an algorithm name and a maximum 77 * key size. 78 * 79 * This constructor implies that the given algorithm can be 80 * used with a key size up to <code>maxKeySize</code>. 81 * 82 * @param alg the algorithm name. 83 * 84 * @param maxKeySize the maximum allowable key size, 85 * specified in number of bits. 86 */ 87 CryptoPermission(String alg, int maxKeySize) { 88 super(null); 89 this.alg = alg; 90 this.maxKeySize = maxKeySize; 91 } 92 93 /** 94 * Constructor that takes an algorithm name, a maximum 95 * key size, and an AlgorithmParameterSpec object. 96 * 97 * This constructor implies that the given algorithm can be 98 * used with a key size up to <code>maxKeySize</code>, and 99 * algorithm 100 * parameters up to the limits set in <code>algParamSpec</code>. 101 * 102 * @param alg the algorithm name. 103 * 104 * @param maxKeySize the maximum allowable key size, 105 * specified in number of bits. 106 * 107 * @param algParamSpec the limits for allowable algorithm 108 * parameters. 109 */ 110 CryptoPermission(String alg, 111 int maxKeySize, 112 AlgorithmParameterSpec algParamSpec) { 113 super(null); 114 this.alg = alg; 115 this.maxKeySize = maxKeySize; 116 this.checkParam = true; 117 this.algParamSpec = algParamSpec; 118 } 119 120 /** 121 * Constructor that takes an algorithm name and the name of 122 * an exemption mechanism. 123 * 124 * This constructor implies that the given algorithm can be 125 * used without any key size or algorithm parameter restrictions 126 * provided that the specified exemption mechanism is enforced. 127 * 128 * @param alg the algorithm name. 129 * 130 * @param exemptionMechanism the name of the exemption mechanism. 131 */ 132 CryptoPermission(String alg, 133 String exemptionMechanism) { 134 super(null); 135 this.alg = alg; 136 this.exemptionMechanism = exemptionMechanism; 137 } 138 139 /** 140 * Constructor that takes an algorithm name, a maximum key 141 * size, and the name of an exemption mechanism. 142 * 143 * This constructor implies that the given algorithm can be 144 * used with a key size up to <code>maxKeySize</code> 145 * provided that the 146 * specified exemption mechanism is enforced. 147 * 148 * @param alg the algorithm name. 149 * @param maxKeySize the maximum allowable key size, 150 * specified in number of bits. 151 * @param exemptionMechanism the name of the exemption 152 * mechanism. 153 */ 154 CryptoPermission(String alg, 155 int maxKeySize, 156 String exemptionMechanism) { 157 super(null); 158 this.alg = alg; 159 this.exemptionMechanism = exemptionMechanism; 160 this.maxKeySize = maxKeySize; 161 } 162 163 /** 164 * Constructor that takes an algorithm name, a maximum key 165 * size, the name of an exemption mechanism, and an 166 * AlgorithmParameterSpec object. 167 * 168 * This constructor implies that the given algorithm can be 169 * used with a key size up to <code>maxKeySize</code> 170 * and algorithm 171 * parameters up to the limits set in <code>algParamSpec</code> 172 * provided that 173 * the specified exemption mechanism is enforced. 174 * 175 * @param alg the algorithm name. 176 * @param maxKeySize the maximum allowable key size, 177 * specified in number of bits. 178 * @param algParamSpec the limit for allowable algorithm 179 * parameter spec. 180 * @param exemptionMechanism the name of the exemption 181 * mechanism. 182 */ 183 CryptoPermission(String alg, 184 int maxKeySize, 185 AlgorithmParameterSpec algParamSpec, 186 String exemptionMechanism) { 187 super(null); 188 this.alg = alg; 189 this.exemptionMechanism = exemptionMechanism; 190 this.maxKeySize = maxKeySize; 191 this.checkParam = true; 192 this.algParamSpec = algParamSpec; 193 } 194 195 /** 196 * Checks if the specified permission is "implied" by 197 * this object. 198 * <p> 199 * More specifically, this method returns true if:<p> 200 * <ul> 201 * <li> <i>p</i> is an instance of CryptoPermission, and<p> 202 * <li> <i>p</i>'s algorithm name equals or (in the case of wildcards) 203 * is implied by this permission's algorithm name, and<p> 204 * <li> <i>p</i>'s maximum allowable key size is less or 205 * equal to this permission's maximum allowable key size, and<p> 206 * <li> <i>p</i>'s algorithm parameter spec equals or is 207 * implied by this permission's algorithm parameter spec, and<p> 208 * <li> <i>p</i>'s exemptionMechanism equals or 209 * is implied by this permission's 210 * exemptionMechanism (a <code>null</code> exemption mechanism 211 * implies any other exemption mechanism). 212 * </ul> 213 * 214 * @param p the permission to check against. 215 * 216 * @return true if the specified permission is equal to or 217 * implied by this permission, false otherwise. 218 */ 219 public boolean implies(Permission p) { 220 if (!(p instanceof CryptoPermission)) 221 return false; 222 223 CryptoPermission cp = (CryptoPermission)p; 224 225 if ((!alg.equalsIgnoreCase(cp.alg)) && 226 (!alg.equalsIgnoreCase(ALG_NAME_WILDCARD))) { 227 return false; 228 } 229 230 // alg is the same as cp's alg or 231 // alg is a wildcard. 232 if (cp.maxKeySize <= this.maxKeySize) { 233 // check algParamSpec. 234 if (!impliesParameterSpec(cp.checkParam, cp.algParamSpec)) { 235 return false; 236 } 237 238 // check exemptionMechanism. 239 if (impliesExemptionMechanism(cp.exemptionMechanism)) { 240 return true; 241 } 242 } 243 244 return false; 245 } 246 247 /** 248 * Checks two CryptoPermission objects for equality. Checks that 249 * <code>obj</code> is a CryptoPermission, and has the same 250 * algorithm name, 251 * exemption mechanism name, maximum allowable key size and 252 * algorithm parameter spec 253 * as this object. 254 * <P> 255 * @param obj the object to test for equality with this object. 256 * @return true if <code>obj</code> is equal to this object. 257 */ 258 public boolean equals(Object obj) { 259 if (obj == this) 260 return true; 261 262 if (!(obj instanceof CryptoPermission)) 263 return false; 264 265 CryptoPermission that = (CryptoPermission) obj; 266 267 if (!(alg.equalsIgnoreCase(that.alg)) || 268 (maxKeySize != that.maxKeySize)) { 269 return false; 270 } 271 if (this.checkParam != that.checkParam) { 272 return false; 273 } 274 return (equalObjects(this.exemptionMechanism, 275 that.exemptionMechanism) && 276 equalObjects(this.algParamSpec, 277 that.algParamSpec)); 278 } 279 280 /** 281 * Returns the hash code value for this object. 282 * 283 * @return a hash code value for this object. 284 */ 285 286 public int hashCode() { 287 int retval = alg.hashCode(); 288 retval ^= maxKeySize; 289 if (exemptionMechanism != null) { 290 retval ^= exemptionMechanism.hashCode(); 291 } 292 if (checkParam) retval ^= 100; 293 if (algParamSpec != null) { 294 retval ^= algParamSpec.hashCode(); 295 } 296 return retval; 297 } 298 299 /** 300 * There is no action defined for a CryptoPermission 301 * onject. 302 */ 303 public String getActions() 304 { 305 return null; 306 } 307 308 /** 309 * Returns a new PermissionCollection object for storing 310 * CryptoPermission objects. 311 * 312 * @return a new PermissionCollection object suitable for storing 313 * CryptoPermissions. 314 */ 315 316 public PermissionCollection newPermissionCollection() { 317 return new CryptoPermissionCollection(); 318 } 319 320 /** 321 * Returns the algorithm name associated with 322 * this CryptoPermission object. 323 */ 324 final String getAlgorithm() { 325 return alg; 326 } 327 328 /** 329 * Returns the exemption mechanism name 330 * associated with this CryptoPermission 331 * object. 332 */ 333 final String getExemptionMechanism() { 334 return exemptionMechanism; 335 } 336 337 /** 338 * Returns the maximum allowable key size associated 339 * with this CryptoPermission object. 340 */ 341 final int getMaxKeySize() { 342 return maxKeySize; 343 } 344 345 /** 346 * Returns true if there is a limitation on the 347 * AlgorithmParameterSpec associated with this 348 * CryptoPermission object and false if otherwise. 349 */ 350 final boolean getCheckParam() { 351 return checkParam; 352 } 353 354 /** 355 * Returns the AlgorithmParameterSpec 356 * associated with this CryptoPermission 357 * object. 358 */ 359 final AlgorithmParameterSpec getAlgorithmParameterSpec() { 360 return algParamSpec; 361 } 362 363 /** 364 * Returns a string describing this CryptoPermission. The convention is to 365 * specify the class name, the algorithm name, the maximum allowable 366 * key size, and the name of the exemption mechanism, in the following 367 * format: '("ClassName" "algorithm" "keysize" "exemption_mechanism")'. 368 * 369 * @return information about this CryptoPermission. 370 */ 371 public String toString() { 372 StringBuilder buf = new StringBuilder(100); 373 buf.append("(CryptoPermission " + alg + " " + maxKeySize); 374 if (algParamSpec != null) { 375 if (algParamSpec instanceof RC2ParameterSpec) { 376 buf.append(" , effective " + 377 ((RC2ParameterSpec)algParamSpec).getEffectiveKeyBits()); 378 } else if (algParamSpec instanceof RC5ParameterSpec) { 379 buf.append(" , rounds " + 380 ((RC5ParameterSpec)algParamSpec).getRounds()); 381 } 382 } 383 if (exemptionMechanism != null) { // OPTIONAL 384 buf.append(" " + exemptionMechanism); 385 } 386 buf.append(")"); 387 return buf.toString(); 388 } 389 390 private boolean impliesExemptionMechanism(String exemptionMechanism) { 391 if (this.exemptionMechanism == null) { 392 return true; 393 } 394 395 if (exemptionMechanism == null) { 396 return false; 397 } 398 399 if (this.exemptionMechanism.equals(exemptionMechanism)) { 400 return true; 401 } 402 403 return false; 404 } 405 406 private boolean impliesParameterSpec(boolean checkParam, 407 AlgorithmParameterSpec algParamSpec) { 408 if ((this.checkParam) && checkParam) { 409 if (algParamSpec == null) { 410 return true; 411 } else if (this.algParamSpec == null) { 412 return false; 413 } 414 415 if (this.algParamSpec.getClass() != algParamSpec.getClass()) { 416 return false; 417 } 418 419 if (algParamSpec instanceof RC2ParameterSpec) { 420 if (((RC2ParameterSpec)algParamSpec).getEffectiveKeyBits() <= 421 ((RC2ParameterSpec) 422 (this.algParamSpec)).getEffectiveKeyBits()) { 423 return true; 424 } 425 } 426 427 if (algParamSpec instanceof RC5ParameterSpec) { 428 if (((RC5ParameterSpec)algParamSpec).getRounds() <= 429 ((RC5ParameterSpec)this.algParamSpec).getRounds()) { 430 return true; 431 } 432 } 433 434 if (algParamSpec instanceof PBEParameterSpec) { 435 if (((PBEParameterSpec)algParamSpec).getIterationCount() <= 436 ((PBEParameterSpec)this.algParamSpec).getIterationCount()) { 437 return true; 438 } 439 } 440 441 // For classes we don't know, the following 442 // may be the best try. 443 if (this.algParamSpec.equals(algParamSpec)) { 444 return true; 445 } 446 return false; 447 } else if (this.checkParam) { 448 return false; 449 } else { 450 return true; 451 } 452 } 453 454 private boolean equalObjects(Object obj1, Object obj2) { 455 if (obj1 == null) { 456 return (obj2 == null ? true : false); 457 } 458 459 return obj1.equals(obj2); 460 } 461 } 462 463 /** 464 * A CryptoPermissionCollection stores a set of CryptoPermission 465 * permissions. 466 * 467 * @see java.security.Permission 468 * @see java.security.Permissions 469 * @see java.security.PermissionCollection 470 * 471 * @author Sharon Liu 472 */ 473 final class CryptoPermissionCollection extends PermissionCollection 474 implements Serializable { 475 476 private static final long serialVersionUID = -511215555898802763L; 477 478 private Vector permissions; 479 480 /** 481 * Creates an empty CryptoPermissionCollection 482 * object. 483 */ 484 CryptoPermissionCollection() { 485 permissions = new Vector(3); 486 } 487 488 /** 489 * Adds a permission to the CryptoPermissionCollection. 490 * 491 * @param permission the Permission object to add. 492 * 493 * @exception SecurityException - if this CryptoPermissionCollection 494 * object has been marked <i>readOnly</i>. 495 */ 496 public void add(Permission permission) 497 { 498 if (isReadOnly()) 499 throw new SecurityException("attempt to add a Permission " + 500 "to a readonly PermissionCollection"); 501 502 if (!(permission instanceof CryptoPermission)) 503 return; 504 505 permissions.addElement(permission); 506 } 507 508 /** 509 * Check and see if this CryptoPermission object implies 510 * the given Permission object. 511 * 512 * @param p the Permission object to compare 513 * 514 * @return true if the given permission is implied by this 515 * CryptoPermissionCollection, false if not. 516 */ 517 public boolean implies(Permission permission) { 518 if (!(permission instanceof CryptoPermission)) 519 return false; 520 521 CryptoPermission cp = (CryptoPermission)permission; 522 523 Enumeration e = permissions.elements(); 524 525 while (e.hasMoreElements()) { 526 CryptoPermission x = (CryptoPermission) e.nextElement(); 527 if (x.implies(cp)) { 528 return true; 529 } 530 } 531 return false; 532 } 533 534 /** 535 * Returns an enumeration of all the CryptoPermission objects 536 * in the container. 537 * 538 * @return an enumeration of all the CryptoPermission objects. 539 */ 540 541 public Enumeration elements() 542 { 543 return permissions.elements(); 544 } 545 }