src/java.base/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java
changeset 47216 71c04702a3d5
parent 36248 29aaf8a0d7a9
child 51504 c9a3e3cac9c7
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package com.sun.crypto.provider;
       
    27 
       
    28 import java.math.BigInteger;
       
    29 import java.security.*;
       
    30 import java.security.spec.*;
       
    31 import java.util.Arrays;
       
    32 import javax.crypto.*;
       
    33 import javax.crypto.spec.*;
       
    34 
       
    35 /**
       
    36  * This class implements password-base encryption algorithm with
       
    37  * SHA1 digest and the following Ciphers (in CBC mode, where applicable):
       
    38  * - DESede cipher and
       
    39  * - RC2 Cipher with 40-bit or 128-bit effective key length and
       
    40  * - RC4 Cipher with 40-bit or 128-bit effective key length
       
    41  * as defined by PKCS #12 version 1.0 standard.
       
    42  *
       
    43  * @author Valerie Peng
       
    44  * @see javax.crypto.CipherSpi
       
    45  */
       
    46 final class PKCS12PBECipherCore {
       
    47 
       
    48     // TBD: replace CipherCore with a CipherSpi object to simplify maintenance
       
    49 
       
    50     private CipherCore cipher;
       
    51     private int blockSize;
       
    52     private int keySize;
       
    53     private int keyLength; // in bits
       
    54     private String algo = null;
       
    55     private String pbeAlgo = null;
       
    56     private byte[] salt = null;
       
    57     private int iCount = 0;
       
    58 
       
    59     private static final int DEFAULT_SALT_LENGTH = 20;
       
    60     private static final int DEFAULT_COUNT = 1024;
       
    61 
       
    62     static final int CIPHER_KEY = 1;
       
    63     static final int CIPHER_IV = 2;
       
    64     static final int MAC_KEY = 3;
       
    65 
       
    66     // Uses default hash algorithm (SHA-1)
       
    67     static byte[] derive(char[] chars, byte[] salt,
       
    68                          int ic, int n, int type) {
       
    69         return derive(chars, salt, ic, n, type, "SHA-1", 64);
       
    70     }
       
    71 
       
    72     // Uses supplied hash algorithm
       
    73     static byte[] derive(char[] chars, byte[] salt, int ic, int n, int type,
       
    74         String hashAlgo, int blockLength) {
       
    75 
       
    76         // Add in trailing NULL terminator.  Special case:
       
    77         // no terminator if password is "\0".
       
    78         int length = chars.length*2;
       
    79         if (length == 2 && chars[0] == 0) {
       
    80             chars = new char[0];
       
    81             length = 0;
       
    82         } else {
       
    83             length += 2;
       
    84         }
       
    85 
       
    86         byte[] passwd = new byte[length];
       
    87         for (int i = 0, j = 0; i < chars.length; i++, j+=2) {
       
    88             passwd[j] = (byte) ((chars[i] >>> 8) & 0xFF);
       
    89             passwd[j+1] = (byte) (chars[i] & 0xFF);
       
    90         }
       
    91         byte[] key = new byte[n];
       
    92 
       
    93         try {
       
    94             MessageDigest sha = MessageDigest.getInstance(hashAlgo);
       
    95 
       
    96             int v = blockLength;
       
    97             int u = sha.getDigestLength();
       
    98             int c = roundup(n, u) / u;
       
    99             byte[] D = new byte[v];
       
   100             int s = roundup(salt.length, v);
       
   101             int p = roundup(passwd.length, v);
       
   102             byte[] I = new byte[s + p];
       
   103 
       
   104             Arrays.fill(D, (byte)type);
       
   105             concat(salt, I, 0, s);
       
   106             concat(passwd, I, s, p);
       
   107 
       
   108             byte[] Ai;
       
   109             byte[] B = new byte[v];
       
   110             byte[] tmp = new byte[v];
       
   111 
       
   112             int i = 0;
       
   113             for (; ; i++, n -= u) {
       
   114                 sha.update(D);
       
   115                 sha.update(I);
       
   116                 Ai = sha.digest();
       
   117                 for (int r = 1; r < ic; r++)
       
   118                     Ai = sha.digest(Ai);
       
   119                 System.arraycopy(Ai, 0, key, u * i, Math.min(n, u));
       
   120                 if (i + 1 == c)
       
   121                     break;
       
   122                 concat(Ai, B, 0, B.length);
       
   123                 BigInteger B1;
       
   124                 B1 = new BigInteger(1, B).add(BigInteger.ONE);
       
   125 
       
   126                 for (int j = 0; j < I.length; j += v) {
       
   127                     BigInteger Ij;
       
   128                     int trunc;
       
   129 
       
   130                     if (tmp.length != v)
       
   131                         tmp = new byte[v];
       
   132                     System.arraycopy(I, j, tmp, 0, v);
       
   133                     Ij = new BigInteger(1, tmp);
       
   134                     Ij = Ij.add(B1);
       
   135                     tmp = Ij.toByteArray();
       
   136                     trunc = tmp.length - v;
       
   137                     if (trunc >= 0) {
       
   138                         System.arraycopy(tmp, trunc, I, j, v);
       
   139                     } else if (trunc < 0) {
       
   140                         Arrays.fill(I, j, j + (-trunc), (byte)0);
       
   141                         System.arraycopy(tmp, 0, I, j + (-trunc), tmp.length);
       
   142                     }
       
   143                 }
       
   144             }
       
   145         } catch (Exception e) {
       
   146             throw new RuntimeException("internal error: " + e);
       
   147         }
       
   148         return key;
       
   149     }
       
   150 
       
   151     private static int roundup(int x, int y) {
       
   152         return ((x + (y - 1)) / y) * y;
       
   153     }
       
   154 
       
   155     private static void concat(byte[] src, byte[] dst, int start, int len) {
       
   156         if (src.length == 0) {
       
   157             return;
       
   158         }
       
   159         int loop = len / src.length;
       
   160         int off, i;
       
   161         for (i = 0, off = 0; i < loop; i++, off += src.length)
       
   162             System.arraycopy(src, 0, dst, off + start, src.length);
       
   163         System.arraycopy(src, 0, dst, off + start, len - off);
       
   164     }
       
   165 
       
   166     PKCS12PBECipherCore(String symmCipherAlg, int defKeySize)
       
   167         throws NoSuchAlgorithmException {
       
   168 
       
   169         algo = symmCipherAlg;
       
   170         keyLength = defKeySize * 8;
       
   171         if (algo.equals("RC4")) {
       
   172             pbeAlgo = "PBEWithSHA1AndRC4_" + keyLength;
       
   173         } else {
       
   174             SymmetricCipher symmCipher = null;
       
   175             if (algo.equals("DESede")) {
       
   176                 symmCipher = new DESedeCrypt();
       
   177                 pbeAlgo = "PBEWithSHA1AndDESede";
       
   178                 keyLength = 112; // effective key length
       
   179             } else if (algo.equals("RC2")) {
       
   180                 symmCipher = new RC2Crypt();
       
   181                 pbeAlgo = "PBEWithSHA1AndRC2_" + keyLength;
       
   182             } else {
       
   183                 throw new NoSuchAlgorithmException("No Cipher implementation " +
       
   184                        "for PBEWithSHA1And" + algo);
       
   185             }
       
   186             blockSize = symmCipher.getBlockSize();
       
   187             cipher = new CipherCore(symmCipher, blockSize);
       
   188             cipher.setMode("CBC");
       
   189             try {
       
   190                 cipher.setPadding("PKCS5Padding");
       
   191             } catch (NoSuchPaddingException nspe) {
       
   192                 // should not happen
       
   193             }
       
   194         }
       
   195         keySize = defKeySize;
       
   196     }
       
   197 
       
   198     void implSetMode(String mode) throws NoSuchAlgorithmException {
       
   199         if ((mode != null) && (!mode.equalsIgnoreCase("CBC"))) {
       
   200             throw new NoSuchAlgorithmException("Invalid cipher mode: "
       
   201                                                + mode);
       
   202         }
       
   203     }
       
   204 
       
   205     void implSetPadding(String padding) throws NoSuchPaddingException {
       
   206         if ((padding != null) &&
       
   207             (!padding.equalsIgnoreCase("PKCS5Padding"))) {
       
   208             throw new NoSuchPaddingException("Invalid padding scheme: " +
       
   209                                              padding);
       
   210         }
       
   211     }
       
   212 
       
   213     int implGetBlockSize() {
       
   214         return blockSize;
       
   215     }
       
   216 
       
   217     int implGetOutputSize(int inLen) {
       
   218         return cipher.getOutputSize(inLen);
       
   219     }
       
   220 
       
   221     byte[] implGetIV() {
       
   222         return cipher.getIV();
       
   223     }
       
   224 
       
   225     AlgorithmParameters implGetParameters() {
       
   226         AlgorithmParameters params = null;
       
   227         if (salt == null) {
       
   228             // Cipher is not initialized with parameters;
       
   229             // follow the recommendation in PKCS12 v1.0
       
   230             // section B.4 to generate salt and iCount.
       
   231             salt = new byte[DEFAULT_SALT_LENGTH];
       
   232             SunJCE.getRandom().nextBytes(salt);
       
   233             iCount = DEFAULT_COUNT;
       
   234         }
       
   235         PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
       
   236         try {
       
   237             params = AlgorithmParameters.getInstance(pbeAlgo,
       
   238                 SunJCE.getInstance());
       
   239             params.init(pbeSpec);
       
   240         } catch (NoSuchAlgorithmException nsae) {
       
   241             // should never happen
       
   242             throw new RuntimeException(
       
   243                 "SunJCE provider is not configured properly");
       
   244         } catch (InvalidParameterSpecException ipse) {
       
   245             // should never happen
       
   246             throw new RuntimeException("PBEParameterSpec not supported");
       
   247         }
       
   248         return params;
       
   249     }
       
   250 
       
   251     void implInit(int opmode, Key key, AlgorithmParameterSpec params,
       
   252                   SecureRandom random) throws InvalidKeyException,
       
   253         InvalidAlgorithmParameterException {
       
   254         implInit(opmode, key, params, random, null);
       
   255     }
       
   256 
       
   257     void implInit(int opmode, Key key, AlgorithmParameterSpec params,
       
   258                   SecureRandom random, CipherSpi cipherImpl)
       
   259                       throws InvalidKeyException,
       
   260         InvalidAlgorithmParameterException {
       
   261         char[] passwdChars = null;
       
   262         salt = null;
       
   263         iCount = 0;
       
   264         if (key instanceof javax.crypto.interfaces.PBEKey) {
       
   265             javax.crypto.interfaces.PBEKey pbeKey =
       
   266                 (javax.crypto.interfaces.PBEKey) key;
       
   267             passwdChars = pbeKey.getPassword();
       
   268             salt = pbeKey.getSalt(); // maybe null if unspecified
       
   269             iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified
       
   270         } else if (key instanceof SecretKey) {
       
   271             byte[] passwdBytes = key.getEncoded();
       
   272             if ((passwdBytes == null) ||
       
   273                 !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
       
   274                 throw new InvalidKeyException("Missing password");
       
   275             }
       
   276             passwdChars = new char[passwdBytes.length];
       
   277             for (int i=0; i<passwdChars.length; i++) {
       
   278                 passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
       
   279             }
       
   280         } else {
       
   281             throw new InvalidKeyException("SecretKey of PBE type required");
       
   282         }
       
   283 
       
   284         if (((opmode == Cipher.DECRYPT_MODE) ||
       
   285              (opmode == Cipher.UNWRAP_MODE)) &&
       
   286             ((params == null) && ((salt == null) || (iCount == 0)))) {
       
   287             throw new InvalidAlgorithmParameterException
       
   288                 ("Parameters missing");
       
   289         }
       
   290 
       
   291         if (params == null) {
       
   292             // generate default for salt and iteration count if necessary
       
   293             if (salt == null) {
       
   294                 salt = new byte[DEFAULT_SALT_LENGTH];
       
   295                 if (random != null) {
       
   296                     random.nextBytes(salt);
       
   297                 } else {
       
   298                     SunJCE.getRandom().nextBytes(salt);
       
   299                 }
       
   300             }
       
   301             if (iCount == 0) iCount = DEFAULT_COUNT;
       
   302         } else if (!(params instanceof PBEParameterSpec)) {
       
   303             throw new InvalidAlgorithmParameterException
       
   304                 ("PBEParameterSpec type required");
       
   305         } else {
       
   306             PBEParameterSpec pbeParams = (PBEParameterSpec) params;
       
   307             // make sure the parameter values are consistent
       
   308             if (salt != null) {
       
   309                 if (!Arrays.equals(salt, pbeParams.getSalt())) {
       
   310                     throw new InvalidAlgorithmParameterException
       
   311                         ("Inconsistent value of salt between key and params");
       
   312                 }
       
   313             } else {
       
   314                 salt = pbeParams.getSalt();
       
   315             }
       
   316             if (iCount != 0) {
       
   317                 if (iCount != pbeParams.getIterationCount()) {
       
   318                     throw new InvalidAlgorithmParameterException
       
   319                         ("Different iteration count between key and params");
       
   320                 }
       
   321             } else {
       
   322                 iCount = pbeParams.getIterationCount();
       
   323             }
       
   324         }
       
   325         // salt is recommended to be ideally as long as the output
       
   326         // of the hash function. However, it may be too strict to
       
   327         // force this; so instead, we'll just require the minimum
       
   328         // salt length to be 8-byte which is what PKCS#5 recommends
       
   329         // and openssl does.
       
   330         if (salt.length < 8) {
       
   331             throw new InvalidAlgorithmParameterException
       
   332                 ("Salt must be at least 8 bytes long");
       
   333         }
       
   334         if (iCount <= 0) {
       
   335             throw new InvalidAlgorithmParameterException
       
   336                 ("IterationCount must be a positive number");
       
   337         }
       
   338         byte[] derivedKey = derive(passwdChars, salt, iCount,
       
   339                                    keySize, CIPHER_KEY);
       
   340         SecretKey cipherKey = new SecretKeySpec(derivedKey, algo);
       
   341 
       
   342         if (cipherImpl != null && cipherImpl instanceof ARCFOURCipher) {
       
   343             ((ARCFOURCipher)cipherImpl).engineInit(opmode, cipherKey, random);
       
   344 
       
   345         } else {
       
   346             byte[] derivedIv = derive(passwdChars, salt, iCount, 8,
       
   347                                   CIPHER_IV);
       
   348             IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8);
       
   349 
       
   350             // initialize the underlying cipher
       
   351             cipher.init(opmode, cipherKey, ivSpec, random);
       
   352         }
       
   353     }
       
   354 
       
   355     void implInit(int opmode, Key key, AlgorithmParameters params,
       
   356                   SecureRandom random)
       
   357         throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   358         implInit(opmode, key, params, random, null);
       
   359     }
       
   360 
       
   361     void implInit(int opmode, Key key, AlgorithmParameters params,
       
   362                   SecureRandom random, CipherSpi cipherImpl)
       
   363         throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   364         AlgorithmParameterSpec paramSpec = null;
       
   365         if (params != null) {
       
   366             try {
       
   367                 paramSpec = params.getParameterSpec(PBEParameterSpec.class);
       
   368             } catch (InvalidParameterSpecException ipse) {
       
   369                 throw new InvalidAlgorithmParameterException(
       
   370                     "requires PBE parameters");
       
   371             }
       
   372         }
       
   373         implInit(opmode, key, paramSpec, random, cipherImpl);
       
   374     }
       
   375 
       
   376     void implInit(int opmode, Key key, SecureRandom random)
       
   377         throws InvalidKeyException {
       
   378         implInit(opmode, key, random, null);
       
   379     }
       
   380 
       
   381     void implInit(int opmode, Key key, SecureRandom random,
       
   382         CipherSpi cipherImpl) throws InvalidKeyException {
       
   383         try {
       
   384             implInit(opmode, key, (AlgorithmParameterSpec) null, random,
       
   385                 cipherImpl);
       
   386         } catch (InvalidAlgorithmParameterException iape) {
       
   387             throw new InvalidKeyException("requires PBE parameters");
       
   388         }
       
   389     }
       
   390 
       
   391     byte[] implUpdate(byte[] in, int inOff, int inLen) {
       
   392         return cipher.update(in, inOff, inLen);
       
   393     }
       
   394 
       
   395     int implUpdate(byte[] in, int inOff, int inLen, byte[] out, int outOff)
       
   396         throws ShortBufferException {
       
   397         return cipher.update(in, inOff, inLen, out, outOff);
       
   398     }
       
   399 
       
   400     byte[] implDoFinal(byte[] in, int inOff, int inLen)
       
   401         throws IllegalBlockSizeException, BadPaddingException {
       
   402         return cipher.doFinal(in, inOff, inLen);
       
   403     }
       
   404 
       
   405     int implDoFinal(byte[] in, int inOff, int inLen, byte[] out, int outOff)
       
   406         throws ShortBufferException, IllegalBlockSizeException,
       
   407                BadPaddingException {
       
   408         return cipher.doFinal(in, inOff, inLen, out, outOff);
       
   409     }
       
   410 
       
   411     int implGetKeySize(Key key) throws InvalidKeyException {
       
   412         return keyLength;
       
   413     }
       
   414 
       
   415     byte[] implWrap(Key key) throws IllegalBlockSizeException,
       
   416         InvalidKeyException {
       
   417         return cipher.wrap(key);
       
   418     }
       
   419 
       
   420     Key implUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
       
   421                    int wrappedKeyType)
       
   422         throws InvalidKeyException, NoSuchAlgorithmException {
       
   423         return cipher.unwrap(wrappedKey, wrappedKeyAlgorithm,
       
   424                              wrappedKeyType);
       
   425     }
       
   426 
       
   427     public static final class PBEWithSHA1AndDESede extends CipherSpi {
       
   428         private final PKCS12PBECipherCore core;
       
   429         public PBEWithSHA1AndDESede() throws NoSuchAlgorithmException {
       
   430             core = new PKCS12PBECipherCore("DESede", 24);
       
   431         }
       
   432         protected byte[] engineDoFinal(byte[] in, int inOff, int inLen)
       
   433             throws IllegalBlockSizeException, BadPaddingException {
       
   434             return core.implDoFinal(in, inOff, inLen);
       
   435         }
       
   436         protected int engineDoFinal(byte[] in, int inOff, int inLen,
       
   437                                     byte[] out, int outOff)
       
   438             throws ShortBufferException, IllegalBlockSizeException,
       
   439                    BadPaddingException {
       
   440             return core.implDoFinal(in, inOff, inLen, out, outOff);
       
   441         }
       
   442         protected int engineGetBlockSize() {
       
   443             return core.implGetBlockSize();
       
   444         }
       
   445         protected byte[] engineGetIV() {
       
   446             return core.implGetIV();
       
   447         }
       
   448         protected int engineGetKeySize(Key key) throws InvalidKeyException {
       
   449             return core.implGetKeySize(key);
       
   450         }
       
   451         protected int engineGetOutputSize(int inLen) {
       
   452             return core.implGetOutputSize(inLen);
       
   453         }
       
   454         protected AlgorithmParameters engineGetParameters() {
       
   455             return core.implGetParameters();
       
   456         }
       
   457         protected void engineInit(int opmode, Key key,
       
   458                                   AlgorithmParameterSpec params,
       
   459                                   SecureRandom random)
       
   460             throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   461             core.implInit(opmode, key, params, random);
       
   462         }
       
   463         protected void engineInit(int opmode, Key key,
       
   464                                   AlgorithmParameters params,
       
   465                                   SecureRandom random)
       
   466             throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   467             core.implInit(opmode, key, params, random);
       
   468         }
       
   469         protected void engineInit(int opmode, Key key, SecureRandom random)
       
   470             throws InvalidKeyException {
       
   471             core.implInit(opmode, key, random);
       
   472         }
       
   473         protected void engineSetMode(String mode)
       
   474             throws NoSuchAlgorithmException {
       
   475             core.implSetMode(mode);
       
   476         }
       
   477         protected void engineSetPadding(String paddingScheme)
       
   478             throws NoSuchPaddingException {
       
   479             core.implSetPadding(paddingScheme);
       
   480         }
       
   481         protected Key engineUnwrap(byte[] wrappedKey,
       
   482                                    String wrappedKeyAlgorithm,
       
   483                                    int wrappedKeyType)
       
   484             throws InvalidKeyException, NoSuchAlgorithmException {
       
   485             return core.implUnwrap(wrappedKey, wrappedKeyAlgorithm,
       
   486                                    wrappedKeyType);
       
   487         }
       
   488         protected byte[] engineUpdate(byte[] in, int inOff, int inLen) {
       
   489             return core.implUpdate(in, inOff, inLen);
       
   490         }
       
   491         protected int engineUpdate(byte[] in, int inOff, int inLen,
       
   492                                    byte[] out, int outOff)
       
   493             throws ShortBufferException {
       
   494             return core.implUpdate(in, inOff, inLen, out, outOff);
       
   495         }
       
   496         protected byte[] engineWrap(Key key)
       
   497             throws IllegalBlockSizeException, InvalidKeyException {
       
   498             return core.implWrap(key);
       
   499         }
       
   500     }
       
   501 
       
   502     public static final class PBEWithSHA1AndRC2_40 extends CipherSpi {
       
   503         private final PKCS12PBECipherCore core;
       
   504         public PBEWithSHA1AndRC2_40() throws NoSuchAlgorithmException {
       
   505             core = new PKCS12PBECipherCore("RC2", 5);
       
   506         }
       
   507         protected byte[] engineDoFinal(byte[] in, int inOff, int inLen)
       
   508             throws IllegalBlockSizeException, BadPaddingException {
       
   509             return core.implDoFinal(in, inOff, inLen);
       
   510         }
       
   511         protected int engineDoFinal(byte[] in, int inOff, int inLen,
       
   512                                     byte[] out, int outOff)
       
   513             throws ShortBufferException, IllegalBlockSizeException,
       
   514                    BadPaddingException {
       
   515             return core.implDoFinal(in, inOff, inLen, out, outOff);
       
   516         }
       
   517         protected int engineGetBlockSize() {
       
   518             return core.implGetBlockSize();
       
   519         }
       
   520         protected byte[] engineGetIV() {
       
   521             return core.implGetIV();
       
   522         }
       
   523         protected int engineGetKeySize(Key key) throws InvalidKeyException {
       
   524             return core.implGetKeySize(key);
       
   525         }
       
   526         protected int engineGetOutputSize(int inLen) {
       
   527             return core.implGetOutputSize(inLen);
       
   528         }
       
   529         protected AlgorithmParameters engineGetParameters() {
       
   530             return core.implGetParameters();
       
   531         }
       
   532         protected void engineInit(int opmode, Key key,
       
   533                                   AlgorithmParameterSpec params,
       
   534                                   SecureRandom random)
       
   535             throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   536             core.implInit(opmode, key, params, random);
       
   537         }
       
   538         protected void engineInit(int opmode, Key key,
       
   539                                   AlgorithmParameters params,
       
   540                                   SecureRandom random)
       
   541             throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   542             core.implInit(opmode, key, params, random);
       
   543         }
       
   544         protected void engineInit(int opmode, Key key, SecureRandom random)
       
   545             throws InvalidKeyException {
       
   546             core.implInit(opmode, key, random);
       
   547         }
       
   548         protected void engineSetMode(String mode)
       
   549             throws NoSuchAlgorithmException {
       
   550             core.implSetMode(mode);
       
   551         }
       
   552         protected void engineSetPadding(String paddingScheme)
       
   553             throws NoSuchPaddingException {
       
   554             core.implSetPadding(paddingScheme);
       
   555         }
       
   556         protected Key engineUnwrap(byte[] wrappedKey,
       
   557                                    String wrappedKeyAlgorithm,
       
   558                                    int wrappedKeyType)
       
   559             throws InvalidKeyException, NoSuchAlgorithmException {
       
   560             return core.implUnwrap(wrappedKey, wrappedKeyAlgorithm,
       
   561                                    wrappedKeyType);
       
   562         }
       
   563         protected byte[] engineUpdate(byte[] in, int inOff, int inLen) {
       
   564             return core.implUpdate(in, inOff, inLen);
       
   565         }
       
   566         protected int engineUpdate(byte[] in, int inOff, int inLen,
       
   567                                    byte[] out, int outOff)
       
   568             throws ShortBufferException {
       
   569             return core.implUpdate(in, inOff, inLen, out, outOff);
       
   570         }
       
   571         protected byte[] engineWrap(Key key)
       
   572             throws IllegalBlockSizeException, InvalidKeyException {
       
   573             return core.implWrap(key);
       
   574         }
       
   575     }
       
   576 
       
   577     public static final class PBEWithSHA1AndRC2_128 extends CipherSpi {
       
   578         private final PKCS12PBECipherCore core;
       
   579         public PBEWithSHA1AndRC2_128() throws NoSuchAlgorithmException {
       
   580             core = new PKCS12PBECipherCore("RC2", 16);
       
   581         }
       
   582         protected byte[] engineDoFinal(byte[] in, int inOff, int inLen)
       
   583             throws IllegalBlockSizeException, BadPaddingException {
       
   584             return core.implDoFinal(in, inOff, inLen);
       
   585         }
       
   586         protected int engineDoFinal(byte[] in, int inOff, int inLen,
       
   587                                     byte[] out, int outOff)
       
   588             throws ShortBufferException, IllegalBlockSizeException,
       
   589                    BadPaddingException {
       
   590             return core.implDoFinal(in, inOff, inLen, out, outOff);
       
   591         }
       
   592         protected int engineGetBlockSize() {
       
   593             return core.implGetBlockSize();
       
   594         }
       
   595         protected byte[] engineGetIV() {
       
   596             return core.implGetIV();
       
   597         }
       
   598         protected int engineGetKeySize(Key key) throws InvalidKeyException {
       
   599             return core.implGetKeySize(key);
       
   600         }
       
   601         protected int engineGetOutputSize(int inLen) {
       
   602             return core.implGetOutputSize(inLen);
       
   603         }
       
   604         protected AlgorithmParameters engineGetParameters() {
       
   605             return core.implGetParameters();
       
   606         }
       
   607         protected void engineInit(int opmode, Key key,
       
   608                                   AlgorithmParameterSpec params,
       
   609                                   SecureRandom random)
       
   610             throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   611             core.implInit(opmode, key, params, random);
       
   612         }
       
   613         protected void engineInit(int opmode, Key key,
       
   614                                   AlgorithmParameters params,
       
   615                                   SecureRandom random)
       
   616             throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   617             core.implInit(opmode, key, params, random);
       
   618         }
       
   619         protected void engineInit(int opmode, Key key, SecureRandom random)
       
   620             throws InvalidKeyException {
       
   621             core.implInit(opmode, key, random);
       
   622         }
       
   623         protected void engineSetMode(String mode)
       
   624             throws NoSuchAlgorithmException {
       
   625             core.implSetMode(mode);
       
   626         }
       
   627         protected void engineSetPadding(String paddingScheme)
       
   628             throws NoSuchPaddingException {
       
   629             core.implSetPadding(paddingScheme);
       
   630         }
       
   631         protected Key engineUnwrap(byte[] wrappedKey,
       
   632                                    String wrappedKeyAlgorithm,
       
   633                                    int wrappedKeyType)
       
   634             throws InvalidKeyException, NoSuchAlgorithmException {
       
   635             return core.implUnwrap(wrappedKey, wrappedKeyAlgorithm,
       
   636                                    wrappedKeyType);
       
   637         }
       
   638         protected byte[] engineUpdate(byte[] in, int inOff, int inLen) {
       
   639             return core.implUpdate(in, inOff, inLen);
       
   640         }
       
   641         protected int engineUpdate(byte[] in, int inOff, int inLen,
       
   642                                    byte[] out, int outOff)
       
   643             throws ShortBufferException {
       
   644             return core.implUpdate(in, inOff, inLen, out, outOff);
       
   645         }
       
   646         protected byte[] engineWrap(Key key)
       
   647             throws IllegalBlockSizeException, InvalidKeyException {
       
   648             return core.implWrap(key);
       
   649         }
       
   650     }
       
   651 
       
   652     public static final class PBEWithSHA1AndRC4_40 extends CipherSpi {
       
   653         private static final int RC4_KEYSIZE = 5;
       
   654         private final PKCS12PBECipherCore core;
       
   655         private final ARCFOURCipher cipher;
       
   656 
       
   657         public PBEWithSHA1AndRC4_40() throws NoSuchAlgorithmException {
       
   658             core = new PKCS12PBECipherCore("RC4", RC4_KEYSIZE);
       
   659             cipher = new ARCFOURCipher();
       
   660         }
       
   661         protected byte[] engineDoFinal(byte[] in, int inOff, int inLen)
       
   662             throws IllegalBlockSizeException, BadPaddingException {
       
   663             return cipher.engineDoFinal(in, inOff, inLen);
       
   664         }
       
   665         protected int engineDoFinal(byte[] in, int inOff, int inLen,
       
   666                                     byte[] out, int outOff)
       
   667             throws ShortBufferException, IllegalBlockSizeException,
       
   668                    BadPaddingException {
       
   669             return cipher.engineDoFinal(in, inOff, inLen, out, outOff);
       
   670         }
       
   671         protected int engineGetBlockSize() {
       
   672             return cipher.engineGetBlockSize();
       
   673         }
       
   674         protected byte[] engineGetIV() {
       
   675             return cipher.engineGetIV();
       
   676         }
       
   677         protected int engineGetKeySize(Key key) throws InvalidKeyException {
       
   678             return RC4_KEYSIZE;
       
   679         }
       
   680         protected int engineGetOutputSize(int inLen) {
       
   681             return cipher.engineGetOutputSize(inLen);
       
   682         }
       
   683         protected AlgorithmParameters engineGetParameters() {
       
   684             return core.implGetParameters();
       
   685         }
       
   686         protected void engineInit(int opmode, Key key,
       
   687                                   AlgorithmParameterSpec params,
       
   688                                   SecureRandom random)
       
   689             throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   690             core.implInit(opmode, key, params, random, cipher);
       
   691         }
       
   692         protected void engineInit(int opmode, Key key,
       
   693                                   AlgorithmParameters params,
       
   694                                   SecureRandom random)
       
   695             throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   696             core.implInit(opmode, key, params, random, cipher);
       
   697         }
       
   698         protected void engineInit(int opmode, Key key, SecureRandom random)
       
   699             throws InvalidKeyException {
       
   700             core.implInit(opmode, key, random, cipher);
       
   701         }
       
   702         protected void engineSetMode(String mode)
       
   703             throws NoSuchAlgorithmException {
       
   704             if (mode.equalsIgnoreCase("ECB") == false) {
       
   705                 throw new NoSuchAlgorithmException("Unsupported mode " + mode);
       
   706             }
       
   707         }
       
   708         protected void engineSetPadding(String paddingScheme)
       
   709             throws NoSuchPaddingException {
       
   710             if (paddingScheme.equalsIgnoreCase("NoPadding") == false) {
       
   711                 throw new NoSuchPaddingException("Padding must be NoPadding");
       
   712             }
       
   713         }
       
   714         protected Key engineUnwrap(byte[] wrappedKey,
       
   715                                    String wrappedKeyAlgorithm,
       
   716                                    int wrappedKeyType)
       
   717             throws InvalidKeyException, NoSuchAlgorithmException {
       
   718             return cipher.engineUnwrap(wrappedKey, wrappedKeyAlgorithm,
       
   719                                    wrappedKeyType);
       
   720         }
       
   721         protected byte[] engineUpdate(byte[] in, int inOff, int inLen) {
       
   722             return cipher.engineUpdate(in, inOff, inLen);
       
   723         }
       
   724         protected int engineUpdate(byte[] in, int inOff, int inLen,
       
   725                                    byte[] out, int outOff)
       
   726             throws ShortBufferException {
       
   727             return cipher.engineUpdate(in, inOff, inLen, out, outOff);
       
   728         }
       
   729         protected byte[] engineWrap(Key key)
       
   730             throws IllegalBlockSizeException, InvalidKeyException {
       
   731             return cipher.engineWrap(key);
       
   732         }
       
   733     }
       
   734 
       
   735     public static final class PBEWithSHA1AndRC4_128 extends CipherSpi {
       
   736         private static final int RC4_KEYSIZE = 16;
       
   737         private final PKCS12PBECipherCore core;
       
   738         private final ARCFOURCipher cipher;
       
   739 
       
   740         public PBEWithSHA1AndRC4_128() throws NoSuchAlgorithmException {
       
   741             core = new PKCS12PBECipherCore("RC4", RC4_KEYSIZE);
       
   742             cipher = new ARCFOURCipher();
       
   743         }
       
   744         protected byte[] engineDoFinal(byte[] in, int inOff, int inLen)
       
   745             throws IllegalBlockSizeException, BadPaddingException {
       
   746             return cipher.engineDoFinal(in, inOff, inLen);
       
   747         }
       
   748         protected int engineDoFinal(byte[] in, int inOff, int inLen,
       
   749                                     byte[] out, int outOff)
       
   750             throws ShortBufferException, IllegalBlockSizeException,
       
   751                    BadPaddingException {
       
   752             return cipher.engineDoFinal(in, inOff, inLen, out, outOff);
       
   753         }
       
   754         protected int engineGetBlockSize() {
       
   755             return cipher.engineGetBlockSize();
       
   756         }
       
   757         protected byte[] engineGetIV() {
       
   758             return cipher.engineGetIV();
       
   759         }
       
   760         protected int engineGetKeySize(Key key) throws InvalidKeyException {
       
   761             return RC4_KEYSIZE;
       
   762         }
       
   763         protected int engineGetOutputSize(int inLen) {
       
   764             return cipher.engineGetOutputSize(inLen);
       
   765         }
       
   766         protected AlgorithmParameters engineGetParameters() {
       
   767             return core.implGetParameters();
       
   768         }
       
   769         protected void engineInit(int opmode, Key key,
       
   770                                   AlgorithmParameterSpec params,
       
   771                                   SecureRandom random)
       
   772             throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   773             core.implInit(opmode, key, params, random, cipher);
       
   774         }
       
   775         protected void engineInit(int opmode, Key key,
       
   776                                   AlgorithmParameters params,
       
   777                                   SecureRandom random)
       
   778             throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   779             core.implInit(opmode, key, params, random, cipher);
       
   780         }
       
   781         protected void engineInit(int opmode, Key key, SecureRandom random)
       
   782             throws InvalidKeyException {
       
   783             core.implInit(opmode, key, random, cipher);
       
   784         }
       
   785         protected void engineSetMode(String mode)
       
   786             throws NoSuchAlgorithmException {
       
   787             if (mode.equalsIgnoreCase("ECB") == false) {
       
   788                 throw new NoSuchAlgorithmException("Unsupported mode " + mode);
       
   789             }
       
   790         }
       
   791         protected void engineSetPadding(String paddingScheme)
       
   792             throws NoSuchPaddingException {
       
   793             if (paddingScheme.equalsIgnoreCase("NoPadding") == false) {
       
   794                 throw new NoSuchPaddingException("Padding must be NoPadding");
       
   795             }
       
   796         }
       
   797         protected Key engineUnwrap(byte[] wrappedKey,
       
   798                                    String wrappedKeyAlgorithm,
       
   799                                    int wrappedKeyType)
       
   800             throws InvalidKeyException, NoSuchAlgorithmException {
       
   801             return cipher.engineUnwrap(wrappedKey, wrappedKeyAlgorithm,
       
   802                                    wrappedKeyType);
       
   803         }
       
   804         protected byte[] engineUpdate(byte[] in, int inOff, int inLen) {
       
   805             return cipher.engineUpdate(in, inOff, inLen);
       
   806         }
       
   807         protected int engineUpdate(byte[] in, int inOff, int inLen,
       
   808                                    byte[] out, int outOff)
       
   809             throws ShortBufferException {
       
   810             return cipher.engineUpdate(in, inOff, inLen, out, outOff);
       
   811         }
       
   812         protected byte[] engineWrap(Key key)
       
   813             throws IllegalBlockSizeException, InvalidKeyException {
       
   814             return cipher.engineWrap(key);
       
   815         }
       
   816     }
       
   817 }