1 /* 2 * Copyright (c) 1999, 2015, 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.AlgorithmParameters; 29 import java.security.Provider; 30 import java.security.Key; 31 import java.security.Security; 32 import java.security.NoSuchAlgorithmException; 33 import java.security.NoSuchProviderException; 34 import java.security.InvalidKeyException; 35 import java.security.InvalidAlgorithmParameterException; 36 import java.security.spec.AlgorithmParameterSpec; 37 38 import sun.security.jca.GetInstance.Instance; 39 40 /** 41 * This class provides the functionality of an exemption mechanism, examples 42 * of which are <i>key recovery</i>, <i>key weakening</i>, and 43 * <i>key escrow</i>. 44 * 45 * <p>Applications or applets that use an exemption mechanism may be granted 46 * stronger encryption capabilities than those which don't. 47 * 48 * @since 1.4 49 */ 50 51 public class ExemptionMechanism { 52 53 // The provider 54 private Provider provider; 55 56 // The provider implementation (delegate) 57 private ExemptionMechanismSpi exmechSpi; 58 59 // The name of the exemption mechanism. 60 private String mechanism; 61 62 // Flag which indicates whether this ExemptionMechanism 63 // result is generated successfully. 64 private boolean done = false; 65 66 // State information 67 private boolean initialized = false; 68 69 // Store away the key at init() time for later comparison. 70 private Key keyStored = null; 71 72 /** 73 * Creates a ExemptionMechanism object. 74 * 75 * @param exmechSpi the delegate 76 * @param provider the provider 77 * @param mechanism the exemption mechanism 78 */ 79 protected ExemptionMechanism(ExemptionMechanismSpi exmechSpi, 80 Provider provider, 81 String mechanism) { 82 this.exmechSpi = exmechSpi; 83 this.provider = provider; 84 this.mechanism = mechanism; 85 } 86 87 /** 88 * Returns the exemption mechanism name of this 89 * <code>ExemptionMechanism</code> object. 90 * 91 * <p>This is the same name that was specified in one of the 92 * <code>getInstance</code> calls that created this 93 * <code>ExemptionMechanism</code> object. 94 * 95 * @return the exemption mechanism name of this 96 * <code>ExemptionMechanism</code> object. 97 */ 98 public final String getName() { 99 return this.mechanism; 100 } 101 102 /** 103 * Returns an <code>ExemptionMechanism</code> object that implements the 104 * specified exemption mechanism algorithm. 105 * 106 * <p> This method traverses the list of registered security Providers, 107 * starting with the most preferred Provider. 108 * A new ExemptionMechanism object encapsulating the 109 * ExemptionMechanismSpi implementation from the first 110 * Provider that supports the specified algorithm is returned. 111 * 112 * <p> Note that the list of registered providers may be retrieved via 113 * the {@link Security#getProviders() Security.getProviders()} method. 114 * 115 * @implNote 116 * The JDK Reference Implementation additionally uses the 117 * {@code jdk.security.provider.preferred} property to determine 118 * the preferred provider order for the specified algorithm. This 119 * may be different than the order of providers returned by 120 * {@link Security#getProviders() Security.getProviders()}. 121 * 122 * @param algorithm the standard name of the requested exemption 123 * mechanism. 124 * See the ExemptionMechanism section in the 125 * <a href= 126 * "{@docRoot}/../technotes/guides/security/StandardNames.html#Exemption"> 127 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 128 * for information about standard exemption mechanism names. 129 * 130 * @return the new <code>ExemptionMechanism</code> object. 131 * 132 * @exception NullPointerException if <code>algorithm</code> 133 * is null. 134 * 135 * @exception NoSuchAlgorithmException if no Provider supports an 136 * ExemptionMechanismSpi implementation for the 137 * specified algorithm. 138 * 139 * @see java.security.Provider 140 */ 141 public static final ExemptionMechanism getInstance(String algorithm) 142 throws NoSuchAlgorithmException { 143 Instance instance = JceSecurity.getInstance("ExemptionMechanism", 144 ExemptionMechanismSpi.class, algorithm); 145 return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl, 146 instance.provider, algorithm); 147 } 148 149 150 /** 151 * Returns an <code>ExemptionMechanism</code> object that implements the 152 * specified exemption mechanism algorithm. 153 * 154 * <p> A new ExemptionMechanism object encapsulating the 155 * ExemptionMechanismSpi implementation from the specified provider 156 * is returned. The specified provider must be registered 157 * in the security provider list. 158 * 159 * <p> Note that the list of registered providers may be retrieved via 160 * the {@link Security#getProviders() Security.getProviders()} method. 161 162 * @param algorithm the standard name of the requested exemption mechanism. 163 * See the ExemptionMechanism section in the 164 * <a href= 165 * "{@docRoot}/../technotes/guides/security/StandardNames.html#Exemption"> 166 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 167 * for information about standard exemption mechanism names. 168 * 169 * @param provider the name of the provider. 170 * 171 * @return the new <code>ExemptionMechanism</code> object. 172 * 173 * @exception NullPointerException if <code>algorithm</code> 174 * is null. 175 * 176 * @exception NoSuchAlgorithmException if an ExemptionMechanismSpi 177 * implementation for the specified algorithm is not 178 * available from the specified provider. 179 * 180 * @exception NoSuchProviderException if the specified provider is not 181 * registered in the security provider list. 182 * 183 * @exception IllegalArgumentException if the <code>provider</code> 184 * is null or empty. 185 * 186 * @see java.security.Provider 187 */ 188 public static final ExemptionMechanism getInstance(String algorithm, 189 String provider) throws NoSuchAlgorithmException, 190 NoSuchProviderException { 191 Instance instance = JceSecurity.getInstance("ExemptionMechanism", 192 ExemptionMechanismSpi.class, algorithm, provider); 193 return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl, 194 instance.provider, algorithm); 195 } 196 197 /** 198 * Returns an <code>ExemptionMechanism</code> object that implements the 199 * specified exemption mechanism algorithm. 200 * 201 * <p> A new ExemptionMechanism object encapsulating the 202 * ExemptionMechanismSpi implementation from the specified Provider 203 * object is returned. Note that the specified Provider object 204 * does not have to be registered in the provider list. 205 * 206 * @param algorithm the standard name of the requested exemption mechanism. 207 * See the ExemptionMechanism section in the 208 * <a href= 209 * "{@docRoot}/../technotes/guides/security/StandardNames.html#Exemption"> 210 * Java Cryptography Architecture Standard Algorithm Name Documentation</a> 211 * for information about standard exemption mechanism names. 212 * 213 * @param provider the provider. 214 * 215 * @return the new <code>ExemptionMechanism</code> object. 216 * 217 * @exception NullPointerException if <code>algorithm</code> 218 * is null. 219 * 220 * @exception NoSuchAlgorithmException if an ExemptionMechanismSpi 221 * implementation for the specified algorithm is not available 222 * from the specified Provider object. 223 * 224 * @exception IllegalArgumentException if the <code>provider</code> 225 * is null. 226 * 227 * @see java.security.Provider 228 */ 229 public static final ExemptionMechanism getInstance(String algorithm, 230 Provider provider) throws NoSuchAlgorithmException { 231 Instance instance = JceSecurity.getInstance("ExemptionMechanism", 232 ExemptionMechanismSpi.class, algorithm, provider); 233 return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl, 234 instance.provider, algorithm); 235 } 236 237 /** 238 * Returns the provider of this <code>ExemptionMechanism</code> object. 239 * 240 * @return the provider of this <code>ExemptionMechanism</code> object. 241 */ 242 public final Provider getProvider() { 243 return this.provider; 244 } 245 246 /** 247 * Returns whether the result blob has been generated successfully by this 248 * exemption mechanism. 249 * 250 * <p>The method also makes sure that the key passed in is the same as 251 * the one this exemption mechanism used in initializing and generating 252 * phases. 253 * 254 * @param key the key the crypto is going to use. 255 * 256 * @return whether the result blob of the same key has been generated 257 * successfully by this exemption mechanism; false if <code>key</code> 258 * is null. 259 * 260 * @exception ExemptionMechanismException if problem(s) encountered 261 * while determining whether the result blob has been generated successfully 262 * by this exemption mechanism object. 263 */ 264 public final boolean isCryptoAllowed(Key key) 265 throws ExemptionMechanismException { 266 boolean ret = false; 267 if (done && (key != null)) { 268 // Check if the key passed in is the same as the one 269 // this exemption mechanism used. 270 ret = keyStored.equals(key); 271 } 272 return ret; 273 } 274 275 /** 276 * Returns the length in bytes that an output buffer would need to be in 277 * order to hold the result of the next 278 * {@link #genExemptionBlob(byte[]) genExemptionBlob} 279 * operation, given the input length <code>inputLen</code> (in bytes). 280 * 281 * <p>The actual output length of the next 282 * {@link #genExemptionBlob(byte[]) genExemptionBlob} 283 * call may be smaller than the length returned by this method. 284 * 285 * @param inputLen the input length (in bytes) 286 * 287 * @return the required output buffer size (in bytes) 288 * 289 * @exception IllegalStateException if this exemption mechanism is in a 290 * wrong state (e.g., has not yet been initialized) 291 */ 292 public final int getOutputSize(int inputLen) throws IllegalStateException { 293 if (!initialized) { 294 throw new IllegalStateException( 295 "ExemptionMechanism not initialized"); 296 } 297 if (inputLen < 0) { 298 throw new IllegalArgumentException( 299 "Input size must be equal to " + "or greater than zero"); 300 } 301 return exmechSpi.engineGetOutputSize(inputLen); 302 } 303 304 /** 305 * Initializes this exemption mechanism with a key. 306 * 307 * <p>If this exemption mechanism requires any algorithm parameters 308 * that cannot be derived from the given <code>key</code>, the 309 * underlying exemption mechanism implementation is supposed to 310 * generate the required parameters itself (using provider-specific 311 * default values); in the case that algorithm parameters must be 312 * specified by the caller, an <code>InvalidKeyException</code> is raised. 313 * 314 * @param key the key for this exemption mechanism 315 * 316 * @exception InvalidKeyException if the given key is inappropriate for 317 * this exemption mechanism. 318 * @exception ExemptionMechanismException if problem(s) encountered in the 319 * process of initializing. 320 */ 321 public final void init(Key key) 322 throws InvalidKeyException, ExemptionMechanismException { 323 done = false; 324 initialized = false; 325 326 keyStored = key; 327 exmechSpi.engineInit(key); 328 initialized = true; 329 } 330 331 /** 332 * Initializes this exemption mechanism with a key and a set of algorithm 333 * parameters. 334 * 335 * <p>If this exemption mechanism requires any algorithm parameters 336 * and <code>params</code> is null, the underlying exemption 337 * mechanism implementation is supposed to generate the required 338 * parameters itself (using provider-specific default values); in the case 339 * that algorithm parameters must be specified by the caller, an 340 * <code>InvalidAlgorithmParameterException</code> is raised. 341 * 342 * @param key the key for this exemption mechanism 343 * @param params the algorithm parameters 344 * 345 * @exception InvalidKeyException if the given key is inappropriate for 346 * this exemption mechanism. 347 * @exception InvalidAlgorithmParameterException if the given algorithm 348 * parameters are inappropriate for this exemption mechanism. 349 * @exception ExemptionMechanismException if problem(s) encountered in the 350 * process of initializing. 351 */ 352 public final void init(Key key, AlgorithmParameterSpec params) 353 throws InvalidKeyException, InvalidAlgorithmParameterException, 354 ExemptionMechanismException { 355 done = false; 356 initialized = false; 357 358 keyStored = key; 359 exmechSpi.engineInit(key, params); 360 initialized = true; 361 } 362 363 /** 364 * Initializes this exemption mechanism with a key and a set of algorithm 365 * parameters. 366 * 367 * <p>If this exemption mechanism requires any algorithm parameters 368 * and <code>params</code> is null, the underlying exemption mechanism 369 * implementation is supposed to generate the required parameters itself 370 * (using provider-specific default values); in the case that algorithm 371 * parameters must be specified by the caller, an 372 * <code>InvalidAlgorithmParameterException</code> is raised. 373 * 374 * @param key the key for this exemption mechanism 375 * @param params the algorithm parameters 376 * 377 * @exception InvalidKeyException if the given key is inappropriate for 378 * this exemption mechanism. 379 * @exception InvalidAlgorithmParameterException if the given algorithm 380 * parameters are inappropriate for this exemption mechanism. 381 * @exception ExemptionMechanismException if problem(s) encountered in the 382 * process of initializing. 383 */ 384 public final void init(Key key, AlgorithmParameters params) 385 throws InvalidKeyException, InvalidAlgorithmParameterException, 386 ExemptionMechanismException { 387 done = false; 388 initialized = false; 389 390 keyStored = key; 391 exmechSpi.engineInit(key, params); 392 initialized = true; 393 } 394 395 /** 396 * Generates the exemption mechanism key blob. 397 * 398 * @return the new buffer with the result key blob. 399 * 400 * @exception IllegalStateException if this exemption mechanism is in 401 * a wrong state (e.g., has not been initialized). 402 * @exception ExemptionMechanismException if problem(s) encountered in the 403 * process of generating. 404 */ 405 public final byte[] genExemptionBlob() throws IllegalStateException, 406 ExemptionMechanismException { 407 if (!initialized) { 408 throw new IllegalStateException( 409 "ExemptionMechanism not initialized"); 410 } 411 byte[] blob = exmechSpi.engineGenExemptionBlob(); 412 done = true; 413 return blob; 414 } 415 416 /** 417 * Generates the exemption mechanism key blob, and stores the result in 418 * the <code>output</code> buffer. 419 * 420 * <p>If the <code>output</code> buffer is too small to hold the result, 421 * a <code>ShortBufferException</code> is thrown. In this case, repeat this 422 * call with a larger output buffer. Use 423 * {@link #getOutputSize(int) getOutputSize} to determine how big 424 * the output buffer should be. 425 * 426 * @param output the buffer for the result 427 * 428 * @return the number of bytes stored in <code>output</code> 429 * 430 * @exception IllegalStateException if this exemption mechanism is in 431 * a wrong state (e.g., has not been initialized). 432 * @exception ShortBufferException if the given output buffer is too small 433 * to hold the result. 434 * @exception ExemptionMechanismException if problem(s) encountered in the 435 * process of generating. 436 */ 437 public final int genExemptionBlob(byte[] output) 438 throws IllegalStateException, ShortBufferException, 439 ExemptionMechanismException { 440 if (!initialized) { 441 throw new IllegalStateException 442 ("ExemptionMechanism not initialized"); 443 } 444 int n = exmechSpi.engineGenExemptionBlob(output, 0); 445 done = true; 446 return n; 447 } 448 449 /** 450 * Generates the exemption mechanism key blob, and stores the result in 451 * the <code>output</code> buffer, starting at <code>outputOffset</code> 452 * inclusive. 453 * 454 * <p>If the <code>output</code> buffer is too small to hold the result, 455 * a <code>ShortBufferException</code> is thrown. In this case, repeat this 456 * call with a larger output buffer. Use 457 * {@link #getOutputSize(int) getOutputSize} to determine how big 458 * the output buffer should be. 459 * 460 * @param output the buffer for the result 461 * @param outputOffset the offset in <code>output</code> where the result 462 * is stored 463 * 464 * @return the number of bytes stored in <code>output</code> 465 * 466 * @exception IllegalStateException if this exemption mechanism is in 467 * a wrong state (e.g., has not been initialized). 468 * @exception ShortBufferException if the given output buffer is too small 469 * to hold the result. 470 * @exception ExemptionMechanismException if problem(s) encountered in the 471 * process of generating. 472 */ 473 public final int genExemptionBlob(byte[] output, int outputOffset) 474 throws IllegalStateException, ShortBufferException, 475 ExemptionMechanismException { 476 if (!initialized) { 477 throw new IllegalStateException 478 ("ExemptionMechanism not initialized"); 479 } 480 int n = exmechSpi.engineGenExemptionBlob(output, outputOffset); 481 done = true; 482 return n; 483 } 484 485 /** 486 * Ensures that the key stored away by this ExemptionMechanism 487 * object will be wiped out when there are no more references to it. 488 */ 489 protected void finalize() { 490 keyStored = null; 491 // Are there anything else we could do? 492 } 493 }