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