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