/*
 * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#include <stddef.h>

#include <openssl/core.h>
#include "internal/cryptlib.h"
#include "internal/core.h"
#include "internal/property.h"
#include "internal/provider.h"

struct construct_data_st {
    OSSL_LIB_CTX *libctx;
    OSSL_METHOD_STORE *store;
    int operation_id;
    int force_store;
    OSSL_METHOD_CONSTRUCT_METHOD *mcm;
    void *mcm_data;
};

static int ossl_method_construct_precondition(OSSL_PROVIDER *provider,
                                              int operation_id, void *cbdata,
                                              int *result)
{
    if (!ossl_assert(result != NULL)) {
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }

    if (!ossl_provider_test_operation_bit(provider, operation_id, result))
        return 0;

    /*
     * The result we get tells if methods have already been constructed.
     * However, we want to tell whether construction should happen (true)
     * or not (false), which is the opposite of what we got.
     */
    *result = !*result;

    return 1;
}

static int ossl_method_construct_postcondition(OSSL_PROVIDER *provider,
                                               int operation_id, int no_store,
                                               void *cbdata, int *result)
{
    if (!ossl_assert(result != NULL)) {
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }

    *result = 1;
    return no_store != 0
        || ossl_provider_set_operation_bit(provider, operation_id);
}

static void ossl_method_construct_this(OSSL_PROVIDER *provider,
                                       const OSSL_ALGORITHM *algo,
                                       int no_store, void *cbdata)
{
    struct construct_data_st *data = cbdata;
    void *method = NULL;

    if ((method = data->mcm->construct(algo, provider, data->mcm_data))
        == NULL)
        return;

    /*
     * Note regarding putting the method in stores:
     *
     * we don't need to care if it actually got in or not here.
     * If it didn't get in, it will simply not be available when
     * ossl_method_construct() tries to get it from the store.
     *
     * It is *expected* that the put function increments the refcnt
     * of the passed method.
     */

    if (data->force_store || !no_store) {
        /* If we haven't been told not to store, add to the global store */
        data->mcm->put(NULL, method, provider, algo->algorithm_names,
                       algo->property_definition, data->mcm_data);
    } else {
        /*
         * If we have been told not to store the method "permanently", we
         * ask for a temporary store, and store the method there.
         * The owner of |data->mcm| is completely responsible for managing
         * that temporary store.
         */
        if ((data->store = data->mcm->get_tmp_store(data->mcm_data)) == NULL)
            return;

        data->mcm->put(data->store, method, provider, algo->algorithm_names,
                       algo->property_definition, data->mcm_data);
    }

    /* refcnt-- because we're dropping the reference */
    data->mcm->destruct(method, data->mcm_data);
}

void *ossl_method_construct(OSSL_LIB_CTX *libctx, int operation_id,
                            OSSL_PROVIDER **provider_rw, int force_store,
                            OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data)
{
    void *method = NULL;

    if ((method = mcm->get(NULL, (const OSSL_PROVIDER **)provider_rw,
                           mcm_data)) == NULL) {
        OSSL_PROVIDER *provider = provider_rw != NULL ? *provider_rw : NULL;
        struct construct_data_st cbdata;

        cbdata.store = NULL;
        cbdata.force_store = force_store;
        cbdata.mcm = mcm;
        cbdata.mcm_data = mcm_data;
        ossl_algorithm_do_all(libctx, operation_id, provider,
                              ossl_method_construct_precondition,
                              ossl_method_construct_this,
                              ossl_method_construct_postcondition,
                              &cbdata);

        /* If there is a temporary store, try there first */
        if (cbdata.store != NULL)
            method = mcm->get(cbdata.store, (const OSSL_PROVIDER **)provider_rw,
                              mcm_data);

        /* If no method was found yet, try the global store */
        if (method == NULL)
            method = mcm->get(NULL, (const OSSL_PROVIDER **)provider_rw, mcm_data);
    }

    return method;
}
