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