1 /* 2 * Copyright (c) 2006, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 6414980 27 * @summary Test that the PKCS#11 KeyStore handles RSA, DSA, and EC keys 28 * @author Andreas Sterbenz 29 * @library .. 30 * @modules jdk.crypto.cryptoki 31 * @run main/othervm AddPrivateKey 32 * @run main/othervm AddPrivateKey sm policy 33 */ 34 35 import java.io.File; 36 import java.io.FileInputStream; 37 import java.io.InputStream; 38 import java.security.KeyFactory; 39 import java.security.KeyStore; 40 import java.security.KeyStore.PasswordProtection; 41 import java.security.KeyStore.PrivateKeyEntry; 42 import java.security.KeyStoreException; 43 import java.security.PrivateKey; 44 import java.security.Provider; 45 import java.security.PublicKey; 46 import java.security.Security; 47 import java.security.Signature; 48 import java.security.cert.X509Certificate; 49 import java.util.Arrays; 50 import java.util.Collections; 51 import java.util.List; 52 53 // this test is currently only run for the NSS KeyStore provider, but it 54 // is really a generic KeyStore test so it should be modified to run for 55 // all providers. 56 public class AddPrivateKey extends SecmodTest { 57 58 private static final String ALIAS1 = "entry1"; 59 private static final String ALIAS2 = "entry2"; 60 private static final String ALIAS3 = "entry3"; 61 private static final int MAX_LINE = 85; 62 private static final int DATA_LENGTH = 4096; 63 private static final byte[] DATA = generateData(DATA_LENGTH); 64 65 public static void main(String[] args) throws Exception { 66 if (initSecmod() == false) { 67 return; 68 } 69 70 String configName = BASE + SEP + "nss.cfg"; 71 Provider p = getSunPKCS11(configName); 72 73 boolean supportsEC = (p.getService("KeyFactory", "EC") != null); 74 75 System.out.println(p); 76 System.out.println(); 77 Security.addProvider(p); 78 79 if (args.length > 1 && "sm".equals(args[0])) { 80 System.setProperty("java.security.policy", 81 BASE + File.separator + args[1]); 82 System.setSecurityManager(new SecurityManager()); 83 } 84 85 KeyStore ks = KeyStore.getInstance(PKCS11, p); 86 ks.load(null, password); 87 for (String alias : aliases(ks)) { 88 System.out.println("Deleting: " + alias); 89 ks.deleteEntry(alias); 90 } 91 92 KeyStore jks = KeyStore.getInstance("JKS"); 93 try (InputStream in = new FileInputStream(BASE + SEP + "keystore.jks")) { 94 char[] jkspass = "passphrase".toCharArray(); 95 jks.load(in, jkspass); 96 for (String alias : Collections.list(jks.aliases())) { 97 if (jks.entryInstanceOf(alias, PrivateKeyEntry.class)) { 98 PrivateKeyEntry entry = (PrivateKeyEntry)jks.getEntry(alias, 99 new PasswordProtection(jkspass)); 100 String algorithm = entry.getPrivateKey().getAlgorithm(); 101 System.out.printf("-Entry %s (%s)%n", alias, algorithm); 102 if ((supportsEC == false) && algorithm.equals("EC")) { 103 System.out.println("EC not supported by provider, " 104 + "skipping"); 105 continue; 106 } 107 if ((supportsEC == false) && algorithm.equals("DSA")) { 108 System.out.println("Provider does not appear to have " 109 + "CKA_NETSCAPE_DB fix, skipping"); 110 continue; 111 } 112 test(p, entry); 113 } // else ignore 114 } 115 } 116 System.out.println("OK"); 117 } 118 119 private static List<String> aliases(KeyStore ks) throws KeyStoreException { 120 return Collections.list(ks.aliases()); 121 } 122 123 private static void test(Provider p, PrivateKeyEntry entry) throws Exception { 124 PrivateKey key = entry.getPrivateKey(); 125 X509Certificate[] chain = (X509Certificate[])entry.getCertificateChain(); 126 PublicKey publicKey = chain[0].getPublicKey(); 127 System.out.println(toString(key)); 128 sign(p, key, publicKey); 129 130 KeyStore ks = KeyStore.getInstance("PKCS11", p); 131 ks.load(null, null); 132 if (ks.size() != 0) { 133 throw new Exception("KeyStore not empty"); 134 } 135 List<String> aliases; 136 137 // test 1: add entry 138 ks.setKeyEntry(ALIAS1, key, null, chain); 139 aliases = aliases(ks); 140 if (aliases.size() != 1) { 141 throw new Exception("size not 1: " + aliases); 142 } 143 if (aliases.get(0).equals(ALIAS1) == false) { 144 throw new Exception("alias mismatch: " + aliases); 145 } 146 147 PrivateKey key2 = (PrivateKey)ks.getKey(ALIAS1, null); 148 System.out.println(toString(key2)); 149 X509Certificate[] chain2 = 150 (X509Certificate[]) ks.getCertificateChain(ALIAS1); 151 if (Arrays.equals(chain, chain2) == false) { 152 throw new Exception("chain mismatch"); 153 } 154 sign(p, key2, publicKey); 155 156 ks.deleteEntry(ALIAS1); 157 if (ks.size() != 0) { 158 throw new Exception("KeyStore not empty"); 159 } 160 161 // test 2: translate to session object, then add entry 162 KeyFactory kf = KeyFactory.getInstance(key.getAlgorithm(), p); 163 PrivateKey key3 = (PrivateKey)kf.translateKey(key); 164 System.out.println(toString(key3)); 165 sign(p, key3, publicKey); 166 167 ks.setKeyEntry(ALIAS2, key3, null, chain); 168 aliases = aliases(ks); 169 if (aliases.size() != 1) { 170 throw new Exception("size not 1"); 171 } 172 if (aliases.get(0).equals(ALIAS2) == false) { 173 throw new Exception("alias mismatch: " + aliases); 174 } 175 176 PrivateKey key4 = (PrivateKey)ks.getKey(ALIAS2, null); 177 System.out.println(toString(key4)); 178 X509Certificate[] chain4 = (X509Certificate[]) 179 ks.getCertificateChain(ALIAS2); 180 if (Arrays.equals(chain, chain4) == false) { 181 throw new Exception("chain mismatch"); 182 } 183 sign(p, key4, publicKey); 184 185 // test 3: change alias 186 ks.setKeyEntry(ALIAS3, key3, null, chain); 187 aliases = aliases(ks); 188 if (aliases.size() != 1) { 189 throw new Exception("size not 1"); 190 } 191 if (aliases.get(0).equals(ALIAS3) == false) { 192 throw new Exception("alias mismatch: " + aliases); 193 } 194 195 PrivateKey key5 = (PrivateKey)ks.getKey(ALIAS3, null); 196 System.out.println(toString(key5)); 197 X509Certificate[] chain5 = (X509Certificate[]) 198 ks.getCertificateChain(ALIAS3); 199 if (Arrays.equals(chain, chain5) == false) { 200 throw new Exception("chain mismatch"); 201 } 202 sign(p, key5, publicKey); 203 204 ks.deleteEntry(ALIAS3); 205 if (ks.size() != 0) { 206 throw new Exception("KeyStore not empty"); 207 } 208 209 System.out.println("OK"); 210 } 211 212 private static void sign(Provider p, PrivateKey privateKey, 213 PublicKey publicKey) throws Exception { 214 String keyAlg = privateKey.getAlgorithm(); 215 String alg; 216 switch (keyAlg) { 217 case "RSA": 218 alg = "SHA1withRSA"; 219 break; 220 case "DSA": 221 alg = "SHA1withDSA"; 222 break; 223 case "EC": 224 alg = "SHA1withECDSA"; 225 break; 226 default: 227 throw new Exception("Unknown algorithm " + keyAlg); 228 } 229 Signature s = Signature.getInstance(alg, p); 230 s.initSign(privateKey); 231 s.update(DATA); 232 byte[] sig = s.sign(); 233 234 s.initVerify(publicKey); 235 s.update(DATA); 236 if (s.verify(sig) == false) { 237 throw new Exception("Signature did not verify"); 238 } 239 } 240 241 private static String toString(Object o) { 242 String s = String.valueOf(o).split("\n")[0]; 243 return (s.length() <= MAX_LINE) ? s : s.substring(0, MAX_LINE); 244 } 245 246 }