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