6870812: enhance security tools to use ECC algorithms
Reviewed-by: vinnie, mullan
--- a/jdk/src/share/classes/java/util/jar/JarFile.java Tue Oct 20 09:51:28 2009 -0700
+++ b/jdk/src/share/classes/java/util/jar/JarFile.java Wed Oct 21 08:17:35 2009 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc. 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
@@ -297,6 +297,7 @@
String name = names[i].toUpperCase(Locale.ENGLISH);
if (name.endsWith(".DSA") ||
name.endsWith(".RSA") ||
+ name.endsWith(".EC") ||
name.endsWith(".SF")) {
// Assume since we found a signature-related file
// that the jar is signed and that we therefore
--- a/jdk/src/share/classes/java/util/jar/JarVerifier.java Tue Oct 20 09:51:28 2009 -0700
+++ b/jdk/src/share/classes/java/util/jar/JarVerifier.java Wed Oct 21 08:17:35 2009 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc. 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
@@ -50,7 +50,7 @@
private Hashtable verifiedSigners;
/* a table mapping names to code signers, for jar entries that have
- passed the .SF/.DSA -> MANIFEST check */
+ passed the .SF/.DSA/.EC -> MANIFEST check */
private Hashtable sigFileSigners;
/* a hash table to hold .SF bytes */
@@ -111,7 +111,7 @@
/*
* Assumptions:
* 1. The manifest should be the first entry in the META-INF directory.
- * 2. The .SF/.DSA files follow the manifest, before any normal entries
+ * 2. The .SF/.DSA/.EC files follow the manifest, before any normal entries
* 3. Any of the following will throw a SecurityException:
* a. digest mismatch between a manifest section and
* the SF section.
@@ -129,7 +129,7 @@
}
if (SignatureFileVerifier.isBlockOrSF(uname)) {
- /* We parse only DSA or RSA PKCS7 blocks. */
+ /* We parse only DSA, RSA or EC PKCS7 blocks. */
parsingBlockOrSF = true;
baos.reset();
mev.setEntry(null, je);
--- a/jdk/src/share/classes/sun/security/jca/Providers.java Tue Oct 20 09:51:28 2009 -0700
+++ b/jdk/src/share/classes/sun/security/jca/Providers.java Wed Oct 21 08:17:35 2009 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc. 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
@@ -86,6 +86,9 @@
private static final String[] jarVerificationProviders = {
"sun.security.provider.Sun",
"sun.security.rsa.SunRsaSign",
+ // Note: SunEC *is* in a signed JAR file, but it's not signed
+ // by EC itself. So it's still safe to be listed here.
+ "sun.security.ec.SunEC",
BACKUP_PROVIDER_CLASSNAME,
};
--- a/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java Tue Oct 20 09:51:28 2009 -0700
+++ b/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java Wed Oct 21 08:17:35 2009 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1996-2009 Sun Microsystems, Inc. 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
@@ -286,8 +286,6 @@
}
String digestAlgname = getDigestAlgorithmId().getName();
- if (digestAlgname.equalsIgnoreCase("SHA"))
- digestAlgname = "SHA1";
byte[] dataSigned;
@@ -337,9 +335,12 @@
String encryptionAlgname =
getDigestEncryptionAlgorithmId().getName();
- if (encryptionAlgname.equalsIgnoreCase("SHA1withDSA"))
- encryptionAlgname = "DSA";
- String algname = digestAlgname + "with" + encryptionAlgname;
+ // Workaround: sometimes the encryptionAlgname is actually
+ // a signature name
+ String tmp = AlgorithmId.getEncAlgFromSigAlg(encryptionAlgname);
+ if (tmp != null) encryptionAlgname = tmp;
+ String algname = AlgorithmId.makeSigAlg(
+ digestAlgname, encryptionAlgname);
Signature sig = Signature.getInstance(algname);
X509Certificate cert = getCertificate(block);
--- a/jdk/src/share/classes/sun/security/tools/JarSigner.java Tue Oct 20 09:51:28 2009 -0700
+++ b/jdk/src/share/classes/sun/security/tools/JarSigner.java Wed Oct 21 08:17:35 2009 +0800
@@ -1031,9 +1031,9 @@
}
if (sigfile.length() > 8) {
- sigfile = sigfile.substring(0, 8).toUpperCase();
+ sigfile = sigfile.substring(0, 8).toUpperCase(Locale.ENGLISH);
} else {
- sigfile = sigfile.toUpperCase();
+ sigfile = sigfile.toUpperCase(Locale.ENGLISH);
}
StringBuilder tmpSigFile = new StringBuilder(sigfile.length());
@@ -1083,8 +1083,8 @@
ZipOutputStream zos = new ZipOutputStream(ps);
/* First guess at what they might be - we don't xclude RSA ones. */
- String sfFilename = (META_INF + sigfile + ".SF").toUpperCase();
- String bkFilename = (META_INF + sigfile + ".DSA").toUpperCase();
+ String sfFilename = (META_INF + sigfile + ".SF").toUpperCase(Locale.ENGLISH);
+ String bkFilename = (META_INF + sigfile + ".DSA").toUpperCase(Locale.ENGLISH);
Manifest manifest = new Manifest();
Map<String,Attributes> mfEntries = manifest.getEntries();
@@ -1447,9 +1447,10 @@
* . META-INF/*.SF
* . META-INF/*.DSA
* . META-INF/*.RSA
+ * . META-INF/*.EC
*/
private boolean signatureRelated(String name) {
- String ucName = name.toUpperCase();
+ String ucName = name.toUpperCase(Locale.ENGLISH);
if (ucName.equals(JarFile.MANIFEST_NAME) ||
ucName.equals(META_INF) ||
(ucName.startsWith(SIG_PREFIX) &&
@@ -1459,7 +1460,7 @@
if (ucName.startsWith(META_INF) &&
SignatureFileVerifier.isBlockOrSF(ucName)) {
- // .SF/.DSA/.RSA files in META-INF subdirs
+ // .SF/.DSA/.RSA/.EC files in META-INF subdirs
// are not considered signature-related
return (ucName.indexOf("/") == ucName.lastIndexOf("/"));
}
@@ -2227,7 +2228,6 @@
}
BigInteger serial = certChain[0].getSerialNumber();
- String digestAlgorithm;
String signatureAlgorithm;
String keyAlgorithm = privateKey.getAlgorithm();
/*
@@ -2237,22 +2237,24 @@
if (sigalg == null) {
if (keyAlgorithm.equalsIgnoreCase("DSA"))
- digestAlgorithm = "SHA1";
+ signatureAlgorithm = "SHA1withDSA";
else if (keyAlgorithm.equalsIgnoreCase("RSA"))
- digestAlgorithm = "SHA256";
- else {
+ signatureAlgorithm = "SHA256withRSA";
+ else if (keyAlgorithm.equalsIgnoreCase("EC"))
+ signatureAlgorithm = "SHA256withECDSA";
+ else
throw new RuntimeException("private key is not a DSA or "
+ "RSA key");
- }
- signatureAlgorithm = digestAlgorithm + "with" + keyAlgorithm;
} else {
signatureAlgorithm = sigalg;
}
// check common invalid key/signature algorithm combinations
- String sigAlgUpperCase = signatureAlgorithm.toUpperCase();
+ String sigAlgUpperCase = signatureAlgorithm.toUpperCase(Locale.ENGLISH);
if ((sigAlgUpperCase.endsWith("WITHRSA") &&
!keyAlgorithm.equalsIgnoreCase("RSA")) ||
+ (sigAlgUpperCase.endsWith("WITHECDSA") &&
+ !keyAlgorithm.equalsIgnoreCase("EC")) ||
(sigAlgUpperCase.endsWith("WITHDSA") &&
!keyAlgorithm.equalsIgnoreCase("DSA"))) {
throw new SignatureException
--- a/jdk/src/share/classes/sun/security/tools/KeyTool.java Tue Oct 20 09:51:28 2009 -0700
+++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java Wed Oct 21 08:17:35 2009 +0800
@@ -1407,7 +1407,7 @@
} else if ("RSA".equalsIgnoreCase(keyAlgName)) {
return "SHA256WithRSA";
} else if ("EC".equalsIgnoreCase(keyAlgName)) {
- return "SHA1withECDSA";
+ return "SHA256withECDSA";
} else {
throw new Exception(rb.getString
("Cannot derive signature algorithm"));
--- a/jdk/src/share/classes/sun/security/tools/TimestampedSigner.java Tue Oct 20 09:51:28 2009 -0700
+++ b/jdk/src/share/classes/sun/security/tools/TimestampedSigner.java Wed Oct 21 08:17:35 2009 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2007-2009 Sun Microsystems, Inc. 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
@@ -159,18 +159,10 @@
// "<digest>with<encryption>"
// or "<digest>with<encryption>and<mgf>"
String signatureAlgorithm = parameters.getSignatureAlgorithm();
- String digestAlgorithm = null;
- String keyAlgorithm = null;
- int with = signatureAlgorithm.indexOf("with");
- if (with > 0) {
- digestAlgorithm = signatureAlgorithm.substring(0, with);
- int and = signatureAlgorithm.indexOf("and", with + 4);
- if (and > 0) {
- keyAlgorithm = signatureAlgorithm.substring(with + 4, and);
- } else {
- keyAlgorithm = signatureAlgorithm.substring(with + 4);
- }
- }
+ String keyAlgorithm =
+ AlgorithmId.getEncAlgFromSigAlg(signatureAlgorithm);
+ String digestAlgorithm =
+ AlgorithmId.getDigAlgFromSigAlg(signatureAlgorithm);
AlgorithmId digestAlgorithmId = AlgorithmId.get(digestAlgorithm);
// Examine signer's certificate
--- a/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java Tue Oct 20 09:51:28 2009 -0700
+++ b/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java Wed Oct 21 08:17:35 2009 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2009 Sun Microsystems, Inc. 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
@@ -54,14 +54,14 @@
("-DIGEST-" + ManifestDigester.MF_MAIN_ATTRS).toUpperCase
(Locale.ENGLISH);
- /** the PKCS7 block for this .DSA/.RSA file */
+ /** the PKCS7 block for this .DSA/.RSA/.EC file */
private PKCS7 block;
/** the raw bytes of the .SF file */
private byte sfBytes[];
/** the name of the signature block file, uppercased and without
- * the extension (.DSA/.RSA)
+ * the extension (.DSA/.RSA/.EC)
*/
private String name;
@@ -80,7 +80,7 @@
/**
* Create the named SignatureFileVerifier.
*
- * @param name the name of the signature block file (.DSA/.RSA)
+ * @param name the name of the signature block file (.DSA/.RSA/.EC)
*
* @param rawBytes the raw bytes of the signature block file
*/
@@ -148,7 +148,8 @@
*/
public static boolean isBlockOrSF(String s) {
// we currently only support DSA and RSA PKCS7 blocks
- if (s.endsWith(".SF") || s.endsWith(".DSA") || s.endsWith(".RSA")) {
+ if (s.endsWith(".SF") || s.endsWith(".DSA") ||
+ s.endsWith(".RSA") || s.endsWith(".EC")) {
return true;
}
return false;
--- a/jdk/src/share/classes/sun/security/x509/AlgorithmId.java Tue Oct 20 09:51:28 2009 -0700
+++ b/jdk/src/share/classes/sun/security/x509/AlgorithmId.java Wed Oct 21 08:17:35 2009 +0800
@@ -883,4 +883,53 @@
nameTable.put(pbeWithSHA1AndDESede_oid, "PBEWithSHA1AndDESede");
nameTable.put(pbeWithSHA1AndRC2_40_oid, "PBEWithSHA1AndRC2_40");
}
+
+ /**
+ * Creates a signature algorithm name from a digest algorithm
+ * name and a encryption algorithm name.
+ */
+ public static String makeSigAlg(String digAlg, String encAlg) {
+ digAlg = digAlg.replace("-", "").toUpperCase(Locale.ENGLISH);
+ if (digAlg.equalsIgnoreCase("SHA")) digAlg = "SHA1";
+
+ encAlg = encAlg.toUpperCase(Locale.ENGLISH);
+ if (encAlg.equals("EC")) encAlg = "ECDSA";
+
+ return digAlg + "with" + encAlg;
+ }
+
+ /**
+ * Extracts the encryption algorithm name from a signature
+ * algorithm name.
+ */
+ public static String getEncAlgFromSigAlg(String signatureAlgorithm) {
+ signatureAlgorithm = signatureAlgorithm.toUpperCase(Locale.ENGLISH);
+ int with = signatureAlgorithm.indexOf("WITH");
+ String keyAlgorithm = null;
+ if (with > 0) {
+ int and = signatureAlgorithm.indexOf("AND", with + 4);
+ if (and > 0) {
+ keyAlgorithm = signatureAlgorithm.substring(with + 4, and);
+ } else {
+ keyAlgorithm = signatureAlgorithm.substring(with + 4);
+ }
+ if (keyAlgorithm.equalsIgnoreCase("ECDSA")) {
+ keyAlgorithm = "EC";
+ }
+ }
+ return keyAlgorithm;
+ }
+
+ /**
+ * Extracts the digest algorithm name from a signature
+ * algorithm name.
+ */
+ public static String getDigAlgFromSigAlg(String signatureAlgorithm) {
+ signatureAlgorithm = signatureAlgorithm.toUpperCase(Locale.ENGLISH);
+ int with = signatureAlgorithm.indexOf("WITH");
+ if (with > 0) {
+ return signatureAlgorithm.substring(0, with);
+ }
+ return null;
+ }
}
--- a/jdk/src/share/classes/sun/tools/jar/SignatureFile.java Tue Oct 20 09:51:28 2009 -0700
+++ b/jdk/src/share/classes/sun/tools/jar/SignatureFile.java Wed Oct 21 08:17:35 2009 +0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1996-2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1996-2009 Sun Microsystems, Inc. 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
@@ -34,6 +34,7 @@
import sun.misc.BASE64Decoder;
import sun.security.pkcs.*;
+import sun.security.x509.AlgorithmId;
/**
* <p>A signature file as defined in the <a
@@ -103,7 +104,7 @@
if (name.length() > 8 || name.indexOf('.') != -1) {
throw new JarException("invalid file name");
}
- rawName = name.toUpperCase();
+ rawName = name.toUpperCase(Locale.ENGLISH);
}
}
@@ -217,7 +218,8 @@
if (signatureBlock != null) {
SignerInfo info = signatureBlock.getSignerInfos()[0];
suffix = info.getDigestEncryptionAlgorithmId().getName();
- suffix = suffix.substring(suffix.length() - 3);
+ String temp = AlgorithmId.getEncAlgFromSigAlg(suffix);
+ if (temp != null) suffix = temp;
}
return "META-INF/" + rawName + "." + suffix;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/ec.sh Wed Oct 21 08:17:35 2009 +0800
@@ -0,0 +1,73 @@
+#
+# Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# @test
+# @bug 6870812
+# @summary enhance security tools to use ECC algorithm
+#
+
+if [ "${TESTJAVA}" = "" ] ; then
+ JAVAC_CMD=`which javac`
+ TESTJAVA=`dirname $JAVAC_CMD`/..
+fi
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+ Windows_* )
+ FS="\\"
+ ;;
+ * )
+ FS="/"
+ ;;
+esac
+
+KS=ec.jks
+JFILE=ec.jar
+
+KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS"
+JAR=$TESTJAVA${FS}bin${FS}jar
+JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner
+
+rm $KS $JFILE
+echo A > A
+$JAR cvf $JFILE A
+
+$KT -alias a -dname CN=a -keyalg ec -genkey -validity 300 || exit 11
+$KT -alias b -dname CN=b -keyalg ec -genkey -validity 300 || exit 12
+$KT -alias c -dname CN=c -keyalg ec -genkey -validity 300 || exit 13
+$KT -alias x -dname CN=x -keyalg ec -genkey -validity 300 || exit 14
+
+$JARSIGNER -keystore $KS -storepass changeit $JFILE a -debug -strict || exit 21
+$JARSIGNER -keystore $KS -storepass changeit $JFILE b -debug -strict -sigalg SHA1withECDSA || exit 22
+$JARSIGNER -keystore $KS -storepass changeit $JFILE c -debug -strict -sigalg SHA512withECDSA || exit 23
+
+$JARSIGNER -keystore $KS -storepass changeit -verify $JFILE a -debug -strict || exit 31
+$JARSIGNER -keystore $KS -storepass changeit -verify $JFILE b -debug -strict || exit 32
+$JARSIGNER -keystore $KS -storepass changeit -verify $JFILE c -debug -strict || exit 33
+
+# Not signed by x, should exit with non-zero
+$JARSIGNER -keystore $KS -storepass changeit -verify $JFILE x -debug -strict && exit 34
+
+exit 0
+