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