1 /*
   2  * Copyright (c) 2015, 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 8056174
  27  * @summary Make sure JarSigner impl conforms to spec
  28  * @library /test/lib
  29  * @modules java.base/sun.security.tools.keytool
  30  *          java.base/sun.security.provider.certpath
  31  *          jdk.jartool
  32  *          jdk.crypto.ec
  33  * @build jdk.test.lib.util.JarUtils
  34  * @run main Spec
  35  */
  36 
  37 import com.sun.jarsigner.ContentSigner;
  38 import com.sun.jarsigner.ContentSignerParameters;
  39 import jdk.security.jarsigner.JarSigner;
  40 import jdk.test.lib.util.JarUtils;
  41 import sun.security.provider.certpath.X509CertPath;
  42 
  43 import java.io.File;
  44 import java.io.IOException;
  45 import java.net.URI;
  46 import java.nio.file.Files;
  47 import java.nio.file.Paths;
  48 import java.security.*;
  49 import java.security.cert.CertPath;
  50 import java.security.cert.CertificateException;
  51 import java.security.cert.CertificateFactory;
  52 import java.util.Arrays;
  53 import java.util.Collections;
  54 import java.util.function.BiConsumer;
  55 
  56 public class Spec {
  57 
  58     public static void main(String[] args) throws Exception {
  59 
  60         // Prepares raw file
  61         Files.write(Paths.get("a"), "a".getBytes());
  62 
  63         // Pack
  64         JarUtils.createJar("a.jar", "a");
  65 
  66         // Prepare a keystore
  67         sun.security.tools.keytool.Main.main(
  68                 ("-keystore ks -storepass changeit -keypass changeit -dname" +
  69                         " CN=RSA -alias r -genkeypair -keyalg rsa").split(" "));
  70         sun.security.tools.keytool.Main.main(
  71                 ("-keystore ks -storepass changeit -keypass changeit -dname" +
  72                         " CN=DSA -alias d -genkeypair -keyalg dsa").split(" "));
  73 
  74         char[] pass = "changeit".toCharArray();
  75 
  76         KeyStore ks = KeyStore.getInstance(
  77                 new File("ks"), pass);
  78         PrivateKey pkr = (PrivateKey)ks.getKey("r", pass);
  79         PrivateKey pkd = (PrivateKey)ks.getKey("d", pass);
  80         CertPath cp = CertificateFactory.getInstance("X.509")
  81                 .generateCertPath(Arrays.asList(ks.getCertificateChain("r")));
  82 
  83         Provider sun = Security.getProvider("SUN");
  84 
  85         // throws
  86         npe(()->new JarSigner.Builder(null));
  87         npe(()->new JarSigner.Builder(null, cp));
  88         iae(()->new JarSigner.Builder(
  89                 pkr, new X509CertPath(Collections.emptyList())));
  90         iae(()->new JarSigner.Builder(pkd, cp));    // unmatched certs alg
  91 
  92         JarSigner.Builder b1 = new JarSigner.Builder(pkr, cp);
  93 
  94         npe(()->b1.digestAlgorithm(null));
  95         nsae(()->b1.digestAlgorithm("HAHA"));
  96         b1.digestAlgorithm("SHA-256");
  97 
  98         npe(()->b1.digestAlgorithm("SHA-256", null));
  99         npe(()->b1.digestAlgorithm(null, sun));
 100         nsae(()->b1.digestAlgorithm("HAHA", sun));
 101         b1.digestAlgorithm("SHA-256", sun);
 102 
 103         npe(()->b1.signatureAlgorithm(null));
 104         nsae(()->b1.signatureAlgorithm("HAHAwithHEHE"));
 105         iae(()->b1.signatureAlgorithm("SHA256withECDSA"));
 106 
 107         npe(()->b1.signatureAlgorithm(null, sun));
 108         npe(()->b1.signatureAlgorithm("SHA256withRSA", null));
 109         nsae(()->b1.signatureAlgorithm("HAHAwithHEHE", sun));
 110         iae(()->b1.signatureAlgorithm("SHA256withDSA", sun));
 111 
 112         npe(()->b1.tsa(null));
 113 
 114         npe(()->b1.signerName(null));
 115         iae(()->b1.signerName(""));
 116         iae(()->b1.signerName("123456789"));
 117         iae(()->b1.signerName("a+b"));
 118 
 119         npe(()->b1.setProperty(null, ""));
 120         uoe(()->b1.setProperty("what", ""));
 121         npe(()->b1.setProperty("tsadigestalg", null));
 122         iae(()->b1.setProperty("tsadigestalg", "HAHA"));
 123         npe(()->b1.setProperty("tsapolicyid", null));
 124         npe(()->b1.setProperty("internalsf", null));
 125         iae(()->b1.setProperty("internalsf", "Hello"));
 126         npe(()->b1.setProperty("sectionsonly", null));
 127         iae(()->b1.setProperty("sectionsonly", "OK"));
 128         npe(()->b1.setProperty("altsigner", null));
 129         npe(()->b1.eventHandler(null));
 130 
 131         // default values
 132         JarSigner.Builder b2 = new JarSigner.Builder(pkr, cp);
 133         JarSigner js2 = b2.build();
 134 
 135         assertTrue(js2.getDigestAlgorithm().equals(
 136                 JarSigner.Builder.getDefaultDigestAlgorithm()));
 137         assertTrue(js2.getSignatureAlgorithm().equals(
 138                 JarSigner.Builder.getDefaultSignatureAlgorithm(pkr)));
 139         assertTrue(js2.getTsa() == null);
 140         assertTrue(js2.getSignerName().equals("SIGNER"));
 141         assertTrue(js2.getProperty("tsadigestalg").equals(
 142                 JarSigner.Builder.getDefaultDigestAlgorithm()));
 143         assertTrue(js2.getProperty("tsapolicyid") == null);
 144         assertTrue(js2.getProperty("internalsf").equals("false"));
 145         assertTrue(js2.getProperty("sectionsonly").equals("false"));
 146         assertTrue(js2.getProperty("altsigner") == null);
 147         uoe(()->js2.getProperty("invalid"));
 148 
 149         // default values
 150         BiConsumer<String,String> myeh = (a,s)->{};
 151         URI tsa = new URI("https://tsa.com");
 152 
 153         JarSigner.Builder b3 = new JarSigner.Builder(pkr, cp)
 154                 .digestAlgorithm("SHA-1")
 155                 .signatureAlgorithm("SHA1withRSA")
 156                 .signerName("Duke")
 157                 .tsa(tsa)
 158                 .setProperty("tsadigestalg", "SHA-512")
 159                 .setProperty("tsapolicyid", "1.2.3.4")
 160                 .setProperty("internalsf", "true")
 161                 .setProperty("sectionsonly", "true")
 162                 .setProperty("altsigner", "MyContentSigner")
 163                 .eventHandler(myeh);
 164         JarSigner js3 = b3.build();
 165 
 166         assertTrue(js3.getDigestAlgorithm().equals("SHA-1"));
 167         assertTrue(js3.getSignatureAlgorithm().equals("SHA1withRSA"));
 168         assertTrue(js3.getTsa().equals(tsa));
 169         assertTrue(js3.getSignerName().equals("DUKE"));
 170         assertTrue(js3.getProperty("tsadigestalg").equals("SHA-512"));
 171         assertTrue(js3.getProperty("tsapolicyid").equals("1.2.3.4"));
 172         assertTrue(js3.getProperty("internalsf").equals("true"));
 173         assertTrue(js3.getProperty("sectionsonly").equals("true"));
 174         assertTrue(js3.getProperty("altsigner").equals("MyContentSigner"));
 175         assertTrue(js3.getProperty("altsignerpath") == null);
 176 
 177         assertTrue(JarSigner.Builder.getDefaultDigestAlgorithm().equals("SHA-256"));
 178 
 179         // Calculating large DSA and RSA keys are too slow.
 180         KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
 181         kpg.initialize(1024);
 182         assertTrue(JarSigner.Builder
 183                 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate())
 184                     .equals("SHA256withRSA"));
 185 
 186         kpg = KeyPairGenerator.getInstance("DSA");
 187         kpg.initialize(1024);
 188         assertTrue(JarSigner.Builder
 189                 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate())
 190                 .equals("SHA256withDSA"));
 191 
 192         kpg = KeyPairGenerator.getInstance("EC");
 193         kpg.initialize(192);
 194         assertTrue(JarSigner.Builder
 195                 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate())
 196                 .equals("SHA256withECDSA"));
 197         kpg.initialize(384);
 198         assertTrue(JarSigner.Builder
 199                 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate())
 200                 .equals("SHA384withECDSA"));
 201         kpg.initialize(571);
 202         assertTrue(JarSigner.Builder
 203                 .getDefaultSignatureAlgorithm(kpg.generateKeyPair().getPrivate())
 204                 .equals("SHA512withECDSA"));
 205     }
 206 
 207     interface RunnableWithException {
 208         void run() throws Exception;
 209     }
 210 
 211     static void uoe(RunnableWithException r) throws Exception {
 212         checkException(r, UnsupportedOperationException.class);
 213     }
 214 
 215     static void nsae(RunnableWithException r) throws Exception {
 216         checkException(r, NoSuchAlgorithmException.class);
 217     }
 218 
 219     static void npe(RunnableWithException r) throws Exception {
 220         checkException(r, NullPointerException.class);
 221     }
 222 
 223     static void iae(RunnableWithException r) throws Exception {
 224         checkException(r, IllegalArgumentException.class);
 225     }
 226 
 227     static void checkException(RunnableWithException r, Class ex)
 228             throws Exception {
 229         try {
 230             r.run();
 231         } catch (Exception e) {
 232             if (ex.isAssignableFrom(e.getClass())) {
 233                 return;
 234             }
 235             throw e;
 236         }
 237         throw new Exception("No exception thrown");
 238     }
 239 
 240     static void assertTrue(boolean x) throws Exception {
 241         if (!x) throw new Exception("Not true");
 242     }
 243 
 244     static class MyContentSigner extends ContentSigner {
 245         @Override
 246         public byte[] generateSignedData(
 247                 ContentSignerParameters parameters,
 248                 boolean omitContent,
 249                 boolean applyTimestamp) throws NoSuchAlgorithmException,
 250                 CertificateException, IOException {
 251             return new byte[0];
 252         }
 253     }
 254 }