{ +-------------------------------------------------------------+ }
{ |                                                             | }
{ |   GM-Software                                               | }
{ |   ===========                                               | }
{ |                                                             | }
{ |   Project: All Projects                                     | }
{ |                                                             | }
{ |   Description: OpenSSL call level API.                      | }
{ |                                                             | }
{ |                                                             | }
{ |   Copyright (C) - 2017 - Gerrit Moeller.                    | }
{ |                                                             | }
{ |   Source code dstributed under MIT license.                 | }
{ |                                                             | }
{ |   See: https://www.gm-software.de                           | }
{ |                                                             | }
{ +-------------------------------------------------------------+ }


{$INCLUDE GMCompilerSettings.inc}

{$IFDEF DELAY_LOAD_WIN_DLLs}
  {$DEFINE DELAY_LOAD_OPENSSL_DLL}
{$ENDIF DELAY_LOAD_WIN_DLLs}

unit GMOpenSSLApi;

interface

uses SysUtils, {$IFDEF JEDIAPI}jwaWinType{$ELSE}Windows{$ENDIF};

const

{$IFDEF CPU64}
  cStrSSLDllName = 'libssl-1_1-x64.dll';
  cStrCryptoDllName = 'libcrypto-1_1-x64.dll';
{$ELSE}
  cStrSSLDllName = 'libssl-1_1.dll';
  cStrCryptoDllName = 'libcrypto-1_1.dll';
{$ENDIF}


const

  EVP_MAX_MD_SIZE       = 64; //* longest known is SHA512 */
  EVP_MAX_KEY_LENGTH    = 32;
  EVP_MAX_IV_LENGTH     = 16;
  EVP_MAX_BLOCK_LENGTH  = 32;

  SHA_DIGEST_LENGTH     = 20;


type

  csize_t = LongWord;
  UInt64 = Int64;

  TSslPtr = Pointer;

  PPByte = ^PByte;

  POPENSSL_INIT_SETTINGS = type TSslPtr;

  PSslPtr = ^TSslPtr;
  PSSL_CTX = type TSslPtr;
  PSSL = type TSslPtr;
  PSSL_METHOD = type TSslPtr;
  PEVP_MD	= type TSslPtr;
  PBIO_METHOD = Type TSslPtr;
  PBIO = type TSslPtr;
  PSession = type TSslPtr;
  PX509_STORE = type TSslPtr;

  PRSA = type TSslPtr;
  PPRSA = ^PRSA;
  PDH = type TSslPtr;
  PSTACK_OFX509 = type TSslPtr;

  PX509 = type TSslPtr;
  PPX509 = ^PX509;

  PEVP_PKEY = type TSslPtr;
  PPEVP_PKEY = ^PEVP_PKEY;

  PASN1_UTCTIME = type TSslPtr;
  PASN1_cInt = type TSslPtr;
  PPasswdCb = type TSslPtr;

  PSSL_CIPHER = type TSslPtr;

  PFunction = procedure;

  X509_NAME = record
    entries: pointer;
    modified: LongInt;
    bytes: pointer;
    hash: LongWord;
  end;
  PX509_NAME = ^X509_NAME;

  DES_cblock = array[0..7] of Byte;
  PDES_cblock = ^DES_cblock;

  des_ks_struct = packed record
    ks: DES_cblock;
    weak_key: LongInt;
  end;
  des_key_schedule = array[1..16] of des_ks_struct;
  PDES_key_schedule = ^des_key_schedule;

  PRAND_METHOD = type TSslPtr;

  PEVP_MD_CTX = type TSslPtr;

  PEVP_CIPHER_CTX = type TSslPtr;

  // RSA
  PENGINE = type TSslPtr;
  PBIGNUM = type TSslPtr;
  PBN_GENCB = type TSslPtr;
  PBN_MONT_CTX = type TSslPtr;
  PBN_CTX = type TSslPtr;

  PRSA_METHOD = type TSslPtr;

  PASN1_TYPE = type TSslPtr;

  PEVP_CIPHER = type TSslPtr;

  Ppem_password_cb = type TSslPtr;

  PCRYPTO_THREADID = ^CRYPTO_THREADID;
  CRYPTO_THREADID = record
    ptr: Pointer;
    val: LongWord;
  end;

  EOpenSSLError = class (Exception);


const

  // OPENSSL_INIT flag range 0xfff00000 reserved for OPENSSL_init_ssl()
  // Max OPENSSL_INIT flag value is 0x80000000

  OPENSSL_INIT_NO_ADD_ALL_DIGESTS     = $00000020;
  OPENSSL_INIT_LOAD_CONFIG            = $00000040;
  OPENSSL_INIT_NO_LOAD_CONFIG         = $00000080;
  OPENSSL_INIT_ASYNC                  = $00000100;
  OPENSSL_INIT_ENGINE_RDRAND          = $00000200;
  OPENSSL_INIT_ENGINE_DYNAMIC         = $00000400;
  OPENSSL_INIT_ENGINE_OPENSSL         = $00000800;
  OPENSSL_INIT_ENGINE_CRYPTODEV       = $00001000;
  OPENSSL_INIT_ENGINE_CAPI            = $00002000;
  OPENSSL_INIT_ENGINE_PADLOCK         = $00004000;
  OPENSSL_INIT_ENGINE_DASYNC          = $00008000;

  OPENSSL_INIT                        = $00010000; // <-- reserved for internal use!
  OPENSSL_INIT_ENGINE_AFALG           = $00020000;

  OPENSSL_INIT_ENGINE_ALL_BUILTIN     =  OPENSSL_INIT_ENGINE_RDRAND or OPENSSL_INIT_ENGINE_DYNAMIC or OPENSSL_INIT_ENGINE_CRYPTODEV or
                                         OPENSSL_INIT_ENGINE_CAPI or OPENSSL_INIT_ENGINE_PADLOCK;

  SSL_ERROR_NONE = 0;
  SSL_ERROR_SSL = 1;
  SSL_ERROR_WANT_READ = 2;
  SSL_ERROR_WANT_WRITE = 3;
  SSL_ERROR_WANT_X509_LOOKUP = 4;
  SSL_ERROR_SYSCALL = 5; //look at error stack/return value/errno
  SSL_ERROR_ZERO_RETURN = 6;
  SSL_ERROR_WANT_CONNECT = 7;
  SSL_ERROR_WANT_ACCEPT = 8;
  
  SSL_CTRL_NEED_TMP_RSA = 1;
  SSL_CTRL_SET_TMP_RSA = 2;
  SSL_CTRL_SET_TMP_DH = 3;
  SSL_CTRL_SET_TMP_ECDH = 4;
  SSL_CTRL_SET_TMP_RSA_CB = 5;
  SSL_CTRL_SET_TMP_DH_CB = 6;
  SSL_CTRL_SET_TMP_ECDH_CB = 7;
  SSL_CTRL_GET_SESSION_REUSED = 8;
  SSL_CTRL_GET_CLIENT_CERT_REQUEST = 9;
  SSL_CTRL_GET_NUM_RENEGOTIATIONS = 10;
  SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS = 11;
  SSL_CTRL_GET_TOTAL_RENEGOTIATIONS = 12;
  SSL_CTRL_GET_FLAGS = 13;
  SSL_CTRL_EXTRA_CHAIN_CERT = 14;
  SSL_CTRL_SET_MSG_CALLBACK = 15;
  SSL_CTRL_SET_MSG_CALLBACK_ARG = 16;
{ only applies to datagram connections  }
  SSL_CTRL_SET_MTU = 17;
{ Stats  }
  SSL_CTRL_SESS_NUMBER = 20;
  SSL_CTRL_SESS_CONNECT = 21;
  SSL_CTRL_SESS_CONNECT_GOOD = 22;
  SSL_CTRL_SESS_CONNECT_RENEGOTIATE = 23;
  SSL_CTRL_SESS_ACCEPT = 24;
  SSL_CTRL_SESS_ACCEPT_GOOD = 25;
  SSL_CTRL_SESS_ACCEPT_RENEGOTIATE = 26;
  SSL_CTRL_SESS_HIT = 27;
  SSL_CTRL_SESS_CB_HIT = 28;
  SSL_CTRL_SESS_MISSES = 29;
  SSL_CTRL_SESS_TIMEOUTS = 30;
  SSL_CTRL_SESS_CACHE_FULL = 31;
  SSL_CTRL_OPTIONS = 32;
  SSL_CTRL_MODE = 33;
  SSL_CTRL_GET_READ_AHEAD = 40;
  SSL_CTRL_SET_READ_AHEAD = 41;
  SSL_CTRL_SET_SESS_CACHE_SIZE = 42;
  SSL_CTRL_GET_SESS_CACHE_SIZE = 43;
  SSL_CTRL_SET_SESS_CACHE_MODE = 44;
  SSL_CTRL_GET_SESS_CACHE_MODE = 45;
  SSL_CTRL_GET_MAX_CERT_LIST = 50;
  SSL_CTRL_SET_MAX_CERT_LIST = 51;

{* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
 * when just a single record has been written): *}
  SSL_MODE_ENABLE_PARTIAL_WRITE = 1;
{* Make it possible to retry SSL_write() with changed buffer location
 * (buffer contents must stay the same!); this is not the default to avoid
 * the misconception that non-blocking SSL_write() behaves like
 * non-blocking write(): *}
  SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = 2;
{* Never bother the application with retries if the transport
 * is blocking: *}
  SSL_MODE_AUTO_RETRY = 4;
{* Don't attempt to automatically build certificate chain *}
  SSL_MODE_NO_AUTO_CHAIN = 8;

  SSL_OP_NO_SSLv2 = $01000000;
  SSL_OP_NO_SSLv3 = $02000000;
  SSL_OP_NO_TLSv1 = $04000000;
  SSL_OP_ALL = $000FFFFF;
  SSL_VERIFY_NONE = $00;
  SSL_VERIFY_PEER = $01;

  OPENSSL_DES_DECRYPT = 0;
  OPENSSL_DES_ENCRYPT = 1;

  X509_V_OK =	0;
  X509_V_ILLEGAL = 1;
  X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 2;
  X509_V_ERR_UNABLE_TO_GET_CRL = 3;
  X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE = 4;
  X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE = 5;
  X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY = 6;
  X509_V_ERR_CERT_SIGNATURE_FAILURE = 7;
  X509_V_ERR_CRL_SIGNATURE_FAILURE = 8;
  X509_V_ERR_CERT_NOT_YET_VALID = 9;
  X509_V_ERR_CERT_HAS_EXPIRED = 10;
  X509_V_ERR_CRL_NOT_YET_VALID = 11;
  X509_V_ERR_CRL_HAS_EXPIRED = 12;
  X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 13;
  X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 14;
  X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD = 15;
  X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 16;
  X509_V_ERR_OUT_OF_MEM = 17;
  X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = 18;
  X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 19;
  X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 20;
  X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = 21;
  X509_V_ERR_CERT_CHAIN_TOO_LONG = 22;
  X509_V_ERR_CERT_REVOKED = 23;
  X509_V_ERR_INVALID_CA = 24;
  X509_V_ERR_PATH_LENGTH_EXCEEDED = 25;
  X509_V_ERR_INVALID_PURPOSE = 26;
  X509_V_ERR_CERT_UNTRUSTED = 27;
  X509_V_ERR_CERT_REJECTED = 28;
  //These are 'informational' when looking for issuer cert
  X509_V_ERR_SUBJECT_ISSUER_MISMATCH = 29;
  X509_V_ERR_AKID_SKID_MISMATCH = 30;
  X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH = 31;
  X509_V_ERR_KEYUSAGE_NO_CERTSIGN = 32;
  X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER = 33;
  X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION = 34;
  //The application is not happy
  X509_V_ERR_APPLICATION_VERIFICATION = 50;

  SSL_FILETYPE_PEM = 1;
  SSL_FILETYPE_ASN1 = 2;

  EVP_PKEY_RSA = 6;

  // RSA
  RSA_PKCS1_PADDING      = 1;
  RSA_SSLV23_PADDING     = 2;
  RSA_NO_PADDING         = 3;
  RSA_PKCS1_OAEP_PADDING = 4;

  // BIO

  BIO_NOCLOSE	        = $00;
  BIO_CLOSE 	        = $01;

  //* modifiers */
  BIO_FP_READ		= $02;
  BIO_FP_WRITE		= $04;
  BIO_FP_APPEND		= $08;
  BIO_FP_TEXT		= $10;

  BIO_C_SET_CONNECT                 = 100;
  BIO_C_DO_STATE_MACHINE            = 101;
  BIO_C_SET_NBIO	            = 102;
  BIO_C_SET_PROXY_PARAM	            = 103;
  BIO_C_SET_FD	                    = 104;
  BIO_C_GET_FD		            = 105;
  BIO_C_SET_FILE_PTR	            = 106;
  BIO_C_GET_FILE_PTR	            = 107;
  BIO_C_SET_FILENAME	            = 108;
  BIO_C_SET_SSL		            = 109;
  BIO_C_GET_SSL		            = 110;
  BIO_C_SET_MD		            = 111;
  BIO_C_GET_MD	                    = 112;
  BIO_C_GET_CIPHER_STATUS           = 113;
  BIO_C_SET_BUF_MEM 	            = 114;
  BIO_C_GET_BUF_MEM_PTR  	    = 115;
  BIO_C_GET_BUFF_NUM_LINES          = 116;
  BIO_C_SET_BUFF_SIZE	            = 117;
  BIO_C_SET_ACCEPT 	            = 118;
  BIO_C_SSL_MODE 	            = 119;
  BIO_C_GET_MD_CTX	            = 120;
  BIO_C_GET_PROXY_PARAM	            = 121;
  BIO_C_SET_BUFF_READ_DATA 	    = 122; // data to read first */
  BIO_C_GET_CONNECT	 	    = 123;
  BIO_C_GET_ACCEPT		    = 124;
  BIO_C_SET_SSL_RENEGOTIATE_BYTES   = 125;
  BIO_C_GET_SSL_NUM_RENEGOTIATES    = 126;
  BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT = 127;
  BIO_C_FILE_SEEK		    = 128;
  BIO_C_GET_CIPHER_CTX		    = 129;
  BIO_C_SET_BUF_MEM_EOF_RETURN	= 130;//*return end of input value*/
  BIO_C_SET_BIND_MODE		= 131;
  BIO_C_GET_BIND_MODE		= 132;
  BIO_C_FILE_TELL		= 133;
  BIO_C_GET_SOCKS		= 134;
  BIO_C_SET_SOCKS		= 135;

  BIO_C_SET_WRITE_BUF_SIZE	= 136;//* for BIO_s_bio */
  BIO_C_GET_WRITE_BUF_SIZE	= 137;
  BIO_C_MAKE_BIO_PAIR		= 138;
  BIO_C_DESTROY_BIO_PAIR	= 139;
  BIO_C_GET_WRITE_GUARANTEE	= 140;
  BIO_C_GET_READ_REQUEST	= 141;
  BIO_C_SHUTDOWN_WR		= 142;
  BIO_C_NREAD0		        = 143;
  BIO_C_NREAD			= 144;
  BIO_C_NWRITE0			= 145;
  BIO_C_NWRITE			= 146;
  BIO_C_RESET_READ_REQUEST	= 147;
  BIO_C_SET_MD_CTX		= 148;

  BIO_C_SET_PREFIX		= 149;
  BIO_C_GET_PREFIX		= 150;
  BIO_C_SET_SUFFIX		= 151;
  BIO_C_GET_SUFFIX		= 152;

  BIO_C_SET_EX_ARG		= 153;
  BIO_C_GET_EX_ARG		= 154;

//DES modes
  DES_ENCRYPT = 1;
  DES_DECRYPT = 0;


 { --------------------- }
 { ---- SSL Library ---- }
 { --------------------- }

  function SSL_get_error(ASSL: PSSL; ret_code: LongInt): LongInt; cdecl;
  function SSL_library_init: LongInt; cdecl;
  procedure SSL_load_error_strings; cdecl;
  function SSL_set_fd(ASSL: PSSL; fd: LongInt): LongInt; cdecl;
  function SSL_ctrl(ASSL: PSSL; cmd: LongInt; larg: Int64; parg: Pointer): Int64; cdecl;

  function SSL_CTX_new(AMethod: PSSL_METHOD): PSSL_CTX; cdecl;
  function SSL_CTX_set_cipher_list(ASSL: PSSL_CTX; str: PAnsiChar): LongInt; cdecl;
  function SSL_CTX_up_ref(ASSL: PSSL_CTX): LongInt; cdecl;
  procedure SSL_CTX_free(ASSL: PSSL_CTX); cdecl;
  function SSL_CTX_ctrl(ctx: PSSL_CTX; cmd: LongInt; larg: Int64; parg: Pointer): Int64; cdecl;
  function SSL_CTX_use_PrivateKey(ctx: PSSL_CTX; pkey: TSslPtr): LongInt; cdecl;
  function SSL_CTX_use_PrivateKey_ASN1(pk: LongInt; ctx: PSSL_CTX; d: TSslPtr; len: LongInt): LongInt; cdecl;
  procedure SSL_CTX_set_verify(ctx: PSSL_CTX; mode: LongInt; arg2: TSslPtr); cdecl;

  function SSL_CTX_use_RSAPrivateKey_file(ctx: PSSL_CTX; filename: PAnsiChar; _type: LongInt): LongInt; cdecl;
  function SSL_CTX_use_certificate(ctx: PSSL_CTX; cert: TSslPtr): LongInt; cdecl;
  function SSL_CTX_use_certificate_ASN1(ctx: PSSL_CTX; len: LongInt; certdata: TSslPtr): LongInt; cdecl;
  function SSL_CTX_use_certificate_file(ctx: PSSL_CTX; filename: PAnsiChar; filetype: LongInt): LongInt; cdecl;
  function SSL_CTX_use_certificate_chain_file(ctx: PSSL_CTX; filename: PAnsiChar): LongInt; cdecl;
  function SSL_CTX_check_private_key(ctx: PSSL_CTX): LongInt; cdecl;
  procedure SSL_CTX_set_default_passwd_cb(ctx: PSSL_CTX; cb: TSslPtr); cdecl;
  procedure SSL_CTX_set_default_passwd_cb_userdata(ctx: PSSL_CTX; u: TSslPtr); cdecl;
  function SSL_CTX_load_verify_locations(ctx: PSSL_CTX; filename: PAnsiChar; path: PAnsiChar): LongInt; cdecl;

  procedure SSL_CTX_set_cert_store(pSslCtx: PSSL_CTX; pCertStore: PX509_STORE); cdecl;
  procedure SSL_CTX_set1_cert_store(pSslCtx: PSSL_CTX; pCertStore: PX509_STORE); cdecl;
  function SSL_CTX_get_cert_store(pSslCtx: PSSL_Ctx): PX509_STORE; cdecl;

  function TLS_method: PSSL_METHOD; cdecl;
  function TLS_client_method: PSSL_METHOD; cdecl;
  function TLS_server_method: PSSL_METHOD; cdecl;

  function SSLv23_method: PSSL_METHOD; cdecl;
  function SSLv23_server_method: PSSL_METHOD; cdecl;
  function SSLv23_client_method: PSSL_METHOD; cdecl;

  function TLSv1_method: PSSL_METHOD; cdecl;
  function TLSv1_server_method: PSSL_METHOD; cdecl;
  function TLSv1_client_method: PSSL_METHOD; cdecl;

  function TLSv1_1_method: PSSL_METHOD; cdecl;
  function TLSv1_1_server_method: PSSL_METHOD; cdecl;
  function TLSv1_1_client_method: PSSL_METHOD; cdecl;

  function TLSv1_2_method: PSSL_METHOD; cdecl;
  function TLSv1_2_server_method: PSSL_METHOD; cdecl;
  function TLSv1_2_client_method: PSSL_METHOD; cdecl;

  function DTLS_method: PSSL_METHOD; cdecl;
  function DTLS_server_method: PSSL_METHOD; cdecl;
  function DTLS_client_method: PSSL_METHOD; cdecl;

  function DTLSv1_method: PSSL_METHOD; cdecl;
  function DTLSv1_server_method: PSSL_METHOD; cdecl;
  function DTLSv1_client_method: PSSL_METHOD; cdecl;

  function DTLSv1_2_method: PSSL_METHOD; cdecl;
  function DTLSv1_2_server_method: PSSL_METHOD; cdecl;
  function DTLSv1_2_client_method: PSSL_METHOD; cdecl;

  function SSL_use_certificate(ASSL: PSSL; cert: PX509): LongInt; cdecl;
  function SSL_use_certificate_ASN1(assl: PSSL; data: TSslPtr; datalen: LongInt): LongInt; cdecl;
  function SSL_use_certificate_file(assl: PSSL; filename: PAnsiChar; filetype: LongInt): LongInt; cdecl;

  function SSL_use_PrivateKey(assl: PSSL; pkey: PEVP_PKEY): LongInt; cdecl;
  function SSL_use_PrivateKey_ASN1(keyKind: LongInt; ssl: PSSL; keydata: Pointer; datalen: LongInt): LongInt; cdecl;
  function SSL_use_PrivateKey_file(ssl: PSSL; filename: PAnsiChar; filetype: LongInt): LongInt; cdecl;

  function SSL_new(ctx: PSSL_CTX): PSSL; cdecl;
  procedure SSL_free(ssl: PSSL); cdecl;
  function SSL_accept(ssl: PSSL): LongInt; cdecl;
  function SSL_connect(ssl: PSSL): LongInt; cdecl;
  function SSL_shutdown(ssl: PSSL): LongInt; cdecl;
  function SSL_read(ssl: PSSL; buf: PAnsiChar; buflen: LongInt): LongInt; cdecl;
  function SSL_peek(ssl: PSSL; buf: PAnsiChar; buflen: LongInt): LongInt; cdecl;
  function SSL_write(ssl: PSSL; buf: PAnsiChar; buflen: LongInt): LongInt; cdecl;
  function SSL_pending(ssl: PSSL): LongInt; cdecl;
  function SSL_get_version(ssl: PSSL): PAnsiChar; cdecl;
  function SSL_get_peer_certificate(ssl: PSSL): PX509; cdecl;
  function SSL_get_current_cipher(assl: PSSL): TSslPtr; cdecl;
  function SSL_get_verify_result(ssl: PSSL): LongInt; cdecl;

  function SSL_CIPHER_get_name(cipher: PSSL_CIPHER): PAnsiChar; cdecl;
  function SSL_CIPHER_get_bits(cipher: PSSL_CIPHER; alg_bits: PLongInt): LongInt; cdecl;
  function SSL_CIPHER_get_version(cipher: PSSL_CIPHER): PAnsiChar; cdecl;
  function SSL_CIPHER_description(cipher: PSSL_CIPHER; buffer: PAnsiChar; bufSize: LongInt): PAnsiChar; cdecl;

  procedure SSL_copy_session_id(dest, src: PSSL); cdecl;
  function SSL_get_session(ssl: PSSL): PSession; cdecl;
  function SSL_set_session(ssl: PSSL; session: PSession): LongInt; cdecl;

  procedure OpenSSL_add_all_algorithms; cdecl;
  procedure OpenSSL_add_all_ciphers; cdecl;
  procedure OpenSSL_add_all_digests; cdecl;

  procedure EVP_cleanup; cdecl;


 { ------------------------ }
 { ---- Crypto Library ---- }
 { ------------------------ }

  function ERR_get_error: LongWord; cdecl;
  function ERR_peek_error: LongWord; cdecl;
  function ERR_peek_last_error: LongWord; cdecl;

  function ERR_error_string(errorCode: LongWord; buffer: PAnsiChar): PAnsiChar; cdecl;
  procedure ERR_error_string_n(errorCode: LongWord; buffer: PAnsiChar; bufSize: size_t); cdecl;

  function ERR_lib_error_string(errorCode: LongWord): PAnsiChar; cdecl;
  function ERR_func_error_string(errorCode: LongWord): PAnsiChar; cdecl;
  function ERR_reason_error_string(errorCode: LongWord): PAnsiChar; cdecl;

  procedure ERR_remove_state(threadId: LongWord); cdecl;
  procedure ERR_remove_thread_state(tid: PCRYPTO_THREADID); cdecl;

  function OPENSSL_init_new: POPENSSL_INIT_SETTINGS; cdecl;
  function OPENSSL_INIT_set_config_appname(init: POPENSSL_INIT_SETTINGS; name: PAnsiChar): LongInt; cdecl;
  procedure OPENSSL_INIT_free(init: POPENSSL_INIT_SETTINGS); cdecl;
  function OPENSSL_init_crypto(opts: UInt64; settings: POPENSSL_INIT_SETTINGS): LongInt; cdecl;
  procedure OPENSSL_cleanup; cdecl;

  procedure CRYPTO_THREADID_set_numeric(id: PCRYPTO_THREADID; val: LongWord); cdecl;
  procedure CRYPTO_THREADID_set_pointer(id: PCRYPTO_THREADID; ptr: Pointer); cdecl;
  procedure CRYPTO_THREADID_current(id: PCRYPTO_THREADID); cdecl;

  function X509_new: PX509; cdecl;
  procedure X509_free(x509: PX509); cdecl;

  procedure DES_random_key(ret: PDES_cblock); cdecl;
  function DES_set_key(Key: PDES_cblock; schedule: PDES_key_schedule): LongInt; cdecl;
  function DES_key_sched(Key: PDES_cblock; schedule: PDES_key_schedule): LongInt; cdecl;
  function DES_set_key_checked(Key: PDES_cblock; schedule: PDES_key_schedule): LongInt; cdecl;
  procedure DES_set_key_unchecked(Key: PDES_cblock; schedule: PDES_key_schedule); cdecl;

  procedure DES_set_odd_parity(Key: PDES_cblock); cdecl;
  function DES_is_weak_key(Key: PDES_cblock): LongInt; cdecl;

  procedure DES_ecb_encrypt(input, output: PDES_cblock; schedule: PDES_key_schedule; enc: LongInt); cdecl;
  procedure DES_ecb2_encrypt(input, output: PDES_cblock; schedule1, schedule2: PDES_key_schedule; enc: LongInt); cdecl;
  procedure DES_ecb3_encrypt(input, output: PDES_cblock; schedule1, schedule2, schedule3: PDES_key_schedule; enc: LongInt); cdecl;

  function X509_STORE_new: PX509_STORE; cdecl;
  procedure X509_STORE_free(pStore: PX509_STORE); cdecl;
  function X509_STORE_lock(pStore: PX509_STORE): LongInt; cdecl;
  function X509_STORE_unlock(pStore: PX509_STORE): LongInt; cdecl;
  function X509_STORE_up_ref(pStore: PX509_STORE): LongInt; cdecl;

  function d2i_X509(ppx509: PPX509; in_Data: PPByte; len: LongInt): PX509; cdecl;
  function i2d_X509(px509: PX509; out_Data: PPByte): LongInt; cdecl;
  function i2d_re_X509_tbs(px509: PX509; out_Data: PPByte): LongInt; cdecl;

  function X509_STORE_add_cert(pStore: PX509_STORE; cert: PX509): LongInt; cdecl;



//procedure InitializeOpenSSL;



implementation

uses GMStrDef, GMCommon {$IFDEF JEDIAPI}, jwaWinBase{$ENDIF};

resourcestring

  RStrRoutineNotFound = 'Routine "%s" not found in DLL "%s"';


{ ------------------------- }
{ ---- Helper Routines ---- }
{ ------------------------- }

function LoadProcAddress(const AModuleName: TGMString; const AProcName: AnsiString; const ACheck: Boolean = True): Pointer;
var moduleHandle: HMODULE; lastErr: DWORD;
begin
//Result := nil;
  moduleHandle := GetModuleHandle(PGMChar(AModuleName));
  if moduleHandle = 0 then
   begin
    moduleHandle := LoadLibrary(PGMChar(AModuleName));
    if (moduleHandle = 0) and ACheck then
     begin
      lastErr := GetLastError;
      GMAPICheckObjParams('LoadLibrary("'+AModuleName+'")', '', lastErr, moduleHandle <> 0, [PGMChar(AModuleName)]);
      //GMAPICheckObj('LoadLibrary("'+AModuleName+'")', ': "'+AModuleName+'"', lastErr, moduleHandle <> 0);
     end;
   end;

  if moduleHandle = 0 then Result := nil else Result := GetProcAddress(moduleHandle, PAnsiChar(AProcName));
  if not Assigned(Result) and ACheck then raise EOpenSSLError.Create(GMFormat(RStrRoutineNotFound, [AProcName, AModuleName]));
end;

//procedure InitializeOpenSSL;
//type TSslLibraryInit = function: LongInt; cdecl;
//   TSslLoadErrorStrings = procedure; cdecl;
//var _SslLibraryInit: TSslLibraryInit; _SslLoadErrorStrings: TSslLoadErrorStrings;
//begin
//_SslLibraryInit := LoadProcAddress(cStrSSLDllName, 'SSL_library_init', False);
//if Assigned(_SslLibraryInit) then _SslLibraryInit;
//
//_SslLoadErrorStrings := LoadProcAddress(cStrSSLDllName, 'SSL_load_error_strings', False);
//if Assigned(_SslLoadErrorStrings) then _SslLoadErrorStrings;
//
////OpenSSL_add_all_algorithms;
////if assigned(_RandScreen) then _RandScreen;
//end;


{ --------------------- }
{ ---- SSL Library ---- }
{ --------------------- }

{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_get_error: function (ASSL: PSSL; ret_code: LongInt): LongInt; cdecl = nil;

function SSL_get_error;
begin
  if not Assigned(vf_SSL_get_error) then vf_SSL_get_error := LoadProcAddress(cStrSSLDllName, 'SSL_get_error');
  Result := vf_SSL_get_error(ASSL, ret_code);
end;
{$ELSE}
function SSL_get_error; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_library_init: function: LongInt; cdecl = nil;

function SSL_library_init;
begin
  if not Assigned(vf_SSL_library_init) then vf_SSL_library_init := LoadProcAddress(cStrSSLDllName, 'SSL_library_init');
  Result := vf_SSL_library_init;
end;
{$ELSE}
function SSL_library_init; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_load_error_strings: procedure; cdecl = nil;

procedure SSL_load_error_strings;
begin
  if not Assigned(vf_SSL_load_error_strings) then vf_SSL_load_error_strings := LoadProcAddress(cStrSSLDllName, 'SSL_load_error_strings');
  vf_SSL_load_error_strings;
end;
{$ELSE}
procedure SSL_load_error_strings; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_set_cipher_list: function (ASSL: PSSL_CTX; str: PAnsiChar): LongInt; cdecl = nil;

function SSL_CTX_set_cipher_list;
begin
  if not Assigned(vf_SSL_CTX_set_cipher_list) then vf_SSL_CTX_set_cipher_list := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_set_cipher_list');
  Result := vf_SSL_CTX_set_cipher_list(ASSL, str);
end;
{$ELSE}
function SSL_CTX_set_cipher_list; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_new: function (AMethod: PSSL_METHOD): PSSL_CTX; cdecl = nil;

function SSL_CTX_new;
begin
  if not Assigned(vf_SSL_CTX_new) then vf_SSL_CTX_new := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_new');
  Result := vf_SSL_CTX_new(AMethod);
end;
{$ELSE}
function SSL_CTX_new; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_up_ref: function (ASSL: PSSL_CTX): LongInt; cdecl = nil;

function SSL_CTX_up_ref;
begin
  if not Assigned(vf_SSL_CTX_up_ref) then vf_SSL_CTX_up_ref := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_up_ref');
  Result := vf_SSL_CTX_up_ref(ASSL);
end;
{$ELSE}
function SSL_CTX_up_ref; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_free: procedure (ASSL: PSSL_CTX); cdecl = nil;

procedure SSL_CTX_free;
begin
  if not Assigned(vf_SSL_CTX_free) then vf_SSL_CTX_free := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_free');
  vf_SSL_CTX_free(ASSL);
end;
{$ELSE}
procedure SSL_CTX_free; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_set_fd: function (ASSL: PSSL; fd: LongInt): LongInt; cdecl = nil;

function SSL_set_fd;
begin
  if not Assigned(vf_SSL_set_fd) then vf_SSL_set_fd := LoadProcAddress(cStrSSLDllName, 'SSL_set_fd');
  Result := vf_SSL_set_fd(ASSL, fd);
end;
{$ELSE}
function SSL_set_fd; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_ctrl: function (ASSL: PSSL; cmd: LongInt; larg: Int64; parg: Pointer): Int64; cdecl = nil;

function SSL_ctrl;
begin
  if not Assigned(vf_SSL_ctrl) then vf_SSL_ctrl := LoadProcAddress(cStrSSLDllName, 'SSL_ctrl');
  Result := vf_SSL_ctrl(ASSL, cmd, larg, parg);
end;
{$ELSE}
function SSL_ctrl; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_ctrl: function (ctx: PSSL_CTX; cmd: LongInt; larg: Int64; parg: Pointer): Int64; cdecl = nil;

function SSL_CTX_ctrl;
begin
  if not Assigned(vf_SSL_CTX_ctrl) then vf_SSL_CTX_ctrl := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_ctrl');
  Result := vf_SSL_CTX_ctrl(ctx, cmd, larg, parg);
end;
{$ELSE}
function SSL_CTX_ctrl; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_TLS_method: function: PSSL_METHOD; cdecl = nil;

function TLS_method;
begin
  if not Assigned(vf_TLS_method) then vf_TLS_method := LoadProcAddress(cStrSSLDllName, 'TLS_method');
  Result := vf_TLS_method;
end;
{$ELSE}
function TLS_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_TLS_client_method: function: PSSL_METHOD; cdecl = nil;

function TLS_client_method;
begin
  if not Assigned(vf_TLS_client_method) then vf_TLS_client_method := LoadProcAddress(cStrSSLDllName, 'TLS_client_method');
  Result := vf_TLS_client_method;
end;
{$ELSE}
function TLS_client_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_TLS_server_method: function: PSSL_METHOD; cdecl = nil;

function TLS_server_method;
begin
  if not Assigned(vf_TLS_server_method) then vf_TLS_server_method := LoadProcAddress(cStrSSLDllName, 'TLS_server_method');
  Result := vf_TLS_server_method;
end;
{$ELSE}
function TLS_server_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSLv23_method: function: PSSL_METHOD; cdecl = nil;

function SSLv23_method;
begin
  if not Assigned(vf_SSLv23_method) then vf_SSLv23_method := LoadProcAddress(cStrSSLDllName, 'SSLv23_method');
  Result := vf_SSLv23_method;
end;
{$ELSE}
function SSLv23_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSLv23_server_method: function: PSSL_METHOD; cdecl = nil;

function SSLv23_server_method;
begin
  if not Assigned(vf_SSLv23_server_method) then vf_SSLv23_server_method := LoadProcAddress(cStrSSLDllName, 'SSLv23_server_method');
  Result := vf_SSLv23_server_method;
end;
{$ELSE}
function SSLv23_server_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSLv23_client_method: function: PSSL_METHOD; cdecl = nil;

function SSLv23_client_method;
begin
  if not Assigned(vf_SSLv23_client_method) then vf_SSLv23_client_method := LoadProcAddress(cStrSSLDllName, 'SSLv23_client_method');
  Result := vf_SSLv23_client_method;
end;
{$ELSE}
function SSLv23_client_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_TLSv1_method: function: PSSL_METHOD; cdecl = nil;

function TLSv1_method;
begin
  if not Assigned(vf_TLSv1_method) then vf_TLSv1_method := LoadProcAddress(cStrSSLDllName, 'TLSv1_method');
  Result := vf_TLSv1_method;
end;
{$ELSE}
function TLSv1_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_TLSv1_server_method: function: PSSL_METHOD; cdecl = nil;

function TLSv1_server_method;
begin
  if not Assigned(vf_TLSv1_server_method) then vf_TLSv1_server_method := LoadProcAddress(cStrSSLDllName, 'TLSv1_server_method');
  Result := vf_TLSv1_server_method;
end;
{$ELSE}
function TLSv1_server_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_TLSv1_client_method: function: PSSL_METHOD; cdecl = nil;

function TLSv1_client_method;
begin
  if not Assigned(vf_TLSv1_client_method) then vf_TLSv1_client_method := LoadProcAddress(cStrSSLDllName, 'TLSv1_client_method');
  Result := vf_TLSv1_client_method;
end;
{$ELSE}
function TLSv1_client_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_TLSv1_1_method: function: PSSL_METHOD; cdecl = nil;

function TLSv1_1_method;
begin
  if not Assigned(vf_TLSv1_1_method) then vf_TLSv1_1_method := LoadProcAddress(cStrSSLDllName, 'TLSv1_1_method');
  Result := vf_TLSv1_1_method;
end;
{$ELSE}
function TLSv1_1_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_TLSv1_1_server_method: function: PSSL_METHOD; cdecl = nil;

function TLSv1_1_server_method;
begin
  if not Assigned(vf_TLSv1_1_server_method) then vf_TLSv1_1_server_method := LoadProcAddress(cStrSSLDllName, 'TLSv1_1_server_method');
  Result := vf_TLSv1_1_server_method;
end;
{$ELSE}
function TLSv1_1_server_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_TLSv1_1_client_method: function: PSSL_METHOD; cdecl = nil;

function TLSv1_1_client_method;
begin
  if not Assigned(vf_TLSv1_1_client_method) then vf_TLSv1_1_client_method := LoadProcAddress(cStrSSLDllName, 'TLSv1_1_client_method');
  Result := vf_TLSv1_1_client_method;
end;
{$ELSE}
function TLSv1_1_client_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_TLSv1_2_method: function: PSSL_METHOD; cdecl = nil;

function TLSv1_2_method;
begin
  if not Assigned(vf_TLSv1_2_method) then vf_TLSv1_2_method := LoadProcAddress(cStrSSLDllName, 'TLSv1_2_method');
  Result := vf_TLSv1_2_method;
end;
{$ELSE}
function TLSv1_2_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_TLSv1_2_server_method: function: PSSL_METHOD; cdecl = nil;

function TLSv1_2_server_method;
begin
  if not Assigned(vf_TLSv1_2_server_method) then vf_TLSv1_2_server_method := LoadProcAddress(cStrSSLDllName, 'TLSv1_2_server_method');
  Result := vf_TLSv1_2_server_method;
end;
{$ELSE}
function TLSv1_2_server_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_TLSv1_2_client_method: function: PSSL_METHOD; cdecl = nil;

function TLSv1_2_client_method;
begin
  if not Assigned(vf_TLSv1_2_client_method) then vf_TLSv1_2_client_method := LoadProcAddress(cStrSSLDllName, 'TLSv1_2_client_method');
  Result := vf_TLSv1_2_client_method;
end;
{$ELSE}
function TLSv1_2_client_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DTLS_method: function: PSSL_METHOD; cdecl = nil;

function DTLS_method;
begin
  if not Assigned(vf_DTLS_method) then vf_DTLS_method := LoadProcAddress(cStrSSLDllName, 'DTLS_method');
  Result := vf_DTLS_method;
end;
{$ELSE}
function DTLS_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DTLS_server_method: function: PSSL_METHOD; cdecl = nil;

function DTLS_server_method;
begin
  if not Assigned(vf_DTLS_server_method) then vf_DTLS_server_method := LoadProcAddress(cStrSSLDllName, 'DTLS_server_method');
  Result := vf_DTLS_server_method;
end;
{$ELSE}
function DTLS_server_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DTLS_client_method: function: PSSL_METHOD; cdecl = nil;

function DTLS_client_method;
begin
  if not Assigned(vf_DTLS_client_method) then vf_DTLS_client_method := LoadProcAddress(cStrSSLDllName, 'DTLS_client_method');
  Result := vf_DTLS_client_method;
end;
{$ELSE}
function DTLS_client_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DTLSv1_method: function: PSSL_METHOD; cdecl = nil;

function DTLSv1_method;
begin
  if not Assigned(vf_DTLSv1_method) then vf_DTLSv1_method := LoadProcAddress(cStrSSLDllName, 'DTLSv1_method');
  Result := vf_DTLSv1_method;
end;
{$ELSE}
function DTLSv1_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DTLSv1_server_method: function: PSSL_METHOD; cdecl = nil;

function DTLSv1_server_method;
begin
  if not Assigned(vf_DTLSv1_server_method) then vf_DTLSv1_server_method := LoadProcAddress(cStrSSLDllName, 'DTLSv1_server_method');
  Result := vf_DTLSv1_server_method;
end;
{$ELSE}
function DTLSv1_server_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DTLSv1_client_method: function: PSSL_METHOD; cdecl = nil;

function DTLSv1_client_method;
begin
  if not Assigned(vf_DTLSv1_client_method) then vf_DTLSv1_client_method := LoadProcAddress(cStrSSLDllName, 'DTLSv1_client_method');
  Result := vf_DTLSv1_client_method;
end;
{$ELSE}
function DTLSv1_client_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DTLSv1_2_method: function: PSSL_METHOD; cdecl = nil;

function DTLSv1_2_method;
begin
  if not Assigned(vf_DTLSv1_2_method) then vf_DTLSv1_2_method := LoadProcAddress(cStrSSLDllName, 'DTLSv1_2_method');
  Result := vf_DTLSv1_2_method;
end;
{$ELSE}
function DTLSv1_2_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DTLSv1_2_server_method: function: PSSL_METHOD; cdecl = nil;

function DTLSv1_2_server_method;
begin
  if not Assigned(vf_DTLSv1_2_server_method) then vf_DTLSv1_2_server_method := LoadProcAddress(cStrSSLDllName, 'DTLSv1_2_server_method');
  Result := vf_DTLSv1_2_server_method;
end;
{$ELSE}
function DTLSv1_2_server_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DTLSv1_2_client_method: function: PSSL_METHOD; cdecl = nil;

function DTLSv1_2_client_method;
begin
  if not Assigned(vf_DTLSv1_2_client_method) then vf_DTLSv1_2_client_method := LoadProcAddress(cStrSSLDllName, 'DTLSv1_2_client_method');
  Result := vf_DTLSv1_2_client_method;
end;
{$ELSE}
function DTLSv1_2_client_method; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_use_certificate: function (ASSL: PSSL; cert: PX509): LongInt; cdecl = nil;

function SSL_use_certificate;
begin
  if not Assigned(vf_SSL_use_certificate) then vf_SSL_use_certificate := LoadProcAddress(cStrSSLDllName, 'SSL_use_certificate');
  Result := vf_SSL_use_certificate(ASSL, cert);
end;
{$ELSE}
function SSL_use_certificate; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_use_certificate_ASN1: function (ASSL: PSSL; data: TSslPtr; datalen: LongInt): LongInt; cdecl = nil;

function SSL_use_certificate_ASN1;
begin
  if not Assigned(vf_SSL_use_certificate_ASN1) then vf_SSL_use_certificate_ASN1 := LoadProcAddress(cStrSSLDllName, 'SSL_use_certificate_ASN1');
  Result := vf_SSL_use_certificate_ASN1(ASSL, data, dataLen);
end;
{$ELSE}
function SSL_use_certificate_ASN1; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_use_certificate_file: function (assl: PSSL; filename: PAnsiChar; filetype: LongInt): LongInt; cdecl = nil;

function SSL_use_certificate_file;
begin
  if not Assigned(vf_SSL_use_certificate_file) then vf_SSL_use_certificate_file := LoadProcAddress(cStrSSLDllName, 'SSL_use_certificate_file');
  Result := vf_SSL_use_certificate_file(assl, filename, filetype);
end;
{$ELSE}
function SSL_use_certificate_file; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_use_PrivateKey: function (assl: PSSL; pkey: PEVP_PKEY): LongInt; cdecl = nil;

function SSL_use_PrivateKey;
begin
  if not Assigned(vf_SSL_use_PrivateKey) then vf_SSL_use_PrivateKey := LoadProcAddress(cStrSSLDllName, 'SSL_use_PrivateKey');
  Result := vf_SSL_use_PrivateKey(assl, pkey);
end;
{$ELSE}
function SSL_use_PrivateKey; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_use_PrivateKey_ASN1: function (keyKind: LongInt; ssl: PSSL; keydata: Pointer; datalen: LongInt): LongInt; cdecl = nil;

function SSL_use_PrivateKey_ASN1;
begin
  if not Assigned(vf_SSL_use_PrivateKey_ASN1) then vf_SSL_use_PrivateKey_ASN1 := LoadProcAddress(cStrSSLDllName, 'SSL_use_PrivateKey_ASN1');
  Result := vf_SSL_use_PrivateKey_ASN1(keykind, ssl, keydata, datalen);
end;
{$ELSE}
function SSL_use_PrivateKey_ASN1; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_use_PrivateKey_file: function (ssl: PSSL; filename: PAnsiChar; filetype: LongInt): LongInt; cdecl = nil;

function SSL_use_PrivateKey_file;
begin
  if not Assigned(vf_SSL_use_PrivateKey_file) then vf_SSL_use_PrivateKey_file := LoadProcAddress(cStrSSLDllName, 'SSL_use_PrivateKey_file');
  Result := vf_SSL_use_PrivateKey_file(ssl, filename, filetype);
end;
{$ELSE}
function SSL_use_PrivateKey_file; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_use_PrivateKey: function (ctx: PSSL_CTX; pkey: TSslPtr): LongInt; cdecl = nil;

function SSL_CTX_use_PrivateKey;
begin
  if not Assigned(vf_SSL_CTX_use_PrivateKey) then vf_SSL_CTX_use_PrivateKey := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_use_PrivateKey');
  Result := vf_SSL_CTX_use_PrivateKey(ctx, pkey);
end;
{$ELSE}
function SSL_CTX_use_PrivateKey; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_use_PrivateKey_ASN1: function (pk: LongInt; ctx: PSSL_CTX; d: TSslPtr; len: LongInt): LongInt; cdecl = nil;

function SSL_CTX_use_PrivateKey_ASN1;
begin
  if not Assigned(vf_SSL_CTX_use_PrivateKey_ASN1) then vf_SSL_CTX_use_PrivateKey_ASN1 := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_use_PrivateKey_ASN1');
  Result := vf_SSL_CTX_use_PrivateKey_ASN1(pk, ctx, d, len);
end;
{$ELSE}
function SSL_CTX_use_PrivateKey_ASN1; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_use_RSAPrivateKey_file: function (ctx: PSSL_CTX; filename: PAnsiChar; _type: LongInt): LongInt; cdecl = nil;

function SSL_CTX_use_RSAPrivateKey_file;
begin
  if not Assigned(vf_SSL_CTX_use_RSAPrivateKey_file) then vf_SSL_CTX_use_RSAPrivateKey_file := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_use_RSAPrivateKey_file');
  Result := vf_SSL_CTX_use_RSAPrivateKey_file(ctx, filename, _type);
end;
{$ELSE}
function SSL_CTX_use_RSAPrivateKey_file; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_use_certificate: function (ctx: PSSL_CTX; cert: TSslPtr): LongInt; cdecl = nil;

function SSL_CTX_use_certificate;
begin
  if not Assigned(vf_SSL_CTX_use_certificate) then vf_SSL_CTX_use_certificate := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_use_certificate');
  Result := vf_SSL_CTX_use_certificate(ctx, cert);
end;
{$ELSE}
function SSL_CTX_use_certificate; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_use_certificate_ASN1: function (ctx: PSSL_CTX; len: LongInt; certdata: TSslPtr): LongInt; cdecl = nil;

function SSL_CTX_use_certificate_ASN1;
begin
  if not Assigned(vf_SSL_CTX_use_certificate_ASN1) then vf_SSL_CTX_use_certificate_ASN1 := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_use_certificate_ASN1');
  Result := vf_SSL_CTX_use_certificate_ASN1(ctx, len, certdata);
end;
{$ELSE}
function SSL_CTX_use_certificate_ASN1; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_use_certificate_file: function (ctx: PSSL_CTX; filename: PAnsiChar; filetype: LongInt): LongInt; cdecl = nil;

function SSL_CTX_use_certificate_file;
begin
  if not Assigned(vf_SSL_CTX_use_certificate_file) then vf_SSL_CTX_use_certificate_file := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_use_certificate_file');
  Result := vf_SSL_CTX_use_certificate_file(ctx, filename, filetype);
end;
{$ELSE}
function SSL_CTX_use_certificate_file; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_use_certificate_chain_file: function (ctx: PSSL_CTX; filename: PAnsiChar): LongInt; cdecl = nil;

function SSL_CTX_use_certificate_chain_file;
begin
  if not Assigned(vf_SSL_CTX_use_certificate_chain_file) then vf_SSL_CTX_use_certificate_chain_file := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_use_certificate_chain_file');
  Result := vf_SSL_CTX_use_certificate_chain_file(ctx, filename);
end;
{$ELSE}
function SSL_CTX_use_certificate_chain_file; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_check_private_key: function (ctx: PSSL_CTX): LongInt; cdecl = nil;

function SSL_CTX_check_private_key;
begin
  if not Assigned(vf_SSL_CTX_check_private_key) then vf_SSL_CTX_check_private_key := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_check_private_key');
  Result := vf_SSL_CTX_check_private_key(ctx);
end;
{$ELSE}
function SSL_CTX_check_private_key; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_set_default_passwd_cb: procedure (ctx: PSSL_CTX; cb: TSslPtr); cdecl = nil;

procedure SSL_CTX_set_default_passwd_cb;
begin
  if not Assigned(vf_SSL_CTX_set_default_passwd_cb) then vf_SSL_CTX_set_default_passwd_cb := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_set_default_passwd_cb');
  vf_SSL_CTX_set_default_passwd_cb(ctx, cb);
end;
{$ELSE}
procedure SSL_CTX_set_default_passwd_cb; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_set_default_passwd_cb_userdata: procedure (ctx: PSSL_CTX; u: TSslPtr); cdecl = nil;

procedure SSL_CTX_set_default_passwd_cb_userdata;
begin
  if not Assigned(vf_SSL_CTX_set_default_passwd_cb_userdata) then vf_SSL_CTX_set_default_passwd_cb_userdata := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_set_default_passwd_cb_userdata');
  vf_SSL_CTX_set_default_passwd_cb_userdata(ctx, u);
end;
{$ELSE}
procedure SSL_CTX_set_default_passwd_cb_userdata; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_load_verify_locations: function (ctx: PSSL_CTX; filename: PAnsiChar; path: PAnsiChar): LongInt; cdecl = nil;

function SSL_CTX_load_verify_locations;
begin
  if not Assigned(vf_SSL_CTX_load_verify_locations) then vf_SSL_CTX_load_verify_locations := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_load_verify_locations');
  Result := vf_SSL_CTX_load_verify_locations(ctx, filename, path);
end;
{$ELSE}
function SSL_CTX_load_verify_locations; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_set_cert_store: procedure (pSslCtx: PSSL_CTX; pCertStore: PX509_STORE); cdecl = nil;

procedure SSL_CTX_set_cert_store;
begin
  if not Assigned(vf_SSL_CTX_set_cert_store) then vf_SSL_CTX_set_cert_store := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_set_cert_store');
  vf_SSL_CTX_set_cert_store(pSslCtx, pCertStore);
end;
{$ELSE}
procedure SSL_CTX_set_cert_store; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_set1_cert_store: procedure (pSslCtx: PSSL_CTX; pCertStore: PX509_STORE); cdecl = nil;

procedure SSL_CTX_set1_cert_store;
begin
  if not Assigned(vf_SSL_CTX_set1_cert_store) then vf_SSL_CTX_set1_cert_store := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_set1_cert_store');
  vf_SSL_CTX_set1_cert_store(pSslCtx, pCertStore);
end;
{$ELSE}
procedure SSL_CTX_set1_cert_store; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_get_cert_store: function (pSslCtx: PSSL_Ctx): PX509_STORE; cdecl = nil;

function SSL_CTX_get_cert_store;
begin
  if not Assigned(vf_SSL_CTX_get_cert_store) then vf_SSL_CTX_get_cert_store := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_get_cert_store');
  Result := vf_SSL_CTX_get_cert_store(pSslCtx);
end;
{$ELSE}
function SSL_CTX_get_cert_store; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_new: function (ctx: PSSL_CTX): PSSL; cdecl = nil;

function SSL_new;
begin
  if not Assigned(vf_SSL_new) then vf_SSL_new := LoadProcAddress(cStrSSLDllName, 'SSL_new');
  Result := vf_SSL_new(ctx);
end;
{$ELSE}
function SSL_new; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_free: procedure (ssl: PSSL); cdecl = nil;

procedure SSL_free;
begin
  if not Assigned(vf_SSL_free) then vf_SSL_free := LoadProcAddress(cStrSSLDllName, 'SSL_free');
  vf_SSL_free(ssl);
end;
{$ELSE}
procedure SSL_free; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_accept: function (ssl: PSSL): LongInt; cdecl = nil;

function SSL_accept;
begin
  if not Assigned(vf_SSL_accept) then vf_SSL_accept := LoadProcAddress(cStrSSLDllName, 'SSL_accept');
  Result := vf_SSL_accept(ssl);
end;
{$ELSE}
function SSL_accept; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_connect: function (ssl: PSSL): LongInt; cdecl = nil;

function SSL_connect;
begin
  if not Assigned(vf_SSL_connect) then vf_SSL_connect := LoadProcAddress(cStrSSLDllName, 'SSL_connect');
  Result := vf_SSL_connect(ssl);
end;
{$ELSE}
function SSL_connect; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_shutdown: function (ssl: PSSL): LongInt; cdecl = nil;

function SSL_shutdown;
begin
  if not Assigned(vf_SSL_shutdown) then vf_SSL_shutdown := LoadProcAddress(cStrSSLDllName, 'SSL_shutdown');
  Result := vf_SSL_shutdown(ssl);
end;
{$ELSE}
function SSL_shutdown; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_read: function (ssl: PSSL; buf: PAnsiChar; buflen: LongInt): LongInt; cdecl = nil;

function SSL_read;
begin
  if not Assigned(vf_SSL_read) then vf_SSL_read := LoadProcAddress(cStrSSLDllName, 'SSL_read');
  Result := vf_SSL_read(ssl, buf, buflen);
end;
{$ELSE}
function SSL_read; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_peek: function (ssl: PSSL; buf: PAnsiChar; buflen: LongInt): LongInt; cdecl = nil;

function SSL_peek;
begin
  if not Assigned(vf_SSL_peek) then vf_SSL_peek := LoadProcAddress(cStrSSLDllName, 'SSL_peek');
  Result := vf_SSL_peek(ssl, buf, buflen);
end;
{$ELSE}
function SSL_peek; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_write: function (ssl: PSSL; buf: PAnsiChar; buflen: LongInt): LongInt; cdecl = nil;

function SSL_write;
begin
  if not Assigned(vf_SSL_write) then vf_SSL_write := LoadProcAddress(cStrSSLDllName, 'SSL_write');
  Result := vf_SSL_write(ssl, buf, buflen);
end;
{$ELSE}
function SSL_write; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_pending: function (ssl: PSSL): LongInt; cdecl = nil;

function SSL_pending;
begin
  if not Assigned(vf_SSL_pending) then vf_SSL_pending := LoadProcAddress(cStrSSLDllName, 'SSL_pending');
  Result := vf_SSL_pending(ssl);
end;
{$ELSE}
function SSL_pending; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_get_version: function (ssl: PSSL): PAnsiChar; cdecl = nil;

function SSL_get_version;
begin
  if not Assigned(vf_SSL_get_version) then vf_SSL_get_version := LoadProcAddress(cStrSSLDllName, 'SSL_get_version');
  Result := vf_SSL_get_version(ssl);
end;
{$ELSE}
function SSL_get_version; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_get_peer_certificate: function (ssl: PSSL): PX509; cdecl = nil;

function SSL_get_peer_certificate;
begin
  if not Assigned(vf_SSL_get_peer_certificate) then vf_SSL_get_peer_certificate := LoadProcAddress(cStrSSLDllName, 'SSL_get_peer_certificate');
  Result := vf_SSL_get_peer_certificate(ssl);
end;
{$ELSE}
function SSL_get_peer_certificate; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CTX_set_verify: procedure (ctx: PSSL_CTX; mode: LongInt; arg2: TSslPtr); cdecl = nil;

procedure SSL_CTX_set_verify;
begin
  if not Assigned(vf_SSL_CTX_set_verify) then vf_SSL_CTX_set_verify := LoadProcAddress(cStrSSLDllName, 'SSL_CTX_set_verify');
  vf_SSL_CTX_set_verify(ctx, mode, arg2);
end;
{$ELSE}
procedure SSL_CTX_set_verify; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_get_current_cipher: function (assl: PSSL): TSslPtr; cdecl = nil;

function SSL_get_current_cipher;
begin
  if not Assigned(vf_SSL_get_current_cipher) then vf_SSL_get_current_cipher := LoadProcAddress(cStrSSLDllName, 'SSL_get_current_cipher');
  Result := vf_SSL_get_current_cipher(assl);
end;
{$ELSE}
function SSL_get_current_cipher; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CIPHER_get_name: function (cipher: PSSL_CIPHER): PAnsiChar; cdecl = nil;

function SSL_CIPHER_get_name;
begin
  if not Assigned(vf_SSL_CIPHER_get_name) then vf_SSL_CIPHER_get_name := LoadProcAddress(cStrSSLDllName, 'SSL_CIPHER_get_name');
  Result := vf_SSL_CIPHER_get_name(cipher);
end;
{$ELSE}
function SSL_CIPHER_get_name; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CIPHER_get_bits: function (cipher: PSSL_CIPHER; alg_bits: PLongInt): LongInt; cdecl = nil;

function SSL_CIPHER_get_bits;
begin
  if not Assigned(vf_SSL_CIPHER_get_bits) then vf_SSL_CIPHER_get_bits := LoadProcAddress(cStrSSLDllName, 'SSL_CIPHER_get_bits');
  Result := vf_SSL_CIPHER_get_bits(cipher, alg_bits);
end;
{$ELSE}
function SSL_CIPHER_get_bits; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CIPHER_get_version: function (cipher: PSSL_CIPHER): PAnsiChar; cdecl = nil;

function SSL_CIPHER_get_version;
begin
  if not Assigned(vf_SSL_CIPHER_get_version) then vf_SSL_CIPHER_get_version := LoadProcAddress(cStrSSLDllName, 'SSL_CIPHER_get_version');
  Result := vf_SSL_CIPHER_get_version(cipher);
end;
{$ELSE}
function SSL_CIPHER_get_version; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_CIPHER_description: function (cipher: PSSL_CIPHER; buffer: PAnsiChar; bufSize: LongInt): PAnsiChar; cdecl = nil;

function SSL_CIPHER_description;
begin
  if not Assigned(vf_SSL_CIPHER_description) then vf_SSL_CIPHER_description := LoadProcAddress(cStrSSLDllName, 'SSL_CIPHER_description');
  Result := vf_SSL_CIPHER_description(cipher, buffer, bufSize);
end;
{$ELSE}
function SSL_CIPHER_description; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_get_verify_result: function (ssl: PSSL): LongInt; cdecl = nil;

function SSL_get_verify_result;
begin
  if not Assigned(vf_SSL_get_verify_result) then vf_SSL_get_verify_result := LoadProcAddress(cStrSSLDllName, 'SSL_get_verify_result');
  Result := vf_SSL_get_verify_result(ssl);
end;
{$ELSE}
function SSL_get_verify_result; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_copy_session_id: procedure (dest, src: PSSL); cdecl = nil;

procedure SSL_copy_session_id;
begin
  if not Assigned(vf_SSL_copy_session_id) then vf_SSL_copy_session_id := LoadProcAddress(cStrSSLDllName, 'SSL_copy_session_id');
  vf_SSL_copy_session_id(dest, src);
end;
{$ELSE}
procedure SSL_copy_session_id; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_get_session: function (ssl: PSSL): PSession; cdecl = nil;

function SSL_get_session;
begin
  if not Assigned(vf_SSL_get_session) then vf_SSL_get_session := LoadProcAddress(cStrSSLDllName, 'SSL_get_session');
  Result := vf_SSL_get_session(ssl);
end;
{$ELSE}
function SSL_get_session; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_SSL_set_session: function (ssl: PSSL; session: PSession): LongInt; cdecl = nil;

function SSL_set_session;
begin
  if not Assigned(vf_SSL_set_session) then vf_SSL_set_session := LoadProcAddress(cStrSSLDllName, 'SSL_set_session');
  Result := vf_SSL_set_session(ssl, session);
end;
{$ELSE}
function SSL_set_session; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_OpenSSL_add_all_algorithms: procedure; cdecl = nil;

procedure OpenSSL_add_all_algorithms;
begin
  if not Assigned(vf_OpenSSL_add_all_algorithms) then vf_OpenSSL_add_all_algorithms := LoadProcAddress(cStrSSLDllName, 'OpenSSL_add_all_algorithms');
  vf_OpenSSL_add_all_algorithms;
end;
{$ELSE}
procedure OpenSSL_add_all_algorithms; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_OpenSSL_add_all_ciphers: procedure; cdecl = nil;

procedure OpenSSL_add_all_ciphers;
begin
  if not Assigned(vf_OpenSSL_add_all_ciphers) then vf_OpenSSL_add_all_ciphers := LoadProcAddress(cStrSSLDllName, 'OpenSSL_add_all_ciphers');
  vf_OpenSSL_add_all_ciphers;
end;
{$ELSE}
procedure OpenSSL_add_all_ciphers; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_OpenSSL_add_all_digests: procedure; cdecl = nil;

procedure OpenSSL_add_all_digests;
begin
  if not Assigned(vf_OpenSSL_add_all_digests) then vf_OpenSSL_add_all_digests := LoadProcAddress(cStrSSLDllName, 'OpenSSL_add_all_digests');
  vf_OpenSSL_add_all_digests;
end;
{$ELSE}
procedure OpenSSL_add_all_digests; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_EVP_cleanup: procedure; cdecl = nil;

procedure EVP_cleanup;
begin
  if not Assigned(vf_EVP_cleanup) then vf_EVP_cleanup := LoadProcAddress(cStrSSLDllName, 'EVP_cleanup');
  vf_EVP_cleanup;
end;
{$ELSE}
procedure EVP_cleanup; external cStrSSLDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{ ------------------------ }
{ ---- Crypto Library ---- }
{ ------------------------ }

{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_ERR_get_error: function: LongWord; cdecl = nil;

function ERR_get_error;
begin
  if not Assigned(vf_ERR_get_error) then vf_ERR_get_error := LoadProcAddress(cStrCryptoDllName, 'ERR_get_error');
  Result := vf_ERR_get_error;
end;
{$ELSE}
function ERR_get_error; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_ERR_peek_error: function: LongWord; cdecl = nil;

function ERR_peek_error;
begin
  if not Assigned(vf_ERR_peek_error) then vf_ERR_peek_error := LoadProcAddress(cStrCryptoDllName, 'ERR_peek_error');
  Result := vf_ERR_peek_error;
end;
{$ELSE}
function ERR_peek_error; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_ERR_peek_last_error: function: LongWord; cdecl = nil;

function ERR_peek_last_error;
begin
  if not Assigned(vf_ERR_peek_last_error) then vf_ERR_peek_last_error := LoadProcAddress(cStrCryptoDllName, 'ERR_peek_last_error');
  Result := vf_ERR_peek_last_error;
end;
{$ELSE}
function ERR_peek_last_error; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_ERR_error_string: function (errorCode: LongWord; buffer: PAnsiChar): PAnsiChar; cdecl = nil;

function ERR_error_string;
begin
  if not Assigned(vf_ERR_error_string) then vf_ERR_error_string := LoadProcAddress(cStrCryptoDllName, 'ERR_error_string');
  Result := vf_ERR_error_string(errorCode, buffer);
end;
{$ELSE}
function ERR_error_string; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_ERR_error_string_n: procedure (errorCode: LongWord; buffer: PAnsiChar; bufSize: size_t); cdecl = nil;

procedure ERR_error_string_n;
begin
  if not Assigned(vf_ERR_error_string_n) then vf_ERR_error_string_n := LoadProcAddress(cStrCryptoDllName, 'ERR_error_string_n');
  vf_ERR_error_string_n(errorCode, buffer, bufSize);
end;
{$ELSE}
procedure ERR_error_string_n; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_ERR_lib_error_string: function (errorCode: LongWord): PAnsiChar; cdecl = nil;

function ERR_lib_error_string;
begin
  if not Assigned(vf_ERR_lib_error_string) then vf_ERR_lib_error_string := LoadProcAddress(cStrCryptoDllName, 'ERR_lib_error_string');
  Result := vf_ERR_lib_error_string(errorCode);
end;
{$ELSE}
function ERR_lib_error_string; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_ERR_func_error_string: function (errorCode: LongWord): PAnsiChar; cdecl = nil;

function ERR_func_error_string;
begin
  if not Assigned(vf_ERR_func_error_string) then vf_ERR_func_error_string := LoadProcAddress(cStrCryptoDllName, 'ERR_func_error_string');
  Result := vf_ERR_func_error_string(errorCode);
end;
{$ELSE}
function ERR_func_error_string; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_ERR_reason_error_string: function (errorCode: LongWord): PAnsiChar; cdecl = nil;

function ERR_reason_error_string;
begin
  if not Assigned(vf_ERR_reason_error_string) then vf_ERR_reason_error_string := LoadProcAddress(cStrCryptoDllName, 'ERR_reason_error_string');
  Result := vf_ERR_reason_error_string(errorCode);
end;
{$ELSE}
function ERR_reason_error_string; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_ERR_remove_state: procedure (threadId: LongWord); cdecl = nil;

procedure ERR_remove_state;
begin
  if not Assigned(vf_ERR_remove_state) then vf_ERR_remove_state := LoadProcAddress(cStrCryptoDllName, 'ERR_remove_state');
  vf_ERR_remove_state(threadId);
end;
{$ELSE}
procedure ERR_remove_state; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_ERR_remove_thread_state: procedure (tid: PCRYPTO_THREADID); cdecl = nil;

procedure ERR_remove_thread_state;
begin
  if not Assigned(vf_ERR_remove_thread_state) then vf_ERR_remove_thread_state := LoadProcAddress(cStrCryptoDllName, 'ERR_remove_thread_state');
  vf_ERR_remove_thread_state(tid);
end;
{$ELSE}
procedure ERR_remove_thread_state; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_OPENSSL_init_new: function: POPENSSL_INIT_SETTINGS; cdecl = nil;

function OPENSSL_init_new;
begin
  if not Assigned(vf_OPENSSL_init_new) then vf_OPENSSL_init_new := LoadProcAddress(cStrCryptoDllName, 'OPENSSL_init_new');
  Result := vf_OPENSSL_init_new;
end;
{$ELSE}
function OPENSSL_init_new; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_OPENSSL_INIT_set_config_appname: function (init: POPENSSL_INIT_SETTINGS; name: PAnsiChar): LongInt; cdecl = nil;

function OPENSSL_INIT_set_config_appname;
begin
  if not Assigned(vf_OPENSSL_INIT_set_config_appname) then vf_OPENSSL_INIT_set_config_appname := LoadProcAddress(cStrCryptoDllName, 'OPENSSL_INIT_set_config_appname');
  Result := vf_OPENSSL_INIT_set_config_appname(init, name);
end;
{$ELSE}
function OPENSSL_INIT_set_config_appname; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_OPENSSL_INIT_free: procedure (init: POPENSSL_INIT_SETTINGS); cdecl = nil;

procedure OPENSSL_INIT_free;
begin
  if not Assigned(vf_OPENSSL_INIT_free) then vf_OPENSSL_INIT_free := LoadProcAddress(cStrCryptoDllName, 'OPENSSL_INIT_free');
  vf_OPENSSL_INIT_free(init);
end;
{$ELSE}
procedure OPENSSL_INIT_free; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_OPENSSL_init_crypto: function (opts: UInt64; settings: POPENSSL_INIT_SETTINGS): LongInt; cdecl = nil;

function OPENSSL_init_crypto;
begin
  if not Assigned(vf_OPENSSL_init_crypto) then vf_OPENSSL_init_crypto := LoadProcAddress(cStrCryptoDllName, 'OPENSSL_init_crypto');
  Result := vf_OPENSSL_init_crypto(opts, settings);
end;
{$ELSE}
function OPENSSL_init_crypto; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_OPENSSL_cleanup: procedure; cdecl = nil;

procedure OPENSSL_cleanup;
begin
  if not Assigned(vf_OPENSSL_cleanup) then vf_OPENSSL_cleanup := LoadProcAddress(cStrCryptoDllName, 'OPENSSL_cleanup');
  vf_OPENSSL_cleanup;
end;
{$ELSE}
procedure OPENSSL_cleanup; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_CRYPTO_THREADID_set_numeric: procedure (id: PCRYPTO_THREADID; val: LongWord); cdecl = nil;

procedure CRYPTO_THREADID_set_numeric;
begin
  if not Assigned(vf_CRYPTO_THREADID_set_numeric) then vf_CRYPTO_THREADID_set_numeric := LoadProcAddress(cStrCryptoDllName, 'CRYPTO_THREADID_set_numeric');
  vf_CRYPTO_THREADID_set_numeric(id, val);
end;
{$ELSE}
procedure CRYPTO_THREADID_set_numeric; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_CRYPTO_THREADID_set_pointer: procedure (id: PCRYPTO_THREADID; ptr: Pointer); cdecl = nil;

procedure CRYPTO_THREADID_set_pointer;
begin
  if not Assigned(vf_CRYPTO_THREADID_set_pointer) then vf_CRYPTO_THREADID_set_pointer := LoadProcAddress(cStrCryptoDllName, 'CRYPTO_THREADID_set_pointer');
  vf_CRYPTO_THREADID_set_pointer(id, ptr);
end;
{$ELSE}
procedure CRYPTO_THREADID_set_pointer; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_CRYPTO_THREADID_current: procedure (id: PCRYPTO_THREADID); cdecl = nil;

procedure CRYPTO_THREADID_current;
begin
  if not Assigned(vf_CRYPTO_THREADID_current) then vf_CRYPTO_THREADID_current := LoadProcAddress(cStrCryptoDllName, 'CRYPTO_THREADID_current');
  vf_CRYPTO_THREADID_current(id);
end;
{$ELSE}
procedure CRYPTO_THREADID_current; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_X509_new: function: PX509; cdecl = nil;

function X509_new;
begin
  if not Assigned(vf_X509_new) then vf_X509_new := LoadProcAddress(cStrCryptoDllName, 'X509_new');
  Result := vf_X509_new;
end;
{$ELSE}
function X509_new; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_X509_free: procedure (x509: PX509); cdecl = nil;

procedure X509_free;
begin
  if not Assigned(vf_X509_free) then vf_X509_free := LoadProcAddress(cStrCryptoDllName, 'X509_free');
  vf_X509_free(x509);
end;
{$ELSE}
procedure X509_free; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DES_random_key: procedure (ret: PDES_cblock); cdecl = nil;

procedure DES_random_key;
begin
  if not Assigned(vf_DES_random_key) then vf_DES_random_key := LoadProcAddress(cStrCryptoDllName, 'DES_random_key');
  vf_DES_random_key(ret);
end;
{$ELSE}
procedure DES_random_key; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DES_set_key: function (Key: PDES_cblock; schedule: PDES_key_schedule): LongInt; cdecl = nil;

function DES_set_key;
begin
  if not Assigned(vf_DES_set_key) then vf_DES_set_key := LoadProcAddress(cStrCryptoDllName, 'DES_set_key');
  Result := vf_DES_set_key(key, schedule);
end;
{$ELSE}
function DES_set_key; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DES_key_sched: function (Key: PDES_cblock; schedule: PDES_key_schedule): LongInt; cdecl = nil;

function DES_key_sched;
begin
  if not Assigned(vf_DES_key_sched) then vf_DES_key_sched := LoadProcAddress(cStrCryptoDllName, 'DES_key_sched');
  Result := vf_DES_key_sched(key, schedule);
end;
{$ELSE}
function DES_key_sched; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DES_set_key_checked: function (Key: PDES_cblock; schedule: PDES_key_schedule): LongInt; cdecl = nil;

function DES_set_key_checked;
begin
  if not Assigned(vf_DES_set_key_checked) then vf_DES_set_key_checked := LoadProcAddress(cStrCryptoDllName, 'DES_set_key_checked');
  Result := vf_DES_set_key_checked(key, schedule);
end;
{$ELSE}
function DES_set_key_checked; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DES_set_key_unchecked: procedure (Key: PDES_cblock; schedule: PDES_key_schedule); cdecl = nil;

procedure DES_set_key_unchecked;
begin
  if not Assigned(vf_DES_set_key_unchecked) then vf_DES_set_key_unchecked := LoadProcAddress(cStrCryptoDllName, 'DES_set_key_unchecked');
  vf_DES_set_key_unchecked(key, schedule);
end;
{$ELSE}
procedure DES_set_key_unchecked; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DES_set_odd_parity: procedure (Key: PDES_cblock); cdecl = nil;

procedure DES_set_odd_parity;
begin
  if not Assigned(vf_DES_set_odd_parity) then vf_DES_set_odd_parity := LoadProcAddress(cStrCryptoDllName, 'DES_set_odd_parity');
  vf_DES_set_odd_parity(key);
end;
{$ELSE}
procedure DES_set_odd_parity; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DES_is_weak_key: function (Key: PDES_cblock): LongInt; cdecl = nil;

function DES_is_weak_key;
begin
  if not Assigned(vf_DES_is_weak_key) then vf_DES_is_weak_key := LoadProcAddress(cStrCryptoDllName, 'DES_is_weak_key');
  Result := vf_DES_is_weak_key(key);
end;
{$ELSE}
function DES_is_weak_key; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DES_ecb_encrypt: procedure (input, output: PDES_cblock; schedule: PDES_key_schedule; enc: LongInt); cdecl = nil;

procedure DES_ecb_encrypt;
begin
  if not Assigned(vf_DES_ecb_encrypt) then vf_DES_ecb_encrypt := LoadProcAddress(cStrCryptoDllName, 'DES_ecb_encrypt');
  vf_DES_ecb_encrypt(input, output, schedule, enc);
end;
{$ELSE}
procedure DES_ecb_encrypt; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DES_ecb2_encrypt: procedure (input, output: PDES_cblock; schedule1, schedule2: PDES_key_schedule; enc: LongInt); cdecl = nil;

procedure DES_ecb2_encrypt;
begin
  if not Assigned(vf_DES_ecb2_encrypt) then vf_DES_ecb2_encrypt := LoadProcAddress(cStrCryptoDllName, 'DES_ecb2_encrypt');
  vf_DES_ecb2_encrypt(input, output, schedule1, schedule2, enc);
end;
{$ELSE}
procedure DES_ecb2_encrypt; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_DES_ecb3_encrypt: procedure (input, output: PDES_cblock; schedule1, schedule2, schedule3: PDES_key_schedule; enc: LongInt); cdecl = nil;

procedure DES_ecb3_encrypt;
begin
  if not Assigned(vf_DES_ecb3_encrypt) then vf_DES_ecb3_encrypt := LoadProcAddress(cStrCryptoDllName, 'DES_ecb3_encrypt');
  vf_DES_ecb3_encrypt(input, output, schedule1, schedule2, schedule3, enc);
end;
{$ELSE}
procedure DES_ecb3_encrypt; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_X509_STORE_new: function: PX509_STORE; cdecl = nil;

function X509_STORE_new;
begin
  if not Assigned(vf_X509_STORE_new) then vf_X509_STORE_new := LoadProcAddress(cStrCryptoDllName, 'X509_STORE_new');
  Result := vf_X509_STORE_new;
end;
{$ELSE}
function X509_STORE_new; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_X509_STORE_free: procedure (pStore: PX509_STORE); cdecl = nil;

procedure X509_STORE_free;
begin
  if not Assigned(vf_X509_STORE_free) then vf_X509_STORE_free := LoadProcAddress(cStrCryptoDllName, 'X509_STORE_free');
  vf_X509_STORE_free(pStore);
end;
{$ELSE}
procedure X509_STORE_free; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_X509_STORE_lock: function (pStore: PX509_STORE): LongInt; cdecl = nil;

function X509_STORE_lock;
begin
  if not Assigned(vf_X509_STORE_lock) then vf_X509_STORE_lock := LoadProcAddress(cStrCryptoDllName, 'X509_STORE_lock');
  Result := vf_X509_STORE_lock(pStore);
end;
{$ELSE}
function X509_STORE_lock; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_X509_STORE_unlock: function (pStore: PX509_STORE): LongInt; cdecl = nil;

function X509_STORE_unlock;
begin
  if not Assigned(vf_X509_STORE_unlock) then vf_X509_STORE_unlock := LoadProcAddress(cStrCryptoDllName, 'X509_STORE_unlock');
  Result := vf_X509_STORE_unlock(pStore);
end;
{$ELSE}
function X509_STORE_unlock; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_X509_STORE_up_ref: function (pStore: PX509_STORE): LongInt; cdecl = nil;

function X509_STORE_up_ref;
begin
  if not Assigned(vf_X509_STORE_up_ref) then vf_X509_STORE_up_ref := LoadProcAddress(cStrCryptoDllName, 'X509_STORE_up_ref');
  Result := vf_X509_STORE_up_ref(pStore);
end;
{$ELSE}
function X509_STORE_up_ref; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_d2i_X509: function (ppx509: PPX509; in_Data: PPByte; len: LongInt): PX509; cdecl = nil;

function d2i_X509;
begin
  if not Assigned(vf_d2i_X509) then vf_d2i_X509 := LoadProcAddress(cStrCryptoDllName, 'd2i_X509');
  Result := vf_d2i_X509(ppx509, in_Data, len);
end;
{$ELSE}
function d2i_X509; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_i2d_X509: function (px509: PX509; out_Data: PPByte): LongInt; cdecl = nil;

function i2d_X509;
begin
  if not Assigned(vf_i2d_X509) then vf_i2d_X509 := LoadProcAddress(cStrCryptoDllName, 'i2d_X509');
  Result := vf_i2d_X509(px509, out_Data);
end;
{$ELSE}
function i2d_X509; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_i2d_re_X509_tbs: function (px509: PX509; out_Data: PPByte): LongInt; cdecl = nil;

function i2d_re_X509_tbs;
begin
  if not Assigned(vf_i2d_re_X509_tbs) then vf_i2d_re_X509_tbs := LoadProcAddress(cStrCryptoDllName, 'i2d_re_X509_tbs');
  Result := vf_i2d_re_X509_tbs(px509, out_Data);
end;
{$ELSE}
function i2d_re_X509_tbs; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


{$IFDEF DELAY_LOAD_OPENSSL_DLL}
var vf_X509_STORE_add_cert: function (pStore: PX509_STORE; cert: PX509): LongInt; cdecl = nil;

function X509_STORE_add_cert;
begin
  if not Assigned(vf_X509_STORE_add_cert) then vf_X509_STORE_add_cert := LoadProcAddress(cStrCryptoDllName, 'X509_STORE_add_cert');
  Result := vf_X509_STORE_add_cert(pStore, cert);
end;
{$ELSE}
function X509_STORE_add_cert; external cStrCryptoDllName;
{$ENDIF DELAY_LOAD_OPENSSL_DLL}


end.