/*
 * Copyright 2020 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> /* memcpy */
#include <openssl/core_names.h>
#include <openssl/param_build.h>
#include "crypto/rsa.h"
#include "rsa_local.h"

int ossl_rsa_acvp_test_gen_params_new(OSSL_PARAM **dst, const OSSL_PARAM src[])
{
    const OSSL_PARAM *p, *s;
    OSSL_PARAM *d, *alloc = NULL;
    int ret = 1;

    static const OSSL_PARAM settable[] = {
        OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XP, NULL, 0),
        OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XP1, NULL, 0),
        OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XP2, NULL, 0),
        OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XQ, NULL, 0),
        OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XQ1, NULL, 0),
        OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XQ2, NULL, 0),
        OSSL_PARAM_END
    };

    /* Assume the first element is a required field if this feature is used */
    p = OSSL_PARAM_locate_const(src, settable[0].key);
    if (p == NULL)
        return 1;

    /* Zeroing here means the terminator is always set at the end */
    alloc = OPENSSL_zalloc(sizeof(settable));
    if (alloc == NULL)
        return 0;

    d = alloc;
    for (s = settable; s->key != NULL; ++s) {
        /* If src contains a key from settable then copy the src to the dest */
        p = OSSL_PARAM_locate_const(src, s->key);
        if (p != NULL) {
            *d = *s; /* shallow copy from the static settable[] */
            d->data_size = p->data_size;
            d->data = OPENSSL_memdup(p->data, p->data_size);
            if (d->data == NULL)
                ret = 0;
            ++d;
        }
    }
    if (ret == 0) {
        ossl_rsa_acvp_test_gen_params_free(alloc);
        alloc = NULL;
    }
    if (*dst != NULL)
        ossl_rsa_acvp_test_gen_params_free(*dst);
    *dst = alloc;
    return ret;
}

void ossl_rsa_acvp_test_gen_params_free(OSSL_PARAM *dst)
{
    OSSL_PARAM *p;

    if (dst == NULL)
        return;

    for (p = dst; p->key != NULL; ++p) {
        OPENSSL_free(p->data);
        p->data = NULL;
    }
    OPENSSL_free(dst);
}

int ossl_rsa_acvp_test_set_params(RSA *r, const OSSL_PARAM params[])
{
    RSA_ACVP_TEST *t;
    const OSSL_PARAM *p;

    if (r->acvp_test != NULL) {
        ossl_rsa_acvp_test_free(r->acvp_test);
        r->acvp_test = NULL;
    }

    t = OPENSSL_zalloc(sizeof(*t));
    if (t == NULL)
        return 0;

    /* Set the input parameters */
    if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XP1)) != NULL
         && !OSSL_PARAM_get_BN(p, &t->Xp1))
        goto err;
    if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XP2)) != NULL
         && !OSSL_PARAM_get_BN(p, &t->Xp2))
        goto err;
    if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XP)) != NULL
         && !OSSL_PARAM_get_BN(p, &t->Xp))
        goto err;
    if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XQ1)) != NULL
         && !OSSL_PARAM_get_BN(p, &t->Xq1))
        goto err;
    if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XQ2)) != NULL
         && !OSSL_PARAM_get_BN(p, &t->Xq2))
        goto err;
    if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XQ)) != NULL
         && !OSSL_PARAM_get_BN(p, &t->Xq))
        goto err;

    /* Setup the output parameters */
    t->p1 = BN_new();
    t->p2 = BN_new();
    t->q1 = BN_new();
    t->q2 = BN_new();
    r->acvp_test = t;
    return 1;
err:
    ossl_rsa_acvp_test_free(t);
    return 0;
}

int ossl_rsa_acvp_test_get_params(RSA *r, OSSL_PARAM params[])
{
    RSA_ACVP_TEST *t;
    OSSL_PARAM *p;

    if (r == NULL)
        return 0;

    t = r->acvp_test;
    if (t != NULL) {
        if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_P1)) != NULL
             && !OSSL_PARAM_set_BN(p, t->p1))
                    return 0;
        if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_P2)) != NULL
             && !OSSL_PARAM_set_BN(p, t->p2))
                    return 0;
        if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_Q1)) != NULL
             && !OSSL_PARAM_set_BN(p, t->q1))
                    return 0;
        if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_Q2)) != NULL
             && !OSSL_PARAM_set_BN(p, t->q2))
                    return 0;
    }
    return 1;
}

void ossl_rsa_acvp_test_free(RSA_ACVP_TEST *t)
{
    if (t != NULL) {
        BN_free(t->Xp1);
        BN_free(t->Xp2);
        BN_free(t->Xp);
        BN_free(t->Xq1);
        BN_free(t->Xq2);
        BN_free(t->Xq);
        BN_free(t->p1);
        BN_free(t->p2);
        BN_free(t->q1);
        BN_free(t->q2);
        OPENSSL_free(t);
    }
}

