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