1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package javax.crypto; 19 20import java.nio.ByteBuffer; 21import java.security.AlgorithmParameters; 22import java.security.InvalidAlgorithmParameterException; 23import java.security.InvalidKeyException; 24import java.security.InvalidParameterException; 25import java.security.Key; 26import java.security.NoSuchAlgorithmException; 27import java.security.NoSuchProviderException; 28import java.security.Provider; 29import java.security.SecureRandom; 30import java.security.Security; 31import java.security.cert.Certificate; 32import java.security.cert.X509Certificate; 33import java.security.spec.AlgorithmParameterSpec; 34import java.util.Set; 35import org.apache.harmony.crypto.internal.NullCipherSpi; 36import 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 */ 62public 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(); 145 } 146 if (!(cipherSpi instanceof NullCipherSpi) && provider == null) { 147 throw new NullPointerException(); 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 the input is {@code null}, or if {@code inputOffset} and 879 * {@code inputLen} do not specify a valid chunk in the input 880 * buffer. 881 */ 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 if (inputOffset < 0 || inputLen < 0 890 || inputLen > input.length 891 || inputOffset > input.length - inputLen) { 892 throw new IllegalArgumentException("Incorrect inputOffset/inputLen parameters"); 893 } 894 if (input.length == 0) { 895 return null; 896 } 897 return spiImpl.engineUpdate(input, inputOffset, inputLen); 898 } 899 900 /** 901 * Continues a multi-part transformation (encryption or decryption). The 902 * transformed bytes are stored in the {@code output} buffer. 903 * <p> 904 * If the size of the {@code output} buffer is too small to hold the result, 905 * a {@code ShortBufferException} is thrown. Use 906 * {@link Cipher#getOutputSize getOutputSize} to check for the size of the 907 * output buffer. 908 * 909 * @param input 910 * the input bytes to transform. 911 * @param inputOffset 912 * the offset in the input to start. 913 * @param inputLen 914 * the length of the input to transform. 915 * @param output 916 * the output buffer. 917 * @return the number of bytes placed in output. 918 * @throws ShortBufferException 919 * if the size of the {@code output} buffer is too small. 920 * @throws IllegalStateException 921 * if this cipher instance is not initialized for encryption or 922 * decryption. 923 * @throws IllegalArgumentException 924 * if the input is {@code null}, the output is {@code null}, or 925 * if {@code inputOffset} and {@code inputLen} do not specify a 926 * valid chunk in the input buffer. 927 */ 928 public final int update(byte[] input, int inputOffset, int inputLen, 929 byte[] output) throws ShortBufferException { 930 return update(input, inputOffset, inputLen, output, 0); 931 } 932 933 /** 934 * Continues a multi-part transformation (encryption or decryption). The 935 * transformed bytes are stored in the {@code output} buffer. 936 * <p> 937 * If the size of the {@code output} buffer is too small to hold the result, 938 * a {@code ShortBufferException} is thrown. Use 939 * {@link Cipher#getOutputSize getOutputSize} to check for the size of the 940 * output buffer. 941 * 942 * @param input 943 * the input bytes to transform. 944 * @param inputOffset 945 * the offset in the input to start. 946 * @param inputLen 947 * the length of the input to transform. 948 * @param output 949 * the output buffer. 950 * @param outputOffset 951 * the offset in the output buffer. 952 * @return the number of bytes placed in output. 953 * @throws ShortBufferException 954 * if the size of the {@code output} buffer is too small. 955 * @throws IllegalStateException 956 * if this cipher instance is not initialized for encryption or 957 * decryption. 958 * @throws IllegalArgumentException 959 * if the input is {@code null}, the output is {@code null}, or 960 * if {@code inputOffset} and {@code inputLen} do not specify a 961 * valid chunk in the input buffer. 962 */ 963 public final int update(byte[] input, int inputOffset, int inputLen, 964 byte[] output, int outputOffset) throws ShortBufferException { 965 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 966 throw new IllegalStateException(); 967 } 968 if (input == null) { 969 throw new IllegalArgumentException("input == null"); 970 } 971 if (output == null) { 972 throw new IllegalArgumentException("output == null"); 973 } 974 if (outputOffset < 0) { 975 throw new IllegalArgumentException("outputOffset < 0"); 976 } 977 if (inputOffset < 0 || inputLen < 0 || inputLen > input.length 978 || inputOffset > input.length - inputLen) { 979 throw new IllegalArgumentException("Incorrect inputOffset/inputLen parameters"); 980 } 981 if (input.length == 0) { 982 return 0; 983 } 984 return spiImpl.engineUpdate(input, inputOffset, inputLen, output, 985 outputOffset); 986 } 987 988 /** 989 * Continues a multi-part transformation (encryption or decryption). The 990 * {@code input.remaining()} bytes starting at {@code input.position()} are 991 * transformed and stored in the {@code output} buffer. 992 * <p> 993 * If the {@code output.remaining()} is too small to hold the transformed 994 * bytes a {@code ShortBufferException} is thrown. Use 995 * {@link Cipher#getOutputSize getOutputSize} to check for the size of the 996 * output buffer. 997 * 998 * @param input 999 * the input buffer to transform. 1000 * @param output 1001 * the output buffer to store the result within. 1002 * @return the number of bytes stored in the output buffer. 1003 * @throws ShortBufferException 1004 * if the size of the {@code output} buffer is too small. 1005 * @throws IllegalStateException 1006 * if this cipher instance is not initialized for encryption or 1007 * decryption. 1008 * @throws IllegalArgumentException 1009 * if the input buffer and the output buffer are the identical 1010 * object. 1011 */ 1012 public final int update(ByteBuffer input, ByteBuffer output) 1013 throws ShortBufferException { 1014 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1015 throw new IllegalStateException(); 1016 } 1017 if (input == output) { 1018 throw new IllegalArgumentException("input == output"); 1019 } 1020 return spiImpl.engineUpdate(input, output); 1021 } 1022 1023 /** 1024 * Finishes a multi-part transformation (encryption or decryption). 1025 * <p> 1026 * Processes any bytes that may have been buffered in previous {@code 1027 * update} calls. 1028 * 1029 * @return the final bytes from the transformation. 1030 * @throws IllegalBlockSizeException 1031 * if the size of the resulting bytes is not a multiple of the 1032 * cipher block size. 1033 * @throws BadPaddingException 1034 * if the padding of the data does not match the padding scheme. 1035 * @throws IllegalStateException 1036 * if this cipher instance is not initialized for encryption or 1037 * decryption. 1038 */ 1039 public final byte[] doFinal() throws IllegalBlockSizeException, 1040 BadPaddingException { 1041 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1042 throw new IllegalStateException(); 1043 } 1044 return spiImpl.engineDoFinal(null, 0, 0); 1045 } 1046 1047 /** 1048 * Finishes a multi-part transformation (encryption or decryption). 1049 * <p> 1050 * Processes any bytes that may have been buffered in previous {@code 1051 * update} calls. 1052 * <p> 1053 * The final transformed bytes are stored in the {@code output} buffer. 1054 * 1055 * @param output 1056 * the output buffer. 1057 * @param outputOffset 1058 * the offset in the output buffer. 1059 * @return the number of bytes placed in the output buffer. 1060 * @throws IllegalBlockSizeException 1061 * if the size of the resulting bytes is not a multiple of the 1062 * cipher block size. 1063 * @throws ShortBufferException 1064 * if the size of the {@code output} buffer is too small. 1065 * @throws BadPaddingException 1066 * if the padding of the data does not match the padding scheme. 1067 * @throws IllegalStateException 1068 * if this cipher instance is not initialized for encryption or 1069 * decryption. 1070 */ 1071 public final int doFinal(byte[] output, int outputOffset) 1072 throws IllegalBlockSizeException, ShortBufferException, 1073 BadPaddingException { 1074 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1075 throw new IllegalStateException(); 1076 } 1077 if (outputOffset < 0) { 1078 throw new IllegalArgumentException("outputOffset < 0"); 1079 } 1080 return spiImpl.engineDoFinal(null, 0, 0, output, outputOffset); 1081 } 1082 1083 /** 1084 * Finishes a multi-part transformation (encryption or decryption). 1085 * <p> 1086 * Processes the bytes in {@code input} buffer, and any bytes that have been 1087 * buffered in previous {@code update} calls. 1088 * 1089 * @param input 1090 * the input buffer. 1091 * @return the final bytes from the transformation. 1092 * @throws IllegalBlockSizeException 1093 * if the size of the resulting bytes is not a multiple of the 1094 * cipher block size. 1095 * @throws BadPaddingException 1096 * if the padding of the data does not match the padding scheme. 1097 * @throws IllegalStateException 1098 * if this cipher instance is not initialized for encryption or 1099 * decryption. 1100 */ 1101 public final byte[] doFinal(byte[] input) throws IllegalBlockSizeException, 1102 BadPaddingException { 1103 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1104 throw new IllegalStateException(); 1105 } 1106 return spiImpl.engineDoFinal(input, 0, input.length); 1107 } 1108 1109 /** 1110 * Finishes a multi-part transformation (encryption or decryption). 1111 * <p> 1112 * Processes the {@code inputLen} bytes in {@code input} buffer at {@code 1113 * inputOffset}, and any bytes that have been buffered in previous {@code 1114 * update} calls. 1115 * 1116 * @param input 1117 * the input buffer. 1118 * @param inputOffset 1119 * the offset in the input buffer. 1120 * @param inputLen 1121 * the length of the input 1122 * @return the final bytes from the transformation. 1123 * @throws IllegalBlockSizeException 1124 * if the size of the resulting bytes is not a multiple of the 1125 * cipher block size. 1126 * @throws BadPaddingException 1127 * if the padding of the data does not match the padding scheme. 1128 * @throws IllegalStateException 1129 * if this cipher instance is not initialized for encryption or 1130 * decryption. 1131 * @throws IllegalArgumentException 1132 * if {@code inputOffset} and {@code inputLen} do not specify an 1133 * valid chunk in the input buffer. 1134 */ 1135 public final byte[] doFinal(byte[] input, int inputOffset, int inputLen) 1136 throws IllegalBlockSizeException, BadPaddingException { 1137 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1138 throw new IllegalStateException(); 1139 } 1140 if (inputOffset < 0 || inputLen < 0 || inputOffset + inputLen > input.length) { 1141 throw new IllegalArgumentException("Incorrect inputOffset/inputLen parameters"); 1142 } 1143 return spiImpl.engineDoFinal(input, inputOffset, inputLen); 1144 } 1145 1146 /** 1147 * Finishes a multi-part transformation (encryption or decryption). 1148 * <p> 1149 * Processes the {@code inputLen} bytes in {@code input} buffer at {@code 1150 * inputOffset}, and any bytes that have been buffered in previous {@code 1151 * update} calls. 1152 * 1153 * @param input 1154 * the input buffer. 1155 * @param inputOffset 1156 * the offset in the input buffer. 1157 * @param inputLen 1158 * the length of the input. 1159 * @param output 1160 * the output buffer for the transformed bytes. 1161 * @return the number of bytes placed in the output buffer. 1162 * @throws ShortBufferException 1163 * if the size of the {@code output} buffer is too small. 1164 * @throws IllegalBlockSizeException 1165 * if the size of the resulting bytes is not a multiple of the 1166 * cipher block size. 1167 * @throws BadPaddingException 1168 * if the padding of the data does not match the padding scheme. 1169 * @throws IllegalStateException 1170 * if this cipher instance is not initialized for encryption or 1171 * decryption. 1172 * @throws IllegalArgumentException 1173 * if {@code inputOffset} and {@code inputLen} do not specify an 1174 * valid chunk in the input buffer. 1175 */ 1176 public final int doFinal(byte[] input, int inputOffset, int inputLen, 1177 byte[] output) throws ShortBufferException, 1178 IllegalBlockSizeException, BadPaddingException { 1179 return doFinal(input, inputOffset, inputLen, output, 0); 1180 } 1181 1182 /** 1183 * Finishes a multi-part transformation (encryption or decryption). 1184 * <p> 1185 * Processes the {@code inputLen} bytes in {@code input} buffer at {@code 1186 * inputOffset}, and any bytes that have been buffered in previous {@code 1187 * update} calls. 1188 * 1189 * @param input 1190 * the input buffer. 1191 * @param inputOffset 1192 * the offset in the input buffer. 1193 * @param inputLen 1194 * the length of the input. 1195 * @param output 1196 * the output buffer for the transformed bytes. 1197 * @param outputOffset 1198 * the offset in the output buffer. 1199 * @return the number of bytes placed in the output buffer. 1200 * @throws ShortBufferException 1201 * if the size of the {@code output} buffer is too small. 1202 * @throws IllegalBlockSizeException 1203 * if the size of the resulting bytes is not a multiple of the 1204 * cipher block size. 1205 * @throws BadPaddingException 1206 * if the padding of the data does not match the padding scheme. 1207 * @throws IllegalStateException 1208 * if this cipher instance is not initialized for encryption or 1209 * decryption. 1210 * @throws IllegalArgumentException 1211 * if {@code inputOffset} and {@code inputLen} do not specify an 1212 * valid chunk in the input buffer. 1213 */ 1214 public final int doFinal(byte[] input, int inputOffset, int inputLen, 1215 byte[] output, int outputOffset) throws ShortBufferException, 1216 IllegalBlockSizeException, BadPaddingException { 1217 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1218 throw new IllegalStateException(); 1219 } 1220 if (inputOffset < 0 || inputLen < 0 || inputOffset + inputLen > input.length) { 1221 throw new IllegalArgumentException("Incorrect inputOffset/inputLen parameters"); 1222 } 1223 return spiImpl.engineDoFinal(input, inputOffset, inputLen, output, 1224 outputOffset); 1225 } 1226 1227 /** 1228 * Finishes a multi-part transformation (encryption or decryption). 1229 * <p> 1230 * Processes the {@code input.remaining()} bytes in {@code input} buffer at 1231 * {@code input.position()}, and any bytes that have been buffered in 1232 * previous {@code update} calls. The transformed bytes are placed into 1233 * {@code output} buffer. 1234 * 1235 * @param input 1236 * the input buffer. 1237 * @param output 1238 * the output buffer. 1239 * @return the number of bytes placed into the output buffer. 1240 * @throws ShortBufferException 1241 * if the size of the {@code output} buffer is too small. 1242 * @throws IllegalBlockSizeException 1243 * if the size of the resulting bytes is not a multiple of the 1244 * cipher block size. 1245 * @throws BadPaddingException 1246 * if the padding of the data does not match the padding scheme. 1247 * @throws IllegalArgumentException 1248 * if the input buffer and the output buffer are the same 1249 * object. 1250 * @throws IllegalStateException 1251 * if this cipher instance is not initialized for encryption or 1252 * decryption. 1253 */ 1254 public final int doFinal(ByteBuffer input, ByteBuffer output) 1255 throws ShortBufferException, IllegalBlockSizeException, 1256 BadPaddingException { 1257 if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) { 1258 throw new IllegalStateException(); 1259 } 1260 if (input == output) { 1261 throw new IllegalArgumentException("input == output"); 1262 } 1263 return spiImpl.engineDoFinal(input, output); 1264 } 1265 1266 /** 1267 * Wraps a key using this cipher instance. 1268 * 1269 * @param key 1270 * the key to wrap. 1271 * @return the wrapped key. 1272 * @throws IllegalBlockSizeException 1273 * if the size of the resulting bytes is not a multiple of the 1274 * cipher block size. 1275 * @throws InvalidKeyException 1276 * if this cipher instance can not wrap this key. 1277 * @throws IllegalStateException 1278 * if this cipher instance is not initialized for wrapping. 1279 */ 1280 public final byte[] wrap(Key key) throws IllegalBlockSizeException, 1281 InvalidKeyException { 1282 if (mode != WRAP_MODE) { 1283 throw new IllegalStateException(); 1284 } 1285 return spiImpl.engineWrap(key); 1286 } 1287 1288 /** 1289 * Unwraps a key using this cipher instance. 1290 * 1291 * @param wrappedKey 1292 * the wrapped key to unwrap. 1293 * @param wrappedKeyAlgorithm 1294 * the algorithm for the wrapped key. 1295 * @param wrappedKeyType 1296 * the type of the wrapped key (one of: {@code SECRET_KEY 1297 * <code>, <code>PRIVATE_KEY} or {@code PUBLIC_KEY}) 1298 * @return the unwrapped key 1299 * @throws InvalidKeyException 1300 * if the {@code wrappedKey} can not be unwrapped to a key of 1301 * type {@code wrappedKeyType} for the {@code 1302 * wrappedKeyAlgorithm}. 1303 * @throws NoSuchAlgorithmException 1304 * if no provider can be found that can create a key of type 1305 * {@code wrappedKeyType} for the {@code wrappedKeyAlgorithm}. 1306 * @throws IllegalStateException 1307 * if this cipher instance is not initialized for unwrapping. 1308 */ 1309 public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, 1310 int wrappedKeyType) throws InvalidKeyException, 1311 NoSuchAlgorithmException { 1312 if (mode != UNWRAP_MODE) { 1313 throw new IllegalStateException(); 1314 } 1315 return spiImpl.engineUnwrap(wrappedKey, wrappedKeyAlgorithm, 1316 wrappedKeyType); 1317 } 1318 1319 /** 1320 * Returns the maximum key length for the specified transformation. 1321 * 1322 * @param transformation 1323 * the transformation name. 1324 * @return the maximum key length, currently {@code Integer.MAX_VALUE}. 1325 * @throws NoSuchAlgorithmException 1326 * if no provider for the specified {@code transformation} can 1327 * be found. 1328 * @throws NullPointerException 1329 * if {@code transformation} is {@code null}. 1330 */ 1331 public static final int getMaxAllowedKeyLength(String transformation) 1332 throws NoSuchAlgorithmException { 1333 if (transformation == null) { 1334 throw new NullPointerException(); 1335 } 1336 checkTransformation(transformation); 1337 //FIXME jurisdiction policy files 1338 return Integer.MAX_VALUE; 1339 } 1340 1341 /** 1342 * Returns the maximum cipher parameter value for the specified 1343 * transformation. If there is no maximum limit, {@code null} is returned. 1344 * 1345 * @param transformation 1346 * the transformation name. 1347 * @return a parameter spec holding the maximum value or {@code null}. 1348 * Currently {@code null}. 1349 * @throws NoSuchAlgorithmException 1350 * if no provider for the specified {@code transformation} can 1351 * be found. 1352 * @throws NullPointerException 1353 * if {@code transformation} is {@code null}. 1354 */ 1355 public static final AlgorithmParameterSpec getMaxAllowedParameterSpec( 1356 String transformation) throws NoSuchAlgorithmException { 1357 if (transformation == null) { 1358 throw new NullPointerException(); 1359 } 1360 checkTransformation(transformation); 1361 //FIXME jurisdiction policy files 1362 return null; 1363 } 1364} 1365