1package org.bouncycastle.jcajce.provider.symmetric.util; 2 3import java.security.AlgorithmParameters; 4import java.security.InvalidAlgorithmParameterException; 5import java.security.InvalidKeyException; 6import java.security.InvalidParameterException; 7import java.security.Key; 8import java.security.Provider; 9import java.security.SecureRandom; 10import java.security.spec.AlgorithmParameterSpec; 11 12import javax.crypto.Cipher; 13import javax.crypto.NoSuchPaddingException; 14import javax.crypto.SecretKey; 15import javax.crypto.ShortBufferException; 16import javax.crypto.spec.IvParameterSpec; 17import javax.crypto.spec.PBEParameterSpec; 18// BEGIN android-removed 19// import javax.crypto.spec.RC2ParameterSpec; 20// import javax.crypto.spec.RC5ParameterSpec; 21// END android-removed 22 23import org.bouncycastle.crypto.CipherParameters; 24import org.bouncycastle.crypto.DataLengthException; 25import org.bouncycastle.crypto.StreamCipher; 26import org.bouncycastle.crypto.params.KeyParameter; 27import org.bouncycastle.crypto.params.ParametersWithIV; 28import org.bouncycastle.jce.provider.BouncyCastleProvider; 29 30public class BaseStreamCipher 31 extends BaseWrapCipher 32 implements PBE 33{ 34 // 35 // specs we can handle. 36 // 37 private Class[] availableSpecs = 38 { 39 // BEGIN android-removed 40 // RC2ParameterSpec.class, 41 // RC5ParameterSpec.class, 42 // END android-removed 43 IvParameterSpec.class, 44 PBEParameterSpec.class 45 }; 46 47 private StreamCipher cipher; 48 private ParametersWithIV ivParam; 49 50 private int ivLength = 0; 51 52 private PBEParameterSpec pbeSpec = null; 53 private String pbeAlgorithm = null; 54 55 protected BaseStreamCipher( 56 StreamCipher engine, 57 int ivLength) 58 { 59 cipher = engine; 60 this.ivLength = ivLength; 61 } 62 63 protected int engineGetBlockSize() 64 { 65 return 0; 66 } 67 68 protected byte[] engineGetIV() 69 { 70 return (ivParam != null) ? ivParam.getIV() : null; 71 } 72 73 protected int engineGetKeySize( 74 Key key) 75 { 76 return key.getEncoded().length * 8; 77 } 78 79 protected int engineGetOutputSize( 80 int inputLen) 81 { 82 return inputLen; 83 } 84 85 protected AlgorithmParameters engineGetParameters() 86 { 87 if (engineParams == null) 88 { 89 if (pbeSpec != null) 90 { 91 try 92 { 93 AlgorithmParameters engineParams = createParametersInstance(pbeAlgorithm); 94 engineParams.init(pbeSpec); 95 96 return engineParams; 97 } 98 catch (Exception e) 99 { 100 return null; 101 } 102 } 103 } 104 105 return engineParams; 106 } 107 108 /** 109 * should never be called. 110 */ 111 protected void engineSetMode( 112 String mode) 113 { 114 if (!mode.equalsIgnoreCase("ECB")) 115 { 116 throw new IllegalArgumentException("can't support mode " + mode); 117 } 118 } 119 120 /** 121 * should never be called. 122 */ 123 protected void engineSetPadding( 124 String padding) 125 throws NoSuchPaddingException 126 { 127 if (!padding.equalsIgnoreCase("NoPadding")) 128 { 129 throw new NoSuchPaddingException("Padding " + padding + " unknown."); 130 } 131 } 132 133 protected void engineInit( 134 int opmode, 135 Key key, 136 AlgorithmParameterSpec params, 137 SecureRandom random) 138 throws InvalidKeyException, InvalidAlgorithmParameterException 139 { 140 CipherParameters param; 141 142 this.pbeSpec = null; 143 this.pbeAlgorithm = null; 144 145 this.engineParams = null; 146 147 // 148 // basic key check 149 // 150 if (!(key instanceof SecretKey)) 151 { 152 throw new InvalidKeyException("Key for algorithm " + key.getAlgorithm() + " not suitable for symmetric enryption."); 153 } 154 155 if (key instanceof BCPBEKey) 156 { 157 BCPBEKey k = (BCPBEKey)key; 158 159 if (k.getOID() != null) 160 { 161 pbeAlgorithm = k.getOID().getId(); 162 } 163 else 164 { 165 pbeAlgorithm = k.getAlgorithm(); 166 } 167 168 if (k.getParam() != null) 169 { 170 param = k.getParam(); 171 pbeSpec = new PBEParameterSpec(k.getSalt(), k.getIterationCount()); 172 } 173 else if (params instanceof PBEParameterSpec) 174 { 175 param = PBE.Util.makePBEParameters(k, params, cipher.getAlgorithmName()); 176 pbeSpec = (PBEParameterSpec)params; 177 } 178 else 179 { 180 throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set."); 181 } 182 183 if (k.getIvSize() != 0) 184 { 185 ivParam = (ParametersWithIV)param; 186 } 187 } 188 else if (params == null) 189 { 190 param = new KeyParameter(key.getEncoded()); 191 } 192 else if (params instanceof IvParameterSpec) 193 { 194 param = new ParametersWithIV(new KeyParameter(key.getEncoded()), ((IvParameterSpec)params).getIV()); 195 ivParam = (ParametersWithIV)param; 196 } 197 else 198 { 199 throw new InvalidAlgorithmParameterException("unknown parameter type."); 200 } 201 202 if ((ivLength != 0) && !(param instanceof ParametersWithIV)) 203 { 204 SecureRandom ivRandom = random; 205 206 if (ivRandom == null) 207 { 208 ivRandom = new SecureRandom(); 209 } 210 211 if ((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher.WRAP_MODE)) 212 { 213 byte[] iv = new byte[ivLength]; 214 215 ivRandom.nextBytes(iv); 216 param = new ParametersWithIV(param, iv); 217 ivParam = (ParametersWithIV)param; 218 } 219 else 220 { 221 throw new InvalidAlgorithmParameterException("no IV set when one expected"); 222 } 223 } 224 225 try 226 { 227 switch (opmode) 228 { 229 case Cipher.ENCRYPT_MODE: 230 case Cipher.WRAP_MODE: 231 cipher.init(true, param); 232 break; 233 case Cipher.DECRYPT_MODE: 234 case Cipher.UNWRAP_MODE: 235 cipher.init(false, param); 236 break; 237 default: 238 throw new InvalidParameterException("unknown opmode " + opmode + " passed"); 239 } 240 } 241 catch (Exception e) 242 { 243 throw new InvalidKeyException(e.getMessage()); 244 } 245 } 246 247 protected void engineInit( 248 int opmode, 249 Key key, 250 AlgorithmParameters params, 251 SecureRandom random) 252 throws InvalidKeyException, InvalidAlgorithmParameterException 253 { 254 AlgorithmParameterSpec paramSpec = null; 255 256 if (params != null) 257 { 258 for (int i = 0; i != availableSpecs.length; i++) 259 { 260 try 261 { 262 paramSpec = params.getParameterSpec(availableSpecs[i]); 263 break; 264 } 265 catch (Exception e) 266 { 267 continue; 268 } 269 } 270 271 if (paramSpec == null) 272 { 273 throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString()); 274 } 275 } 276 277 engineInit(opmode, key, paramSpec, random); 278 engineParams = params; 279 } 280 281 protected void engineInit( 282 int opmode, 283 Key key, 284 SecureRandom random) 285 throws InvalidKeyException 286 { 287 try 288 { 289 engineInit(opmode, key, (AlgorithmParameterSpec)null, random); 290 } 291 catch (InvalidAlgorithmParameterException e) 292 { 293 throw new InvalidKeyException(e.getMessage()); 294 } 295 } 296 297 protected byte[] engineUpdate( 298 byte[] input, 299 int inputOffset, 300 int inputLen) 301 { 302 byte[] out = new byte[inputLen]; 303 304 cipher.processBytes(input, inputOffset, inputLen, out, 0); 305 306 return out; 307 } 308 309 protected int engineUpdate( 310 byte[] input, 311 int inputOffset, 312 int inputLen, 313 byte[] output, 314 int outputOffset) 315 throws ShortBufferException 316 { 317 try 318 { 319 cipher.processBytes(input, inputOffset, inputLen, output, outputOffset); 320 321 return inputLen; 322 } 323 catch (DataLengthException e) 324 { 325 throw new ShortBufferException(e.getMessage()); 326 } 327 } 328 329 protected byte[] engineDoFinal( 330 byte[] input, 331 int inputOffset, 332 int inputLen) 333 { 334 if (inputLen != 0) 335 { 336 byte[] out = engineUpdate(input, inputOffset, inputLen); 337 338 cipher.reset(); 339 340 return out; 341 } 342 343 cipher.reset(); 344 345 return new byte[0]; 346 } 347 348 protected int engineDoFinal( 349 byte[] input, 350 int inputOffset, 351 int inputLen, 352 byte[] output, 353 int outputOffset) 354 { 355 if (inputLen != 0) 356 { 357 cipher.processBytes(input, inputOffset, inputLen, output, outputOffset); 358 } 359 360 cipher.reset(); 361 362 return inputLen; 363 } 364} 365