1 /*
   2  * Copyright (c) 2002, 2017, 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.security.*;
  29 import java.security.spec.*;
  30 import javax.crypto.*;
  31 import javax.crypto.spec.*;
  32 
  33 /**
  34  * This class represents password-based encryption as defined by the PKCS #5
  35  * standard.
  36  *
  37  * @author Jan Luehe
  38  *
  39  *
  40  * @see javax.crypto.Cipher
  41  */
  42 final class PBES1Core {
  43 
  44     // the encapsulated DES cipher
  45     private CipherCore cipher;
  46     private MessageDigest md;
  47     private int blkSize;
  48     private String algo = null;
  49     private byte[] salt = null;
  50     private int iCount = 10;
  51 
  52     /**
  53      * Creates an instance of PBE Cipher using the specified CipherSpi
  54      * instance.
  55      *
  56      */
  57     PBES1Core(String cipherAlg) throws NoSuchAlgorithmException,
  58         NoSuchPaddingException {
  59         algo = cipherAlg;
  60         if (algo.equals("DES")) {
  61             cipher = new CipherCore(new DESCrypt(),
  62                                     DESConstants.DES_BLOCK_SIZE);
  63         } else if (algo.equals("DESede")) {
  64 
  65             cipher = new CipherCore(new DESedeCrypt(),
  66                                     DESConstants.DES_BLOCK_SIZE);
  67         } else {
  68             throw new NoSuchAlgorithmException("No Cipher implementation " +
  69                                                "for PBEWithMD5And" + algo);
  70         }
  71         cipher.setMode("CBC");
  72         cipher.setPadding("PKCS5Padding");
  73         // get instance of MD5
  74         md = MessageDigest.getInstance("MD5");
  75     }
  76 
  77     /**
  78      * Sets the mode of this cipher. This algorithm can only be run in CBC
  79      * mode.
  80      *
  81      * @param mode the cipher mode
  82      *
  83      * @exception NoSuchAlgorithmException if the requested cipher mode is
  84      * invalid
  85      */
  86     void setMode(String mode) throws NoSuchAlgorithmException {
  87         cipher.setMode(mode);
  88     }
  89 
  90      /**
  91      * Sets the padding mechanism of this cipher. This algorithm only uses
  92      * PKCS #5 padding.
  93      *
  94      * @param padding the padding mechanism
  95      *
  96      * @exception NoSuchPaddingException if the requested padding mechanism
  97      * is invalid
  98      */
  99     void setPadding(String paddingScheme) throws NoSuchPaddingException {
 100         cipher.setPadding(paddingScheme);
 101     }
 102 
 103     /**
 104      * Returns the block size (in bytes).
 105      *
 106      * @return the block size (in bytes)
 107      */
 108     int getBlockSize() {
 109         return DESConstants.DES_BLOCK_SIZE;
 110     }
 111 
 112     /**
 113      * Returns the length in bytes that an output buffer would need to be in
 114      * order to hold the result of the next <code>update</code> or
 115      * <code>doFinal</code> operation, given the input length
 116      * <code>inputLen</code> (in bytes).
 117      *
 118      * <p>This call takes into account any unprocessed (buffered) data from a
 119      * previous <code>update</code> call, and padding.
 120      *
 121      * <p>The actual output length of the next <code>update</code> or
 122      * <code>doFinal</code> call may be smaller than the length returned by
 123      * this method.
 124      *
 125      * @param inputLen the input length (in bytes)
 126      *
 127      * @return the required output buffer size (in bytes)
 128      *
 129      */
 130     int getOutputSize(int inputLen) {
 131         return cipher.getOutputSize(inputLen);
 132     }
 133 
 134     /**
 135      * Returns the initialization vector (IV) in a new buffer.
 136      *
 137      * <p> This is useful in the case where a random IV has been created
 138      * (see <a href = "#init">init</a>),
 139      * or in the context of password-based encryption or
 140      * decryption, where the IV is derived from a user-supplied password.
 141      *
 142      * @return the initialization vector in a new buffer, or null if the
 143      * underlying algorithm does not use an IV, or if the IV has not yet
 144      * been set.
 145      */
 146     byte[] getIV() {
 147         return cipher.getIV();
 148     }
 149 
 150     /**
 151      * Returns the parameters used with this cipher.
 152      *
 153      * <p>The returned parameters may be the same that were used to initialize
 154      * this cipher, or may contain the default set of parameters or a set of
 155      * randomly generated parameters used by the underlying cipher
 156      * implementation (provided that the underlying cipher implementation
 157      * uses a default set of parameters or creates new parameters if it needs
 158      * parameters but was not initialized with any).
 159      *
 160      * @return the parameters used with this cipher, or null if this cipher
 161      * does not use any parameters.
 162      */
 163     AlgorithmParameters getParameters() {
 164         AlgorithmParameters params = null;
 165         if (salt == null) {
 166             salt = new byte[8];
 167             SunJCE.getRandom().nextBytes(salt);
 168         }
 169         PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, iCount);
 170         try {
 171             params = AlgorithmParameters.getInstance("PBEWithMD5And" +
 172                 (algo.equalsIgnoreCase("DES")? "DES":"TripleDES"),
 173                 SunJCE.getInstance());
 174             params.init(pbeSpec);
 175         } catch (NoSuchAlgorithmException nsae) {
 176             // should never happen
 177             throw new RuntimeException("SunJCE called, but not configured");
 178         } catch (InvalidParameterSpecException ipse) {
 179             // should never happen
 180             throw new RuntimeException("PBEParameterSpec not supported");
 181         }
 182         return params;
 183     }
 184 
 185     /**
 186      * Initializes this cipher with a key, a set of
 187      * algorithm parameters, and a source of randomness.
 188      * The cipher is initialized for one of the following four operations:
 189      * encryption, decryption, key wrapping or key unwrapping, depending on
 190      * the value of <code>opmode</code>.
 191      *
 192      * <p>If this cipher (including its underlying feedback or padding scheme)
 193      * requires any random bytes, it will get them from <code>random</code>.
 194      *
 195      * @param opmode the operation mode of this cipher (this is one of
 196      * the following:
 197      * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>),
 198      * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
 199      * @param key the encryption key
 200      * @param params the algorithm parameters
 201      * @param random the source of randomness
 202      *
 203      * @exception InvalidKeyException if the given key is inappropriate for
 204      * initializing this cipher
 205      * @exception InvalidAlgorithmParameterException if the given algorithm
 206      * parameters are inappropriate for this cipher
 207      */
 208     void init(int opmode, Key key, AlgorithmParameterSpec params,
 209               SecureRandom random)
 210         throws InvalidKeyException, InvalidAlgorithmParameterException {
 211         if (((opmode == Cipher.DECRYPT_MODE) ||
 212              (opmode == Cipher.UNWRAP_MODE)) && (params == null)) {
 213             throw new InvalidAlgorithmParameterException("Parameters "
 214                                                          + "missing");
 215         }
 216         if ((key == null) ||
 217             (key.getEncoded() == null) ||
 218             !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
 219             throw new InvalidKeyException("Missing password");
 220         }
 221 
 222         if (params == null) {
 223             // create random salt and use default iteration count
 224             salt = new byte[8];
 225             random.nextBytes(salt);
 226         } else {
 227             if (!(params instanceof PBEParameterSpec)) {
 228                 throw new InvalidAlgorithmParameterException
 229                     ("Wrong parameter type: PBE expected");
 230             }
 231             salt = ((PBEParameterSpec) params).getSalt();
 232             // salt must be 8 bytes long (by definition)
 233             if (salt.length != 8) {
 234                 throw new InvalidAlgorithmParameterException
 235                     ("Salt must be 8 bytes long");
 236             }
 237             iCount = ((PBEParameterSpec) params).getIterationCount();
 238             if (iCount <= 0) {
 239                 throw new InvalidAlgorithmParameterException
 240                     ("IterationCount must be a positive number");
 241             }
 242         }
 243 
 244         byte[] derivedKey = deriveCipherKey(key);
 245         // use all but the last 8 bytes as the key value
 246         SecretKeySpec cipherKey = new SecretKeySpec(derivedKey, 0,
 247                                                     derivedKey.length-8, algo);
 248         // use the last 8 bytes as the IV
 249         IvParameterSpec ivSpec = new IvParameterSpec(derivedKey,
 250                                                      derivedKey.length-8,
 251                                                      8);
 252         // initialize the underlying cipher
 253         cipher.init(opmode, cipherKey, ivSpec, random);
 254     }
 255 
 256     private byte[] deriveCipherKey(Key key) {
 257 
 258         byte[] result = null;
 259         byte[] passwdBytes = key.getEncoded();
 260 
 261         if (algo.equals("DES")) {
 262             // P || S (password concatenated with salt)
 263             byte[] concat = new byte[Math.addExact(passwdBytes.length, salt.length)];
 264             System.arraycopy(passwdBytes, 0, concat, 0, passwdBytes.length);
 265             java.util.Arrays.fill(passwdBytes, (byte)0x00);
 266             System.arraycopy(salt, 0, concat, passwdBytes.length, salt.length);
 267 
 268             // digest P || S with c iterations
 269             byte[] toBeHashed = concat;
 270             for (int i = 0; i < iCount; i++) {
 271                 md.update(toBeHashed);
 272                 toBeHashed = md.digest(); // this resets the digest
 273             }
 274             java.util.Arrays.fill(concat, (byte)0x00);
 275             result = toBeHashed;
 276         } else if (algo.equals("DESede")) {
 277             // if the 2 salt halves are the same, invert one of them
 278             int i;
 279             for (i=0; i<4; i++) {
 280                 if (salt[i] != salt[i+4])
 281                     break;
 282             }
 283             if (i==4) { // same, invert 1st half
 284                 for (i=0; i<2; i++) {
 285                     byte tmp = salt[i];
 286                     salt[i] = salt[3-i];
 287                     salt[3-i] = tmp;
 288                 }
 289             }
 290 
 291             // Now digest each half (concatenated with password). For each
 292             // half, go through the loop as many times as specified by the
 293             // iteration count parameter (inner for loop).
 294             // Concatenate the output from each digest round with the
 295             // password, and use the result as the input to the next digest
 296             // operation.
 297             byte[] kBytes = null;
 298             IvParameterSpec iv = null;
 299             byte[] toBeHashed = null;
 300             result = new byte[DESedeKeySpec.DES_EDE_KEY_LEN +
 301                               DESConstants.DES_BLOCK_SIZE];
 302             for (i = 0; i < 2; i++) {
 303                 toBeHashed = new byte[salt.length/2];
 304                 System.arraycopy(salt, i*(salt.length/2), toBeHashed, 0,
 305                                  toBeHashed.length);
 306                 for (int j=0; j < iCount; j++) {
 307                     md.update(toBeHashed);
 308                     md.update(passwdBytes);
 309                     toBeHashed = md.digest(); // this resets the digest
 310                 }
 311                 System.arraycopy(toBeHashed, 0, result, i*16,
 312                                  toBeHashed.length);
 313             }
 314         }
 315         return result;
 316     }
 317 
 318     void init(int opmode, Key key, AlgorithmParameters params,
 319               SecureRandom random)
 320         throws InvalidKeyException, InvalidAlgorithmParameterException {
 321         PBEParameterSpec pbeSpec = null;
 322         if (params != null) {
 323             try {
 324                 pbeSpec = params.getParameterSpec(PBEParameterSpec.class);
 325             } catch (InvalidParameterSpecException ipse) {
 326                 throw new InvalidAlgorithmParameterException("Wrong parameter "
 327                                                              + "type: PBE "
 328                                                              + "expected");
 329             }
 330         }
 331         init(opmode, key, pbeSpec, random);
 332     }
 333 
 334     /**
 335      * Continues a multiple-part encryption or decryption operation
 336      * (depending on how this cipher was initialized), processing another data
 337      * part.
 338      *
 339      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
 340      * buffer, starting at <code>inputOffset</code>, are processed, and the
 341      * result is stored in a new buffer.
 342      *
 343      * @param input the input buffer
 344      * @param inputOffset the offset in <code>input</code> where the input
 345      * starts
 346      * @param inputLen the input length
 347      *
 348      * @return the new buffer with the result
 349      *
 350      */
 351     byte[] update(byte[] input, int inputOffset, int inputLen) {
 352         return cipher.update(input, inputOffset, inputLen);
 353     }
 354 
 355     /**
 356      * Continues a multiple-part encryption or decryption operation
 357      * (depending on how this cipher was initialized), processing another data
 358      * part.
 359      *
 360      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
 361      * buffer, starting at <code>inputOffset</code>, are processed, and the
 362      * result is stored in the <code>output</code> buffer, starting at
 363      * <code>outputOffset</code>.
 364      *
 365      * @param input the input buffer
 366      * @param inputOffset the offset in <code>input</code> where the input
 367      * starts
 368      * @param inputLen the input length
 369      * @param output the buffer for the result
 370      * @param outputOffset the offset in <code>output</code> where the result
 371      * is stored
 372      *
 373      * @return the number of bytes stored in <code>output</code>
 374      *
 375      * @exception ShortBufferException if the given output buffer is too small
 376      * to hold the result
 377      */
 378     int update(byte[] input, int inputOffset, int inputLen,
 379                byte[] output, int outputOffset)
 380         throws ShortBufferException {
 381         return cipher.update(input, inputOffset, inputLen,
 382                              output, outputOffset);
 383     }
 384 
 385     /**
 386      * Encrypts or decrypts data in a single-part operation,
 387      * or finishes a multiple-part operation.
 388      * The data is encrypted or decrypted, depending on how this cipher was
 389      * initialized.
 390      *
 391      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
 392      * buffer, starting at <code>inputOffset</code>, and any input bytes that
 393      * may have been buffered during a previous <code>update</code> operation,
 394      * are processed, with padding (if requested) being applied.
 395      * The result is stored in a new buffer.
 396      *
 397      * <p>The cipher is reset to its initial state (uninitialized) after this
 398      * call.
 399      *
 400      * @param input the input buffer
 401      * @param inputOffset the offset in <code>input</code> where the input
 402      * starts
 403      * @param inputLen the input length
 404      *
 405      * @return the new buffer with the result
 406      *
 407      * @exception IllegalBlockSizeException if this cipher is a block cipher,
 408      * no padding has been requested (only in encryption mode), and the total
 409      * input length of the data processed by this cipher is not a multiple of
 410      * block size
 411      * @exception BadPaddingException if decrypting and padding is chosen,
 412      * but the last input data does not have proper padding bytes.
 413      */
 414     byte[] doFinal(byte[] input, int inputOffset, int inputLen)
 415         throws IllegalBlockSizeException, BadPaddingException {
 416         return cipher.doFinal(input, inputOffset, inputLen);
 417     }
 418 
 419     /**
 420      * Encrypts or decrypts data in a single-part operation,
 421      * or finishes a multiple-part operation.
 422      * The data is encrypted or decrypted, depending on how this cipher was
 423      * initialized.
 424      *
 425      * <p>The first <code>inputLen</code> bytes in the <code>input</code>
 426      * buffer, starting at <code>inputOffset</code>, and any input bytes that
 427      * may have been buffered during a previous <code>update</code> operation,
 428      * are processed, with padding (if requested) being applied.
 429      * The result is stored in the <code>output</code> buffer, starting at
 430      * <code>outputOffset</code>.
 431      *
 432      * <p>The cipher is reset to its initial state (uninitialized) after this
 433      * call.
 434      *
 435      * @param input the input buffer
 436      * @param inputOffset the offset in <code>input</code> where the input
 437      * starts
 438      * @param inputLen the input length
 439      * @param output the buffer for the result
 440      * @param outputOffset the offset in <code>output</code> where the result
 441      * is stored
 442      *
 443      * @return the number of bytes stored in <code>output</code>
 444      *
 445      * @exception IllegalBlockSizeException if this cipher is a block cipher,
 446      * no padding has been requested (only in encryption mode), and the total
 447      * input length of the data processed by this cipher is not a multiple of
 448      * block size
 449      * @exception ShortBufferException if the given output buffer is too small
 450      * to hold the result
 451      * @exception BadPaddingException if decrypting and padding is chosen,
 452      * but the last input data does not have proper padding bytes.
 453      */
 454     int doFinal(byte[] input, int inputOffset, int inputLen,
 455                 byte[] output, int outputOffset)
 456         throws ShortBufferException, IllegalBlockSizeException,
 457                BadPaddingException {
 458         return cipher.doFinal(input, inputOffset, inputLen,
 459                                     output, outputOffset);
 460     }
 461 
 462     /**
 463      * Wrap a key.
 464      *
 465      * @param key the key to be wrapped.
 466      *
 467      * @return the wrapped key.
 468      *
 469      * @exception IllegalBlockSizeException if this cipher is a block
 470      * cipher, no padding has been requested, and the length of the
 471      * encoding of the key to be wrapped is not a
 472      * multiple of the block size.
 473      *
 474      * @exception InvalidKeyException if it is impossible or unsafe to
 475      * wrap the key with this cipher (e.g., a hardware protected key is
 476      * being passed to a software only cipher).
 477      */
 478     byte[] wrap(Key key)
 479         throws IllegalBlockSizeException, InvalidKeyException {
 480         byte[] result = null;
 481 
 482         try {
 483             byte[] encodedKey = key.getEncoded();
 484             if ((encodedKey == null) || (encodedKey.length == 0)) {
 485                 throw new InvalidKeyException("Cannot get an encoding of " +
 486                                               "the key to be wrapped");
 487             }
 488 
 489             result = doFinal(encodedKey, 0, encodedKey.length);
 490         } catch (BadPaddingException e) {
 491             // Should never happen
 492         }
 493 
 494         return result;
 495     }
 496 
 497     /**
 498      * Unwrap a previously wrapped key.
 499      *
 500      * @param wrappedKey the key to be unwrapped.
 501      *
 502      * @param wrappedKeyAlgorithm the algorithm the wrapped key is for.
 503      *
 504      * @param wrappedKeyType the type of the wrapped key.
 505      * This is one of <code>Cipher.SECRET_KEY</code>,
 506      * <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.
 507      *
 508      * @return the unwrapped key.
 509      *
 510      * @exception NoSuchAlgorithmException if no installed providers
 511      * can create keys of type <code>wrappedKeyType</code> for the
 512      * <code>wrappedKeyAlgorithm</code>.
 513      *
 514      * @exception InvalidKeyException if <code>wrappedKey</code> does not
 515      * represent a wrapped key of type <code>wrappedKeyType</code> for
 516      * the <code>wrappedKeyAlgorithm</code>.
 517      */
 518     Key unwrap(byte[] wrappedKey,
 519                String wrappedKeyAlgorithm,
 520                int wrappedKeyType)
 521         throws InvalidKeyException, NoSuchAlgorithmException {
 522         byte[] encodedKey;
 523         try {
 524             encodedKey = doFinal(wrappedKey, 0, wrappedKey.length);
 525         } catch (BadPaddingException ePadding) {
 526             throw new InvalidKeyException("The wrapped key is not padded " +
 527                                           "correctly");
 528         } catch (IllegalBlockSizeException eBlockSize) {
 529             throw new InvalidKeyException("The wrapped key does not have " +
 530                                           "the correct length");
 531         }
 532         return ConstructKeys.constructKey(encodedKey, wrappedKeyAlgorithm,
 533                                           wrappedKeyType);
 534     }
 535 }