{-------------------------------------------------------------------------------
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      THIS ISN'T COMPLETE TRANSLATION OF C++ HEADERS AND NEVER WILL BE.

  FOR COPYRIGHT OF ORIGINAL ERIC YOUNG SOFTWARE LOOK AT FILES IN HEADER FOLDER.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Author :      Jan Tomasek
Description :
EMail :       tomasej@fel.cvut.cz       http://www.feld.cvut.cz/~x590tomasej
Creation :    Jul 1998
Version :     0.20
Support :
Legal issues:
      Copyright (C) 1998 by Jan Tomasek <xtomasej@fel.cvut.cz>
      All rights reserved.

      This library is free for commercial and non-commercial use as long as
      the following conditions are aheared to.  The following conditions
      apply to all code found in this distribution.  The documentation
      included with this distribution is covered by the same copyright terms.

      Copyright remains Jan Tomasek's, and as such any Copyright notices in
      the code are not to be removed.
      If this package is used in a product, Jan Tomasek should be given
      attribution as the author of the parts of the library used.
      This can be in the form of a textual message at program startup or
      in documentation (online or textual) provided with the package.

      Redistribution and use in source and binary forms, with or without
      modification, are permitted provided that the following conditions
      are met:
      1. Redistributions of source code must retain the copyright
         notice, this list of conditions and the following disclaimer.
      2. Redistributions in binary form must reproduce the above copyright
         notice, this list of conditions and the following disclaimer in the
         documentation and/or other materials provided with the distribution.
      3. All advertising materials mentioning features or use of this software
         must display the following acknowledgement:
             "This product includes software written by
              Jan Tomasek <xtomasej@fel.cvut.cz>"

      THIS SOFTWARE IS PROVIDED BY JAN TOMASEK ``AS IS'' AND
      ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      SUCH DAMAGE.

      The licence and distribution terms for any publically available version or
      derivative of this code cannot be changed.  i.e. this code cannot simply
      be copied and put under another distribution licence
      [including the GNU Public Licence.]

History :
  21.07.98 Released for testing
  24.07.98 First usefull version
    .07.98 All transated parts is in ssl.h marked  with '...'. Sometimes I had
           to change order of types and constants, pascal isn't c.
           Importing dynamicaly.
-------------------------------------------------------------------------------}

Unit SSLeay;
{$F+}

Interface
{$I SSLeay.def}    {Conditional definitions ...}

Uses
  WinTypes, LIBeay;
{$I SSLconst.inc}  {Constants for SSLeay and LIBeay}

Type
{$I convtype.inc}

  PSSL_CIPHER     =^TSSL_CIPHER;
  PSSL_COMPRESSION=^TSSL_COMPRESSION;
  PSSL_SESSION    =^TSSL_SESSION;
  PSSL_METHOD     =^TSSL_METHOD;
  PSSL_CTX        =^TSSL_CTX;
  PSSL            =^TSSL;

{$I md2_t.inc}
{$I md5_t.inc}
{$I des_t.inc}
{$I mdc2t.inc}
{$I sha_t.inc}
{$I epv_t.inc}
{$I ssl2t.inc}
{$I ssl3t.inc}

  TSSLcallback   = Procedure(ssl: PSSL; location: int; ret: int) cdecl;

  {used to hold info on the particular ciphers used}
  TSSL_CIPHER = record
    valid                    : int;              {int valid;}
    name                     : PChar;            {char *name;                   /* text name */}
    id                       : ulong;            {unsigned long id;             /* id, 4 bytes, first is version */}
    algorithms               : ulong;            {unsigned long algorithms;     /* what ciphers are used */}
    algorithm2               : ulong;            {unsigned long algorithm2;     /* Extra flags */}
    mask                     : ulong;            {unsigned long mask;           /* used for matching */}
  End;{-- SSL_CIPHER ----------------------------------------------------------}

  TSSL_COMPRESSION = record
    stuff                    : PChar;            {char *stuff;}
  End;{-- SSL_COMPRESSION -----------------------------------------------------}

(* Lets make this into an ASN.1 type structure as follows
   SSL_SESSION_ID ::= SEQUENCE {
         version                INTEGER,        -- structure version number
         SSLversion             INTEGER,        -- SSL version number
         Cipher                 OCTET_STRING,   -- the 3 byte cipher ID
         Session_ID             OCTET_STRING,   -- the Session ID
         Master_key             OCTET_STRING,   -- the master key
         Key_Arg [ 0 ] IMPLICIT OCTET_STRING,   -- the optional Key argument
         Time [ 1 ] EXPLICIT    INTEGER,        -- optional Start Time
         Timeout [ 2 ] EXPLICIT INTEGER,        -- optional Timeout ins seconds
         Peer [ 3 ] EXPLICIT    X509,           -- optional Peer Certificate
         }
   Look in ssl/ssl_asn1.c for more details
   I'm using EXPLICIT tags so I can read the damn things using asn1parse :-). *)

  TSSL_SESSION = record
    ssl_version              : int;              {int ssl_version;      /* what ssl version session info is
                                                                         * being kept in here? */}
    { only really used in SSLv2 }
    key_arg_length           : uint;             {unsigned int key_arg_length;}
    key_arg                  : Array[0..SSL_MAX_KEY_ARG_LENGTH-1] of Char; {unsigned char key_arg[SSL_MAX_KEY_ARG_LENGTH];}
    master_key_length        : int;              {int master_key_length;}
    master_key               : Array[0..SSL_MAX_MASTER_KEY_LENGTH-1] of Char;
                                                 {unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];}
    { session_id - valid? }
    session_id_length        : uint;             {unsigned int session_id_length;}
    session_id               : Array[0..SSL_MAX_SSL_SESSION_ID_LENGTH-1] of Char;
                                                 {unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];}

    not_resumable            : int;              {int not_resumable;}

    { The cert is the certificate used to establish this connection }
    cert                     : Pcert_st;         {struct cert_st /* CERT */ *cert;}

    { This is the cert for the other end.  On servers, it will be
      the same as cert->x509}
    peer                     : PX509;            {X509 *peer;}

    references               : int;              {int references;}
    timeout                  : long;             {long timeout;}
    time                     : long;             {long time;}

    read_compression         : PSSL_COMPRESSION; {SSL_COMPRESSION *read_compression;}
    write_compression        : PSSL_COMPRESSION; {SSL_COMPRESSION *write_compression;}

    cipher                   : PSSL_CIPHER;      {SSL_CIPHER *cipher;}
    cipher_id                : ulong;            {unsigned long cipher_id;      /* when ASN.1 loaded, this
                                                                                 * needs to be used to load
                                                                                 * the 'cipher' structure */}
    ciphers                  : PSTACK;           {STACK /* SSL_CIPHER */ *ciphers; /* shared ciphers? */}

    app_data                 : PChar;            {char *app_data; /* application specific data */}
  End;{-- TSSL_SESSION --------------------------------------------------------}

  {Used to hold functions for SSLv2 or SSLv3 functions}
  TSSL_METHOD = record
    version                  : int;              {int version;                                  }
    ssl_new                  : func;             {!!!Sova int ( *ssl_new)();                            }
    ssl_clear                : func;             {void ( *ssl_clear)();                         }
    ssl_free                 : func;             {void ( *ssl_free)();                          }
    ssl_accept               : func;             {int ( *ssl_accept)();                         }
    ssl_connect              : func;             {int ( *ssl_connect)();                        }
    ssl_read                 : func;             {int ( *ssl_read)();                           }
    ssl_peek                 : func;             {int ( *ssl_peek)();                           }
    ssl_write                : func;             {int ( *ssl_write)();                          }
    ssl_shutdown             : func;             {int ( *ssl_shutdown)();                       }
    ssl_renegotiate          : func;             {int ( *ssl_renegotiate)();                    }
    ssl_ctr                  : func;             {long ( *ssl_ctrl)();                          }
    ssl_ctx_ctrl             : func;             {long ( *ssl_ctx_ctrl)();                      }
    get_cipher_by_char       : PSSL_CIPHER;      {SSL_CIPHER *( *get_cipher_by_char)();         }
    put_cipher_by_char       : func;             {int ( *put_cipher_by_char)();                 }
    ssl_pending              : func;             {int ( *ssl_pending)();                        }
    num_ciphers              : func;             {int ( *num_ciphers)();                        }
    get_cipher               : func;             {SSL_CIPHER *( *get_cipher)();                 }
    get_ssl_method           : func;             {struct ssl_method_st *( *get_ssl_method)();   }
    get_timeout              : func;             {long ( *get_timeout)();                       }
  End;{-- TSSL_METHOD ---------------------------------------------------------}

  TSSL_CTX = record                            {typedef struct ssl_ctx_st           }
    method                   : PSSL_METHOD;      {SSL_METHOD *method;               }
    options                  : ULong;            {unsigned long options;            }

    cipher_list              : PSTACK;           {STACK /* SSL_CIPHER */ *cipher_list;}
    { same as above but sorted for lookup }
    cipher_list_by_id        : PSTACK;           {STACK /* SSL_CIPHER */ *cipher_list_by_id;}

    cert_store               : Px509_store_st;   {struct x509_store_st /* X509_STORE */ *cert_store;}
    { a set of SSL_SESSION's }
    sessions                 : Plhash_st;        {struct lhash_st /* LHASH */ *sessions;}

    {This can have one of 2 values, ored together,
     - SSL_SESS_CACHE_CLIENT,
     - SSL_SESS_CACHE_SERVER,
       Default is SSL_SESSION_CACHE_SERVER, which means only
       SSL_accept which cache SSL_SESSIONS.}
    session_cache_mode       : int;              {int session_cache_mode;}

    {If timeout is not 0, it is the default timeout value set
     when SSL_new() is called.  This has been put in to make
     life easier to set things up}
    session_timeout          : long;             {long session_timeout;}

    {If this callback is not null, it will be called each
     time a session id is added to the cache.  If this function
     returns 1, it means that the callback will do a
     SSL_SESSION_free() when it has finished using it.  Otherwise,
     on 0, it means the callback has finished with it.
     If remove_session_cb is not null, it will be called when
     a session-id is removed from the cache.  Again, a return
     of 0 mens that SSLeay should not SSL_SESSION_free() since
     the application is doing something with it.}
                                                 {#ifndef NOPROTO}
    new_session_cb           : func;             {  int ( *new_session_cb)(struct ssl_st *ssl,SSL_SESSION *sess);}
    remove_session_cb        : func;             {  void ( *remove_session_cb)(struct ssl_ctx_st *ctx,SSL_SESSION *sess);}
    get_session_cb           : func;             {  SSL_SESSION *( *get_session_cb)(struct ssl_st *ssl,}
                                                 {          unsigned char *data,int len,int *copy);}
                                                 {#else
                                                 {  int ( *new_session_cb)();}
                                                 {  void ( *remove_session_cb)();}
                                                 {  SSL_SESSION *( *get_session_cb)();}
                                                 {#endif}

    { SSL new (expensive) connection - started }
    sess_connect             : int ;             {int sess_connect;}
    { SSL new (expensive) connection - finished }
    sess_connect_good        : int ;             {int sess_connect_good;}
    { SSL new (expensive) accept - started }
    sess_accept              : int ;             {int sess_accept;}
    { SSL new (expensive) accept - finished }
    sess_accept_good         : int ;             {int sess_accept_good;}
    { session lookup misses  }
    sess_miss                : int ;             {int sess_miss;}
    { session reuse attempt on timeouted session }
    sess_timeout             : int ;             {int sess_timeout;}
    { session reuse actually done }
    sess_hit                 : int ;             {int sess_hit;}
    { session-id that was not in the cache was
      passed back via the callback.  This
      indicates that the application is supplying
      session-id's from other processes -
      spooky :-)   }
    sess_cb_hit              : int ;             {int sess_cb_hit;}

    references               : int ;             {int references;}

    info_callback            : TSSLcallback;     {void (*info_callback)();}

    {if defined, these override the X509_verify_cert() calls}
    app_verify_callback      : func;             {int (*app_verify_callback)();}
    app_verify_arg           : PChar;            {char *app_verify_arg;}

    { default values to use in SSL structures }
    default_cert             : Pcert_st;         {struct cert_st /* CERT */ *default_cert;}
    default_read_ahead       : int;              {int default_read_ahead;}
    default_verify_mode      : int;              {int default_verify_mode;}
    default_verify_callback  : func;             {int (*default_verify_callback)();

    { Default password callback. }
    default_passwd_callback  : func;             {int (*default_passwd_callback)();}

    { get client cert callback }
    client_cert_cb           : func;             {int (*client_cert_cb)(/* SSL *ssl, X509 **x509, EVP_PKEY **pkey */);

    { what we put in client requests }
    client_CA                : PSTACK;           {STACK *client_CA;}

    quiet_shutdown           : int;              {int quiet_shutdown;}

    app_data                 : PChar;            {char *app_data;}
  End;{-- TSSL_CTX ------------------------------------------------------------}


  TSSL = record                                  {typedef struct ssl_st}
    {procol version
      2 for SSLv2
      3 for SSLv3
     -3 for SSLv3 but accept SSLv2}
    version                  : int;              {int version;}
    { SSL_ST_CONNECT or SSL_ST_ACCEPT }
    ssltype                  : int;              {int type;}
    method                   : PSSL_METHOD;      {SSL_METHOD *method; /* SSLv3 */}
    {There are 2 BIO's even though they are normally both the
     same.  This is so data can be read and written to different
     handlers}
                                                 {#ifdef HEADER_BIO_H}
    rbio                     : PBIO;             {      BIO *rbio; /* used by SSL_read */}
    wbio                     : PBIO;             {      BIO *wbio; /* used by SSL_write */}
    bbio                     : PBIO;             {      BIO *bbio; /* used during session-id reuse to concatinate}
                                                 {        * messages */}
                                                 {#else}
                                                 {      char *rbio; /* used by SSL_read */}
                                                 {      char *wbio; /* used by SSL_write */}
                                                 {      char *bbio;}
                                                 {#endif}
    rwstate                  : int;              {int rwstate;}
    {true when we are actually in SSL_accept() or SSL_connect()}
    in_handshake             : int;              {int in_handshake;}
    handshake_func           : func;             {int (*handshake_func)();}
    {/* int server; */ /* are we the server side? */}
    new_session              : int;              {int new_session;/* 1 if we are to use a new session */}
    quiet_shutdown           : int;              {int quiet_shutdown;/* don't send shutdown packets */}
    {we have shut things down, 0x01 sent, 0x02 for received}
    shutdown                 : int;              {int shutdown;}
    state                    : int;              {int state;  /* where we are */}
    rstate                   : int;              {int rstate; /* where we are when reading */}
    { buffer used during init }
    init_buf                 : PBUF_MEM;         {BUF_MEM *init_buf;}
    init_num                 : int;              {int init_num; /* amount read/written */}
    init_off          : int;                     {int init_off; /* amount read/written */}
    { used internally to point at a raw packet }
    packet                   : PChar;            {unsigned char *packet;}
    packet_length            : uint;             {unsigned int packet_length;}
    { SSLv2/3 variables }
    s2                       : Pssl2_ctx_st;     {struct ssl2_ctx_st *s2; /* SSLv2 variables */}
    s3                       : Pssl3_ctx_st;     {struct ssl3_ctx_st *s3; /* SSLv3 variables */}
    { Read as many input bytes as possible }
    read_ahead               : int;              {int read_ahead; /* Read as many input bytes as possible */}
    hit                      : int;              {int hit; /* reusing a previous session */}
    { crypto }
    cipher_list              : PSTACK;           {STACK /* SSL_CIPHER */ *cipher_list;}
    cipher_list_by_id        : PSTACK;           {STACK /* SSL_CIPHER */ *cipher_list_by_id;}
    {These are the ones being used, the ones is SSL_SESSION are
     the ones to be 'copied' into these ones}
    enc_read_ctx             : PEVP_CIPHER_CTX;  {EVP_CIPHER_CTX *enc_read_ctx;        /* cryptographic state */}
    read_hash                : PEVP_MD;          {EVP_MD *read_hash; /* used for mac generation */}
    read_compression         : PSSL_COMPRESSION; {SSL_COMPRESSION *read_compression; /* compression */}
    enc_write_ctx            : PEVP_CIPHER_CTX;  {EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */}
    write_hash               : PEVP_MD;          {EVP_MD *write_hash; /* used for mac generation */}
    write_compression        : PSSL_COMPRESSION; {SSL_COMPRESSION *write_compression; /* compression */}

    { session info }
    { client cert? }
    { This is used to hold the server certificate used }
    cert                     : Pcert_st;         {struct cert_st /* CERT */ *cert;}
    { This can also be in the session once a session is established }
    session                  : PSSL_SESSION;     {SSL_SESSION *session;}
    { Used in SSL2 and SSL3 }
    verify_mode              : int;              {int verify_mode; /* 0 don't care about verify failure.
                                                                    * 1 fail if verify fails */}
    verify_callback          : func;             {int (*verify_callback)(); /* fail if callback returns 0 */}
    { optional informational callback }
    info_callback            : TSSLcallback;     {void (*info_callback)(); /* optional informational callback */}

    error                    : int;              {int error; /* error bytes to be written */}
    error_code               : int;              {int error_code; /* actual code */}

    ctx                      : PSSL_CTX;         {SSL_CTX *ctx;}
    { set this flag to 1 and a sleep(1) is put into all SSL_read()
      and SSL_write() calls, good for nbio debuging :-) }
    debug                    : int;              {int debug;}
    { extra application data }
    verify_result            : int;              {int verify_result;}
    app_data                 : PChar;            {char *app_data;}
    { for server side, keep the list of CA_dn we can use }
    client_CA                : PSTACK;           {STACK /* X509_NAME */ *client_CA;}

    first_packet             : int;              {int first_packet;}
  End;{-- TSSL ----------------------------------------------------------------}

{-- Macros. PASCAL haven't macros :-( monkey work! ----------------------------}
Procedure SSL_CTX_set_quiet_shutdown(ctx:PSSL_CTX; y:int);
Function  SSL_CTX_get_quiet_shutdown(ctx:PSSL_CTX):int;
Procedure SSL_set_quiet_shutdown(s:PSSL; y:int);
Function  SSL_get_quiet_shutdown(s:PSSL):int;
Procedure SSL_set_shutdown(s:PSSL; mode:int);
Function  SSL_get_shutdown(s:PSSL):int;
Function  SSL_version(s:PSSL):int;

Procedure SSL_CTX_set_options(ctx:PSSL_CTX; op:ulong);

Function  SSL_CTX_get_cert_store(ctx:PSSL_CTX):Px509_store_st;

Function  SSL_session_reused(s:PSSL):int;

Function  SSL_CTX_sessions(ctx:PSSL_CTX):Plhash_st;
{ You will need to include lhash.h to access the following #define }
Function  SSL_CTX_sess_connect(ctx:PSSL_CTX):int;
Function  SSL_CTX_sess_connect_good(ctx:PSSL_CTX):int;
Function  SSL_CTX_sess_accept(ctx:PSSL_CTX):int;
Function  SSL_CTX_sess_accept_good(ctx:PSSL_CTX):int;
Function  SSL_CTX_sess_hits(ctx:PSSL_CTX):int;
Function  SSL_CTX_sess_cb_hits(ctx:PSSL_CTX):int;
Function  SSL_CTX_sess_misses(ctx:PSSL_CTX):int;
Function  SSL_CTX_sess_timeouts(ctx:PSSL_CTX):int;

Procedure SSL_CTX_sess_set_new_cb(ctx:PSSL_CTX; cb:func);
Function  SSL_CTX_sess_get_new_cb(ctx:PSSL_CTX):func;
Procedure SSL_CTX_sess_set_remove_cb(ctx:PSSL_CTX; cb:func);
Function  SSL_CTX_sess_get_remove_cb(ctx:PSSL_CTX):func;
Procedure SSL_CTX_sess_set_get_cb(ctx:PSSL_CTX; cb:func);
Function  SSL_CTX_sess_get_get_cb(ctx:PSSL_CTX):func;
Procedure SSL_CTX_set_session_cache_mode(ctx:PSSL_CTX; m:int);
Function  SSL_CTX_get_session_cache_mode(ctx:PSSL_CTX):int;
Procedure SSL_CTX_set_timeout(ctx:PSSL_CTX; t:int);
Function  SSL_CTX_get_timeout(ctx:PSSL_CTX):int;

Procedure SSL_CTX_set_info_callback(ctx:PSSL_CTX; cb:TSSLcallback);
Function  SSL_CTX_get_info_callback(ctx:PSSL_CTX):TSSLcallback;
Procedure SSL_CTX_set_default_read_ahead(ctx:PSSL_CTX; m:int);

Procedure SSL_CTX_set_client_cert_cb(ctx:PSSL_CTX; cb:func);
Function  SSL_CTX_get_client_cert_cb(ctx:PSSL_CTX):func;

{ These will only be used when doing non-blocking IO }
Function SSL_want(s:PSSL):int;
Function SSL_want_nothing(s:PSSL):boolean;
Function SSL_want_read(s:PSSL):boolean;
Function SSL_want_write(s:PSSL):boolean;
Function SSL_want_x509_lookup(s:PSSL):boolean;

{ application stuff }
Procedure SSL_set_verify_result(s:PSSL; arg:int);
Function  SSL_get_verify_result(s:PSSL):int;
Procedure SSL_set_app_data(s:PSSL; arg:PChar);
Function  SSL_get_app_data(s:PSSL):PChar;

Procedure SSL_SESSION_set_app_data(s:PSSL; arg:PChar);
Function  SSL_SESSION_get_app_data(s:PSSL):PChar;

Procedure SSL_CTX_set_app_data(ctx:PSSL_CTX; arg:PChar);
Function  SSL_CTX_get_app_data(ctx:PSSL_CTX):PChar;

Function  SSL_state(a:PSSL):int;

{ SSL info callback functions }
Procedure SSL_set_info_callback(ssl:PSSL; cb:TSSLcallback);
Function  SSL_get_info_callback(ssl:PSSL):TSSLcallback;

{ Is the SSL_connection established? }
Function  SSL_is_init_finished(a:PSSL):Boolean;
Function  SSL_in_init(a:PSSL):Boolean;
Function  SSL_in_before(a:PSSL):Boolean;
Function  SSL_in_connect_init(a:PSSL):Boolean;
Function  SSL_in_accept_init(a:PSSL):Boolean;

Function  SSL_get_session(s:PSSL):PSSL_SESSION;
Function  SSL_get_SSL_CTX(s:PSSL):PSSL_CTX;


Function Init:Boolean;
Procedure Done;

{-- Realy imported functions --------------------------------------------------}
Const
 BEGIN_IMP_FUNC                :Pointer=nil;
 SSL_CTX_set_cipher_list       :Function (ctx:PSSL_CTX; str:PChar):int                       cdecl=nil;
 SSL_CTX_new                   :Function (meth:PSSL_METHOD):PSSL_CTX                         cdecl=nil;
 SSL_CTX_free                  :Procedure(ctx:PSSL_CTX)                                      cdecl=nil;
 SSL_CTX_flush_sessions        :Procedure(ctx:PSSL_CTX; tm:long)                             cdecl=nil;

 SSL_get_current_cipher        :Function (s:PSSL):PSSL_CIPHER                                cdecl=nil;
 SSL_CIPHER_get_bits           :Function (c:PSSL_CIPHER; var alg_bits:int):int               cdecl=nil;
 SSL_CIPHER_get_version        :Function (c:PSSL_CIPHER):PChar                               cdecl=nil;
 SSL_CIPHER_get_name           :Function (c:PSSL_CIPHER):PChar                               cdecl=nil;

 SSL_get_fd                    :Function (s:PSSL):int                                        cdecl=nil;
 SSL_get_cipher_list           :Function (s:PSSL; n:int):PChar                               cdecl=nil;
 SSL_get_shared_ciphers        :Function (s:PSSL; buf:PChar; len:int):PChar                  cdecl=nil;
 SSL_get_read_ahead            :Function (s:PSSL):int                                        cdecl=nil;
 SSL_pending                   :Function (s:PSSL):int                                        cdecl=nil;

 SSL_set_cipher_list           :Function (s:PSSL; str:PChar):int                             cdecl=nil;
 SSL_set_read_ahead            :Procedure(s:PSSL; yes:int)                                   cdecl=nil;
{D1!!! SSL_get_verify_mode           :Function (s:PSSL):int;                                       cdecl=nil;}
 SSL_use_RSAPrivateKey         :Function (ssl:PSSL; rsa:PRSA):int                            cdecl=nil;
 SSL_use_RSAPrivateKey_ASN1    :Function (ssl:PSSL; d:PChar; len:long):int                   cdecl=nil;
 SSL_use_RSAPrivateKey_file    :Function (ssl:PSSL; afile:PChar; atype:int):int              cdecl=nil;
 SSL_use_PrivateKey            :Function (ssl:PSSL; pkey:PEVP_PKEY):int                      cdecl=nil;
 SSL_use_PrivateKey_ASN1       :Function (pk:int; ssl:PSSL; d:PChar; len:long):int           cdecl=nil;
 SSL_use_PrivateKey_file       :Function (ssl:PChar; afile:PChar; atype:int):int             cdecl=nil;
 SSL_use_certificate           :Function (ssl:PSSL; x:PX509):int                             cdecl=nil;
 SSL_use_certificate_ASN1      :Function (ssl:PSSL; len:int; d:PChar):int                    cdecl=nil;
 SSL_use_certificate_file      :Function (ssl:PSSL; afile:PChar; atype:int):int              cdecl=nil;
 ERR_load_SSL_strings          :Procedure                                                    cdecl=nil;
 SSL_load_error_strings        :Procedure                                                    cdecl=nil;
 SSL_state_string              :Function (s:PSSL):PChar                                      cdecl=nil;
 SSL_rstate_string             :Function (s:PSSL):PChar                                      cdecl=nil;
 SSL_state_string_long         :Function (s:PSSL):PChar                                      cdecl=nil;
 SSL_rstate_string_long        :Function (s:PSSL):PChar                                      cdecl=nil;
 SSL_get_time                  :Function (s:PSSL_SESSION):long                               cdecl=nil;
 SSL_set_time                  :Function (s:PSSL_SESSION; t:long):long                       cdecl=nil;
 SSL_get_timeout               :Function (s:PSSL_SESSION):long                               cdecl=nil;
 SSL_set_timeout               :Function (s:PSSL_SESSION; t:long):long                       cdecl=nil;
 SSL_copy_session_id           :Procedure(ato:PSSL; from:PSSL)                               cdecl=nil;
 SSL_get_peer_certificate      :function (s:PSSL):PX509                                      cdecl=nil;
 SSL_CTX_get_verify_mode       :Function (ctx:PSSL_CTX):int                                  cdecl=nil;
 SSL_CTX_use_RSAPrivateKey     :Function (ctx:PSSL_CTX; rsa:PRSA):int                        cdecl=nil;
 SSL_CTX_use_RSAPrivateKey_ASN1:Function (ctx:PSSL_CTX; d:PChar; len:long):int               cdecl=nil;
 SSL_CTX_use_RSAPrivateKey_file:Function (ctx:PSSL_CTX; afile:char; atype:int):int           cdecl=nil;
 SSL_CTX_use_PrivateKey        :Function (ctx:PSSL_CTX; pkey:PEVP_PKEY):int                  cdecl=nil;
 SSL_CTX_use_PrivateKey_ASN1   :Function (pk:int; ctx:PSSL_CTX; d:PChar; len:long):int       cdecl=nil;
 SSL_CTX_use_PrivateKey_file   :Function (ctx:PSSL_CTX; pfile:PChar; atype:int):int          cdecl=nil;
 SSL_CTX_use_certificate       :Function (ctx:PSSL_CTX; x:PX509):int                         cdecl=nil;
 SSL_CTX_use_certificate_ASN1  :Function (ctx:PSSL_CTX; len:int; d:PChar):int                cdecl=nil;
 SSL_CTX_use_certificate_file  :Function (ctx:PSSL_CTX; afile:PChar; atype:int):int          cdecl=nil;

 SSL_new                       :Function (ctx:PSSL_CTX):PSSL                                 cdecl=nil;
 SSL_clear                     :Procedure(s:PSSL)                                            cdecl=nil;
 SSL_free                      :Procedure(ssl:PSSL)                                          cdecl=nil;
 SSL_accept                    :Function (ssl:PSSL):int                                      cdecl=nil;
 SSL_connect                   :Function (ssl:PSSL):int                                      cdecl=nil;
 SSL_read                      :Function (ssl:PSSL; buf:PChar; num:int):int                  cdecl=nil;
 SSL_peek                      :Function (ssl:PSSL; buf:PChar; num:int):int                  cdecl=nil;
 SSL_write                     :Function (ssl:PSSL; buf:PChar; num:int):int                  cdecl=nil;
 SSL_ctrl                      :Function (ssl:PSSL; cmd:int; larg:long; parg:PChar):long     cdecl=nil;
 SSL_CTX_ctrl                  :Function (ctx:PSSL_CTX; cmd:int; larg:long; parg:PChar):long cdecl=nil;

 SSL_get_error                 :Function (s:PSSL; ret_code:int):int                          cdecl=nil;
 SSL_get_version               :Function (s:PSSL):PChar                                      cdecl=nil;

 { This sets the 'default' SSL version that SSL_new() will create }
 SSL_CTX_set_ssl_version       :Function (ctx:PSSL_CTX; meth:PSSL_METHOD):int                cdecl=nil;

 SSLv2_method                  :Function :PSSL_METHOD                                        cdecl=nil;
 SSLv2_server_method           :Function :PSSL_METHOD                                        cdecl=nil;
 SSLv2_client_method           :Function :PSSL_METHOD                                        cdecl=nil;

 SSLv3_method                  :Function :PSSL_METHOD                                        cdecl=nil;
 SSLv3_server_method           :Function :PSSL_METHOD                                        cdecl=nil;
 SSLv3_client_method           :Function :PSSL_METHOD                                        cdecl=nil;

 SSLv23_method                 :Function :PSSL_METHOD                                        cdecl=nil;
 SSLv23_server_method          :Function :PSSL_METHOD                                        cdecl=nil;
 SSLv23_client_method          :Function :PSSL_METHOD                                        cdecl=nil;

 SSL_get_ciphers               :Function (s:PSSL):PSTACK                                     cdecl=nil;

 SSL_do_handshake              :Function (s:PSSL):int                                        cdecl=nil;
 SSL_renegotiate               :Function (s:PSSL):int                                        cdecl=nil;
 SSL_shutdown                  :Function (s:PSSL):int                                        cdecl=nil;

 SSL_get_ssl_method            :Function (s:PSSL):PSSL_METHOD                                cdecl=nil;
 SSL_set_ssl_method            :Function (s:PSSL; method:PSSL_METHOD):int                     cdecl=nil;
 SSL_alert_type_string_long    :Function (value:int):PChar                                   cdecl=nil;
 SSL_alert_type_string         :Function (value:int):PChar                                   cdecl=nil;
 SSL_alert_desc_string_long    :Function (value:int):PChar                                   cdecl=nil;
 SSL_alert_desc_string         :Function (value:int):PChar                                   cdecl=nil;

 SSL_load_client_CA_file       :Function (afile:PChar):PSTACK                                cdecl=nil;
 SSL_set_client_CA_list        :Procedure (s:PSSL; list:PSTACK)                              cdecl=nil;
 SSL_CTX_set_client_CA_list    :Procedure(ctx:PSSL_CTX; list:PSTACK)                         cdecl=nil;
 SSL_get_client_CA_list        :Function (s:PSSL):PSTACK                                     cdecl=nil;
 SSL_CTX_get_client_CA_list    :Function (ctx:PSSL_CTX):PSTACK                               cdecl=nil;
 SSL_add_client_CA             :Function (ssl:PSSL;x:PX509):int                              cdecl=nil;
 SSL_CTX_add_client_CA         :Function (ctx:PSSL_CTX;x:PX509):int                          cdecl=nil;

 SSL_set_fd                    :Function (s:PSSL; fd:int):int                                cdecl=nil;
 SSL_set_rfd                   :Function (s:PSSL; fd:int):int                                cdecl=nil;
 SSL_set_wfd                   :Function (s:PSSL; fd:int):int                                cdecl=nil;

 SSL_set_connect_state         :Procedure(s:PSSL)                                            cdecl=nil;
 SSL_set_accept_state          :Procedure(s:PSSL)                                            cdecl=nil;

 SSL_get_default_timeout       :Function (s:PSSL):long                                       cdecl=nil;

 SSLeay_add_ssl_algorithms     :Procedure                                                    cdecl=nil;

 SSL_CIPHER_description        :Function(ssl_cipher:PSSL_CIPHER; buf:PChar; size:int):PChar  cdecl=nil;
{D1!!! SSL_dup_CA_list               :Function(sk:PSTACK):PSTACK;                                  cdecl=nil;}

{D1!!! SSL_dup                       :Function(ssl:PSSL):PSSL;                                     cdecl=nil;}

{D1!!! SSL_get_certificate           :Function(ssl:PSSL):PX509;                                    cdecl=nil;}
{D1!!! SSL_get_privatekey            :Function(ssl:PSSL):Pevp_pkey;                                cdecl=nil;}
 END_IMP_FUNC                  :Pointer=nil;


Implementation
Uses
  WinProcs;

Const
  Initialized  : Boolean = False;
  Handle       : THandle = 0;
  _           ={$IFDEF Win32}'';{$ELSE}'_' ;{$ENDIF}
  LibraryName ={$IFDEF Win32}'SSLeay32.dll';{$ELSE}'SSLeay16.dll';{$ENDIF}

Function LoadFunction(Var res:Boolean; FceName:String):TFARPROC;
Begin
  If res Then Begin
    FceName := _+FceName+#0;
    Result  := GetProcAddress(Handle, @FceName[1]);
    If Result=nil Then res:=False;
  End Else
    Result  := nil;
End;

Function  Init:Boolean;
Begin
  If Initialized Then Begin Result:=True; Exit; End;

  Result := LIBeay.Init;
  If not Result Then Exit;

  {-- Load external functions -------------------------------------------------}
  Handle := LoadLibrary(LibraryName);
  If Handle=0 Then Exit;

  Result :=True;

  @SSL_CTX_set_cipher_list          := LoadFunction(Result, 'SSL_CTX_set_cipher_list');
  @SSL_CTX_new                      := LoadFunction(Result, 'SSL_CTX_new');
  @SSL_CTX_free                     := LoadFunction(Result, 'SSL_CTX_free');
  @SSL_CTX_flush_sessions           := LoadFunction(Result, 'SSL_CTX_flush_sessions');

  @SSL_get_current_cipher           := LoadFunction(Result, 'SSL_get_current_cipher');
  @SSL_CIPHER_get_bits              := LoadFunction(Result, 'SSL_CIPHER_get_bits');
  @SSL_CIPHER_get_version           := LoadFunction(Result, 'SSL_CIPHER_get_version');
  @SSL_CIPHER_get_name              := LoadFunction(Result, 'SSL_CIPHER_get_name');

  @SSL_get_fd                       := LoadFunction(Result, 'SSL_get_fd');
  @SSL_get_cipher_list              := LoadFunction(Result, 'SSL_get_cipher_list');
  @SSL_get_shared_ciphers           := LoadFunction(Result, 'SSL_get_shared_ciphers');
  @SSL_get_read_ahead               := LoadFunction(Result, 'SSL_get_read_ahead');
  @SSL_pending                      := LoadFunction(Result, 'SSL_pending');

  @SSL_set_cipher_list              := LoadFunction(Result, 'SSL_set_cipher_list');
  @SSL_set_read_ahead               := LoadFunction(Result, 'SSL_set_read_ahead');
{D11!!!  @SSL_get_verify_mode              := LoadFunction(Result, 'SSL_get_verify_mode');}
  @SSL_use_RSAPrivateKey            := LoadFunction(Result, 'SSL_use_RSAPrivateKey');
  @SSL_use_RSAPrivateKey_ASN1       := LoadFunction(Result, 'SSL_use_RSAPrivateKey_ASN1');
  @SSL_use_RSAPrivateKey_file       := LoadFunction(Result, 'SSL_use_RSAPrivateKey_file');
  @SSL_use_PrivateKey               := LoadFunction(Result, 'SSL_use_PrivateKey');
  @SSL_use_PrivateKey_ASN1          := LoadFunction(Result, 'SSL_use_PrivateKey_ASN1');
  @SSL_use_PrivateKey_file          := LoadFunction(Result, 'SSL_use_PrivateKey_file');
  @SSL_use_certificate              := LoadFunction(Result, 'SSL_use_certificate');
  @SSL_use_certificate_ASN1         := LoadFunction(Result, 'SSL_use_certificate_ASN1');
  @SSL_use_certificate_file         := LoadFunction(Result, 'SSL_use_certificate_file');
  @ERR_load_SSL_strings             := LoadFunction(Result, 'ERR_load_SSL_strings');
  @SSL_load_error_strings           := LoadFunction(Result, 'SSL_load_error_strings');
  @SSL_state_string                 := LoadFunction(Result, 'SSL_state_string');
  @SSL_rstate_string                := LoadFunction(Result, 'SSL_rstate_string');
  @SSL_state_string_long            := LoadFunction(Result, 'SSL_state_string_long');
  @SSL_rstate_string_long           := LoadFunction(Result, 'SSL_rstate_string_long');
  @SSL_get_time                     := LoadFunction(Result, 'SSL_get_time');
  @SSL_set_time                     := LoadFunction(Result, 'SSL_set_time');
  @SSL_get_timeout                  := LoadFunction(Result, 'SSL_get_timeout');
  @SSL_set_timeout                  := LoadFunction(Result, 'SSL_set_timeout');
  @SSL_copy_session_id              := LoadFunction(Result, 'SSL_copy_session_id');

  @SSL_get_peer_certificate         := LoadFunction(Result, 'SSL_get_peer_certificate');

  @SSL_CTX_get_verify_mode          := LoadFunction(Result, 'SSL_CTX_get_verify_mode');
  @SSL_CTX_use_RSAPrivateKey        := LoadFunction(Result, 'SSL_CTX_use_RSAPrivateKey');
  @SSL_CTX_use_RSAPrivateKey_ASN1   := LoadFunction(Result, 'SSL_CTX_use_RSAPrivateKey_ASN1');
  @SSL_CTX_use_RSAPrivateKey_file   := LoadFunction(Result, 'SSL_CTX_use_RSAPrivateKey_file');
  @SSL_CTX_use_PrivateKey           := LoadFunction(Result, 'SSL_CTX_use_PrivateKey');
  @SSL_CTX_use_PrivateKey_ASN1      := LoadFunction(Result, 'SSL_CTX_use_PrivateKey_ASN1');
  @SSL_CTX_use_PrivateKey_file      := LoadFunction(Result, 'SSL_CTX_use_PrivateKey_file');
  @SSL_CTX_use_certificate          := LoadFunction(Result, 'SSL_CTX_use_certificate');
  @SSL_CTX_use_certificate_ASN1     := LoadFunction(Result, 'SSL_CTX_use_certificate_ASN1');
  @SSL_CTX_use_certificate_file     := LoadFunction(Result, 'SSL_CTX_use_certificate_file');

  @SSL_new                          := LoadFunction(Result, 'SSL_new');
  @SSL_clear                        := LoadFunction(Result, 'SSL_clear');
  @SSL_free                         := LoadFunction(Result, 'SSL_free');
  @SSL_accept                       := LoadFunction(Result, 'SSL_accept');
  @SSL_connect                      := LoadFunction(Result, 'SSL_connect');
  @SSL_read                         := LoadFunction(Result, 'SSL_read');
  @SSL_peek                         := LoadFunction(Result, 'SSL_peek');
  @SSL_write                        := LoadFunction(Result, 'SSL_write');
  @SSL_ctrl                         := LoadFunction(Result, 'SSL_ctrl');
  @SSL_CTX_ctrl                     := LoadFunction(Result, 'SSL_CTX_ctrl');

  @SSL_get_error                    := LoadFunction(Result, 'SSL_get_error');
  @SSL_get_version                  := LoadFunction(Result, 'SSL_get_version');

  @SSL_CTX_set_ssl_version          := LoadFunction(Result, 'SSL_CTX_set_ssl_version');

  @SSLv2_method                     := LoadFunction(Result, 'SSLv2_method');
  @SSLv2_server_method              := LoadFunction(Result, 'SSLv2_server_method');
  @SSLv2_client_method              := LoadFunction(Result, 'SSLv2_client_method');

  @SSLv3_method                     := LoadFunction(Result, 'SSLv3_method');
  @SSLv3_server_method              := LoadFunction(Result, 'SSLv3_server_method');
  @SSLv3_client_method              := LoadFunction(Result, 'SSLv3_client_method');

  @SSLv23_method                    := LoadFunction(Result, 'SSLv23_method');
  @SSLv23_server_method             := LoadFunction(Result, 'SSLv23_server_method');
  @SSLv23_client_method             := LoadFunction(Result, 'SSLv23_client_method');

  @SSL_get_ciphers                  := LoadFunction(Result, 'SSL_get_ciphers');

  @SSL_do_handshake                 := LoadFunction(Result, 'SSL_do_handshake');
  @SSL_renegotiate                  := LoadFunction(Result, 'SSL_renegotiate');
  @SSL_shutdown                     := LoadFunction(Result, 'SSL_shutdown');

  @SSL_get_ssl_method               := LoadFunction(Result, 'SSL_get_ssl_method');
  @SSL_set_ssl_method               := LoadFunction(Result, 'SSL_set_ssl_method');
  @SSL_alert_type_string_long       := LoadFunction(Result, 'SSL_alert_type_string_long');
  @SSL_alert_type_string            := LoadFunction(Result, 'SSL_alert_type_string');
  @SSL_alert_desc_string_long       := LoadFunction(Result, 'SSL_alert_desc_string_long');
  @SSL_alert_desc_string            := LoadFunction(Result, 'SSL_alert_desc_string');

  @SSL_load_client_CA_file          := LoadFunction(Result, 'SSL_load_client_CA_file');
  @SSL_set_client_CA_list           := LoadFunction(Result, 'SSL_set_client_CA_list');
  @SSL_CTX_set_client_CA_list       := LoadFunction(Result, 'SSL_CTX_set_client_CA_list');
  @SSL_get_client_CA_list           := LoadFunction(Result, 'SSL_get_client_CA_list');
  @SSL_CTX_get_client_CA_list       := LoadFunction(Result, 'SSL_CTX_get_client_CA_list');
  @SSL_add_client_CA                := LoadFunction(Result, 'SSL_add_client_CA');
  @SSL_CTX_add_client_CA            := LoadFunction(Result, 'SSL_CTX_add_client_CA');

  @SSL_set_fd                       := LoadFunction(Result, 'SSL_set_fd');
  @SSL_set_rfd                      := LoadFunction(Result, 'SSL_set_rfd');
  @SSL_set_wfd                      := LoadFunction(Result, 'SSL_set_wfd');

  @SSL_set_connect_state            := LoadFunction(Result, 'SSL_set_connect_state');
  @SSL_set_accept_state             := LoadFunction(Result, 'SSL_set_accept_state');

  @SSL_get_default_timeout          := LoadFunction(Result, 'SSL_get_default_timeout');

  @SSLeay_add_ssl_algorithms        := LoadFunction(Result, 'SSLeay_add_ssl_algorithms');

  @SSL_CIPHER_description           := LoadFunction(Result, 'SSL_CIPHER_description');
{D1!!!  @SSL_dup_CA_list                  := LoadFunction(Result, 'SSL_dup_CA_list');

  @SSL_dup                          := LoadFunction(Result, 'SSL_dup');

  @SSL_get_certificate              := LoadFunction(Result, 'SSL_get_certificate');
  @SSL_get_privatekey               := LoadFunction(Result, 'SSL_get_privatekey');}

  {-- Initalize library -------------------------------------------------------}
  Initialized:= Result;
  If not Result Then Exit;

  SSLeay_add_ssl_algorithms;
  SSL_load_error_strings;
  ERR_load_SSL_strings;
End;

Procedure SetFuncPoiter2Nil;
Begin
  { This is maybe danger construction !}
  FillChar(BEGIN_IMP_FUNC, (Longint(@END_IMP_FUNC)-Longint(@BEGIN_IMP_FUNC)), 0);
End;

Procedure Done;
Begin
  If not Initialized Then Exit;
  Initialized:=False;

  FreeLibrary(Handle); Handle:=0;
  SetFuncPoiter2Nil;
End;

Procedure SSL_CTX_set_quiet_shutdown(ctx:PSSL_CTX; y:int); Begin ctx^.quiet_shutdown:=y;       End;
Function  SSL_CTX_get_quiet_shutdown(ctx:PSSL_CTX):int;    Begin Result:=ctx^.quiet_shutdown;  End;
Procedure SSL_set_quiet_shutdown(s:PSSL; y:int);           Begin s^.quiet_shutdown:=y;         End;
Function  SSL_get_quiet_shutdown(s:PSSL):int;              Begin Result:=s^.quiet_shutdown;    End;
Procedure SSL_set_shutdown(s:PSSL; mode:int);              Begin s^.shutdown:=mode;            End;
Function  SSL_get_shutdown(s:PSSL):int;                    Begin Result:=s^.shutdown;          End;
Function  SSL_version(s:PSSL):int;                         Begin Result:=s^.version;           End;

Procedure SSL_CTX_set_options(ctx:PSSL_CTX; op:ulong);     Begin ctx^.options:=ctx^.options or op End;

{ Normally you will only use these if your application wants to use
  the certificate store in other places, perhaps PKCS7 }
Function  SSL_CTX_get_cert_store(ctx:PSSL_CTX):Px509_store_st; Begin Result:=ctx^.cert_store End;
{!!!Translate
Procedure SSL_CTX_set_cert_store(ctx:PSSL_CTX; cs:Px509_store_st);
  Begin X509_STORE_free((ctx)->cert_store),(ctx)->cert_store=(cs))}

Function  SSL_session_reused(s:PSSL):int;              Begin Result:=s^.hit End;

Function  SSL_CTX_sessions(ctx:PSSL_CTX):Plhash_st;    Begin Result:=ctx^.sessions End;
{ You will need to include lhash.h to access the following #define }
Function  SSL_CTX_sess_connect(ctx:PSSL_CTX):int;      Begin Result:=ctx^.sess_connect End;
Function  SSL_CTX_sess_connect_good(ctx:PSSL_CTX):int; Begin Result:=ctx^.sess_connect_good End;
Function  SSL_CTX_sess_accept(ctx:PSSL_CTX):int;       Begin Result:=ctx^.sess_accept End;
Function  SSL_CTX_sess_accept_good(ctx:PSSL_CTX):int;  Begin Result:=ctx^.sess_accept_good End;
Function  SSL_CTX_sess_hits(ctx:PSSL_CTX):int;         Begin Result:=ctx^.sess_hit End;
Function  SSL_CTX_sess_cb_hits(ctx:PSSL_CTX):int;      Begin Result:=ctx^.sess_cb_hit End;
Function  SSL_CTX_sess_misses(ctx:PSSL_CTX):int;       Begin Result:=ctx^.sess_miss End;
Function  SSL_CTX_sess_timeouts(ctx:PSSL_CTX):int;     Begin Result:=ctx^.sess_timeout End;

Procedure SSL_CTX_sess_set_new_cb(ctx:PSSL_CTX; cb:func);     Begin ctx^.new_session_cb:=cb End;
Function  SSL_CTX_sess_get_new_cb(ctx:PSSL_CTX):func;         Begin Result:=ctx^.new_session_cb End;
Procedure SSL_CTX_sess_set_remove_cb(ctx:PSSL_CTX; cb:func);  Begin ctx^.remove_session_cb:=cb End;
Function  SSL_CTX_sess_get_remove_cb(ctx:PSSL_CTX):func;      Begin Result:=ctx^.remove_session_cb End;
Procedure SSL_CTX_sess_set_get_cb(ctx:PSSL_CTX; cb:func);     Begin ctx^.get_session_cb:=cb End;
Function  SSL_CTX_sess_get_get_cb(ctx:PSSL_CTX):func;         Begin Result:=ctx^.get_session_cb End;
Procedure SSL_CTX_set_session_cache_mode(ctx:PSSL_CTX; m:int);Begin ctx^.session_cache_mode:=m End;
Function  SSL_CTX_get_session_cache_mode(ctx:PSSL_CTX):int;   Begin Result:=ctx^.session_cache_mode End;
Procedure SSL_CTX_set_timeout(ctx:PSSL_CTX; t:int);           Begin ctx^.session_timeout:=t End;
Function  SSL_CTX_get_timeout(ctx:PSSL_CTX):int;              Begin Result:=ctx^.session_timeout End;

Procedure SSL_CTX_set_info_callback(ctx:PSSL_CTX; cb:TSSLcallback);Begin ctx^.info_callback:=cb End;
Function  SSL_CTX_get_info_callback(ctx:PSSL_CTX):TSSLcallback;    Begin Result:=ctx^.info_callback End;
Procedure SSL_CTX_set_default_read_ahead(ctx:PSSL_CTX; m:int);     Begin ctx^.default_read_ahead:=m End;

Procedure SSL_CTX_set_client_cert_cb(ctx:PSSL_CTX; cb:func); Begin ctx^.client_cert_cb:=cb End;
Function  SSL_CTX_get_client_cert_cb(ctx:PSSL_CTX):func;     Begin Result:=ctx^.client_cert_cb End;

{ These will only be used when doing non-blocking IO }
Function SSL_want(s:PSSL):int;                Begin Result:=s^.rwstate End;
Function SSL_want_nothing(s:PSSL):boolean;    Begin Result:=s^.rwstate = SSL_NOTHING End;
Function SSL_want_read(s:PSSL):boolean;       Begin Result:=s^.rwstate = SSL_READING End;
Function SSL_want_write(s:PSSL):boolean;      Begin Result:=s^.rwstate = SSL_WRITING End;
Function SSL_want_x509_lookup(s:PSSL):boolean;Begin Result:=s^.rwstate = SSL_X509_LOOKUP End;

{ application stuff }
Procedure SSL_set_verify_result(s:PSSL; arg:int); Begin s^.verify_result:={(long)}arg End;
Function  SSL_get_verify_result(s:PSSL):int;      Begin Result:=s^.verify_result End;
Procedure SSL_set_app_data(s:PSSL; arg:PChar);    Begin s^.app_data:=arg End;
Function  SSL_get_app_data(s:PSSL):PChar;         Begin Result:=s^.app_data End;

Procedure SSL_SESSION_set_app_data(s:PSSL; arg:PChar);Begin s^.app_data:=arg End;
Function  SSL_SESSION_get_app_data(s:PSSL):PChar;     Begin Result:=s^.app_data End;

Procedure SSL_CTX_set_app_data(ctx:PSSL_CTX; arg:PChar);Begin ctx^.app_data:=arg End;
Function  SSL_CTX_get_app_data(ctx:PSSL_CTX):PChar;     Begin Result:=ctx^.app_data End;

Function  SSL_state(a:PSSL):int; Begin Result:=a^.state End;

{ SSL info callback functions }
Procedure SSL_set_info_callback(ssl:PSSL; cb:TSSLcallback); Begin ssl^.info_callback:=cb End;
Function  SSL_get_info_callback(ssl:PSSL):TSSLcallback;     Begin Result:=ssl^.info_callback End;

{ Is the SSL_connection established? }
Function  SSL_is_init_finished(a:PSSL):Boolean; Begin Result:=a^.state = SSL_ST_OK End;
Function  SSL_in_init(a:PSSL):Boolean;          Begin Result:=(a^.state and SSL_ST_INIT   )>0 End;
Function  SSL_in_before(a:PSSL):Boolean;        Begin Result:=(a^.state and SSL_ST_BEFORE )>0 End;
Function  SSL_in_connect_init(a:PSSL):Boolean;  Begin Result:=(a^.state and SSL_ST_CONNECT)>0 End;
Function  SSL_in_accept_init(a:PSSL):Boolean;   Begin Result:=(a^.state and SSL_ST_ACCEPT )>0 End;

Function  SSL_get_session(s:PSSL):PSSL_SESSION; Begin Result:=s^.session End;
Function  SSL_get_SSL_CTX(s:PSSL):PSSL_CTX;     Begin Result:=s^.ctx End;



initialization
  Initialized:=False;
{$IFDEF WIN32}
finalization
  If Initialized Then Done;
{$ENDIF}
End.
