/*
 * Copyright 2014 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 org.conscrypt;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.Signature;
import java.util.ArrayList;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;

/**
 * Provides a place where NativeCrypto can call back up to do Java language
 * calls to work on delegated key types from native code. Delegated keys are
 * usually backed by hardware so we don't have access directly to the private
 * key material. If it were a key where we can get to the private key, we
 * would not ever call into this class.
 *
 * @hide
 */
@Internal
public final class CryptoUpcalls {

    private CryptoUpcalls() {
    }

    private static boolean isOurProvider(Provider p) {
        return p.getClass().getPackage().equals(CryptoUpcalls.class.getPackage());
    }

    /**
     * Finds providers that are not us that provide the requested algorithms.
     */
    private static ArrayList<Provider> getExternalProviders(String algorithm) {
        ArrayList<Provider> providers = new ArrayList<>(1);
        for (Provider p : Security.getProviders(algorithm)) {
            if (!isOurProvider(p)) {
                providers.add(p);
            }
        }
        if (providers.isEmpty()) {
            System.err.println("Could not find external provider for algorithm: " + algorithm);
        }
        return providers;
    }

    public static byte[] rawSignDigestWithPrivateKey(PrivateKey javaKey, byte[] message) {
        // Get the raw signature algorithm for this key type.
        String algorithm;
        // Hint: Algorithm names come from:
        // http://docs.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html
        String keyAlgorithm = javaKey.getAlgorithm();
        if ("RSA".equals(keyAlgorithm)) {
            // IMPORTANT: Due to a platform bug, this will throw
            // NoSuchAlgorithmException
            // on Android 4.0.x and 4.1.x. Fixed in 4.2 and higher.
            // See https://android-review.googlesource.com/#/c/40352/
            algorithm = "NONEwithRSA";
        } else if ("EC".equals(keyAlgorithm)) {
            algorithm = "NONEwithECDSA";
        } else {
            throw new RuntimeException("Unexpected key type: " + javaKey.toString());
        }

        Signature signature;

        // Since this is a delegated key, we cannot handle providing a signature using this key.
        // Otherwise we wouldn't end up in this classs in the first place. The first step is to
        // try to get the most preferred provider as long as it isn't us.
        try {
            signature = Signature.getInstance(algorithm);
            signature.initSign(javaKey);

            // Ignore it if it points back to us.
            if (isOurProvider(signature.getProvider())) {
                signature = null;
            }
        } catch (NoSuchAlgorithmException e) {
            System.err.println("Unsupported signature algorithm: " + algorithm);
            return null;
        } catch (InvalidKeyException e) {
            System.err.println("Preferred provider doesn't support key:");
            e.printStackTrace();
            signature = null;
        }

        // If the preferred provider was us, fall back to trying to find the
        // first not-us provider that initializes correctly.
        if (signature == null) {
            ArrayList<Provider> providers = getExternalProviders("Signature." + algorithm);
            for (Provider p : providers) {
                try {
                    signature = Signature.getInstance(algorithm, p);
                    signature.initSign(javaKey);
                    break;
                } catch (NoSuchAlgorithmException | InvalidKeyException e) {
                    signature = null;
                }
            }
            if (signature == null) {
                System.err.println("Could not find provider for algorithm: " + algorithm);
                return null;
            }
        }

        // Sign the message.
        try {
            signature.update(message);
            return signature.sign();
        } catch (Exception e) {
            System.err.println("Exception while signing message with " + javaKey.getAlgorithm()
                    + " private key:");
            e.printStackTrace();
            return null;
        }
    }

    public static byte[] rsaDecryptWithPrivateKey(PrivateKey javaKey, int openSSLPadding,
            byte[] input) {
        String keyAlgorithm = javaKey.getAlgorithm();
        if (!"RSA".equals(keyAlgorithm)) {
            System.err.println("Unexpected key type: " + keyAlgorithm);
            return null;
        }

        String jcaPadding;
        switch (openSSLPadding) {
            case NativeConstants.RSA_PKCS1_PADDING:
                jcaPadding = "PKCS1Padding";
                break;
            case NativeConstants.RSA_NO_PADDING:
                jcaPadding = "NoPadding";
                break;
            case NativeConstants.RSA_PKCS1_OAEP_PADDING:
                jcaPadding = "OAEPPadding";
                break;
            default:
                System.err.println("Unsupported OpenSSL/BoringSSL padding: " + openSSLPadding);
                return null;
        }

        String transformation = "RSA/ECB/" + jcaPadding;
        Cipher c = null;

        // Since this is a delegated key, we cannot handle providing a cipher using this key.
        // Otherwise we wouldn't end up in this classs in the first place. The first step is to
        // try to get the most preferred provider as long as it isn't us.
        try {
            c = Cipher.getInstance(transformation);
            c.init(Cipher.DECRYPT_MODE, javaKey);

            // Ignore it if it points back to us.
            if (isOurProvider(c.getProvider())) {
                c = null;
            }
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            System.err.println("Unsupported cipher algorithm: " + transformation);
            return null;
        } catch (InvalidKeyException e) {
            System.err.println("Preferred provider doesn't support key:");
            e.printStackTrace();
            c = null;
        }

        // If the preferred provider was us, fall back to trying to find the
        // first not-us provider that initializes correctly.
        if (c == null) {
            ArrayList<Provider> providers = getExternalProviders("Cipher." + transformation);
            for (Provider p : providers) {
                try {
                    c = Cipher.getInstance(transformation, p);
                    c.init(Cipher.DECRYPT_MODE, javaKey);
                    break;
                } catch (NoSuchAlgorithmException | InvalidKeyException
                        | NoSuchPaddingException e) {
                    c = null;
                }
            }
            if (c == null) {
                System.err.println("Could not find provider for algorithm: " + transformation);
                return null;
            }
        }

        try {
            return c.doFinal(input);
        } catch (Exception e) {
            System.err.println("Exception while decrypting message with " + javaKey.getAlgorithm()
                    + " private key using " + transformation + ":");
            e.printStackTrace();
            return null;
        }
    }
}
