/*
 * Copyright (c) 2020, 2022, 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.
 */

/*
 * @test
 * @bug 8242184 8242068 8267319
 * @summary keytool and jarsigner for all algorithms
 * @library /test/lib
 * @modules java.base/sun.security.util
 * @run testng/timeout=300 GenerateAll
 */

import jdk.test.lib.SecurityTools;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.security.DerUtils;
import jdk.test.lib.util.JarUtils;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;

import static sun.security.util.KnownOIDs.*;

import sun.security.util.KnownOIDs;
import sun.security.util.ObjectIdentifier;
import sun.security.util.SignatureUtil;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.util.Base64;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;

public class GenerateAll {

    @BeforeTest
    public void beforeTest() throws Exception {
        // Create a CA in a separate keystore
        kt("-genkeypair -alias ca -dname CN=CA -keyalg ec -ext bc -keystore ca");
        kt("-export -alias ca -file ca.crt -rfc -keystore ca");

        // Import CA cert to user keystore so we can import reply later
        kt("-import -alias root -file ca.crt -noprompt");

        JarUtils.createJarFile(Path.of("a.jar"), Path.of("."), Path.of("ks"));
    }

    @DataProvider(name = "eddsa")
    public Object[][] eddsaData() {
        return new Object[][]{
                {"eddsa", null, Ed25519},
                {"eddsa", "eddsa", Ed25519},
                {"eddsa", "ed25519", Ed25519},
                {"eddsa", "ed448", null},
                {"ed25519", null, Ed25519},
                {"ed25519", "eddsa", Ed25519},
                {"ed25519", "ed25519", Ed25519},
                {"ed25519", "ed448", null},
                {"ed448", null, Ed448},
                {"ed448", "eddsa", Ed448},
                {"ed448", "ed25519", null},
                {"ed448", "ed448", Ed448},
        };
    }

    /**
     * Test various names of EdDSA
     * @param keyAlg keytool -keyalg
     * @param sigAlg (optional) keytool -sigalg
     * @param expected expected algorithm of generated signature
     */
    @Test(dataProvider = "eddsa")
    public void eddsaTest(String keyAlg, String sigAlg, KnownOIDs expected)
            throws Exception {
        String alias = keyAlg + "-" + sigAlg;
        OutputAnalyzer oa = kt0("-genkeypair -alias " + alias
                + " -dname CN=" + alias + " -keyalg " + keyAlg
                + (sigAlg == null ? "" : (" -sigalg " + sigAlg)));
        if (expected == null) {
            oa.shouldNotHaveExitValue(0);
        } else {
            oa.shouldHaveExitValue(0);
            kt("-alias " + alias + " -export -file " + alias + ".crt");
            byte[] crt = Files.readAllBytes(Path.of(alias + ".crt"));
            DerUtils.checkAlg(crt, "020", expected);     // tbsCertificate.signature
            DerUtils.checkAlg(crt, "0600", expected);    // tbsCertificate.subjectPublicKeyInfo.algorithm
            DerUtils.checkAlg(crt, "10", expected);      // signatureAlgorithm
        }
    }

    @DataProvider(name = "all")
    public Object[][] dataProvider() {
        return new Object[][]{
                {"rsa", "rsa", null, "RSA", SHA_384, SHA384withRSA},
                {"dsa", "dsa", null, "DSA", SHA_256, SHA256withDSA},
                {"r", "rsa", "rsassa-pss", "RSA", SHA_384, RSASSA_PSS},
                {"pss", "rsassa-pss", null, "RSA", SHA_384, RSASSA_PSS},
                {"ec", "ec", null, "EC", SHA_384, SHA384withECDSA},
                {"ed25519", "ed25519", null, "EC", SHA_512, Ed25519},
                {"ed448", "ed448", null, "EC", SHAKE256_LEN, Ed448},
        };
    }

    /**
     * Testing all algorithms.
     * @param alias alias
     * @param keyAlg keytool -keyalg
     * @param sigAlg (optional) keytool -sigalg
     * @param ext block extension inside signed JAR
     * @param expDigAlg expected digAlg in PKCS7 SignerInfo
     * @param expEncAlg expected encAlg in PKCS7 SignerInfo
     */
    @Test(dataProvider = "all")
    public void test(String alias, String keyAlg, String sigAlg, String ext,
                     KnownOIDs expDigAlg, KnownOIDs expEncAlg) throws Throwable {

        char[] pass = "changeit".toCharArray();

        // If no sigAlg, derive automatically
        String extra = sigAlg == null ? "" : (" -sigalg " + sigAlg);

        // gen
        kt("-genkeypair -alias " + alias + " -dname CN=" + alias
                + " -keyalg " + keyAlg + extra);
        kt("-export -alias " + alias + " -rfc -file " + alias + ".self");

        // req
        kt("-certreq -alias " + alias + " -file " + alias + ".req" + extra);
        kt("-printcertreq -file " + alias + ".req");

        // gencert
        kt("-gencert -alias ca -infile " + alias
                + ".req -outfile " + alias + ".crt -rfc -keystore ca");
        kt("-printcert -file " + alias + ".crt");
        kt("-importcert -alias " + alias + " -file " + alias + ".crt");

        // crl
        kt("-gencrl -alias " + alias + " -id 0 -rfc -file "
                + alias + ".crl" + extra);
        kt("-printcrl -file " + alias + ".crl")
                .shouldContain("Verified by " + alias);

        // sign
        js("a.jar " + alias + extra);

        // check data
        KeyStore ks = KeyStore.getInstance(new File("ks"), pass);
        PrivateKey pk = (PrivateKey)ks.getKey(alias, pass);

        if (sigAlg == null) {
            sigAlg = SignatureUtil.getDefaultSigAlgForKey(pk);
        }

        KnownOIDs sigOID = KnownOIDs.findMatch(sigAlg);
        KnownOIDs keyOID = KnownOIDs.findMatch(keyAlg);

        byte[] crt = read(alias + ".self");
        DerUtils.checkAlg(crt, "020", sigOID);  // tbsCertificate.signature
        DerUtils.checkAlg(crt, "0600", keyOID); // tbsCertificate.subjectPublicKeyInfo.algorithm
        assertEquals(
                DerUtils.innerDerValue(crt, "02"),   // tbsCertificate.signature
                DerUtils.innerDerValue(crt, "1"));   // signatureAlgorithm

        byte[] req = read(alias + ".req");
        DerUtils.checkAlg(req, "10", sigOID);   // signatureAlgorithm
        DerUtils.checkAlg(req, "0200", keyOID); // certificationRequestInfo.subjectPKInfo.algorithm

        byte[] crl = read(alias + ".crl");
        DerUtils.checkAlg(crl, "000", sigOID);  // tbsCertList.signature
        assertEquals(
                DerUtils.innerDerValue(crl, "00"),   // tbsCertList.signature
                DerUtils.innerDerValue(crl, "1"));   // signatureAlgorithm

        try (JarFile jf = new JarFile("a.jar")) {
            JarEntry je = jf.getJarEntry(
                    "META-INF/" + alias.toUpperCase() + "." + ext);
            byte[] p7 = jf.getInputStream(je).readAllBytes();
            // SignerInfo.digestAlgorithm
            DerUtils.checkAlg(p7, "104020", expDigAlg);
            // SignerInfo.signatureAlgorithm
            if (DerUtils.innerDerValue(p7, "10403").isContextSpecific()) {
                // SignerInfo has signedAttributes at 104030
                DerUtils.checkAlg(p7, "104040", expEncAlg);
            } else {
                DerUtils.checkAlg(p7, "104030", expEncAlg);
            }
        }
    }

    @AfterTest
    public void afterTest() throws Exception {
        js("-verify a.jar -verbose -certs");
    }

    static byte[] read(String f) throws IOException {
        try (var v = Files.lines(Path.of(f))) {
            return Base64.getDecoder().decode(v.filter(s -> !s.startsWith("-----"))
                    .collect(Collectors.joining("")));
        }
    }

    static OutputAnalyzer kt(String arg) throws Exception {
        return kt0(arg).shouldHaveExitValue(0);
    }

    static OutputAnalyzer kt0(String arg) throws Exception {
        return SecurityTools.keytool("-keystore ks -storepass changeit " + arg);
    }

    static OutputAnalyzer js(String arg) throws Exception {
        return SecurityTools.jarsigner("-keystore ks -storepass changeit " + arg)
                .shouldHaveExitValue(0);
    }
}
