src/java.base/share/classes/com/sun/crypto/provider/HmacPKCS12PBECore.java
changeset 52996 2457d862a646
parent 51504 c9a3e3cac9c7
equal deleted inserted replaced
52995:9af672cab7cb 52996:2457d862a646
       
     1 /*
       
     2  * Copyright (c) 2003, 2018, 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.util.Arrays;
       
    29 
       
    30 import javax.crypto.SecretKey;
       
    31 import javax.crypto.spec.SecretKeySpec;
       
    32 import javax.crypto.spec.PBEParameterSpec;
       
    33 import java.security.*;
       
    34 import java.security.spec.*;
       
    35 
       
    36 /**
       
    37  * This is an implementation of the HMAC algorithms as defined
       
    38  * in PKCS#12 v1.1 standard (see RFC 7292 Appendix B.4).
       
    39  *
       
    40  * @author Valerie Peng
       
    41  */
       
    42 abstract class HmacPKCS12PBECore extends HmacCore {
       
    43 
       
    44     public static final class HmacPKCS12PBE_SHA1 extends HmacPKCS12PBECore {
       
    45         public HmacPKCS12PBE_SHA1() throws NoSuchAlgorithmException {
       
    46             super("SHA1", 64);
       
    47         }
       
    48     }
       
    49 
       
    50     public static final class HmacPKCS12PBE_SHA224 extends HmacPKCS12PBECore {
       
    51         public HmacPKCS12PBE_SHA224() throws NoSuchAlgorithmException {
       
    52             super("SHA-224", 64);
       
    53         }
       
    54     }
       
    55 
       
    56     public static final class HmacPKCS12PBE_SHA256 extends HmacPKCS12PBECore {
       
    57         public HmacPKCS12PBE_SHA256() throws NoSuchAlgorithmException {
       
    58             super("SHA-256", 64);
       
    59         }
       
    60     }
       
    61 
       
    62     public static final class HmacPKCS12PBE_SHA384 extends HmacPKCS12PBECore {
       
    63         public HmacPKCS12PBE_SHA384() throws NoSuchAlgorithmException {
       
    64             super("SHA-384", 128);
       
    65         }
       
    66     }
       
    67 
       
    68     public static final class HmacPKCS12PBE_SHA512 extends HmacPKCS12PBECore {
       
    69         public HmacPKCS12PBE_SHA512() throws NoSuchAlgorithmException {
       
    70             super("SHA-512", 128);
       
    71         }
       
    72     }
       
    73 
       
    74     public static final class HmacPKCS12PBE_SHA512_224 extends HmacPKCS12PBECore {
       
    75         public HmacPKCS12PBE_SHA512_224() throws NoSuchAlgorithmException {
       
    76             super("SHA-512/224", 128);
       
    77         }
       
    78     }
       
    79 
       
    80     public static final class HmacPKCS12PBE_SHA512_256 extends HmacPKCS12PBECore {
       
    81         public HmacPKCS12PBE_SHA512_256() throws NoSuchAlgorithmException {
       
    82             super("SHA-512/256", 128);
       
    83         }
       
    84     }
       
    85 
       
    86     private final String algorithm;
       
    87     private final int bl;
       
    88 
       
    89     /**
       
    90      * Standard constructor, creates a new HmacSHA1 instance.
       
    91      */
       
    92     public HmacPKCS12PBECore(String algorithm, int bl) throws NoSuchAlgorithmException {
       
    93         super(algorithm, bl);
       
    94         this.algorithm = algorithm;
       
    95         this.bl = bl;
       
    96     }
       
    97 
       
    98     /**
       
    99      * Initializes the HMAC with the given secret key and algorithm parameters.
       
   100      *
       
   101      * @param key the secret key.
       
   102      * @param params the algorithm parameters.
       
   103      *
       
   104      * @exception InvalidKeyException if the given key is inappropriate for
       
   105      * initializing this MAC.
       
   106      * @exception InvalidAlgorithmParameterException if the given algorithm
       
   107      * parameters are inappropriate for this MAC.
       
   108      */
       
   109     protected void engineInit(Key key, AlgorithmParameterSpec params)
       
   110         throws InvalidKeyException, InvalidAlgorithmParameterException {
       
   111         char[] passwdChars;
       
   112         byte[] salt = null;
       
   113         int iCount = 0;
       
   114         if (key instanceof javax.crypto.interfaces.PBEKey) {
       
   115             javax.crypto.interfaces.PBEKey pbeKey =
       
   116                 (javax.crypto.interfaces.PBEKey) key;
       
   117             passwdChars = pbeKey.getPassword();
       
   118             salt = pbeKey.getSalt(); // maybe null if unspecified
       
   119             iCount = pbeKey.getIterationCount(); // maybe 0 if unspecified
       
   120         } else if (key instanceof SecretKey) {
       
   121             byte[] passwdBytes;
       
   122             if (!(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3)) ||
       
   123                     (passwdBytes = key.getEncoded()) == null) {
       
   124                 throw new InvalidKeyException("Missing password");
       
   125             }
       
   126             passwdChars = new char[passwdBytes.length];
       
   127             for (int i=0; i<passwdChars.length; i++) {
       
   128                 passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
       
   129             }
       
   130             Arrays.fill(passwdBytes, (byte)0x00);
       
   131         } else {
       
   132             throw new InvalidKeyException("SecretKey of PBE type required");
       
   133         }
       
   134 
       
   135         byte[] derivedKey;
       
   136         try {
       
   137             if (params == null) {
       
   138                 // should not auto-generate default values since current
       
   139                 // javax.crypto.Mac api does not have any method for caller to
       
   140                 // retrieve the generated defaults.
       
   141                 if ((salt == null) || (iCount == 0)) {
       
   142                     throw new InvalidAlgorithmParameterException
       
   143                             ("PBEParameterSpec required for salt and iteration count");
       
   144                 }
       
   145             } else if (!(params instanceof PBEParameterSpec)) {
       
   146                 throw new InvalidAlgorithmParameterException
       
   147                         ("PBEParameterSpec type required");
       
   148             } else {
       
   149                 PBEParameterSpec pbeParams = (PBEParameterSpec) params;
       
   150                 // make sure the parameter values are consistent
       
   151                 if (salt != null) {
       
   152                     if (!Arrays.equals(salt, pbeParams.getSalt())) {
       
   153                         throw new InvalidAlgorithmParameterException
       
   154                                 ("Inconsistent value of salt between key and params");
       
   155                     }
       
   156                 } else {
       
   157                     salt = pbeParams.getSalt();
       
   158                 }
       
   159                 if (iCount != 0) {
       
   160                     if (iCount != pbeParams.getIterationCount()) {
       
   161                         throw new InvalidAlgorithmParameterException
       
   162                                 ("Different iteration count between key and params");
       
   163                     }
       
   164                 } else {
       
   165                     iCount = pbeParams.getIterationCount();
       
   166                 }
       
   167             }
       
   168             // For security purpose, we need to enforce a minimum length
       
   169             // for salt; just require the minimum salt length to be 8-byte
       
   170             // which is what PKCS#5 recommends and openssl does.
       
   171             if (salt.length < 8) {
       
   172                 throw new InvalidAlgorithmParameterException
       
   173                         ("Salt must be at least 8 bytes long");
       
   174             }
       
   175             if (iCount <= 0) {
       
   176                 throw new InvalidAlgorithmParameterException
       
   177                         ("IterationCount must be a positive number");
       
   178             }
       
   179             derivedKey = PKCS12PBECipherCore.derive(passwdChars, salt,
       
   180                     iCount, engineGetMacLength(), PKCS12PBECipherCore.MAC_KEY,
       
   181                     algorithm, bl);
       
   182         } finally {
       
   183             Arrays.fill(passwdChars, '\0');
       
   184         }
       
   185         SecretKey cipherKey = new SecretKeySpec(derivedKey, "HmacSHA1");
       
   186         super.engineInit(cipherKey, null);
       
   187     }
       
   188 }