SSL Programmer's Reference

Jump to: navigation, search

Table of Contents

Introduction to Secure Sockets Layer and Transport Layer Security

Secure Sockets Layer (SSL) and its newer IETF version Transport Layer Security (TLS) runs above TCP layer and below higher application level protocols such as HTTP, FTP, SMTP, see Figure 1.

Figure 1: SSL/TLS runs between network layer and application layer

Figure 1: SSL/TLS runs between network layer and application layer

SSL/TLS allows an SSL-enabled server to authenticate itself to an SSL-enabled client, and if necessary, allows the client to authenticate itself to the server. After the authentication and cryptology parameter negotiation, a secure channel is established so that the client and server can exchange information in a secure way.

In order to SSL/TLS-enable your server, firstly, you need obtain a certificate from a Certificate Authority (CA) whose public certificate is accessible to all your potential clients. For example, if you want to build an SSL/TLS enabled web server with potential clients all over the world, you need a certificate from CA like http://wwww.verisign.com, while, if your clients are all from the same company, a certificate from company Registration Authority (RA) is good enough. Secondly, the certificate you obtained must have a certain binding to your SSL/TLS-enabled server. For example, if your SSL/TLS server is running at www.sslfoobar.com, then your certificate should bind to "www.sslfoobar.com", most likely as the Common Name in the SubjectName field of your certificate.

Figure 1: Packet Format of SSL Record

Figure 2: Packet Format of SSL Record

Figure 2 shows the packet format of an SSL record. One TCP fragment may include one or more SSL records, or even partial of one SSL record. All shaded parts in Figure 2 are encrypted upon receiving. The receiver waits until a full SSL record has been received, then it decrypts the record, verifies the padding if necessary, and verifies the hashing results. If all the verification passes, the receiver puts the Data into socket receiving queue for user to retrieve.

SSL/TLS handshake messages are responsible to negotiate the encryption and hashing algorithms to protect Data. Before handshake negotiation finishes, SSL/TLS handshake messages are sent in format as shown in Figure 2, however, in clear text format rather than encrypted, and no hashing results and no padding. The receiver can tell if an SSL record is a handshake record or not by looking at the 'type' field. Figure 3 shows a typical handshake exchange.

Client                                          Server
ClientHello -------->

                                           ServerHello
                                           Certificate
                             <-------- ServerHelloDone

ClientKeyExchange
ChangeCipherSpec
Finished(encrypted) -------->

                                      ChangeCipherSpec
                         <-------- Finished(encrypted)

Application Data <------------------> Application Data
(encrypted)                                (encrypted)

Figure 3: Typical SSL Handshake

Treck SSL/TLS Features

Treck SSL/TLS is proud to have the following features:

  • Small code size. Treck SSL has small code size of about 50k.
  • Supports 512, 1024, 2048-bit and above exportable and non-exportable cipher suites
  • Configurable support for any combination of SSL 3.0, TLS 1.0, TLS 1.1 and TLS 1.2
  • Configurable support for SSL server, SSL client or both
  • Configurable support for RSA and Ephemeral Diffie-Hellman key exchange method
  • Configurable support for RSA signature algorithm with MD5 or SHA1 to SHA512
  • Configurable support for DSS signature algorithm with MD5 or SHA1 to SHA256
  • Configurable support for Mutual authentication
  • Support SSL re-handshake
  • Configurable support for parsing SSL 2.0 client hello
  • Configurable support for DES, 3DES, AES, RC2, and ARCFOUR (compatible with RC4) algorithms
  • Support resumed handshake, user determines the cache size.
  • Support for configuring cipher suite per session level
  • Support user interaction in certificate processing
  • Support wild card certificate match
  • Support socket call back function for SSL events, such as handshake failure, connection establishment, connection close for each direction, or bad certificate
  • Standard BSD Socket APIs for sending and receiving user data
  • Supported Cipher suites include:
TM_TLS_RSA_NULL_MD5 0x0001
TM_TLS_RSA_NULL_SHA 0x0002
TM_TLS_RSA_EXPORT_RC4_40_MD5 0x0003
TM_TLS_RSA_RC4_128_MD5 0x0004
TM_TLS_RSA_RC4_128_SHA 0x0005
TM_TLS_RSA_EXPORT_RC2_40_MD5 0x0006
TM_TLS_RSA_EXPORT_DES40_CBC_SHA 0x0008
TM_TLS_RSA_DES_CBC_SHA 0x0009
TM_TLS_RSA_3DES_EDE_CBC_SHA 0x000A
TM_TLS_DHE_DSS_EPT_DES40_CBC_SHA 0x0011
TM_TLS_DHE_DSS_DES_CBC_SHA 0x0012
TM_TLS_DHE_DSS_3DES_EDE_CBC_SHA 0x0013
TM_TLS_DHE_RSA_EPT_DES40_CBC_SHA 0x0014
TM_TLS_DHE_RSA_DES_CBC_SHA 0x0015
TM_TLS_DHE_RSA_3DES_EDE_CBC_SHA 0x0016
TM_TLS_RSA_AES_128_CBC_SHA 0x002F
TM_TLS_DHE_DSS_AES_128_CBC_SHA 0x0032
TM_TLS_DHE_RSA_AES_128_CBC_SHA 0x0033
TM_TLS_RSA_AES_256_CBC_SHA 0x0035
TM_TLS_DHE_DSS_AES_256_CBC_SHA 0x0038
TM_TLS_DHE_RSA_AES_256_CBC_SHA 0x0039
TM_TLS_RSA_EPT1K_DES_CBC_SHA 0x0062
TM_TLS_DHE_DSS_EPT1K_DES_CBC_SHA 0x0063
TM_TLS_RSA_EPT1K_RC4_56_SHA 0x0064
TM_TLS_DHE_DSS_EPT1K_RC4_56_SHA 0x0065
TM_TLS_DHE_DSS_RC4_128_SHA 0x0066
TLS 1.2 cipher suites:
TM_TLS_RSA_NULL_SHA256 0x003B
TM_TLS_RSA_AES_128_CBC_SHA256 0x003C
TM_TLS_RSA_AES_256_CBC_SHA256 0x003D
TM_TLS_DHE_DSS_AES_128_CBC_SHA256 0x0040
TM_TLS_DHE_RSA_AES_128_CBC_SHA256 0x0067
TM_TLS_DHE_DSS_AES_256_CBC_SHA256 0x006A
TM_TLS_DHE_RSA_AES_256_CBC_SHA256 0x006B
Warning Warning: TLS 1.1 and 1.2 specifically exclude support for export cipher suites. However, export suites may be advertised in an outbound Client Hello message to allow their use with a lower SSL version if, for example, the server selects TLS 1.0.

Compile Time Settings

TM_USE_SSL_CLIENT
TM_USE_SSL_SERVER
TM_SSL_DEBUG
TM_USE_SSL_VERSION_30
TM_USE_TLS_VERSION_10
TM_USE_TLS_VERSION_11
TM_USE_TLS_VERSION_12
TM_SSL_ACCEPT_20_CLIENTHELLO
TM_SSL_IMMEDIATE_CLOSE_NOTIFY
TM_SSL_SEND_DATA_MIN_SIZE
TM_SSL_SEND_DATA_MAX_SIZE
TM_SSL_USE_EPHEMERAL_DH
TM_SSL_USE_MUTUAL_AUTH
TM_SSL_REJECT_EXPORTABLE_CIPHER
TM_SSL30_DSSSIGN_NETSCAPE_FORMAT
TM_SSL_DHE_PRIME_GROUP
TM_SSL_DHE_GENERATOR
TM_SSL_DHSECRET_DEFAULT_SIZE
TM_USE_PKI
TM_USE_SW_CRYPTOENGINE
TM_USE_MD2
TM_USE_MD5
TM_USE_SHA1
TM_USE_DES
TM_USE_3DES
TM_USE_AES
TM_USE_RC2
TM_USE_ARCFOUR
TM_PUBKEY_USE_DIFFIEHELLMAN
TM_USE_DIFFIEHELLMAN_PADDING
TM_PUBKEY_USE_RSA
TM_PUBKEY_USE_DSA
TM_SSL_DISABLE_CLIENT_SEC_RENEG
TM_SSL_DISABLE_SERVER_SEC_RENEG
TM_PKI_ALLOW_DN_SET_BUG

Function Reference

setsockopt()
tfRegisterSocketCBParam()
tfRegisterSocketCB()
tfRegisterSocketPacketCB()
tfSslAddEphemeralRsaKeys()
tfSslClientUserStart()
tfSslConnectUserClose()
tfSslNewSession()
tfSslRegisterCertificateCB()
tfSslRemoveEphemeralRsaKeys()
tfSslServerAddClientAuthCa()
tfSslServerRemoveClientAuthCa()
tfSslServerUserCreate()
tfSslServerUserHelloRequest()
tfSslSessionUserClose()
tfSslSetSessionOptions()
tfSslSetSessionProposals()
tfSslSetSignatureHashAlgorithms()
tfSslUninitialize()
tfSslUserSendFlush()
tfUseSsl()

For PKI APIs please see the PKI page.

Examples

SSL Server Example

#include <trsocket.h>
int main()
{
    ttUserLinkLayer linkLayerHandle;
    ttUserInterface interfaceHandle;
    struct sockaddr_storage myIp4Addr;
    struct sockaddr_storage peerIp4Addr;
    char * rootCaCertIdentity = “root_ca_certificate”;
    char * myCertIdentity = “ssl_server_certificate”;
    char buffer[BUFFER_SIZE];
    int value;
    int sockListen;
    int sockAccept;
    int sessionId;
    int recvLen;
    int sentLen;
...
/*Step 1. Start Treck */
    errorCode = tfStartTreck();
/*Step 2. Open Link layer and open interface. */
    linkLayerHandle = tfUseEthernet();
/* Using win32 port */
    interfaceHandle = tfUseWin32Driver( "eth0",
                                        linkLayerHandle,
                                        &errorCode);
    errorCode = tfNgOpenInterface( interfaceHandle,
                                    &myIp4Addr,
                                    24,
                                    TM_DEV_MCAST_ENB,
                                    0,
                                    1,
                                    0);
    assert(errorCode == TM_ENOERROR);
/*Step 3. Open a listening socket and bind it to SSL server address, if
SSL is not used, we may call listen (step 7) right after this step.
Now, since SSL is used, we need insert step 4, step 5 and step 6 before
we call listen */
    sockListen = socket(PF_INET, SOCK_STREAM, IP_PROTOTCP);
    assert(sockListen != -1);
    myIp4Addr.ss_port = htons(TM_SSL_PORT);
    errorCode = bind(sockListen,
                        (struct sockaddr *)&myIp4Addr.addr.ipSockAddr,
                        sizeof(myIp4Addr));
                        assert(errorCode == TM_ENOERROR);
#ifdef TM_USE_SSL_SERVER
/*Step 4. Enable PKI and add certificates , we need at least add root
CA’s certificate as well as the SSL serve r’s own certificate. In order
to add SSL server’s own certificate, we must add private/public key
pair first */
    errorCode = tfUsePki();
    assert(errorCode == TM_ENOERROR);
/* add CA’s certificate, name it “ rootcascertificate”, cacert.pem is
the CA certificate file, must in openssl format , i.e., starting line
must contain ‘Begin’, ending line must contain ‘End’ . Note that if no
file system is supported, you can call with memory pointer rather than
file name, please see tfPkiCertificateAdd for details */
    errorCode = tfPkiCertificateAdd ( "cacert.pem", /*the file name of ca cert*/
                                        TM_PKI_CERTIFICATE_PEM,
                                        TM_PKI_CERT_NONLOCAL | TM_PKI_CERT_ROOTCA,
                                        rootCaCertIdentity, /*name of ca cert*/
                                        strlen(rootCaCertIdentity),
                                        0);
/* add SSL server’s private key and public key pair. Suppose we are
going to use RSA key pairs, OpenSSL calls this private key */
    errorCode = tfPkiOwnKeyPairAdd ( "rsa1024key.pem",
                                        TM_PKI_CERTIFICATE_PEM,
                                        TM_PKI_RSA_KEY
                                        );
/* add SSL server’s certificate. This LOCAL certificate certificates
the key pair you just added above */
    errorCode = tfPkiCertificateAdd ( "rsa1024cert.pem",
                                        TM_PKI_CERTIFICATE_PEM,
                                        TM_PKI_CERT_LOCAL,
                                        myCertIdentity ,/*name of SSL server cert*/
                                        strlen(myCertIdentity),
                                        rootCaCertIdentity); /* The ca certificate
which is used to sign SSL server’s certificate */
    assert(errorCode == TM_ENOERROR);
/*Step 5. Enable SSL and open a new SSL server session. If we need add
ephemeral RSA keys, add it now by calling tfSslAddEphemeralRsaKeys. If
we use mutual authentication and we need to add client authentication
CAs, add it now by calling tfSslServerAddClientAuthCa */
    errorCode = tfUseSsl(16); /*as many as 16 sessions are supported */
    assert(errorCode == TM_ENOERROR);
    sessionId = tfSslNewSession(
/*In this session, use the following SSL server’s certificate. If you
have two SSL servers to support, you need two server sessions */
                                    myCertIdentity,
/* each session will have as many as 16 cache entries */
                                    16,
/* This session, TLS 1.0, 1.1 and 1.2 are supported */
                                    TM_TLS_VERSION_10 | TM_TLS_VERSION_11 | TM_TLS_VERSION_12,
/* No options are required. (No client authentication) */
                                    0);
    assert(sessionId != -1);
/*Step 6. set socket option for that listening socket . If you want to
enable SSL after a normal TCP connection has been established, please
see the example in tfSslServerUserCreate */
    value = 1;
/* To indicate that this is SSL server */
    errorCode = setsockopt (sockListen, IP_PROTOTCP, TM_TCP_SSL_SERVER,
                            (const char TM_FAR *) &value, sizeof (int));
    assert(errorCode == TM_ENOERROR);
/*This listening socket is going to use SSL session # sessionId */
    value = sessionId;
    errorCode = setsockopt (sockListen, IP_PROTOTCP, TM_TCP_SSLSESSION,
                            (const char TM_FAR *) &value, sizeof (int));
    assert(errorCode == TM_ENOERROR);
/* Set the SSL send threshold size. This call will overwrite the
default value TM_SSL_SEND_DATA_MIN_SIZE */
    value = 300;
    errorCode = setsockopt (sockListen,
                            IP_PROTOTCP, TM_TCP_SSL_SEND_MIN_SIZE,
                            (const char TM_FAR *) &value,
                            sizeof (int));
    assert(errorCode == TM_ENOERROR);
#endif /* TM_USE_SSL_SERVER */
/*Step 7. Now we are able to call listen, accept, send and receive.
Data exchanged in this SSL-enabled socket is protected by the SSL
cipher suite negotiated in SSL handshake. Note that, we use the same
send() and recv() API for SSL and normal TCP connec tion
*/
    errorCode = listen(sockListen, 1);
    assert(errorCode != TM_SOCKET_ERROR);
    sockAccept = accept(sockListen,
                        (struct sockaddr TM_FAR *)&peerIp4Addr,
                        (int TM_FAR *)&sockaddrLength);
    {
        recvLen = recv( sockAccept,
                            buffer,
                            BUFFER_SIZE,
                            0);
        sentLen = send( sockAccept,
                            buffer,
                            recvLen,
                            0);
        ...
    }
#ifdef TM_USE_SSL_SERVER
/*Step 8. User may explicitly flush the SSL send buffer */
    sentLen = tfSslUserSendFlush(sockAccept);
/*Step 9. User may explicitly call connect close to close the SSL layer
on sockAccept */
    errorCode = tfSslConnectUse rClose(sockAccept)
#endif /* TM_USE_SSL_SERVER */
/*Step 9.1. After SSL layer is tore down, user can still be able to
call send and recv on this same socket to send/receive unprotected TCP
data.
*/
    {
        recvLen = recv( sockAccept,
                            buffer,
                            BUFFER_SIZE,
                            0);
        sentLen = send( sockAccept,
                            buffer,
                            recvLen,
                            0);
        ...
    }
/* If SSL is used, and user doesn’t explicitly call Ste p 8 and Step 9,
the tfClose call will implicitly call them */
    tfClose(sockAccept);
    tfClose(sockListen);
/*Step 10. If sessionId is not used any more, close it */
    tfSslSessionUserClose(sessionId);
/*Step 11. If SSL is not used by any other app lications, un-initialize
it, i.e., free the SSL global variable */
    tfSslUninitialize();
/*Step 12. If PKI is not used by any other applications, un -initialize
it, i.e., free the PKI global variable */
    tfPkiUninitialize();
    return errorCode;
}


SSL Client Example

#include <trsocket.h>
int main()
{
    ttUserLinkLayer linkLayerHandle;
    ttUserInterface interfaceHandle;
    struct sockaddr_storage myIp4Addr;
    struct sockaddr_storage serverAddr;
    char * rootCaCertIdentity = "root_ca_certificate";
    char * myCertIdentity = (char *)0;
    char buffer[BUFFER_SIZE];
    int value;
    int sockConn;
    int sessionId;
    int recvLen;
    int sentLen;
...
 
/*Step 1. Start Treck */
    errorCode = tfStartTreck();
/*Step 2. Open Link layer and open interface. */
    linkLayerHandle = tfUseEthernet();
/* Using win32 port */
    interfaceHandle = tfUseWin32Driver( "eth0",
                                        linkLayerHandle,
                                        &errorCode);
    errorCode = tfNgOpenInterface( interfaceHandle,
                                    &myIp4Addr,
                                    24,
                                    TM_DEV_MCAST_ENB,
                                    0,
                                    1,
                                    0);
    assert(errorCode == TM_ENOERROR);
/*Step 3. Open a connecting socket, set the server's address. If SSL is
not used, we may call connect (step 7) right after this step. Now,
since SSL is used, we need insert step 4, step 5 and step 6 before we
call connect */
    sockConn = socket(PF_INET, SOCK_STREAM, IP_PROTOTCP);
    assert(sockConn != -1);
    serverAddr.ss_len = sizeof(struct sockaddr_in);
    serverAddr.ss_family = PF_INET;
    serverAddr.addr.ipv4.sin_addr.s_addr = inet_addr("192.168.0.111");
    serverAddr.ss_port = htons(TM_SSL_PORT);
#ifdef TM_USE_SSL_CLIENT
/*Step 4. Enable PKI and add certificates, we need at least add root
CA's certificate as well as the SSL server's own certificate. In order
to add SSL server's own certificate, we must add private/public key
pair first */
    errorCode = tfUsePki();
    assert(errorCode == TM_ENOERROR);
/* add CA's certificate, name it " rootcascertificate", cacert.pem is
the CA certificate file, must in openssl format, i.e., starting line
must contain `Begin', ending line must contain `End'. Note that if no
file system is supported, you can call with memory pointer rather than
file name, please see tfPkiCertificateAdd for details */
    errorCode = tfPkiCertificateAdd ("cacert.pem", /*the file name of ca cert*/
                                        TM_PKI_CERTIFICATE_PEM,
                                        TM_PKI_CERT_NONLOCAL | TM_PKI_CERT_ROOTCA,
                                        rootCaCertIdentity, /*name of ca cert*/
                                        strlen(rootCaCertIdentity),
                                        0);
/* If client authentication is used, we need to add SSL client's
private/public key pairs and the corresponding certificate, see SSL
server example to see how to add them */
 
/*Step 5. Enable SSL and open a new SSL client session. If we need
change default cipher suite proposals, we call tfSslSetSessionProposals
on that client session */
    errorCode = tfUseSsl(16); /*as many as 16 sessions are supported */
    assert(errorCode == TM_ENOERROR);
    sessionId = tfSslNewSession(
/* If you don't have a certificate, input NULL */
                                    myCertIdentity,
/* maximum caches for this session */
                                    32,
/* This session, TLS 1.0, 1.1 and 1.2 are supported */
                                    TM_TLS_VERSION_10 | TM_TLS_VERSION_11 | TM_TLS_VERSION_12,
                                    0);
    assert(sessionId != -1);
/*Step 6. set socket option for th is connect socket */
    value = 1;
/* To indicate that this is SSL server */
    errorCode = setsockopt (sockConn, IP_PROTOTCP, TM_TCP_SSL_CLIENT,
(const char TM_FAR *) &value, sizeof (int));
    assert(errorCode == TM_ENOERROR);
/*This connect socket is going to use SSL session # sessionId */
    value = sessionId;
    errorCode = setsockopt (sockConn, IP_PROTOTCP, TM_TCP_SSLSESSION,
                                (const char TM_FAR *) &value, sizeof (int));
    assert(errorCode == TM_ENOERROR);
#endif /* TM_USE_SSL_CLIENT */
/*Step 7. Now we are able to call connect */
    errorCode = connect(sockConn,
                        (struct sockaddr TM_FAR*)&serverAddr,
                        sizeof(struct sockaddr_storage));
    assert(errorCode != TM_SOCKET_ERROR);
#ifdef TM_USE_SSL_CLIENT
/*Step 8. After TCP connection is established, we start SSL */
    errorCode = tfSslClientUserStart(sockConn,
                                        "www.mytreck.com");
    assert(errorCode == TM_ENOERROR);
#endif /* TM_USE_SSL_CLIENT */
    {
        recvLen = recv( sockConn,
                        buffer,
                        BUFFER_SIZE,
                        0);
 
        sentLen = send( sockConn,
                        buffer,
                        recvLen,
                        0);
    ...
    }
#ifdef TM_USE_SSL_CLIENT
/*Step 9. User may explicitly flush the SSL send buffer */
    sentLen = tfSslUserSendFlush(sockConn);
/*Step 10. User may explicitly call connect close to close the SSL
layer on sockConn */
    errorCode = tfSslConnectUserClose(sockConn)
#endif /* TM_USE_SSL_CLIENT */
/* If SSL is used, and user doesn't explicitly call Step 8 and Step 9,
the tfClose call will implicitly call them */
    tfClose(sockConn);
/*Step 11. If sessionId is not used any more, close it */
    tfSslSessionUserClose(sessionId);
/*Step 12. If SSL is not used by any other applications, un -initialize
it, i.e., free the SSL global variable */
    tfSslUninitialize();
/*Step 13. If PKI is not used by any other applications, un -initialize
it, i.e., free the PKI global variable */
    tfPkiUninitialize();
    return errorCode;
}

Applications

Treck SSL can be used with other Treck products, such as HTTP server or FTP server/client, this may require a separate purchase. For more details please see the following sections

References

Please see Appendix E: Open Source Licensing Information.


Table of Contents