1 package org.bouncycastle.jcajce.provider.symmetric.util; 2 3 import java.lang.reflect.Constructor; 4 import java.lang.reflect.Method; 5 import java.nio.ByteBuffer; 6 import java.security.AlgorithmParameters; 7 import java.security.InvalidAlgorithmParameterException; 8 import java.security.InvalidKeyException; 9 import java.security.InvalidParameterException; 10 import java.security.Key; 11 import java.security.NoSuchAlgorithmException; 12 import java.security.SecureRandom; 13 import java.security.spec.AlgorithmParameterSpec; 14 15 import javax.crypto.BadPaddingException; 16 import javax.crypto.Cipher; 17 import javax.crypto.IllegalBlockSizeException; 18 import javax.crypto.NoSuchPaddingException; 19 import javax.crypto.SecretKey; 20 import javax.crypto.ShortBufferException; 21 import javax.crypto.interfaces.PBEKey; 22 import javax.crypto.spec.IvParameterSpec; 23 // BEGIN android-added 24 import javax.crypto.spec.PBEKeySpec; 25 // END android-added 26 import javax.crypto.spec.PBEParameterSpec; 27 // BEGIN android-removed 28 // import javax.crypto.spec.RC2ParameterSpec; 29 // import javax.crypto.spec.RC5ParameterSpec; 30 // END android-removed 31 32 import org.bouncycastle.asn1.cms.GCMParameters; 33 import org.bouncycastle.crypto.BlockCipher; 34 import org.bouncycastle.crypto.BufferedBlockCipher; 35 import org.bouncycastle.crypto.CipherParameters; 36 import org.bouncycastle.crypto.DataLengthException; 37 import org.bouncycastle.crypto.InvalidCipherTextException; 38 import org.bouncycastle.crypto.OutputLengthException; 39 import org.bouncycastle.crypto.modes.AEADBlockCipher; 40 import org.bouncycastle.crypto.modes.CBCBlockCipher; 41 import org.bouncycastle.crypto.modes.CCMBlockCipher; 42 import org.bouncycastle.crypto.modes.CFBBlockCipher; 43 import org.bouncycastle.crypto.modes.CTSBlockCipher; 44 // BEGIN android-removed 45 // import org.bouncycastle.crypto.modes.EAXBlockCipher; 46 // import org.bouncycastle.crypto.modes.GCFBBlockCipher; 47 // END android-removed 48 import org.bouncycastle.crypto.modes.GCMBlockCipher; 49 // BEGIN android-removed 50 // import org.bouncycastle.crypto.modes.GOFBBlockCipher; 51 // import org.bouncycastle.crypto.modes.OCBBlockCipher; 52 // END android-removed 53 import org.bouncycastle.crypto.modes.OFBBlockCipher; 54 // BEGIN android-removed 55 // import org.bouncycastle.crypto.modes.OpenPGPCFBBlockCipher; 56 // import org.bouncycastle.crypto.modes.PGPCFBBlockCipher; 57 // END android-removed 58 import org.bouncycastle.crypto.modes.SICBlockCipher; 59 import org.bouncycastle.crypto.paddings.BlockCipherPadding; 60 import org.bouncycastle.crypto.paddings.ISO10126d2Padding; 61 import org.bouncycastle.crypto.paddings.ISO7816d4Padding; 62 import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher; 63 import org.bouncycastle.crypto.paddings.TBCPadding; 64 import org.bouncycastle.crypto.paddings.X923Padding; 65 import org.bouncycastle.crypto.paddings.ZeroBytePadding; 66 import org.bouncycastle.crypto.params.AEADParameters; 67 import org.bouncycastle.crypto.params.KeyParameter; 68 import org.bouncycastle.crypto.params.ParametersWithIV; 69 import org.bouncycastle.crypto.params.ParametersWithRandom; 70 // BEGIN android-removed 71 // import org.bouncycastle.crypto.params.ParametersWithSBox; 72 // END android-removed 73 import org.bouncycastle.crypto.params.RC2Parameters; 74 // BEGIN android-removed 75 // import org.bouncycastle.crypto.params.RC5Parameters; 76 // import org.bouncycastle.jcajce.PBKDF1Key; 77 // import org.bouncycastle.jcajce.PBKDF1KeyWithParameters; 78 // END android-removed 79 import org.bouncycastle.jcajce.PKCS12Key; 80 import org.bouncycastle.jcajce.PKCS12KeyWithParameters; 81 import org.bouncycastle.jcajce.spec.AEADParameterSpec; 82 // BEGIN android-removed 83 // import org.bouncycastle.jcajce.spec.GOST28147ParameterSpec; 84 // import org.bouncycastle.jcajce.spec.RepeatedSecretKeySpec; 85 // END android-removed 86 import org.bouncycastle.util.Strings; 87 88 public class BaseBlockCipher 89 extends BaseWrapCipher 90 implements PBE 91 { 92 private static final Class gcmSpecClass = lookup("javax.crypto.spec.GCMParameterSpec"); 93 94 // 95 // specs we can handle. 96 // 97 private Class[] availableSpecs = 98 { 99 // BEGIN android-removed 100 // RC2ParameterSpec.class, 101 // RC5ParameterSpec.class, 102 // END android-removed 103 gcmSpecClass, 104 IvParameterSpec.class, 105 PBEParameterSpec.class, 106 // BEGIN android-removed 107 // GOST28147ParameterSpec.class 108 // END android-removed 109 }; 110 111 private BlockCipher baseEngine; 112 private BlockCipherProvider engineProvider; 113 private GenericBlockCipher cipher; 114 private ParametersWithIV ivParam; 115 private AEADParameters aeadParams; 116 117 private int keySizeInBits; 118 private int scheme = -1; 119 private int digest; 120 121 private int ivLength = 0; 122 123 private boolean padded; 124 private boolean fixedIv = true; 125 private PBEParameterSpec pbeSpec = null; 126 private String pbeAlgorithm = null; 127 128 private String modeName = null; 129 lookup(String className)130 private static Class lookup(String className) 131 { 132 try 133 { 134 Class def = BaseBlockCipher.class.getClassLoader().loadClass(className); 135 136 return def; 137 } 138 catch (Exception e) 139 { 140 return null; 141 } 142 } 143 BaseBlockCipher( BlockCipher engine)144 protected BaseBlockCipher( 145 BlockCipher engine) 146 { 147 baseEngine = engine; 148 149 cipher = new BufferedGenericBlockCipher(engine); 150 } 151 BaseBlockCipher( BlockCipher engine, int scheme, int digest, int keySizeInBits, int ivLength)152 protected BaseBlockCipher( 153 BlockCipher engine, 154 int scheme, 155 int digest, 156 int keySizeInBits, 157 int ivLength) 158 { 159 baseEngine = engine; 160 161 this.scheme = scheme; 162 this.digest = digest; 163 this.keySizeInBits = keySizeInBits; 164 this.ivLength = ivLength; 165 166 cipher = new BufferedGenericBlockCipher(engine); 167 } 168 BaseBlockCipher( BlockCipherProvider provider)169 protected BaseBlockCipher( 170 BlockCipherProvider provider) 171 { 172 baseEngine = provider.get(); 173 engineProvider = provider; 174 175 cipher = new BufferedGenericBlockCipher(provider.get()); 176 } 177 BaseBlockCipher( AEADBlockCipher engine)178 protected BaseBlockCipher( 179 AEADBlockCipher engine) 180 { 181 this.baseEngine = engine.getUnderlyingCipher(); 182 this.ivLength = baseEngine.getBlockSize(); 183 this.cipher = new AEADGenericBlockCipher(engine); 184 } 185 BaseBlockCipher( AEADBlockCipher engine, boolean fixedIv, int ivLength)186 protected BaseBlockCipher( 187 AEADBlockCipher engine, 188 boolean fixedIv, 189 int ivLength) 190 { 191 this.baseEngine = engine.getUnderlyingCipher(); 192 this.fixedIv = fixedIv; 193 this.ivLength = ivLength; 194 this.cipher = new AEADGenericBlockCipher(engine); 195 } 196 BaseBlockCipher( org.bouncycastle.crypto.BlockCipher engine, int ivLength)197 protected BaseBlockCipher( 198 org.bouncycastle.crypto.BlockCipher engine, 199 int ivLength) 200 { 201 baseEngine = engine; 202 203 this.cipher = new BufferedGenericBlockCipher(engine); 204 this.ivLength = ivLength / 8; 205 } 206 BaseBlockCipher( BufferedBlockCipher engine, int ivLength)207 protected BaseBlockCipher( 208 BufferedBlockCipher engine, 209 int ivLength) 210 { 211 baseEngine = engine.getUnderlyingCipher(); 212 213 this.cipher = new BufferedGenericBlockCipher(engine); 214 this.ivLength = ivLength / 8; 215 } 216 engineGetBlockSize()217 protected int engineGetBlockSize() 218 { 219 return baseEngine.getBlockSize(); 220 } 221 engineGetIV()222 protected byte[] engineGetIV() 223 { 224 if (aeadParams != null) 225 { 226 return aeadParams.getNonce(); 227 } 228 229 return (ivParam != null) ? ivParam.getIV() : null; 230 } 231 engineGetKeySize( Key key)232 protected int engineGetKeySize( 233 Key key) 234 { 235 return key.getEncoded().length * 8; 236 } 237 engineGetOutputSize( int inputLen)238 protected int engineGetOutputSize( 239 int inputLen) 240 { 241 return cipher.getOutputSize(inputLen); 242 } 243 engineGetParameters()244 protected AlgorithmParameters engineGetParameters() 245 { 246 if (engineParams == null) 247 { 248 if (pbeSpec != null) 249 { 250 try 251 { 252 engineParams = createParametersInstance(pbeAlgorithm); 253 engineParams.init(pbeSpec); 254 } 255 catch (Exception e) 256 { 257 return null; 258 } 259 } 260 else if (aeadParams != null) 261 { 262 try 263 { 264 engineParams = createParametersInstance("GCM"); 265 engineParams.init(new GCMParameters(aeadParams.getNonce(), aeadParams.getMacSize() / 8).getEncoded()); 266 } 267 catch (Exception e) 268 { 269 throw new RuntimeException(e.toString()); 270 } 271 } 272 else if (ivParam != null) 273 { 274 String name = cipher.getUnderlyingCipher().getAlgorithmName(); 275 276 if (name.indexOf('/') >= 0) 277 { 278 name = name.substring(0, name.indexOf('/')); 279 } 280 281 try 282 { 283 engineParams = createParametersInstance(name); 284 engineParams.init(ivParam.getIV()); 285 } 286 catch (Exception e) 287 { 288 throw new RuntimeException(e.toString()); 289 } 290 } 291 } 292 293 return engineParams; 294 } 295 engineSetMode( String mode)296 protected void engineSetMode( 297 String mode) 298 throws NoSuchAlgorithmException 299 { 300 modeName = Strings.toUpperCase(mode); 301 302 if (modeName.equals("ECB")) 303 { 304 ivLength = 0; 305 cipher = new BufferedGenericBlockCipher(baseEngine); 306 } 307 else if (modeName.equals("CBC")) 308 { 309 ivLength = baseEngine.getBlockSize(); 310 cipher = new BufferedGenericBlockCipher( 311 new CBCBlockCipher(baseEngine)); 312 } 313 else if (modeName.startsWith("OFB")) 314 { 315 ivLength = baseEngine.getBlockSize(); 316 if (modeName.length() != 3) 317 { 318 int wordSize = Integer.parseInt(modeName.substring(3)); 319 320 cipher = new BufferedGenericBlockCipher( 321 new OFBBlockCipher(baseEngine, wordSize)); 322 } 323 else 324 { 325 cipher = new BufferedGenericBlockCipher( 326 new OFBBlockCipher(baseEngine, 8 * baseEngine.getBlockSize())); 327 } 328 } 329 else if (modeName.startsWith("CFB")) 330 { 331 ivLength = baseEngine.getBlockSize(); 332 if (modeName.length() != 3) 333 { 334 int wordSize = Integer.parseInt(modeName.substring(3)); 335 336 cipher = new BufferedGenericBlockCipher( 337 new CFBBlockCipher(baseEngine, wordSize)); 338 } 339 else 340 { 341 cipher = new BufferedGenericBlockCipher( 342 new CFBBlockCipher(baseEngine, 8 * baseEngine.getBlockSize())); 343 } 344 } 345 // BEGIN android-removed 346 // else if (modeName.startsWith("PGP")) 347 // { 348 // boolean inlineIV = modeName.equalsIgnoreCase("PGPCFBwithIV"); 349 // 350 // ivLength = baseEngine.getBlockSize(); 351 // cipher = new BufferedGenericBlockCipher( 352 // new PGPCFBBlockCipher(baseEngine, inlineIV)); 353 // } 354 // else if (modeName.equalsIgnoreCase("OpenPGPCFB")) 355 // { 356 // ivLength = 0; 357 // cipher = new BufferedGenericBlockCipher( 358 // new OpenPGPCFBBlockCipher(baseEngine)); 359 // } 360 // else if (modeName.startsWith("SIC")) 361 // { 362 // ivLength = baseEngine.getBlockSize(); 363 // if (ivLength < 16) 364 // { 365 // throw new IllegalArgumentException("Warning: SIC-Mode can become a twotime-pad if the blocksize of the cipher is too small. Use a cipher with a block size of at least 128 bits (e.g. AES)"); 366 // } 367 // fixedIv = false; 368 // cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher( 369 // new SICBlockCipher(baseEngine))); 370 // } 371 // END android-removed 372 else if (modeName.startsWith("CTR")) 373 { 374 ivLength = baseEngine.getBlockSize(); 375 fixedIv = false; 376 cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher( 377 new SICBlockCipher(baseEngine))); 378 } 379 // BEGIN android-removed 380 // else if (modeName.startsWith("GOFB")) 381 // { 382 // ivLength = baseEngine.getBlockSize(); 383 // cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher( 384 // new GOFBBlockCipher(baseEngine))); 385 // } 386 // else if (modeName.startsWith("GCFB")) 387 // { 388 // ivLength = baseEngine.getBlockSize(); 389 // cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher( 390 // new GCFBBlockCipher(baseEngine))); 391 // } 392 // END android-removed 393 else if (modeName.startsWith("CTS")) 394 { 395 ivLength = baseEngine.getBlockSize(); 396 cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(new CBCBlockCipher(baseEngine))); 397 } 398 else if (modeName.startsWith("CCM")) 399 { 400 ivLength = 13; // CCM nonce 7..13 bytes 401 cipher = new AEADGenericBlockCipher(new CCMBlockCipher(baseEngine)); 402 } 403 // BEGIN android-removed 404 // else if (modeName.startsWith("OCB")) 405 // { 406 // if (engineProvider != null) 407 // { 408 // /* 409 // * RFC 7253 4.2. Nonce is a string of no more than 120 bits 410 // */ 411 // ivLength = 15; 412 // cipher = new AEADGenericBlockCipher(new OCBBlockCipher(baseEngine, engineProvider.get())); 413 // } 414 // else 415 // { 416 // throw new NoSuchAlgorithmException("can't support mode " + mode); 417 // } 418 // } 419 // else if (modeName.startsWith("EAX")) 420 // { 421 // ivLength = baseEngine.getBlockSize(); 422 // cipher = new AEADGenericBlockCipher(new EAXBlockCipher(baseEngine)); 423 // } 424 // END android-removed 425 else if (modeName.startsWith("GCM")) 426 { 427 ivLength = baseEngine.getBlockSize(); 428 cipher = new AEADGenericBlockCipher(new GCMBlockCipher(baseEngine)); 429 } 430 else 431 { 432 throw new NoSuchAlgorithmException("can't support mode " + mode); 433 } 434 } 435 engineSetPadding( String padding)436 protected void engineSetPadding( 437 String padding) 438 throws NoSuchPaddingException 439 { 440 String paddingName = Strings.toUpperCase(padding); 441 442 if (paddingName.equals("NOPADDING")) 443 { 444 if (cipher.wrapOnNoPadding()) 445 { 446 cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(cipher.getUnderlyingCipher())); 447 } 448 } 449 else if (paddingName.equals("WITHCTS")) 450 { 451 cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(cipher.getUnderlyingCipher())); 452 } 453 else 454 { 455 padded = true; 456 457 if (isAEADModeName(modeName)) 458 { 459 throw new NoSuchPaddingException("Only NoPadding can be used with AEAD modes."); 460 } 461 else if (paddingName.equals("PKCS5PADDING") || paddingName.equals("PKCS7PADDING")) 462 { 463 cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher()); 464 } 465 else if (paddingName.equals("ZEROBYTEPADDING")) 466 { 467 cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ZeroBytePadding()); 468 } 469 else if (paddingName.equals("ISO10126PADDING") || paddingName.equals("ISO10126-2PADDING")) 470 { 471 cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ISO10126d2Padding()); 472 } 473 else if (paddingName.equals("X9.23PADDING") || paddingName.equals("X923PADDING")) 474 { 475 cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new X923Padding()); 476 } 477 else if (paddingName.equals("ISO7816-4PADDING") || paddingName.equals("ISO9797-1PADDING")) 478 { 479 cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ISO7816d4Padding()); 480 } 481 else if (paddingName.equals("TBCPADDING")) 482 { 483 cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new TBCPadding()); 484 } 485 else 486 { 487 throw new NoSuchPaddingException("Padding " + padding + " unknown."); 488 } 489 } 490 } 491 492 // BEGIN android-added 493 // TODO(27995180): This might need to be removed if we drop support for BCPBE keys without IV 494 // in PKCS12 isBCPBEKeyWithoutIV(Key key)495 private boolean isBCPBEKeyWithoutIV(Key key) { 496 return (key instanceof BCPBEKey) && !(((BCPBEKey)key).getParam() instanceof ParametersWithIV); 497 } 498 // END android-added 499 engineInit( int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random)500 protected void engineInit( 501 int opmode, 502 Key key, 503 AlgorithmParameterSpec params, 504 SecureRandom random) 505 throws InvalidKeyException, InvalidAlgorithmParameterException 506 { 507 CipherParameters param; 508 509 this.pbeSpec = null; 510 this.pbeAlgorithm = null; 511 this.engineParams = null; 512 this.aeadParams = null; 513 514 // 515 // basic key check 516 // 517 if (!(key instanceof SecretKey)) 518 { 519 throw new InvalidKeyException("Key for algorithm " + ((key != null) ? key.getAlgorithm() : null) + " not suitable for symmetric enryption."); 520 } 521 522 // 523 // for RC5-64 we must have some default parameters 524 // 525 if (params == null && baseEngine.getAlgorithmName().startsWith("RC5-64")) 526 { 527 throw new InvalidAlgorithmParameterException("RC5 requires an RC5ParametersSpec to be passed in."); 528 } 529 530 // 531 // a note on iv's - if ivLength is zero the IV gets ignored (we don't use it). 532 // 533 // BEGIN android-changed 534 // Was: if (scheme == PKCS12 || key instanceof PKCS12Key) 535 // If the key is a BCPBE one without an IV, ignore the fact that the scheme is PKCS12. 536 // TODO(27995180): consider whether we want to keep support for these keys and PKCS12. 537 if ((scheme == PKCS12 || key instanceof PKCS12Key) && !isBCPBEKeyWithoutIV(key)) 538 // END android-changed 539 { 540 SecretKey k; 541 try 542 { 543 k = (SecretKey)key; 544 } 545 catch (Exception e) 546 { 547 throw new InvalidKeyException("PKCS12 requires a SecretKey/PBEKey"); 548 } 549 550 if (params instanceof PBEParameterSpec) 551 { 552 pbeSpec = (PBEParameterSpec)params; 553 } 554 555 if (k instanceof PBEKey && pbeSpec == null) 556 { 557 PBEKey pbeKey = (PBEKey)k; 558 if (pbeKey.getSalt() == null) 559 { 560 throw new InvalidAlgorithmParameterException("PBEKey requires parameters to specify salt"); 561 } 562 pbeSpec = new PBEParameterSpec(pbeKey.getSalt(), pbeKey.getIterationCount()); 563 } 564 565 if (pbeSpec == null && !(k instanceof PBEKey)) 566 { 567 throw new InvalidKeyException("Algorithm requires a PBE key"); 568 } 569 570 if (key instanceof BCPBEKey) 571 { 572 // PKCS#12 sets an IV, if we get a key that doesn't have ParametersWithIV we need to reject it. If the 573 // key has no parameters it means it's an old-school JCE PBE Key - we use getEncoded() on it. 574 CipherParameters pbeKeyParam = ((BCPBEKey)key).getParam(); 575 if (pbeKeyParam instanceof ParametersWithIV) 576 { 577 param = pbeKeyParam; 578 } 579 else if (pbeKeyParam == null) 580 { 581 // BEGIN android-changed 582 // Was: param = PBE.Util.makePBEParameters(k.getEncoded(), PKCS12, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName()); 583 // TODO(27995180): consider rejecting such keys for PKCS12 584 // See above for the android-changed with a TODO for the same bug that makes 585 // this code unreachable. 586 // END android-changed 587 throw new IllegalStateException("Unreachable code"); 588 } 589 else 590 { 591 throw new InvalidKeyException("Algorithm requires a PBE key suitable for PKCS12"); 592 } 593 } 594 else 595 { 596 param = PBE.Util.makePBEParameters(k.getEncoded(), PKCS12, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName()); 597 } 598 if (param instanceof ParametersWithIV) 599 { 600 ivParam = (ParametersWithIV)param; 601 } 602 } 603 // BEGIN android-removed 604 // else if (key instanceof PBKDF1Key) 605 // { 606 // PBKDF1Key k = (PBKDF1Key)key; 607 608 // if (params instanceof PBEParameterSpec) 609 // { 610 // pbeSpec = (PBEParameterSpec)params; 611 // } 612 // if (k instanceof PBKDF1KeyWithParameters && pbeSpec == null) 613 // { 614 // pbeSpec = new PBEParameterSpec(((PBKDF1KeyWithParameters)k).getSalt(), ((PBKDF1KeyWithParameters)k).getIterationCount()); 615 // } 616 617 // param = PBE.Util.makePBEParameters(k.getEncoded(), PKCS5S1, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName()); 618 // if (param instanceof ParametersWithIV) 619 // { 620 // ivParam = (ParametersWithIV)param; 621 // } 622 // } 623 // END android-removed 624 else if (key instanceof BCPBEKey) 625 { 626 BCPBEKey k = (BCPBEKey)key; 627 628 if (k.getOID() != null) 629 { 630 pbeAlgorithm = k.getOID().getId(); 631 } 632 else 633 { 634 pbeAlgorithm = k.getAlgorithm(); 635 } 636 637 if (k.getParam() != null) 638 { 639 param = adjustParameters(params, k.getParam()); 640 } 641 else if (params instanceof PBEParameterSpec) 642 { 643 pbeSpec = (PBEParameterSpec)params; 644 // BEGIN android-added 645 // At this point, k.getParam() == null, so the key hasn't been generated. If 646 // the parameters have non-default values, recreate the BCPBEKey from algorithm 647 // parameters as to generate the key. 648 if ((pbeSpec.getSalt().length != 0) && (pbeSpec.getIterationCount() > 0)) { 649 k = new BCPBEKey(k.getAlgorithm(), k.getOID(), k.getType(), k.getDigest(), 650 k.getKeySize(), k.getIvSize(), 651 new PBEKeySpec( 652 k.getPassword(), pbeSpec.getSalt(), pbeSpec.getIterationCount(), 653 k.getKeySize()), 654 null /* CipherParameters */); 655 } 656 // END android-added 657 param = PBE.Util.makePBEParameters(k, params, cipher.getUnderlyingCipher().getAlgorithmName()); 658 } 659 else 660 { 661 throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set."); 662 } 663 664 if (param instanceof ParametersWithIV) 665 { 666 ivParam = (ParametersWithIV)param; 667 } 668 } 669 else if (key instanceof PBEKey) 670 { 671 PBEKey k = (PBEKey)key; 672 pbeSpec = (PBEParameterSpec)params; 673 if (k instanceof PKCS12KeyWithParameters && pbeSpec == null) 674 { 675 pbeSpec = new PBEParameterSpec(k.getSalt(), k.getIterationCount()); 676 } 677 678 param = PBE.Util.makePBEParameters(k.getEncoded(), scheme, digest, keySizeInBits, ivLength * 8, pbeSpec, cipher.getAlgorithmName()); 679 if (param instanceof ParametersWithIV) 680 { 681 ivParam = (ParametersWithIV)param; 682 } 683 } 684 // BEGIN android-changed 685 // Was: else if (!(key instanceof RepeatedSecretKeySpec)) 686 else 687 // END android-changed 688 { 689 if (scheme == PKCS5S1 || scheme == PKCS5S1_UTF8 || scheme == PKCS5S2 || scheme == PKCS5S2_UTF8) 690 { 691 throw new InvalidKeyException("Algorithm requires a PBE key"); 692 } 693 param = new KeyParameter(key.getEncoded()); 694 } 695 // BEGIN android-removed 696 // else 697 // { 698 // param = null; 699 // } 700 // END android-removed 701 702 if (params instanceof AEADParameterSpec) 703 { 704 if (!isAEADModeName(modeName) && !(cipher instanceof AEADGenericBlockCipher)) 705 { 706 throw new InvalidAlgorithmParameterException("AEADParameterSpec can only be used with AEAD modes."); 707 } 708 709 AEADParameterSpec aeadSpec = (AEADParameterSpec)params; 710 711 KeyParameter keyParam; 712 if (param instanceof ParametersWithIV) 713 { 714 keyParam = (KeyParameter)((ParametersWithIV)param).getParameters(); 715 } 716 else 717 { 718 keyParam = (KeyParameter)param; 719 } 720 param = aeadParams = new AEADParameters(keyParam, aeadSpec.getMacSizeInBits(), aeadSpec.getNonce(), aeadSpec.getAssociatedData()); 721 } 722 else if (params instanceof IvParameterSpec) 723 { 724 if (ivLength != 0) 725 { 726 IvParameterSpec p = (IvParameterSpec)params; 727 728 if (p.getIV().length != ivLength && !(cipher instanceof AEADGenericBlockCipher) && fixedIv) 729 { 730 throw new InvalidAlgorithmParameterException("IV must be " + ivLength + " bytes long."); 731 } 732 733 if (param instanceof ParametersWithIV) 734 { 735 param = new ParametersWithIV(((ParametersWithIV)param).getParameters(), p.getIV()); 736 } 737 else 738 { 739 param = new ParametersWithIV(param, p.getIV()); 740 } 741 ivParam = (ParametersWithIV)param; 742 } 743 else 744 { 745 if (modeName != null && modeName.equals("ECB")) 746 { 747 throw new InvalidAlgorithmParameterException("ECB mode does not use an IV"); 748 } 749 } 750 } 751 // BEGIN android-removed 752 // else if (params instanceof GOST28147ParameterSpec) 753 // { 754 // GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params; 755 // 756 // param = new ParametersWithSBox( 757 // new KeyParameter(key.getEncoded()), ((GOST28147ParameterSpec)params).getSbox()); 758 // 759 // if (gost28147Param.getIV() != null && ivLength != 0) 760 // { 761 // if (param instanceof ParametersWithIV) 762 // { 763 // param = new ParametersWithIV(((ParametersWithIV)param).getParameters(), gost28147Param.getIV()); 764 // } 765 // else 766 // { 767 // param = new ParametersWithIV(param, gost28147Param.getIV()); 768 // } 769 // ivParam = (ParametersWithIV)param; 770 // } 771 // } 772 // else if (params instanceof RC2ParameterSpec) 773 // { 774 // RC2ParameterSpec rc2Param = (RC2ParameterSpec)params; 775 // 776 // param = new RC2Parameters(key.getEncoded(), ((RC2ParameterSpec)params).getEffectiveKeyBits()); 777 // 778 // if (rc2Param.getIV() != null && ivLength != 0) 779 // { 780 // if (param instanceof ParametersWithIV) 781 // { 782 // param = new ParametersWithIV(((ParametersWithIV)param).getParameters(), rc2Param.getIV()); 783 // } 784 // else 785 // { 786 // param = new ParametersWithIV(param, rc2Param.getIV()); 787 // } 788 // ivParam = (ParametersWithIV)param; 789 // } 790 // } 791 // else if (params instanceof RC5ParameterSpec) 792 // { 793 // RC5ParameterSpec rc5Param = (RC5ParameterSpec)params; 794 // 795 // param = new RC5Parameters(key.getEncoded(), ((RC5ParameterSpec)params).getRounds()); 796 // if (baseEngine.getAlgorithmName().startsWith("RC5")) 797 // { 798 // if (baseEngine.getAlgorithmName().equals("RC5-32")) 799 // { 800 // if (rc5Param.getWordSize() != 32) 801 // { 802 // throw new InvalidAlgorithmParameterException("RC5 already set up for a word size of 32 not " + rc5Param.getWordSize() + "."); 803 // } 804 // } 805 // else if (baseEngine.getAlgorithmName().equals("RC5-64")) 806 // { 807 // if (rc5Param.getWordSize() != 64) 808 // { 809 // throw new InvalidAlgorithmParameterException("RC5 already set up for a word size of 64 not " + rc5Param.getWordSize() + "."); 810 // } 811 // } 812 // } 813 // else 814 // { 815 // throw new InvalidAlgorithmParameterException("RC5 parameters passed to a cipher that is not RC5."); 816 // } 817 // if ((rc5Param.getIV() != null) && (ivLength != 0)) 818 // { 819 // if (param instanceof ParametersWithIV) 820 // { 821 // param = new ParametersWithIV(((ParametersWithIV)param).getParameters(), rc5Param.getIV()); 822 // } 823 // else 824 // { 825 // param = new ParametersWithIV(param, rc5Param.getIV()); 826 // } 827 // ivParam = (ParametersWithIV)param; 828 // } 829 // } 830 // END android-removed 831 else if (gcmSpecClass != null && gcmSpecClass.isInstance(params)) 832 { 833 if (!isAEADModeName(modeName) && !(cipher instanceof AEADGenericBlockCipher)) 834 { 835 throw new InvalidAlgorithmParameterException("GCMParameterSpec can only be used with AEAD modes."); 836 } 837 838 try 839 { 840 Method tLen = gcmSpecClass.getDeclaredMethod("getTLen", new Class[0]); 841 Method iv= gcmSpecClass.getDeclaredMethod("getIV", new Class[0]); 842 843 KeyParameter keyParam; 844 if (param instanceof ParametersWithIV) 845 { 846 keyParam = (KeyParameter)((ParametersWithIV)param).getParameters(); 847 } 848 else 849 { 850 keyParam = (KeyParameter)param; 851 } 852 param = aeadParams = new AEADParameters(keyParam, ((Integer)tLen.invoke(params, new Object[0])).intValue(), (byte[])iv.invoke(params, new Object[0])); 853 } 854 catch (Exception e) 855 { 856 throw new InvalidAlgorithmParameterException("Cannot process GCMParameterSpec."); 857 } 858 } 859 else if (params != null && !(params instanceof PBEParameterSpec)) 860 { 861 throw new InvalidAlgorithmParameterException("unknown parameter type."); 862 } 863 864 if ((ivLength != 0) && !(param instanceof ParametersWithIV) && !(param instanceof AEADParameters)) 865 { 866 SecureRandom ivRandom = random; 867 868 if (ivRandom == null) 869 { 870 ivRandom = new SecureRandom(); 871 } 872 if ((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher.WRAP_MODE)) 873 { 874 byte[] iv = new byte[ivLength]; 875 876 // BEGIN android-changed 877 // Was: ivRandom.nextBytes(iv); 878 // TODO(27995180): for such keys, consider whether we want to reject them or 879 // allow them if the IV is passed in the parameters 880 if (!isBCPBEKeyWithoutIV(key)) { 881 ivRandom.nextBytes(iv); 882 } 883 // END android-changed 884 param = new ParametersWithIV(param, iv); 885 ivParam = (ParametersWithIV)param; 886 } 887 else if (cipher.getUnderlyingCipher().getAlgorithmName().indexOf("PGPCFB") < 0) 888 { 889 // BEGIN android-changed 890 // Was: throw new InvalidAlgorithmParameterException("no IV set when one expected"); 891 // TODO(27995180): for such keys, consider whether we want to reject them or 892 // allow them if the IV is passed in the parameters 893 if (!isBCPBEKeyWithoutIV(key)) { 894 throw new InvalidAlgorithmParameterException("no IV set when one expected"); 895 } else { 896 // Mimic behaviour in 1.52 by using an IV of 0's 897 param = new ParametersWithIV(param, new byte[ivLength]); 898 ivParam = (ParametersWithIV)param; 899 } 900 // END android-changed 901 } 902 } 903 904 905 906 if (random != null && padded) 907 { 908 param = new ParametersWithRandom(param, random); 909 } 910 911 try 912 { 913 switch (opmode) 914 { 915 case Cipher.ENCRYPT_MODE: 916 case Cipher.WRAP_MODE: 917 cipher.init(true, param); 918 break; 919 case Cipher.DECRYPT_MODE: 920 case Cipher.UNWRAP_MODE: 921 cipher.init(false, param); 922 break; 923 default: 924 throw new InvalidParameterException("unknown opmode " + opmode + " passed"); 925 } 926 927 if (cipher instanceof AEADGenericBlockCipher && aeadParams == null) 928 { 929 AEADBlockCipher aeadCipher = ((AEADGenericBlockCipher)cipher).cipher; 930 931 aeadParams = new AEADParameters((KeyParameter)ivParam.getParameters(), aeadCipher.getMac().length * 8, ivParam.getIV()); 932 } 933 } 934 catch (final Exception e) 935 { 936 throw new InvalidKeyOrParametersException(e.getMessage(), e); 937 } 938 } 939 adjustParameters(AlgorithmParameterSpec params, CipherParameters param)940 private CipherParameters adjustParameters(AlgorithmParameterSpec params, CipherParameters param) 941 { 942 CipherParameters key; 943 944 if (param instanceof ParametersWithIV) 945 { 946 key = ((ParametersWithIV)param).getParameters(); 947 if (params instanceof IvParameterSpec) 948 { 949 IvParameterSpec iv = (IvParameterSpec)params; 950 951 ivParam = new ParametersWithIV(key, iv.getIV()); 952 param = ivParam; 953 } 954 // BEGIN android-removed 955 // else if (params instanceof GOST28147ParameterSpec) 956 // { 957 // // need to pick up IV and SBox. 958 // GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params; 959 // 960 // param = new ParametersWithSBox(param, gost28147Param.getSbox()); 961 // 962 // if (gost28147Param.getIV() != null && ivLength != 0) 963 // { 964 // ivParam = new ParametersWithIV(key, gost28147Param.getIV()); 965 // param = ivParam; 966 // } 967 // } 968 // END android-removed 969 } 970 else 971 { 972 if (params instanceof IvParameterSpec) 973 { 974 IvParameterSpec iv = (IvParameterSpec)params; 975 976 ivParam = new ParametersWithIV(param, iv.getIV()); 977 param = ivParam; 978 } 979 // BEGIN android-removed 980 // else if (params instanceof GOST28147ParameterSpec) 981 // { 982 // // need to pick up IV and SBox. 983 // GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params; 984 // 985 // param = new ParametersWithSBox(param, gost28147Param.getSbox()); 986 // 987 // if (gost28147Param.getIV() != null && ivLength != 0) 988 // { 989 // param = new ParametersWithIV(param, gost28147Param.getIV()); 990 // } 991 // } 992 // END android-removed 993 } 994 return param; 995 } 996 engineInit( int opmode, Key key, AlgorithmParameters params, SecureRandom random)997 protected void engineInit( 998 int opmode, 999 Key key, 1000 AlgorithmParameters params, 1001 SecureRandom random) 1002 throws InvalidKeyException, InvalidAlgorithmParameterException 1003 { 1004 AlgorithmParameterSpec paramSpec = null; 1005 1006 if (params != null) 1007 { 1008 for (int i = 0; i != availableSpecs.length; i++) 1009 { 1010 if (availableSpecs[i] == null) 1011 { 1012 continue; 1013 } 1014 1015 try 1016 { 1017 paramSpec = params.getParameterSpec(availableSpecs[i]); 1018 break; 1019 } 1020 catch (Exception e) 1021 { 1022 // try again if possible 1023 } 1024 } 1025 1026 if (paramSpec == null) 1027 { 1028 throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString()); 1029 } 1030 } 1031 1032 engineInit(opmode, key, paramSpec, random); 1033 1034 engineParams = params; 1035 } 1036 engineInit( int opmode, Key key, SecureRandom random)1037 protected void engineInit( 1038 int opmode, 1039 Key key, 1040 SecureRandom random) 1041 throws InvalidKeyException 1042 { 1043 try 1044 { 1045 engineInit(opmode, key, (AlgorithmParameterSpec)null, random); 1046 } 1047 catch (InvalidAlgorithmParameterException e) 1048 { 1049 throw new InvalidKeyException(e.getMessage()); 1050 } 1051 } 1052 engineUpdateAAD(byte[] input, int offset, int length)1053 protected void engineUpdateAAD(byte[] input, int offset, int length) 1054 { 1055 cipher.updateAAD(input, offset, length); 1056 } 1057 engineUpdateAAD(ByteBuffer bytebuffer)1058 protected void engineUpdateAAD(ByteBuffer bytebuffer) 1059 { 1060 int offset = bytebuffer.arrayOffset() + bytebuffer.position(); 1061 int length = bytebuffer.limit() - bytebuffer.position(); 1062 engineUpdateAAD(bytebuffer.array(), offset, length); 1063 } 1064 engineUpdate( byte[] input, int inputOffset, int inputLen)1065 protected byte[] engineUpdate( 1066 byte[] input, 1067 int inputOffset, 1068 int inputLen) 1069 { 1070 int length = cipher.getUpdateOutputSize(inputLen); 1071 1072 if (length > 0) 1073 { 1074 byte[] out = new byte[length]; 1075 1076 int len = cipher.processBytes(input, inputOffset, inputLen, out, 0); 1077 1078 if (len == 0) 1079 { 1080 return null; 1081 } 1082 else if (len != out.length) 1083 { 1084 byte[] tmp = new byte[len]; 1085 1086 System.arraycopy(out, 0, tmp, 0, len); 1087 1088 return tmp; 1089 } 1090 1091 return out; 1092 } 1093 1094 cipher.processBytes(input, inputOffset, inputLen, null, 0); 1095 1096 return null; 1097 } 1098 engineUpdate( byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset)1099 protected int engineUpdate( 1100 byte[] input, 1101 int inputOffset, 1102 int inputLen, 1103 byte[] output, 1104 int outputOffset) 1105 throws ShortBufferException 1106 { 1107 if (outputOffset + cipher.getUpdateOutputSize(inputLen) > output.length) 1108 { 1109 throw new ShortBufferException("output buffer too short for input."); 1110 } 1111 1112 try 1113 { 1114 return cipher.processBytes(input, inputOffset, inputLen, output, outputOffset); 1115 } 1116 catch (DataLengthException e) 1117 { 1118 // should never occur 1119 throw new IllegalStateException(e.toString()); 1120 } 1121 } 1122 engineDoFinal( byte[] input, int inputOffset, int inputLen)1123 protected byte[] engineDoFinal( 1124 byte[] input, 1125 int inputOffset, 1126 int inputLen) 1127 throws IllegalBlockSizeException, BadPaddingException 1128 { 1129 int len = 0; 1130 byte[] tmp = new byte[engineGetOutputSize(inputLen)]; 1131 1132 if (inputLen != 0) 1133 { 1134 len = cipher.processBytes(input, inputOffset, inputLen, tmp, 0); 1135 } 1136 1137 try 1138 { 1139 len += cipher.doFinal(tmp, len); 1140 } 1141 catch (DataLengthException e) 1142 { 1143 throw new IllegalBlockSizeException(e.getMessage()); 1144 } 1145 1146 if (len == tmp.length) 1147 { 1148 return tmp; 1149 } 1150 1151 byte[] out = new byte[len]; 1152 1153 System.arraycopy(tmp, 0, out, 0, len); 1154 1155 return out; 1156 } 1157 engineDoFinal( byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset)1158 protected int engineDoFinal( 1159 byte[] input, 1160 int inputOffset, 1161 int inputLen, 1162 byte[] output, 1163 int outputOffset) 1164 throws IllegalBlockSizeException, BadPaddingException, ShortBufferException 1165 { 1166 int len = 0; 1167 1168 if (outputOffset + engineGetOutputSize(inputLen) > output.length) 1169 { 1170 throw new ShortBufferException("output buffer too short for input."); 1171 } 1172 1173 try 1174 { 1175 if (inputLen != 0) 1176 { 1177 len = cipher.processBytes(input, inputOffset, inputLen, output, outputOffset); 1178 } 1179 1180 return (len + cipher.doFinal(output, outputOffset + len)); 1181 } 1182 catch (OutputLengthException e) 1183 { 1184 throw new IllegalBlockSizeException(e.getMessage()); 1185 } 1186 catch (DataLengthException e) 1187 { 1188 throw new IllegalBlockSizeException(e.getMessage()); 1189 } 1190 } 1191 isAEADModeName( String modeName)1192 private boolean isAEADModeName( 1193 String modeName) 1194 { 1195 // BEGIN android-changed 1196 return "CCM".equals(modeName) || "GCM".equals(modeName); 1197 // END android-changed 1198 } 1199 1200 /* 1201 * The ciphers that inherit from us. 1202 */ 1203 1204 static private interface GenericBlockCipher 1205 { init(boolean forEncryption, CipherParameters params)1206 public void init(boolean forEncryption, CipherParameters params) 1207 throws IllegalArgumentException; 1208 wrapOnNoPadding()1209 public boolean wrapOnNoPadding(); 1210 getAlgorithmName()1211 public String getAlgorithmName(); 1212 getUnderlyingCipher()1213 public org.bouncycastle.crypto.BlockCipher getUnderlyingCipher(); 1214 getOutputSize(int len)1215 public int getOutputSize(int len); 1216 getUpdateOutputSize(int len)1217 public int getUpdateOutputSize(int len); 1218 updateAAD(byte[] input, int offset, int length)1219 public void updateAAD(byte[] input, int offset, int length); 1220 processByte(byte in, byte[] out, int outOff)1221 public int processByte(byte in, byte[] out, int outOff) 1222 throws DataLengthException; 1223 processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)1224 public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) 1225 throws DataLengthException; 1226 doFinal(byte[] out, int outOff)1227 public int doFinal(byte[] out, int outOff) 1228 throws IllegalStateException, 1229 BadPaddingException; 1230 } 1231 1232 private static class BufferedGenericBlockCipher 1233 implements GenericBlockCipher 1234 { 1235 private BufferedBlockCipher cipher; 1236 BufferedGenericBlockCipher(BufferedBlockCipher cipher)1237 BufferedGenericBlockCipher(BufferedBlockCipher cipher) 1238 { 1239 this.cipher = cipher; 1240 } 1241 BufferedGenericBlockCipher(org.bouncycastle.crypto.BlockCipher cipher)1242 BufferedGenericBlockCipher(org.bouncycastle.crypto.BlockCipher cipher) 1243 { 1244 this.cipher = new PaddedBufferedBlockCipher(cipher); 1245 } 1246 BufferedGenericBlockCipher(org.bouncycastle.crypto.BlockCipher cipher, BlockCipherPadding padding)1247 BufferedGenericBlockCipher(org.bouncycastle.crypto.BlockCipher cipher, BlockCipherPadding padding) 1248 { 1249 this.cipher = new PaddedBufferedBlockCipher(cipher, padding); 1250 } 1251 init(boolean forEncryption, CipherParameters params)1252 public void init(boolean forEncryption, CipherParameters params) 1253 throws IllegalArgumentException 1254 { 1255 cipher.init(forEncryption, params); 1256 } 1257 wrapOnNoPadding()1258 public boolean wrapOnNoPadding() 1259 { 1260 return !(cipher instanceof CTSBlockCipher); 1261 } 1262 getAlgorithmName()1263 public String getAlgorithmName() 1264 { 1265 return cipher.getUnderlyingCipher().getAlgorithmName(); 1266 } 1267 getUnderlyingCipher()1268 public org.bouncycastle.crypto.BlockCipher getUnderlyingCipher() 1269 { 1270 return cipher.getUnderlyingCipher(); 1271 } 1272 getOutputSize(int len)1273 public int getOutputSize(int len) 1274 { 1275 return cipher.getOutputSize(len); 1276 } 1277 getUpdateOutputSize(int len)1278 public int getUpdateOutputSize(int len) 1279 { 1280 return cipher.getUpdateOutputSize(len); 1281 } 1282 updateAAD(byte[] input, int offset, int length)1283 public void updateAAD(byte[] input, int offset, int length) 1284 { 1285 throw new UnsupportedOperationException("AAD is not supported in the current mode."); 1286 } 1287 processByte(byte in, byte[] out, int outOff)1288 public int processByte(byte in, byte[] out, int outOff) throws DataLengthException 1289 { 1290 return cipher.processByte(in, out, outOff); 1291 } 1292 processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)1293 public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException 1294 { 1295 return cipher.processBytes(in, inOff, len, out, outOff); 1296 } 1297 doFinal(byte[] out, int outOff)1298 public int doFinal(byte[] out, int outOff) throws IllegalStateException, BadPaddingException 1299 { 1300 try 1301 { 1302 return cipher.doFinal(out, outOff); 1303 } 1304 catch (InvalidCipherTextException e) 1305 { 1306 throw new BadPaddingException(e.getMessage()); 1307 } 1308 } 1309 } 1310 1311 private static class AEADGenericBlockCipher 1312 implements GenericBlockCipher 1313 { 1314 private static final Constructor aeadBadTagConstructor; 1315 1316 static { 1317 Class aeadBadTagClass = lookup("javax.crypto.AEADBadTagException"); 1318 if (aeadBadTagClass != null) 1319 { 1320 aeadBadTagConstructor = findExceptionConstructor(aeadBadTagClass); 1321 } 1322 else 1323 { 1324 aeadBadTagConstructor = null; 1325 } 1326 } 1327 findExceptionConstructor(Class clazz)1328 private static Constructor findExceptionConstructor(Class clazz) 1329 { 1330 try 1331 { 1332 return clazz.getConstructor(new Class[]{String.class}); 1333 } 1334 catch (Exception e) 1335 { 1336 return null; 1337 } 1338 } 1339 1340 private AEADBlockCipher cipher; 1341 AEADGenericBlockCipher(AEADBlockCipher cipher)1342 AEADGenericBlockCipher(AEADBlockCipher cipher) 1343 { 1344 this.cipher = cipher; 1345 } 1346 init(boolean forEncryption, CipherParameters params)1347 public void init(boolean forEncryption, CipherParameters params) 1348 throws IllegalArgumentException 1349 { 1350 cipher.init(forEncryption, params); 1351 } 1352 getAlgorithmName()1353 public String getAlgorithmName() 1354 { 1355 return cipher.getUnderlyingCipher().getAlgorithmName(); 1356 } 1357 wrapOnNoPadding()1358 public boolean wrapOnNoPadding() 1359 { 1360 return false; 1361 } 1362 getUnderlyingCipher()1363 public org.bouncycastle.crypto.BlockCipher getUnderlyingCipher() 1364 { 1365 return cipher.getUnderlyingCipher(); 1366 } 1367 getOutputSize(int len)1368 public int getOutputSize(int len) 1369 { 1370 return cipher.getOutputSize(len); 1371 } 1372 getUpdateOutputSize(int len)1373 public int getUpdateOutputSize(int len) 1374 { 1375 return cipher.getUpdateOutputSize(len); 1376 } 1377 updateAAD(byte[] input, int offset, int length)1378 public void updateAAD(byte[] input, int offset, int length) 1379 { 1380 cipher.processAADBytes(input, offset, length); 1381 } 1382 processByte(byte in, byte[] out, int outOff)1383 public int processByte(byte in, byte[] out, int outOff) throws DataLengthException 1384 { 1385 return cipher.processByte(in, out, outOff); 1386 } 1387 processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)1388 public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException 1389 { 1390 return cipher.processBytes(in, inOff, len, out, outOff); 1391 } 1392 doFinal(byte[] out, int outOff)1393 public int doFinal(byte[] out, int outOff) throws IllegalStateException, BadPaddingException 1394 { 1395 try 1396 { 1397 return cipher.doFinal(out, outOff); 1398 } 1399 catch (InvalidCipherTextException e) 1400 { 1401 if (aeadBadTagConstructor != null) 1402 { 1403 BadPaddingException aeadBadTag = null; 1404 try 1405 { 1406 aeadBadTag = (BadPaddingException)aeadBadTagConstructor 1407 .newInstance(new Object[]{e.getMessage()}); 1408 } 1409 catch (Exception i) 1410 { 1411 // Shouldn't happen, but fall through to BadPaddingException 1412 } 1413 if (aeadBadTag != null) 1414 { 1415 throw aeadBadTag; 1416 } 1417 } 1418 throw new BadPaddingException(e.getMessage()); 1419 } 1420 } 1421 } 1422 1423 private static class InvalidKeyOrParametersException 1424 extends InvalidKeyException 1425 { 1426 private final Throwable cause; 1427 InvalidKeyOrParametersException(String msg, Throwable cause)1428 InvalidKeyOrParametersException(String msg, Throwable cause) 1429 { 1430 super(msg); 1431 this.cause = cause; 1432 } 1433 getCause()1434 public Throwable getCause() 1435 { 1436 return cause; 1437 } 1438 } 1439 } 1440