jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java
changeset 28243 47080f9ae750
parent 25859 3317bb8137f4
child 29909 388fe481deeb
equal deleted inserted replaced
28242:0cbef7c46996 28243:47080f9ae750
    67 import sun.security.util.DerValue;
    67 import sun.security.util.DerValue;
    68 import sun.security.util.ObjectIdentifier;
    68 import sun.security.util.ObjectIdentifier;
    69 import sun.security.pkcs.ContentInfo;
    69 import sun.security.pkcs.ContentInfo;
    70 import sun.security.x509.AlgorithmId;
    70 import sun.security.x509.AlgorithmId;
    71 import sun.security.pkcs.EncryptedPrivateKeyInfo;
    71 import sun.security.pkcs.EncryptedPrivateKeyInfo;
       
    72 import sun.security.provider.JavaKeyStore.JKS;
       
    73 import sun.security.util.KeyStoreDelegator;
    72 
    74 
    73 
    75 
    74 /**
    76 /**
    75  * This class provides the keystore implementation referred to as "PKCS12".
    77  * This class provides the keystore implementation referred to as "PKCS12".
    76  * Implements the PKCS#12 PFX protected using the Password privacy mode.
    78  * Implements the PKCS#12 PFX protected using the Password privacy mode.
   127  *
   129  *
   128  *
   130  *
   129  */
   131  */
   130 public final class PKCS12KeyStore extends KeyStoreSpi {
   132 public final class PKCS12KeyStore extends KeyStoreSpi {
   131 
   133 
       
   134     // special PKCS12 keystore that supports PKCS12 and JKS file formats
       
   135     public static final class DualFormatPKCS12 extends KeyStoreDelegator {
       
   136         public DualFormatPKCS12() {
       
   137             super("PKCS12", PKCS12KeyStore.class, "JKS", JKS.class);
       
   138         }
       
   139     }
       
   140 
   132     public static final int VERSION_3 = 3;
   141     public static final int VERSION_3 = 3;
   133 
   142 
   134     private static final String[] KEY_PROTECTION_ALGORITHM = {
   143     private static final String[] KEY_PROTECTION_ALGORITHM = {
   135         "keystore.pkcs12.keyProtectionAlgorithm",
   144         "keystore.pkcs12.keyProtectionAlgorithm",
   136         "keystore.PKCS12.keyProtectionAlgorithm"
   145         "keystore.PKCS12.keyProtectionAlgorithm"
  1051             return false;
  1060             return false;
  1052         }
  1061         }
  1053     }
  1062     }
  1054 
  1063 
  1055     /**
  1064     /**
       
  1065      * Determines if the keystore {@code Entry} for the specified
       
  1066      * {@code alias} is an instance or subclass of the specified
       
  1067      * {@code entryClass}.
       
  1068      *
       
  1069      * @param alias the alias name
       
  1070      * @param entryClass the entry class
       
  1071      *
       
  1072      * @return true if the keystore {@code Entry} for the specified
       
  1073      *          {@code alias} is an instance or subclass of the
       
  1074      *          specified {@code entryClass}, false otherwise
       
  1075      *
       
  1076      * @since 1.5
       
  1077      */
       
  1078     @Override
       
  1079     public boolean
       
  1080         engineEntryInstanceOf(String alias,
       
  1081                               Class<? extends KeyStore.Entry> entryClass)
       
  1082     {
       
  1083         if (entryClass == KeyStore.TrustedCertificateEntry.class) {
       
  1084             return engineIsCertificateEntry(alias);
       
  1085         }
       
  1086 
       
  1087         Entry entry = entries.get(alias.toLowerCase(Locale.ENGLISH));
       
  1088         if (entryClass == KeyStore.PrivateKeyEntry.class) {
       
  1089             return (entry != null && entry instanceof PrivateKeyEntry);
       
  1090         }
       
  1091         if (entryClass == KeyStore.SecretKeyEntry.class) {
       
  1092             return (entry != null && entry instanceof SecretKeyEntry);
       
  1093         }
       
  1094         return false;
       
  1095     }
       
  1096 
       
  1097     /**
  1056      * Returns the (alias) name of the first keystore entry whose certificate
  1098      * Returns the (alias) name of the first keystore entry whose certificate
  1057      * matches the given certificate.
  1099      * matches the given certificate.
  1058      *
  1100      *
  1059      * <p>This method attempts to match the given certificate with each
  1101      * <p>This method attempts to match the given certificate with each
  1060      * keystore entry. If the entry being considered
  1102      * keystore entry. If the entry being considered
  1082                     ((CertEntry) entry).trustedKeyUsage != null) {
  1124                     ((CertEntry) entry).trustedKeyUsage != null) {
  1083                 certElem = ((CertEntry) entry).cert;
  1125                 certElem = ((CertEntry) entry).cert;
  1084             } else {
  1126             } else {
  1085                 continue;
  1127                 continue;
  1086             }
  1128             }
  1087             if (certElem.equals(cert)) {
  1129             if (certElem != null && certElem.equals(cert)) {
  1088                 return alias;
  1130                 return alias;
  1089             }
  1131             }
  1090         }
  1132         }
  1091         return null;
  1133         return null;
  1092     }
  1134     }
  1921                 }
  1963                 }
  1922 
  1964 
  1923                 safeContentsData = safeContents.getData();
  1965                 safeContentsData = safeContents.getData();
  1924             } else if (contentType.equals((Object)ContentInfo.ENCRYPTED_DATA_OID)) {
  1966             } else if (contentType.equals((Object)ContentInfo.ENCRYPTED_DATA_OID)) {
  1925                 if (password == null) {
  1967                 if (password == null) {
  1926                    continue;
  1968 
       
  1969                     if (debug != null) {
       
  1970                         debug.println("Warning: skipping PKCS#7 encryptedData" +
       
  1971                             " content-type - no password was supplied");
       
  1972                     }
       
  1973                     continue;
  1927                 }
  1974                 }
  1928 
  1975 
  1929                 if (debug != null) {
  1976                 if (debug != null) {
  1930                     debug.println("Loading PKCS#7 encryptedData content-type");
  1977                     debug.println("Loading PKCS#7 encryptedData content-type");
  1931                 }
  1978                 }
  1963                             // Retry using an empty password
  2010                             // Retry using an empty password
  1964                             // without a NULL terminator.
  2011                             // without a NULL terminator.
  1965                             password = new char[1];
  2012                             password = new char[1];
  1966                             continue;
  2013                             continue;
  1967                         }
  2014                         }
  1968                         throw new IOException(
  2015                         throw new IOException("keystore password was incorrect",
  1969                             "failed to decrypt safe contents entry: " + e, e);
  2016                             new UnrecoverableKeyException(
       
  2017                                 "failed to decrypt safe contents entry: " + e));
  1970                     }
  2018                     }
  1971                 }
  2019                 }
  1972             } else {
  2020             } else {
  1973                 throw new IOException("public key protected PKCS12" +
  2021                 throw new IOException("public key protected PKCS12" +
  1974                                         " not supported");
  2022                                         " not supported");
  2282 
  2330 
  2283     private String getUnfriendlyName() {
  2331     private String getUnfriendlyName() {
  2284         counter++;
  2332         counter++;
  2285         return (String.valueOf(counter));
  2333         return (String.valueOf(counter));
  2286     }
  2334     }
       
  2335 
       
  2336     /*
       
  2337      * PKCS12 permitted first 24 bytes:
       
  2338      *
       
  2339      * 30 82 -- -- 02 01 03 30 82 -- -- 06 09 2A 86 48 86 F7 0D 01 07 01 A0 8-
       
  2340      * 30 -- 02 01 03 30 -- 06 09 2A 86 48 86 F7 0D 01 07 01 A0 -- 04 -- -- --
       
  2341      * 30 81 -- 02 01 03 30 81 -- 06 09 2A 86 48 86 F7 0D 01 07 01 A0 81 -- 04
       
  2342      * 30 82 -- -- 02 01 03 30 81 -- 06 09 2A 86 48 86 F7 0D 01 07 01 A0 81 --
       
  2343      * 30 83 -- -- -- 02 01 03 30 82 -- -- 06 09 2A 86 48 86 F7 0D 01 07 01 A0
       
  2344      * 30 83 -- -- -- 02 01 03 30 83 -- -- -- 06 09 2A 86 48 86 F7 0D 01 07 01
       
  2345      * 30 84 -- -- -- -- 02 01 03 30 83 -- -- -- 06 09 2A 86 48 86 F7 0D 01 07
       
  2346      * 30 84 -- -- -- -- 02 01 03 30 84 -- -- -- -- 06 09 2A 86 48 86 F7 0D 01
       
  2347      */
       
  2348 
       
  2349     private static final long[][] PKCS12_HEADER_PATTERNS = {
       
  2350         { 0x3082000002010330L, 0x82000006092A8648L, 0x86F70D010701A080L },
       
  2351         { 0x3000020103300006L, 0x092A864886F70D01L, 0x0701A00004000000L },
       
  2352         { 0x3081000201033081L, 0x0006092A864886F7L, 0x0D010701A0810004L },
       
  2353         { 0x3082000002010330L, 0x810006092A864886L, 0xF70D010701A08100L },
       
  2354         { 0x3083000000020103L, 0x3082000006092A86L, 0x4886F70D010701A0L },
       
  2355         { 0x3083000000020103L, 0x308200000006092AL, 0x864886F70D010701L },
       
  2356         { 0x3084000000000201L, 0x0330820000000609L, 0x2A864886F70D0107L },
       
  2357         { 0x3084000000000201L, 0x0330820000000006L, 0x092A864886F70D01L }
       
  2358     };
       
  2359 
       
  2360     private static final long[][] PKCS12_HEADER_MASKS = {
       
  2361         { 0xFFFF0000FFFFFFFFL, 0xFF0000FFFFFFFFFFL, 0xFFFFFFFFFFFFFFF0L },
       
  2362         { 0xFF00FFFFFFFF00FFL, 0xFFFFFFFFFFFFFFFFL, 0xFFFFFF00FF000000L },
       
  2363         { 0xFFFF00FFFFFFFFFFL, 0x00FFFFFFFFFFFFFFL, 0xFFFFFFFFFFFF00FFL },
       
  2364         { 0xFFFF0000FFFFFFFFL, 0xFF00FFFFFFFFFFFFL, 0xFFFFFFFFFFFFFF00L },
       
  2365         { 0xFFFF000000FFFFFFL, 0xFFFF0000FFFFFFFFL, 0xFFFFFFFFFFFFFFFFL },
       
  2366         { 0xFFFF000000FFFFFFL, 0xFFFF000000FFFFFFL, 0xFFFFFFFFFFFFFFFFL },
       
  2367         { 0xFFFF00000000FFFFL, 0xFFFFFF000000FFFFL, 0xFFFFFFFFFFFFFFFFL },
       
  2368         { 0xFFFF00000000FFFFL, 0xFFFFFF00000000FFL, 0xFFFFFFFFFFFFFFFFL }
       
  2369     };
       
  2370 
       
  2371     /**
       
  2372      * Probe the first few bytes of the keystore data stream for a valid
       
  2373      * PKCS12 keystore encoding.
       
  2374      */
       
  2375     @Override
       
  2376     public boolean engineProbe(InputStream stream) throws IOException {
       
  2377 
       
  2378         DataInputStream dataStream;
       
  2379         if (stream instanceof DataInputStream) {
       
  2380             dataStream = (DataInputStream)stream;
       
  2381         } else {
       
  2382             dataStream = new DataInputStream(stream);
       
  2383         }
       
  2384 
       
  2385         long firstPeek = dataStream.readLong();
       
  2386         long nextPeek = dataStream.readLong();
       
  2387         long finalPeek = dataStream.readLong();
       
  2388         boolean result = false;
       
  2389 
       
  2390         for (int i = 0; i < PKCS12_HEADER_PATTERNS.length; i++) {
       
  2391             if (PKCS12_HEADER_PATTERNS[i][0] ==
       
  2392                     (firstPeek & PKCS12_HEADER_MASKS[i][0]) &&
       
  2393                 (PKCS12_HEADER_PATTERNS[i][1] ==
       
  2394                     (nextPeek & PKCS12_HEADER_MASKS[i][1])) &&
       
  2395                 (PKCS12_HEADER_PATTERNS[i][2] ==
       
  2396                     (finalPeek & PKCS12_HEADER_MASKS[i][2]))) {
       
  2397                 result = true;
       
  2398                 break;
       
  2399             }
       
  2400         }
       
  2401 
       
  2402         return result;
       
  2403     }
  2287 }
  2404 }