1package org.bouncycastle.jce.provider; 2 3import java.security.AlgorithmParameters; 4import java.security.InvalidAlgorithmParameterException; 5import java.security.InvalidKeyException; 6import java.security.InvalidParameterException; 7import java.security.Key; 8import java.security.NoSuchAlgorithmException; 9import java.security.SecureRandom; 10import java.security.spec.AlgorithmParameterSpec; 11 12import javax.crypto.BadPaddingException; 13import javax.crypto.Cipher; 14import javax.crypto.CipherSpi; 15import javax.crypto.IllegalBlockSizeException; 16import javax.crypto.NoSuchPaddingException; 17import javax.crypto.SecretKey; 18import javax.crypto.ShortBufferException; 19import javax.crypto.spec.IvParameterSpec; 20import javax.crypto.spec.PBEParameterSpec; 21// BEGIN android-removed 22// import javax.crypto.spec.RC2ParameterSpec; 23// import javax.crypto.spec.RC5ParameterSpec; 24// END android-removed 25 26import org.bouncycastle.crypto.BlockCipher; 27import org.bouncycastle.crypto.BufferedBlockCipher; 28import org.bouncycastle.crypto.CipherParameters; 29import org.bouncycastle.crypto.DataLengthException; 30import org.bouncycastle.crypto.InvalidCipherTextException; 31import org.bouncycastle.crypto.engines.AESFastEngine; 32import org.bouncycastle.crypto.engines.DESEngine; 33// BEGIN android-removed 34// import org.bouncycastle.crypto.engines.GOST28147Engine; 35// END android-removed 36import org.bouncycastle.crypto.engines.RC2Engine; 37import org.bouncycastle.crypto.engines.TwofishEngine; 38import org.bouncycastle.crypto.modes.AEADBlockCipher; 39import org.bouncycastle.crypto.modes.CBCBlockCipher; 40import org.bouncycastle.crypto.modes.CCMBlockCipher; 41import org.bouncycastle.crypto.modes.CFBBlockCipher; 42import org.bouncycastle.crypto.modes.CTSBlockCipher; 43// BEGIN android-removed 44// import org.bouncycastle.crypto.modes.EAXBlockCipher; 45// END android-removed 46import org.bouncycastle.crypto.modes.GCMBlockCipher; 47// BEGIN android-removed 48// import org.bouncycastle.crypto.modes.GOFBBlockCipher; 49// END android-removed 50import org.bouncycastle.crypto.modes.OFBBlockCipher; 51// BEGIN android-removed 52// import org.bouncycastle.crypto.modes.OpenPGPCFBBlockCipher; 53// import org.bouncycastle.crypto.modes.PGPCFBBlockCipher; 54// END android-removed 55import org.bouncycastle.crypto.modes.SICBlockCipher; 56import org.bouncycastle.crypto.paddings.BlockCipherPadding; 57import org.bouncycastle.crypto.paddings.ISO10126d2Padding; 58import org.bouncycastle.crypto.paddings.ISO7816d4Padding; 59import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher; 60import org.bouncycastle.crypto.paddings.TBCPadding; 61import org.bouncycastle.crypto.paddings.X923Padding; 62import org.bouncycastle.crypto.paddings.ZeroBytePadding; 63import org.bouncycastle.crypto.params.KeyParameter; 64import org.bouncycastle.crypto.params.ParametersWithIV; 65import org.bouncycastle.crypto.params.ParametersWithRandom; 66// BEGIN android-removed 67// import org.bouncycastle.crypto.params.ParametersWithSBox; 68// import org.bouncycastle.crypto.params.RC2Parameters; 69// import org.bouncycastle.crypto.params.RC5Parameters; 70// END android-removed 71import org.bouncycastle.jcajce.provider.symmetric.util.BCPBEKey; 72import org.bouncycastle.jcajce.provider.symmetric.util.PBE; 73// BEGIN android-removed 74// import org.bouncycastle.jce.spec.GOST28147ParameterSpec; 75// END android-removed 76import org.bouncycastle.jce.spec.RepeatedSecretKeySpec; 77import org.bouncycastle.util.Strings; 78 79public class JCEBlockCipher 80 extends CipherSpi 81 implements PBE 82{ 83 // 84 // specs we can handle. 85 // 86 private Class[] availableSpecs = 87 { 88 // BEGIN android-removed 89 // RC2ParameterSpec.class, 90 // RC5ParameterSpec.class, 91 // END android-removed 92 IvParameterSpec.class, 93 PBEParameterSpec.class, 94 // BEGIN android-removed 95 // GOST28147ParameterSpec.class 96 // END android-removed 97 }; 98 99 private BlockCipher baseEngine; 100 private GenericBlockCipher cipher; 101 private ParametersWithIV ivParam; 102 103 private int ivLength = 0; 104 105 private boolean padded; 106 107 private PBEParameterSpec pbeSpec = null; 108 private String pbeAlgorithm = null; 109 110 private String modeName = null; 111 112 private AlgorithmParameters engineParams; 113 114 protected JCEBlockCipher( 115 BlockCipher engine) 116 { 117 baseEngine = engine; 118 119 cipher = new BufferedGenericBlockCipher(engine); 120 } 121 122 protected JCEBlockCipher( 123 BlockCipher engine, 124 int ivLength) 125 { 126 baseEngine = engine; 127 128 this.cipher = new BufferedGenericBlockCipher(engine); 129 this.ivLength = ivLength / 8; 130 } 131 132 protected JCEBlockCipher( 133 BufferedBlockCipher engine, 134 int ivLength) 135 { 136 baseEngine = engine.getUnderlyingCipher(); 137 138 this.cipher = new BufferedGenericBlockCipher(engine); 139 this.ivLength = ivLength / 8; 140 } 141 142 protected int engineGetBlockSize() 143 { 144 return baseEngine.getBlockSize(); 145 } 146 147 protected byte[] engineGetIV() 148 { 149 return (ivParam != null) ? ivParam.getIV() : null; 150 } 151 152 protected int engineGetKeySize( 153 Key key) 154 { 155 return key.getEncoded().length * 8; 156 } 157 158 protected int engineGetOutputSize( 159 int inputLen) 160 { 161 return cipher.getOutputSize(inputLen); 162 } 163 164 protected AlgorithmParameters engineGetParameters() 165 { 166 if (engineParams == null) 167 { 168 if (pbeSpec != null) 169 { 170 try 171 { 172 engineParams = AlgorithmParameters.getInstance(pbeAlgorithm, BouncyCastleProvider.PROVIDER_NAME); 173 engineParams.init(pbeSpec); 174 } 175 catch (Exception e) 176 { 177 return null; 178 } 179 } 180 else if (ivParam != null) 181 { 182 String name = cipher.getUnderlyingCipher().getAlgorithmName(); 183 184 if (name.indexOf('/') >= 0) 185 { 186 name = name.substring(0, name.indexOf('/')); 187 } 188 189 try 190 { 191 engineParams = AlgorithmParameters.getInstance(name, BouncyCastleProvider.PROVIDER_NAME); 192 engineParams.init(ivParam.getIV()); 193 } 194 catch (Exception e) 195 { 196 throw new RuntimeException(e.toString()); 197 } 198 } 199 } 200 201 return engineParams; 202 } 203 204 protected void engineSetMode( 205 String mode) 206 throws NoSuchAlgorithmException 207 { 208 modeName = Strings.toUpperCase(mode); 209 210 if (modeName.equals("ECB")) 211 { 212 ivLength = 0; 213 cipher = new BufferedGenericBlockCipher(baseEngine); 214 } 215 else if (modeName.equals("CBC")) 216 { 217 ivLength = baseEngine.getBlockSize(); 218 cipher = new BufferedGenericBlockCipher( 219 new CBCBlockCipher(baseEngine)); 220 } 221 else if (modeName.startsWith("OFB")) 222 { 223 ivLength = baseEngine.getBlockSize(); 224 if (modeName.length() != 3) 225 { 226 int wordSize = Integer.parseInt(modeName.substring(3)); 227 228 cipher = new BufferedGenericBlockCipher( 229 new OFBBlockCipher(baseEngine, wordSize)); 230 } 231 else 232 { 233 cipher = new BufferedGenericBlockCipher( 234 new OFBBlockCipher(baseEngine, 8 * baseEngine.getBlockSize())); 235 } 236 } 237 else if (modeName.startsWith("CFB")) 238 { 239 ivLength = baseEngine.getBlockSize(); 240 if (modeName.length() != 3) 241 { 242 int wordSize = Integer.parseInt(modeName.substring(3)); 243 244 cipher = new BufferedGenericBlockCipher( 245 new CFBBlockCipher(baseEngine, wordSize)); 246 } 247 else 248 { 249 cipher = new BufferedGenericBlockCipher( 250 new CFBBlockCipher(baseEngine, 8 * baseEngine.getBlockSize())); 251 } 252 } 253 // BEGIN android-removed 254 // else if (modeName.startsWith("PGP")) 255 // { 256 // boolean inlineIV = modeName.equalsIgnoreCase("PGPCFBwithIV"); 257 // 258 // ivLength = baseEngine.getBlockSize(); 259 // cipher = new BufferedGenericBlockCipher( 260 // new PGPCFBBlockCipher(baseEngine, inlineIV)); 261 // } 262 // else if (modeName.equalsIgnoreCase("OpenPGPCFB")) 263 // { 264 // ivLength = 0; 265 // cipher = new BufferedGenericBlockCipher( 266 // new OpenPGPCFBBlockCipher(baseEngine)); 267 // } 268 // END android-removed 269 else if (modeName.startsWith("SIC")) 270 { 271 ivLength = baseEngine.getBlockSize(); 272 if (ivLength < 16) 273 { 274 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)"); 275 } 276 cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher( 277 new SICBlockCipher(baseEngine))); 278 } 279 else if (modeName.startsWith("CTR")) 280 { 281 ivLength = baseEngine.getBlockSize(); 282 cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher( 283 new SICBlockCipher(baseEngine))); 284 } 285 // BEGIN android-removed 286 // else if (modeName.startsWith("GOFB")) 287 // { 288 // ivLength = baseEngine.getBlockSize(); 289 // cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher( 290 // new GOFBBlockCipher(baseEngine))); 291 // } 292 // END android-removed 293 else if (modeName.startsWith("CTS")) 294 { 295 ivLength = baseEngine.getBlockSize(); 296 cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(new CBCBlockCipher(baseEngine))); 297 } 298 else if (modeName.startsWith("CCM")) 299 { 300 ivLength = baseEngine.getBlockSize(); 301 cipher = new AEADGenericBlockCipher(new CCMBlockCipher(baseEngine)); 302 } 303 // BEGIN android-removed 304 // else if (modeName.startsWith("EAX")) 305 // { 306 // ivLength = baseEngine.getBlockSize(); 307 // cipher = new AEADGenericBlockCipher(new EAXBlockCipher(baseEngine)); 308 // } 309 // END android-removed 310 else if (modeName.startsWith("GCM")) 311 { 312 ivLength = baseEngine.getBlockSize(); 313 cipher = new AEADGenericBlockCipher(new GCMBlockCipher(baseEngine)); 314 } 315 else 316 { 317 throw new NoSuchAlgorithmException("can't support mode " + mode); 318 } 319 } 320 321 protected void engineSetPadding( 322 String padding) 323 throws NoSuchPaddingException 324 { 325 String paddingName = Strings.toUpperCase(padding); 326 327 if (paddingName.equals("NOPADDING")) 328 { 329 if (cipher.wrapOnNoPadding()) 330 { 331 cipher = new BufferedGenericBlockCipher(new BufferedBlockCipher(cipher.getUnderlyingCipher())); 332 } 333 } 334 else if (paddingName.equals("WITHCTS")) 335 { 336 cipher = new BufferedGenericBlockCipher(new CTSBlockCipher(cipher.getUnderlyingCipher())); 337 } 338 else 339 { 340 padded = true; 341 342 if (isAEADModeName(modeName)) 343 { 344 throw new NoSuchPaddingException("Only NoPadding can be used with AEAD modes."); 345 } 346 else if (paddingName.equals("PKCS5PADDING") || paddingName.equals("PKCS7PADDING")) 347 { 348 cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher()); 349 } 350 else if (paddingName.equals("ZEROBYTEPADDING")) 351 { 352 cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ZeroBytePadding()); 353 } 354 else if (paddingName.equals("ISO10126PADDING") || paddingName.equals("ISO10126-2PADDING")) 355 { 356 cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ISO10126d2Padding()); 357 } 358 else if (paddingName.equals("X9.23PADDING") || paddingName.equals("X923PADDING")) 359 { 360 cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new X923Padding()); 361 } 362 else if (paddingName.equals("ISO7816-4PADDING") || paddingName.equals("ISO9797-1PADDING")) 363 { 364 cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new ISO7816d4Padding()); 365 } 366 else if (paddingName.equals("TBCPADDING")) 367 { 368 cipher = new BufferedGenericBlockCipher(cipher.getUnderlyingCipher(), new TBCPadding()); 369 } 370 else 371 { 372 throw new NoSuchPaddingException("Padding " + padding + " unknown."); 373 } 374 } 375 } 376 377 protected void engineInit( 378 int opmode, 379 Key key, 380 AlgorithmParameterSpec params, 381 SecureRandom random) 382 throws InvalidKeyException, InvalidAlgorithmParameterException 383 { 384 CipherParameters param; 385 386 this.pbeSpec = null; 387 this.pbeAlgorithm = null; 388 this.engineParams = null; 389 390 // 391 // basic key check 392 // 393 if (!(key instanceof SecretKey)) 394 { 395 throw new InvalidKeyException("Key for algorithm " + key.getAlgorithm() + " not suitable for symmetric enryption."); 396 } 397 398 // BEGIN android-removed 399 // // 400 // // for RC5-64 we must have some default parameters 401 // // 402 // if (params == null && baseEngine.getAlgorithmName().startsWith("RC5-64")) 403 // { 404 // throw new InvalidAlgorithmParameterException("RC5 requires an RC5ParametersSpec to be passed in."); 405 // } 406 // END android-removed 407 408 // 409 // a note on iv's - if ivLength is zero the IV gets ignored (we don't use it). 410 // 411 if (key instanceof BCPBEKey) 412 { 413 BCPBEKey k = (BCPBEKey)key; 414 415 if (k.getOID() != null) 416 { 417 pbeAlgorithm = k.getOID().getId(); 418 } 419 else 420 { 421 pbeAlgorithm = k.getAlgorithm(); 422 } 423 424 if (k.getParam() != null) 425 { 426 param = k.getParam(); 427 pbeSpec = new PBEParameterSpec(k.getSalt(), k.getIterationCount()); 428 } 429 else if (params instanceof PBEParameterSpec) 430 { 431 pbeSpec = (PBEParameterSpec)params; 432 param = PBE.Util.makePBEParameters(k, params, cipher.getUnderlyingCipher().getAlgorithmName()); 433 } 434 else 435 { 436 throw new InvalidAlgorithmParameterException("PBE requires PBE parameters to be set."); 437 } 438 439 if (param instanceof ParametersWithIV) 440 { 441 ivParam = (ParametersWithIV)param; 442 } 443 } 444 else if (params == null) 445 { 446 param = new KeyParameter(key.getEncoded()); 447 } 448 else if (params instanceof IvParameterSpec) 449 { 450 if (ivLength != 0) 451 { 452 IvParameterSpec p = (IvParameterSpec)params; 453 454 if (p.getIV().length != ivLength && !isAEADModeName(modeName)) 455 { 456 throw new InvalidAlgorithmParameterException("IV must be " + ivLength + " bytes long."); 457 } 458 459 if (key instanceof RepeatedSecretKeySpec) 460 { 461 param = new ParametersWithIV(null, p.getIV()); 462 ivParam = (ParametersWithIV)param; 463 } 464 else 465 { 466 param = new ParametersWithIV(new KeyParameter(key.getEncoded()), p.getIV()); 467 ivParam = (ParametersWithIV)param; 468 } 469 } 470 else 471 { 472 if (modeName != null && modeName.equals("ECB")) 473 { 474 throw new InvalidAlgorithmParameterException("ECB mode does not use an IV"); 475 } 476 477 param = new KeyParameter(key.getEncoded()); 478 } 479 } 480 // BEGIN android-removed 481 // else if (params instanceof GOST28147ParameterSpec) 482 // { 483 // GOST28147ParameterSpec gost28147Param = (GOST28147ParameterSpec)params; 484 // 485 // param = new ParametersWithSBox( 486 // new KeyParameter(key.getEncoded()), ((GOST28147ParameterSpec)params).getSbox()); 487 // 488 // if (gost28147Param.getIV() != null && ivLength != 0) 489 // { 490 // param = new ParametersWithIV(param, gost28147Param.getIV()); 491 // ivParam = (ParametersWithIV)param; 492 // } 493 // } 494 // else if (params instanceof RC2ParameterSpec) 495 // { 496 // RC2ParameterSpec rc2Param = (RC2ParameterSpec)params; 497 // 498 // param = new RC2Parameters(key.getEncoded(), ((RC2ParameterSpec)params).getEffectiveKeyBits()); 499 // 500 // if (rc2Param.getIV() != null && ivLength != 0) 501 // { 502 // param = new ParametersWithIV(param, rc2Param.getIV()); 503 // ivParam = (ParametersWithIV)param; 504 // } 505 // } 506 // else if (params instanceof RC5ParameterSpec) 507 // { 508 // RC5ParameterSpec rc5Param = (RC5ParameterSpec)params; 509 // 510 // param = new RC5Parameters(key.getEncoded(), ((RC5ParameterSpec)params).getRounds()); 511 // if (baseEngine.getAlgorithmName().startsWith("RC5")) 512 // { 513 // if (baseEngine.getAlgorithmName().equals("RC5-32")) 514 // { 515 // if (rc5Param.getWordSize() != 32) 516 // { 517 // throw new InvalidAlgorithmParameterException("RC5 already set up for a word size of 32 not " + rc5Param.getWordSize() + "."); 518 // } 519 // } 520 // else if (baseEngine.getAlgorithmName().equals("RC5-64")) 521 // { 522 // if (rc5Param.getWordSize() != 64) 523 // { 524 // throw new InvalidAlgorithmParameterException("RC5 already set up for a word size of 64 not " + rc5Param.getWordSize() + "."); 525 // } 526 // } 527 // } 528 // else 529 // { 530 // throw new InvalidAlgorithmParameterException("RC5 parameters passed to a cipher that is not RC5."); 531 // } 532 // if ((rc5Param.getIV() != null) && (ivLength != 0)) 533 // { 534 // param = new ParametersWithIV(param, rc5Param.getIV()); 535 // ivParam = (ParametersWithIV)param; 536 // } 537 // } 538 // END android-removed 539 else 540 { 541 throw new InvalidAlgorithmParameterException("unknown parameter type."); 542 } 543 544 if ((ivLength != 0) && !(param instanceof ParametersWithIV)) 545 { 546 SecureRandom ivRandom = random; 547 548 if (ivRandom == null) 549 { 550 ivRandom = new SecureRandom(); 551 } 552 553 if ((opmode == Cipher.ENCRYPT_MODE) || (opmode == Cipher.WRAP_MODE)) 554 { 555 byte[] iv = new byte[ivLength]; 556 557 ivRandom.nextBytes(iv); 558 param = new ParametersWithIV(param, iv); 559 ivParam = (ParametersWithIV)param; 560 } 561 else if (cipher.getUnderlyingCipher().getAlgorithmName().indexOf("PGPCFB") < 0) 562 { 563 throw new InvalidAlgorithmParameterException("no IV set when one expected"); 564 } 565 } 566 567 if (random != null && padded) 568 { 569 param = new ParametersWithRandom(param, random); 570 } 571 572 try 573 { 574 switch (opmode) 575 { 576 case Cipher.ENCRYPT_MODE: 577 case Cipher.WRAP_MODE: 578 cipher.init(true, param); 579 break; 580 case Cipher.DECRYPT_MODE: 581 case Cipher.UNWRAP_MODE: 582 cipher.init(false, param); 583 break; 584 default: 585 throw new InvalidParameterException("unknown opmode " + opmode + " passed"); 586 } 587 } 588 catch (Exception e) 589 { 590 throw new InvalidKeyException(e.getMessage()); 591 } 592 } 593 594 protected void engineInit( 595 int opmode, 596 Key key, 597 AlgorithmParameters params, 598 SecureRandom random) 599 throws InvalidKeyException, InvalidAlgorithmParameterException 600 { 601 AlgorithmParameterSpec paramSpec = null; 602 603 if (params != null) 604 { 605 for (int i = 0; i != availableSpecs.length; i++) 606 { 607 try 608 { 609 paramSpec = params.getParameterSpec(availableSpecs[i]); 610 break; 611 } 612 catch (Exception e) 613 { 614 // try again if possible 615 } 616 } 617 618 if (paramSpec == null) 619 { 620 throw new InvalidAlgorithmParameterException("can't handle parameter " + params.toString()); 621 } 622 } 623 624 engineInit(opmode, key, paramSpec, random); 625 626 engineParams = params; 627 } 628 629 protected void engineInit( 630 int opmode, 631 Key key, 632 SecureRandom random) 633 throws InvalidKeyException 634 { 635 try 636 { 637 engineInit(opmode, key, (AlgorithmParameterSpec)null, random); 638 } 639 catch (InvalidAlgorithmParameterException e) 640 { 641 throw new InvalidKeyException(e.getMessage()); 642 } 643 } 644 645 protected byte[] engineUpdate( 646 byte[] input, 647 int inputOffset, 648 int inputLen) 649 { 650 int length = cipher.getUpdateOutputSize(inputLen); 651 652 if (length > 0) 653 { 654 byte[] out = new byte[length]; 655 656 int len = cipher.processBytes(input, inputOffset, inputLen, out, 0); 657 658 if (len == 0) 659 { 660 return null; 661 } 662 else if (len != out.length) 663 { 664 byte[] tmp = new byte[len]; 665 666 System.arraycopy(out, 0, tmp, 0, len); 667 668 return tmp; 669 } 670 671 return out; 672 } 673 674 cipher.processBytes(input, inputOffset, inputLen, null, 0); 675 676 return null; 677 } 678 679 protected int engineUpdate( 680 byte[] input, 681 int inputOffset, 682 int inputLen, 683 byte[] output, 684 int outputOffset) 685 throws ShortBufferException 686 { 687 try 688 { 689 return cipher.processBytes(input, inputOffset, inputLen, output, outputOffset); 690 } 691 catch (DataLengthException e) 692 { 693 throw new ShortBufferException(e.getMessage()); 694 } 695 } 696 697 protected byte[] engineDoFinal( 698 byte[] input, 699 int inputOffset, 700 int inputLen) 701 throws IllegalBlockSizeException, BadPaddingException 702 { 703 int len = 0; 704 byte[] tmp = new byte[engineGetOutputSize(inputLen)]; 705 706 if (inputLen != 0) 707 { 708 len = cipher.processBytes(input, inputOffset, inputLen, tmp, 0); 709 } 710 711 try 712 { 713 len += cipher.doFinal(tmp, len); 714 } 715 catch (DataLengthException e) 716 { 717 throw new IllegalBlockSizeException(e.getMessage()); 718 } 719 catch (InvalidCipherTextException e) 720 { 721 throw new BadPaddingException(e.getMessage()); 722 } 723 724 if (len == tmp.length) 725 { 726 return tmp; 727 } 728 729 byte[] out = new byte[len]; 730 731 System.arraycopy(tmp, 0, out, 0, len); 732 733 return out; 734 } 735 736 protected int engineDoFinal( 737 byte[] input, 738 int inputOffset, 739 int inputLen, 740 byte[] output, 741 int outputOffset) 742 throws IllegalBlockSizeException, BadPaddingException, ShortBufferException 743 { 744 // BEGIN android-note 745 // added ShortBufferException to the throws statement 746 // END android-note 747 int len = 0; 748 749 // BEGIN android-added 750 int outputLen = cipher.getOutputSize(inputLen); 751 752 if (outputLen + outputOffset > output.length) { 753 throw new ShortBufferException("need at least " + outputLen + " bytes"); 754 } 755 // BEGIN android-added 756 757 if (inputLen != 0) 758 { 759 len = cipher.processBytes(input, inputOffset, inputLen, output, outputOffset); 760 } 761 762 try 763 { 764 return (len + cipher.doFinal(output, outputOffset + len)); 765 } 766 catch (DataLengthException e) 767 { 768 throw new IllegalBlockSizeException(e.getMessage()); 769 } 770 catch (InvalidCipherTextException e) 771 { 772 throw new BadPaddingException(e.getMessage()); 773 } 774 } 775 776 private boolean isAEADModeName( 777 String modeName) 778 { 779 return "CCM".equals(modeName) || "EAX".equals(modeName) || "GCM".equals(modeName); 780 } 781 782 /* 783 * The ciphers that inherit from us. 784 */ 785 786 /** 787 * DES 788 */ 789 static public class DES 790 extends JCEBlockCipher 791 { 792 public DES() 793 { 794 super(new DESEngine()); 795 } 796 } 797 798 // BEGIN android-removed 799 // /** 800 // * DESCBC 801 // */ 802 // static public class DESCBC 803 // extends JCEBlockCipher 804 // { 805 // public DESCBC() 806 // { 807 // super(new CBCBlockCipher(new DESEngine()), 64); 808 // } 809 // } 810 // 811 // /** 812 // * GOST28147 813 // */ 814 // static public class GOST28147 815 // extends JCEBlockCipher 816 // { 817 // public GOST28147() 818 // { 819 // super(new GOST28147Engine()); 820 // } 821 // } 822 // 823 // static public class GOST28147cbc 824 // extends JCEBlockCipher 825 // { 826 // public GOST28147cbc() 827 // { 828 // super(new CBCBlockCipher(new GOST28147Engine()), 64); 829 // } 830 // } 831 // 832 // /** 833 // * RC2 834 // */ 835 // static public class RC2 836 // extends JCEBlockCipher 837 // { 838 // public RC2() 839 // { 840 // super(new RC2Engine()); 841 // } 842 // } 843 // 844 // /** 845 // * RC2CBC 846 // */ 847 // static public class RC2CBC 848 // extends JCEBlockCipher 849 // { 850 // public RC2CBC() 851 // { 852 // super(new CBCBlockCipher(new RC2Engine()), 64); 853 // } 854 // } 855 // END android-removed 856 857 /** 858 * PBEWithMD5AndDES 859 */ 860 static public class PBEWithMD5AndDES 861 extends JCEBlockCipher 862 { 863 public PBEWithMD5AndDES() 864 { 865 super(new CBCBlockCipher(new DESEngine())); 866 } 867 } 868 869 /** 870 * PBEWithMD5AndRC2 871 */ 872 static public class PBEWithMD5AndRC2 873 extends JCEBlockCipher 874 { 875 public PBEWithMD5AndRC2() 876 { 877 super(new CBCBlockCipher(new RC2Engine())); 878 } 879 } 880 881 /** 882 * PBEWithSHA1AndDES 883 */ 884 static public class PBEWithSHA1AndDES 885 extends JCEBlockCipher 886 { 887 public PBEWithSHA1AndDES() 888 { 889 super(new CBCBlockCipher(new DESEngine())); 890 } 891 } 892 893 /** 894 * PBEWithSHA1AndRC2 895 */ 896 static public class PBEWithSHA1AndRC2 897 extends JCEBlockCipher 898 { 899 public PBEWithSHA1AndRC2() 900 { 901 super(new CBCBlockCipher(new RC2Engine())); 902 } 903 } 904 905 906 907 /** 908 * PBEWithSHAAnd128BitRC2-CBC 909 */ 910 static public class PBEWithSHAAnd128BitRC2 911 extends JCEBlockCipher 912 { 913 public PBEWithSHAAnd128BitRC2() 914 { 915 super(new CBCBlockCipher(new RC2Engine())); 916 } 917 } 918 919 /** 920 * PBEWithSHAAnd40BitRC2-CBC 921 */ 922 static public class PBEWithSHAAnd40BitRC2 923 extends JCEBlockCipher 924 { 925 public PBEWithSHAAnd40BitRC2() 926 { 927 super(new CBCBlockCipher(new RC2Engine())); 928 } 929 } 930 931 /** 932 * PBEWithSHAAndTwofish-CBC 933 */ 934 static public class PBEWithSHAAndTwofish 935 extends JCEBlockCipher 936 { 937 public PBEWithSHAAndTwofish() 938 { 939 super(new CBCBlockCipher(new TwofishEngine())); 940 } 941 } 942 943 /** 944 * PBEWithAES-CBC 945 */ 946 static public class PBEWithAESCBC 947 extends JCEBlockCipher 948 { 949 public PBEWithAESCBC() 950 { 951 super(new CBCBlockCipher(new AESFastEngine())); 952 } 953 } 954 955 static private interface GenericBlockCipher 956 { 957 public void init(boolean forEncryption, CipherParameters params) 958 throws IllegalArgumentException; 959 960 public boolean wrapOnNoPadding(); 961 962 public String getAlgorithmName(); 963 964 public BlockCipher getUnderlyingCipher(); 965 966 public int getOutputSize(int len); 967 968 public int getUpdateOutputSize(int len); 969 970 public int processByte(byte in, byte[] out, int outOff) 971 throws DataLengthException; 972 973 public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) 974 throws DataLengthException; 975 976 public int doFinal(byte[] out, int outOff) 977 throws IllegalStateException, InvalidCipherTextException; 978 } 979 980 private static class BufferedGenericBlockCipher 981 implements GenericBlockCipher 982 { 983 private BufferedBlockCipher cipher; 984 985 BufferedGenericBlockCipher(BufferedBlockCipher cipher) 986 { 987 this.cipher = cipher; 988 } 989 990 BufferedGenericBlockCipher(BlockCipher cipher) 991 { 992 this.cipher = new PaddedBufferedBlockCipher(cipher); 993 } 994 995 BufferedGenericBlockCipher(BlockCipher cipher, BlockCipherPadding padding) 996 { 997 this.cipher = new PaddedBufferedBlockCipher(cipher, padding); 998 } 999 1000 public void init(boolean forEncryption, CipherParameters params) 1001 throws IllegalArgumentException 1002 { 1003 cipher.init(forEncryption, params); 1004 } 1005 1006 public boolean wrapOnNoPadding() 1007 { 1008 return !(cipher instanceof CTSBlockCipher); 1009 } 1010 1011 public String getAlgorithmName() 1012 { 1013 return cipher.getUnderlyingCipher().getAlgorithmName(); 1014 } 1015 1016 public BlockCipher getUnderlyingCipher() 1017 { 1018 return cipher.getUnderlyingCipher(); 1019 } 1020 1021 public int getOutputSize(int len) 1022 { 1023 return cipher.getOutputSize(len); 1024 } 1025 1026 public int getUpdateOutputSize(int len) 1027 { 1028 return cipher.getUpdateOutputSize(len); 1029 } 1030 1031 public int processByte(byte in, byte[] out, int outOff) throws DataLengthException 1032 { 1033 return cipher.processByte(in, out, outOff); 1034 } 1035 1036 public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException 1037 { 1038 return cipher.processBytes(in, inOff, len, out, outOff); 1039 } 1040 1041 public int doFinal(byte[] out, int outOff) throws IllegalStateException, InvalidCipherTextException 1042 { 1043 return cipher.doFinal(out, outOff); 1044 } 1045 } 1046 1047 private static class AEADGenericBlockCipher 1048 implements GenericBlockCipher 1049 { 1050 private AEADBlockCipher cipher; 1051 1052 AEADGenericBlockCipher(AEADBlockCipher cipher) 1053 { 1054 this.cipher = cipher; 1055 } 1056 1057 public void init(boolean forEncryption, CipherParameters params) 1058 throws IllegalArgumentException 1059 { 1060 cipher.init(forEncryption, params); 1061 } 1062 1063 public String getAlgorithmName() 1064 { 1065 return cipher.getUnderlyingCipher().getAlgorithmName(); 1066 } 1067 1068 public boolean wrapOnNoPadding() 1069 { 1070 return false; 1071 } 1072 1073 public BlockCipher getUnderlyingCipher() 1074 { 1075 return cipher.getUnderlyingCipher(); 1076 } 1077 1078 public int getOutputSize(int len) 1079 { 1080 return cipher.getOutputSize(len); 1081 } 1082 1083 public int getUpdateOutputSize(int len) 1084 { 1085 return cipher.getUpdateOutputSize(len); 1086 } 1087 1088 public int processByte(byte in, byte[] out, int outOff) throws DataLengthException 1089 { 1090 return cipher.processByte(in, out, outOff); 1091 } 1092 1093 public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException 1094 { 1095 return cipher.processBytes(in, inOff, len, out, outOff); 1096 } 1097 1098 public int doFinal(byte[] out, int outOff) throws IllegalStateException, InvalidCipherTextException 1099 { 1100 return cipher.doFinal(out, outOff); 1101 } 1102 } 1103} 1104