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 |
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 } |