1 /* 2 * Copyright (c) 2015, 2020, 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 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 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 SHA384withDSA("SHA384withDSA"), 75 SHA512withDSA("SHA512withDSA"), 76 77 SHA3_224withDSA("SHA3-224withDSA"), 78 SHA3_256withDSA("SHA3-256withDSA"), 79 SHA3_384withDSA("SHA3-384withDSA"), 80 SHA3_512withDSA("SHA3-512withDSA"), 81 82 SHA1withRSA("Sha1withrSA"), 83 SHA224withRSA("SHA224withRSA"), 84 SHA256withRSA("SHA256withRSA"), 85 SHA384withRSA("SHA384withRSA"), 86 SHA512withRSA("SHA512withRSA"), 87 SHA512_224withRSA("SHA512/224withRSA"), 88 SHA512_256withRSA("SHA512/256withRSA"), 89 SHA3_224withRSA("SHA3-224withRSA"), 90 SHA3_256withRSA("SHA3-256withRSA"), 91 SHA3_384withRSA("SHA3-384withRSA"), 92 SHA3_512withRSA("SHA3-512withRSA"), 93 94 SHA1withECDSA("SHA1withECDSA"), 95 SHA224withECDSA("SHA224withECDSA"), 96 SHA256withECDSA("SHA256withECDSA"), 97 SHA384withECDSA("SHA384withECDSA"), 98 SHA512withECDSA("SHA512withECDSA"), 99 SHA3_224withECDSA("SHA3-224withECDSA"), 100 SHA3_256withECDSA("SHA3-256withECDSA"), 101 SHA3_384withECDSA("SHA3-384withECDSA"), 102 SHA3_512withECDSA("SHA3-512withECDSA"), 103 104 MD5andSHA1withRSA("MD5andSHA1withRSA"), 105 106 RSASSA_PSS("RSASSA-PSS"); 107 108 final String name; 109 110 SigAlg(String name) { 111 this.name = name; 112 } 113 } 114 115 static class Test { 116 final Provider provider; 117 final KeyAlg keyAlg; 118 final SigAlg sigAlg; 119 final int keySize; 120 final AlgorithmParameterSpec sigParams; 121 122 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider) { 123 this(sigAlg, keyAlg, provider, -1, null); 124 } 125 126 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider, int keySize) { 127 this(sigAlg, keyAlg, provider, keySize, null); 128 } 129 130 Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider, int keySize, 131 AlgorithmParameterSpec sigParams) { 132 this.provider = provider; 133 this.keyAlg = keyAlg; 134 this.sigAlg = sigAlg; 135 this.keySize = keySize; 136 this.sigParams = sigParams; 137 } 138 139 private static String formatParams(AlgorithmParameterSpec aps) { 140 if (aps == null) return "null"; 141 if (aps instanceof PSSParameterSpec) { 142 PSSParameterSpec p = (PSSParameterSpec) aps; 143 return String.format("PSSParameterSpec (%s, %s, %s, %s)", 144 p.getDigestAlgorithm(), formatParams(p.getMGFParameters()), 145 p.getSaltLength(), p.getTrailerField()); 146 } else if (aps instanceof MGF1ParameterSpec) { 147 return "MGF1" + 148 ((MGF1ParameterSpec)aps).getDigestAlgorithm(); 149 } else { 150 return aps.toString(); 151 } 152 } 153 154 public String toString() { 155 return String.format("Test: provider = %s, signature alg = %s, " 156 + " w/ %s, key alg = %s", provider, sigAlg, 157 formatParams(sigParams), keyAlg); 158 } 159 } 160 161 private static final Test[] tests = { 162 new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Default, 1024), 163 new Test(SigAlg.MD2withRSA, KeyAlg.RSA, Provider.Default), 164 new Test(SigAlg.MD5withRSA, KeyAlg.RSA, Provider.Default), 165 new Test(SigAlg.SHA3_224withRSA, KeyAlg.RSA, Provider.Default), 166 new Test(SigAlg.SHA3_256withRSA, KeyAlg.RSA, Provider.Default), 167 new Test(SigAlg.SHA3_384withRSA, KeyAlg.RSA, Provider.Default), 168 new Test(SigAlg.SHA3_512withRSA, KeyAlg.RSA, Provider.Default), 169 new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Sun, 1024), 170 new Test(SigAlg.SHA224withDSA, KeyAlg.DSA, Provider.Sun, 2048), 171 new Test(SigAlg.SHA256withDSA, KeyAlg.DSA, Provider.Sun, 2048), 172 }; 173 174 private static final String str = "to-be-signed"; 175 private static final int N = 3; 176 177 public static void main(String argv[]) { 178 boolean result = Arrays.stream(tests).allMatch((test) -> runTest(test)); 179 result &= runTestPSS(2048); 180 if (result) { 181 System.out.println("All tests passed"); 182 } else { 183 throw new RuntimeException("Some tests failed"); 184 } 185 } 186 187 private static boolean runTestPSS(int keysize) { 188 boolean result = true; 189 SigAlg pss = SigAlg.RSASSA_PSS; 190 Iterator<String> mdAlgs = SigTestUtil.getDigestAlgorithms 191 (SignatureType.RSASSA_PSS, keysize).iterator(); 192 while (mdAlgs.hasNext()) { 193 result &= runTest(new Test(pss, KeyAlg.RSA, Provider.SunRsaSign, 194 keysize, SigTestUtil.generateDefaultParameter 195 (SignatureType.RSASSA_PSS, mdAlgs.next()))); 196 } 197 return result; 198 } 199 200 static boolean runTest(Test test) { 201 System.out.println(test); 202 try { 203 // Generate all private/public key pairs 204 PrivateKey[] privKeys = new PrivateKey[N]; 205 PublicKey[] pubKeys = new PublicKey[N]; 206 PublicKey[] anotherPubKeys = new PublicKey[N]; 207 Signature signature; 208 KeyPairGenerator kpg; 209 if (test.provider != Provider.Default) { 210 signature = Signature.getInstance(test.sigAlg.name, 211 test.provider.name); 212 // try using the same provider first, if not, fallback 213 // to the first available impl 214 try { 215 kpg = KeyPairGenerator.getInstance( 216 test.keyAlg.name, test.provider.name); 217 } catch (NoSuchAlgorithmException nsae) { 218 kpg = KeyPairGenerator.getInstance( 219 test.keyAlg.name); 220 } 221 } else { 222 signature = Signature.getInstance(test.sigAlg.name); 223 kpg = KeyPairGenerator.getInstance(test.keyAlg.name); 224 } 225 if (test.sigParams != null) { 226 signature.setParameter(test.sigParams); 227 } 228 229 for (int j=0; j < N; j++) { 230 if (test.keySize != -1) { 231 kpg.initialize(test.keySize); 232 } 233 KeyPair kp = kpg.genKeyPair(); 234 KeyPair anotherKp = kpg.genKeyPair(); 235 privKeys[j] = kp.getPrivate(); 236 pubKeys[j] = kp.getPublic(); 237 anotherPubKeys[j] = anotherKp.getPublic(); 238 239 if (Arrays.equals(pubKeys[j].getEncoded(), 240 anotherPubKeys[j].getEncoded())) { 241 System.out.println("Failed: it should not get " 242 + "the same pair of public key"); 243 return false; 244 } 245 } 246 247 // Create a chain of signed objects 248 SignedObject[] objects = new SignedObject[N]; 249 objects[0] = new SignedObject(str, privKeys[0], signature); 250 for (int j = 1; j < N; j++) { 251 objects[j] = new SignedObject(objects[j - 1], privKeys[j], 252 signature); 253 } 254 255 // Verify the chain 256 int n = objects.length - 1; 257 SignedObject object = objects[n]; 258 do { 259 if (!object.verify(pubKeys[n], signature)) { 260 System.out.println("Failed: verification failed, n = " + n); 261 return false; 262 } 263 if (object.verify(anotherPubKeys[n], signature)) { 264 System.out.println("Failed: verification should not " 265 + "succeed with wrong public key, n = " + n); 266 return false; 267 } 268 269 object = (SignedObject) object.getObject(); 270 n--; 271 } while (n > 0); 272 273 System.out.println("signed data: " + object.getObject()); 274 if (!str.equals(object.getObject())) { 275 System.out.println("Failed: signed data is not equal to " 276 + "original one"); 277 return false; 278 } 279 280 System.out.println("Test passed"); 281 return true; 282 } catch (NoSuchProviderException nspe) { 283 if (test.provider == Provider.SunMSCAPI 284 && !System.getProperty("os.name").startsWith("Windows")) { 285 System.out.println("SunMSCAPI is available only on Windows: " 286 + nspe); 287 return true; 288 } 289 System.out.println("Unexpected exception: " + nspe); 290 return false; 291 } catch (Exception e) { 292 System.out.println("Unexpected exception: " + e); 293 e.printStackTrace(System.out); 294 return false; 295 } 296 } 297 } 298