c82ad845e1
Reviewed-by: rhalade, ascarpino
304 lines
11 KiB
Java
304 lines
11 KiB
Java
/*
|
|
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
import java.security.*;
|
|
import java.security.spec.*;
|
|
import java.util.*;
|
|
import jdk.test.lib.SigTestUtil;
|
|
import static jdk.test.lib.SigTestUtil.SignatureType;
|
|
|
|
/*
|
|
* @test
|
|
* @bug 8050374 8181048 8146293
|
|
* @summary Verify a chain of signed objects
|
|
* @library /test/lib
|
|
* @build jdk.test.lib.SigTestUtil
|
|
* @run main Chain
|
|
*/
|
|
public class Chain {
|
|
|
|
static enum KeyAlg {
|
|
RSA("RSA"),
|
|
DSA("DSA"),
|
|
EC("EC");
|
|
|
|
final String name;
|
|
|
|
KeyAlg(String alg) {
|
|
this.name = alg;
|
|
}
|
|
}
|
|
|
|
static enum Provider {
|
|
Default("default"),
|
|
SunRsaSign("SunRsaSign"),
|
|
Sun("SUN"),
|
|
SunEC("SunEC"),
|
|
SunJSSE("SunJSSE"),
|
|
SunMSCAPI("SunMSCAPI"),
|
|
TestProvider_or_SunRsaSign(System.getProperty("test.provider.name", "SunRsaSign")),
|
|
TestProvider_or_Sun(System.getProperty("test.provider.name", "SUN")),
|
|
TestProvider_or_SunEC(System.getProperty("test.provider.name", "SunEC"));
|
|
|
|
final String name;
|
|
|
|
Provider(String name) {
|
|
this.name = name;
|
|
}
|
|
}
|
|
|
|
static enum SigAlg {
|
|
MD2withRSA("MD2withRSA"),
|
|
MD5withRSA("md5withRSA"),
|
|
|
|
SHA1withDSA("SHA1withDSA"),
|
|
SHA224withDSA("SHA224withDSA"),
|
|
SHA256withDSA("SHA256withDSA"),
|
|
SHA384withDSA("SHA384withDSA"),
|
|
SHA512withDSA("SHA512withDSA"),
|
|
|
|
SHA3_224withDSA("SHA3-224withDSA"),
|
|
SHA3_256withDSA("SHA3-256withDSA"),
|
|
SHA3_384withDSA("SHA3-384withDSA"),
|
|
SHA3_512withDSA("SHA3-512withDSA"),
|
|
|
|
SHA1withRSA("Sha1withrSA"),
|
|
SHA224withRSA("SHA224withRSA"),
|
|
SHA256withRSA("SHA256withRSA"),
|
|
SHA384withRSA("SHA384withRSA"),
|
|
SHA512withRSA("SHA512withRSA"),
|
|
SHA512_224withRSA("SHA512/224withRSA"),
|
|
SHA512_256withRSA("SHA512/256withRSA"),
|
|
SHA3_224withRSA("SHA3-224withRSA"),
|
|
SHA3_256withRSA("SHA3-256withRSA"),
|
|
SHA3_384withRSA("SHA3-384withRSA"),
|
|
SHA3_512withRSA("SHA3-512withRSA"),
|
|
|
|
SHA1withECDSA("SHA1withECDSA"),
|
|
SHA224withECDSA("SHA224withECDSA"),
|
|
SHA256withECDSA("SHA256withECDSA"),
|
|
SHA384withECDSA("SHA384withECDSA"),
|
|
SHA512withECDSA("SHA512withECDSA"),
|
|
SHA3_224withECDSA("SHA3-224withECDSA"),
|
|
SHA3_256withECDSA("SHA3-256withECDSA"),
|
|
SHA3_384withECDSA("SHA3-384withECDSA"),
|
|
SHA3_512withECDSA("SHA3-512withECDSA"),
|
|
|
|
MD5andSHA1withRSA("MD5andSHA1withRSA"),
|
|
|
|
RSASSA_PSS("RSASSA-PSS");
|
|
|
|
final String name;
|
|
|
|
SigAlg(String name) {
|
|
this.name = name;
|
|
}
|
|
}
|
|
|
|
static class Test {
|
|
final Provider provider;
|
|
final KeyAlg keyAlg;
|
|
final SigAlg sigAlg;
|
|
final int keySize;
|
|
final AlgorithmParameterSpec sigParams;
|
|
|
|
Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider) {
|
|
this(sigAlg, keyAlg, provider, -1, null);
|
|
}
|
|
|
|
Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider, int keySize) {
|
|
this(sigAlg, keyAlg, provider, keySize, null);
|
|
}
|
|
|
|
Test(SigAlg sigAlg, KeyAlg keyAlg, Provider provider, int keySize,
|
|
AlgorithmParameterSpec sigParams) {
|
|
this.provider = provider;
|
|
this.keyAlg = keyAlg;
|
|
this.sigAlg = sigAlg;
|
|
this.keySize = keySize;
|
|
this.sigParams = sigParams;
|
|
}
|
|
|
|
private static String formatParams(AlgorithmParameterSpec aps) {
|
|
if (aps == null) return "null";
|
|
if (aps instanceof PSSParameterSpec) {
|
|
PSSParameterSpec p = (PSSParameterSpec) aps;
|
|
return String.format("PSSParameterSpec (%s, %s, %s, %s)",
|
|
p.getDigestAlgorithm(), formatParams(p.getMGFParameters()),
|
|
p.getSaltLength(), p.getTrailerField());
|
|
} else if (aps instanceof MGF1ParameterSpec) {
|
|
return "MGF1" +
|
|
((MGF1ParameterSpec)aps).getDigestAlgorithm();
|
|
} else {
|
|
return aps.toString();
|
|
}
|
|
}
|
|
|
|
public String toString() {
|
|
return String.format("Test: provider = %s, signature alg = %s, "
|
|
+ " w/ %s, key alg = %s", provider, sigAlg,
|
|
formatParams(sigParams), keyAlg);
|
|
}
|
|
}
|
|
|
|
private static final Test[] tests = {
|
|
new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.Default, 1024),
|
|
new Test(SigAlg.MD2withRSA, KeyAlg.RSA, Provider.Default),
|
|
new Test(SigAlg.MD5withRSA, KeyAlg.RSA, Provider.Default),
|
|
new Test(SigAlg.SHA224withRSA, KeyAlg.RSA, Provider.Default),
|
|
new Test(SigAlg.SHA256withRSA, KeyAlg.RSA, Provider.Default),
|
|
new Test(SigAlg.SHA3_224withRSA, KeyAlg.RSA, Provider.Default),
|
|
new Test(SigAlg.SHA3_256withRSA, KeyAlg.RSA, Provider.Default),
|
|
new Test(SigAlg.SHA3_384withRSA, KeyAlg.RSA, Provider.Default),
|
|
new Test(SigAlg.SHA3_512withRSA, KeyAlg.RSA, Provider.Default),
|
|
new Test(SigAlg.SHA1withDSA, KeyAlg.DSA, Provider.TestProvider_or_Sun, 1024),
|
|
new Test(SigAlg.SHA224withDSA, KeyAlg.DSA, Provider.TestProvider_or_Sun, 2048),
|
|
new Test(SigAlg.SHA256withDSA, KeyAlg.DSA, Provider.TestProvider_or_Sun, 2048),
|
|
};
|
|
|
|
private static final String str = "to-be-signed";
|
|
private static final int N = 3;
|
|
|
|
public static void main(String argv[]) {
|
|
boolean result = Arrays.stream(tests).allMatch((test) -> runTest(test));
|
|
result &= runTestPSS(2048);
|
|
if (result) {
|
|
System.out.println("All tests passed");
|
|
} else {
|
|
throw new RuntimeException("Some tests failed");
|
|
}
|
|
}
|
|
|
|
private static boolean runTestPSS(int keysize) {
|
|
boolean result = true;
|
|
SigAlg pss = SigAlg.RSASSA_PSS;
|
|
Iterator<String> mdAlgs = SigTestUtil.getDigestAlgorithms
|
|
(SignatureType.RSASSA_PSS, keysize).iterator();
|
|
while (mdAlgs.hasNext()) {
|
|
result &= runTest(new Test(pss, KeyAlg.RSA, Provider.TestProvider_or_SunRsaSign,
|
|
keysize, SigTestUtil.generateDefaultParameter
|
|
(SignatureType.RSASSA_PSS, mdAlgs.next())));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static boolean runTest(Test test) {
|
|
System.out.println(test);
|
|
try {
|
|
// Generate all private/public key pairs
|
|
PrivateKey[] privKeys = new PrivateKey[N];
|
|
PublicKey[] pubKeys = new PublicKey[N];
|
|
PublicKey[] anotherPubKeys = new PublicKey[N];
|
|
Signature signature;
|
|
KeyPairGenerator kpg;
|
|
if (test.provider != Provider.Default) {
|
|
signature = Signature.getInstance(test.sigAlg.name,
|
|
test.provider.name);
|
|
// try using the same provider first, if not, fallback
|
|
// to the first available impl
|
|
try {
|
|
kpg = KeyPairGenerator.getInstance(
|
|
test.keyAlg.name, test.provider.name);
|
|
} catch (NoSuchAlgorithmException nsae) {
|
|
kpg = KeyPairGenerator.getInstance(
|
|
test.keyAlg.name);
|
|
}
|
|
} else {
|
|
signature = Signature.getInstance(test.sigAlg.name);
|
|
kpg = KeyPairGenerator.getInstance(test.keyAlg.name);
|
|
}
|
|
if (test.sigParams != null) {
|
|
signature.setParameter(test.sigParams);
|
|
}
|
|
|
|
for (int j=0; j < N; j++) {
|
|
if (test.keySize != -1) {
|
|
kpg.initialize(test.keySize);
|
|
}
|
|
KeyPair kp = kpg.genKeyPair();
|
|
KeyPair anotherKp = kpg.genKeyPair();
|
|
privKeys[j] = kp.getPrivate();
|
|
pubKeys[j] = kp.getPublic();
|
|
anotherPubKeys[j] = anotherKp.getPublic();
|
|
|
|
if (Arrays.equals(pubKeys[j].getEncoded(),
|
|
anotherPubKeys[j].getEncoded())) {
|
|
System.out.println("Failed: it should not get "
|
|
+ "the same pair of public key");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Create a chain of signed objects
|
|
SignedObject[] objects = new SignedObject[N];
|
|
objects[0] = new SignedObject(str, privKeys[0], signature);
|
|
for (int j = 1; j < N; j++) {
|
|
objects[j] = new SignedObject(objects[j - 1], privKeys[j],
|
|
signature);
|
|
}
|
|
|
|
// Verify the chain
|
|
int n = objects.length - 1;
|
|
SignedObject object = objects[n];
|
|
do {
|
|
if (!object.verify(pubKeys[n], signature)) {
|
|
System.out.println("Failed: verification failed, n = " + n);
|
|
return false;
|
|
}
|
|
if (object.verify(anotherPubKeys[n], signature)) {
|
|
System.out.println("Failed: verification should not "
|
|
+ "succeed with wrong public key, n = " + n);
|
|
return false;
|
|
}
|
|
|
|
object = (SignedObject) object.getObject();
|
|
n--;
|
|
} while (n > 0);
|
|
|
|
System.out.println("signed data: " + object.getObject());
|
|
if (!str.equals(object.getObject())) {
|
|
System.out.println("Failed: signed data is not equal to "
|
|
+ "original one");
|
|
return false;
|
|
}
|
|
|
|
System.out.println("Test passed");
|
|
return true;
|
|
} catch (NoSuchProviderException nspe) {
|
|
if (test.provider == Provider.SunMSCAPI
|
|
&& !System.getProperty("os.name").startsWith("Windows")) {
|
|
System.out.println("SunMSCAPI is available only on Windows: "
|
|
+ nspe);
|
|
return true;
|
|
}
|
|
System.out.println("Unexpected exception: " + nspe);
|
|
return false;
|
|
} catch (Exception e) {
|
|
System.out.println("Unexpected exception: " + e);
|
|
e.printStackTrace(System.out);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|