1 package org.bouncycastle.jcajce.provider.symmetric.util; 2 3 import java.security.AlgorithmParameters; 4 import java.security.InvalidAlgorithmParameterException; 5 import java.security.InvalidKeyException; 6 import java.security.Key; 7 import java.security.KeyFactory; 8 import java.security.NoSuchAlgorithmException; 9 import java.security.NoSuchProviderException; 10 import java.security.PrivateKey; 11 import java.security.SecureRandom; 12 import java.security.spec.AlgorithmParameterSpec; 13 import java.security.spec.InvalidKeySpecException; 14 import java.security.spec.PKCS8EncodedKeySpec; 15 import java.security.spec.X509EncodedKeySpec; 16 17 import javax.crypto.BadPaddingException; 18 import javax.crypto.Cipher; 19 import javax.crypto.CipherSpi; 20 import javax.crypto.IllegalBlockSizeException; 21 import javax.crypto.NoSuchPaddingException; 22 import javax.crypto.ShortBufferException; 23 import javax.crypto.spec.IvParameterSpec; 24 import javax.crypto.spec.PBEParameterSpec; 25 // BEGIN android-removed 26 // import javax.crypto.spec.RC2ParameterSpec; 27 // import javax.crypto.spec.RC5ParameterSpec; 28 // END android-removed 29 import javax.crypto.spec.SecretKeySpec; 30 31 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; 32 import org.bouncycastle.crypto.CipherParameters; 33 import org.bouncycastle.crypto.InvalidCipherTextException; 34 import org.bouncycastle.crypto.Wrapper; 35 import org.bouncycastle.crypto.params.KeyParameter; 36 import org.bouncycastle.crypto.params.ParametersWithIV; 37 import org.bouncycastle.jce.provider.BouncyCastleProvider; 38 39 public abstract class BaseWrapCipher 40 extends CipherSpi 41 implements PBE 42 { 43 // 44 // specs we can handle. 45 // 46 private Class[] availableSpecs = 47 { 48 IvParameterSpec.class, 49 PBEParameterSpec.class, 50 // BEGIN android-removed 51 // RC2ParameterSpec.class, 52 // RC5ParameterSpec.class 53 // END android-removed 54 }; 55 56 protected int pbeType = PKCS12; 57 protected int pbeHash = SHA1; 58 protected int pbeKeySize; 59 protected int pbeIvSize; 60 61 protected AlgorithmParameters engineParams = null; 62 63 protected Wrapper wrapEngine = null; 64 65 private int ivSize; 66 private byte[] iv; 67 68 protected BaseWrapCipher() 69 { 70 } 71 72 protected BaseWrapCipher( 73 Wrapper wrapEngine) 74 { 75 this(wrapEngine, 0); 76 } 77 78 protected BaseWrapCipher( 79 Wrapper wrapEngine, 80 int ivSize) 81 { 82 this.wrapEngine = wrapEngine; 83 this.ivSize = ivSize; 84 } 85 86 protected int engineGetBlockSize() 87 { 88 return 0; 89 } 90 91 protected byte[] engineGetIV() 92 { 93 return (byte[])iv.clone(); 94 } 95 96 protected int engineGetKeySize( 97 Key key) 98 { 99 return key.getEncoded().length; 100 } 101 102 protected int engineGetOutputSize( 103 int inputLen) 104 { 105 return -1; 106 } 107 108 protected AlgorithmParameters engineGetParameters() 109 { 110 return null; 111 } 112 113 protected void engineSetMode( 114 String mode) 115 throws NoSuchAlgorithmException 116 { 117 throw new NoSuchAlgorithmException("can't support mode " + mode); 118 } 119 120 protected void engineSetPadding( 121 String padding) 122 throws NoSuchPaddingException 123 { 124 throw new NoSuchPaddingException("Padding " + padding + " unknown."); 125 } 126 127 protected void engineInit( 128 int opmode, 129 Key key, 130 AlgorithmParameterSpec params, 131 SecureRandom random) 132 throws InvalidKeyException, InvalidAlgorithmParameterException 133 { 134 CipherParameters param; 135 136 if (key instanceof BCPBEKey) 137 { 138 BCPBEKey k = (BCPBEKey)key; 139 140 if (params instanceof PBEParameterSpec) 141 { 142 param = PBE.Util.makePBEParameters(k, params, wrapEngine.getAlgorithmName()); 143 } 144 else if (k.getParam() != null) 145 { 146 param = k.getParam(); 147 } 148 else 149 { 150 throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set."); 151 } 152 } 153 else 154 { 155 param = new KeyParameter(key.getEncoded()); 156 } 157 158 if (params instanceof IvParameterSpec) 159 { 160 IvParameterSpec iv = (IvParameterSpec) params; 161 param = new ParametersWithIV(param, iv.getIV()); 162 } 163 164 if (param instanceof KeyParameter && ivSize != 0) 165 { 166 iv = new byte[ivSize]; 167 random.nextBytes(iv); 168 param = new ParametersWithIV(param, iv); 169 } 170 171 switch (opmode) 172 { 173 case Cipher.WRAP_MODE: 174 wrapEngine.init(true, param); 175 break; 176 case Cipher.UNWRAP_MODE: 177 wrapEngine.init(false, param); 178 break; 179 case Cipher.ENCRYPT_MODE: 180 case Cipher.DECRYPT_MODE: 181 throw new IllegalArgumentException("engine only valid for wrapping"); 182 default: 183 System.out.println("eeek!"); 184 } 185 } 186 187 protected void engineInit( 188 int opmode, 189 Key key, 190 AlgorithmParameters params, 191 SecureRandom random) 192 throws InvalidKeyException, InvalidAlgorithmParameterException 193 { 194 AlgorithmParameterSpec paramSpec = null; 195 196 if (params != null) 197 { 198 for (int i = 0; i != availableSpecs.length; i++) 199 { 200 try 201 { 202 paramSpec = params.getParameterSpec(availableSpecs[i]); 203 break; 204 } 205 catch (Exception e) 206 { 207 // try next spec 208 } 209 } 210 211 if (paramSpec == null) 212 { 213 throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString()); 214 } 215 } 216 217 engineParams = params; 218 engineInit(opmode, key, paramSpec, random); 219 } 220 221 protected void engineInit( 222 int opmode, 223 Key key, 224 SecureRandom random) 225 throws InvalidKeyException 226 { 227 try 228 { 229 engineInit(opmode, key, (AlgorithmParameterSpec)null, random); 230 } 231 catch (InvalidAlgorithmParameterException e) 232 { 233 throw new IllegalArgumentException(e.getMessage()); 234 } 235 } 236 237 protected byte[] engineUpdate( 238 byte[] input, 239 int inputOffset, 240 int inputLen) 241 { 242 throw new RuntimeException("not supported for wrapping"); 243 } 244 245 protected int engineUpdate( 246 byte[] input, 247 int inputOffset, 248 int inputLen, 249 byte[] output, 250 int outputOffset) 251 throws ShortBufferException 252 { 253 throw new RuntimeException("not supported for wrapping"); 254 } 255 256 protected byte[] engineDoFinal( 257 byte[] input, 258 int inputOffset, 259 int inputLen) 260 throws IllegalBlockSizeException, BadPaddingException 261 { 262 return null; 263 } 264 265 // BEGIN android-changed 266 // added ShortBufferException to throws statement 267 protected int engineDoFinal( 268 byte[] input, 269 int inputOffset, 270 int inputLen, 271 byte[] output, 272 int outputOffset) 273 throws IllegalBlockSizeException, BadPaddingException, ShortBufferException 274 { 275 return 0; 276 } 277 // END android-changed 278 279 protected byte[] engineWrap( 280 Key key) 281 throws IllegalBlockSizeException, InvalidKeyException 282 { 283 byte[] encoded = key.getEncoded(); 284 if (encoded == null) 285 { 286 throw new InvalidKeyException("Cannot wrap key, null encoding."); 287 } 288 289 try 290 { 291 if (wrapEngine == null) 292 { 293 return engineDoFinal(encoded, 0, encoded.length); 294 } 295 else 296 { 297 return wrapEngine.wrap(encoded, 0, encoded.length); 298 } 299 } 300 catch (BadPaddingException e) 301 { 302 throw new IllegalBlockSizeException(e.getMessage()); 303 } 304 } 305 306 protected Key engineUnwrap( 307 byte[] wrappedKey, 308 String wrappedKeyAlgorithm, 309 int wrappedKeyType) 310 throws InvalidKeyException, NoSuchAlgorithmException 311 { 312 byte[] encoded; 313 try 314 { 315 if (wrapEngine == null) 316 { 317 encoded = engineDoFinal(wrappedKey, 0, wrappedKey.length); 318 } 319 else 320 { 321 encoded = wrapEngine.unwrap(wrappedKey, 0, wrappedKey.length); 322 } 323 } 324 catch (InvalidCipherTextException e) 325 { 326 throw new InvalidKeyException(e.getMessage()); 327 } 328 catch (BadPaddingException e) 329 { 330 throw new InvalidKeyException(e.getMessage()); 331 } 332 catch (IllegalBlockSizeException e2) 333 { 334 throw new InvalidKeyException(e2.getMessage()); 335 } 336 337 if (wrappedKeyType == Cipher.SECRET_KEY) 338 { 339 return new SecretKeySpec(encoded, wrappedKeyAlgorithm); 340 } 341 else if (wrappedKeyAlgorithm.equals("") && wrappedKeyType == Cipher.PRIVATE_KEY) 342 { 343 /* 344 * The caller doesn't know the algorithm as it is part of 345 * the encrypted data. 346 */ 347 try 348 { 349 PrivateKeyInfo in = PrivateKeyInfo.getInstance(encoded); 350 351 PrivateKey privKey = BouncyCastleProvider.getPrivateKey(in); 352 353 if (privKey != null) 354 { 355 return privKey; 356 } 357 else 358 { 359 throw new InvalidKeyException("algorithm " + in.getPrivateKeyAlgorithm().getAlgorithm() + " not supported"); 360 } 361 } 362 catch (Exception e) 363 { 364 throw new InvalidKeyException("Invalid key encoding."); 365 } 366 } 367 else 368 { 369 try 370 { 371 KeyFactory kf = KeyFactory.getInstance(wrappedKeyAlgorithm, BouncyCastleProvider.PROVIDER_NAME); 372 373 if (wrappedKeyType == Cipher.PUBLIC_KEY) 374 { 375 return kf.generatePublic(new X509EncodedKeySpec(encoded)); 376 } 377 else if (wrappedKeyType == Cipher.PRIVATE_KEY) 378 { 379 return kf.generatePrivate(new PKCS8EncodedKeySpec(encoded)); 380 } 381 } 382 catch (NoSuchProviderException e) 383 { 384 throw new InvalidKeyException("Unknown key type " + e.getMessage()); 385 } 386 catch (InvalidKeySpecException e2) 387 { 388 throw new InvalidKeyException("Unknown key type " + e2.getMessage()); 389 } 390 391 throw new InvalidKeyException("Unknown key type " + wrappedKeyType); 392 } 393 } 394 395 } 396