/*
 * Copyright 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 <string.h>
#include <openssl/params.h>
#include <openssl/param_build.h>
#include "internal/param_build_set.h"
#include "internal/e_os.h" /* strcasecmp */

#define OSSL_PARAM_ALLOCATED_END    127
#define OSSL_PARAM_MERGE_LIST_MAX   128

#define OSSL_PARAM_BUF_PUBLIC 0
#define OSSL_PARAM_BUF_SECURE 1
#define OSSL_PARAM_BUF_MAX    (OSSL_PARAM_BUF_SECURE + 1)

typedef struct {
    OSSL_PARAM_ALIGNED_BLOCK *alloc; /* The allocated buffer */
    OSSL_PARAM_ALIGNED_BLOCK *cur;   /* Current position in the allocated buf */
    size_t blocks;    /* Number of aligned blocks */
    size_t alloc_sz;  /* The size of the allocated buffer (in bytes) */
} OSSL_PARAM_BUF;

size_t ossl_param_bytes_to_blocks(size_t bytes)
{
    return (bytes + OSSL_PARAM_ALIGN_SIZE - 1) / OSSL_PARAM_ALIGN_SIZE;
}

static int ossl_param_buf_alloc(OSSL_PARAM_BUF *out, size_t extra_blocks,
                                int is_secure)
{
    size_t sz = OSSL_PARAM_ALIGN_SIZE * (extra_blocks + out->blocks);

    out->alloc = is_secure ? OPENSSL_secure_zalloc(sz) : OPENSSL_zalloc(sz);
    if (out->alloc == NULL) {
        ERR_raise(ERR_LIB_CRYPTO, is_secure ? CRYPTO_R_SECURE_MALLOC_FAILURE
                                            : ERR_R_MALLOC_FAILURE);
        return 0;
    }
    out->alloc_sz = sz;
    out->cur = out->alloc + extra_blocks;
    return 1;
}

void ossl_param_set_secure_block(OSSL_PARAM *last, void *secure_buffer,
                                 size_t secure_buffer_sz)
{
    last->key = NULL;
    last->data_size = secure_buffer_sz;
    last->data = secure_buffer;
    last->data_type = OSSL_PARAM_ALLOCATED_END;
}

static OSSL_PARAM *ossl_param_dup(const OSSL_PARAM *src, OSSL_PARAM *dst,
                                  OSSL_PARAM_BUF buf[OSSL_PARAM_BUF_MAX],
                                  int *param_count)
{
    const OSSL_PARAM *in;
    int has_dst = (dst != NULL);
    int is_secure;
    size_t param_sz, blks;

    for (in = src; in->key != NULL; in++) {
        is_secure = CRYPTO_secure_allocated(in->data);
        if (has_dst) {
            *dst = *in;
            dst->data = buf[is_secure].cur;
        }

        if (in->data_type == OSSL_PARAM_OCTET_PTR
            || in->data_type == OSSL_PARAM_UTF8_PTR) {
            param_sz = sizeof(in->data);
            if (has_dst)
                *((const void **)dst->data) = *(const void **)in->data;
        } else {
            param_sz = in->data_size;
            if (has_dst)
                memcpy(dst->data, in->data, param_sz);
        }
        if (in->data_type == OSSL_PARAM_UTF8_STRING)
            param_sz++; /* NULL terminator */
        blks = ossl_param_bytes_to_blocks(param_sz);

        if (has_dst) {
            dst++;
            buf[is_secure].cur += blks;
        } else {
            buf[is_secure].blocks += blks;
        }
        if (param_count != NULL)
            ++*param_count;
    }
    return dst;
}

OSSL_PARAM *OSSL_PARAM_dup(const OSSL_PARAM *src)
{
    size_t param_blocks;
    OSSL_PARAM_BUF buf[OSSL_PARAM_BUF_MAX];
    OSSL_PARAM *last, *dst;
    int param_count = 1; /* Include terminator in the count */

    if (src == NULL) {
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
        return NULL;
    }

    memset(buf, 0, sizeof(buf));

    /* First Pass: get the param_count and block sizes required */
    (void)ossl_param_dup(src, NULL, buf, &param_count);

    param_blocks = ossl_param_bytes_to_blocks(param_count * sizeof(*src));
    /*
     * The allocated buffer consists of an array of OSSL_PARAM followed by
     * aligned data bytes that the array elements will point to.
     */
    if (!ossl_param_buf_alloc(&buf[OSSL_PARAM_BUF_PUBLIC], param_blocks, 0))
        return NULL;

    /* Allocate a secure memory buffer if required */
    if (buf[OSSL_PARAM_BUF_SECURE].blocks > 0
        && !ossl_param_buf_alloc(&buf[OSSL_PARAM_BUF_SECURE], 0, 1)) {
        OPENSSL_free(buf[OSSL_PARAM_BUF_PUBLIC].alloc);
        return NULL;
    }

    dst = (OSSL_PARAM *)buf[OSSL_PARAM_BUF_PUBLIC].alloc;
    last = ossl_param_dup(src, dst, buf, NULL);
    /* Store the allocated secure memory buffer in the last param block */
    ossl_param_set_secure_block(last, buf[OSSL_PARAM_BUF_SECURE].alloc,
                                buf[OSSL_PARAM_BUF_SECURE].alloc_sz);
    return dst;
}

static int compare_params(const void *left, const void *right)
{
    const OSSL_PARAM *l = *(const OSSL_PARAM **)left;
    const OSSL_PARAM *r = *(const OSSL_PARAM **)right;

    return strcasecmp(l->key, r->key);
}

OSSL_PARAM *OSSL_PARAM_merge(const OSSL_PARAM *p1, const OSSL_PARAM *p2)
{
    const OSSL_PARAM *list1[OSSL_PARAM_MERGE_LIST_MAX + 1];
    const OSSL_PARAM *list2[OSSL_PARAM_MERGE_LIST_MAX + 1];
    const OSSL_PARAM *p = NULL;
    const OSSL_PARAM **p1cur, **p2cur;
    OSSL_PARAM *params, *dst;
    size_t  list1_sz = 0, list2_sz = 0;
    int diff;

    if (p1 == NULL && p2 == NULL) {
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
        return NULL;
    }

    /* Copy p1 to list1 */
    if (p1 != NULL) {
        for (p = p1; p->key != NULL && list1_sz < OSSL_PARAM_MERGE_LIST_MAX; p++)
            list1[list1_sz++] = p;
    }
    list1[list1_sz] = NULL;

    /* copy p2 to a list2 */
    if (p2 != NULL) {
        for (p = p2; p->key != NULL && list2_sz < OSSL_PARAM_MERGE_LIST_MAX; p++)
            list2[list2_sz++] = p;
    }
    list2[list2_sz] = NULL;
    if (list1_sz == 0 && list2_sz == 0) {
        ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_NO_PARAMS_TO_MERGE);
        return NULL;
    }

    /* Sort the 2 lists */
    qsort(list1, list1_sz, sizeof(OSSL_PARAM *), compare_params);
    qsort(list2, list2_sz, sizeof(OSSL_PARAM *), compare_params);

   /* Allocate enough space to store the merged parameters */
    params = OPENSSL_zalloc((list1_sz + list2_sz + 1) * sizeof(*p1));
    if (params == NULL) {
        ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
        return NULL;
    }
    dst = params;
    p1cur = list1;
    p2cur = list2;
    while (1) {
        /* If list1 is finished just tack list2 onto the end */
        if (*p1cur == NULL) {
            do {
                *dst++ = **p2cur;
                p2cur++;
            } while (*p2cur != NULL);
            break;
        }
        /* If list2 is finished just tack list1 onto the end */
        if (*p2cur == NULL) {
            do {
                *dst++ = **p1cur;
                p1cur++;
            } while (*p1cur != NULL);
            break;
        }
        /* consume the list element with the smaller key */
        diff = strcasecmp((*p1cur)->key, (*p2cur)->key);
        if (diff == 0) {
            /* If the keys are the same then throw away the list1 element */
            *dst++ = **p2cur;
            p2cur++;
            p1cur++;
        } else if (diff > 0) {
            *dst++ = **p2cur;
            p2cur++;
        } else {
            *dst++ = **p1cur;
            p1cur++;
        }
    }
    return params;
}

void OSSL_PARAM_free(OSSL_PARAM *params)
{
    if (params != NULL) {
        OSSL_PARAM *p;

        for (p = params; p->key != NULL; p++)
            ;
        if (p->data_type == OSSL_PARAM_ALLOCATED_END)
            OPENSSL_secure_clear_free(p->data, p->data_size);
        OPENSSL_free(params);
    }
}
