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