/*
 * Copyright 2021-2022 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
 */

/*
 * Low level APIs are deprecated for public use, but still ok for internal use.
 */
#include "internal/deprecated.h"

#include <openssl/core.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/params.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include "internal/passphrase.h"
#include "internal/nelem.h"
#include "prov/implementations.h"
#include "prov/bio.h"
#include "prov/provider_ctx.h"
#include "endecoder_local.h"

static int write_blob(void *provctx, OSSL_CORE_BIO *cout,
                      void *data, int len)
{
    BIO *out = ossl_bio_new_from_core_bio(provctx, cout);
    int ret;

    if (out == NULL)
        return 0;
    ret = BIO_write(out, data, len);

    BIO_free(out);
    return ret;
}

static OSSL_FUNC_encoder_newctx_fn key2blob_newctx;
static OSSL_FUNC_encoder_freectx_fn key2blob_freectx;

static void *key2blob_newctx(void *provctx)
{
    return provctx;
}

static void key2blob_freectx(void *vctx)
{
}

static int key2blob_check_selection(int selection, int selection_mask)
{
    /*
     * The selections are kinda sorta "levels", i.e. each selection given
     * here is assumed to include those following.
     */
    int checks[] = {
        OSSL_KEYMGMT_SELECT_PRIVATE_KEY,
        OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
        OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
    };
    size_t i;

    /* The decoder implementations made here support guessing */
    if (selection == 0)
        return 1;

    for (i = 0; i < OSSL_NELEM(checks); i++) {
        int check1 = (selection & checks[i]) != 0;
        int check2 = (selection_mask & checks[i]) != 0;

        /*
         * If the caller asked for the currently checked bit(s), return
         * whether the decoder description says it's supported.
         */
        if (check1)
            return check2;
    }

    /* This should be dead code, but just to be safe... */
    return 0;
}

static int key2blob_encode(void *vctx, const void *key, int selection,
                           OSSL_CORE_BIO *cout)
{
    int pubkey_len = 0, ok = 0;
    unsigned char *pubkey = NULL;

    pubkey_len = i2o_ECPublicKey(key, &pubkey);
    if (pubkey_len > 0 && pubkey != NULL)
        ok = write_blob(vctx, cout, pubkey, pubkey_len);
    OPENSSL_free(pubkey);
    return ok;
}

/*
 * MAKE_BLOB_ENCODER() Makes an OSSL_DISPATCH table for a particular key->blob
 * encoder
 *
 * impl:                The keytype to encode
 * type:                The C structure type holding the key data
 * selection_name:      The acceptable selections.  This translates into
 *                      the macro EVP_PKEY_##selection_name.
 *
 * The selection is understood as a "level" rather than an exact set of
 * requests from the caller.  The encoder has to decide what contents fit
 * the encoded format.  For example, the EC public key blob will only contain
 * the encoded public key itself, no matter if the selection bits include
 * OSSL_KEYMGMT_SELECT_PARAMETERS or not.  However, if the selection includes
 * OSSL_KEYMGMT_SELECT_PRIVATE_KEY, the same encoder will simply refuse to
 * cooperate, because it cannot output the private key.
 *
 * EVP_PKEY_##selection_name are convenience macros that combine "typical"
 * OSSL_KEYMGMT_SELECT_ macros for a certain type of EVP_PKEY content.
 */
#define MAKE_BLOB_ENCODER(impl, type, selection_name)                   \
    static OSSL_FUNC_encoder_import_object_fn                           \
    impl##2blob_import_object;                                          \
    static OSSL_FUNC_encoder_free_object_fn impl##2blob_free_object;    \
    static OSSL_FUNC_encoder_does_selection_fn                          \
    impl##2blob_does_selection;                                         \
    static OSSL_FUNC_encoder_encode_fn impl##2blob_encode;              \
                                                                        \
    static void *impl##2blob_import_object(void *ctx, int selection,    \
                                           const OSSL_PARAM params[])   \
    {                                                                   \
        return ossl_prov_import_key(ossl_##impl##_keymgmt_functions,    \
                                    ctx, selection, params);            \
    }                                                                   \
    static void impl##2blob_free_object(void *key)                      \
    {                                                                   \
        ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key);       \
    }                                                                   \
    static int impl##2blob_does_selection(void *ctx, int selection)     \
    {                                                                   \
        return key2blob_check_selection(selection,                      \
                                        EVP_PKEY_##selection_name);     \
    }                                                                   \
    static int impl##2blob_encode(void *vctx, OSSL_CORE_BIO *cout,      \
                                  const void *key,                      \
                                  const OSSL_PARAM key_abstract[],      \
                                  int selection,                        \
                                  OSSL_PASSPHRASE_CALLBACK *cb,         \
                                  void *cbarg)                          \
    {                                                                   \
        /* We don't deal with abstract objects */                       \
        if (key_abstract != NULL) {                                     \
            ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);     \
            return 0;                                                   \
        }                                                               \
        return key2blob_encode(vctx, key, selection, cout);             \
    }                                                                   \
    const OSSL_DISPATCH ossl_##impl##_to_blob_encoder_functions[] = {   \
        { OSSL_FUNC_ENCODER_NEWCTX,                                     \
          (void (*)(void))key2blob_newctx },                            \
        { OSSL_FUNC_ENCODER_FREECTX,                                    \
          (void (*)(void))key2blob_freectx },                           \
        { OSSL_FUNC_ENCODER_DOES_SELECTION,                             \
          (void (*)(void))impl##2blob_does_selection },                 \
        { OSSL_FUNC_ENCODER_IMPORT_OBJECT,                              \
          (void (*)(void))impl##2blob_import_object },                  \
        { OSSL_FUNC_ENCODER_FREE_OBJECT,                                \
          (void (*)(void))impl##2blob_free_object },                    \
        { OSSL_FUNC_ENCODER_ENCODE,                                     \
          (void (*)(void))impl##2blob_encode },                         \
        { 0, NULL }                                                     \
    }

#ifndef OPENSSL_NO_EC
MAKE_BLOB_ENCODER(ec, ec, PUBLIC_KEY);
# ifndef OPENSSL_NO_SM2
MAKE_BLOB_ENCODER(sm2, ec, PUBLIC_KEY);
# endif
#endif
