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 18package javax.crypto; 19 20import java.security.AlgorithmParameters; 21import java.security.InvalidAlgorithmParameterException; 22import java.security.InvalidKeyException; 23import java.security.Key; 24import java.security.NoSuchAlgorithmException; 25import java.security.NoSuchProviderException; 26import java.security.Provider; 27import java.security.Security; 28import java.security.spec.AlgorithmParameterSpec; 29import java.util.Arrays; 30import 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 */ 36public 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 * The {@code provider} supplied does not have to be registered. 146 * 147 * @param algorithm 148 * the name of the requested exemption mechanism. 149 * @param provider 150 * the provider that is providing the algorithm. 151 * @return the new {@code ExemptionMechanism} instance. 152 * @throws NoSuchAlgorithmException 153 * if the specified algorithm is not provided by the specified 154 * provider. 155 * @throws NullPointerException 156 * if the algorithm parameter is {@code null}. 157 * @throws IllegalArgumentException 158 * if the provider parameter is {@code null}. 159 */ 160 public static final ExemptionMechanism getInstance(String algorithm, 161 Provider provider) throws NoSuchAlgorithmException { 162 if (algorithm == null) { 163 throw new NullPointerException("algorithm == null"); 164 } 165 if (provider == null) { 166 throw new IllegalArgumentException("provider == null"); 167 } 168 Object spi = ENGINE.getInstance(algorithm, provider, null); 169 return new ExemptionMechanism((ExemptionMechanismSpi) spi, provider, algorithm); 170 } 171 172 /** 173 * Returns the provider of this {@code ExemptionMechanism} instance. 174 * 175 * @return the provider of this {@code ExemptionMechanism} instance. 176 */ 177 public final Provider getProvider() { 178 return provider; 179 } 180 181 /** 182 * Returns whether the result blob for this {@code ExemptionMechanism} 183 * instance has been generated successfully and that the specified key is 184 * the same as the one that was used to initialize and generate. 185 * 186 * @param key 187 * the key to verify. 188 * @return whether the result blob for this {@code ExemptionMechanism} 189 * instance has been generated successfully. 190 * @throws ExemptionMechanismException 191 * if an error occurs while determining whether the result blob 192 * has been generated successfully. 193 */ 194 public final boolean isCryptoAllowed(Key key) 195 throws ExemptionMechanismException { 196 197 if (generated 198 && (initKey.equals(key) || Arrays.equals(initKey.getEncoded(), 199 key.getEncoded()))) { 200 return true; 201 } 202 return false; 203 } 204 205 /** 206 * Returns the size in bytes for the output buffer needed to hold the output 207 * of the next {@link #genExemptionBlob} call, given the specified {@code 208 * inputLen} (in bytes). 209 * 210 * @param inputLen 211 * the specified input length (in bytes). 212 * @return the size in bytes for the output buffer. 213 * @throws IllegalStateException 214 * if this {@code ExemptionMechanism} instance is not 215 * initialized. 216 */ 217 public final int getOutputSize(int inputLen) throws IllegalStateException { 218 if (!isInit) { 219 throw new IllegalStateException("ExemptionMechanism is not initialized"); 220 } 221 return spiImpl.engineGetOutputSize(inputLen); 222 } 223 224 /** 225 * Initializes this {@code ExemptionMechanism} instance with the 226 * specified key. 227 * 228 * @param key 229 * the key to initialize this instance with. 230 * @throws InvalidKeyException 231 * if the key cannot be used to initialize this mechanism. 232 * @throws ExemptionMechanismException 233 * if error(s) occur during initialization. 234 */ 235 public final void init(Key key) throws InvalidKeyException, 236 ExemptionMechanismException { 237 generated = false; 238 spiImpl.engineInit(key); 239 initKey = key; 240 isInit = true; 241 } 242 243 /** 244 * Initializes this {@code ExemptionMechanism} instance with the 245 * specified key and algorithm parameters. 246 * 247 * @param key 248 * the key to initialize this instance with. 249 * @param param 250 * the parameters for this exemption mechanism algorithm. 251 * @throws InvalidKeyException 252 * if the key cannot be used to initialize this mechanism. 253 * @throws InvalidAlgorithmParameterException 254 * if the parameters cannot be used to initialize this 255 * mechanism. 256 * @throws ExemptionMechanismException 257 * if error(s) occur during initialization. 258 */ 259 public final void init(Key key, AlgorithmParameters param) 260 throws InvalidKeyException, InvalidAlgorithmParameterException, 261 ExemptionMechanismException { 262 generated = false; 263 spiImpl.engineInit(key, param); 264 initKey = key; 265 isInit = true; 266 } 267 268 /** 269 * Initializes this {@code ExemptionMechanism} instance with the 270 * specified key and algorithm parameters. 271 * 272 * @param key 273 * the key to initialize this instance with. 274 * @param param 275 * the parameters for this exemption mechanism algorithm. 276 * @throws InvalidKeyException 277 * if the key cannot be used to initialize this mechanism. 278 * @throws InvalidAlgorithmParameterException 279 * the the parameters cannot be used to initialize this 280 * mechanism. 281 * @throws ExemptionMechanismException 282 * if error(s) occur during initialization. 283 */ 284 public final void init(Key key, AlgorithmParameterSpec param) 285 throws InvalidKeyException, InvalidAlgorithmParameterException, 286 ExemptionMechanismException { 287 generated = false; 288 spiImpl.engineInit(key, param); 289 initKey = key; 290 isInit = true; 291 } 292 293 /** 294 * Generates the result key blob for this exemption mechanism. 295 * 296 * @return the result key blob for this exemption mechanism. 297 * @throws IllegalStateException 298 * if this {@code ExemptionMechanism} instance is not 299 * initialized. 300 * @throws ExemptionMechanismException 301 * if error(s) occur during generation. 302 */ 303 public final byte[] genExemptionBlob() throws IllegalStateException, 304 ExemptionMechanismException { 305 if (!isInit) { 306 throw new IllegalStateException("ExemptionMechanism is not initialized"); 307 } 308 generated = false; 309 byte[] result = spiImpl.engineGenExemptionBlob(); 310 generated = true; 311 return result; 312 } 313 314 /** 315 * Generates the result key blob for this exemption mechanism and stores it 316 * into the {@code output} buffer. 317 * 318 * @param output 319 * the output buffer for the result key blob. 320 * @return the number of bytes written to the {@code output} buffer. 321 * @throws IllegalStateException 322 * if this {@code ExemptionMechanism} instance is not 323 * initialized. 324 * @throws ShortBufferException 325 * if the provided buffer is too small for the result key blob. 326 * @throws ExemptionMechanismException 327 * if error(s) occur during generation. 328 */ 329 public final int genExemptionBlob(byte[] output) 330 throws IllegalStateException, ShortBufferException, 331 ExemptionMechanismException { 332 return genExemptionBlob(output, 0); 333 } 334 335 /** 336 * Generates the result key blob for this exemption mechanism and stores it 337 * into the {@code output} buffer at offset {@code outputOffset}. 338 * 339 * @param output 340 * the output buffer for the result key blob. 341 * @param outputOffset 342 * the offset in the output buffer to start. 343 * @return the number of bytes written to the {@code output} buffer. 344 * @throws IllegalStateException 345 * if this {@code ExemptionMechanism} instance is not 346 * initialized. 347 * @throws ShortBufferException 348 * if the provided buffer is too small for the result key blob. 349 * @throws ExemptionMechanismException 350 * if error(s) occur during generation. 351 */ 352 public final int genExemptionBlob(byte[] output, int outputOffset) 353 throws IllegalStateException, ShortBufferException, 354 ExemptionMechanismException { 355 if (!isInit) { 356 throw new IllegalStateException("ExemptionMechanism is not initialized"); 357 } 358 generated = false; 359 int len = spiImpl.engineGenExemptionBlob(output, outputOffset); 360 generated = true; 361 return len; 362 } 363 364 @Override protected void finalize() { 365 try { 366 super.finalize(); 367 } catch (Throwable t) { 368 // for consistency with the RI, we must override Object.finalize() to 369 // remove the throws clause. 370 throw new AssertionError(t); 371 } 372 } 373} 374