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