/*
 * Copyright 2020-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 "internal/e_os.h"
#include <string.h>

#include <openssl/core.h>
#include <openssl/core_names.h>
#include <openssl/core_object.h>
#include <openssl/err.h>
#include <openssl/pkcs12.h>
#include <openssl/provider.h>
#include <openssl/decoder.h>
#include <openssl/store.h>
#include "internal/provider.h"
#include "internal/passphrase.h"
#include "crypto/evp.h"
#include "crypto/x509.h"
#include "store_local.h"

#ifndef OSSL_OBJECT_PKCS12
/*
 * The object abstraction doesn't know PKCS#12, but we want to indicate
 * it anyway, so we create our own.  Since the public macros use positive
 * numbers, negative ones should be fine.  They must never slip out from
 * this translation unit anyway.
 */
# define OSSL_OBJECT_PKCS12 -1
#endif

/*
 * ossl_store_handle_load_result() is initially written to be a companion
 * to our 'file:' scheme provider implementation, but has been made generic
 * to serve others as well.
 *
 * This result handler takes any object abstraction (see provider-object(7))
 * and does the best it can with it.  If the object is passed by value (not
 * by reference), the contents are currently expected to be DER encoded.
 * If an object type is specified, that will be respected; otherwise, this
 * handler will guess the contents, by trying the following in order:
 *
 * 1.  Decode it into an EVP_PKEY, using OSSL_DECODER.
 * 2.  Decode it into an X.509 certificate, using d2i_X509 / d2i_X509_AUX.
 * 3.  Decode it into an X.509 CRL, using d2i_X509_CRL.
 * 4.  Decode it into a PKCS#12 structure, using d2i_PKCS12 (*).
 *
 * For the 'file:' scheme implementation, this is division of labor.  Since
 * the libcrypto <-> provider interface currently doesn't support certain
 * structures as first class objects, they must be unpacked from DER here
 * rather than in the provider.  The current exception is asymmetric keys,
 * which can reside within the provider boundary, most of all thanks to
 * OSSL_FUNC_keymgmt_load(), which allows loading the key material by
 * reference.
 */

struct extracted_param_data_st {
    int object_type;
    const char *data_type;
    const char *data_structure;
    const char *utf8_data;
    const void *octet_data;
    size_t octet_data_size;
    const void *ref;
    size_t ref_size;
    const char *desc;
};

static int try_name(struct extracted_param_data_st *, OSSL_STORE_INFO **);
static int try_key(struct extracted_param_data_st *, OSSL_STORE_INFO **,
                   OSSL_STORE_CTX *, const OSSL_PROVIDER *,
                   OSSL_LIB_CTX *, const char *);
static int try_cert(struct extracted_param_data_st *, OSSL_STORE_INFO **,
                    OSSL_LIB_CTX *, const char *);
static int try_crl(struct extracted_param_data_st *, OSSL_STORE_INFO **,
                   OSSL_LIB_CTX *, const char *);
static int try_pkcs12(struct extracted_param_data_st *, OSSL_STORE_INFO **,
                      OSSL_STORE_CTX *, OSSL_LIB_CTX *, const char *);

int ossl_store_handle_load_result(const OSSL_PARAM params[], void *arg)
{
    struct ossl_load_result_data_st *cbdata = arg;
    OSSL_STORE_INFO **v = &cbdata->v;
    OSSL_STORE_CTX *ctx = cbdata->ctx;
    const OSSL_PROVIDER *provider =
        OSSL_STORE_LOADER_get0_provider(ctx->fetched_loader);
    OSSL_LIB_CTX *libctx = ossl_provider_libctx(provider);
    const char *propq = ctx->properties;
    const OSSL_PARAM *p;
    struct extracted_param_data_st helper_data;

    memset(&helper_data, 0, sizeof(helper_data));
    helper_data.object_type = OSSL_OBJECT_UNKNOWN;

    if ((p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_TYPE)) != NULL
        && !OSSL_PARAM_get_int(p, &helper_data.object_type))
        return 0;
    p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_TYPE);
    if (p != NULL
        && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.data_type))
        return 0;
    p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA);
    if (p != NULL
        && !OSSL_PARAM_get_octet_string_ptr(p, &helper_data.octet_data,
                                            &helper_data.octet_data_size)
        && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.utf8_data))
        return 0;
    p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_STRUCTURE);
    if (p != NULL
        && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.data_structure))
        return 0;
    p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_REFERENCE);
    if (p != NULL && !OSSL_PARAM_get_octet_string_ptr(p, &helper_data.ref,
                                                      &helper_data.ref_size))
        return 0;
    p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DESC);
    if (p != NULL && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.desc))
        return 0;

    /*
     * The helper functions return 0 on actual errors, otherwise 1, even if
     * they didn't fill out |*v|.
     */
    ERR_set_mark();
    if (*v == NULL && !try_name(&helper_data, v))
        goto err;
    ERR_pop_to_mark();
    ERR_set_mark();
    if (*v == NULL && !try_key(&helper_data, v, ctx, provider, libctx, propq))
        goto err;
    ERR_pop_to_mark();
    ERR_set_mark();
    if (*v == NULL && !try_cert(&helper_data, v, libctx, propq))
        goto err;
    ERR_pop_to_mark();
    ERR_set_mark();
    if (*v == NULL && !try_crl(&helper_data, v, libctx, propq))
        goto err;
    ERR_pop_to_mark();
    ERR_set_mark();
    if (*v == NULL && !try_pkcs12(&helper_data, v, ctx, libctx, propq))
        goto err;
    ERR_pop_to_mark();

    if (*v == NULL)
        ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_UNSUPPORTED);

    return (*v != NULL);
 err:
    ERR_clear_last_mark();
    return 0;
}

static int try_name(struct extracted_param_data_st *data, OSSL_STORE_INFO **v)
{
    if (data->object_type == OSSL_OBJECT_NAME) {
        char *newname = NULL, *newdesc = NULL;

        if (data->utf8_data == NULL)
            return 0;
        if ((newname = OPENSSL_strdup(data->utf8_data)) == NULL
            || (data->desc != NULL
                && (newdesc = OPENSSL_strdup(data->desc)) == NULL)
            || (*v = OSSL_STORE_INFO_new_NAME(newname)) == NULL) {
            OPENSSL_free(newname);
            OPENSSL_free(newdesc);
            return 0;
        }
        OSSL_STORE_INFO_set0_NAME_description(*v, newdesc);
    }
    return 1;
}

/*
 * For the rest of the object types, the provider code may not know what
 * type of data it gave us, so we may need to figure that out on our own.
 * Therefore, we do check for OSSL_OBJECT_UNKNOWN everywhere below, and
 * only return 0 on error if the object type is known.
 */

static EVP_PKEY *try_key_ref(struct extracted_param_data_st *data,
                             OSSL_STORE_CTX *ctx,
                             const OSSL_PROVIDER *provider,
                             OSSL_LIB_CTX *libctx, const char *propq)
{
    EVP_PKEY *pk = NULL;
    EVP_KEYMGMT *keymgmt = NULL;
    void *keydata = NULL;

    /* If we have an object reference, we must have a data type */
    if (data->data_type == NULL)
        return 0;

    keymgmt = EVP_KEYMGMT_fetch(libctx, data->data_type, propq);
    if (keymgmt != NULL) {
        /*
         * There are two possible cases
         *
         * 1.  The keymgmt is from the same provider as the loader,
         *     so we can use evp_keymgmt_load()
         * 2.  The keymgmt is from another provider, then we must
         *     do the export/import dance.
         */
        if (EVP_KEYMGMT_get0_provider(keymgmt) == provider) {
            keydata = evp_keymgmt_load(keymgmt, data->ref, data->ref_size);
        } else {
            struct evp_keymgmt_util_try_import_data_st import_data;
            OSSL_FUNC_store_export_object_fn *export_object =
                ctx->fetched_loader->p_export_object;

            import_data.keymgmt = keymgmt;
            import_data.keydata = NULL;
            import_data.selection = OSSL_KEYMGMT_SELECT_ALL;

            if (export_object != NULL) {
                /*
                 * No need to check for errors here, the value of
                 * |import_data.keydata| is as much an indicator.
                 */
                (void)export_object(ctx->loader_ctx,
                                    data->ref, data->ref_size,
                                    &evp_keymgmt_util_try_import,
                                    &import_data);
            }

            keydata = import_data.keydata;
        }
    }
    if (keydata != NULL)
        pk = evp_keymgmt_util_make_pkey(keymgmt, keydata);
    EVP_KEYMGMT_free(keymgmt);

    return pk;
}

static EVP_PKEY *try_key_value(struct extracted_param_data_st *data,
                               OSSL_STORE_CTX *ctx,
                               OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg,
                               OSSL_LIB_CTX *libctx, const char *propq)
{
    EVP_PKEY *pk = NULL;
    OSSL_DECODER_CTX *decoderctx = NULL;
    const unsigned char *pdata = data->octet_data;
    size_t pdatalen = data->octet_data_size;
    int selection = 0;

    switch (ctx->expected_type) {
    case 0:
        break;
    case OSSL_STORE_INFO_PARAMS:
        selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
        break;
    case OSSL_STORE_INFO_PUBKEY:
        selection =
            OSSL_KEYMGMT_SELECT_PUBLIC_KEY
            | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
        break;
    case OSSL_STORE_INFO_PKEY:
        selection = OSSL_KEYMGMT_SELECT_ALL;
        break;
    default:
        return NULL;
    }

    decoderctx =
        OSSL_DECODER_CTX_new_for_pkey(&pk, NULL, data->data_structure,
                                      data->data_type, selection, libctx,
                                      propq);
    (void)OSSL_DECODER_CTX_set_passphrase_cb(decoderctx, cb, cbarg);

    /* No error if this couldn't be decoded */
    (void)OSSL_DECODER_from_data(decoderctx, &pdata, &pdatalen);

    OSSL_DECODER_CTX_free(decoderctx);

    return pk;
}

typedef OSSL_STORE_INFO *store_info_new_fn(EVP_PKEY *);

static EVP_PKEY *try_key_value_legacy(struct extracted_param_data_st *data,
                                      store_info_new_fn **store_info_new,
                                      OSSL_STORE_CTX *ctx,
                                      OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg,
                                      OSSL_LIB_CTX *libctx, const char *propq)
{
    EVP_PKEY *pk = NULL;
    const unsigned char *der = data->octet_data, *derp;
    long der_len = (long)data->octet_data_size;

    /* Try PUBKEY first, that's a real easy target */
    if (ctx->expected_type == 0
        || ctx->expected_type == OSSL_STORE_INFO_PUBKEY) {
        derp = der;
        pk = d2i_PUBKEY_ex(NULL, &derp, der_len, libctx, propq);

        if (pk != NULL)
            *store_info_new = OSSL_STORE_INFO_new_PUBKEY;
    }

    /* Try private keys next */
    if (pk == NULL
        && (ctx->expected_type == 0
            || ctx->expected_type == OSSL_STORE_INFO_PKEY)) {
        unsigned char *new_der = NULL;
        X509_SIG *p8 = NULL;
        PKCS8_PRIV_KEY_INFO *p8info = NULL;

        /* See if it's an encrypted PKCS#8 and decrypt it. */
        derp = der;
        p8 = d2i_X509_SIG(NULL, &derp, der_len);

        if (p8 != NULL) {
            char pbuf[PEM_BUFSIZE];
            size_t plen = 0;

            if (!cb(pbuf, sizeof(pbuf), &plen, NULL, cbarg)) {
                ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_BAD_PASSWORD_READ);
            } else {
                const X509_ALGOR *alg = NULL;
                const ASN1_OCTET_STRING *oct = NULL;
                int len = 0;

                X509_SIG_get0(p8, &alg, &oct);

                /*
                 * No need to check the returned value, |new_der|
                 * will be NULL on error anyway.
                 */
                PKCS12_pbe_crypt(alg, pbuf, plen,
                                 oct->data, oct->length,
                                 &new_der, &len, 0);
                der_len = len;
                der = new_der;
            }
            X509_SIG_free(p8);
        }

        /*
         * If the encrypted PKCS#8 couldn't be decrypted,
         * |der| is NULL
         */
        if (der != NULL) {
            /* Try to unpack an unencrypted PKCS#8, that's easy */
            derp = der;
            p8info = d2i_PKCS8_PRIV_KEY_INFO(NULL, &derp, der_len);

            if (p8info != NULL) {
                pk = EVP_PKCS82PKEY_ex(p8info, libctx, propq);
                PKCS8_PRIV_KEY_INFO_free(p8info);
            }
        }

        if (pk != NULL)
            *store_info_new = OSSL_STORE_INFO_new_PKEY;

        OPENSSL_free(new_der);
    }

    return pk;
}

static int try_key(struct extracted_param_data_st *data, OSSL_STORE_INFO **v,
                   OSSL_STORE_CTX *ctx, const OSSL_PROVIDER *provider,
                   OSSL_LIB_CTX *libctx, const char *propq)
{
    store_info_new_fn *store_info_new = NULL;

    if (data->object_type == OSSL_OBJECT_UNKNOWN
        || data->object_type == OSSL_OBJECT_PKEY) {
        EVP_PKEY *pk = NULL;

        /* Prefer key by reference than key by value */
        if (data->object_type == OSSL_OBJECT_PKEY && data->ref != NULL) {
            pk = try_key_ref(data, ctx, provider, libctx, propq);

            /*
             * If for some reason we couldn't get a key, it's an error.
             * It indicates that while decoders could make a key reference,
             * the keymgmt somehow couldn't handle it, or doesn't have a
             * OSSL_FUNC_keymgmt_load function.
             */
            if (pk == NULL)
                return 0;
        } else if (data->octet_data != NULL) {
            OSSL_PASSPHRASE_CALLBACK *cb = ossl_pw_passphrase_callback_dec;
            void *cbarg = &ctx->pwdata;

            pk = try_key_value(data, ctx, cb, cbarg, libctx, propq);

            /*
             * Desperate last maneuver, in case the decoders don't support
             * the data we have, then we try on our own to at least get an
             * engine provided legacy key.
             * This is the same as der2key_decode() does, but in a limited
             * way and within the walls of libcrypto.
             */
            if (pk == NULL)
                pk = try_key_value_legacy(data, &store_info_new, ctx,
                                          cb, cbarg, libctx, propq);
        }

        if (pk != NULL) {
            data->object_type = OSSL_OBJECT_PKEY;

            if (store_info_new == NULL) {
                /*
                 * We determined the object type for OSSL_STORE_INFO, which
                 * makes an explicit difference between an EVP_PKEY with just
                 * (domain) parameters and an EVP_PKEY with actual key
                 * material.
                 * The logic is that an EVP_PKEY with actual key material
                 * always has the public half.
                 */
                if (evp_keymgmt_util_has(pk, OSSL_KEYMGMT_SELECT_PRIVATE_KEY))
                    store_info_new = OSSL_STORE_INFO_new_PKEY;
                else if (evp_keymgmt_util_has(pk,
                                              OSSL_KEYMGMT_SELECT_PUBLIC_KEY))
                    store_info_new = OSSL_STORE_INFO_new_PUBKEY;
                else
                    store_info_new = OSSL_STORE_INFO_new_PARAMS;
            }
            *v = store_info_new(pk);
        }

        if (*v == NULL)
            EVP_PKEY_free(pk);
    }

    return 1;
}

static int try_cert(struct extracted_param_data_st *data, OSSL_STORE_INFO **v,
                    OSSL_LIB_CTX *libctx, const char *propq)
{
    if (data->object_type == OSSL_OBJECT_UNKNOWN
        || data->object_type == OSSL_OBJECT_CERT) {
        /*
         * In most cases, we can try to interpret the serialized
         * data as a trusted cert (X509 + X509_AUX) and fall back
         * to reading it as a normal cert (just X509), but if
         * |data_type| (the PEM name) specifically declares it as a
         * trusted cert, then no fallback should be engaged.
         * |ignore_trusted| tells if the fallback can be used (1)
         * or not (0).
         */
        int ignore_trusted = 1;
        X509 *cert = X509_new_ex(libctx, propq);

        if (cert == NULL)
            return 0;

        /* If we have a data type, it should be a PEM name */
        if (data->data_type != NULL
            && (strcasecmp(data->data_type, PEM_STRING_X509_TRUSTED) == 0))
            ignore_trusted = 0;

        if (d2i_X509_AUX(&cert, (const unsigned char **)&data->octet_data,
                         data->octet_data_size) == NULL
            && (!ignore_trusted
                || d2i_X509(&cert, (const unsigned char **)&data->octet_data,
                            data->octet_data_size) == NULL)) {
            X509_free(cert);
            cert = NULL;
        }

        if (cert != NULL) {
            /* We determined the object type */
            data->object_type = OSSL_OBJECT_CERT;
            *v = OSSL_STORE_INFO_new_CERT(cert);
            if (*v == NULL)
                X509_free(cert);
        }
    }

    return 1;
}

static int try_crl(struct extracted_param_data_st *data, OSSL_STORE_INFO **v,
                   OSSL_LIB_CTX *libctx, const char *propq)
{
    if (data->object_type == OSSL_OBJECT_UNKNOWN
        || data->object_type == OSSL_OBJECT_CRL) {
        X509_CRL *crl;

        crl = d2i_X509_CRL(NULL, (const unsigned char **)&data->octet_data,
                           data->octet_data_size);

        if (crl != NULL)
            /* We determined the object type */
            data->object_type = OSSL_OBJECT_CRL;

        if (crl != NULL && !ossl_x509_crl_set0_libctx(crl, libctx, propq)) {
            X509_CRL_free(crl);
            crl = NULL;
        }

        if (crl != NULL)
            *v = OSSL_STORE_INFO_new_CRL(crl);
        if (*v == NULL)
            X509_CRL_free(crl);
    }

    return 1;
}

static int try_pkcs12(struct extracted_param_data_st *data, OSSL_STORE_INFO **v,
                      OSSL_STORE_CTX *ctx,
                      OSSL_LIB_CTX *libctx, const char *propq)
{
    int ok = 1;

    /* There is no specific object type for PKCS12 */
    if (data->object_type == OSSL_OBJECT_UNKNOWN) {
        /* Initial parsing */
        PKCS12 *p12;

        p12 = d2i_PKCS12(NULL, (const unsigned char **)&data->octet_data,
                         data->octet_data_size);

        if (p12 != NULL) {
            char *pass = NULL;
            char tpass[PEM_BUFSIZE + 1];
            size_t tpass_len;
            EVP_PKEY *pkey = NULL;
            X509 *cert = NULL;
            STACK_OF(X509) *chain = NULL;

            data->object_type = OSSL_OBJECT_PKCS12;

            ok = 0;              /* Assume decryption or parse error */

            if (PKCS12_verify_mac(p12, "", 0)
                || PKCS12_verify_mac(p12, NULL, 0)) {
                pass = "";
            } else {
                static char prompt_info[] = "PKCS12 import pass phrase";
                OSSL_PARAM pw_params[] = {
                    OSSL_PARAM_utf8_string(OSSL_PASSPHRASE_PARAM_INFO,
                                           prompt_info,
                                           sizeof(prompt_info) - 1),
                    OSSL_PARAM_END
                };

                if (!ossl_pw_get_passphrase(tpass, sizeof(tpass) - 1,
                                            &tpass_len,
                                            pw_params, 0, &ctx->pwdata)) {
                    ERR_raise(ERR_LIB_OSSL_STORE,
                              OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR);
                    goto p12_end;
                }
                pass = tpass;
                /*
                 * ossl_pw_get_passphrase() does not NUL terminate but
                 * we must do it for PKCS12_parse()
                 */
                pass[tpass_len] = '\0';
                if (!PKCS12_verify_mac(p12, pass, tpass_len)) {
                    ERR_raise_data(ERR_LIB_OSSL_STORE,
                                   OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC,
                                   tpass_len == 0 ? "empty password" :
                                   "maybe wrong password");
                    goto p12_end;
                }
            }

            if (PKCS12_parse(p12, pass, &pkey, &cert, &chain)) {
                STACK_OF(OSSL_STORE_INFO) *infos = NULL;
                OSSL_STORE_INFO *osi_pkey = NULL;
                OSSL_STORE_INFO *osi_cert = NULL;
                OSSL_STORE_INFO *osi_ca = NULL;

                ok = 1;          /* Parsing went through correctly! */

                if ((infos = sk_OSSL_STORE_INFO_new_null()) != NULL) {
                    if (pkey != NULL) {
                        if ((osi_pkey = OSSL_STORE_INFO_new_PKEY(pkey)) != NULL
                            /* clearing pkey here avoids case distinctions */
                            && (pkey = NULL) == NULL
                            && sk_OSSL_STORE_INFO_push(infos, osi_pkey) != 0)
                            osi_pkey = NULL;
                        else
                            ok = 0;
                    }
                    if (ok && cert != NULL) {
                        if ((osi_cert = OSSL_STORE_INFO_new_CERT(cert)) != NULL
                            /* clearing cert here avoids case distinctions */
                            && (cert = NULL) == NULL
                            && sk_OSSL_STORE_INFO_push(infos, osi_cert) != 0)
                            osi_cert = NULL;
                        else
                            ok = 0;
                    }
                    while (ok && sk_X509_num(chain) > 0) {
                        X509 *ca = sk_X509_value(chain, 0);

                        if ((osi_ca = OSSL_STORE_INFO_new_CERT(ca)) != NULL
                            && sk_X509_shift(chain) != NULL
                            && sk_OSSL_STORE_INFO_push(infos, osi_ca) != 0)
                            osi_ca = NULL;
                        else
                            ok = 0;
                    }
                }
                EVP_PKEY_free(pkey);
                X509_free(cert);
                OSSL_STACK_OF_X509_free(chain);
                OSSL_STORE_INFO_free(osi_pkey);
                OSSL_STORE_INFO_free(osi_cert);
                OSSL_STORE_INFO_free(osi_ca);
                if (!ok) {
                    sk_OSSL_STORE_INFO_pop_free(infos, OSSL_STORE_INFO_free);
                    infos = NULL;
                }
                ctx->cached_info = infos;
            }
         p12_end:
            OPENSSL_cleanse(tpass, sizeof(tpass));
            PKCS12_free(p12);
        }
        *v = sk_OSSL_STORE_INFO_shift(ctx->cached_info);
    }

    return ok;
}
