Topic: Familiarity with the library

Hello everyone!
Not long time ago I has met with the library WolfSSL.
This library has made a big impression on me.
Immediately apologize for my English, I use google translate.

For the study I was wrote two simple programs: an echo server and client to add their support TLS 1.2.

I have a few questions:
1) It is necessary to make sure that the server has only worked with TLS and did not support the work of insecure channel. If the client connecting without TLS support, it must be disconnected by server. How this can be done (on the server side)?

2) It is necessary to add support for TLS to disposable keys were generated and unique to each session, and not store it on file in file system. I read about the mechanism of formation of the key for the current session in SSL/TLS - Ephemeral Diffie-Hellman. How to use it in WolfSSL library?

If possible, please give examples.
Thank you for attention.

Share

Re: Familiarity with the library

Can anybody help me please?

Share

Re: Familiarity with the library

Hi Alexander79,

Thank you for your question. I am looking into it and will have an answer for you shortly.

Regards,

Kaleb

Re: Familiarity with the library

Hi Alexander79,

For question 1:
The server is going to connect to the socket and call wolfSSL_accept() where it will wait to read 5 bytes (ssl record header). If after reading the 5 byte record header the server determines whether the connection is not a TLS connection wolfSSL_accept() will return an error code which your application can then check. At that point your application can do whatever you desire with the socket. example:

if (wolfSSL_accept(ssl) != SSL_SUCCESS)                                     
      {                                                                           
          int err = wolfSSL_get_error(ssl, 0);                                    
          char buffer[WOLFSSL_MAX_ERROR_SZ];                                      
          printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); 
          /*err_sys("SSL_accept failed");*/                                                              
      }

Question 2:
You will need to use DHE or ECDHE based cipher suite. You can set these by using wolfSSL_CTX_set_cipher_list() this function is defined in wolfssl/ssl.h. example:

if (wolfSSL_CTX_set_cipher_list(cipherSuiteCtx, suite) == SSL_SUCCESS)
      valid = 1

For negotiating the ephemeral key you will have to load a public and private key file however the ephemeral key will automatically be negotiated internally in our libraries.

Load public key:

         if (SSL_CTX_use_certificate_file(ctx, ourCert, SSL_FILETYPE_PEM)        
                                          != SSL_SUCCESS)
                         err_sys("can't load server cert file, check file and run from"      
                     " wolfSSL home dir");

Load private key:

         if (SSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM)          
                                          != SSL_SUCCESS)                        
             err_sys("can't load server private key file, check file and run "   
                 "from wolfSSL home dir");

Kind Regards,

Kaleb

Re: Familiarity with the library

Thanks for your answer.
About question 2.
1) I add certificate (wolfSSL_CTX_use_certificate_file) and private key file (wolfSSL_CTX_use_PrivateKey_file). What should I do next to use DHE?
2) What can I do with wolfSSL_CTX_set_cipher_list next?

If certificate file and the key will located in one directory with server - this is normal.
Client should not store any files (certificate, keys etc).

Share

Re: Familiarity with the library

Hi Alexander79,

1) use one of the following functions to set the DH parameters:

wolfSSL_SetTmpDH(ssl, p, sizeof(p), g, sizeof(g));

or

wolfSSL_CTX_SetTmpDH(ctx, p, sizeof(p), g, sizeof(g));

2) by setting the cipher list this tells the server what ciphers the client supports. The server will select the strongest option that it and the client both support for use of the session

Client can store certificate and keys in the same way we store them in the file wolfssl/certs_test.h if there is no file system

You can read more about these and more here:  https://www.wolfssl.com/wolfSSL/Docs-wo … rence.html

or in our API documentation here:
http://wolfssl.com/wolfSSL/Docs-wolfssl … rence.html

Kind Regards,

Kaleb

7 (edited by Alexander79 2015-08-27 13:32:49)

Re: Familiarity with the library

Don't understand, what I'm doing wrong...
Please, look at my source code, I post it down here.
On server side, function wolfSSL_accept return error, after function wolfSSL_connect at client side.

Also don't understand how to work with cipher's and certificate's, with functions wolfSSL_CTX_set_cipher_list and wolfSSL_CTX_SetTmpDH.

I was readed manuals, looked samples, but still cannot make it work...

Can you fix my source code, please?
Tell me, please, what I'm doing wrong?

There is simple echo client-server:
SERVER

#include <iostream>
#include <string>
#include <algorithm>
#include <conio.h>
#include <wolfssl/ssl.h>

#define CERT_SERVER_PATH "Certs/server-cert.pem"
#define KEY_SERVER_PATH "Certs/server-key.pem"
#define PORT 1234

#define Assert(expr) _ASSERT_EXPR((expr), _CRT_WIDE(#expr))

#define _WINSOCKAPI_
#include <Windows.h>

#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")

void Exit(WOLFSSL* ssl)
{
    std::string err_str(80, 0);

    int err = wolfSSL_get_error(ssl, 0);
    wolfSSL_ERR_error_string(err, &err_str[0]);

    std::cerr << err_str << "\n";
    Assert(false && "Error");
    exit(-1);
}

WOLFSSL_CTX* Init()
{
    WSADATA wsa_data;
    WORD version;

    version = MAKEWORD(2, 0);
    WSAStartup(version, &wsa_data);

    wolfSSL_Init();

    auto ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method());

    const char* cipher_list = "DHE-RSA-AES128-SHA256";
    if (wolfSSL_CTX_set_cipher_list(ctx, cipher_list) != SSL_SUCCESS)
        Exit(nullptr);

    return ctx;
}

void LoadCerts(WOLFSSL_CTX* ctx)
{
    if (wolfSSL_CTX_use_certificate_file(ctx, CERT_SERVER_PATH, SSL_FILETYPE_PEM) != SSL_SUCCESS)
        Exit(nullptr);

    if (wolfSSL_CTX_use_PrivateKey_file(ctx, KEY_SERVER_PATH, SSL_FILETYPE_PEM) != SSL_SUCCESS)
        Exit(nullptr);
}

int Send(WOLFSSL* ssl, const std::string& data)
{
    return wolfSSL_write(ssl, (char*)data.c_str(), data.size());
}

int Recv(WOLFSSL* ssl, std::string& data, int size)
{
    return wolfSSL_read(ssl, (char*)&data[0], size);
}

void Clean(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
{
    wolfSSL_shutdown(ssl);
    wolfSSL_free(ssl);
    wolfSSL_CTX_free(ctx);
    wolfSSL_Cleanup();
    WSACleanup();
}

int main()
{
    int yes = 1;
    SOCKET server_socket = INVALID_SOCKET;
    struct sockaddr_in sockaddr;

    WOLFSSL_CTX* ctx = nullptr;
    WOLFSSL* ssl = nullptr;

    if (!(ctx = Init()))
        Exit(nullptr);

    LoadCerts(ctx);

    server_socket = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);

    memset(&sockaddr, 0x00, sizeof(sockaddr_in));
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_port = htons(PORT);
    sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    ::setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&yes, sizeof(int));
    ::bind(server_socket, (struct sockaddr*)&sockaddr, sizeof(struct sockaddr));
    ::listen(server_socket, 1);

    std::cout << "Waiting connection...\n";
    SOCKET client_socket = ::accept(server_socket, nullptr, nullptr);
    std::cout << "Got new connection\n";

    if (!(ssl = wolfSSL_new(ctx)))
        Exit(ssl);

    wolfSSL_set_fd(ssl, client_socket);

    if (wolfSSL_accept(ssl) != SSL_SUCCESS)
        Exit(ssl);

    std::cout << "Secure socket ready\n";
    std::string data(80, 0);

    if (!Recv(ssl, data, data.size()))
        Exit(ssl);

    std::cout << "Recv: " << data << "\n";

    data.erase(std::remove(data.begin(), data.end(), '\0'), data.end());
    data += "  <---> ECHO\n";

    if (!Send(ssl, data))
        Exit(ssl);

    Clean(ssl, ctx);
    std::cout << "\nDone\n";
    _getch();
    return 0;
}

CLIENT

#include <iostream>
#include <string>
#include <algorithm>
#include <conio.h>
#include <wolfssl/ssl.h>

#define CERT_CLIENT_PATH "Certs/client-cert.pem"
#define IP "127.0.0.1"
#define PORT 1234

#define Assert(expr) _ASSERT_EXPR((expr), _CRT_WIDE(#expr))

#define _WINSOCKAPI_
#include <Windows.h>

#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")

void Exit(WOLFSSL* ssl)
{
    std::string err_str(80, 0);

    int err = wolfSSL_get_error(ssl, 0);
    wolfSSL_ERR_error_string(err, &err_str[0]);

    std::cerr << err_str << "\n";
    Assert(false && "Error");
    exit(-1);
}

WOLFSSL_CTX* Init()
{
    WSADATA wsa_data;
    WORD version;

    version = MAKEWORD(2, 0);
    WSAStartup(version, &wsa_data);

    wolfSSL_Init();

    auto ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());

    const char* cipher_list = "DHE-RSA-AES128-SHA256";
    if (wolfSSL_CTX_set_cipher_list(ctx, cipher_list) != SSL_SUCCESS)
        Exit(nullptr);

    return ctx;
}

int Send(WOLFSSL* ssl, const std::string& data)
{
    return wolfSSL_write(ssl, (char*)data.c_str(), data.size());
}

int Recv(WOLFSSL* ssl, std::string& data, int size)
{
    return wolfSSL_read(ssl, (char*)&data[0], size);
}

void Clean(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
{
    wolfSSL_shutdown(ssl);
    wolfSSL_free(ssl);
    wolfSSL_CTX_free(ctx);
    wolfSSL_Cleanup();
    WSACleanup();
}

int main()
{
    int yes = 1;
    SOCKET socket = INVALID_SOCKET;
    struct sockaddr_in sockaddr;

    WOLFSSL_CTX* ctx = nullptr;
    WOLFSSL* ssl = nullptr;

    if (!(ctx = Init()))
        Exit(nullptr);

    struct hostent* target = nullptr;

    socket = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);
    target = gethostbyname(IP);

    memset(&sockaddr, 0x00, sizeof(sockaddr_in));
    sockaddr.sin_family = AF_INET;
    ((u_long*)&sockaddr.sin_addr)[0] = ((u_long**)target->h_addr_list)[0][0];
    sockaddr.sin_port = htons(PORT);

    std::cout << "Connecting... ";
    if (::connect(socket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
        Exit(nullptr);

    if (!(ssl = wolfSSL_new(ctx)))
        Exit(ssl);

    wolfSSL_set_fd(ssl, socket);

    if (wolfSSL_connect(ssl) == SSL_SUCCESS)
        Exit(ssl);

    std::cout << " Done\n";
    std::string data = "hello";

    if (!Send(ssl, data))
        Exit(ssl);

    if (!Recv(ssl, data, data.size()))
        Exit(ssl);

    std::cout << "Respone: " << data;

    Clean(ssl, ctx);
    std::cout << "\nDone\n";
    _getch();
    return 0;
}

Share

Re: Familiarity with the library

Hi alexander79,

I can not fix your code unfortunately. I have never worked in or with C++ or C# unfortunately and cannot get your code to compile in a reasonable amount of time. What I will do is post two examples of an example client and server in our examples directory on github. You can view the code there and try to translate that into your working language/environment.

Link to client: https://github.com/wolfSSL/wolfssl-exam … ls-ecdhe.c

Link to server: https://github.com/wolfSSL/wolfssl-exam … ls-ecdhe.c

I am also including a diff of the base client with the ecdh additions so you can see what changes were made:

Client diff:

--- client-tls.c    2015-08-28 14:02:17.000000000 -0600
+++ client-tls-ecdhe.c    2015-08-28 13:44:15.000000000 -0600
@@ -23,12 +23,14 @@
 #include    <string.h>
 #include    <errno.h>
 #include    <arpa/inet.h>
+#include    <wolfssl/options.h>
 #include    <wolfssl/ssl.h>          /* wolfSSL security library */
+#include    <wolfssl/test.h>
 
 #define MAXDATASIZE  4096           /* maximum acceptable amount of data */
 #define SERV_PORT    11111          /* define default port number */
 
-const char* cert = "../certs/ca-cert.pem";
+const char* cert = "../certs/server-ecc.pem";
 
 /*
  * clients initial contact with server. (socket to connect, security layer)
@@ -68,6 +70,10 @@
     WOLFSSL_CTX* ctx;
     WOLFSSL*     ssl;    /* create WOLFSSL object */
     int         ret = 0;
+    const char* myCert        = "../certs/client-ecc-cert.pem";
+    const char* myKey         = "../certs/ecc-client-key.pem";
+    char* cipherList          = "ECDHE-ECDSA-CHACHA20-POLY1305";
+    char buffer[WOLFSSL_MAX_ERROR_SZ];
 
     wolfSSL_Init();      /* initialize wolfSSL */
 
@@ -77,11 +83,25 @@
         return EXIT_FAILURE;
     }
 
+    if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
+            err_sys("client can't set cipher list 1");
+
+    if (wolfSSL_CTX_use_certificate_chain_file(ctx, myCert)
+                                                               != SSL_SUCCESS)
+            err_sys("can't load client cert file, check file and run from"
+                    " wolfSSL home dir");
+
+    if (wolfSSL_CTX_use_PrivateKey_file(ctx, myKey, SSL_FILETYPE_PEM)
+                                         != SSL_SUCCESS)
+            err_sys("can't load client private key file, check file and run "
+                    "from wolfSSL home dir");
+
     /* load CA certificates into wolfSSL_CTX. which will verify the server */
     if (wolfSSL_CTX_load_verify_locations(ctx, cert, 0) != SSL_SUCCESS) {
         printf("Error loading %s. Please check the file.\n", cert);
         return EXIT_FAILURE;
     }
+
     if ((ssl = wolfSSL_new(ctx)) == NULL) {
         printf("wolfSSL_new error.\n");
         return EXIT_FAILURE;
@@ -91,8 +111,14 @@
     ret = wolfSSL_connect(ssl);
     if (ret == SSL_SUCCESS) {
         ret = ClientGreet(sock, ssl);
+    } else {
+        printf("Failure:");
+        ret = wolfSSL_get_error(ssl, 0);
+        printf(" ret = %d", ret);
+        printf(" %s\n", wolfSSL_ERR_error_string(ret, buffer));
     }
 
+
     /* frees all data before client termination */
     wolfSSL_free(ssl);
     wolfSSL_CTX_free(ctx);

Server diff:

--- server-tls.c    2015-08-28 14:05:27.000000000 -0600
+++ server-tls-ecdhe.c    2015-08-28 14:06:19.000000000 -0600
@@ -32,6 +32,7 @@
 #include <netinet/in.h>
 #include <stdlib.h>
 #include <errno.h>
+#include <wolfssl/options.h>
 
 /* include the wolfSSL library for our TLS 1.2 security */
 #include <wolfssl/ssl.h>
@@ -124,6 +125,7 @@
     int ret      = 0; /* Return value */
     /* Server and client socket address structures */
     struct sockaddr_in serverAddr, clientAddr;
+    char* cipherList = "ECDHE-ECDSA-CHACHA20-POLY1305";
 
     /* Initialize wolfSSL */
     wolfSSL_Init();
@@ -141,7 +143,7 @@
     }
 
     /* Load server certificate into WOLFSSL_CTX */
-    if (wolfSSL_CTX_use_certificate_file(ctx, "../certs/server-cert.pem",
+    if (wolfSSL_CTX_use_certificate_file(ctx, "../certs/server-ecc.pem",
                 SSL_FILETYPE_PEM) != SSL_SUCCESS) {
         fprintf(stderr, "Error loading certs/server-cert.pem, please check"
                 "the file.\n");
@@ -149,13 +151,16 @@
     }
 
     /* Load server key into WOLFSSL_CTX */
-    if (wolfSSL_CTX_use_PrivateKey_file(ctx, "../certs/server-key.pem",
+    if (wolfSSL_CTX_use_PrivateKey_file(ctx, "../certs/ecc-key.pem",
                 SSL_FILETYPE_PEM) != SSL_SUCCESS) {
         fprintf(stderr, "Error loading certs/server-key.pem, please check"
                 "the file.\n");
         return EXIT_FAILURE;
     }
 
+    if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
+            printf("client can't set cipher list 1");
+
     /* Initialize the server address struct to zero */
     memset((char *)&serverAddr, 0, sizeof(serverAddr));
 

Re: Familiarity with the library

I' use as example this source code:
https://github.com/wolfSSL/wolfssl-exam … ls-ecdhe.c

But function wolfSSL_CTX_use_certificate_file() return error while trying parse file server-ecc.pem from WolfSSL library.
I looked inside this function, it's open and read file, but there is some error while parsing.

Share

10 (edited by Kaleb J. Himes 2015-08-31 12:29:53)

Re: Familiarity with the library

Hi Alexander79,

But function wolfSSL_CTX_use_certificate_file() return error while trying parse file server-ecc.pem from WolfSSL library.
I looked inside this function, it's open and read file, but there is some error while parsing.

There are two potential reasons that function would return an error if you use the certificate in our libraries. Either the certificate is not in the correct location or it is expired. Check the dates on the certificate you're using and make sure today's date falls inbetween the ASN before and after date. For example today is Aug 31 2015 so a cert with the following dates is not expired. (Also ensure your computer has the correct date set as our libraries will use your systems date to check expiration on a certificate).

            Not Before: May  7 18:21:01 2015 GMT
            Not After : Jan 31 18:21:01 2018 GMT

Secondly you may have the certificate in a different location then I did. Make sure the path is correct.
This line in the file may need to have a different path then

../certs/server-ecc.pem

depending on where
your project is being built.

if (wolfSSL_CTX_use_certificate_file(ctx, "../certs/server-ecc.pem",

I updated the example this morning https://github.com/wolfSSL/wolfssl-exam … ls-ecdhe.c to allow for debugging also. If you add

DEBUG_WOLFSSL

to your pre-processor definitions you should get more meaningful error codes back. Error codes can be viewed in the following locations:

If your project returns an error between -100 and -300 see wolfssl/wolfssl/wolfcrypt/error-crypt.h
If project returns an error between -301 and -501 see wolfssl/wolfssl/error-ssl.h

Regards,

Kaleb

Re: Familiarity with the library

Hi Alexander79,

I had not heard back from you in a day or two. I was just checking in to see if you were able to get those example projects working. Let me know if there is anything else.

Kind Regards,

Kaleb