SharkSSL™ Embedded SSL/TLS Stack
The SharkSSL API

Introduction to the SharkSSL API

SharkSSL provides a unique transport agnostic API that is not directly connected to the network transport layer, such as the socket layer provided by a TCP/IP stack. The reason SharkSSL is not directly connected to the transport layer API is to make it possible to integrate and provide SSL for any type of network and/or underlying API. For example, some embedded systems may not use an RTOS, and all calls are designed around event driven callbacks. Another system may use a proprietary network protocol very different from TCP/IP. SharkSSL is designed such that it can be integrated in all of these environments, regardless of the network API provided by these systems. The following provides a quick introduction to the transport agnostic SharkSSL API.

Example Socket Lib

The example code includes a basic TCP/IP interface library that maps the SharkSSL transport agnostic API to the standard socket API. The library also includes mappings to non BSD TCP/IP stacks such as NetX™. All example code delivered with SharkSSL uses this library. Depending on your requirements and your embedded system, you may simply use this basic library or you may use the direct transport agnostic API provided by SharkSSL. The example library selib, short for SharkSSL Example Lib, is designed to block and wait for data; thus selib requires that you use an RTOS. You must use the transport agnostic API provided by SharkSSL if you are not using an RTOS and/or if your TCP/IP stack provides a non standard callback API.

See the SharkSSL Example Lib (selib) API for more information.

Bare Metal Environments

The transport agnostic SharkSSL API is optimized for both bare metal systems and RTOS environments. The socket example library selib is using blocking socket calls and is optimized for RTOS environments, however, the socket library can be used on bare metal systems when a selib porting layer is used together with the Socket Context Manager SeCtx. See the "arch" (architecture) directory and the raw lwIP port for more details.

Transport Agnostic API

(How to use the SharkSSL Transport Agnostic API)

SharkSSL is implemented in standard ANSI C; however, the SharkSSL API uses an object oriented design inherited from the Barracuda Web Server. An introduction to how this API works can be found in our online Barracuda Web Server manual. The API is designed such that it maps easily to C++, and the SharkSSL header files include an inline wrapper API for C++, which is activated when you include the SharkSSL headers in a C++ file.

A typical SharkSSL powered application starts by creating one SharkSsl instance (object). The SharkSsl instance is used as a place holder for SharkSslCon objects and includes information such as if the instance is used as an SSL server or an SSL client. The SharkSsl instance also includes information on the certificates you have loaded. A SharkSslCon object is created, by calling function SharkSsl_createCon, for each network (socket) connection created by your client or server network program.

Figure 1 shows the relation between one SharkSsl object and three spawned SharksslCon objects.

A SharkSslCon object provides an input buffer and an output buffer. These buffers can be used for creating a zero copy API for your network program. The size of the input and output buffer is specified when you create the SharkSsl instance. The input buffer is designed such that it can dynamically grow if it is not sufficiently large enough for the incoming message. Many SSL ciphers are block based, and the input buffer must be sufficiently large enough to keep the SSL frame in memory. The data cannot be decrypted until the complete frame is received. In addition, the input buffer must be able to store the received certificate received from the peer side. Certificates can be large, especially chained certificates.

The following code snippet shows how to create a SharkSslCon instance after you have created a new socket connection. Function createNewSocket is a fictitious function that creates a handle to some type of network connection, either a client or server connection.

int sock = createNewSocket();
SharkSslCon *s = SharkSsl_createCon(ssl); /* ssl is a SharkSsl instance */
SharkSslCon * SharkSsl_createCon(SharkSsl *o)
Create a SharkSslCon object.
struct SharkSslCon SharkSslCon
SharkSslCon is an opaque handle returned by function SharkSsl_createCon.
Definition: SharkSSL.h:553

Some protocols such as HTTPS start directly with secure communication, and others are upgraded after some initial handshaking. SharkSSL supports both methods. You start using the SharkSSL API when you are ready to start a secure communication link.

The SSL protocol uses asymmetric encryption for exchanging the private keys used for symmetric encryption. We must therefore start by performing the initial SSL handshake. SharkSSL is internally maintaining state information in the SharkSslCon instance. Function SharkSslCon_decrypt returns the state information and the action your network API must follow. The following example function is designed to handle the initial SSL handshake and to decrypt messages received on the stream when the SSL protocol switches to symmetric encryption. The function returns the length of the decrypted message and the internal SharksslCon read buffer in the outBuf parameter.

int readAndDecrypt(SharkSslCon* s, int sock, U8** outBuf)
{
int rlen = 0;
for(;;)
{
int slen;
switch(SharkSslCon_decrypt(s, (U16)rlen))
{
/*Read from socket stream and insert into the SharksslCon rec buf*/
rlen = recv(sock,SharkSslCon_getBuf(s),SharkSslCon_getBufLen(s),0);
break; /* Continue loop: call SharkSslCon_decrypt */
if ((slen = SharkSslCon_getHandshakeDataLen(s)) != 0)
{
if (slen != send(sock, SharkSslCon_getHandshakeData(s),slen,0))
return -1; /* Sock send err */
}
rlen = 0;
break; /* Continue loop: call SharkSslCon_decrypt with rlen=0 */
rlen = SharkSslCon_copyDecData(s, buf, maxLen);
/* decrypted rlen bytes */
{
if ((rlen == 0) && (maxLen > 0))
{
break; /* zero-length record, decrypt next one */
}
}
/* Use zero copy API i.e. return the SharkSSL input buffer */
*outBuf = SharkSslCon_getBuf(s);
return rlen;
}
}
}
U16 SharkSslCon_getHandshakeDataLen(SharkSslCon *o)
This function is used in conjunction with state SharkSslCon_Handshake returned by function SharkSslCo...
U16 SharkSslCon_getBufLen(SharkSslCon *o)
Returns the length of the SharkSslCon input buffer.
SharkSslCon_RetVal SharkSslCon_decrypt(SharkSslCon *o, U16 readLen)
Decrypt the received data copied into the SharkSslCon receive buffer (the buffer returned by SharkSsl...
U8 SharkSslCon_decryptMore(SharkSslCon *o)
This function is used in conjunction with state SharkSslCon_Decrypted returned by function SharkSslCo...
U8 * SharkSslCon_getBuf(SharkSslCon *o)
Returns a pointer to the SharkSslCon input/receive buffer.
U16 SharkSslCon_copyDecData(SharkSslCon *o, U8 *buf, U16 maxLen)
Copy decoded data to 'buf'.
U8 * SharkSslCon_getHandshakeData(SharkSslCon *o)
This function is used in conjunction with state SharkSslCon_Handshake returned by function SharkSslCo...
@ SharkSslCon_Decrypted
Returned when a block of received data has been successfully decrypted.
Definition: SharkSSL.h:628
@ SharkSslCon_Handshake
Returned when an SSL/TLS handshake message has been received or is to be sent.
Definition: SharkSSL.h:641
@ SharkSslCon_NeedMoreData
Returned when SharkSSL holds an incomplete SSL/TLS record or when the connection is initially establi...
Definition: SharkSSL.h:654

The above example function is designed for standard BSD sockets. The "send" function sends data on the stream and "recv" blocks and waits for data on the stream. The example serves as a very basic example for how to use the SharkSSL API for performing SSL handshake and decrypting messages received on the stream. The SharkSSL Example Lib includes functionality similar to the example code above, however, the SSL handshaking and reading data from the stream is not managed in the same function. The functionality is split into the two functions: seSec_handshake and seSec_read.

The above example code only handles a subset of the states returned by SharkSslCon_decrypt. We recommend that you study the source code for the three SharkSSL example lib functions seSec_handshake, seSec_read, and seSec_write for more information on using the SharkSSL API.

Event Driven TCP/IP Stack

If you are using an event driven TCP/IP stack that is callback based, make sure to keep the state information in between the calls. For example, in the above code, you must maintain the SharkSslCon instance and the "rlen" stack argument in an object. You can convert the function into an event driven API by moving these two variables into your TCP/IP callback object and then remove the for(;;) loop in the code above.

See the SharkSSL core API for details.