1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package javax.crypto; 19 20 import java.nio.ByteBuffer; 21 import java.security.AlgorithmParameters; 22 import java.security.InvalidAlgorithmParameterException; 23 import java.security.InvalidKeyException; 24 import java.security.InvalidParameterException; 25 import java.security.Key; 26 import java.security.NoSuchAlgorithmException; 27 import java.security.NoSuchProviderException; 28 import java.security.Provider; 29 import java.security.Provider.Service; 30 import java.security.ProviderException; 31 import java.security.SecureRandom; 32 import java.security.Security; 33 import java.security.cert.Certificate; 34 import java.security.cert.X509Certificate; 35 import java.security.spec.AlgorithmParameterSpec; 36 import java.util.ArrayList; 37 import java.util.Locale; 38 import java.util.Set; 39 import org.apache.harmony.crypto.internal.NullCipherSpi; 40 import org.apache.harmony.security.fortress.Engine; 41 42 /** 43 * This class provides access to implementations of cryptographic ciphers for 44 * encryption and decryption. Cipher classes can not be instantiated directly, 45 * one has to call the Cipher's {@code getInstance} method with the name of a 46 * requested transformation, optionally with a provider. A transformation 47 * specifies an operation (or a set of operations) as a string in the form: 48 * <ul> 49 * <li><i>"algorithm/mode/padding"</i></li> or 50 * <li><i>"algorithm"</i></li> 51 * </ul> 52 * <i>algorithm</i> is the name of a cryptographic algorithm, <i>mode</i> is the 53 * name of a feedback mode and <i>padding</i> is the name of a padding scheme. 54 * If <i>mode</i> and/or <i>padding</i> values are omitted, provider specific 55 * default values will be used. 56 * <p> 57 * A valid transformation would be: 58 * <ul> 59 * {@code Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");} 60 * </ul> 61 * When a block cipher is requested in stream cipher mode, the number of bits 62 * to be processed at a time can be optionally specified by appending it to the 63 * mode name. e.g. <i>"AES/CFB8/NoPadding"</i>. If no number is specified, a 64 * provider specific default value is used. 65 */ 66 public class Cipher { 67 68 /** 69 * Constant for decryption operation mode. 70 */ 71 public static final int DECRYPT_MODE = 2; 72 73 /** 74 * Constant for encryption operation mode. 75 */ 76 public static final int ENCRYPT_MODE = 1; 77 78 /** 79 * Constant indicating that the key to be unwrapped is a private key. 80 */ 81 public static final int PRIVATE_KEY = 2; 82 83 /** 84 * Constant indicating that the key to be unwrapped is a public key. 85 */ 86 public static final int PUBLIC_KEY = 1; 87 88 /** 89 * Constant indicating that the key to be unwrapped is a secret key. 90 */ 91 public static final int SECRET_KEY = 3; 92 93 /** 94 * Constant for key unwrapping operation mode. 95 */ 96 public static final int UNWRAP_MODE = 4; 97 98 /** 99 * Constant for key wrapping operation mode. 100 */ 101 public static final int WRAP_MODE = 3; 102 103 private int mode; 104 105 /** Items that need to be set on the Cipher instance. */ 106 private enum NeedToSet { 107 NONE, MODE, PADDING, BOTH, 108 }; 109 110 /** 111 * The service name. 112 */ 113 private static final String SERVICE = "Cipher"; 114 115 /** 116 * Used to access common engine functionality. 117 */ 118 private static final Engine ENGINE = new Engine(SERVICE); 119 120 /** The attribute used for supported paddings. */ 121 private static final String ATTRIBUTE_PADDINGS = "SupportedPaddings"; 122 123 /** The attribute used for supported modes. */ 124 private static final String ATTRIBUTE_MODES = "SupportedModes"; 125 126 /** 127 * The provider. 128 */ 129 private Provider provider; 130 131 /** 132 * The provider specified when instance created. 133 */ 134 private final Provider specifiedProvider; 135 136 /** 137 * The SPI implementation. 138 */ 139 private CipherSpi spiImpl; 140 141 /** 142 * The SPI implementation. 143 */ 144 private final CipherSpi specifiedSpi; 145 146 /** 147 * The transformation. 148 */ 149 private final String transformation; 150 151 /** 152 * The transformation split into parts. 153 */ 154 private final String[] transformParts; 155 156 /** 157 * Lock held while the SPI is initializing. 158 */ 159 private final Object initLock = new Object(); 160 161 private static SecureRandom secureRandom; 162 163 /** 164 * Creates a new Cipher instance. 165 * 166 * @param cipherSpi 167 * the implementation delegate of the cipher. 168 * @param provider 169 * the provider of the implementation of this cipher. 170 * @param transformation 171 * the name of the transformation that this cipher performs. 172 * @throws NullPointerException 173 * if either cipherSpi is {@code null} or provider is {@code 174 * null} and {@code cipherSpi} is a {@code NullCipherSpi}. 175 */ Cipher(CipherSpi cipherSpi, Provider provider, String transformation)176 protected Cipher(CipherSpi cipherSpi, Provider provider, String transformation) { 177 if (cipherSpi == null) { 178 throw new NullPointerException("cipherSpi == null"); 179 } 180 if (!(cipherSpi instanceof NullCipherSpi) && provider == null) { 181 throw new NullPointerException("provider == null"); 182 } 183 this.specifiedProvider = provider; 184 this.specifiedSpi = cipherSpi; 185 this.transformation = transformation; 186 this.transformParts = null; 187 } 188 Cipher(String transformation, String[] transformParts, Provider provider)189 private Cipher(String transformation, String[] transformParts, Provider provider) { 190 this.transformation = transformation; 191 this.transformParts = transformParts; 192 this.specifiedProvider = provider; 193 this.specifiedSpi = null; 194 } 195 196 197 /** 198 * Creates a new Cipher for the specified transformation. The installed 199 * providers are searched in order for an implementation of the specified 200 * transformation. The first found provider providing the transformation is 201 * used to create the cipher. If no provider is found an exception is 202 * thrown. 203 * 204 * @param transformation 205 * the name of the transformation to create a cipher for. 206 * @return a cipher for the requested transformation. 207 * @throws NoSuchAlgorithmException 208 * if no installed provider can provide the 209 * <i>transformation</i>, or it is {@code null}, empty or in an 210 * invalid format. 211 * @throws NoSuchPaddingException 212 * if no installed provider can provide the padding scheme in 213 * the <i>transformation</i>. 214 */ getInstance(String transformation)215 public static final Cipher getInstance(String transformation) 216 throws NoSuchAlgorithmException, NoSuchPaddingException { 217 return getCipher(transformation, null); 218 } 219 220 /** 221 * Creates a new cipher for the specified transformation provided by the 222 * specified provider. 223 * 224 * @param transformation 225 * the name of the transformation to create a cipher for. 226 * @param provider 227 * the name of the provider to ask for the transformation. 228 * @return a cipher for the requested transformation. 229 * @throws NoSuchAlgorithmException 230 * if the specified provider can not provide the 231 * <i>transformation</i>, or it is {@code null}, empty or in an 232 * invalid format. 233 * @throws NoSuchProviderException 234 * if no provider with the specified name can be found. 235 * @throws NoSuchPaddingException 236 * if the requested padding scheme in the <i>transformation</i> 237 * is not available. 238 * @throws IllegalArgumentException 239 * if the specified provider is {@code null}. 240 */ getInstance(String transformation, String provider)241 public static final Cipher getInstance(String transformation, 242 String provider) throws NoSuchAlgorithmException, 243 NoSuchProviderException, NoSuchPaddingException { 244 245 if (provider == null) { 246 throw new IllegalArgumentException("provider == null"); 247 } 248 249 Provider p = Security.getProvider(provider); 250 if (p == null) { 251 throw new NoSuchProviderException("Provider not available: " + provider); 252 } 253 return getInstance(transformation, p); 254 } 255 256 /** 257 * Creates a new cipher for the specified transformation. The 258 * {@code provider} supplied does not have to be registered. 259 * 260 * @param transformation 261 * the name of the transformation to create a cipher for. 262 * @param provider 263 * the provider to ask for the transformation. 264 * @return a cipher for the requested transformation. 265 * @throws NoSuchAlgorithmException 266 * if the specified provider can not provide the 267 * <i>transformation</i>, or it is {@code null}, empty or in an 268 * invalid format. 269 * @throws NoSuchPaddingException 270 * if the requested padding scheme in the <i>transformation</i> 271 * is not available. 272 * @throws IllegalArgumentException 273 * if the provider is {@code null}. 274 */ getInstance(String transformation, Provider provider)275 public static final Cipher getInstance(String transformation, 276 Provider provider) throws NoSuchAlgorithmException, 277 NoSuchPaddingException { 278 if (provider == null) { 279 throw new IllegalArgumentException("provider == null"); 280 } 281 return getCipher(transformation, provider); 282 } 283 invalidTransformation(String transformation)284 private static NoSuchAlgorithmException invalidTransformation(String transformation) 285 throws NoSuchAlgorithmException { 286 throw new NoSuchAlgorithmException("Invalid transformation: " + transformation); 287 } 288 289 /** 290 * Create a Cipher instance but don't choose a CipherSpi until we have more 291 * information. 292 */ getCipher(String transformation, Provider provider)293 private static Cipher getCipher(String transformation, Provider provider) 294 throws NoSuchAlgorithmException, NoSuchPaddingException { 295 if (transformation == null || transformation.isEmpty()) { 296 throw invalidTransformation(transformation); 297 } 298 299 String[] transformParts = checkTransformation(transformation); 300 if (tryCombinations(null, provider, transformParts) == null) { 301 if (provider == null) { 302 throw new NoSuchAlgorithmException("No provider found for " + transformation); 303 } else { 304 throw new NoSuchAlgorithmException("Provider " + provider.getName() 305 + " does not provide " + transformation); 306 } 307 } 308 return new Cipher(transformation, transformParts, provider); 309 } 310 checkTransformation(String transformation)311 private static String[] checkTransformation(String transformation) 312 throws NoSuchAlgorithmException { 313 // ignore an extra prefix / characters such as in 314 // "/DES/CBC/PKCS5Padding" http://b/3387688 315 if (transformation.startsWith("/")) { 316 transformation = transformation.substring(1); 317 } 318 // 'transformation' should be of the form "algorithm/mode/padding". 319 String[] pieces = transformation.split("/"); 320 if (pieces.length > 3) { 321 throw invalidTransformation(transformation); 322 } 323 // Empty or missing pieces are represented by null. 324 String[] result = new String[3]; 325 for (int i = 0; i < pieces.length; ++i) { 326 String piece = pieces[i].trim(); 327 if (!piece.isEmpty()) { 328 result[i] = piece; 329 } 330 } 331 // You MUST specify an algorithm. 332 if (result[0] == null) { 333 throw invalidTransformation(transformation); 334 } 335 if (!(result[1] == null && result[2] == null) && (result[1] == null || result[2] == null)) { 336 throw invalidTransformation(transformation); 337 } 338 return result; 339 } 340 341 /** 342 * Makes sure a CipherSpi that matches this type is selected. 343 */ getSpi(Key key)344 private CipherSpi getSpi(Key key) { 345 if (specifiedSpi != null) { 346 return specifiedSpi; 347 } 348 349 synchronized (initLock) { 350 if (spiImpl != null && key == null) { 351 return spiImpl; 352 } 353 354 final Engine.SpiAndProvider sap = tryCombinations(key, specifiedProvider, 355 transformParts); 356 if (sap == null) { 357 throw new ProviderException("No provider for " + transformation); 358 } 359 360 spiImpl = (CipherSpi) sap.spi; 361 provider = sap.provider; 362 363 return spiImpl; 364 } 365 } 366 367 /** 368 * Convenience call when the Key is not available. 369 */ getSpi()370 private CipherSpi getSpi() { 371 return getSpi(null); 372 } 373 374 /** 375 * Try all combinations of mode strings: 376 * 377 * <pre> 378 * [cipher]/[mode]/[padding] 379 * [cipher]/[mode] 380 * [cipher]//[padding] 381 * [cipher] 382 * </pre> 383 */ tryCombinations(Key key, Provider provider, String[] transformParts)384 private static Engine.SpiAndProvider tryCombinations(Key key, Provider provider, 385 String[] transformParts) { 386 Engine.SpiAndProvider sap = null; 387 388 if (transformParts[1] != null && transformParts[2] != null) { 389 sap = tryTransform(key, provider, transformParts[0] + "/" + transformParts[1] + "/" 390 + transformParts[2], transformParts, NeedToSet.NONE); 391 if (sap != null) { 392 return sap; 393 } 394 } 395 396 if (transformParts[1] != null) { 397 sap = tryTransform(key, provider, transformParts[0] + "/" + transformParts[1], 398 transformParts, NeedToSet.PADDING); 399 if (sap != null) { 400 return sap; 401 } 402 } 403 404 if (transformParts[2] != null) { 405 sap = tryTransform(key, provider, transformParts[0] + "//" + transformParts[2], 406 transformParts, NeedToSet.MODE); 407 if (sap != null) { 408 return sap; 409 } 410 } 411 412 return tryTransform(key, provider, transformParts[0], transformParts, NeedToSet.BOTH); 413 } 414 tryTransform(Key key, Provider provider, String transform, String[] transformParts, NeedToSet type)415 private static Engine.SpiAndProvider tryTransform(Key key, Provider provider, String transform, 416 String[] transformParts, NeedToSet type) { 417 if (provider != null) { 418 Provider.Service service = provider.getService(SERVICE, transform); 419 if (service == null) { 420 return null; 421 } 422 return tryTransformWithProvider(key, transformParts, type, service); 423 } 424 ArrayList<Provider.Service> services = ENGINE.getServices(transform); 425 if (services == null) { 426 return null; 427 } 428 for (Provider.Service service : services) { 429 Engine.SpiAndProvider sap = tryTransformWithProvider(key, transformParts, type, service); 430 if (sap != null) { 431 return sap; 432 } 433 } 434 return null; 435 } 436 tryTransformWithProvider(Key key, String[] transformParts, NeedToSet type, Provider.Service service)437 private static Engine.SpiAndProvider tryTransformWithProvider(Key key, String[] transformParts, 438 NeedToSet type, Provider.Service service) { 439 try { 440 if (key != null && !service.supportsParameter(key)) { 441 return null; 442 } 443 444 /* 445 * Check to see if the Cipher even supports the attributes before 446 * trying to instantiate it. 447 */ 448 if (!matchAttribute(service, ATTRIBUTE_MODES, transformParts[1]) 449 || !matchAttribute(service, ATTRIBUTE_PADDINGS, transformParts[2])) { 450 return null; 451 } 452 453 Engine.SpiAndProvider sap = ENGINE.getInstance(service, null); 454 if (sap.spi == null || sap.provider == null) { 455 return null; 456 } 457 if (!(sap.spi instanceof CipherSpi)) { 458 return null; 459 } 460 CipherSpi spi = (CipherSpi) sap.spi; 461 if (((type == NeedToSet.MODE) || (type == NeedToSet.BOTH)) 462 && (transformParts[1] != null)) { 463 spi.engineSetMode(transformParts[1]); 464 } 465 if (((type == NeedToSet.PADDING) || (type == NeedToSet.BOTH)) 466 && (transformParts[2] != null)) { 467 spi.engineSetPadding(transformParts[2]); 468 } 469 return sap; 470 } catch (NoSuchAlgorithmException ignored) { 471 } catch (NoSuchPaddingException ignored) { 472 } 473 return null; 474 } 475 476 /** 477 * If the attribute listed exists, check that it matches the regular 478 * expression. 479 */ matchAttribute(Service service, String attr, String value)480 private static boolean matchAttribute(Service service, String attr, String value) { 481 if (value == null) { 482 return true; 483 } 484 final String pattern = service.getAttribute(attr); 485 if (pattern == null) { 486 return true; 487 } 488 final String valueUc = value.toUpperCase(Locale.US); 489 return valueUc.matches(pattern.toUpperCase(Locale.US)); 490 } 491 492 /** 493 * Returns the provider of this cipher instance. 494 * 495 * @return the provider of this cipher instance. 496 */ getProvider()497 public final Provider getProvider() { 498 getSpi(); 499 return provider; 500 } 501 502 /** 503 * Returns the name of the algorithm of this cipher instance. 504 * <p> 505 * This is the name of the <i>transformation</i> argument used in the 506 * {@code getInstance} call creating this object. 507 * 508 * @return the name of the algorithm of this cipher instance. 509 */ getAlgorithm()510 public final String getAlgorithm() { 511 return transformation; 512 } 513 514 /** 515 * Returns this ciphers block size (in bytes). 516 * 517 * @return this ciphers block size. 518 */ getBlockSize()519 public final int getBlockSize() { 520 return getSpi().engineGetBlockSize(); 521 } 522 523 /** 524 * Returns the length in bytes an output buffer needs to be when this cipher 525 * is updated with {@code inputLen} bytes. 526 * 527 * @param inputLen 528 * the number of bytes of the input. 529 * @return the output buffer length for the input length. 530 * @throws IllegalStateException 531 * if this cipher instance is in an invalid state. 532 */ getOutputSize(int inputLen)533 public final int getOutputSize(int inputLen) { 534 if (mode == 0) { 535 throw new IllegalStateException("Cipher has not yet been initialized"); 536 } 537 return getSpi().engineGetOutputSize(inputLen); 538 } 539 540 /** 541 * Returns the <i>initialization vector</i> for this cipher instance. 542 * 543 * @return the <i>initialization vector</i> for this cipher instance. 544 */ getIV()545 public final byte[] getIV() { 546 return getSpi().engineGetIV(); 547 } 548 549 /** 550 * Returns the parameters that where used to create this cipher instance. 551 * <p> 552 * These may be a the same parameters that were used to create this cipher 553 * instance, or may be a combination of default and random parameters, 554 * depending on the underlying cipher implementation. 555 * 556 * @return the parameters that where used to create this cipher instance, or 557 * {@code null} if this cipher instance does not have any 558 * parameters. 559 */ getParameters()560 public final AlgorithmParameters getParameters() { 561 return getSpi().engineGetParameters(); 562 } 563 564 /** 565 * Returns the exemption mechanism associated with this cipher. 566 * 567 * @return currently {@code null} 568 */ getExemptionMechanism()569 public final ExemptionMechanism getExemptionMechanism() { 570 //FIXME implement getExemptionMechanism 571 572 // try { 573 // return ExemptionMechanism.getInstance(transformation, provider); 574 // } catch (NoSuchAlgorithmException e) { 575 return null; 576 // } 577 578 } 579 checkMode(int mode)580 private void checkMode(int mode) { 581 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE && mode != UNWRAP_MODE 582 && mode != WRAP_MODE) { 583 throw new InvalidParameterException("Invalid mode: " + mode); 584 } 585 } 586 587 /** 588 * Initializes this cipher instance with the specified key. 589 * <p> 590 * The cipher is initialized for the specified operational mode (one of: 591 * encryption, decryption, key wrapping or key unwrapping) depending on 592 * {@code opmode}. 593 * <p> 594 * If this cipher instance needs any algorithm parameters or random values 595 * that the specified key can not provide, the underlying implementation of 596 * this cipher is supposed to generate the required parameters (using its 597 * provider or random values). 598 * <p> 599 * When a cipher instance is initialized by a call to any of the {@code 600 * init} methods, the state of the instance is overridden, meaning that it 601 * is equivalent to creating a new instance and calling its {@code init} 602 * method. 603 * 604 * @param opmode 605 * the operation this cipher instance should be initialized for 606 * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 607 * WRAP_MODE} or {@code UNWRAP_MODE}). 608 * @param key 609 * the input key for the operation. 610 * @throws InvalidKeyException 611 * if the specified key can not be used to initialize this 612 * cipher instance. 613 */ init(int opmode, Key key)614 public final void init(int opmode, Key key) throws InvalidKeyException { 615 if (secureRandom == null) { 616 // In theory it might be thread-unsafe but in the given case it's OK 617 // since it does not matter which SecureRandom instance is passed 618 // to the init() 619 secureRandom = new SecureRandom(); 620 } 621 init(opmode, key, secureRandom); 622 } 623 624 /** 625 * Initializes this cipher instance with the specified key and a source of 626 * randomness. 627 * <p> 628 * The cipher is initialized for the specified operational mode (one of: 629 * encryption, decryption, key wrapping or key unwrapping) depending on 630 * {@code opmode}. 631 * <p> 632 * If this cipher instance needs any algorithm parameters or random values 633 * that the specified key can not provide, the underlying implementation of 634 * this cipher is supposed to generate the required parameters (using its 635 * provider or random values). Random values are generated using {@code 636 * random}; 637 * <p> 638 * When a cipher instance is initialized by a call to any of the {@code 639 * init} methods, the state of the instance is overridden, means it is 640 * equivalent to creating a new instance and calling it {@code init} method. 641 * 642 * @param opmode 643 * the operation this cipher instance should be initialized for 644 * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 645 * WRAP_MODE} or {@code UNWRAP_MODE}). 646 * @param key 647 * the input key for the operation. 648 * @param random 649 * the source of randomness to use. 650 * @throws InvalidKeyException 651 * if the specified key can not be used to initialize this 652 * cipher instance. 653 * @throws InvalidParameterException 654 * if the specified opmode is invalid. 655 */ init(int opmode, Key key, SecureRandom random)656 public final void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException { 657 checkMode(opmode); 658 // FIXME InvalidKeyException 659 // if keysize exceeds the maximum allowable keysize 660 // (jurisdiction policy files) 661 getSpi(key).engineInit(opmode, key, random); 662 mode = opmode; 663 } 664 665 /** 666 * Initializes this cipher instance with the specified key and algorithm 667 * parameters. 668 * <p> 669 * The cipher is initialized for the specified operational mode (one of: 670 * encryption, decryption, key wrapping or key unwrapping). 671 * <p> 672 * If this cipher instance needs any algorithm parameters and {@code params} 673 * is {@code null}, the underlying implementation of this cipher is supposed 674 * to generate the required parameters (using its provider or random 675 * values). 676 * <p> 677 * When a cipher instance is initialized by a call to any of the {@code 678 * init} methods, the state of the instance is overridden, means it is 679 * equivalent to creating a new instance and calling it {@code init} method. 680 * 681 * @param opmode 682 * the operation this cipher instance should be initialized for 683 * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 684 * WRAP_MODE} or {@code UNWRAP_MODE}). 685 * @param key 686 * the input key for the operation. 687 * @param params 688 * the algorithm parameters. 689 * @throws InvalidKeyException 690 * if the specified key can not be used to initialize this 691 * cipher instance. 692 * @throws InvalidAlgorithmParameterException 693 * it the specified parameters are inappropriate for this 694 * cipher. 695 */ init(int opmode, Key key, AlgorithmParameterSpec params)696 public final void init(int opmode, Key key, AlgorithmParameterSpec params) 697 throws InvalidKeyException, InvalidAlgorithmParameterException { 698 if (secureRandom == null) { 699 secureRandom = new SecureRandom(); 700 } 701 init(opmode, key, params, secureRandom); 702 } 703 704 /** 705 * Initializes this cipher instance with the specified key, algorithm 706 * parameters and a source of randomness. 707 * <p> 708 * The cipher is initialized for the specified operational mode (one of: 709 * encryption, decryption, key wrapping or key unwrapping) depending on 710 * {@code opmode}. 711 * <p> 712 * If this cipher instance needs any algorithm parameters and {@code params} 713 * is {@code null}, the underlying implementation of this cipher is supposed 714 * to generate the required parameters (using its provider or random 715 * values). Random values are generated using {@code random}; 716 * <p> 717 * When a cipher instance is initialized by a call to any of the {@code 718 * init} methods, the state of the instance is overridden, meaning that it 719 * is equivalent to creating a new instance and calling it {@code init} 720 * method. 721 * 722 * @param opmode 723 * the operation this cipher instance should be initialized for 724 * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 725 * WRAP_MODE} or {@code UNWRAP_MODE}). 726 * @param key 727 * the input key for the operation. 728 * @param params 729 * the algorithm parameters. 730 * @param random 731 * the source of randomness to use. 732 * @throws InvalidKeyException 733 * if the specified key can not be used to initialize this 734 * cipher instance. 735 * @throws InvalidAlgorithmParameterException 736 * it the specified parameters are inappropriate for this 737 * cipher. 738 * @throws InvalidParameterException 739 * if the specified {@code opmode} is invalid. 740 */ init(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random)741 public final void init(int opmode, Key key, AlgorithmParameterSpec params, 742 SecureRandom random) throws InvalidKeyException, 743 InvalidAlgorithmParameterException { 744 checkMode(opmode); 745 // FIXME InvalidKeyException 746 // if keysize exceeds the maximum allowable keysize 747 // (jurisdiction policy files) 748 // FIXME InvalidAlgorithmParameterException 749 // cryptographic strength exceed the legal limits 750 // (jurisdiction policy files) 751 getSpi(key).engineInit(opmode, key, params, random); 752 mode = opmode; 753 } 754 755 /** 756 * Initializes this cipher instance with the specified key and algorithm 757 * parameters. 758 * <p> 759 * The cipher is initialized for the specified operation (one of: 760 * encryption, decryption, key wrapping or key unwrapping) depending on 761 * {@code opmode}. 762 * <p> 763 * If this cipher instance needs any algorithm parameters and {@code params} 764 * is {@code null}, the underlying implementation of this cipher is supposed 765 * to generate the required parameters (using its provider or random 766 * values). 767 * <p> 768 * When a cipher instance is initialized by a call to any of the {@code 769 * init} methods, the state of the instance is overridden, meaning that it 770 * is equivalent to creating a new instance and calling it {@code init} 771 * method. 772 * 773 * @param opmode 774 * the operation this cipher instance should be initialized for 775 * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 776 * WRAP_MODE} or {@code UNWRAP_MODE}). 777 * @param key 778 * the input key for the operation. 779 * @param params 780 * the algorithm parameters. 781 * @throws InvalidKeyException 782 * if the specified key can not be used to initialize this 783 * cipher instance. 784 * @throws InvalidAlgorithmParameterException 785 * it the specified parameters are inappropriate for this 786 * cipher. 787 */ init(int opmode, Key key, AlgorithmParameters params)788 public final void init(int opmode, Key key, AlgorithmParameters params) 789 throws InvalidKeyException, InvalidAlgorithmParameterException { 790 if (secureRandom == null) { 791 secureRandom = new SecureRandom(); 792 } 793 init(opmode, key, params, secureRandom); 794 } 795 796 /** 797 * Initializes this cipher instance with the specified key, algorithm 798 * parameters and a source of randomness. 799 * <p> 800 * The cipher will be initialized for the specified operation (one of: 801 * encryption, decryption, key wrapping or key unwrapping) depending on 802 * {@code opmode}. 803 * <p> 804 * If this cipher instance needs any algorithm parameters and {@code params} 805 * is {@code null}, the underlying implementation of this cipher is supposed 806 * to generate the required parameters (using its provider or random 807 * values). Random values are generated using {@code random}. 808 * <p> 809 * When a cipher instance is initialized by a call to any of the {@code 810 * init} methods, the state of the instance is overridden, means it is 811 * equivalent to creating a new instance and calling it {@code init} method. 812 * 813 * @param opmode 814 * the operation this cipher instance should be initialized for 815 * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 816 * WRAP_MODE} or {@code UNWRAP_MODE}). 817 * @param key 818 * the input key for the operation. 819 * @param params 820 * the algorithm parameters. 821 * @param random 822 * the source of randomness to use. 823 * @throws InvalidKeyException 824 * if the specified key can not be used to initialize this 825 * cipher instance. 826 * @throws InvalidAlgorithmParameterException 827 * if the specified parameters are inappropriate for this 828 * cipher. 829 * @throws InvalidParameterException 830 * if the specified {@code opmode} is invalid. 831 */ init(int opmode, Key key, AlgorithmParameters params, SecureRandom random)832 public final void init(int opmode, Key key, AlgorithmParameters params, 833 SecureRandom random) throws InvalidKeyException, 834 InvalidAlgorithmParameterException { 835 checkMode(opmode); 836 // FIXME InvalidKeyException 837 // if keysize exceeds the maximum allowable keysize 838 // (jurisdiction policy files) 839 // FIXME InvalidAlgorithmParameterException 840 // cryptographic strength exceed the legal limits 841 // (jurisdiction policy files) 842 getSpi(key).engineInit(opmode, key, params, random); 843 mode = opmode; 844 } 845 846 /** 847 * Initializes this cipher instance with the public key from the specified 848 * certificate. 849 * <p> 850 * The cipher will be initialized for the specified operation (one of: 851 * encryption, decryption, key wrapping or key unwrapping) depending on 852 * {@code opmode}. 853 * <p> 854 * It the type of the certificate is X.509 and the certificate has a <i>key 855 * usage</i> extension field marked as critical, the specified {@code 856 * opmode} has the be enabled for this key, otherwise an {@code 857 * InvalidKeyException} is thrown. 858 * <p> 859 * If this cipher instance needs any algorithm parameters that the key in 860 * the certificate can not provide, the underlying implementation of this 861 * cipher is supposed to generate the required parameters (using its 862 * provider or random values). 863 * <p> 864 * When a cipher instance is initialized by a call to any of the {@code 865 * init} methods, the state of the instance is overridden, means it is 866 * equivalent to creating a new instance and calling it {@code init} method. 867 * 868 * @param opmode 869 * the operation this cipher instance should be initialized for 870 * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 871 * WRAP_MODE} or {@code UNWRAP_MODE}). 872 * @param certificate 873 * the certificate. 874 * @throws InvalidKeyException 875 * if the public key in the certificate can not be used to 876 * initialize this cipher instance. 877 */ init(int opmode, Certificate certificate)878 public final void init(int opmode, Certificate certificate) 879 throws InvalidKeyException { 880 if (secureRandom == null) { 881 secureRandom = new SecureRandom(); 882 } 883 init(opmode, certificate, secureRandom); 884 } 885 886 /** 887 * Initializes this cipher instance with the public key from the specified 888 * certificate and a source of randomness. 889 * <p> 890 * The cipher will be initialized for the specified operation (one of: 891 * encryption, decryption, key wrapping or key unwrapping) depending on 892 * {@code opmode}. 893 * <p> 894 * It the type of the certificate is X.509 and the certificate has a <i>key 895 * usage</i> extension field marked as critical, the specified {@code 896 * opmode} has the be enabled for this key, otherwise an {@code 897 * InvalidKeyException} is thrown. 898 * <p> 899 * If this cipher instance needs any algorithm parameters that the key in 900 * the certificate can not provide, the underlying implementation of this 901 * cipher is supposed to generate the required parameters (using its 902 * provider or random values). Random values are generated using {@code 903 * random}. 904 * <p> 905 * When a cipher instance is initialized by a call to any of the {@code 906 * init} methods, the state of the instance is overridden, means it is 907 * equivalent to creating a new instance and calling it {@code init} method. 908 * 909 * @param opmode 910 * the operation this cipher instance should be initialized for 911 * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code 912 * WRAP_MODE} or {@code UNWRAP_MODE}). 913 * @param certificate 914 * the certificate. 915 * @param random 916 * the source of randomness to be used. 917 * @throws InvalidKeyException 918 * if the public key in the certificate can not be used to 919 * initialize this cipher instance. 920 */ init(int opmode, Certificate certificate, SecureRandom random)921 public final void init(int opmode, Certificate certificate, 922 SecureRandom random) throws InvalidKeyException { 923 checkMode(opmode); 924 if (certificate instanceof X509Certificate) { 925 Set<String> ce = ((X509Certificate) certificate).getCriticalExtensionOIDs(); 926 boolean critical = false; 927 if (ce != null && !ce.isEmpty()) { 928 for (String oid : ce) { 929 if (oid.equals("2.5.29.15")) { // KeyUsage OID = 2.5.29.15 930 critical = true; 931 break; 932 } 933 } 934 if (critical) { 935 boolean[] keyUsage = ((X509Certificate) certificate).getKeyUsage(); 936 // As specified in RFC 3280: 937 // Internet X.509 Public Key Infrastructure 938 // Certificate and Certificate Revocation List (CRL) Profile. 939 // Section 4.2.1.3 Key Usage 940 // http://www.ietf.org/rfc/rfc3280.txt 941 // 942 // KeyUsage ::= BIT STRING {digitalSignature (0), 943 // nonRepudiation (1), 944 // keyEncipherment (2), 945 // dataEncipherment (3), 946 // keyAgreement (4), 947 // keyCertSign (5), 948 // cRLSign (6), 949 // encipherOnly (7), 950 // decipherOnly (8) } 951 if (keyUsage != null) { 952 if (opmode == ENCRYPT_MODE && !keyUsage[3]) { 953 throw new InvalidKeyException("The public key in the certificate " 954 + "cannot be used for ENCRYPT_MODE"); 955 } else if (opmode == WRAP_MODE && !keyUsage[2]) { 956 throw new InvalidKeyException("The public key in the certificate " 957 + "cannot be used for WRAP_MODE"); 958 } 959 } 960 } 961 } 962 } 963 // FIXME InvalidKeyException 964 // if keysize exceeds the maximum allowable keysize 965 // (jurisdiction policy files) 966 final Key key = certificate.getPublicKey(); 967 getSpi(key).engineInit(opmode, key, random); 968 mode = opmode; 969 } 970 971 /** 972 * Continues a multi-part transformation (encryption or decryption). The 973 * transformed bytes are returned. 974 * 975 * @param input 976 * the input bytes to transform. 977 * @return the transformed bytes in a new buffer, or {@code null} if the 978 * input has zero length. 979 * @throws IllegalStateException 980 * if this cipher instance is not initialized for encryption or 981 * decryption. 982 * @throws IllegalArgumentException 983 * if the input is {@code null}. 984 */ update(byte[] input)985 public final byte[] update(byte[] input) { 986 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 987 throw new IllegalStateException(); 988 } 989 if (input == null) { 990 throw new IllegalArgumentException("input == null"); 991 } 992 if (input.length == 0) { 993 return null; 994 } 995 return getSpi().engineUpdate(input, 0, input.length); 996 } 997 998 /** 999 * Continues a multi-part transformation (encryption or decryption). The 1000 * transformed bytes are returned. 1001 * 1002 * @param input 1003 * the input bytes to transform. 1004 * @param inputOffset 1005 * the offset in the input to start. 1006 * @param inputLen 1007 * the length of the input to transform. 1008 * @return the transformed bytes in a new buffer, or {@code null} if the 1009 * input has zero length. 1010 * @throws IllegalStateException 1011 * if this cipher instance is not initialized for encryption or 1012 * decryption. 1013 * @throws IllegalArgumentException 1014 * if {@code input} is {@code null}, or if {@code inputOffset} and 1015 * {@code inputLen} do not specify a valid chunk in the input 1016 * buffer. 1017 */ update(byte[] input, int inputOffset, int inputLen)1018 public final byte[] update(byte[] input, int inputOffset, int inputLen) { 1019 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1020 throw new IllegalStateException(); 1021 } 1022 if (input == null) { 1023 throw new IllegalArgumentException("input == null"); 1024 } 1025 checkInputOffsetAndCount(input.length, inputOffset, inputLen); 1026 if (input.length == 0) { 1027 return null; 1028 } 1029 return getSpi().engineUpdate(input, inputOffset, inputLen); 1030 } 1031 checkInputOffsetAndCount(int inputArrayLength, int inputOffset, int inputLen)1032 private static void checkInputOffsetAndCount(int inputArrayLength, 1033 int inputOffset, 1034 int inputLen) { 1035 if ((inputOffset | inputLen) < 0 1036 || inputOffset > inputArrayLength 1037 || inputArrayLength - inputOffset < inputLen) { 1038 throw new IllegalArgumentException("input.length=" + inputArrayLength 1039 + "; inputOffset=" + inputOffset 1040 + "; inputLen=" + inputLen); 1041 } 1042 } 1043 1044 /** 1045 * Continues a multi-part transformation (encryption or decryption). The 1046 * transformed bytes are stored in the {@code output} buffer. 1047 * <p> 1048 * If the size of the {@code output} buffer is too small to hold the result, 1049 * a {@code ShortBufferException} is thrown. Use 1050 * {@link Cipher#getOutputSize getOutputSize} to check for the size of the 1051 * output buffer. 1052 * 1053 * @param input 1054 * the input bytes to transform. 1055 * @param inputOffset 1056 * the offset in the input to start. 1057 * @param inputLen 1058 * the length of the input to transform. 1059 * @param output 1060 * the output buffer. 1061 * @return the number of bytes placed in output. 1062 * @throws ShortBufferException 1063 * if the size of the {@code output} buffer is too small. 1064 * @throws IllegalStateException 1065 * if this cipher instance is not initialized for encryption or 1066 * decryption. 1067 * @throws IllegalArgumentException 1068 * if the input is {@code null}, the output is {@code null}, or 1069 * if {@code inputOffset} and {@code inputLen} do not specify a 1070 * valid chunk in the input buffer. 1071 */ update(byte[] input, int inputOffset, int inputLen, byte[] output)1072 public final int update(byte[] input, int inputOffset, int inputLen, 1073 byte[] output) throws ShortBufferException { 1074 return update(input, inputOffset, inputLen, output, 0); 1075 } 1076 1077 /** 1078 * Continues a multi-part transformation (encryption or decryption). The 1079 * transformed bytes are stored in the {@code output} buffer. 1080 * <p> 1081 * If the size of the {@code output} buffer is too small to hold the result, 1082 * a {@code ShortBufferException} is thrown. Use 1083 * {@link Cipher#getOutputSize getOutputSize} to check for the size of the 1084 * output buffer. 1085 * 1086 * @param input 1087 * the input bytes to transform. 1088 * @param inputOffset 1089 * the offset in the input to start. 1090 * @param inputLen 1091 * the length of the input to transform. 1092 * @param output 1093 * the output buffer. 1094 * @param outputOffset 1095 * the offset in the output buffer. 1096 * @return the number of bytes placed in output. 1097 * @throws ShortBufferException 1098 * if the size of the {@code output} buffer is too small. 1099 * @throws IllegalStateException 1100 * if this cipher instance is not initialized for encryption or 1101 * decryption. 1102 * @throws IllegalArgumentException 1103 * if the input is {@code null}, the output is {@code null}, or 1104 * if {@code inputOffset} and {@code inputLen} do not specify a 1105 * valid chunk in the input buffer. 1106 */ update(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset)1107 public final int update(byte[] input, int inputOffset, int inputLen, 1108 byte[] output, int outputOffset) throws ShortBufferException { 1109 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1110 throw new IllegalStateException(); 1111 } 1112 if (input == null) { 1113 throw new IllegalArgumentException("input == null"); 1114 } 1115 if (output == null) { 1116 throw new IllegalArgumentException("output == null"); 1117 } 1118 if (outputOffset < 0) { 1119 throw new IllegalArgumentException("outputOffset < 0. outputOffset=" + outputOffset); 1120 } 1121 checkInputOffsetAndCount(input.length, inputOffset, inputLen); 1122 if (input.length == 0) { 1123 return 0; 1124 } 1125 return getSpi().engineUpdate(input, inputOffset, inputLen, output, 1126 outputOffset); 1127 } 1128 1129 /** 1130 * Continues a multi-part transformation (encryption or decryption). The 1131 * {@code input.remaining()} bytes starting at {@code input.position()} are 1132 * transformed and stored in the {@code output} buffer. 1133 * <p> 1134 * If the {@code output.remaining()} is too small to hold the transformed 1135 * bytes a {@code ShortBufferException} is thrown. Use 1136 * {@link Cipher#getOutputSize getOutputSize} to check for the size of the 1137 * output buffer. 1138 * 1139 * @param input 1140 * the input buffer to transform. 1141 * @param output 1142 * the output buffer to store the result within. 1143 * @return the number of bytes stored in the output buffer. 1144 * @throws ShortBufferException 1145 * if the size of the {@code output} buffer is too small. 1146 * @throws IllegalStateException 1147 * if this cipher instance is not initialized for encryption or 1148 * decryption. 1149 * @throws IllegalArgumentException 1150 * if the input buffer and the output buffer are the identical 1151 * object. 1152 */ update(ByteBuffer input, ByteBuffer output)1153 public final int update(ByteBuffer input, ByteBuffer output) 1154 throws ShortBufferException { 1155 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1156 throw new IllegalStateException(); 1157 } 1158 if (input == output) { 1159 throw new IllegalArgumentException("input == output"); 1160 } 1161 return getSpi().engineUpdate(input, output); 1162 } 1163 1164 /** 1165 * Continues a multi-part transformation (encryption or decryption) with 1166 * Authenticated Additional Data (AAD). AAD may only be added after the 1167 * {@code Cipher} is initialized and before any data is passed to the 1168 * instance. 1169 * <p> 1170 * This is only usable with cipher modes that support Authenticated 1171 * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM). 1172 * 1173 * @param input bytes of AAD to use with the cipher 1174 * @throws IllegalStateException 1175 * if this cipher instance is not initialized for encryption or 1176 * decryption. 1177 * @throws IllegalArgumentException 1178 * if {@code input} is {@code null} 1179 * @throws UnsupportedOperationException if the cipher does not support AEAD 1180 * @since 1.7 1181 */ updateAAD(byte[] input)1182 public final void updateAAD(byte[] input) { 1183 if (input == null) { 1184 throw new IllegalArgumentException("input == null"); 1185 } 1186 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1187 throw new IllegalStateException(); 1188 } 1189 if (input.length == 0) { 1190 return; 1191 } 1192 getSpi().engineUpdateAAD(input, 0, input.length); 1193 } 1194 1195 /** 1196 * Continues a multi-part transformation (encryption or decryption) with 1197 * Authenticated Additional Data (AAD). AAD may only be added after the 1198 * {@code Cipher} is initialized and before any data is passed to the 1199 * instance. 1200 * <p> 1201 * This is only usable with cipher modes that support Authenticated 1202 * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM). 1203 * 1204 * @param input bytes of AAD to use with the cipher 1205 * @param inputOffset offset within bytes of additional data to add to cipher 1206 * @param inputLen length of bytes of additional data to add to cipher 1207 * @throws IllegalStateException 1208 * if this cipher instance is not initialized for encryption or 1209 * decryption. 1210 * @throws IllegalArgumentException 1211 * if {@code input} is {@code null}, or if {@code inputOffset} and 1212 * {@code inputLen} do not specify a valid chunk in the input 1213 * buffer. 1214 * @throws UnsupportedOperationException if the cipher does not support AEAD 1215 * @since 1.7 1216 */ updateAAD(byte[] input, int inputOffset, int inputLen)1217 public final void updateAAD(byte[] input, int inputOffset, int inputLen) { 1218 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1219 throw new IllegalStateException(); 1220 } 1221 if (input == null) { 1222 throw new IllegalArgumentException("input == null"); 1223 } 1224 checkInputOffsetAndCount(input.length, inputOffset, inputLen); 1225 if (input.length == 0) { 1226 return; 1227 } 1228 getSpi().engineUpdateAAD(input, inputOffset, inputLen); 1229 } 1230 1231 /** 1232 * Continues a multi-part transformation (encryption or decryption) with 1233 * Authenticated Additional Data (AAD). AAD may only be added after the 1234 * {@code Cipher} is initialized and before any data is passed to the 1235 * instance. 1236 * <p> 1237 * This is only usable with cipher modes that support Authenticated 1238 * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM). 1239 * 1240 * @param input buffer of AAD to be used 1241 * @throws IllegalStateException 1242 * if this cipher instance is not initialized for encryption or 1243 * decryption. 1244 * @throws UnsupportedOperationException if the cipher does not support AEAD 1245 * @since 1.7 1246 */ updateAAD(ByteBuffer input)1247 public final void updateAAD(ByteBuffer input) { 1248 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1249 throw new IllegalStateException("Cipher is not initialized"); 1250 } 1251 if (input == null) { 1252 throw new IllegalArgumentException("input == null"); 1253 } 1254 getSpi().engineUpdateAAD(input); 1255 } 1256 1257 /** 1258 * Finishes a multi-part transformation (encryption or decryption). 1259 * <p> 1260 * Processes any bytes that may have been buffered in previous {@code 1261 * update} calls. 1262 * 1263 * @return the final bytes from the transformation. 1264 * @throws IllegalBlockSizeException 1265 * if the size of the resulting bytes is not a multiple of the 1266 * cipher block size. 1267 * @throws BadPaddingException 1268 * if the padding of the data does not match the padding scheme. 1269 * @throws IllegalStateException 1270 * if this cipher instance is not initialized for encryption or 1271 * decryption. 1272 */ doFinal()1273 public final byte[] doFinal() throws IllegalBlockSizeException, 1274 BadPaddingException { 1275 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1276 throw new IllegalStateException(); 1277 } 1278 return getSpi().engineDoFinal(null, 0, 0); 1279 } 1280 1281 /** 1282 * Finishes a multi-part transformation (encryption or decryption). 1283 * <p> 1284 * Processes any bytes that may have been buffered in previous {@code 1285 * update} calls. 1286 * <p> 1287 * The final transformed bytes are stored in the {@code output} buffer. 1288 * 1289 * @param output 1290 * the output buffer. 1291 * @param outputOffset 1292 * the offset in the output buffer. 1293 * @return the number of bytes placed in the output buffer. 1294 * @throws IllegalBlockSizeException 1295 * if the size of the resulting bytes is not a multiple of the 1296 * cipher block size. 1297 * @throws ShortBufferException 1298 * if the size of the {@code output} buffer is too small. 1299 * @throws BadPaddingException 1300 * if the padding of the data does not match the padding scheme. 1301 * @throws IllegalStateException 1302 * if this cipher instance is not initialized for encryption or 1303 * decryption. 1304 */ doFinal(byte[] output, int outputOffset)1305 public final int doFinal(byte[] output, int outputOffset) 1306 throws IllegalBlockSizeException, ShortBufferException, 1307 BadPaddingException { 1308 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1309 throw new IllegalStateException(); 1310 } 1311 if (outputOffset < 0) { 1312 throw new IllegalArgumentException("outputOffset < 0. outputOffset=" + outputOffset); 1313 } 1314 return getSpi().engineDoFinal(null, 0, 0, output, outputOffset); 1315 } 1316 1317 /** 1318 * Finishes a multi-part transformation (encryption or decryption). 1319 * <p> 1320 * Processes the bytes in {@code input} buffer, and any bytes that have been 1321 * buffered in previous {@code update} calls. 1322 * 1323 * @param input 1324 * the input buffer. 1325 * @return the final bytes from the transformation. 1326 * @throws IllegalBlockSizeException 1327 * if the size of the resulting bytes is not a multiple of the 1328 * cipher block size. 1329 * @throws BadPaddingException 1330 * if the padding of the data does not match the padding scheme. 1331 * @throws IllegalStateException 1332 * if this cipher instance is not initialized for encryption or 1333 * decryption. 1334 */ doFinal(byte[] input)1335 public final byte[] doFinal(byte[] input) throws IllegalBlockSizeException, 1336 BadPaddingException { 1337 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1338 throw new IllegalStateException(); 1339 } 1340 return getSpi().engineDoFinal(input, 0, input.length); 1341 } 1342 1343 /** 1344 * Finishes a multi-part transformation (encryption or decryption). 1345 * <p> 1346 * Processes the {@code inputLen} bytes in {@code input} buffer at {@code 1347 * inputOffset}, and any bytes that have been buffered in previous {@code 1348 * update} calls. 1349 * 1350 * @param input 1351 * the input buffer. 1352 * @param inputOffset 1353 * the offset in the input buffer. 1354 * @param inputLen 1355 * the length of the input 1356 * @return the final bytes from the transformation. 1357 * @throws IllegalBlockSizeException 1358 * if the size of the resulting bytes is not a multiple of the 1359 * cipher block size. 1360 * @throws BadPaddingException 1361 * if the padding of the data does not match the padding scheme. 1362 * @throws IllegalStateException 1363 * if this cipher instance is not initialized for encryption or 1364 * decryption. 1365 * @throws IllegalArgumentException 1366 * if {@code inputOffset} and {@code inputLen} do not specify an 1367 * valid chunk in the input buffer. 1368 */ doFinal(byte[] input, int inputOffset, int inputLen)1369 public final byte[] doFinal(byte[] input, int inputOffset, int inputLen) 1370 throws IllegalBlockSizeException, BadPaddingException { 1371 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1372 throw new IllegalStateException(); 1373 } 1374 checkInputOffsetAndCount(input.length, inputOffset, inputLen); 1375 return getSpi().engineDoFinal(input, inputOffset, inputLen); 1376 } 1377 1378 /** 1379 * Finishes a multi-part transformation (encryption or decryption). 1380 * <p> 1381 * Processes the {@code inputLen} bytes in {@code input} buffer at {@code 1382 * inputOffset}, and any bytes that have been buffered in previous {@code 1383 * update} calls. 1384 * 1385 * @param input 1386 * the input buffer. 1387 * @param inputOffset 1388 * the offset in the input buffer. 1389 * @param inputLen 1390 * the length of the input. 1391 * @param output 1392 * the output buffer for the transformed bytes. 1393 * @return the number of bytes placed in the output buffer. 1394 * @throws ShortBufferException 1395 * if the size of the {@code output} buffer is too small. 1396 * @throws IllegalBlockSizeException 1397 * if the size of the resulting bytes is not a multiple of the 1398 * cipher block size. 1399 * @throws BadPaddingException 1400 * if the padding of the data does not match the padding scheme. 1401 * @throws IllegalStateException 1402 * if this cipher instance is not initialized for encryption or 1403 * decryption. 1404 * @throws IllegalArgumentException 1405 * if {@code inputOffset} and {@code inputLen} do not specify an 1406 * valid chunk in the input buffer. 1407 */ doFinal(byte[] input, int inputOffset, int inputLen, byte[] output)1408 public final int doFinal(byte[] input, int inputOffset, int inputLen, 1409 byte[] output) throws ShortBufferException, 1410 IllegalBlockSizeException, BadPaddingException { 1411 return doFinal(input, inputOffset, inputLen, output, 0); 1412 } 1413 1414 /** 1415 * Finishes a multi-part transformation (encryption or decryption). 1416 * <p> 1417 * Processes the {@code inputLen} bytes in {@code input} buffer at {@code 1418 * inputOffset}, and any bytes that have been buffered in previous {@code 1419 * update} calls. 1420 * 1421 * @param input 1422 * the input buffer. 1423 * @param inputOffset 1424 * the offset in the input buffer. 1425 * @param inputLen 1426 * the length of the input. 1427 * @param output 1428 * the output buffer for the transformed bytes. 1429 * @param outputOffset 1430 * the offset in the output buffer. 1431 * @return the number of bytes placed in the output buffer. 1432 * @throws ShortBufferException 1433 * if the size of the {@code output} buffer is too small. 1434 * @throws IllegalBlockSizeException 1435 * if the size of the resulting bytes is not a multiple of the 1436 * cipher block size. 1437 * @throws BadPaddingException 1438 * if the padding of the data does not match the padding scheme. 1439 * @throws IllegalStateException 1440 * if this cipher instance is not initialized for encryption or 1441 * decryption. 1442 * @throws IllegalArgumentException 1443 * if {@code inputOffset} and {@code inputLen} do not specify an 1444 * valid chunk in the input buffer. 1445 */ doFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset)1446 public final int doFinal(byte[] input, int inputOffset, int inputLen, 1447 byte[] output, int outputOffset) throws ShortBufferException, 1448 IllegalBlockSizeException, BadPaddingException { 1449 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1450 throw new IllegalStateException(); 1451 } 1452 checkInputOffsetAndCount(input.length, inputOffset, inputLen); 1453 return getSpi().engineDoFinal(input, inputOffset, inputLen, output, 1454 outputOffset); 1455 } 1456 1457 /** 1458 * Finishes a multi-part transformation (encryption or decryption). 1459 * <p> 1460 * Processes the {@code input.remaining()} bytes in {@code input} buffer at 1461 * {@code input.position()}, and any bytes that have been buffered in 1462 * previous {@code update} calls. The transformed bytes are placed into 1463 * {@code output} buffer. 1464 * 1465 * @param input 1466 * the input buffer. 1467 * @param output 1468 * the output buffer. 1469 * @return the number of bytes placed into the output buffer. 1470 * @throws ShortBufferException 1471 * if the size of the {@code output} buffer is too small. 1472 * @throws IllegalBlockSizeException 1473 * if the size of the resulting bytes is not a multiple of the 1474 * cipher block size. 1475 * @throws BadPaddingException 1476 * if the padding of the data does not match the padding scheme. 1477 * @throws IllegalArgumentException 1478 * if the input buffer and the output buffer are the same 1479 * object. 1480 * @throws IllegalStateException 1481 * if this cipher instance is not initialized for encryption or 1482 * decryption. 1483 */ doFinal(ByteBuffer input, ByteBuffer output)1484 public final int doFinal(ByteBuffer input, ByteBuffer output) 1485 throws ShortBufferException, IllegalBlockSizeException, 1486 BadPaddingException { 1487 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1488 throw new IllegalStateException(); 1489 } 1490 if (input == output) { 1491 throw new IllegalArgumentException("input == output"); 1492 } 1493 return getSpi().engineDoFinal(input, output); 1494 } 1495 1496 /** 1497 * Wraps a key using this cipher instance. 1498 * 1499 * @param key 1500 * the key to wrap. 1501 * @return the wrapped key. 1502 * @throws IllegalBlockSizeException 1503 * if the size of the resulting bytes is not a multiple of the 1504 * cipher block size. 1505 * @throws InvalidKeyException 1506 * if this cipher instance can not wrap this key. 1507 * @throws IllegalStateException 1508 * if this cipher instance is not initialized for wrapping. 1509 */ wrap(Key key)1510 public final byte[] wrap(Key key) throws IllegalBlockSizeException, 1511 InvalidKeyException { 1512 if (mode != WRAP_MODE) { 1513 throw new IllegalStateException(); 1514 } 1515 return getSpi().engineWrap(key); 1516 } 1517 1518 /** 1519 * Unwraps a key using this cipher instance. 1520 * 1521 * @param wrappedKey 1522 * the wrapped key to unwrap. 1523 * @param wrappedKeyAlgorithm 1524 * the algorithm for the wrapped key. 1525 * @param wrappedKeyType 1526 * the type of the wrapped key (one of: {@code SECRET_KEY 1527 * <code>, <code>PRIVATE_KEY} or {@code PUBLIC_KEY}) 1528 * @return the unwrapped key 1529 * @throws InvalidKeyException 1530 * if the {@code wrappedKey} can not be unwrapped to a key of 1531 * type {@code wrappedKeyType} for the {@code 1532 * wrappedKeyAlgorithm}. 1533 * @throws NoSuchAlgorithmException 1534 * if no provider can be found that can create a key of type 1535 * {@code wrappedKeyType} for the {@code wrappedKeyAlgorithm}. 1536 * @throws IllegalStateException 1537 * if this cipher instance is not initialized for unwrapping. 1538 */ unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType)1539 public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, 1540 int wrappedKeyType) throws InvalidKeyException, 1541 NoSuchAlgorithmException { 1542 if (mode != UNWRAP_MODE) { 1543 throw new IllegalStateException(); 1544 } 1545 return getSpi().engineUnwrap(wrappedKey, wrappedKeyAlgorithm, 1546 wrappedKeyType); 1547 } 1548 1549 /** 1550 * Returns the maximum key length for the specified transformation. 1551 * 1552 * @param transformation 1553 * the transformation name. 1554 * @return the maximum key length, currently {@code Integer.MAX_VALUE}. 1555 * @throws NoSuchAlgorithmException 1556 * if no provider for the specified {@code transformation} can 1557 * be found. 1558 * @throws NullPointerException 1559 * if {@code transformation} is {@code null}. 1560 */ getMaxAllowedKeyLength(String transformation)1561 public static final int getMaxAllowedKeyLength(String transformation) 1562 throws NoSuchAlgorithmException { 1563 if (transformation == null) { 1564 throw new NullPointerException("transformation == null"); 1565 } 1566 checkTransformation(transformation); 1567 //FIXME jurisdiction policy files 1568 return Integer.MAX_VALUE; 1569 } 1570 1571 /** 1572 * Returns the maximum cipher parameter value for the specified 1573 * transformation. If there is no maximum limit, {@code null} is returned. 1574 * 1575 * @param transformation 1576 * the transformation name. 1577 * @return a parameter spec holding the maximum value or {@code null}. 1578 * Currently {@code null}. 1579 * @throws NoSuchAlgorithmException 1580 * if no provider for the specified {@code transformation} can 1581 * be found. 1582 * @throws NullPointerException 1583 * if {@code transformation} is {@code null}. 1584 */ getMaxAllowedParameterSpec( String transformation)1585 public static final AlgorithmParameterSpec getMaxAllowedParameterSpec( 1586 String transformation) throws NoSuchAlgorithmException { 1587 if (transformation == null) { 1588 throw new NullPointerException("transformation == null"); 1589 } 1590 checkTransformation(transformation); 1591 //FIXME jurisdiction policy files 1592 return null; 1593 } 1594 } 1595