src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java
changeset 47417 5984d1c9d03d
parent 47216 71c04702a3d5
child 50778 bba1deda9216
equal deleted inserted replaced
47416:a627f88bed3a 47417:5984d1c9d03d
    44 import java.security.cert.Certificate;
    44 import java.security.cert.Certificate;
    45 import java.security.cert.CertificateFactory;
    45 import java.security.cert.CertificateFactory;
    46 import java.security.cert.X509Certificate;
    46 import java.security.cert.X509Certificate;
    47 import java.security.cert.CertificateException;
    47 import java.security.cert.CertificateException;
    48 import java.security.spec.AlgorithmParameterSpec;
    48 import java.security.spec.AlgorithmParameterSpec;
       
    49 import java.security.spec.InvalidParameterSpecException;
    49 import java.security.spec.KeySpec;
    50 import java.security.spec.KeySpec;
    50 import java.security.spec.PKCS8EncodedKeySpec;
    51 import java.security.spec.PKCS8EncodedKeySpec;
    51 import java.util.*;
    52 import java.util.*;
    52 
    53 
    53 import java.security.AlgorithmParameters;
    54 import java.security.AlgorithmParameters;
   145     private static final String[] KEY_PROTECTION_ALGORITHM = {
   146     private static final String[] KEY_PROTECTION_ALGORITHM = {
   146         "keystore.pkcs12.keyProtectionAlgorithm",
   147         "keystore.pkcs12.keyProtectionAlgorithm",
   147         "keystore.PKCS12.keyProtectionAlgorithm"
   148         "keystore.PKCS12.keyProtectionAlgorithm"
   148     };
   149     };
   149 
   150 
       
   151     private static final int MAX_ITERATION_COUNT = 5000000;
       
   152     private static final int PBE_ITERATION_COUNT = 50000; // default
       
   153     private static final int MAC_ITERATION_COUNT = 100000; // default
       
   154     private static final int SALT_LEN = 20;
       
   155 
   150     // friendlyName, localKeyId, trustedKeyUsage
   156     // friendlyName, localKeyId, trustedKeyUsage
   151     private static final String[] CORE_ATTRIBUTES = {
   157     private static final String[] CORE_ATTRIBUTES = {
   152         "1.2.840.113549.1.9.20",
   158         "1.2.840.113549.1.9.20",
   153         "1.2.840.113549.1.9.21",
   159         "1.2.840.113549.1.9.21",
   154         "2.16.840.1.113894.746875.1.1"
   160         "2.16.840.1.113894.746875.1.1"
   190     private static ObjectIdentifier pbes2_OID;
   196     private static ObjectIdentifier pbes2_OID;
   191     private static ObjectIdentifier TrustedKeyUsage_OID;
   197     private static ObjectIdentifier TrustedKeyUsage_OID;
   192     private static ObjectIdentifier[] AnyUsage;
   198     private static ObjectIdentifier[] AnyUsage;
   193 
   199 
   194     private int counter = 0;
   200     private int counter = 0;
   195     private static final int iterationCount = 1024;
       
   196     private static final int SALT_LEN = 20;
       
   197 
   201 
   198     // private key count
   202     // private key count
   199     // Note: This is a workaround to allow null localKeyID attribute
   203     // Note: This is a workaround to allow null localKeyID attribute
   200     // in pkcs12 with one private key entry and associated cert-chain
   204     // in pkcs12 with one private key entry and associated cert-chain
   201     private int privateKeyCount = 0;
   205     private int privateKeyCount = 0;
   325         }
   329         }
   326 
   330 
   327         byte[] encryptedKey;
   331         byte[] encryptedKey;
   328         AlgorithmParameters algParams;
   332         AlgorithmParameters algParams;
   329         ObjectIdentifier algOid;
   333         ObjectIdentifier algOid;
       
   334 
   330         try {
   335         try {
   331             // get the encrypted private key
   336             // get the encrypted private key
   332             EncryptedPrivateKeyInfo encrInfo =
   337             EncryptedPrivateKeyInfo encrInfo =
   333                         new EncryptedPrivateKeyInfo(encrBytes);
   338                         new EncryptedPrivateKeyInfo(encrBytes);
   334             encryptedKey = encrInfo.getEncryptedData();
   339             encryptedKey = encrInfo.getEncryptedData();
   345                                  + "PKCS#8 EncryptedPrivateKeyInfo: " + ioe);
   350                                  + "PKCS#8 EncryptedPrivateKeyInfo: " + ioe);
   346             uke.initCause(ioe);
   351             uke.initCause(ioe);
   347             throw uke;
   352             throw uke;
   348         }
   353         }
   349 
   354 
   350         try {
   355        try {
       
   356             PBEParameterSpec pbeSpec;
       
   357             int ic = 0;
       
   358 
       
   359             if (algParams != null) {
       
   360                 try {
       
   361                     pbeSpec =
       
   362                         algParams.getParameterSpec(PBEParameterSpec.class);
       
   363                 } catch (InvalidParameterSpecException ipse) {
       
   364                     throw new IOException("Invalid PBE algorithm parameters");
       
   365                 }
       
   366                 ic = pbeSpec.getIterationCount();
       
   367 
       
   368                 if (ic > MAX_ITERATION_COUNT) {
       
   369                     throw new IOException("PBE iteration count too large");
       
   370                 }
       
   371             }
       
   372 
   351             byte[] keyInfo;
   373             byte[] keyInfo;
   352             while (true) {
   374             while (true) {
   353                 try {
   375                 try {
   354                     // Use JCE
   376                     // Use JCE
   355                     SecretKey skey = getPBEKey(password);
   377                     SecretKey skey = getPBEKey(password);
   385                 KeyFactory kfac = KeyFactory.getInstance(keyAlgo);
   407                 KeyFactory kfac = KeyFactory.getInstance(keyAlgo);
   386                 PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(keyInfo);
   408                 PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(keyInfo);
   387                 key = kfac.generatePrivate(kspec);
   409                 key = kfac.generatePrivate(kspec);
   388 
   410 
   389                 if (debug != null) {
   411                 if (debug != null) {
   390                     debug.println("Retrieved a protected private key (" +
   412                     debug.println("Retrieved a protected private key at alias" +
   391                         key.getClass().getName() + ") at alias '" + alias +
   413                         " '" + alias + "' (" +
   392                         "'");
   414                         new AlgorithmId(algOid).getName() +
       
   415                         " iterations: " + ic + ")");
   393                 }
   416                 }
   394 
   417 
   395             // decode secret key
   418             // decode secret key
   396             } else {
   419             } else {
   397                 byte[] keyBytes = in.getOctetString();
   420                 byte[] keyBytes = in.getOctetString();
   408                 } else {
   431                 } else {
   409                     key = secretKeySpec;
   432                     key = secretKeySpec;
   410                 }
   433                 }
   411 
   434 
   412                 if (debug != null) {
   435                 if (debug != null) {
   413                     debug.println("Retrieved a protected secret key (" +
   436                     debug.println("Retrieved a protected secret key at alias " +
   414                         key.getClass().getName() + ") at alias '" + alias +
   437                         "'" + alias + "' (" +
   415                         "'");
   438                         new AlgorithmId(algOid).getName() +
       
   439                         " iterations: " + ic + ")");
   416                 }
   440                 }
   417             }
   441             }
   418         } catch (Exception e) {
   442         } catch (Exception e) {
   419             UnrecoverableKeyException uke =
   443             UnrecoverableKeyException uke =
   420                 new UnrecoverableKeyException("Get Key failed: " +
   444                 new UnrecoverableKeyException("Get Key failed: " +
   588 
   612 
   589                 if ((key.getFormat().equals("PKCS#8")) ||
   613                 if ((key.getFormat().equals("PKCS#8")) ||
   590                     (key.getFormat().equals("PKCS8"))) {
   614                     (key.getFormat().equals("PKCS8"))) {
   591 
   615 
   592                     if (debug != null) {
   616                     if (debug != null) {
   593                         debug.println("Setting a protected private key (" +
   617                         debug.println(
   594                             key.getClass().getName() + ") at alias '" + alias +
   618                             "Setting a protected private key at alias '" +
   595                             "'");
   619                             alias + "'");
   596                         }
   620                         }
   597 
   621 
   598                     // Encrypt the private key
   622                     // Encrypt the private key
   599                     keyEntry.protectedPrivKey =
   623                     keyEntry.protectedPrivKey =
   600                         encryptPrivateKey(key.getEncoded(), passwordProtection);
   624                         encryptPrivateKey(key.getEncoded(), passwordProtection);
   636                 // Encrypt the secret key (using same PBE as for private keys)
   660                 // Encrypt the secret key (using same PBE as for private keys)
   637                 keyEntry.protectedSecretKey =
   661                 keyEntry.protectedSecretKey =
   638                     encryptPrivateKey(pkcs8.toByteArray(), passwordProtection);
   662                     encryptPrivateKey(pkcs8.toByteArray(), passwordProtection);
   639 
   663 
   640                 if (debug != null) {
   664                 if (debug != null) {
   641                     debug.println("Setting a protected secret key (" +
   665                     debug.println("Setting a protected secret key at alias '" +
   642                         key.getClass().getName() + ") at alias '" + alias +
   666                         alias + "'");
   643                         "'");
       
   644                 }
   667                 }
   645                 secretKeyCount++;
   668                 secretKeyCount++;
   646                 entry = keyEntry;
   669                 entry = keyEntry;
   647 
   670 
   648             } else {
   671             } else {
   759     }
   782     }
   760 
   783 
   761     /*
   784     /*
   762      * Generate PBE Algorithm Parameters
   785      * Generate PBE Algorithm Parameters
   763      */
   786      */
   764     private AlgorithmParameters getAlgorithmParameters(String algorithm)
   787     private AlgorithmParameters getPBEAlgorithmParameters(String algorithm)
   765         throws IOException
   788         throws IOException
   766     {
   789     {
   767         AlgorithmParameters algParams = null;
   790         AlgorithmParameters algParams = null;
   768 
   791 
   769         // create PBE parameters from salt and iteration count
   792         // create PBE parameters from salt and iteration count
   770         PBEParameterSpec paramSpec =
   793         PBEParameterSpec paramSpec =
   771                 new PBEParameterSpec(getSalt(), iterationCount);
   794                 new PBEParameterSpec(getSalt(), PBE_ITERATION_COUNT);
   772         try {
   795         try {
   773            algParams = AlgorithmParameters.getInstance(algorithm);
   796            algParams = AlgorithmParameters.getInstance(algorithm);
   774            algParams.init(paramSpec);
   797            algParams.init(paramSpec);
   775         } catch (Exception e) {
   798         } catch (Exception e) {
   776            throw new IOException("getAlgorithmParameters failed: " +
   799            throw new IOException("getPBEAlgorithmParameters failed: " +
   777                                  e.getMessage(), e);
   800                                  e.getMessage(), e);
   778         }
   801         }
   779         return algParams;
   802         return algParams;
   780     }
   803     }
   781 
   804 
   857                     passwordProtection.getProtectionParameters();
   880                     passwordProtection.getProtectionParameters();
   858                 if (algParamSpec != null) {
   881                 if (algParamSpec != null) {
   859                     algParams = AlgorithmParameters.getInstance(algorithm);
   882                     algParams = AlgorithmParameters.getInstance(algorithm);
   860                     algParams.init(algParamSpec);
   883                     algParams.init(algParamSpec);
   861                 } else {
   884                 } else {
   862                     algParams = getAlgorithmParameters(algorithm);
   885                     algParams = getPBEAlgorithmParameters(algorithm);
   863                 }
   886                 }
   864             } else {
   887             } else {
   865                 // Check default key protection algorithm for PKCS12 keystores
   888                 // Check default key protection algorithm for PKCS12 keystores
   866                 algorithm = AccessController.doPrivileged(
   889                 algorithm = AccessController.doPrivileged(
   867                     new PrivilegedAction<String>() {
   890                     new PrivilegedAction<String>() {
   877                         }
   900                         }
   878                     });
   901                     });
   879                 if (algorithm == null || algorithm.isEmpty()) {
   902                 if (algorithm == null || algorithm.isEmpty()) {
   880                     algorithm = "PBEWithSHA1AndDESede";
   903                     algorithm = "PBEWithSHA1AndDESede";
   881                 }
   904                 }
   882                 algParams = getAlgorithmParameters(algorithm);
   905                 algParams = getPBEAlgorithmParameters(algorithm);
   883             }
   906             }
   884 
   907 
   885             ObjectIdentifier pbeOID = mapPBEAlgorithmToOID(algorithm);
   908             ObjectIdentifier pbeOID = mapPBEAlgorithmToOID(algorithm);
   886             if (pbeOID == null) {
   909             if (pbeOID == null) {
   887                     throw new IOException("PBE algorithm '" + algorithm +
   910                     throw new IOException("PBE algorithm '" + algorithm +
  1192         // -- create safeContent Data ContentInfo
  1215         // -- create safeContent Data ContentInfo
  1193         if (privateKeyCount > 0 || secretKeyCount > 0) {
  1216         if (privateKeyCount > 0 || secretKeyCount > 0) {
  1194 
  1217 
  1195             if (debug != null) {
  1218             if (debug != null) {
  1196                 debug.println("Storing " + (privateKeyCount + secretKeyCount) +
  1219                 debug.println("Storing " + (privateKeyCount + secretKeyCount) +
  1197                     " protected key(s) in a PKCS#7 data content-type");
  1220                     " protected key(s) in a PKCS#7 data");
  1198             }
  1221             }
  1199 
  1222 
  1200             byte[] safeContentData = createSafeContent();
  1223             byte[] safeContentData = createSafeContent();
  1201             ContentInfo dataContentInfo = new ContentInfo(safeContentData);
  1224             ContentInfo dataContentInfo = new ContentInfo(safeContentData);
  1202             dataContentInfo.encode(authSafeContentInfo);
  1225             dataContentInfo.encode(authSafeContentInfo);
  1205         // -- create EncryptedContentInfo
  1228         // -- create EncryptedContentInfo
  1206         if (certificateCount > 0) {
  1229         if (certificateCount > 0) {
  1207 
  1230 
  1208             if (debug != null) {
  1231             if (debug != null) {
  1209                 debug.println("Storing " + certificateCount +
  1232                 debug.println("Storing " + certificateCount +
  1210                     " certificate(s) in a PKCS#7 encryptedData content-type");
  1233                     " certificate(s) in a PKCS#7 encryptedData");
  1211             }
  1234             }
  1212 
  1235 
  1213             byte[] encrData = createEncryptedData(password);
  1236             byte[] encrData = createEncryptedData(password);
  1214             ContentInfo encrContentInfo =
  1237             ContentInfo encrContentInfo =
  1215                 new ContentInfo(ContentInfo.ENCRYPTED_DATA_OID,
  1238                 new ContentInfo(ContentInfo.ENCRYPTED_DATA_OID,
  1476             byte[] salt = getSalt();
  1499             byte[] salt = getSalt();
  1477 
  1500 
  1478             // generate MAC (MAC key is generated within JCE)
  1501             // generate MAC (MAC key is generated within JCE)
  1479             Mac m = Mac.getInstance("HmacPBESHA1");
  1502             Mac m = Mac.getInstance("HmacPBESHA1");
  1480             PBEParameterSpec params =
  1503             PBEParameterSpec params =
  1481                         new PBEParameterSpec(salt, iterationCount);
  1504                         new PBEParameterSpec(salt, MAC_ITERATION_COUNT);
  1482             SecretKey key = getPBEKey(passwd);
  1505             SecretKey key = getPBEKey(passwd);
  1483             m.init(key, params);
  1506             m.init(key, params);
  1484             m.update(data);
  1507             m.update(data);
  1485             byte[] macResult = m.doFinal();
  1508             byte[] macResult = m.doFinal();
  1486 
  1509 
  1487             // encode as MacData
  1510             // encode as MacData
  1488             MacData macData = new MacData(algName, macResult, salt,
  1511             MacData macData = new MacData(algName, macResult, salt,
  1489                                                 iterationCount);
  1512                                                 MAC_ITERATION_COUNT);
  1490             DerOutputStream bytes = new DerOutputStream();
  1513             DerOutputStream bytes = new DerOutputStream();
  1491             bytes.write(macData.getEncoded());
  1514             bytes.write(macData.getEncoded());
  1492             mData = bytes.toByteArray();
  1515             mData = bytes.toByteArray();
  1493         } catch (Exception e) {
  1516         } catch (Exception e) {
  1494             throw new IOException("calculateMac failed: " + e, e);
  1517             throw new IOException("calculateMac failed: " + e, e);
  1876 
  1899 
  1877         byte[] encryptedData = null;
  1900         byte[] encryptedData = null;
  1878 
  1901 
  1879         // create AlgorithmParameters
  1902         // create AlgorithmParameters
  1880         AlgorithmParameters algParams =
  1903         AlgorithmParameters algParams =
  1881                 getAlgorithmParameters("PBEWithSHA1AndRC2_40");
  1904                 getPBEAlgorithmParameters("PBEWithSHA1AndRC2_40");
  1882         DerOutputStream bytes = new DerOutputStream();
  1905         DerOutputStream bytes = new DerOutputStream();
  1883         AlgorithmId algId =
  1906         AlgorithmId algId =
  1884                 new AlgorithmId(pbeWithSHAAnd40BitRC2CBC_OID, algParams);
  1907                 new AlgorithmId(pbeWithSHAAnd40BitRC2CBC_OID, algParams);
  1885         algId.encode(bytes);
  1908         algId.encode(bytes);
  1886         byte[] encodedAlgId = bytes.toByteArray();
  1909         byte[] encodedAlgId = bytes.toByteArray();
  1996             contentType = safeContents.getContentType();
  2019             contentType = safeContents.getContentType();
  1997             safeContentsData = null;
  2020             safeContentsData = null;
  1998             if (contentType.equals(ContentInfo.DATA_OID)) {
  2021             if (contentType.equals(ContentInfo.DATA_OID)) {
  1999 
  2022 
  2000                 if (debug != null) {
  2023                 if (debug != null) {
  2001                     debug.println("Loading PKCS#7 data content-type");
  2024                     debug.println("Loading PKCS#7 data");
  2002                 }
  2025                 }
  2003 
  2026 
  2004                 safeContentsData = safeContents.getData();
  2027                 safeContentsData = safeContents.getData();
  2005             } else if (contentType.equals(ContentInfo.ENCRYPTED_DATA_OID)) {
  2028             } else if (contentType.equals(ContentInfo.ENCRYPTED_DATA_OID)) {
  2006                 if (password == null) {
  2029                 if (password == null) {
  2007 
  2030 
  2008                     if (debug != null) {
  2031                     if (debug != null) {
  2009                         debug.println("Warning: skipping PKCS#7 encryptedData" +
  2032                         debug.println("Warning: skipping PKCS#7 encryptedData" +
  2010                             " content-type - no password was supplied");
  2033                             " - no password was supplied");
  2011                     }
  2034                     }
  2012                     continue;
  2035                     continue;
  2013                 }
       
  2014 
       
  2015                 if (debug != null) {
       
  2016                     debug.println("Loading PKCS#7 encryptedData content-type");
       
  2017                 }
  2036                 }
  2018 
  2037 
  2019                 DerInputStream edi =
  2038                 DerInputStream edi =
  2020                                 safeContents.getContent().toDerInputStream();
  2039                                 safeContents.getContent().toDerInputStream();
  2021                 int edVersion = edi.getInteger();
  2040                 int edVersion = edi.getInteger();
  2033 
  2052 
  2034                 // parse Algorithm parameters
  2053                 // parse Algorithm parameters
  2035                 DerInputStream in = seq[1].toDerInputStream();
  2054                 DerInputStream in = seq[1].toDerInputStream();
  2036                 ObjectIdentifier algOid = in.getOID();
  2055                 ObjectIdentifier algOid = in.getOID();
  2037                 AlgorithmParameters algParams = parseAlgParameters(algOid, in);
  2056                 AlgorithmParameters algParams = parseAlgParameters(algOid, in);
       
  2057 
       
  2058                 PBEParameterSpec pbeSpec;
       
  2059                 int ic = 0;
       
  2060 
       
  2061                 if (algParams != null) {
       
  2062                     try {
       
  2063                         pbeSpec =
       
  2064                             algParams.getParameterSpec(PBEParameterSpec.class);
       
  2065                     } catch (InvalidParameterSpecException ipse) {
       
  2066                         throw new IOException(
       
  2067                             "Invalid PBE algorithm parameters");
       
  2068                     }
       
  2069                     ic = pbeSpec.getIterationCount();
       
  2070 
       
  2071                     if (ic > MAX_ITERATION_COUNT) {
       
  2072                         throw new IOException("PBE iteration count too large");
       
  2073                     }
       
  2074                 }
       
  2075 
       
  2076                 if (debug != null) {
       
  2077                     debug.println("Loading PKCS#7 encryptedData " +
       
  2078                         "(" + new AlgorithmId(algOid).getName() +
       
  2079                         " iterations: " + ic + ")");
       
  2080                 }
  2038 
  2081 
  2039                 while (true) {
  2082                 while (true) {
  2040                     try {
  2083                     try {
  2041                         // Use JCE
  2084                         // Use JCE
  2042                         SecretKey skey = getPBEKey(password);
  2085                         SecretKey skey = getPBEKey(password);
  2064             loadSafeContents(sc, password);
  2107             loadSafeContents(sc, password);
  2065         }
  2108         }
  2066 
  2109 
  2067         // The MacData is optional.
  2110         // The MacData is optional.
  2068         if (password != null && s.available() > 0) {
  2111         if (password != null && s.available() > 0) {
  2069            MacData macData = new MacData(s);
  2112             MacData macData = new MacData(s);
  2070            try {
  2113             int ic = macData.getIterations();
       
  2114 
       
  2115             try {
       
  2116                 if (ic > MAX_ITERATION_COUNT) {
       
  2117                     throw new InvalidAlgorithmParameterException(
       
  2118                         "MAC iteration count too large: " + ic);
       
  2119                 }
       
  2120 
  2071                 String algName =
  2121                 String algName =
  2072                         macData.getDigestAlgName().toUpperCase(Locale.ENGLISH);
  2122                         macData.getDigestAlgName().toUpperCase(Locale.ENGLISH);
  2073 
  2123 
  2074                 // Change SHA-1 to SHA1
  2124                 // Change SHA-1 to SHA1
  2075                 algName = algName.replace("-", "");
  2125                 algName = algName.replace("-", "");
  2076 
  2126 
  2077                 // generate MAC (MAC key is created within JCE)
  2127                 // generate MAC (MAC key is created within JCE)
  2078                 Mac m = Mac.getInstance("HmacPBE" + algName);
  2128                 Mac m = Mac.getInstance("HmacPBE" + algName);
  2079                 PBEParameterSpec params =
  2129                 PBEParameterSpec params =
  2080                         new PBEParameterSpec(macData.getSalt(),
  2130                         new PBEParameterSpec(macData.getSalt(), ic);
  2081                                         macData.getIterations());
       
  2082                 SecretKey key = getPBEKey(password);
  2131                 SecretKey key = getPBEKey(password);
  2083                 m.init(key, params);
  2132                 m.init(key, params);
  2084                 m.update(authSafeData);
  2133                 m.update(authSafeData);
  2085                 byte[] macResult = m.doFinal();
  2134                 byte[] macResult = m.doFinal();
  2086 
  2135 
  2087                 if (debug != null) {
  2136                 if (debug != null) {
  2088                     debug.println("Checking keystore integrity " +
  2137                     debug.println("Checking keystore integrity " +
  2089                         "(MAC algorithm: " + m.getAlgorithm() + ")");
  2138                         "(" + m.getAlgorithm() + " iterations: " + ic + ")");
  2090                 }
  2139                 }
  2091 
  2140 
  2092                 if (!MessageDigest.isEqual(macData.getDigest(), macResult)) {
  2141                 if (!MessageDigest.isEqual(macData.getDigest(), macResult)) {
  2093                    throw new UnrecoverableKeyException("Failed PKCS12" +
  2142                    throw new UnrecoverableKeyException("Failed PKCS12" +
  2094                                         " integrity checking");
  2143                                         " integrity checking");
  2095                 }
  2144                 }
  2096            } catch (Exception e) {
  2145             } catch (Exception e) {
  2097                 throw new IOException("Integrity check failed: " + e, e);
  2146                 throw new IOException("Integrity check failed: " + e, e);
  2098            }
  2147             }
  2099         }
  2148         }
  2100 
  2149 
  2101         /*
  2150         /*
  2102          * Match up private keys with certificate chains.
  2151          * Match up private keys with certificate chains.
  2103          */
  2152          */