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