/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package libcore.java.security;

import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;

/**
 * Prints a list of all algorithms provided by security providers.  Intended to be run
 * via vogar as part of the algorithm documentation update process.
 * <p>
 * {@code vogar libcore/tools/src/java/libcore/java/security/ListProviders.java}
 */
public class ListProviders {

    private static final boolean SHOW_PROVIDER = false;

    // These algorithms were previously provided, but now are aliases for a different
    // algorithm.  For documentation purposes, we want to continue having them show up
    // as supported.
    private static final Set<String> KNOWN_ALIASES = new TreeSet<>(Arrays.asList(new String[]{
            "Alg.Alias.Signature.DSA",
            "Alg.Alias.Signature.DSAwithSHA1",
            "Alg.Alias.Signature.ECDSA",
            "Alg.Alias.Signature.ECDSAwithSHA1",
    }));

    // Ciphers come in algorithm/mode/padding combinations, and not all combinations are explicitly
    // registered by the providers (sometimes only the base algorithm is registered).  While there
    // is a mechanism for providers to specify which modes and/or paddings are supported for a
    // given algorithm, none of our providers use it.  Thus, when a base algorithm is seen, all
    // combinations of modes and paddings will be tried to see which ones are supported.
    private static final Set<String> CIPHER_MODES = new TreeSet<>(Arrays.asList(new String[]{
            "CBC",
            "CFB",
            "CTR",
            "CTS",
            "ECB",
            "GCM",
            "OFB",
            "NONE",
    }));
    private static final Set<String> CIPHER_PADDINGS = new TreeSet<>(Arrays.asList(new String[]{
            "NoPadding",
            "OAEPPadding",
            "OAEPwithSHA-1andMGF1Padding",
            "OAEPwithSHA-224andMGF1Padding",
            "OAEPwithSHA-256andMGF1Padding",
            "OAEPwithSHA-384andMGF1Padding",
            "OAEPwithSHA-512andMGF1Padding",
            "PKCS1Padding",
            "PKCS5Padding",
            "ISO10126Padding",
    }));

    private static void print(Provider p, String type, String algorithm) {
        System.out.println((SHOW_PROVIDER ? p.getName() + ": " : "") + type + " " + algorithm);
    }

    public static void main(String[] argv) {
        System.out.println("BEGIN ALGORITHM LIST");
        for (Provider p : Security.getProviders()) {
            Set<Provider.Service> services = new TreeSet<Provider.Service>(
                    new Comparator<Provider.Service>() {
                        public int compare(Provider.Service a, Provider.Service b) {
                            int typeCompare = a.getType().compareTo(b.getType());
                            if (typeCompare != 0) {
                                return typeCompare;
                            }
                            return a.getAlgorithm().compareTo(b.getAlgorithm());
                        }
                    });
            services.addAll(p.getServices());
            for (Provider.Service s : services) {
                if (s.getType().equals("Cipher") && s.getAlgorithm().startsWith("PBE")) {
                    // PBE ciphers are a mess and generally don't do anything but delegate
                    // to the underlying cipher.  We don't want to document them.
                    continue;
                }
                if (s.getType().equals("Cipher") && s.getAlgorithm().indexOf('/') == -1) {
                    for (String mode : CIPHER_MODES) {
                        for (String padding : CIPHER_PADDINGS) {
                            try {
                                String name = s.getAlgorithm() + "/" + mode + "/" + padding;
                                Cipher.getInstance(name, p);
                                print(p, s.getType(), name);
                            } catch (NoSuchAlgorithmException
                                    |NoSuchPaddingException
                                    |IllegalArgumentException e) {
                                // This combination doesn't work
                            }
                        }
                    }
                } else {
                    print(p, s.getType(), s.getAlgorithm());
                }
            }
            for (String alias : KNOWN_ALIASES) {
                if (p.containsKey(alias)) {
                    String[] elements = alias.split("\\.");  // Split takes a regex
                    print(p, elements[2], elements[3]);
                }
            }
        }
        System.out.println("END ALGORITHM LIST");
    }
}