This package includes the SharkSSL lite library and header files.

Dependents:   WebSocket-Client-Example SharkMQ-LED-Demo

SharkSSL-Lite

Description: SharkSSL is an SSL v3.0 TLS v1.0/1.1/1.2 implementation of the TLS and SSL protocol standard. With its array of compile-time options and Raycrypto proprietary cryptographic algorithms, SharkSSL can be fine-tuned to a footprint that occupies less than 20 kB, while maintaining full x.509 authentication. The SharkSSL-Lite download includes a subset of SharkSSL and header files made for use in non-commercial and for evaluation purposes.

Features

Examples

Limitations

SharkSSL-Lite includes a limited set of ciphers. To use SharkSSL-Lite, the peer side must support Elliptic Curve Cryptography (ECC) and you must use ECC certificates. The peer side must also support the new ChaCha20/Poly1305 cipher combination.

ChaCha20 and Poly1305 for TLS is published RFC 7905. The development of this new cipher was a response to many attacks discovered against other widely used TLS cipher suites. ChaCha20 is the cipher and Poly1305 is an authenticated encryption mode.

SharkSSL-Lite occupies less than 20kB, while maintaining full x.509 authentication. The ChaCha20/Poly1305 cipher software implementation is equally as fast as many hardware accelerated AES engines.

Creating ECC Certificates for SharkSSL-Lite

The following video shows how to create an Elliptic Curve Cryptography (ECC) certificate for a server, how to install the certificate in the server, and how to make the mbed clients connecting to the server trust this certificate. The server in this video is installed on a private/personal computer on a private network for test purposes. The video was produced for the embedded.com article How to run your own secure IoT cloud server.

inc/SharkSSL.h

Committer:
wini
Date:
2016-05-23
Revision:
1:d5e0e1dcf0d6
Parent:
0:e0adec41ad6b

File content as of revision 1:d5e0e1dcf0d6:

/*
 *     ____             _________                __                _
 *    / __ \___  ____ _/ /_  __(_)___ ___  ___  / /   ____  ____ _(_)____
 *   / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ /   / __ \/ __ `/ / ___/
 *  / _, _/  __/ /_/ / / / / / / / / / / /  __/ /___/ /_/ / /_/ / / /__
 * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/
 *                                                       /____/
 *
 *                 SharkSSL Embedded SSL/TLS Stack
 ****************************************************************************
 *   PROGRAM MODULE
 *
 *   $Id: SharkSSL.h 3863 2016-03-19 02:15:11Z wini $
 *
 *   COPYRIGHT:  Real Time Logic LLC, 2010 - 2013
 *
 *   This software is copyrighted by and is the sole property of Real
 *   Time Logic LLC.  All rights, title, ownership, or other interests in
 *   the software remain the property of Real Time Logic LLC.  This
 *   software may only be used in accordance with the terms and
 *   conditions stipulated in the corresponding license agreement under
 *   which the software has been supplied.  Any unauthorized use,
 *   duplication, transmission, distribution, or disclosure of this
 *   software is expressly forbidden.
 *
 *   This Copyright notice may not be removed or modified without prior
 *   written consent of Real Time Logic LLC.
 *
 *   Real Time Logic LLC. reserves the right to modify this software
 *   without notice.
 *
 *               http://www.realtimelogic.com
 *               http://www.sharkssl.com
 ****************************************************************************
 *
 */
#ifndef _SharkSsl_h
#define _SharkSsl_h

#include "TargConfig.h"      /* platform dependencies  */
#include "SharkSSL_cfg.h"    /* SharkSSL configuration */
#ifdef __cplusplus
#include <stddef.h>          /* size_t for new, delete */
#endif

#ifndef SHARKSSL_API
#define SHARKSSL_API
#else  /* Barracuda */
#define SHARKSSL_BA 1
#include <ThreadLib.h>
#include <BaServerLib.h>
#endif

#include "SharkSslCrypto.h"  /* Crypto API */

/** \defgroup ECDSA ECDSA sign/verify functions
\ingroup RayCryptoApi

See [Signing and Verifying Binaries](@ref signing) for an example
of how to use the ECDSA ECDSA sign/verify functions.

*/




/** \addtogroup SharkSslAlert
@{

Alert messages are generated by SharkSSL or the peer side on errors.

Alert messages are one of: fatal or warning. A fatal error means that
the connection must be closed.
*/

/** SSL/TLS warning message */
#define SHARKSSL_ALERT_LEVEL_WARNING               1

/** Fatal error message. Connection must be closed. */
#define SHARKSSL_ALERT_LEVEL_FATAL                 2

/** \defgroup SharkSslAlertMsg SSL/TLS Alert Messages
\ingroup SharkSslAlert
@{

\brief Alert messages returned by function #SharkSslCon_getAlertDescription

Alert messages are generated by SharkSSL when processing the incoming
data fails. Alert messages can also be received from the peer side,
when the peer fails to process the data.
*/

/** SHARKSSL_ALERT_CLOSE_NOTIFY */
#define SHARKSSL_ALERT_CLOSE_NOTIFY                0
/** SHARKSSL_ALERT_UNEXPECTED_MESSAGE */
#define SHARKSSL_ALERT_UNEXPECTED_MESSAGE          10
/** SHARKSSL_ALERT_BAD_RECORD_MAC */
#define SHARKSSL_ALERT_BAD_RECORD_MAC              20
/** SHARKSSL_ALERT_DECRYPTION_FAILED */
#define SHARKSSL_ALERT_DECRYPTION_FAILED           21
/** SHARKSSL_ALERT_RECORD_OVERFLOW */
#define SHARKSSL_ALERT_RECORD_OVERFLOW             22
/** SHARKSSL_ALERT_DECOMPRESSION_FAILURE */
#define SHARKSSL_ALERT_DECOMPRESSION_FAILURE       30
/** SHARKSSL_ALERT_HANDSHAKE_FAILURE */
#define SHARKSSL_ALERT_HANDSHAKE_FAILURE           40
/** SHARKSSL_ALERT_NO_CERTIFICATE */
#define SHARKSSL_ALERT_NO_CERTIFICATE              41  /* SSL 3.0 only */
/** SHARKSSL_ALERT_BAD_CERTIFICATE */
#define SHARKSSL_ALERT_BAD_CERTIFICATE             42
/** SHARKSSL_ALERT_UNSUPPORTED_CERTIFICATE */
#define SHARKSSL_ALERT_UNSUPPORTED_CERTIFICATE     43
/** SHARKSSL_ALERT_CERTIFICATE_REVOKED */
#define SHARKSSL_ALERT_CERTIFICATE_REVOKED         44
/** SHARKSSL_ALERT_CERTIFICATE_EXPIRED */
#define SHARKSSL_ALERT_CERTIFICATE_EXPIRED         45
/** SHARKSSL_ALERT_CERTIFICATE_UNKNOWN */
#define SHARKSSL_ALERT_CERTIFICATE_UNKNOWN         46
/** SHARKSSL_ALERT_ILLEGAL_PARAMETER */
#define SHARKSSL_ALERT_ILLEGAL_PARAMETER           47
/** SHARKSSL_ALERT_UNKNOWN_CA */
#define SHARKSSL_ALERT_UNKNOWN_CA                  48
/** SHARKSSL_ALERT_ACCESS_DENIED */
#define SHARKSSL_ALERT_ACCESS_DENIED               49
/** SHARKSSL_ALERT_DECODE_ERROR */
#define SHARKSSL_ALERT_DECODE_ERROR                50
/** SHARKSSL_ALERT_DECRYPT_ERROR */
#define SHARKSSL_ALERT_DECRYPT_ERROR               51
/** SHARKSSL_ALERT_EXPORT_RESTRICTION */
#define SHARKSSL_ALERT_EXPORT_RESTRICTION          60
/** SHARKSSL_ALERT_PROTOCOL_VERSION */
#define SHARKSSL_ALERT_PROTOCOL_VERSION            70
/** SHARKSSL_ALERT_INSUFFICIENT_SECURITY */
#define SHARKSSL_ALERT_INSUFFICIENT_SECURITY       71
/** SHARKSSL_ALERT_INTERNAL_ERROR */
#define SHARKSSL_ALERT_INTERNAL_ERROR              80
/** SHARKSSL_ALERT_USER_CANCELED */
#define SHARKSSL_ALERT_USER_CANCELED               90
/** SHARKSSL_ALERT_NO_RENEGOTIATION */
#define SHARKSSL_ALERT_NO_RENEGOTIATION            100
/** SHARKSSL_ALERT_UNKNOWN_PSK_IDENTITY */
#define SHARKSSL_ALERT_UNKNOWN_PSK_IDENTITY        115

/** @} */ /* end group SharkSslAlertMsg */ 
/** @} */ /* end group SharkSslAlert */ 


/** \defgroup SharkSslCiphers Supported Ciphersuites
\ingroup SharkSslInfoAndCodes
@{

 \brief Supported Ciphersuites and values returned by
SharkSslCon_getCiphersuite.
*/

/** TLS_NULL_WITH_NULL_NULL */
#define TLS_NULL_WITH_NULL_NULL                       0x0000
/** TLS_RSA_WITH_NULL_MD5 */
#define TLS_RSA_WITH_NULL_MD5                         0x0001
/** TLS_RSA_WITH_NULL_SHA */
#define TLS_RSA_WITH_NULL_SHA                         0x0002
/** TLS_RSA_WITH_RC4_128_MD5 */
#define TLS_RSA_WITH_RC4_128_MD5                      0x0004
/** TLS_RSA_WITH_RC4_128_SHA */
#define TLS_RSA_WITH_RC4_128_SHA                      0x0005
/** TLS_RSA_WITH_DES_CBC_SHA */
#define TLS_RSA_WITH_DES_CBC_SHA                      0x0009
/** TLS_RSA_WITH_3DES_EDE_CBC_SHA */
#define TLS_RSA_WITH_3DES_EDE_CBC_SHA                 0x000A
/** TLS_DHE_RSA_WITH_DES_CBC_SHA */
#define TLS_DHE_RSA_WITH_DES_CBC_SHA                  0x0015
/** TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA */
#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA             0x0016
/** TLS_RSA_WITH_AES_128_CBC_SHA */
#define TLS_RSA_WITH_AES_128_CBC_SHA                  0x002F
/** TLS_DHE_RSA_WITH_AES_128_CBC_SHA */
#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA              0x0033
/** TLS_RSA_WITH_AES_256_CBC_SHA */
#define TLS_RSA_WITH_AES_256_CBC_SHA                  0x0035
/** TLS_DHE_RSA_WITH_AES_256_CBC_SHA */
#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA              0x0039
/** TLS_RSA_WITH_NULL_SHA256 */
#define TLS_RSA_WITH_NULL_SHA256                      0x003B
/** TLS_RSA_WITH_AES_128_CBC_SHA256 */
#define TLS_RSA_WITH_AES_128_CBC_SHA256               0x003C
/** TLS_RSA_WITH_AES_256_CBC_SHA256 */
#define TLS_RSA_WITH_AES_256_CBC_SHA256               0x003D
/** TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 */
#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256           0x0067
/** TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */
#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256           0x006B
/** TLS_PSK_WITH_RC4_128_SHA */
#define TLS_PSK_WITH_RC4_128_SHA                      0x008A
/** TLS_PSK_WITH_3DES_EDE_CBC_SHA */
#define TLS_PSK_WITH_3DES_EDE_CBC_SHA                 0x008B
/** TLS_PSK_WITH_AES_128_CBC_SHA */
#define TLS_PSK_WITH_AES_128_CBC_SHA                  0x008C
/** TLS_PSK_WITH_AES_256_CBC_SHA */
#define TLS_PSK_WITH_AES_256_CBC_SHA                  0x008D
/** TLS_RSA_WITH_AES_128_GCM_SHA256 */
#define TLS_RSA_WITH_AES_128_GCM_SHA256               0x009C
/** TLS_RSA_WITH_AES_256_GCM_SHA384 */
#define TLS_RSA_WITH_AES_256_GCM_SHA384               0x009D
/** TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 */
#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256           0x009E
/** TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */
#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384           0x009F
/** TLS_PSK_WITH_AES_128_GCM_SHA256 */
#define TLS_PSK_WITH_AES_128_GCM_SHA256               0x00A8
/** TLS_PSK_WITH_AES_256_GCM_SHA384 */
#define TLS_PSK_WITH_AES_256_GCM_SHA384               0x00A9
/** TLS_PSK_WITH_AES_128_CBC_SHA256 */
#define TLS_PSK_WITH_AES_128_CBC_SHA256               0x00AE
/** TLS_PSK_WITH_AES_256_CBC_SHA384 */
#define TLS_PSK_WITH_AES_256_CBC_SHA384               0x00AF
/** TLS_ECDH_ECDSA_WITH_NULL_SHA */
#define TLS_ECDH_ECDSA_WITH_NULL_SHA                  0xC001
/** TLS_ECDH_ECDSA_WITH_RC4_128_SHA */
#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA               0xC002
/** TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA */
#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA          0xC003
/** TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA */
#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA           0xC004
/** TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA */
#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA           0xC005
/** TLS_ECDHE_ECDSA_WITH_NULL_SHA */
#define TLS_ECDHE_ECDSA_WITH_NULL_SHA                 0xC006
/** TLS_ECDHE_ECDSA_WITH_RC4_128_SHA */
#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA              0xC007
/** TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA */
#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA         0xC008
/** TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA */
#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA          0xC009
/** TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA */
#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA          0xC00A
/** TLS_ECDH_RSA_WITH_NULL_SHA */
#define TLS_ECDH_RSA_WITH_NULL_SHA                    0xC00B
/** TLS_ECDH_RSA_WITH_RC4_128_SHA */
#define TLS_ECDH_RSA_WITH_RC4_128_SHA                 0xC00C
/** TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA */
#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA            0xC00D
/** TLS_ECDH_RSA_WITH_AES_128_CBC_SHA */
#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA             0xC00E
/** TLS_ECDH_RSA_WITH_AES_256_CBC_SHA */
#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA             0xC00F
/** TLS_ECDHE_RSA_WITH_NULL_SHA */
#define TLS_ECDHE_RSA_WITH_NULL_SHA                   0xC010
/** TLS_ECDHE_RSA_WITH_RC4_128_SHA */
#define TLS_ECDHE_RSA_WITH_RC4_128_SHA                0xC011
/** TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA */
#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA           0xC012
/** TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA */
#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA            0xC013
/** TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA */
#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA            0xC014
/** TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 */
#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256       0xC023
/** TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 */
#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384       0xC024
/** TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 */
#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256        0xC025
/** TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 */
#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384        0xC026
/** TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 */
#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256         0xC027
/** TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 */
#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384         0xC028
/** TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 */
#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256          0xC029
/** TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 */
#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384          0xC02A
/** TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 */
#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256       0xC02B
/** TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 */
#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384       0xC02C
/** TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 */
#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256        0xC02D
/** TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 */
#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384        0xC02E
/** TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 */
#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256         0xC02F
/** TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 */
#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384         0xC030
/** TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 */
#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256          0xC031
/** TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 */
#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384          0xC032
/** TLS_RSA_WITH_AES_128_CCM */
#define TLS_RSA_WITH_AES_128_CCM                      0xC09C
/** TLS_RSA_WITH_AES_256_CCM */
#define TLS_RSA_WITH_AES_256_CCM                      0xC09D
/** TLS_DHE_RSA_WITH_AES_128_CCM */
#define TLS_DHE_RSA_WITH_AES_128_CCM                  0xC09E
/** TLS_DHE_RSA_WITH_AES_256_CCM */
#define TLS_DHE_RSA_WITH_AES_256_CCM                  0xC09F
/** TLS_RSA_WITH_AES_128_CCM_8 */
#define TLS_RSA_WITH_AES_128_CCM_8                    0xC0A0
/** TLS_RSA_WITH_AES_256_CCM_8 */
#define TLS_RSA_WITH_AES_256_CCM_8                    0xC0A1
/** TLS_DHE_RSA_WITH_AES_128_CCM_8 */
#define TLS_DHE_RSA_WITH_AES_128_CCM_8                0xC0A2
/** TLS_DHE_RSA_WITH_AES_256_CCM_8 */
#define TLS_DHE_RSA_WITH_AES_256_CCM_8                0xC0A3
/** TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */
#define TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256   0xCC13
/** TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 */
#define TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCC14
/** TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 */
#define TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256     0xCC15

/** @} */ /* end group SharkSslCiphers */ 


/** \defgroup SharkSslProtocol SSL and TLS protocol version
\ingroup SharkSslInfoAndCodes
@{
 \brief Return values from function #SharkSslCon_getProtocol.
*/

/** SHARKSSL_PROTOCOL_UNKNOWN */
#define SHARKSSL_PROTOCOL_UNKNOWN                  0x00
/** SHARKSSL_PROTOCOL_SSL_3_0 */
#define SHARKSSL_PROTOCOL_SSL_3_0                  0x30
/** SHARKSSL_PROTOCOL_TLS_1_0 */
#define SHARKSSL_PROTOCOL_TLS_1_0                  0x31
/** SHARKSSL_PROTOCOL_TLS_1_1 */
#define SHARKSSL_PROTOCOL_TLS_1_1                  0x32 
/** SHARKSSL_PROTOCOL_TLS_1_2 */
#define SHARKSSL_PROTOCOL_TLS_1_2                  0x33

/** @} */ /* end group SharkSslProtocol */ 


#if (SHARKSSL_ENABLE_RSA || SHARKSSL_ENABLE_ECDSA)
#ifndef BA_API  /* standalone SharkSSL */
#define BA_API SHARKSSL_API
#ifdef _SHARKSSL_C_
#define SingleListCode 1
#endif
#endif
#include "SingleList.h"
#endif


#if SHARKSSL_ENABLE_SESSION_CACHE || SHARKSSL_NOPACK

/** @addtogroup SharkSslSessionApi
@{
*/

/** SharkSslSession is an opaque handle returned by function
    #SharkSslCon_acquireSession.
 */
typedef struct SharkSslSession SharkSslSession;

/** @} */ /* end group SharkSslSessionApi */ 

#ifndef _DOXYGEN
typedef struct SharkSslSessionCache
{
   SharkSslSession *cache;
   ThreadMutexBase  cacheMutex;
   U16 cacheSize;
} SharkSslSessionCache;
#endif
#endif


/** \addtogroup SharkSslInfoAndCodes
@{
*/

/** Select one of client or server mode when creating a #SharkSsl
    object.

    __Note:__ A SharkSsl instance in server mode requires that you
    install at a minimum one certificate by calling function
    #SharkSsl_addCertificate.
*/
typedef enum
{
   SharkSsl_Unspecified,  /*!< Invalid value */
   SharkSsl_Server,       /*!< Select SSL server mode */
   SharkSsl_Client        /*!< Select SSL client mode */
} SharkSsl_Role;

/** @} */ /* end group SharkSslInfoAndCodes */


#if (SHARKSSL_ENABLE_RSA || SHARKSSL_ENABLE_ECDSA)
/** \addtogroup SharkSslInfoAndCodes
@{
*/

/** The SharkSSL Certificate is in a binary format optimized for speed
    and size. The certificate can be created by calling #sharkssl_PEM
    or by using the command line tool
    [SharkSslParseCert](\ref SharkSslParseCert)
 */
typedef const U8 *SharkSslCert;

#if SHARKSSL_ENABLE_CA_LIST
/** The SharkSSL Certificate Authority (CA) List is in a binary format
    optimized for speed and size. The list can be created by calling
    #SharkSslCertStore_assemble or by using the command line tool
    [SharkSSLParseCAList](\ref SharkSSLParseCAList).
 */
typedef const U8 *SharkSslCAList;
#endif

/** @} */ /* end group SharkSslInfoAndCodes */
#endif

#if SHARKSSL_ENABLE_PSK || SHARKSSL_NOPACK
/** \addtogroup SharkSslInfoAndCodes
@{
*/

/** The SharkSSL PSK table is in an optimized binary format. 
    The table can be created by using the command line tool
    [SharkSslParsePSKTable](\ref SharkSSLParsePSKTable).
 */
typedef const U8 *SharkSslPSKTable;

/** @} */ /* end group SharkSslInfoAndCodes */
#endif

#ifndef _DOXYGEN
struct SharkSsl;
#endif


/* Non documented API used by SharkSslSCMgr when used indirectly by
   Lua code in the Barracuda Application Server. The code manages
   automatic destruction of SharkSslSCMgr.
 */
#ifndef _DOXYGEN
struct SharkSslIntf;
typedef void (*SharkSslIntf_Terminate)(struct SharkSslIntf* o,
                                       struct SharkSsl* ssl); 
typedef struct SharkSslIntf
{
   SharkSslIntf_Terminate terminate;
} SharkSslIntf;
#define SharkSslIntf_constructor(o,terminateFunc) (o)->terminate=terminateFunc
#endif


/** \addtogroup SharkSslInfoAndCodes
@{
*/

/**  SharkSslCon is an opaque handle returned by function
     #SharkSsl_createCon. 

     The lifetime of a SharkSslCon object is as follows:

     - Create a network connection and create a SharkSslCon object by
       calling #SharkSsl_createCon

     - Use the SharkSslCon functions to encode and decode data sent
       and received over the network. See #SharkSslCon_encrypt and
       #SharkSslCon_decrypt for more information.

     - When you are ready to close the connection: close the network
       connection and call function #SharkSsl_terminateCon

   \sa  SharkSsl
*/
typedef struct SharkSslCon SharkSslCon;


/** A SharkSsl object is the coordinator for managing #SharkSslCon
    objects (See #SharkSsl_constructor for details).
*/
typedef struct
SharkSsl
{
#ifdef __cplusplus
   void *operator new(size_t s) { return ::baMalloc(s); }
   void operator delete(void* d) { if(d) ::baFree(d); }
   void *operator new(size_t, void *place) { return place; }
   void operator delete(void*, void *) { }

   SharkSsl() {};

   SharkSsl(SharkSsl_Role role,
            U16 cacheSize         = 0,
            U16 inBufStartSize    = 4096,
            U16 outBufSize        = 4096
            );

   ~SharkSsl();
   SharkSslCon *createCon(void);
   U8 setCAList(SharkSslCAList caList);
   U8 addCertificate(SharkSslCert cert);
   void terminateCon(SharkSslCon *sslCon);
#endif
   #if (SHARKSSL_SSL_SERVER_CODE && SHARKSSL_SSL_CLIENT_CODE) || SHARKSSL_NOPACK
   SharkSsl_Role role;
   #endif
   U16 outBufSize;
   U16 inBufStartSize;
   U16 nCon;
   #if (SHARKSSL_ENABLE_RSA || (SHARKSSL_ENABLE_ECDSA))  || SHARKSSL_NOPACK
   SingleList certList;
   #if SHARKSSL_ENABLE_CA_LIST  || SHARKSSL_NOPACK
   SharkSslCAList caList;
   #endif
   #endif
   #if SHARKSSL_ENABLE_PSK  || SHARKSSL_NOPACK
   SharkSslPSKTable tablePSK;
   #endif
   #if SHARKSSL_ENABLE_SESSION_CACHE  || SHARKSSL_NOPACK
   SharkSslSessionCache sessionCache;
   /* Reserved for use with one SharkSslSCMgr object  */
   SharkSslIntf* intf;
   #endif
} SharkSsl;

/** @} */ /* end group SharkSslInfoAndCodes */

/** @addtogroup SharkSslCoreApi
@{
*/

/** The #SharkSslCon_decrypt and #SharkSslCon_encrypt return values.
 */
typedef enum
{
   /** Indicates general errors, including configuration errors.
    */
   SharkSslCon_Error = 1, 

   /** The memory pool is too small.
    */
   SharkSslCon_AllocationError,

   /** Returned when a block of received data has been successfully decrypted.

       __selib.c code snippet:__
       \dontinclude selib.c
       \skipline case SharkSslCon_Decrypted:
       \until return

       \sa SharkSslCon_getDecData
    */
   SharkSslCon_Decrypted,

   /** Returned when an SSL/TLS handshake message has been received or
       is to be sent. During this phase, one must call
       #SharkSslCon_getHandshakeData and
       #SharkSslCon_getHandshakeDataLen, and send the handshake data to
       the peer side. 

       __selib.c code snippet:__
       \dontinclude selib.c
       \skipline case SharkSslCon_Handshake:
       \until xprintf(("handshake complete"));
    */
   SharkSslCon_Handshake,

   /** Returned when SharkSSL holds an incomplete SSL/TLS record or
       when the connection is initially established and the readLen
       parameter is zero. 

       __selib.c code snippet:__
       \dontinclude selib.c
       \skipline case SharkSslCon_NeedMoreData:
       \until decrypt next record

       \sa #SharkSslCon_getBuf and #SharkSslCon_getBufLen
    */
   SharkSslCon_NeedMoreData,

   /** Returned when an [SSL/TLS alert message](@ref SharkSslAlertMsg)
       must be sent to the peer side. The error code, which must be
       sent to the peer, indicates that SharkSSL was unable to decode
       the data sent from the peer.
       
       __selib.c code snippet:__
       \dontinclude selib.c
       \skipline case SharkSslCon_AlertSend:
       \until return

       \sa #SharkSslCon_getAlertData and #SharkSslCon_getAlertDataLen
   */
   SharkSslCon_AlertSend,

   /** SharkSSL received an [SSL/TLS alert message](@ref SharkSslAlertMsg)
       from the peer, which means that the peer either failed to
       decode the message from SharkSSL or the peer entered an
       exception state.

       \sa SharkSslCon_getAlertLevel and SharkSslCon_getAlertDescription
    */
   SharkSslCon_AlertRecv,

   /** SharkSSL has successfully decrypted a chunk of data. The data
       is available in the SharkSSL receive buffer, which is returned
       by function #SharkSslCon_getEncData. The length is returned by
       function #SharkSslCon_getEncDataLen.

       __selib.c code snippet:__
       \dontinclude selib.c
       \skipline case SharkSslCon_Encrypted:
       \until return maxLen
   */
   SharkSslCon_Encrypted,

   /** An error condition returned by function #SharkSslCon_encrypt if
       the SSL handshake is not completed. You cannot send encrypted
       data before completing the handshake phase.
    */
   SharkSslCon_HandshakeNotComplete,

   /** Returned by function #SharkSslCon_encrypt if
       #SHARKSSL_ENABLE_CLONE_CERTINFO is disabled and when a complete
       certificate is received from the peer during the SSL handshake
       phase. Fixme more...
   */
   SharkSslCon_Certificate,

   /** Unrecognized format of a provided certificate.
    */
   SharkSslCon_CertificateError

} SharkSslCon_RetVal;

/** @} */ /* end group SharkSslCoreApi */

#if (SHARKSSL_ENABLE_RSA || SHARKSSL_ENABLE_ECDSA)

/** \defgroup SharkSslCertInfo Peer's certificate information
\ingroup SharkSslInfoAndCodes

\brief Certificate information returned by #SharkSslCon_getCertInfo

@{
*/

/** Certificate KeyUsage and ExtendedKeyUsage flags and relative
    pseudofunctions
 */
#if SHARKSSL_ENABLE_CERT_KEYUSAGE
#define SHARKSSL_CERT_KEYUSAGE_DIGITALSIGNATURE     0x00000001
#define SHARKSSL_CERT_KEYUSAGE_NONREPUDIATION       0x00000002
#define SHARKSSL_CERT_KEYUSAGE_KEYENCIPHERMENT      0x00000004
#define SHARKSSL_CERT_KEYUSAGE_DATAENCIPHERMENT     0x00000008
#define SHARKSSL_CERT_KEYUSAGE_KEYAGREEMENT         0x00000010
#define SHARKSSL_CERT_KEYUSAGE_KEYCERTSIGN          0x00000020
#define SHARKSSL_CERT_KEYUSAGE_CRLSIGN              0x00000040
#define SHARKSSL_CERT_KEYUSAGE_ENCIPHERONLY         0x00000080 
#define SHARKSSL_CERT_KEYUSAGE_DECIPHERONLY         0x00000100
#define SHARKSSL_CERT_KEYUSAGE_PRESENT              0x00000200
#define SHARKSSL_CERT_KEYUSAGE_CRITICAL             0x00000400

#define SHARKSSL_CERT_KEYPURPOSE_SERVERAUTH         0x00010000
#define SHARKSSL_CERT_KEYPURPOSE_CLIENTAUTH         0x00020000
#define SHARKSSL_CERT_KEYPURPOSE_CODESIGNING        0x00040000
#define SHARKSSL_CERT_KEYPURPOSE_EMAILPROTECTION    0x00080000
#define SHARKSSL_CERT_KEYPURPOSE_TIMESTAMPING       0x00100000
#define SHARKSSL_CERT_KEYPURPOSE_OCSPSIGNING        0x00200000

#define SharkSslCertInfo_KeyFlagSet(o,f)            ((o)->keyUsagePurposes & f)

/** The following pseudo-functions return a non-zero value
    if the corresponding flag is set 
 */
#define SharkSslCertInfo_isKeyUsagePresent(o)       SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYUSAGE_PRESENT)
#define SharkSslCertInfo_isKeyUsageCritical(o)      SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYUSAGE_CRITICAL)
#define SharkSslCertInfo_KU_digitalSignature(o)     SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYUSAGE_DIGITALSIGNATURE)
#define SharkSslCertInfo_KU_nonRepudiation(o)       SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYUSAGE_NONREPUDIATION)
#define SharkSslCertInfo_KU_keyEncipherment(o)      SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYUSAGE_KEYENCIPHERMENT)
#define SharkSslCertInfo_KU_dataEncipherment(o)     SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYUSAGE_DATAENCIPHERMENT)
#define SharkSslCertInfo_KU_keyAgreement(o)         SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYUSAGE_KEYAGREEMENT)
#define SharkSslCertInfo_KU_keyCertSign(o)          SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYUSAGE_KEYCERTSIGN)
#define SharkSslCertInfo_KU_cRLSign(o)              SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYUSAGE_CRLSIGN)
#define SharkSslCertInfo_KU_encipherOnly(o)         SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYUSAGE_ENCIPHERONLY)
#define SharkSslCertInfo_KU_decipherOnly(o)         SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYUSAGE_DECIPHERONLY)

#define SharkSslCertInfo_kp_serverAuth(o)           SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYPURPOSE_SERVERAUTH)
#define SharkSslCertInfo_kp_clientAuth(o)           SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYPURPOSE_CLIENTAUTH)
#define SharkSslCertInfo_kp_codeSigning(o)          SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYPURPOSE_CODESIGNING)
#define SharkSslCertInfo_kp_emailProtection(o)      SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYPURPOSE_EMAILPROTECTION)
#define SharkSslCertInfo_kp_timeStamping(o)         SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYPURPOSE_TIMESTAMPING)
#define SharkSslCertInfo_kp_OCSPSigning(o)          SharkSslCertInfo_KeyFlagSet(o, SHARKSSL_CERT_KEYPURPOSE_OCSPSIGNING)
#endif


/** Certificate Distinguished Name

    Example from certcheck.c:

    \dontinclude certcheck.c
    \skip  Begin Cert Info
    \until End Cert Info

    \sa SharkSslCertInfo

 */
typedef struct SharkSslCertDN
{
   const U8 *countryName; /**< ISO3166 country code */
   const U8 *province;  /**< State or Province */
   const U8 *locality; /**< The city or town name */ 
   const U8 *organization; /**< Organization Name (company or department) */
   const U8 *unit; /**< Organizational Unit (OU: department or organization unit) */
   /** Common Name is the Host + Domain Name (example:
       www.mycompany.com, where www is host and mycompany.com is Domain
       Name) */
   const U8 *commonName;
   const U8 *emailAddress;

   U8 countryNameLen;   /** length in bytes of the field "country" */
   U8 provinceLen;      /** length in bytes of the field "province" */
   U8 localityLen;      /** length in bytes of the field "locality" */
   U8 organizationLen;  /** length in bytes of the field "organization" */
   U8 unitLen;          /** length in bytes of the field "unit" */
   U8 commonNameLen;    /** length in bytes of the field "common name" */
   U8 emailAddressLen;    /** length in bytes of the field "emailAddress" */
} SharkSslCertDN;

#define SharkSslCertDN_constructor(o) memset(o,0,sizeof(SharkSslCertDN))

#define SharkSslCertDN_setCountryName(o, countryNameMA) \
   (o)->countryName=(const U8*)countryNameMA,(o)->countryNameLen=(U8)strlen(countryNameMA)
#define SharkSslCertDN_setProvince(o, provinceMA) \
   (o)->province=(const U8*)provinceMA,(o)->provinceLen=(U8)strlen(provinceMA)
#define SharkSslCertDN_setLocality(o, localityMA) \
   (o)->locality=(const U8*)localityMA,(o)->localityLen=(U8)strlen(localityMA)
#define SharkSslCertDN_setOrganization(o, organizationMA) \
   (o)->organization=(const U8*)organizationMA,(o)->organizationLen=(U8)strlen(organizationMA)
#define SharkSslCertDN_setUnit(o, unitMA) \
   (o)->unit=(const U8*)unitMA,(o)->unitLen=(U8)strlen(unitMA)
#define SharkSslCertDN_setCommonName(o, commonNameMA) \
   (o)->commonName=(const U8*)commonNameMA,(o)->commonNameLen=(U8)strlen(commonNameMA)


/** The peer's certificate information returned by #SharkSslCon_getCertInfo.
    \sa SharkSslCertDN
 */
typedef struct SharkSslCertInfo
{
     /** Length of 'sn' (serial number) */
   U16 snLen;

   /**  Certificate version is offset at 0 so add +1 for actual
        version number.
   */
   U8  version; 

   /** The Certificate Authority flag (CA) is set to one if the
       certificate is a CA i.e. a root certificate.
    */
   U8 CAflag;

   /** Binary serial number. The length is provided in 'snLen'
    */
   U8 *sn;

   /** Certificate is valid from date (in UTCTime format: YYMMDDHHMMSSZ)
    */
   U8 *timeFrom;

   /** Certificate expiration date (in UTCTime format: YYMMDDHHMMSSZ)
    */
   U8 *timeTo;

   /** The entity who has signed and issued the certificate (<a 
       href="http://tools.ietf.org/html/rfc2459#section-4.1.2.4"
       >RFC2459 4.1.2.4</a>)
    */
   SharkSslCertDN issuer;

   /** The entity associated with the public key (<a 
       href="http://tools.ietf.org/html/rfc2459#section-4.1.2.6"
       >RFC2459 4.1.2.6</a>).
    */
   SharkSslCertDN subject;

   /** Subject Alternative DNS Names, if set, is a pointer to a list
       of alternative names. Each entry in the list is prefixed with
       a 1-byte length, followed by a string of 'length' bytes; 
       the list ends with a zero length. 
       The following example is from certcheck.c:

       \dontinclude certcheck.c
       \skipline U8 *tp
       \until xprintf(("\n"))
    */
   U8 *subjectAltDNSNames;

   #if SHARKSSL_ENABLE_CERT_KEYUSAGE
   /** KeyUsage & ExtendedKeyUsage (key purposes) flags. 
       Verify that the KeyUsage extension is present through the 
         SharkSslCertInfo_isKeyUsagePresent(o) pseudo-function, 
       then verify all the flags through the pseudo-functions:
         SharkSslCertInfo_KU_digitalSignature(o)
         SharkSslCertInfo_KU_nonRepudiation(o)
         SharkSslCertInfo_KU_keyEncipherment(o)
         SharkSslCertInfo_KU_dataEncipherment(o)
         SharkSslCertInfo_KU_keyAgreement(o)
         SharkSslCertInfo_KU_keyCertSign(o)
         SharkSslCertInfo_KU_cRLSign(o)
         SharkSslCertInfo_KU_encipherOnly(o)
         SharkSslCertInfo_KU_decipherOnly(o)

       Verify the ExtendedKeyUsage purposes through the following:
         SharkSslCertInfo_kp_serverAuth(o)
         SharkSslCertInfo_kp_clientAuth(o)
         SharkSslCertInfo_kp_codeSigning(o)
         SharkSslCertInfo_kp_emailProtection(o)
         SharkSslCertInfo_kp_timeStamping(o)
         SharkSslCertInfo_kp_OCSPSigning(o)
    */ 
   U32 keyUsagePurposes; 
   #endif

   /** Pointer to parent node when the SharkSslCertInfo object is part of
       a certificate chain. You walk up the chain until you reach the root.
   */
   struct SharkSslCertInfo *parent;
} SharkSslCertInfo;

/** @} */ /* end group SharkSslCertInfo */ 
#endif

/** @addtogroup SharkSslApi
@{
*/


#ifdef __cplusplus
extern "C" {
#endif

/** A SharkSsl object is the coordinator for managing SharkSslCon
    objects.

    You must at a minimum create one SharkSsl object. A more advanced
    configuration may include several SharkSsl objects. For example, a
    system that includes both a client and server SSL stack must
    create and initialize two SharkSsl objects.

    \param o Uninitialized data of size sizeof(SharkSsl).

    \param role Select client or server SSL mode. See #SharkSsl_Role
    for details.

    \param cacheSize The session resumption cache size. Setting this
    to zero disables the cache management code. See
    [SSL Session Management](@ref SharkSslSessionApi) for details.

    \param inBufStartSize
    \param outBufSize

    parameter must be provided if you plan on using function
    #SharkSslCon_trustedCA or #SharkSslCon_trusted. See
    #SharkSslCAList for details.

    \sa #SharkSsl_addCertificate, #SharkSsl_setCAList,
    SharkSsl_createCon, and SharkSsl_terminateCon.
 */
SHARKSSL_API void  SharkSsl_constructor(
                      SharkSsl *o,
                      SharkSsl_Role role,
                      U16 cacheSize,
                      U16 inBufStartSize,
                      U16 outBufSize
                      );

/** Close the SharkSsl object. Closing a SharkSsl object is not
    common in embedded devices. You would normally keep the SharkSsl
    object for the lifetime of the application. You must make sure
    all #SharkSslCon objects are terminated by calling
    #SharkSslCon_terminate for each active connection prior to calling
    the SharkSsl_destructor.
 */
SHARKSSL_API void  SharkSsl_destructor(SharkSsl *o);


/** Create a #SharkSslCon object. You must create one SharkSslCon
    object for each active network connection that requires encryption.

    The following code snippet is from the
    [example programs](\ref SharkExamples).
    \code
int rc;
SharkSslCon* scon;
if( (rc=se_connect(&sock, "realtimelogic.com", 443)) == 0) // open socket
{
   if( (scon = SharkSsl_createCon(&sharkSsl)) != NULL)
   {
      // success
   \endcode

    \return a SharkSslCon object or NULL if memory is exhausted.

    \sa SharkSsl_terminateCon and SharkSslCon_terminate
 */
SharkSslCon *SharkSsl_createCon(SharkSsl *o);


/** Terminate a SharkSslCon object created by function SharkSsl_createCon.

    \param o the SharkSsl object. Setting this parameter to NULL is
    the same as calling macro #SharkSslCon_terminate.

    \param con the SharkSslCon object to reclaim.

    Code snippet from the example code: sessioncache.c 

       \dontinclude sessioncache.c
       \skipline Release resources
       \until se_close

 */
void SharkSsl_terminateCon(const SharkSsl *o, SharkSslCon* con);


#if SHARKSSL_ENABLE_SESSION_CACHE

/** Returns the SharkSsl session cache size.
    \sa SharkSsl_constructor (parameter cacheSize) and
    #SHARKSSL_ENABLE_SESSION_CACHE
*/
SHARKSSL_API U16   SharkSsl_getCacheSize(SharkSsl *o);

#define SharkSsl_setIntf(o, sharkSslIntf) (o)->intf=sharkSslIntf
#define SharkSsl_getIntf(o) (o)->intf

#endif


/** The SharkSslCon object must be reclaimed when you close the
 * network connection.

    \sa #SharkSsl_createCon
    \sa SharkSsl_terminateCon
 */ 
#define SharkSslCon_terminate(o) SharkSsl_terminateCon(0, o)

/** @addtogroup SharkSslCoreApi
@{
*/

/** Decrypt the received data copied into the SharkSslCon receive
    buffer (the buffer returned by #SharkSslCon_getBuf). See
    #SharkSslCon_RetVal for example code.

    The SharkSslCon_decrypt function keeps decrypt state information
    in the SharkSslCon object and the function can therefore be used
    in event driven systems.

    \param o the SharkSslCon object returned by function #SharkSsl_createCon.

    \param readLen the length of the received network data copied into
    the buffer returned by #SharkSslCon_getBuf.

    \return the decrypt state information #SharkSslCon_RetVal.

    \sa SharkSslCon_getBuf, SharkSslCon_getBufLen, SharkSslCon_encrypt
 */
SharkSslCon_RetVal SharkSslCon_decrypt(SharkSslCon *o, U16 readLen);


/** Encrypt the data provided by parameter 'buf' or encrypt data in
    the SharkSslCon send buffer. SharkSSL provides a zero copy API and
    you can optionally copy data directly to the SharkSslCon send
    buffer. The send buffer is returned by calling function
    #SharkSslCon_getEncBufPtr.

    The SharkSslCon_encrypt function keeps decrypt state information
    in the SharkSslCon object and the function can therefore be used
    in event driven systems.

    \param o the SharkSslCon object returned by function #SharkSsl_createCon.

    \param buf the data to be encrypted or NULL when encrypting data
    copied directly to the SharkSslCon send buffer i.e. when copying
    the data to the pointer returned by function
    #SharkSslCon_getEncBufPtr.

    \param maxLen is the length of 'buf' or the length of the data
    data copied directly to the SharkSslCon send buffer.

    \return the decrypt state information #SharkSslCon_RetVal.

    \sa SharkSslCon_getEncBufPtr, SharkSslCon_getEncBufSize, SharkSslCon_decrypt
 */
SharkSslCon_RetVal SharkSslCon_encrypt(SharkSslCon *o, U8 *buf, U16 maxLen);


/** Returns TRUE if the SSL handshake phase is completed. See
    state #SharkSslCon_Handshake for example code.
*/
U8 SharkSslCon_isHandshakeComplete(SharkSslCon *o);


/** This function is used in conjunction with state
    SharkSslCon_Encrypted returned by function
    #SharkSslCon_encrypt. 

    The function returns TRUE if the SharkSslCon send buffer is full
    and must be flushed out.

    The maximum size of the output buffer is set with parameter
    'outBufSize' when calling the #SharkSsl_constructor. When the
    unencrypted buffer is larger than what fits into the internal
    output buffer, SharkSSL breaks the unencrypted data into multiple
    chunks and SharkSslCon_encryptMore lets the application know when
    the buffer must be flushed.

    See #SharkSslCon_Encrypted for example code.
 */
U8  SharkSslCon_encryptMore(SharkSslCon *o);


/** This function is used in conjunction with state
    SharkSslCon_Decrypted returned by function
    #SharkSslCon_decrypt.

    The function returns TRUE if a complete SSL frame has been
    decrypted and is ready for consumption. See #SharkSslCon_Decrypted
    for example code.

 */
U8  SharkSslCon_decryptMore(SharkSslCon *o);

/** Returns a pointer to the SharkSslCon input/receive buffer. The
    pointer returned by SharkSslCon_getBuf is where you copy the
    encrypted data you receive from the network.

    Example code:
    \code
   readLen = recv(mysocket, SharkSslCon_getBuf(s),SharkSslCon_getBufLen(s), 0);
   \endcode
    \sa SharkSslCon_getBufLen and SharkSslCon_getDecData
 */
U8 *SharkSslCon_getBuf(SharkSslCon *o);


/** Returns the length of the SharkSslCon input buffer. The buffer is
    internally managed by SharkSSL and may dynamically grow as large
    as 16Kbytes. The SharkSslCon input buffer start size is set with
    parameter inBufStartSize when calling the #SharkSsl_constructor.

    Many ciphers are block based and the receiving end must read the
    complete block before it can be decrypted. The SSL/TLS
    specification enables blocks up to 16K in size. Note, the block
    will not be larger than the size of the packet sent by the peer
    side.

    \sa SharkSslCon_getBuf
 */
U16 SharkSslCon_getBufLen(SharkSslCon *o);

/** Copy decoded data to 'buf'. Provides an alternative to using the
    zero copy API and the buffer returned by #SharkSslCon_getDecData.

    \param o the SharkSslCon object returned by function #SharkSsl_createCon.
    \param buf a buffer provided by the caller
    \param maxLen the size of parameter 'buf'. SharkSSL will copy at
    most maxLen bytes to 'buf'.

    Example:
    \code
for(;;)
{
   switch (SharkSslCon_decrypt(s, (U16)readLen))
   {
      case SharkSslCon_Decrypted:
         readLen = SharkSslCon_copyDecData(s, buf, maxLen);
         // decrypted readLen bytes
         if (SharkSslCon_decryptMore(s))
         {
            if ((readLen == 0) && (maxLen > 0))
            {
               break; // zero-length record, decrypt next one
            }
         }
         return readLen;

      // other cases not shown here
    \endcode
    \sa SharkSslCon_getDecData
 */
U16 SharkSslCon_copyDecData(SharkSslCon *o, U8 *buf, U16 maxLen);


/** Get a pointer to the decoded data.

    See #SharkSslCon_Decrypted for example code.

    \param o the SharkSslCon object returned by function #SharkSsl_createCon.
    \param bufPtr is set to the beginning of the decoded data.
    \returns Number of bytes decoded.
    \sa SharkSslCon_copyDecData
 */
SHARKSSL_API U16 SharkSslCon_getDecData(SharkSslCon *o, U8 **bufPtr);


/** This function is used in conjunction with state
    SharkSslCon_Handshake returned by function
    #SharkSslCon_encrypt. 

    The function returns the handshake data that must be sent to the
    peer side, if any.

    See #SharkSslCon_Handshake for example code.

    \sa SharkSslCon_getHandshakeDataLen
 */
U8 *SharkSslCon_getHandshakeData(SharkSslCon *o);


/** This function is used in conjunction with state
    SharkSslCon_Handshake returned by function
    #SharkSslCon_decrypt.

    The function returns the length of the handshake data that must be
    sent to the peer side, if any. The function returns zero if no
    handshake data should be sent.
    
    See #SharkSslCon_Handshake for example code.

    \sa SharkSslCon_getHandshakeData
 */
U16 SharkSslCon_getHandshakeDataLen(SharkSslCon *o);


/** This function is used in conjunction with state
    SharkSslCon_Encrypted returned by function
    #SharkSslCon_encrypt.

    The function returns a pointer to the encoded data that must be
    sent to the peer side.

    \sa SharkSslCon_getEncDataLen and SharkSslCon_encryptMore
 */
U8 *SharkSslCon_getEncData(SharkSslCon *o);


/** This function is used in conjunction with state
    SharkSslCon_Encrypted returned by function
    #SharkSslCon_encrypt.

    The function returns the length of the encoded data that must be
    sent to the peer side.
   
    See #SharkSslCon_Encrypted for example code.

    \sa SharkSslCon_getEncData and SharkSslCon_encryptMore
 */
U16 SharkSslCon_getEncDataLen(SharkSslCon *o);


/** This function is used in conjunction with #SharkSslCon_encrypt
    when using the zero copy send API.

    \return a pointer to the internal SharkSslCon send buffer. 
    \sa SharkSslCon_getEncBufSize.
 */
U8 *SharkSslCon_getEncBufPtr(SharkSslCon *o);


/** Returns the length of the buffer returned by #SharkSslCon_getEncBufPtr
 */
U16 SharkSslCon_getEncBufSize(SharkSslCon *o);


/** This function is used in conjunction with state
    #SharkSslCon_AlertSend returned by function #SharkSslCon_encrypt or
    in conjunction with state #SharkSslCon_AlertRecv returned by
    function #SharkSslCon_decrypt.

    \returns #SHARKSSL_ALERT_LEVEL_WARNING or #SHARKSSL_ALERT_LEVEL_FATAL

    \sa #SharkSslCon_getAlertDescription and #SharkSslCon_getAlertData
 */
U8  SharkSslCon_getAlertLevel(SharkSslCon *o);


/** This function is used in conjunction with state
    #SharkSslCon_AlertSend returned by function #SharkSslCon_encrypt or
    in conjunction with state #SharkSslCon_AlertRecv returned by
    function #SharkSslCon_decrypt.

    returns the [SSL/TLS alert message](@ref SharkSslAlertMsg)

    \sa #SharkSslCon_getAlertLevel and #SharkSslCon_getAlertData
 */
U8  SharkSslCon_getAlertDescription(SharkSslCon *o);


/** This function is used in conjunction with state
    #SharkSslCon_AlertSend returned by function
    #SharkSslCon_encrypt.

    The function returns a pointer to the alert data that must be sent
    to the peer side.

    \sa #SharkSslCon_getAlertDataLen
 */
#define SharkSslCon_getAlertData(o)    SharkSslCon_getEncData(o)


/** This function is used in conjunction with state
    #SharkSslCon_AlertSend returned by function
    #SharkSslCon_encrypt. 

    The function returns the length of the alert data that must be
    sent to the peer side.

    \sa #SharkSslCon_getAlertData
 */
#define SharkSslCon_getAlertDataLen(o) SharkSslCon_getEncDataLen(o)

/** @} */ /* end group SharkSslCoreApi */ 

#if SHARKSSL_ENABLE_INFO_API

/** Returns the active session's [chiper suite](@ref Ciphersuites)
 */
SHARKSSL_API U16 SharkSslCon_getCiphersuite(SharkSslCon *o);

/** Returns the active session's [protocol version](@ref SharkSslProtocol)
 */
SHARKSSL_API U8  SharkSslCon_getProtocol(SharkSslCon *o);

#endif

#if SHARKSSL_ENABLE_SNI

#if SHARKSSL_SSL_CLIENT_CODE
/** set Server Name Indication for TLS client connections
 */
SHARKSSL_API U8  SharkSslCon_setSNI(SharkSslCon *o, const char *name, U16 length); 
#endif

#endif


#if (SHARKSSL_ENABLE_RSA || SHARKSSL_ENABLE_ECDSA)
#if (SHARKSSL_SSL_CLIENT_CODE && SHARKSSL_ENABLE_CLIENT_AUTH)
/** Returns TRUE if the server requested a certificate from the client
    to verify that the client's identity (authentication)
 */
U8  SharkSslCon_certificateRequested(SharkSslCon *o);
#endif

/** Returns the peer's certificate if the handshaking has
    completed. The certificate is available at any time if the code is
    compiled with #SHARKSSL_ENABLE_CLONE_CERTINFO enabled. The
    certificate is only available when #SharkSslCon_decrypt returns the
    state #SharkSslCon_Certificate if the certificate cloning code is
    not enabled.
 */
SHARKSSL_API SharkSslCertInfo  *SharkSslCon_getCertInfo(SharkSslCon *o);


/** Add a certificate to the SharkSsl object. A SharkSsl object in
    [server mode](\ref #SharkSsl_Server) is required to have at least
    one certificate.

    __Note:__ You must install the certificate(s) before using the
    SharkSsl object -- i.e. before calling #SharkSsl_createCon.

    \returns TRUE on success or FALSE on error. The function
    fails if you have existing connections in the SharkSsl object.
 */
SHARKSSL_API U8 SharkSsl_addCertificate(SharkSsl *o, SharkSslCert cert);

#if SHARKSSL_ENABLE_CA_LIST

/** Set a Certificate Authority (CA) list so the SharkSSL object can
    permform certificate validation on the peer's certificate.
    
    \param o the SharkSsl object.

    \param caList list created by calling #SharkSslCertStore_assemble
    or by using the command line tool
    [SharkSSLParseCAList](\ref SharkSSLParseCAList)

    __Note:__ You can only set one CA list, thus the CA list must
    include all root certificates required for your system.

    The example program certcheck.c includes code that shows how to
    perform complete certificate validation of the connected servers.

    \return TRUE if the CA list was successfully installed or FALSE if
    another CA list has previously been installed.

    \sa #SharkSslCAList and SharkSslCon_trusted.
 */
SHARKSSL_API U8  SharkSsl_setCAList(SharkSsl *o, SharkSslCAList caList);

/** Returns TRUE if the certificate is valid and is signed with a root
    certificate trusted by SharkSSL. Root certificates can optionally
    be installed with parameter #SharkSslCAList when calling
    #SharkSsl_constructor.

    Note, the function only validates the certificate. You must
    typically also validate the domain name. Function
    #SharkSslCon_trusted extends the certificate validation and also
    includes domain name validation.

    \sa SharkSslCon_trusted
 */
SHARKSSL_API U8  SharkSslCon_trustedCA(SharkSslCon *o);

U8  SharkSslCon_isCAListEmpty(SharkSslCon *o);
#endif  /* SHARKSSL_ENABLE_CA_LIST */

#if (SHARKSSL_SSL_SERVER_CODE && SHARKSSL_ENABLE_RSA)
/** Description to be added.
 */

/* to be used as 'flag' param */
#define SHARKSSL_SET_FAVOR_RSA      1  
#define SHARKSSL_CLEAR_FAVOR_RSA    0

/** A SharkSSL server can have multiple certificates, such as RSA
    certificates with various strengths, and Elliptic Curve
    Certificates (ECC). A SharkSSL server connection will select the
    strongest cipher combination supported by the server and the
    client. In general, the ECC certificate will be preferred by the
    server connection, if supported by the client. Most browsers today
    support ECC, however, Certificate Authorities do not typically
    support ECC.

    The purpose with function SharkSslCon_favorRSA is to favor RSA
    certificates over ECC when a client such as browser supports both
    ECC and RSA. An M2M device can then force the use of ECC by
    calling function SharkSslCon_selectCiphersuite, or at compile time
    by removing RSA support. This enables devices to use ECC, with
    self signed Certificate Authority certificates and browsers to use
    RSA certificates signed by well known Certificate Authorities.
 */
U8  SharkSslCon_favorRSA(SharkSslCon *o, U8 flag);
#endif  /* SHARKSSL_SSL_SERVER_CODE */
#endif  /* SHARKSSL_ENABLE_RSA || SHARKSSL_ENABLE_ECDSA */

#if SHARKSSL_ENABLE_PSK
/** To be documented 
 */
SHARKSSL_API U8 SharkSsl_setPSKTable(SharkSsl *o, SharkSslPSKTable tablePSK);
#endif  /* SHARKSSL_ENABLE_PSK */

#if SHARKSSL_SSL_CLIENT_CODE 
U8  SharkSslCon_selectProtocol(SharkSslCon *o, U8 protocol);
#endif

/** @addtogroup SharkSslSessionApi
@{
*/

#if SHARKSSL_ENABLE_SESSION_CACHE

/** Release a session created by function #SharkSslCon_acquireSession.
 */
SHARKSSL_API U8    SharkSslSession_release(SharkSslSession *o, SharkSsl *s);

#if SHARKSSL_SSL_SERVER_CODE
/** experimental 
 */
SHARKSSL_API U8    SharkSslCon_releaseSession(SharkSslCon *o);
#endif

#if SHARKSSL_SSL_CLIENT_CODE 

/** Request a SharkSslSession object from the client's session pool.

    \returns a SharkSslSession object on success or NULL if the
    session cache pool is exhausted. See parameter 'cacheSize' in
    function SharkSsl_constructor for more information on the cache
    size.
  */
SHARKSSL_API SharkSslSession *SharkSslCon_acquireSession(SharkSslCon *o);


/** Resume an existing session.
    \param o the SharkSslCon object.
    \param s a session object created by function #SharkSslCon_acquireSession.

    \returns TRUE on success or FALSE if the session cannot be resumed.
 */
SHARKSSL_API U8 SharkSslCon_resumeSession(SharkSslCon *o, SharkSslSession *s); 

/** Returns the last time the session was accessed. Delta time can be
    calculated as follows: baGetUnixTime() -
    SharkSslSession_getLatestAccessTime(ss);
 */
SHARKSSL_API U32   SharkSslSession_getLatestAccessTime(SharkSslSession *o);
#endif
#endif

/** @} */ /* end group SharkSslSessionApi */

#if (SHARKSSL_SSL_SERVER_CODE && SHARKSSL_ENABLE_CLIENT_AUTH && \
    (SHARKSSL_ENABLE_RSA || SHARKSSL_ENABLE_ECDSA))
/** This function is used by server solutions that require client SSL
    certificate authentication. For example, it can be used by an
    HTTPS server that requires the client to authenticate using a
    certificate signed with a Certificate Authority (CA) known to the
    server. The second parameter, caList specifies one or several CA
    certificates the server uses when validating the client
    certificate.

    The function must be called before the initial handshake has
    started or just after calling SharkSslCon_renegotiate. Calling
    SharkSslCon_requestClientCert after #SharkSslCon_renegotiate
    enables an existing session to request client authentication at a
    later stage. For example, a server may require that the client
    authenticates when the user navigates to a protected web page.

    \param o the SharkSslCon object returned by function #SharkSsl_createCon.

    \param caList the SharkSSL CA list is in a binary format optimized
    for speed and size. The list can be created by calling
    #SharkSslCertStore_assemble or by using the command line tool
    [SharkSSLParseCAList](\ref SharkSSLParseCAList). The client is
    then requested to provide an SSL certificate and this certificate
    must be signed using one of the CA certificates provided in the
    caList. The SSL handshake or rehandshake fails if the client's
    certificate is not trusted or not signed with a known CA
    certificate.

    \return TRUE (1) if the request is accepted. Returns FALSE (0) if
    the SharkSSL connection is already going through or done with a
    handshaking phase.
 */
SHARKSSL_API U8 SharkSslCon_requestClientCert(
   SharkSslCon *o, const void *caList);
#endif

#if ((SHARKSSL_SSL_SERVER_CODE || SHARKSSL_SSL_CLIENT_CODE) && \
     SHARKSSL_ENABLE_SELECT_CIPHERSUITE)
/**
This function enables you to limit the number of ciphers at
runtime. Cipher suites can be enabled/disabled at compile time, but
your application may require that you also allow only specific ciphers
at runtime. By default, all ciphers enabled at compile time can be
used by SharkSSL. Calling this function disables the use of all
ciphers except the selected cipher. You can call this function up to N
times and re-enable N ciphers. N is by default set to 8 at compile
time. You can change the N value by setting macro
#SHARKSSL_SELECT_CIPHERSUITE_LIST_DEPTH.

The function must be called before the initial handshake has completed
or just after calling SharkSslCon_renegotiate. Calling
SharkSslCon_selectCiphersuite and then #SharkSslCon_renegotiate
enables an existing session to change cipher.

<b>Example:</b><br>
SharkSslCon_selectCiphersuite(myCon, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)

\param o the SharkSslCon object returned by function #SharkSsl_createCon.

\param cipherSuite is one of the [supported ciphers](\ref SharkSslCiphers)
enabled at compile time.

\return TRUE (1) if the request is accepted. Returns FALSE (0) if the
SharkSSL connection is currently in the handshaking phase, if the
selected cipher was not enabled at compile time, or if called more
than N times.
*/
SHARKSSL_API U8 SharkSslCon_selectCiphersuite(SharkSslCon *o, U16 cipherSuite);

/** Clears the selection, thus enabling all ciphers.
 */
SHARKSSL_API U8 SharkSslCon_clearCiphersuiteSelection(SharkSslCon *o); 
#endif

#if (SHARKSSL_SSL_SERVER_CODE && SHARKSSL_ENABLE_SECURE_RENEGOTIATION)
/** This function enables you to renegotiate an already established
    SSL/TLS connection. Renegotiation is also known as
    rehandshake. The function informs the SharkSSL state machine for
    the active connection that you wish to renegotiate the
    connection. The actual renegotiation is initiated and performed
    the next time you call #SharkSslCon_decrypt.

    The function is typically used in combination with
    #SharkSslCon_requestClientCert, when requesting client SSL
    certificate authentication on an existing connection. The function
    can also be used in combination with
    #SharkSslCon_selectCiphersuite, to force a change in the cipher
    being used.

    \param o the SharkSslCon object returned by function #SharkSsl_createCon.

    \return TRUE (1) if the request is accepted. Returns FALSE (0) if
    the SharkSSL connection is currently in the handshaking phase.
*/
SHARKSSL_API U8 SharkSslCon_renegotiate(SharkSslCon *o);
#endif

/** @} */ /* end group SharkSslApi */ 


#if SHARKSSL_ENABLE_PEM_API
/** @addtogroup RayCryptoApi
@{
*/


/** Return values from function #sharkssl_PEM
 */
typedef enum
{
   /** OK */
   SHARKSSL_PEM_OK = 0,

   /** OK_PUBLIC */
   SHARKSSL_PEM_OK_PUBLIC = 1,

   /** ALLOCATION_ERROR */
   SHARKSSL_PEM_ALLOCATION_ERROR = - 3000,

   /** KEY_PARSE_ERROR */
   SHARKSSL_PEM_KEY_PARSE_ERROR,

   /** KEY_WRONG_IV */
   SHARKSSL_PEM_KEY_WRONG_IV,

   /** KEY_WRONG_LENGTH */
   SHARKSSL_PEM_KEY_WRONG_LENGTH,

   /** KEY_PASSPHRASE_REQUIRED */
   SHARKSSL_PEM_KEY_PASSPHRASE_REQUIRED,

   /** KEY_UNRECOGNIZED_FORMAT */
   SHARKSSL_PEM_KEY_UNRECOGNIZED_FORMAT,

   /** KEY_UNSUPPORTED_FORMAT */
   SHARKSSL_PEM_KEY_UNSUPPORTED_FORMAT,

   /** KEY_UNSUPPORTED_MODULUS_LENGTH */
   SHARKSSL_PEM_KEY_UNSUPPORTED_MODULUS_LENGTH,

   /** KEY_UNSUPPORTED_ENCRYPTION_TYPE */
   SHARKSSL_PEM_KEY_UNSUPPORTED_ENCRYPTION_TYPE,

   /** KEY_CERT_MISMATCH */
   SHARKSSL_PEM_KEY_CERT_MISMATCH,

   /** CERT_UNRECOGNIZED_FORMAT */
   SHARKSSL_PEM_CERT_UNRECOGNIZED_FORMAT,

   /** CERT_UNSUPPORTED_TYPE */
   SHARKSSL_PEM_CERT_UNSUPPORTED_TYPE,

   /** KEY_UNSUPPORTED_VERSION */
   SHARKSSL_PEM_KEY_UNSUPPORTED_VERSION,

   /** INTERNAL ERROR */
   SHARKSSL_PEM_INTERNAL_ERROR
} sharkssl_PEM_RetVal;


/** fixme doc
 */
SHARKSSL_API sharkssl_PEM_RetVal sharkssl_PEM(
   const char *certPEM, const char *keyPEM, 
   const char *passphrase, SharkSslCert *sharkSslCert);

/** @} */ /* end group RayCryptoApi */
#endif

#if SHARKSSL_ENABLE_RSA

/** \addtogroup SharkSslInfoAndCodes
@{
*/

/** SHARKSSL_RSA_NO_PADDING for raw RSA encryption (insecure).
 */
#define SHARKSSL_RSA_NO_PADDING      0


/** SHARKSSL_RSA_PKCS1_PADDING for
    [PKCS #1 v1.5](http://tools.ietf.org/html/rfc2313).
*/
#define SHARKSSL_RSA_PKCS1_PADDING   1


/** Return values from functions #sharkssl_RSA_public_encrypt,
    #sharkssl_RSA_private_decrypt, #sharkssl_RSA_public_decrypt,
    #sharkssl_RSA_private_encrypt
 */
typedef enum
{
   /** OK */
   SHARKSSL_RSA_OK = 0,

   /** ALLOCATION_ERROR */
   SHARKSSL_RSA_ALLOCATION_ERROR = -3000,

   /** INTERNAL_ERROR */
   SHARKSSL_RSA_INTERNAL_ERROR = -3100,

   /** WRONG_PARAMETERS */
   SHARKSSL_RSA_WRONG_PARAMETERS,

   /** WRONG_KEY_FORMAT */
   SHARKSSL_RSA_WRONG_KEY_FORMAT,

   /** WRONG_KEY_LENGTH */
   SHARKSSL_RSA_WRONG_KEY_LENGTH,

   /** INPUT_DATA_LENGTH_TOO_BIG */
   SHARKSSL_RSA_INPUT_DATA_LENGTH_TOO_BIG,

   /** INPUT_DATA_LENGTH_AND_KEY_LENGTH_MISMATCH */
   SHARKSSL_RSA_INPUT_DATA_LENGTH_AND_KEY_LENGTH_MISMATCH,

   /** PKCS1_PADDING_ERROR */
   SHARKSSL_RSA_PKCS1_PADDING_ERROR
} sharkssl_RSA_RetVal;
#endif

/** @} */ /* end group SharkSslInfoAndCodes */ 

#if SHARKSSL_ENABLE_RSA_API

/** \defgroup RSA RSA encrypt/decrypt functions
\ingroup RayCryptoApi

@{
*/

/** SharkSslRSAKey is an alias for the #SharkSslCert type and is a
    private/public key converted by sharkssl_PEM_to_RSAKey or the
    command line tool [SharkSslParseKey](\ref SharkSslParseKey).
 */
typedef U8* SharkSslRSAKey;

#if SHARKSSL_ENABLE_PEM_API
/** Convert an RSA private or public key in PEM format to the
    #SharkSslRSAKey format.
 
    Note: the converted value must be released by calling
    SharkSslRSAKey_free, when no longer needed.

    example:
    \code
   {
      SharkSslRSAKey RSAKey;   
      ...
      RSAKey = sharksslPEM_to_RSAKey(key, pass);
      if (RSAKey)
      {
         ...
         void SharkSslRSAKey_free(RSAKey);
      }
   }
   \endcode

   \return the private/public key in #SharkSslRSAKey format or NULL if
   the conversion fails.
  */
SHARKSSL_API SharkSslRSAKey sharkssl_PEM_to_RSAKey(
   const char *PEMKey, const char *passphrase);

/** Extract the public key form a certificate in PEM format

    Note: the converted value must be released by calling
    SharkSslRSAKey_free, when no longer needed.

    example:
    \code
   {
      SharkSslRSAKey RSAKey;   
      ...
      RSAKey = sharkssl_PEM_extractPublicKey(cert);
      if (RSAKey)
      {
         ...
         void SharkSslRSAKey_free(RSAKey);
      }
   }
   \endcode

   \return the certificate's public key in #SharkSslRSAKey format 
   or NULL if the conversion fails.

 */
SHARKSSL_API SharkSslRSAKey
sharkssl_PEM_extractPublicKey(const char *certPEM);

/** Release a SharkSslRSAKey allocated by functions #sharkssl_PEM_to_RSAKey
    and sharkssl_PEM_extractPublicKey.
 */
SHARKSSL_API void SharkSslRSAKey_free(SharkSslRSAKey key);
#endif

#if SHARKSSL_ENABLE_RSA

/** Returns the private or public key's modulus size in bytes.
 */
SHARKSSL_API U16 SharkSslRSAKey_size(SharkSslRSAKey key);

/** Encrypt data using the public key or private key. The private key
    includes the public key an can for this reason be used for
    encrypting the data.

    \param in the plaintext

    \param len is the length/size of parameter 'in'. This length must be
    exactly #SharkSslRSAKey_size (key) when selecting
    #SHARKSSL_RSA_NO_PADDING or a value between 1 and
    (#SharkSslRSAKey_size (key) - 11) when selecting
    SHARKSSL_RSA_PKCS1_PADDING.

    \param out the encrypted ciphertext is copied to this buffer. The
    size of this buffer must be no less than #SharkSslRSAKey_size (key)

    \param key is the public key in SharkSslRSAKey format.

   \param padding is one of #SHARKSSL_RSA_PKCS1_PADDING or
   #SHARKSSL_RSA_NO_PADDING

   \return the size of the encrypted ciphertext, or -1 if any error occurs
 */
SHARKSSL_API sharkssl_RSA_RetVal sharkssl_RSA_public_encrypt(
   U16 len, U8 *in, U8 *out, SharkSslRSAKey key, U8 padding);


/** Decrypt ciphertext using the private key.

    \param len is the length/size of parameter 'in'. This length must be
    exactly #SharkSslRSAKey_size (key).

    \param in the ciphertext

    \param out the decrypted ciphertext is copied to this buffer. The
    size of this buffer must be no less than #SharkSslRSAKey_size (key)

    \param privkey is the private key in SharkSslRSAKey format.

   \param padding is one of #SHARKSSL_RSA_PKCS1_PADDING or
   #SHARKSSL_RSA_NO_PADDING

   \return the size of the decrypted ciphertext, or -1 if any error occurs
 */
SHARKSSL_API sharkssl_RSA_RetVal sharkssl_RSA_private_decrypt(
   U16 len, U8 *in, U8 *out, SharkSslRSAKey privkey, U8 padding);


/** Sign a message digest using the private key. 

    \param in commonly, an algorithm identifier followed by a message digest

    \param len is the length/size of parameter 'in'. This length must be
    exactly #SharkSslRSAKey_size (key) when selecting
    #SHARKSSL_RSA_NO_PADDING or a value between 1 and
    (#SharkSslRSAKey_size (key) - 11) when selecting
    SHARKSSL_RSA_PKCS1_PADDING.

    \param out the signature is copied to this buffer. The size
    of this buffer must be no less than #SharkSslRSAKey_size (key)

    \param privkey is the private key in SharkSslRSAKey format.

   \param padding is one of #SHARKSSL_RSA_PKCS1_PADDING or
   #SHARKSSL_RSA_NO_PADDING

   \return the size of the signature, or -1 if any error occurs
 */
SHARKSSL_API sharkssl_RSA_RetVal sharkssl_RSA_private_encrypt(
   U16 len, U8 *in, U8 *out, SharkSslRSAKey privkey, U8 padding);


/** Bring back a message digest using the public key or private key. 
    The private key includes the public key an can for this reason be used for
    this operation.

    \param in the RSA signature

    \param len is the length/size of parameter 'in'. This length must be
    exactly #SharkSslRSAKey_size (key).

    \param out the message digest is copied to this buffer. The size
    of this buffer must be no less than #SharkSslRSAKey_size (key)

    \param key is the public key in SharkSslRSAKey format.

   \param padding is one of #SHARKSSL_RSA_PKCS1_PADDING or
   #SHARKSSL_RSA_NO_PADDING

   \return the size of the obtained message digest, or -1 if any error occurs
 */
SHARKSSL_API sharkssl_RSA_RetVal sharkssl_RSA_public_decrypt(
   U16 len, U8 *in, U8 *out, SharkSslRSAKey key, U8 padding);

#endif

/** @} */ /* end group RSA */
#endif


/** To be used as hashlen parameter in sharkssl_ECDSA_ functions
    These are the hash lengths for the functions implemented in SharkSSL/RayCrypto

    SHARKSSL_MD5_HASH_LEN
    SHARKSSL_SHA1_HASH_LEN
    SHARKSSL_SHA256_HASH_LEN
    SHARKSSL_SHA384_HASH_LEN
    SHARKSSL_SHA512_HASH_LEN
    SHARKSSL_POLY1305_HASH_LEN
 */


#if SHARKSSL_USE_ECC

/*
 * use as curveID parameter
 */
#define SHARKSSL_EC_CURVE_ID_SECP192R1  19
#define SHARKSSL_EC_CURVE_ID_SECP224R1  21
#define SHARKSSL_EC_CURVE_ID_SECP256R1  23
#define SHARKSSL_EC_CURVE_ID_SECP384R1  24
#define SHARKSSL_EC_CURVE_ID_SECP521R1  25


/** 
    @ingroup ECDSA
    SharkSslECCKey is an alias for the #SharkSslCert type and is a
    private/public key converted by #sharkssl_PEM_to_ECCKey or the
    command line tool [SharkSslParseKey](\ref SharkSslParseKey).
 */
typedef U8* SharkSslECCKey;

#if SHARKSSL_ENABLE_PEM_API
/** 
    @ingroup ECDSA
    Convert an ECC private or public key in PEM format to the
    #SharkSslECCKey format.
 
    Note: the converted value must be released by calling
    SharkSslECCKey_free, when no longer needed.

    example:
    \code
   {
      SharkSslECCKey ECCKey;   
      ...
      ECCKey = sharksslPEM_to_ECCKey(key, pass);
      if (ECCKey)
      {
         ...
         void SharkSslECCKey_free(ECCKey);
      }
   }
   \endcode

   \return the private/public key in #SharkSslECCKey format or NULL if
   the conversion fails.
  */
SHARKSSL_API SharkSslECCKey sharkssl_PEM_to_ECCKey(
   const char *PEMKey, const char *passphrase);
#endif


#if SHARKSSL_ENABLE_ECCKEY_CREATE
int SharkSslECCKey_create(SharkSslECCKey *key, U16 curveID);
#endif


#if (SHARKSSL_ENABLE_PEM_API || SHARKSSL_ENABLE_ECCKEY_CREATE)
/** Release a SharkSslECCKey allocated by functions #sharkssl_PEM_to_ECCKey
    or #SharkSslECCKey_create
 */
SHARKSSL_API void SharkSslECCKey_free(SharkSslECCKey key);
#endif

/** \addtogroup SharkSslInfoAndCodes
@{
*/


#if (SHARKSSL_ENABLE_ECDSA && SHARKSSL_ENABLE_ECDSA_API)
/** Return values from functions #sharkssl_ECDSA_sign_hash,
    #sharkssl_ECDSA_verify_hash
 */
typedef enum
{
   /** OK */
   SHARKSSL_ECDSA_OK = 0,

   /** ALLOCATION_ERROR */
   SHARKSSL_ECDSA_ALLOCATION_ERROR = -3200,

   /** INTERNAL_ERROR */
   SHARKSSL_ECDSA_INTERNAL_ERROR = -3300,

   /** WRONG_PARAMETERS */
   SHARKSSL_ECDSA_WRONG_PARAMETERS,

   /** WRONG_KEY_FORMAT */
   SHARKSSL_ECDSA_WRONG_KEY_FORMAT,

   /** KEY_IS_NOT_PRIVATE */
   SHARKSSL_ECDSA_KEY_NOT_PRIVATE,

   /** KEY_IS_NOT_PUBLIC */
   SHARKSSL_ECDSA_KEY_NOT_PUBLIC,

   /** SIGLEN_TOO_SMALL */
   SHARKSSL_ECDSA_SIGLEN_TOO_SMALL,

   /** VERIFICATION_FAIL */
   SHARKSSL_ECDSA_VERIFICATION_FAIL,

   /** WRONG SIGNATURE */
   SHARKSSL_ECDSA_WRONG_SIGNATURE
} sharkssl_ECDSA_RetVal;

/** @} */ /* end group SharkSslInfoAndCodes */ 

/** @addtogroup ECDSA
@{
*/


#if (!SHARKSSL_ECDSA_ONLY_VERIFY)
/** Returns the maximum length (in bytes) of a DER-encoded ECDSA 
    signature generated with the private key 'privkey'. This function 
    is typically used in combination with #sharkssl_ECDSA_sign_hash to
    compute the maximum length of the signature and to allocate a 
    buffer large enough to hold the signature 'sig'.

    \param privkey is the private key in SharkSslECCKey format.
 */
SHARKSSL_API U16 sharkssl_ECDSA_siglen(SharkSslECCKey privkey);

/** Generate the signature using the ECC private key and a hash. 

    \param privkey is the private key in #SharkSslECCKey format.

    \param sig is a pointer to the buffer where the DER-encoded ECDSA
     signature will be generated. The size of this buffer must not be
     smaller than the value returned by #sharkssl_ECDSA_siglen for
     param 'privkey'. The length of this buffer, which may be larger
     than required, is provided in the next parameter (siglen).

    \param siglen is parameter "sig"'s length and is provided as an
     input parameter. The signature length will be returned as output
     parameter.

    \param hash the message digest obtained from a hash function
     e.g. SHA256. 

    \param hashlen the length of the message digest (see above).

    \return SHARKSSL_ECDSA_OK if the signature generation is succesful, 
     or one of the #sharkssl_ECDSA_RetVal error codes.
 */
SHARKSSL_API sharkssl_ECDSA_RetVal sharkssl_ECDSA_sign_hash(
   SharkSslECCKey privkey, U8 *sig, U16 *siglen, U8 *hash, U8 hashlen);
#endif

/** Verify a message using the ECC public key and a hash algorithm. 

    \param pubkey is the public key in SharkSslECCKey format.

    \param sig is a pointer to the DER-encoded ECDSA signature 
     that is to be verified.

    \param siglen is parameter "sig"'s length.

    \param hash the message digest obtained from a hash function
     e.g. SHA256. 

    \param hashlen the length of the message digest (see above).

    \return SHARKSSL_ECDSA_OK if the signature verification is succesful, 
     or one of the #sharkssl_ECDSA_RetVal error codes.
 */
SHARKSSL_API sharkssl_ECDSA_RetVal sharkssl_ECDSA_verify_hash(
   SharkSslECCKey pubkey, U8 *sig, U16 siglen, U8 *hash, U8 hashlen);

#endif

/** @} */ /* end group ECC */
#endif


#if (SHARKSSL_ENABLE_CA_LIST && SHARKSSL_ENABLE_CERTSTORE_API)

/** @addtogroup SharkSslCertApi
@{
*/


#ifndef BA_API  /* standalone SharkSSL */
#define BA_API SHARKSSL_API
typedef U8 BaBool;
#endif
#include "DoubleList.h"

/** SharkSslCertStore is a container object used when assembling a
    #SharkSslCAList. See #SharkSslCertStore_assemble for details.
 */
typedef struct SharkSslCertStore
{
   DoubleList certList;
   SharkSslCAList caList;
   U16 elements;  /* number of elements in list */
} SharkSslCertStore;

/** Initialize a SharkSslCertStore object. See #SharkSslCertStore for
    details.  The object must reside in memory as long as the produced
    SharkSslCAList is used by a SharkSSL object.

    \param o Uninitialized data of size sizeof(SharkSsl).

    \sa #SharkSslCertStore_assemble.
*/
SHARKSSL_API void  SharkSslCertStore_constructor(SharkSslCertStore *o);

/** Cleanup all memory used by the SharkSslCAList object. 
 */
SHARKSSL_API void  SharkSslCertStore_destructor(SharkSslCertStore* o);

/** Alias for SharkSslCertStore_destructor */
#define            SharkSslCertStore_release(o) SharkSslCertStore_destructor(o)

/** add a certificate in PEM or p7b format to the CA store. A
    convenient way to get CA's is to export the certificates from a
    browser in PEM or p7b format. The p7b format is a container format
    that can contain many CA's.

    \param o the SharkSslCertStore object.
    \param cert is a one PEM cert or multiple certs in p7b format.
    \param certlen is the length of parameter 'cert'
    \sa SharkSslCertStore_assemble.
    \return the number of certificates successfully parsed and added to
    the certificate store or a negative value if memory could not be allocated.
 */
SHARKSSL_API U16   SharkSslCertStore_add(
   SharkSslCertStore *o, const char *cert, U32 certlen);

/** Assemble all certificates added by calling #SharkSslCertStore_add.
    The SharkSslCertStore object can be released as soon as the
    #SharkSslCAList is assembled.

    \param o the SharkSslCertStore object
    \param outList is the SharkSslCAList out value
    \return TRUE on success or FALSE if memory could not be allocated
    \sa #SharkSslCertStore_destructor and #SharkSsl_setCAList
 */
SHARKSSL_API U8  SharkSslCertStore_assemble(
   SharkSslCertStore *o, SharkSslCAList *outList);

/** @} */ /* end group SharkSslCertApi */ 
#endif  /* SHARKSSL_ENABLE_CA_LIST && SHARKSSL_ENABLE_CERTSTORE_API */





#ifdef __cplusplus
}

inline SharkSsl::SharkSsl(
   SharkSsl_Role role, U16 cacheSize, U16 inBufStartSize, U16 outBufSize) {
   SharkSsl_constructor(this, role, cacheSize, inBufStartSize, outBufSize);
}
inline SharkSsl::~SharkSsl() {
   SharkSsl_destructor(this);
}
inline SharkSslCon *SharkSsl::createCon(void) {
   return SharkSsl_createCon(this);
}
inline void SharkSsl::terminateCon(SharkSslCon *sslCon) {
   SharkSsl_terminateCon(this, sslCon);
}

#if (SHARKSSL_ENABLE_RSA || SHARKSSL_ENABLE_ECDSA)
inline U8 SharkSsl::addCertificate(SharkSslCert cert) {
   return SharkSsl_addCertificate(this, cert);
}
#if SHARKSSL_ENABLE_CA_LIST
inline U8 SharkSsl::setCAList(SharkSslCAList caList) {
   return SharkSsl_setCAList(this, caList);
}
#endif  /* SHARKSSL_ENABLE_CA_LIST */
#endif  /* SHARKSSL_ENABLE_RSA || SHARKSSL_ENABLE_ECDSA */

#if SHARKSSL_ENABLE_PSK
inline U8 SharkSsl::setPSKTable(SharkSslPSKTable tablePSK) {
   return SharkSsl_setPSKTable(this, tablePSK);
}
#endif  /* SHARKSSL_ENABLE_PSK */

#endif  /* __cplusplus */


#endif