/* Copyright (c) 2020-2023 The Creators of Simphone

   See the file COPYING.LESSER.txt for copying permission.
*/

#ifndef _SSSL_H_
#define _SSSL_H_

#include "simtypes.h"

/* return SSL library version */
const char *sim_ssl_get_version (void);

#define SSL_KEY_EC 0        /* EC key index in struct _ssl_master */
#define SSL_KEY_RSA 1       /* RSA key index in sssl struct _ssl_master */
#define SSL_KEY_ANONYMOUS 2 /* anonymous EC key (for sim_ssl_new_key__) */

/* extract dynamically-allocated (SIMSTRING) binary public key out of (RSA or EC private) key. return nil if SIM_SSL_ERROR */
simtype sim_ssl_convert_key__ (void *key, int keyidx);

/* free private key (pointer to EVP_PKEY) */
void sim_ssl_free_key__ (void *key);

/* make or validate a private (RSA or EC) key and
   return pointer to EVP_PKEY (which the caller must free), or NULL if SIM_SSL_ERROR */
void *sim_ssl_new_key__ (const simtype key, int keyidx, simbool validate);

/* set private keys (pointers to EVP_PKEY) */
int sim_ssl_set_keys__ (void *ec, void *rsa);

/* initialize and deinitialize SSL library */
int ssl_init_ (const char *ciphers, const simtype curves, const simtype sigalgs);
void ssl_uninit_ (simbool init);

/* finish thread that used SSL functions */
void ssl_exit_thread_ (void);

/* free master key (pointer to struct _ssl_master)
   including contact ids, peer public keys and shared RSA key from socket after handshake */
void ssl_free (simsocket sock);

/* perform client handshake to contact address on a TCP socket descriptor.
   PROXY_ADDRESS_CONTROL/PROXY_ADDRESS_TRAVERSER establish special proxy connections.
   as a side effect, set contact ids and a copy of peer public keys and session master keys into the socket */
int ssl_handshake_client_ (simsocket sock, const char *address, int handshake);

/* perform server handshake on a TCP socket descriptor. */
#define ssl_handshake_server_(sock, handshake) ssl_handshake_client_ (sock, NULL, handshake)

#define SSL_HANDSHAKE_LOCAL (-1)  /* handshake from server to local socket */
#define SSL_HANDSHAKE_NOKEY 0     /* anonymous handshake with no key (client-side) */
#define SSL_HANDSHAKE_ANONYMOUS 1 /* handshake with anonymous key (server-side) */
#define SSL_HANDSHAKE_SERVER 2    /* handshake from proxy to customer */
#define SSL_HANDSHAKE_CLIENT 3    /* handshake between client and server */
#define SSL_HANDSHAKE_PROXY 4     /* handshake from customer to proxy */

/* regenerate anonymous EC key */
int ssl_reinit_ (void);

#define SSL_RSA_BITS_MIN 2048  /* minimal RSA public key size */
#define SSL_RSA_BITS_MAX 16384 /* maximal RSA public key size */

/* return maximal number of bytes that can be encrypted with RSA public key or non-positive in case of error.
   use nil for own key */
int ssl_rsa_size_ (const simtype key);

/* encrypt input data (if hash nil) or verify hash with RSA public key; return encrypted/verified data or nil */
simtype ssl_rsa_crypt_public_ (const simtype input, const simtype key, const simtype hash);

/* decrypt or sign input data with set RSA private key; return decrypted/signed data or nil */
simtype ssl_rsa_crypt_private_ (const simtype input, simbool decrypt);

/* debug logging */
int ssl_log_keys (const char *module, int level, simnumber id);

#endif
