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