/****************************************************************
* *
* Copyright (c) 2013-2022 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#ifndef GTM_TLS_INTERFACE_H
#define GTM_TLS_INTERFACE_H
#ifndef GTM_TLS_INTERFACE_DEFINITIONS_INCLUDED
#define GTM_TLS_INTERFACE_DEFINITIONS_INCLUDED
#define GTM_TLS_API_VERSION 0x00000006
#define GTM_TLS_API_VERSION_SOCK 0x00000002 /* when TLS sockets added */
#define GTM_TLS_API_VERSION_RENEGOPT 0x00000004 /* WRITE /TLS renegotiate with options */
#define GTM_TLS_API_VERSION_NONBLOCK 0x00000005 /* WRITE /BLOCK("OFF") */
#define GTM_TLS_API_VERSION_GET_ERROR 0x00000006 /* gtm_tls_get_error() socket ptr for errbuf */
#define MAX_X509_LEN 256
#define MAX_ALGORITHM_LEN 64
#define MAX_TIME_STRLEN 32
#define MAX_TLSID_LEN 32
#define MAX_SESSION_ID_LEN 64 /* twice SSL_MAX_SSL_SESSION_ID_LENGTH since in hex */
#define INVALID_TLS_CONTEXT NULL
#define INVALID_TLS_SOCKET NULL
/* SSL/TLS protocol allows for renegoitations (change in cipher spec, etc.) to take place at any point during the communication. So,
* it is likely for a call to `gtm_tls_recv' or `gtm_tls_send' to initiate a renegoitation sequence in which case a `gtm_tls_recv'
* might have to 'send' data and `gtm_tls_send' to 'recv' data. In such cases, the SSL/TLS reference implementation returns one of
* the following two return codes. They do not indicate an error situation. Instead, they indicate that the reference implementation
* could not successfully complete the operation without reading or writing more data to the underlying TCP/IP connection and gives
* a chance to the application to wait for the underlying TCP/IP pipe to become ready for a read (if GTMTLS_WANT_READ is returned)
* or write (if GTMTLS_WANT_WRITE is returned).
*/
#define GTMTLS_WANT_READ -2
#define GTMTLS_WANT_WRITE -3
#define GTMTLS_PASSWD_ENV_PREFIX "gtmtls_passwd_"
/* below also defined in gtmcrypt_util.h so prevent redefinition in gtm_tls_impl.h */
#ifndef GTM_PASSPHRASE_MAX
#define GTM_PASSPHRASE_MAX 512 /* obfuscated */
#define GTM_PASSPHRASE_MAX_ASCII (GTM_PASSPHRASE_MAX / 2)
#elif GTM_PASSPHRASE_MAX != 512
#error "GTM-E-GTMTLSINTERFACE different values for GTM_PASSPHRASE_MAX"
#endif
/* Note these flags may be in either the ctx or ssl structures but not all
* may have meaning in both. */
/* GTMTLS_OP_INTERACTIVE_MODE and GTMTLS_OP_NOPWDENVVAR must match definition in gtmcrypt_interface,h */
/* Whether the library is loaded in an interactive environment so that password prompting can happen if needed. */
#define GTMTLS_OP_INTERACTIVE_MODE 0x00000001
/* Turn-on compression for SSL/TLS protocol. */
#define GTMTLS_OP_ENABLE_COMPRESSION 0x00000002
/* Socket created for a client-mode operation. */
#define GTMTLS_OP_CLIENT_MODE 0x00000004
/* Peer verification is needed. */
#define GTMTLS_OP_VERIFY_PEER 0x00000008
/* Socket device */
#define GTMTLS_OP_SOCKET_DEV 0x00000010
/* Socket (client) created for direct mode auditing (APD). Temporarily defined with GTMTLS_OP_SOCKET_DEV's value */
#define GTMTLS_OP_DM_AUDIT 0x00000010
/* No cipher list specifed at top tls level */
#define GTMTLS_OP_ABSENT_CIPHER 0x00000020
/* Default cipher list used */
#define GTMTLS_OP_DEFAULT_CIPHER 0x00000040
/* REPL_CIPHER_LIST used */
#define GTMTLS_OP_REPL_CIPHER 0x00000080
/* No verify mode specifed at top tls level */
#define GTMTLS_OP_ABSENT_VERIFYMODE 0x00000100
/* This is SSL_OP_ALLOW_CLIENT_RENEGOTIATION; Previously set between V62001-V62002A, but not used */
#define GTMTLS_OP_RENEGOTIATE_REQUESTED 0x00000200
/* No gtmcrypt_config or tls in config needed for client only use */
#define GTMTLS_OP_ABSENT_CONFIG 0x00000400
/* No environment variable for password - used by gc_update_passwd so must be same in gtmcrypt_interface.h */
#define GTMTLS_OP_NOPWDENVVAR 0x00000800
/* Bit mask for VERIFY_LEVEL options - one now and one planned but allow two more */
#define GTMTLS_OP_VERIFY_LEVEL_MASK 0x0000F000
#define GTMTLS_OP_VERIFY_LEVEL_CMPLMNT 0x7FFF0FFF /* 4SCA: 32bit complement */
/* Check SSL_get_verify_result after SSL_connect and other useful places */
#define GTMTLS_OP_VERIFY_LEVEL_CHECK 0x00001000
/* Default VERIFY_LEVEL options */
#define GTMTLS_OP_VERIFY_LEVEL_DEFAULT GTMTLS_OP_VERIFY_LEVEL_CHECK
/* For socket level only - explicit SSL_set_client_CA_list has been done */
#define GTMTLS_OP_CLIENT_CA 0x00010000
/* CAfile or CApath processed */
#define GTMTLS_OP_CA_LOADED 0x00020000
#define GTMTLS_OP_NOSHUTDOWN 0x00040000
/* NON BLOCKing WRITE so set SSL_MODE_ENABLE_PARTIAL_WRITE */
#define GTMTLS_OP_NONBLOCK_WRITE 0x00080000
#define GTMTLS_IS_FIPS_MODE(CTX) (TRUE == CTX->fips_mode)
#define GTMTLS_RUNTIME_LIB_VERSION(CTX) (CTX->runtime_version)
typedef struct gtm_tls_conn_info_struct
{
/* SSL Session Information */
char protocol[MAX_ALGORITHM_LEN]; /* Descriptive name of the negoitiated protocol (for instance, TLSv1). */
char session_algo[MAX_ALGORITHM_LEN];/* Algorithm negoitated by the SSL/TLS session. */
char session_id[MAX_SESSION_ID_LEN + 1]; /* Hexadecimal representation of the negotiated Session-ID. */
char *compression; /* Compression method used for the SSL/TLS session. */
int secure_renegotiation; /* 1 if SSL/TLS renegotiation is supported and 0 otherwise. */
int reused; /* Is the session reused? */
long session_expiry_timeout; /* Time at which this session expires (-1 if doesn't expire). */
/* Remote Certificate Information */
char cert_algo[MAX_ALGORITHM_LEN]; /* Certificate's asymmetric cryptography algorithm. */
int cert_nbits; /* Strength of the certificate's asymmetric cryptography. */
char subject[MAX_X509_LEN]; /* To whom the certificate belongs? */
char issuer[MAX_X509_LEN]; /* CA who issued the certificate. */
char not_before[MAX_TIME_STRLEN]; /* Date before which the certificate is not valid. */
char not_after[MAX_TIME_STRLEN]; /* Date after which the certificate is not valid. */
/* items after this added for GTM_TLS_API_VERSION_SOCK */
long options; /* bitmask of SSL options */
int renegotiation_pending; /* no handshake yet */
/* items after this added for GTM_TLS_API_VERSION_RENEGOPT */
int total_renegotiations; /* SSL_total_renegotiations */
int verify_mode; /* SSL_get_verify_mode */
} gtm_tls_conn_info;
typedef struct gtm_tls_ctx_struct
{
int flags;
int fips_mode;
unsigned long compile_time_version; /* OpenSSL version that this library is compiled with. */
unsigned long runtime_version; /* OpenSSL version that this library is currently running with. */
void *ctx;
int version; /* caller GTM_TLS_API_VERSION */
int plugin_version; /* added with GTM_TLS_API_VERSION_NONBLOCK */
} gtm_tls_ctx_t;
typedef struct gtm_tls_session_struct
{
int flags;
void *ssl;
void *session;
char tlsid[MAX_TLSID_LEN + 1];
gtm_tls_ctx_t *gtm_ctx;
char *errstr;
} gtm_tls_socket_t;
#endif /* GTM_TLS_INTERFACE_DEFINITIONS_INCLUDED */
/* Note: The below function prototypes should be kept in sync with the corresponding declarations/definitions in sr_unix/gtm_tls.h,
* sr_unix/gtm_tls.c, and sr_unix/gtm_tls_funclist.h.
*/
/* Returns the most recent error (null-terminated) related to the workings of the SSL/TLS reference implementation. */
extern const char *gtm_tls_get_error(gtm_tls_socket_t *);
/* If the most recent invocation of the SSL/TLS reference implementation resulted in a system call error, `gtm_tls_errno' returns
* the value of `errno'. Otherwise, -1 is returned in which case `gtm_tls_get_error' provides more information.
*/
extern int gtm_tls_errno(void);
/* Initializes the SSL/TLS context for a process. Typically invoked only once (unless the previous attempt failed). Attributes
* necessary to initialize the SSL/TLS context are obtained from the configuration file pointed to by `$gtmcrypt_config'.
*
* Arguments:
* `version' : The API version that the caller understands. Current version is 0x5.
* `flags' : Initialization flags as a bitmask. The first one the API understands is GTMTLS_OP_INTERACTIVE_MODE.
* Set this bitmask if the process doing the SSL/TLS initialization is run in an interactive mode. This lets
* the API decide if it can prompt for a password if a need arises while decrypting the private key.
*
* Returns a value, of type gtm_tls_ctx_t, representing the initialized SSL/TLS context. This context can be used, later by the
* application, to create as many SSL/TLS aware sockets as needed. In case of an error, INVALID_TLS_CONTEXT is returned in which
* case gtm_tls_get_error() provides the necessary error detail.
*/
extern gtm_tls_ctx_t *gtm_tls_init(int version, int flags);
/* Stores a M program provided password for later use.
*
* Arguments:
* `tls_ctx' : The SSL/TLS context corresponding to this process.
* `tlsid' : identifier of config file section to select the private key corresponding to this password.
* `obs_passwd' : obfuscated password in the same format as a gtmtls_passwd_
environment variable's value.
*
* Returns:
* 1 Success
* 0 Not an interactive context
* -1 Failure - use gtm_tls_get_error() to get reason
*/
extern int gtm_tls_store_passwd(gtm_tls_ctx_t *tls_ctx, const char *tlsid, const char *obs_passwd);
/* Provides additional information to merge with config file
*
* Arguments:
* `tls_ctx' : The SSL/TLS context corresponding to this process.
* `configstr': to be used by config_read_str.
*
* Returns:
* 0 Success
* -1 Failure - use gtm_tls_get_error() to get reason
*/
extern int gtm_tls_add_config(gtm_tls_ctx_t *tls_ctx, const char *idstr, const char *configstr);
/* Prefetches the password corresponding to a private key.
*
* Arguments:
* `tls_ctx' : The SSL/TLS context corresponding to this process.
* `env_name' : The name of the environment variable that corresponds to the private key in question. The SSL/TLS API identifies
* a private key by a name that is specified in the configuration file. The name of the environment variable is then
* obtained by prefixing "gtmtls_passwd_" to the identifier. So, if the identifier is `PRODUCTION', then the name
* of the environment variable is "gtmtls_passwd_PRODUCTION".
*
* No return value. Since this is only an attempt to prefetch the password, no error is reported. Another attempt will be made,
* later to acquire the password when actually decrypting the private key.
*
* Note 1: This function is typically invoked whenever the application detects that an environment variable of the form
* "gtmtls_passwd_<identifier>" is present in the environment but doesn't have any assoicated value. In such a case the below
* function prompts the user to provide the password before continuing any further. The password is not validated, but is stored
* for future use.
*
* Note 2: The function honors the GTMTLS_OP_INTERACTIVE_MODE flag passed to the `gtm_tls_init' function. If the application has
* initialized the SSL/TLS API in a non-interactive mode, the API does not prompt the user for password.
*/
extern void gtm_tls_prefetch_passwd(gtm_tls_ctx_t *tls_ctx, char *env_name);
/* Converts a Unix TCP/IP socket into a SSL/TLS aware socket.
*
* Arguments:
* `ctx' : The SSL/TLS context corresponding to this process.
* `prev_socket` : Pointer to an existing `gtm_tls_socket_t' structure. A non-null value indicates reuse.
* `sockfd' : The Unix TCP/IP socket identifier.
* `tls_id' : Identifier corresponding to the private key and certificate pair that should be used for future communication.
* The plugin searches for the identifier in the configuration file pointed to by `$gtmcrypt_config' to get other
* information corresponding to this connection (like, path to the private key, certificate and the format of the
* private key).
* `flags' : Additional configuration options. See GTMTLS_OP* macros for more details.
*
* Returns a value, of type gtm_tls_socket_t *, representing the initialized SSL/TLS aware socket. This value can be used for actual
* communication to provide security. In case of an error, INVALID_TLS_SOCKET is returned in which case gtm_tls_get_error()
* provides the necessary error detail. If `prev_socket' is non-NULL, then that storage area is used for setting up the new socket
* instead of creating a new storage area.
*
* Note 1: If the password corresponding to the `tls_id' has not yet been prefetched by the SSL/TLS API, then the API attempts to
* read the password from the environment.
*
* Note 2: The function honors the GTMTLS_OP_INTERACTIVE_MODE flag passed to the `gtm_tls_init' function. If the application has
* initialized the SSL/TLS API in a non-interactive mode, this function does not prompt the user for password.
*/
extern gtm_tls_socket_t *gtm_tls_socket(gtm_tls_ctx_t *ctx, gtm_tls_socket_t *prev_socket, int sockfd, char *id, int flags);
/* Connects using SSL/TLS aware socket. Assumes the other transport endpoint understands SSL/TLS.
*
* Arguments:
* `socket' : The SSL/TLS socket (initialized using `gtm_tls_socket').
*
* Returns 0 if the connection is successful. Otherwise, one of -1, GTMTLS_WANT_READ or GTMTLS_WANT_WRITE is returned. In case of
* -1, `gtm_tls_errno' and `gtm_tls_get_error' can be used to obtain the necessary error detail.
*
* Note: The function makes use of an existing SSL session (if one is available).
*/
extern int gtm_tls_connect(gtm_tls_socket_t *socket);
/* Accepts an incoming connection using SSL/TLS aware socket. Assumes the other transport endpoint understands SSL/TLS.
*
* Arguments:
* `socket' : The SSL/TLS socket (initialized using `gtm_tls_socket').
*
* Returns 0 if the connection is successful. Otherwise, one of -1, GTMTLS_WANT_READ or GTMTLS_WANT_WRITE is returned. In case of
* -1, `gtm_tls_errno' and `gtm_tls_get_error' can be used to obtain the necessary error detail.
*
*/
extern int gtm_tls_accept(gtm_tls_socket_t *socket);
/* Renegotiates an active SSL/TLS connection. Note: This function does the renegotiation in a blocking fashion and more importantly
* handles EINTR internally by retrying the renegotiation.
*
* Arguments:
* `socket' : The SSL/TLS socket (initialized using `gtm_tls_socket').
*
* Return value: none.
*/
extern int gtm_tls_renegotiate(gtm_tls_socket_t *socket);
/* Process configuration file options for WRITE /TLS("renegotiate") and then calls gtm_tls_renegotiate
*
* Arguments:
* `socket' : The SSL/TLS socket (initialized using `gtm_tls_socket').
*
* Return value: none.
*/
extern int gtm_tls_renegotiate_options(gtm_tls_socket_t *socket, int msec_timeout, char *idstr, char *configstr,
int tlsid_present);
/* Obtains additional SSL/TLS related information on the peer. This function is typically invoked to log information for diagnostic
* purposes.
*
* Arguments:
* `socket' : The SSL/TLS socket (initialized using `gtm_tls_socket').
* `conn_info' : A pointer to the `gtm_tls_conn_info' structure.
*
* Returns 0 if the connection is successful (and conn_info structure is filled). Otherwise, one of -1, GTMTLS_WANT_READ or
* GTMTLS_WANT_WRITE is returned. In case of -1, `gtm_tls_errno' and `gtm_tls_get_error' can be used to obtain the necessary error
* detail.
*/
extern int gtm_tls_get_conn_info(gtm_tls_socket_t *socket, gtm_tls_conn_info *conn_info);
/* Transmits message securely to the transport endpoint. This function should be invoked ONLY after successful invocations of either
* `gtm_tls_connect' or `gtm_tls_accept'.
*
* Arguments:
* `socket' : The SSL/TLS socket (initialized using `gtm_tls_socket').
* `buf' : Buffer containing the message that has to be transmitted.
* `send_len' : Length of the message that has to be transmitted.
*
* If successful, returns the number of bytes (> 0) actually sent through the SSL/TLS connection. Otherwise, one of -1,
* GTMTLS_WANT_READ or GTMTLS_WANT_WRITE is returned. In case of -1, `gtm_tls_errno' and `gtm_tls_get_error' can be used to obtain
* the necessary error detail.
*/
extern int gtm_tls_send(gtm_tls_socket_t *socket, char *buf, int send_len);
/* Receives message securely from the transport endpoint. This function should be invoked ONLY after successful invocations of
* either `gtm_tls_connect' or `gtm_tls_accept'.
*
* Arguments:
* `socket' : The SSL/TLS socket (initialized using `gtm_tls_socket').
* `buf' : Buffer in which the received data (after having decrypted) has to be placed.
* `recv_len' : Upper bound on the amount of data that can be received.
* become ready for a `send' or `recv'.
*
* If successful, returns the number of bytes (> 0) actually received from the SSL/TLS connection. Otherwise, one of -1,
* GTMTLS_WANT_READ or GTMTLS_WANT_WRITE is returned. In case of -1, `gtm_tls_errno' and `gtm_tls_get_error' can be used to obtain
* the necessary error detail.
*/
extern int gtm_tls_recv(gtm_tls_socket_t *socket, char *buf, int recv_len);
/* Returns the number of bytes cached in the SSL/TLS layer and is ready for immediate retrieval with the `gtm_tls_recv'.
*
* Arguments:
* `socket' : The SSL/TLS socket (initialized using `gtm_tls_socket').
*
* Note: Data from the peer is received in blocks. Therefore, data can be buffered inside the SSL/TLS layer and is ready for
* immediate retrieval with `gtm_tls_recv'. Given this, it is important for the application to call this function, if `select'
* or `poll' on the underlying TCP/IP socket indicates that the subsequent `recv' will block, and check if there are any bytes
* readily available.
*/
extern int gtm_tls_cachedbytes(gtm_tls_socket_t *socket);
/* Close the SSL/TLS socket connection.
*
* Arguments:
* `socket' : Pointer to the SSL/TLS socket (initialized using `gtm_tls_socket').
*
* Note: This function merely shuts down the active SSL/TLS connection. The session is still preserved in the SSL/TLS internal
* structures for reuse when a connection is made with the same server at a later point.
*
* Returns 0 if successful and -1 otherwise. In case of an error, `gtm_tls_errno' and `gtm_tls_get_error' can be used to obtain
* necessary error detail.
*
*/
extern void gtm_tls_socket_close(gtm_tls_socket_t *socket);
/* Closes an active SSL/TLS session. This frees up the session and thus makes the session not resuable for a future connection.
* Any subsequent connection will create a new session.
*
* Note: The function takes a pointer to the gtm_tls_socket_t structure. This is because it forces the actual `socket' value to be
* INVALID_TLS_SOCKET.
*/
extern void gtm_tls_session_close(gtm_tls_socket_t **socket);
/* Frees up any memory allocated by the SSL/TLS context. This function should typically be invoked at process exit.
*
* Arguments:
* `ctx' : Pointer to the SSL/TLS context (initialized using `gtm_tls_init').
*
* No return value.
*
* Note: The function takes a pointer to the gtm_tls_ctx_t structure. This is because it forces the actual `ctx' value to be
* INVALID_TLS_CONTEXT.
*/
extern void gtm_tls_fini(gtm_tls_ctx_t **ctx);
/* Return the value of GTM_TLS_API_VERSION for the gtm tls plugin. This can be
* used to check if the plugin supports features needed by the caller.
*
* Argument:
* caller_version : GTM_TLS_API_VERSION of caller - not used currently.
*
* Returns the GTM_TLS_API_VERSION of the plugin.
*/
extern int gtm_tls_version(int caller_version);
#endif