/*
 * Copyright 2017-2026 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 may obtain a copy of the License at
 * https://www.openssl.org/source/license.html
 * or in the file LICENSE in the source distribution.
 */

#include <string.h>
#include <stdio.h>

#include <openssl/opensslconf.h>
#include <openssl/err.h>
#include <openssl/e_os2.h>
#include <openssl/ssl.h>
#include <openssl/ssl3.h>
#include <openssl/tls1.h>

#include "internal/nelem.h"
#include "testutil.h"

static SSL_CTX *ctx;
static SSL *s;

static int test_empty(void)
{
    STACK_OF(SSL_CIPHER) *sk = NULL, *scsv = NULL;
    const unsigned char bytes[] = { 0x00 };
    int ret = 0;

    if (!TEST_int_eq(SSL_bytes_to_cipher_list(s, bytes, 0, 0, &sk, &scsv), 0)
        || !TEST_ptr_null(sk)
        || !TEST_ptr_null(scsv))
        goto err;
    ret = 1;

err:
    sk_SSL_CIPHER_free(sk);
    sk_SSL_CIPHER_free(scsv);
    return ret;
}

static int test_unsupported(void)
{
    STACK_OF(SSL_CIPHER) *sk, *scsv;
    /* ECDH-RSA-AES256 (unsupported), ECDHE-ECDSA-AES128, <unassigned> */
    const unsigned char bytes[] = { 0xc0, 0x0f, 0x00, 0x2f, 0x01, 0x00 };
    int ret = 0;

    if (!TEST_true(SSL_bytes_to_cipher_list(s, bytes, sizeof(bytes),
            0, &sk, &scsv))
        || !TEST_ptr(sk)
        || !TEST_int_eq(sk_SSL_CIPHER_num(sk), 1)
        || !TEST_ptr(scsv)
        || !TEST_int_eq(sk_SSL_CIPHER_num(scsv), 0)
        || !TEST_str_eq(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk, 0)),
            "AES128-SHA"))
        goto err;

    ret = 1;
err:
    sk_SSL_CIPHER_free(sk);
    sk_SSL_CIPHER_free(scsv);
    return ret;
}

static int test_v3(void)
{
    STACK_OF(SSL_CIPHER) *sk = NULL, *scsv = NULL;
    /* ECDHE-ECDSA-AES256GCM, ECDHE-ECDSA-CHACHAPOLY, DHE-RSA-AES256GCM,
     * EMPTY-RENEGOTIATION-INFO-SCSV, FALLBACK-SCSV */
    const unsigned char bytes[] = { 0x00, 0x2f, 0x00, 0x33, 0x00, 0x9f, 0x00, 0xff,
        0x56, 0x00 };
    int ret = 0;

    if (!SSL_bytes_to_cipher_list(s, bytes, sizeof(bytes), 0, &sk, &scsv)
        || !TEST_ptr(sk)
        || !TEST_int_eq(sk_SSL_CIPHER_num(sk), 3)
        || !TEST_ptr(scsv)
        || !TEST_int_eq(sk_SSL_CIPHER_num(scsv), 2)
        || !TEST_str_eq(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk, 0)),
            "AES128-SHA")
        || !TEST_str_eq(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk, 1)),
            "DHE-RSA-AES128-SHA")
        || !TEST_str_eq(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(sk, 2)),
            "DHE-RSA-AES256-GCM-SHA384")
        || !TEST_str_eq(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(scsv, 0)),
            "TLS_EMPTY_RENEGOTIATION_INFO_SCSV")
        || !TEST_str_eq(SSL_CIPHER_get_name(sk_SSL_CIPHER_value(scsv, 1)),
            "TLS_FALLBACK_SCSV"))
        goto err;

    ret = 1;
err:
    sk_SSL_CIPHER_free(sk);
    sk_SSL_CIPHER_free(scsv);
    return ret;
}

int setup_tests(void)
{
    if (!TEST_ptr(ctx = SSL_CTX_new(TLS_server_method()))
        || !TEST_ptr(s = SSL_new(ctx)))
        return 0;

    ADD_TEST(test_empty);
    ADD_TEST(test_unsupported);
    ADD_TEST(test_v3);
    return 1;
}

void cleanup_tests(void)
{
    SSL_free(s);
    SSL_CTX_free(ctx);
}
