1 /** 2 * Copyright (c) 2015, 2019, 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 import java.security.*; 25 import java.security.spec.*; 26 import java.util.*; 27 import jdk.test.lib.SigTestUtil; 28 import static jdk.test.lib.SigTestUtil.SignatureType; 29 30 /* 31 * @test 32 * @bug 8050374 8181048 8146293 33 * @summary Verify a chain of signed objects 34 * @library /test/lib 35 * @build jdk.test.lib.SigTestUtil 36 * @run main Chain 37 */ 38 public class Chain { 39 40 static enum KeyAlg { 41 RSA("RSA"), 42 DSA("DSA"), 43 EC("EC"); 44 45 final String name; 46 KeyAlg(String alg)47 KeyAlg(String alg) { 48 this.name = alg; 49 } 50 } 51 52 static enum Provider { 53 Default("default"), 54 SunRsaSign("SunRsaSign"), 55 Sun("SUN"), 56 SunEC("SunEC"), 57 SunJSSE("SunJSSE"), 58 SunMSCAPI("SunMSCAPI"); 59 60 final String name; 61 Provider(String name)62 Provider(String name) { 63 this.name = name; 64 } 65 } 66 67 static enum SigAlg { 68 MD2withRSA("MD2withRSA"), 69 MD5withRSA("md5withRSA"), 70 71 SHA1withDSA("SHA1withDSA"), 72 SHA224withDSA("SHA224withDSA"), 73 SHA256withDSA("SHA256withDSA"), 74 75 SHA1withRSA("Sha1withrSA"), 76 SHA224withRSA("SHA224withRSA"), 77 SHA256withRSA("SHA256withRSA"), 78 SHA384withRSA("SHA384withRSA"), 79 SHA512withRSA("SHA512withRSA"), 80 SHA512_224withRSA("SHA512/224withRSA"), 81 SHA512_256withRSA("SHA512/256withRSA"), 82 83 SHA1withECDSA("SHA1withECDSA"), 84 SHA256withECDSA("SHA256withECDSA"), 85 SHA224withECDSA("SHA224withECDSA"), 86 SHA384withECDSA("SHA384withECDSA"), 87 SHA512withECDSA("SHA512withECDSA"), 88 89 MD5andSHA1withRSA("MD5andSHA1withRSA"), 90 91 RSASSA_PSS("RSASSA-PSS"); 92 93 final String name; 94 SigAlg(String name)95 SigAlg(String name) { 96 this.name = name; 97 } 98 } 99 100 static class Test { 101 final Provider provider; 102 final KeyAlg keyAlg; 103 final SigAlg sigAlg; 104 final int keySize; 105 final AlgorithmParameterSpec sigParams; 106 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider)107 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider) { 108 this(sigAlg, keyAlg, provider, -1, null); 109 } 110 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider, int keySize)111 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider, int keySize) { 112 this(sigAlg, keyAlg, provider, keySize, null); 113 } 114 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider, int keySize, AlgorithmParameterSpec sigParams)115 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider, int keySize, 116 AlgorithmParameterSpec sigParams) { 117 this.provider = provider; 118 this.keyAlg = keyAlg; 119 this.sigAlg = sigAlg; 120 this.keySize = keySize; 121 this.sigParams = sigParams; 122 } 123 formatParams(AlgorithmParameterSpec aps)124 private static String formatParams(AlgorithmParameterSpec aps) { 125 if (aps == null) return "null"; 126 if (aps instanceof PSSParameterSpec) { 127 PSSParameterSpec p = (PSSParameterSpec) aps; 128 return String.format("PSSParameterSpec (%s, %s, %s, %s)", 129 p.getDigestAlgorithm(), formatParams(p.getMGFParameters()), 130 p.getSaltLength(), p.getTrailerField()); 131 } else if (aps instanceof MGF1ParameterSpec) { 132 return "MGF1" + 133 ((MGF1ParameterSpec)aps).getDigestAlgorithm(); 134 } else { 135 return aps.toString(); 136 } 137 } 138 toString()139 public String toString() { 140 return String.format("Test: provider = %s, signature alg = %s, " 141 + " w/ %s, key alg = %s", provider, sigAlg, 142 formatParams(sigParams), keyAlg); 143 } 144 } 145 146 private static final Test[] tests = { 147 new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Default, 1024), 148 new Test(SigAlg.MD2withRSA, KeyAlg.RSA, Provider.Default), 149 new Test(SigAlg.MD5withRSA, KeyAlg.RSA, Provider.Default), 150 new Test(SigAlg.SHA1withRSA, KeyAlg.RSA, Provider.Default), 151 new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Sun, 1024), 152 new Test(SigAlg.SHA224withDSA, KeyAlg.DSA, Provider.Sun, 2048), 153 new Test(SigAlg.SHA256withDSA, KeyAlg.DSA, Provider.Sun, 2048), 154 }; 155 156 private static final String str = "to-be-signed"; 157 private static final int N = 3; 158 main(String argv[])159 public static void main(String argv[]) { 160 boolean result = Arrays.stream(tests).allMatch((test) -> runTest(test)); 161 result &= runTestPSS(2048); 162 if (result) { 163 System.out.println("All tests passed"); 164 } else { 165 throw new RuntimeException("Some tests failed"); 166 } 167 } 168 runTestPSS(int keysize)169 private static boolean runTestPSS(int keysize) { 170 boolean result = true; 171 SigAlg pss = SigAlg.RSASSA_PSS; 172 Iterator<String> mdAlgs = SigTestUtil.getDigestAlgorithms 173 (SignatureType.RSASSA_PSS, keysize).iterator(); 174 while (mdAlgs.hasNext()) { 175 result &= runTest(new Test(pss, KeyAlg.RSA, Provider.SunRsaSign, 176 keysize, SigTestUtil.generateDefaultParameter 177 (SignatureType.RSASSA_PSS, mdAlgs.next()))); 178 } 179 return result; 180 } 181 runTest(Test test)182 static boolean runTest(Test test) { 183 System.out.println(test); 184 try { 185 // Generate all private/public key pairs 186 PrivateKey[] privKeys = new PrivateKey[N]; 187 PublicKey[] pubKeys = new PublicKey[N]; 188 PublicKey[] anotherPubKeys = new PublicKey[N]; 189 Signature signature; 190 KeyPairGenerator kpg; 191 if (test.provider != Provider.Default) { 192 signature = Signature.getInstance(test.sigAlg.name, 193 test.provider.name); 194 // try using the same provider first, if not, fallback 195 // to the first available impl 196 try { 197 kpg = KeyPairGenerator.getInstance( 198 test.keyAlg.name, test.provider.name); 199 } catch (NoSuchAlgorithmException nsae) { 200 kpg = KeyPairGenerator.getInstance( 201 test.keyAlg.name); 202 } 203 } else { 204 signature = Signature.getInstance(test.sigAlg.name); 205 kpg = KeyPairGenerator.getInstance(test.keyAlg.name); 206 } 207 if (test.sigParams != null) { 208 signature.setParameter(test.sigParams); 209 } 210 211 for (int j=0; j < N; j++) { 212 if (test.keySize != -1) { 213 kpg.initialize(test.keySize); 214 } 215 KeyPair kp = kpg.genKeyPair(); 216 KeyPair anotherKp = kpg.genKeyPair(); 217 privKeys[j] = kp.getPrivate(); 218 pubKeys[j] = kp.getPublic(); 219 anotherPubKeys[j] = anotherKp.getPublic(); 220 221 if (Arrays.equals(pubKeys[j].getEncoded(), 222 anotherPubKeys[j].getEncoded())) { 223 System.out.println("Failed: it should not get " 224 + "the same pair of public key"); 225 return false; 226 } 227 } 228 229 // Create a chain of signed objects 230 SignedObject[] objects = new SignedObject[N]; 231 objects[0] = new SignedObject(str, privKeys[0], signature); 232 for (int j = 1; j < N; j++) { 233 objects[j] = new SignedObject(objects[j - 1], privKeys[j], 234 signature); 235 } 236 237 // Verify the chain 238 int n = objects.length - 1; 239 SignedObject object = objects[n]; 240 do { 241 if (!object.verify(pubKeys[n], signature)) { 242 System.out.println("Failed: verification failed, n = " + n); 243 return false; 244 } 245 if (object.verify(anotherPubKeys[n], signature)) { 246 System.out.println("Failed: verification should not " 247 + "succeed with wrong public key, n = " + n); 248 return false; 249 } 250 251 object = (SignedObject) object.getObject(); 252 n--; 253 } while (n > 0); 254 255 System.out.println("signed data: " + object.getObject()); 256 if (!str.equals(object.getObject())) { 257 System.out.println("Failed: signed data is not equal to " 258 + "original one"); 259 return false; 260 } 261 262 System.out.println("Test passed"); 263 return true; 264 } catch (NoSuchProviderException nspe) { 265 if (test.provider == Provider.SunMSCAPI 266 && !System.getProperty("os.name").startsWith("Windows")) { 267 System.out.println("SunMSCAPI is available only on Windows: " 268 + nspe); 269 return true; 270 } 271 System.out.println("Unexpected exception: " + nspe); 272 return false; 273 } catch (Exception e) { 274 System.out.println("Unexpected exception: " + e); 275 e.printStackTrace(System.out); 276 return false; 277 } 278 } 279 } 280 281