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 */ 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 */ 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 */ 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 */ 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 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 {@code input} is {@code null}, or if {@code inputOffset} and 879 * {@code inputLen} do not specify a valid chunk in the input 880 * buffer. 881 */ 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 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 */ 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 */ 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 */ 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 * Continues a multi-part transformation (encryption or decryption) with 1030 * Authenticated Additional Data (AAD). AAD may only be added after the 1031 * {@code Cipher} is initialized and before any data is passed to the 1032 * instance. 1033 * <p> 1034 * This is only usable with cipher modes that support Authenticated 1035 * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM). 1036 * 1037 * @param input bytes of AAD to use with the cipher 1038 * @throws IllegalStateException 1039 * if this cipher instance is not initialized for encryption or 1040 * decryption. 1041 * @throws IllegalArgumentException 1042 * if {@code input} is {@code null} 1043 * @throws UnsupportedOperationException if the cipher does not support AEAD 1044 * @since 1.7 1045 */ 1046 public final void updateAAD(byte[] input) { 1047 if (input == null) { 1048 throw new IllegalArgumentException("input == null"); 1049 } 1050 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1051 throw new IllegalStateException(); 1052 } 1053 if (input.length == 0) { 1054 return; 1055 } 1056 spiImpl.engineUpdateAAD(input, 0, input.length); 1057 } 1058 1059 /** 1060 * Continues a multi-part transformation (encryption or decryption) with 1061 * Authenticated Additional Data (AAD). AAD may only be added after the 1062 * {@code Cipher} is initialized and before any data is passed to the 1063 * instance. 1064 * <p> 1065 * This is only usable with cipher modes that support Authenticated 1066 * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM). 1067 * 1068 * @param input bytes of AAD to use with the cipher 1069 * @param inputOffset offset within bytes of additional data to add to cipher 1070 * @param inputLen length of bytes of additional data to add to cipher 1071 * @throws IllegalStateException 1072 * if this cipher instance is not initialized for encryption or 1073 * decryption. 1074 * @throws IllegalArgumentException 1075 * if {@code input} is {@code null}, or if {@code inputOffset} and 1076 * {@code inputLen} do not specify a valid chunk in the input 1077 * buffer. 1078 * @throws UnsupportedOperationException if the cipher does not support AEAD 1079 * @since 1.7 1080 */ 1081 public final void updateAAD(byte[] input, int inputOffset, int inputLen) { 1082 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1083 throw new IllegalStateException(); 1084 } 1085 if (input == null) { 1086 throw new IllegalArgumentException("input == null"); 1087 } 1088 checkInputOffsetAndCount(input.length, inputOffset, inputLen); 1089 if (input.length == 0) { 1090 return; 1091 } 1092 spiImpl.engineUpdateAAD(input, inputOffset, inputLen); 1093 } 1094 1095 /** 1096 * Continues a multi-part transformation (encryption or decryption) with 1097 * Authenticated Additional Data (AAD). AAD may only be added after the 1098 * {@code Cipher} is initialized and before any data is passed to the 1099 * instance. 1100 * <p> 1101 * This is only usable with cipher modes that support Authenticated 1102 * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM). 1103 * 1104 * @param input buffer of AAD to be used 1105 * @throws IllegalStateException 1106 * if this cipher instance is not initialized for encryption or 1107 * decryption. 1108 * @throws UnsupportedOperationException if the cipher does not support AEAD 1109 * @since 1.7 1110 */ 1111 public final void updateAAD(ByteBuffer input) { 1112 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1113 throw new IllegalStateException("Cipher is not initialized"); 1114 } 1115 if (input == null) { 1116 throw new IllegalArgumentException("input == null"); 1117 } 1118 spiImpl.engineUpdateAAD(input); 1119 } 1120 1121 /** 1122 * Finishes a multi-part transformation (encryption or decryption). 1123 * <p> 1124 * Processes any bytes that may have been buffered in previous {@code 1125 * update} calls. 1126 * 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 */ 1137 public final byte[] doFinal() throws IllegalBlockSizeException, 1138 BadPaddingException { 1139 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1140 throw new IllegalStateException(); 1141 } 1142 return spiImpl.engineDoFinal(null, 0, 0); 1143 } 1144 1145 /** 1146 * Finishes a multi-part transformation (encryption or decryption). 1147 * <p> 1148 * Processes any bytes that may have been buffered in previous {@code 1149 * update} calls. 1150 * <p> 1151 * The final transformed bytes are stored in the {@code output} buffer. 1152 * 1153 * @param output 1154 * the output buffer. 1155 * @param outputOffset 1156 * the offset in the output buffer. 1157 * @return the number of bytes placed in the output buffer. 1158 * @throws IllegalBlockSizeException 1159 * if the size of the resulting bytes is not a multiple of the 1160 * cipher block size. 1161 * @throws ShortBufferException 1162 * if the size of the {@code output} buffer is too small. 1163 * @throws BadPaddingException 1164 * if the padding of the data does not match the padding scheme. 1165 * @throws IllegalStateException 1166 * if this cipher instance is not initialized for encryption or 1167 * decryption. 1168 */ 1169 public final int doFinal(byte[] output, int outputOffset) 1170 throws IllegalBlockSizeException, ShortBufferException, 1171 BadPaddingException { 1172 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1173 throw new IllegalStateException(); 1174 } 1175 if (outputOffset < 0) { 1176 throw new IllegalArgumentException("outputOffset < 0. outputOffset=" + outputOffset); 1177 } 1178 return spiImpl.engineDoFinal(null, 0, 0, output, outputOffset); 1179 } 1180 1181 /** 1182 * Finishes a multi-part transformation (encryption or decryption). 1183 * <p> 1184 * Processes the bytes in {@code input} buffer, and any bytes that have been 1185 * buffered in previous {@code update} calls. 1186 * 1187 * @param input 1188 * the input buffer. 1189 * @return the final bytes from the transformation. 1190 * @throws IllegalBlockSizeException 1191 * if the size of the resulting bytes is not a multiple of the 1192 * cipher block size. 1193 * @throws BadPaddingException 1194 * if the padding of the data does not match the padding scheme. 1195 * @throws IllegalStateException 1196 * if this cipher instance is not initialized for encryption or 1197 * decryption. 1198 */ 1199 public final byte[] doFinal(byte[] input) throws IllegalBlockSizeException, 1200 BadPaddingException { 1201 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1202 throw new IllegalStateException(); 1203 } 1204 return spiImpl.engineDoFinal(input, 0, input.length); 1205 } 1206 1207 /** 1208 * Finishes a multi-part transformation (encryption or decryption). 1209 * <p> 1210 * Processes the {@code inputLen} bytes in {@code input} buffer at {@code 1211 * inputOffset}, and any bytes that have been buffered in previous {@code 1212 * update} calls. 1213 * 1214 * @param input 1215 * the input buffer. 1216 * @param inputOffset 1217 * the offset in the input buffer. 1218 * @param inputLen 1219 * the length of the input 1220 * @return the final bytes from the transformation. 1221 * @throws IllegalBlockSizeException 1222 * if the size of the resulting bytes is not a multiple of the 1223 * cipher block size. 1224 * @throws BadPaddingException 1225 * if the padding of the data does not match the padding scheme. 1226 * @throws IllegalStateException 1227 * if this cipher instance is not initialized for encryption or 1228 * decryption. 1229 * @throws IllegalArgumentException 1230 * if {@code inputOffset} and {@code inputLen} do not specify an 1231 * valid chunk in the input buffer. 1232 */ 1233 public final byte[] doFinal(byte[] input, int inputOffset, int inputLen) 1234 throws IllegalBlockSizeException, BadPaddingException { 1235 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1236 throw new IllegalStateException(); 1237 } 1238 checkInputOffsetAndCount(input.length, inputOffset, inputLen); 1239 return spiImpl.engineDoFinal(input, inputOffset, inputLen); 1240 } 1241 1242 /** 1243 * Finishes a multi-part transformation (encryption or decryption). 1244 * <p> 1245 * Processes the {@code inputLen} bytes in {@code input} buffer at {@code 1246 * inputOffset}, and any bytes that have been buffered in previous {@code 1247 * update} calls. 1248 * 1249 * @param input 1250 * the input buffer. 1251 * @param inputOffset 1252 * the offset in the input buffer. 1253 * @param inputLen 1254 * the length of the input. 1255 * @param output 1256 * the output buffer for the transformed bytes. 1257 * @return the number of bytes placed in the output buffer. 1258 * @throws ShortBufferException 1259 * if the size of the {@code output} buffer is too small. 1260 * @throws IllegalBlockSizeException 1261 * if the size of the resulting bytes is not a multiple of the 1262 * cipher block size. 1263 * @throws BadPaddingException 1264 * if the padding of the data does not match the padding scheme. 1265 * @throws IllegalStateException 1266 * if this cipher instance is not initialized for encryption or 1267 * decryption. 1268 * @throws IllegalArgumentException 1269 * if {@code inputOffset} and {@code inputLen} do not specify an 1270 * valid chunk in the input buffer. 1271 */ 1272 public final int doFinal(byte[] input, int inputOffset, int inputLen, 1273 byte[] output) throws ShortBufferException, 1274 IllegalBlockSizeException, BadPaddingException { 1275 return doFinal(input, inputOffset, inputLen, output, 0); 1276 } 1277 1278 /** 1279 * Finishes a multi-part transformation (encryption or decryption). 1280 * <p> 1281 * Processes the {@code inputLen} bytes in {@code input} buffer at {@code 1282 * inputOffset}, and any bytes that have been buffered in previous {@code 1283 * update} calls. 1284 * 1285 * @param input 1286 * the input buffer. 1287 * @param inputOffset 1288 * the offset in the input buffer. 1289 * @param inputLen 1290 * the length of the input. 1291 * @param output 1292 * the output buffer for the transformed bytes. 1293 * @param outputOffset 1294 * the offset in the output buffer. 1295 * @return the number of bytes placed in the output buffer. 1296 * @throws ShortBufferException 1297 * if the size of the {@code output} buffer is too small. 1298 * @throws IllegalBlockSizeException 1299 * if the size of the resulting bytes is not a multiple of the 1300 * cipher block size. 1301 * @throws BadPaddingException 1302 * if the padding of the data does not match the padding scheme. 1303 * @throws IllegalStateException 1304 * if this cipher instance is not initialized for encryption or 1305 * decryption. 1306 * @throws IllegalArgumentException 1307 * if {@code inputOffset} and {@code inputLen} do not specify an 1308 * valid chunk in the input buffer. 1309 */ 1310 public final int doFinal(byte[] input, int inputOffset, int inputLen, 1311 byte[] output, int outputOffset) throws ShortBufferException, 1312 IllegalBlockSizeException, BadPaddingException { 1313 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1314 throw new IllegalStateException(); 1315 } 1316 checkInputOffsetAndCount(input.length, inputOffset, inputLen); 1317 return spiImpl.engineDoFinal(input, inputOffset, inputLen, output, 1318 outputOffset); 1319 } 1320 1321 /** 1322 * Finishes a multi-part transformation (encryption or decryption). 1323 * <p> 1324 * Processes the {@code input.remaining()} bytes in {@code input} buffer at 1325 * {@code input.position()}, and any bytes that have been buffered in 1326 * previous {@code update} calls. The transformed bytes are placed into 1327 * {@code output} buffer. 1328 * 1329 * @param input 1330 * the input buffer. 1331 * @param output 1332 * the output buffer. 1333 * @return the number of bytes placed into the output buffer. 1334 * @throws ShortBufferException 1335 * if the size of the {@code output} buffer is too small. 1336 * @throws IllegalBlockSizeException 1337 * if the size of the resulting bytes is not a multiple of the 1338 * cipher block size. 1339 * @throws BadPaddingException 1340 * if the padding of the data does not match the padding scheme. 1341 * @throws IllegalArgumentException 1342 * if the input buffer and the output buffer are the same 1343 * object. 1344 * @throws IllegalStateException 1345 * if this cipher instance is not initialized for encryption or 1346 * decryption. 1347 */ 1348 public final int doFinal(ByteBuffer input, ByteBuffer output) 1349 throws ShortBufferException, IllegalBlockSizeException, 1350 BadPaddingException { 1351 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1352 throw new IllegalStateException(); 1353 } 1354 if (input == output) { 1355 throw new IllegalArgumentException("input == output"); 1356 } 1357 return spiImpl.engineDoFinal(input, output); 1358 } 1359 1360 /** 1361 * Wraps a key using this cipher instance. 1362 * 1363 * @param key 1364 * the key to wrap. 1365 * @return the wrapped key. 1366 * @throws IllegalBlockSizeException 1367 * if the size of the resulting bytes is not a multiple of the 1368 * cipher block size. 1369 * @throws InvalidKeyException 1370 * if this cipher instance can not wrap this key. 1371 * @throws IllegalStateException 1372 * if this cipher instance is not initialized for wrapping. 1373 */ 1374 public final byte[] wrap(Key key) throws IllegalBlockSizeException, 1375 InvalidKeyException { 1376 if (mode != WRAP_MODE) { 1377 throw new IllegalStateException(); 1378 } 1379 return spiImpl.engineWrap(key); 1380 } 1381 1382 /** 1383 * Unwraps a key using this cipher instance. 1384 * 1385 * @param wrappedKey 1386 * the wrapped key to unwrap. 1387 * @param wrappedKeyAlgorithm 1388 * the algorithm for the wrapped key. 1389 * @param wrappedKeyType 1390 * the type of the wrapped key (one of: {@code SECRET_KEY 1391 * <code>, <code>PRIVATE_KEY} or {@code PUBLIC_KEY}) 1392 * @return the unwrapped key 1393 * @throws InvalidKeyException 1394 * if the {@code wrappedKey} can not be unwrapped to a key of 1395 * type {@code wrappedKeyType} for the {@code 1396 * wrappedKeyAlgorithm}. 1397 * @throws NoSuchAlgorithmException 1398 * if no provider can be found that can create a key of type 1399 * {@code wrappedKeyType} for the {@code wrappedKeyAlgorithm}. 1400 * @throws IllegalStateException 1401 * if this cipher instance is not initialized for unwrapping. 1402 */ 1403 public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, 1404 int wrappedKeyType) throws InvalidKeyException, 1405 NoSuchAlgorithmException { 1406 if (mode != UNWRAP_MODE) { 1407 throw new IllegalStateException(); 1408 } 1409 return spiImpl.engineUnwrap(wrappedKey, wrappedKeyAlgorithm, 1410 wrappedKeyType); 1411 } 1412 1413 /** 1414 * Returns the maximum key length for the specified transformation. 1415 * 1416 * @param transformation 1417 * the transformation name. 1418 * @return the maximum key length, currently {@code Integer.MAX_VALUE}. 1419 * @throws NoSuchAlgorithmException 1420 * if no provider for the specified {@code transformation} can 1421 * be found. 1422 * @throws NullPointerException 1423 * if {@code transformation} is {@code null}. 1424 */ 1425 public static final int getMaxAllowedKeyLength(String transformation) 1426 throws NoSuchAlgorithmException { 1427 if (transformation == null) { 1428 throw new NullPointerException("transformation == null"); 1429 } 1430 checkTransformation(transformation); 1431 //FIXME jurisdiction policy files 1432 return Integer.MAX_VALUE; 1433 } 1434 1435 /** 1436 * Returns the maximum cipher parameter value for the specified 1437 * transformation. If there is no maximum limit, {@code null} is returned. 1438 * 1439 * @param transformation 1440 * the transformation name. 1441 * @return a parameter spec holding the maximum value or {@code null}. 1442 * Currently {@code null}. 1443 * @throws NoSuchAlgorithmException 1444 * if no provider for the specified {@code transformation} can 1445 * be found. 1446 * @throws NullPointerException 1447 * if {@code transformation} is {@code null}. 1448 */ 1449 public static final AlgorithmParameterSpec getMaxAllowedParameterSpec( 1450 String transformation) throws NoSuchAlgorithmException { 1451 if (transformation == null) { 1452 throw new NullPointerException("transformation == null"); 1453 } 1454 checkTransformation(transformation); 1455 //FIXME jurisdiction policy files 1456 return null; 1457 } 1458 } 1459