1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package javax.crypto; 19 20 import java.security.AlgorithmParameters; 21 import java.security.InvalidAlgorithmParameterException; 22 import java.security.InvalidKeyException; 23 import java.security.Key; 24 import java.security.NoSuchAlgorithmException; 25 import java.security.NoSuchProviderException; 26 import java.security.Provider; 27 import java.security.Security; 28 import java.security.spec.AlgorithmParameterSpec; 29 import java.util.Arrays; 30 import org.apache.harmony.security.fortress.Engine; 31 32 /** 33 * This class implements the functionality of an exemption mechanism such as 34 * <i>key recovery</i>, <i>key weakening</i>, or <i>key escrow</i>. 35 */ 36 public class ExemptionMechanism { 37 38 // Used to access common engine functionality 39 private static final Engine ENGINE = new Engine("ExemptionMechanism"); 40 41 // Store used provider 42 private final Provider provider; 43 44 // Store used spi implementation 45 private final ExemptionMechanismSpi spiImpl; 46 47 // Store mechanism name 48 private final String mechanism; 49 50 // Store state (initialized or not) 51 private boolean isInit; 52 53 // Store initKey value 54 private Key initKey; 55 56 // Indicates if blob generated successfully 57 private boolean generated; 58 59 /** 60 * Creates a {@code ExemptionMechanism} instance. 61 * 62 * @param exmechSpi 63 * the implementation delegate. 64 * @param provider 65 * the associated provider. 66 * @param mechanism 67 * the name of the mechanism. 68 */ 69 protected ExemptionMechanism(ExemptionMechanismSpi exmechSpi, 70 Provider provider, String mechanism) { 71 this.mechanism = mechanism; 72 this.spiImpl = exmechSpi; 73 this.provider = provider; 74 isInit = false; 75 } 76 77 /** 78 * Returns the name of this {@code ExemptionMechanism}. 79 * 80 * @return the name of this {@code ExemptionMechanism}. 81 */ 82 public final String getName() { 83 return mechanism; 84 } 85 86 /** 87 * Returns a new {@code ExemptionMechanism} instance that provides the 88 * specified exemption mechanism algorithm. 89 * 90 * @param algorithm 91 * the name of the requested exemption mechanism. 92 * @return the new {@code ExemptionMechanism} instance. 93 * @throws NoSuchAlgorithmException 94 * if the specified algorithm is not available by any provider. 95 * @throws NullPointerException 96 * if the algorithm parameter is {@code null}. 97 */ 98 public static final ExemptionMechanism getInstance(String algorithm) 99 throws NoSuchAlgorithmException { 100 if (algorithm == null) { 101 throw new NullPointerException("algorithm == null"); 102 } 103 Engine.SpiAndProvider sap = ENGINE.getInstance(algorithm, null); 104 return new ExemptionMechanism((ExemptionMechanismSpi) sap.spi, sap.provider, algorithm); 105 } 106 107 /** 108 * Returns a new {@code ExemptionMechansm} instance that provides the 109 * specified exemption mechanism algorithm from the specified provider. 110 * 111 * @param algorithm 112 * the name of the requested exemption mechanism. 113 * @param provider 114 * the name of the provider that is providing the algorithm. 115 * @return the new {@code ExemptionMechanism} instance. 116 * @throws NoSuchAlgorithmException 117 * if the specified algorithm is not provided by the specified 118 * provider. 119 * @throws NoSuchProviderException 120 * if the specified provider is not available. 121 * @throws NullPointerException 122 * if the algorithm parameter is {@code null}. 123 * @throws IllegalArgumentException 124 * if the provider parameter is {@code null}. 125 */ 126 public static final ExemptionMechanism getInstance(String algorithm, 127 String provider) throws NoSuchAlgorithmException, 128 NoSuchProviderException { 129 if (provider == null) { 130 throw new IllegalArgumentException("provider == null"); 131 } 132 Provider impProvider = Security.getProvider(provider); 133 if (impProvider == null) { 134 throw new NoSuchProviderException(provider); 135 } 136 if (algorithm == null) { 137 throw new NullPointerException("algorithm == null"); 138 } 139 return getInstance(algorithm, impProvider); 140 } 141 142 /** 143 * Returns a new {@code ExemptionMechanism} instance that provides the 144 * specified exemption mechanism algorithm from the specified provider. 145 * 146 * @param algorithm 147 * the name of the requested exemption mechanism. 148 * @param provider 149 * the provider that is providing the algorithm. 150 * @return the new {@code ExemptionMechanism} instance. 151 * @throws NoSuchAlgorithmException 152 * if the specified algorithm is not provided by the specified 153 * provider. 154 * @throws NullPointerException 155 * if the algorithm parameter is {@code null}. 156 * @throws IllegalArgumentException 157 * if the provider parameter is {@code null}. 158 */ 159 public static final ExemptionMechanism getInstance(String algorithm, 160 Provider provider) throws NoSuchAlgorithmException { 161 if (algorithm == null) { 162 throw new NullPointerException("algorithm == null"); 163 } 164 if (provider == null) { 165 throw new IllegalArgumentException("provider == null"); 166 } 167 Object spi = ENGINE.getInstance(algorithm, provider, null); 168 return new ExemptionMechanism((ExemptionMechanismSpi) spi, provider, algorithm); 169 } 170 171 /** 172 * Returns the provider of this {@code ExemptionMechanism} instance. 173 * 174 * @return the provider of this {@code ExemptionMechanism} instance. 175 */ 176 public final Provider getProvider() { 177 return provider; 178 } 179 180 /** 181 * Returns whether the result blob for this {@code ExemptionMechanism} 182 * instance has been generated successfully and that the specified key is 183 * the same as the one that was used to initialize and generate. 184 * 185 * @param key 186 * the key to verify. 187 * @return whether the result blob for this {@code ExemptionMechanism} 188 * instance has been generated successfully. 189 * @throws ExemptionMechanismException 190 * if an error occurs while determining whether the result blob 191 * has been generated successfully. 192 */ 193 public final boolean isCryptoAllowed(Key key) 194 throws ExemptionMechanismException { 195 196 if (generated 197 && (initKey.equals(key) || Arrays.equals(initKey.getEncoded(), 198 key.getEncoded()))) { 199 return true; 200 } 201 return false; 202 } 203 204 /** 205 * Returns the size in bytes for the output buffer needed to hold the output 206 * of the next {@link #genExemptionBlob} call, given the specified {@code 207 * inputLen} (in bytes). 208 * 209 * @param inputLen 210 * the specified input length (in bytes). 211 * @return the size in bytes for the output buffer. 212 * @throws IllegalStateException 213 * if this {@code ExemptionMechanism} instance is not 214 * initialized. 215 */ 216 public final int getOutputSize(int inputLen) throws IllegalStateException { 217 if (!isInit) { 218 throw new IllegalStateException("ExemptionMechanism is not initialized"); 219 } 220 return spiImpl.engineGetOutputSize(inputLen); 221 } 222 223 /** 224 * Initializes this {@code ExemptionMechanism} instance with the 225 * specified key. 226 * 227 * @param key 228 * the key to initialize this instance with. 229 * @throws InvalidKeyException 230 * if the key cannot be used to initialize this mechanism. 231 * @throws ExemptionMechanismException 232 * if error(s) occur during initialization. 233 */ 234 public final void init(Key key) throws InvalidKeyException, 235 ExemptionMechanismException { 236 generated = false; 237 spiImpl.engineInit(key); 238 initKey = key; 239 isInit = true; 240 } 241 242 /** 243 * Initializes this {@code ExemptionMechanism} instance with the 244 * specified key and algorithm parameters. 245 * 246 * @param key 247 * the key to initialize this instance with. 248 * @param param 249 * the parameters for this exemption mechanism algorithm. 250 * @throws InvalidKeyException 251 * if the key cannot be used to initialize this mechanism. 252 * @throws InvalidAlgorithmParameterException 253 * if the parameters cannot be used to initialize this 254 * mechanism. 255 * @throws ExemptionMechanismException 256 * if error(s) occur during initialization. 257 */ 258 public final void init(Key key, AlgorithmParameters param) 259 throws InvalidKeyException, InvalidAlgorithmParameterException, 260 ExemptionMechanismException { 261 generated = false; 262 spiImpl.engineInit(key, param); 263 initKey = key; 264 isInit = true; 265 } 266 267 /** 268 * Initializes this {@code ExemptionMechanism} instance with the 269 * specified key and algorithm parameters. 270 * 271 * @param key 272 * the key to initialize this instance with. 273 * @param param 274 * the parameters for this exemption mechanism algorithm. 275 * @throws InvalidKeyException 276 * if the key cannot be used to initialize this mechanism. 277 * @throws InvalidAlgorithmParameterException 278 * the the parameters cannot be used to initialize this 279 * mechanism. 280 * @throws ExemptionMechanismException 281 * if error(s) occur during initialization. 282 */ 283 public final void init(Key key, AlgorithmParameterSpec param) 284 throws InvalidKeyException, InvalidAlgorithmParameterException, 285 ExemptionMechanismException { 286 generated = false; 287 spiImpl.engineInit(key, param); 288 initKey = key; 289 isInit = true; 290 } 291 292 /** 293 * Generates the result key blob for this exemption mechanism. 294 * 295 * @return the result key blob for this exemption mechanism. 296 * @throws IllegalStateException 297 * if this {@code ExemptionMechanism} instance is not 298 * initialized. 299 * @throws ExemptionMechanismException 300 * if error(s) occur during generation. 301 */ 302 public final byte[] genExemptionBlob() throws IllegalStateException, 303 ExemptionMechanismException { 304 if (!isInit) { 305 throw new IllegalStateException("ExemptionMechanism is not initialized"); 306 } 307 generated = false; 308 byte[] result = spiImpl.engineGenExemptionBlob(); 309 generated = true; 310 return result; 311 } 312 313 /** 314 * Generates the result key blob for this exemption mechanism and stores it 315 * into the {@code output} buffer. 316 * 317 * @param output 318 * the output buffer for the result key blob. 319 * @return the number of bytes written to the {@code output} buffer. 320 * @throws IllegalStateException 321 * if this {@code ExemptionMechanism} instance is not 322 * initialized. 323 * @throws ShortBufferException 324 * if the provided buffer is too small for the result key blob. 325 * @throws ExemptionMechanismException 326 * if error(s) occur during generation. 327 */ 328 public final int genExemptionBlob(byte[] output) 329 throws IllegalStateException, ShortBufferException, 330 ExemptionMechanismException { 331 return genExemptionBlob(output, 0); 332 } 333 334 /** 335 * Generates the result key blob for this exemption mechanism and stores it 336 * into the {@code output} buffer at offset {@code outputOffset}. 337 * 338 * @param output 339 * the output buffer for the result key blob. 340 * @param outputOffset 341 * the offset in the output buffer to start. 342 * @return the number of bytes written to the {@code output} buffer. 343 * @throws IllegalStateException 344 * if this {@code ExemptionMechanism} instance is not 345 * initialized. 346 * @throws ShortBufferException 347 * if the provided buffer is too small for the result key blob. 348 * @throws ExemptionMechanismException 349 * if error(s) occur during generation. 350 */ 351 public final int genExemptionBlob(byte[] output, int outputOffset) 352 throws IllegalStateException, ShortBufferException, 353 ExemptionMechanismException { 354 if (!isInit) { 355 throw new IllegalStateException("ExemptionMechanism is not initialized"); 356 } 357 generated = false; 358 int len = spiImpl.engineGenExemptionBlob(output, outputOffset); 359 generated = true; 360 return len; 361 } 362 363 /** 364 * Override to clear any key state in the instance. 365 */ 366 @Override protected void finalize() { 367 try { 368 super.finalize(); 369 } catch (Throwable t) { 370 // for consistency with the RI, we must override Object.finalize() to 371 // remove the throws clause. 372 throw new AssertionError(t); 373 } 374 } 375 } 376