 /*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.commons.crypto.jna;

import java.nio.ByteBuffer;

import org.apache.commons.crypto.Crypto;

import com.sun.jna.Function;
import com.sun.jna.NativeLibrary;
import com.sun.jna.NativeLong;
import com.sun.jna.ptr.PointerByReference;

final class OpenSslNativeJna {

    static final int OPENSSL_INIT_ENGINE_RDRAND = 0x00000200;

    static final int OOSL_JNA_ENCRYPT_MODE = 1;
    static final int OOSL_JNA_DECRYPT_MODE = 0;

    static final boolean INIT_OK;

    static final Throwable INIT_ERROR;

    /** Full version from JNA call. */
    static final long VERSION;

    /** Major Minor version from JNA call, without the maintenance level. */
    static final long VERSION_X_Y;

    static final long VERSION_1_1_X = 0x10100000;
    static final long VERSION_2_0_X = 0x20000000;
    static final long VERSION_3_0_X = 0x30000000;
    static final long VERSION_3_1_X = 0x30100000;

    private static final OpenSslInterfaceNativeJna JnaImplementation;

    static {
        OpenSslJna.debug("OpenSslNativeJna static init start");
        final String libraryName = System.getProperty(Crypto.JNA_LIBRARY_NAME_PROPERTY, Crypto.JNA_LIBRARY_NAME_DEFAULT);
        OpenSslJna.debug("OpenSslNativeJna NativeLibrary.getInstance('%s')", libraryName);
        // CRYPTO-179 - avoid crash
        if ("Mac OS X".equals(System.getProperty("os.name"))
            && System.getProperty(Crypto.JNA_LIBRARY_NAME_PROPERTY, "").isEmpty()
            && System.getProperty(Crypto.JNA_LIBRARY_PATH_PROPERTY, "").isEmpty()
        ) {
            String ret = OpenSslMacOS.checkLibrary(Crypto.MACOS_LIBRARY_NAME_DEFAULT);
            if (ret != null) {
                throw new UnsatisfiedLinkError(
                    String.format("Cannot load default library '%s'; please define %s! (%s)",
                        Crypto.MACOS_LIBRARY_NAME_DEFAULT, Crypto.JNA_LIBRARY_PATH_PROPERTY, ret));
            }
        }
        @SuppressWarnings("resource") // NativeLibrary.getInstance returns a singleton
        final NativeLibrary crypto = NativeLibrary.getInstance(libraryName);
        OpenSslJna.debug("OpenSslNativeJna NativeLibrary.getInstance('%s') -> %s", libraryName, crypto);
        Function versionFunction = null;
        try {
            versionFunction = crypto.getFunction("OpenSSL_version_num"); // Used by OpenSSL 1.1 and 3.x, so more likely
        } catch (final UnsatisfiedLinkError e) {
            versionFunction = crypto.getFunction("SSLeay"); // Fallback only needed for LibreSSL 2.x
        }
        // Must find one of the above two functions; else give up with UnsatisfiedLinkError

        VERSION = versionFunction.invokeLong(new Object[]{});
        //CHECKSTYLE:OFF
        VERSION_X_Y = VERSION & 0xffff0000; // keep only major.minor
        //CHECKSTYLE:ON

        OpenSslJna.debug(String.format("OpenSslNativeJna detected version 0x%x => 0x%x", VERSION, VERSION_X_Y));

        if (VERSION_X_Y == VERSION_1_1_X) {
            OpenSslJna.debug("Creating OpenSsl11XNativeJna");
            JnaImplementation = new OpenSsl11XNativeJna();
        } else if (VERSION_X_Y == VERSION_2_0_X) {
            OpenSslJna.debug("Creating LibreSsl20XNativeJna");
            JnaImplementation = new LibreSsl20XNativeJna();
       } else if (VERSION_X_Y == VERSION_3_0_X || VERSION_X_Y == VERSION_3_1_X) { // assume these are the same
           OpenSslJna.debug("Creating OpenSsl30XNativeJna");
           JnaImplementation = new OpenSsl30XNativeJna();
       } else {
            throw new UnsupportedOperationException(String.format("Unsupported Version: %x", VERSION_X_Y));
       }

        INIT_OK = JnaImplementation._INIT_OK();

        INIT_ERROR = INIT_OK ? null : JnaImplementation._INIT_ERROR();
        OpenSslJna.debug("OpenSslNativeJna INIT_OK = %s, INIT_ERROR = '%s', JnaImplementation = %s", INIT_OK, INIT_ERROR, JnaImplementation.getClass());
        OpenSslJna.debug("OpenSslNativeJna static init end");
    }

    public static PointerByReference ENGINE_by_id(final String string) {
        return JnaImplementation._ENGINE_by_id(string);
    }

    public static int ENGINE_cleanup() {
        return JnaImplementation._ENGINE_cleanup();
    }

    public static int ENGINE_finish(final PointerByReference rdrandEngine) {
        return JnaImplementation._ENGINE_finish(rdrandEngine);
    }

    public static int ENGINE_free(final PointerByReference rdrandEngine) {
        return JnaImplementation._ENGINE_free(rdrandEngine);
    }

    public static int ENGINE_init(final PointerByReference rdrandEngine) {
        return JnaImplementation._ENGINE_init(rdrandEngine);
    }

    public static void ENGINE_load_rdrand() {
        JnaImplementation._ENGINE_load_rdrand();
    }

    public static int ENGINE_set_default(final PointerByReference rdrandEngine, final int eNGINE_METHOD_RAND) {
        return JnaImplementation._ENGINE_set_default(rdrandEngine, eNGINE_METHOD_RAND);
    }

    public static String ERR_error_string(final NativeLong err, final char[] object) {
        return JnaImplementation._ERR_error_string(err, null);
    }

    public static NativeLong ERR_peek_error() {
        return JnaImplementation._ERR_peek_error();
    }

    public static PointerByReference EVP_aes_128_cbc() {
        return JnaImplementation._EVP_aes_128_cbc();
    }

    public static PointerByReference EVP_aes_128_ctr() {
        return JnaImplementation._EVP_aes_128_ctr();
    }

    public static PointerByReference EVP_aes_192_cbc() {
        return JnaImplementation._EVP_aes_192_cbc();
    }

    public static PointerByReference EVP_aes_192_ctr() {
        return JnaImplementation._EVP_aes_192_ctr();
    }

    public static PointerByReference EVP_aes_256_cbc() {
        return JnaImplementation._EVP_aes_256_cbc();
    }

    public static PointerByReference EVP_aes_256_ctr() {
        return JnaImplementation._EVP_aes_256_ctr();
    }

    public static void EVP_CIPHER_CTX_cleanup(final PointerByReference context) {
        JnaImplementation._EVP_CIPHER_CTX_cleanup(context);
    }

    public static void EVP_CIPHER_CTX_free(final PointerByReference context) {
        JnaImplementation._EVP_CIPHER_CTX_free(context);
    }

    public static PointerByReference EVP_CIPHER_CTX_new() {
        return JnaImplementation._EVP_CIPHER_CTX_new();
    }

    public static int EVP_CIPHER_CTX_set_padding(final PointerByReference context, final int padding) {
        return JnaImplementation._EVP_CIPHER_CTX_set_padding(context, padding);
    }

    public static int EVP_CipherFinal_ex(final PointerByReference context, final ByteBuffer outBuffer,
            final int[] outlen) {
        return JnaImplementation._EVP_CipherFinal_ex(context, outBuffer, outlen);
    }

    public static int EVP_CipherInit_ex(final PointerByReference context, final PointerByReference algo,
            final Object object, final byte[] encoded, final byte[] iv, final int cipherMode) {
        return JnaImplementation._EVP_CipherInit_ex(context, algo, null, encoded, iv, cipherMode);
    }

    public static int EVP_CipherUpdate(final PointerByReference context, final ByteBuffer outBuffer,
            final int[] outlen, final ByteBuffer inBuffer, final int remaining) {
        return JnaImplementation._EVP_CipherUpdate(context, outBuffer, outlen, inBuffer, remaining);
    }

    public static String OpenSSLVersion(final int i) {
        return JnaImplementation._OpenSSL_version(i);
    }

    public static long OpenSSL_version_num() {
        return JnaImplementation._OpenSSL_version_num();
    }

    public static int RAND_bytes(final ByteBuffer buf, final int length) {
        return JnaImplementation._RAND_bytes(buf, length);
    }

    public static PointerByReference RAND_get_rand_method() {
        return JnaImplementation._RAND_get_rand_method();
    }

    public static PointerByReference RAND_SSLeay() {
        return JnaImplementation._RAND_SSLeay();
    }

    private OpenSslNativeJna() {
    }
}
