/*
    Copyright (C) 2008-2024, Millistream Market Data <support@millistream.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#ifndef MDFCRYPT_H
# define MDFCRYPT_H 1

#define MIN_DH_LENGTH 256
#define MAX_DH_LENGTH (MIN_DH_LENGTH * 4)
#define MAX_ENCRYPTED_MESSAGES_PER_KEY 4294967295
#define MAX_ENCRYPTED_BYTES (__UINT64_C(137438953440))

#if !OPENSSL_VERSION_PREREQ(1,1)
# define EVP_MD_CTX_free(a) EVP_MD_CTX_destroy(a)
#endif

struct c_algo {
	uint32_t id;
	char *name;
};

static const struct c_algo DIGESTS[] = {
	{ 0,  "MD5" },
	{ 1,  "SHA1" },
	{ 2,  "SHA256" },
	{ 4,  "SHA512" },
	{ 3,  "RIPEMD160" },
	{ 5,  "whirlpool" },
	{ 6,  "SHA3-224" },
	{ 7,  "SHA3-256" },
	{ 8,  "SHA3-384" },
#if OPENSSL_VERSION_PREREQ(1,1) /* for some reason 1.0.2g claims to load this, so we have to block it hard */
	{ 9,  "SHA3-512" },
#endif
	{ 10, "SM3" },
	{ 11, "blake2s256" },
	{ 12, "blake2b512" }
};

static const struct c_algo CIPHERS[] = {
	{ 0,  "AES-128-CTR" },
	{ 1,  "AES-192-CTR" },
	{ 2,  "AES-256-CTR" },
	{ 3,  "ChaCha20" },
	{ 4,  "SM4-CTR" },
	{ 5,  "ARIA-128-CTR" },
	{ 6,  "ARIA-192-CTR" },
	{ 7,  "ARIA-256-CTR" },
	{ 8,  "CAMELLIA-128-CTR" },
	{ 9,  "CAMELLIA-192-CTR" },
	{ 10, "CAMELLIA-256-CTR" }
};

enum enc_or_dec {
	DECRYPT,
	ENCRYPT
};

#if OPENSSL_VERSION_PREREQ(3,0)
EVP_PKEY *mdf_int_load_rsapublickey ();
#else
RSA *mdf_int_load_rsapublickey ();
#endif
int mdf_int_set_keys (struct crypto *crypto, const enum enc_or_dec enc_or_dec, unsigned char *nonce, int nonce_len);
int mdf_int_handle_server_rekey (struct crypto *crypto, uint8_t *data, const size_t tlen);
uint32_t mdf_int_check_digest (int i);
uint32_t mdf_int_check_cipher (int i);
uint32_t mdf_int_get_default_digests ();
uint32_t mdf_int_get_default_ciphers ();
int mdf_int_asn1_verify (EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen, const int choosen_digest);
#endif

