Friday, January 25, 2008

SSL OpenSSL with Visual C++

Today I have another solution to work with SSL from Visual C++ using OpenSSL.

Well, the OpenSSL compilation was described before, so I can’t described here again. Click here if you want to know more about OpenSSL compilation

To work with SSL is easy with OpenSSL, really is a layer to add to our Windows Socket Projects.

The steps you’ll have to do are:

1. Add the OpenSSL libs (libeay32.lib, ssleay32.lib) to your project in Link options. Well, and touch some different options in this sheet, download the projects to see more about this point.
2. Add the OpenSSL header files to your main cpp.
3. And the OpenSSL SSL commands.

Here is the sample server code:


#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <winsock.h>

#include <openssl/rsa.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>


/* certificates root path */
#define HOME "./"
/* certificate and private key */
#define CERTF HOME "micert.pem"
#define KEYF HOME "mikey.key"

/* checking fuctions */
#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }

int err;


void main ()
{
int err;
int listen_sd;
int sd;
struct sockaddr_in sa_serv;
struct sockaddr_in sa_cli;
int client_len;
SSL_CTX* ctx;
SSL* ssl;
X509* client_cert;
char* str;
char buf [4096];
SSL_METHOD *meth;
WORD wVersionRequested;
WSADATA wsaData;

/* SSL init. Keep the Key and the certificate in the context. */

SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
meth = SSLv23_server_method();
ctx = SSL_CTX_new (meth);
if (!ctx) {
    ERR_print_errors_fp(stderr);
    exit(2);
}

if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {
    ERR_print_errors_fp(stderr);
    exit(3);
}
if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
    ERR_print_errors_fp(stderr);
    exit(4);
}

if (!SSL_CTX_check_private_key(ctx)) {
    fprintf(stderr,"The private Key don’t match with the certificate\n");
    exit(5);
}

/*****************************************************/
/*                                                   */
/* Socket Initialitation */
/*                                                   */
/*****************************************************/



wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup(wVersionRequested, &wsaData );
if ( err != 0 )
{
    printf("///Error in WSAStartup//%d\n",err);
    exit(err);

}

listen_sd = socket (AF_INET, SOCK_STREAM, 0);
printf("socket() return 0x%X (%d)\n", listen_sd, listen_sd);
CHK_ERR(listen_sd, "socket");

memset (&sa_serv, '\0', sizeof(sa_serv));
sa_serv.sin_family = AF_INET;
sa_serv.sin_addr.s_addr = INADDR_ANY;
sa_serv.sin_port = htons (9000); /* Server listen Port */

err = bind(listen_sd, (struct sockaddr*) &sa_serv,
sizeof (sa_serv));
CHK_ERR(err, "bind");

/*****************************************************/
/*                                                   */
/* setting listening */
/*                                                   */
/*****************************************************/

printf("listening\n");
err = listen (listen_sd, 5); CHK_ERR(err, "listen");

client_len = sizeof(sa_cli);
sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len);
CHK_ERR(sd, "accept");
closesocket (listen_sd);

printf ("Connection from %lx, port %x\n",
sa_cli.sin_addr.s_addr, sa_cli.sin_port);

/*****************************************************/
/*                                                   */
/* preparing SSL with the recived socket */
/*                                                   */
/*****************************************************/


ssl = SSL_new (ctx); CHK_NULL(ssl);
SSL_set_fd (ssl, sd);
err = SSL_accept (ssl); CHK_SSL(err);

/* Showing cipher - optional */

printf ("SSL connection using %s\n", SSL_get_cipher (ssl));

/* Get Client cert, if exist - optional */

client_cert = SSL_get_peer_certificate (ssl);
if (client_cert != NULL) {
    printf ("Client Certificate:\n");

    str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
    CHK_NULL(str);
    printf ("\t subject: %s\n", str);
    OPENSSL_free (str);

    str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0);
    CHK_NULL(str);
    printf ("\t issuer: %s\n", str);
    OPENSSL_free (str);

    /* Here we could check all we want about client certificate. */

    X509_free (client_cert);
} else
    printf ("The Client hasn’t certificate.\n");

/* Exchanging messages */

err = SSL_read (ssl, buf, sizeof(buf) - 1); CHK_SSL(err);
buf[err] = '\0';
printf ("Read %d characters:'%s'\n", err, buf);

err = SSL_write (ssl, "I’m listening.", strlen("I’m listening.")); CHK_SSL(err);

/* Freeing resources */

closesocket (sd);
SSL_free (ssl);
SSL_CTX_free (ctx);
}

Bellow is the SSL Client Code.

#include <stdio.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <winsock.h>

#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>


#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }

void main ()
{
int err=0;
int sd;
struct sockaddr_in sa;
SSL_CTX* ctx;
SSL* ssl;
X509* scert;
char* txt;
char buff [4096];
SSL_METHOD *meth;
WORD wVersionRequested;
WSADATA wsaData;
SSLeay_add_ssl_algorithms();
meth = SSLv2_client_method();
SSL_load_error_strings();
ctx = SSL_CTX_new (meth); CHK_NULL(ctx);

CHK_SSL(err);

/*****************************************************/
/*                                                   */
/* Socket Init and connecting. */
/*                                                   */
/*****************************************************/


wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup(wVersionRequested, &wsaData );
if ( err != 0 )
{
    printf("///Error in WSAStartup //%d\n",err);
    exit(1);

}


sd = socket (AF_INET, SOCK_STREAM, 0);
CHK_ERR(sd, "socket");

memset (&sa, '\0', sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr ("127.0.0.1"); /* Server Ip */
sa.sin_port = htons (9000); /* Server port */

err = connect(sd, (struct sockaddr*) &sa,
sizeof(sa)); CHK_ERR(err, "connection");

/*****************************************************/
/*                                                   */
/* Starting SSL connection */
/*                                                   */
/*****************************************************/

ssl = SSL_new (ctx); CHK_NULL(ssl);
SSL_set_fd (ssl, sd);
err = SSL_connect (ssl); CHK_SSL(err);

/* Get the cipher - optional */

printf ("SSL connection using %s\n", SSL_get_cipher (ssl));

/* Get Server certificate - optional */

scert = SSL_get_peer_certificate (ssl); CHK_NULL(scert);
printf ("Server Certificate:\n");

txt = X509_NAME_oneline (X509_get_subject_name (scert),0,0);
CHK_NULL(txt);
printf ("\t Subject: %s\n", txt);
OPENSSL_free (txt);

txt = X509_NAME_oneline (X509_get_issuer_name (scert),0,0);
CHK_NULL(txt);
printf ("\t Issuer: %s\n", txt);
OPENSSL_free (txt);

/* Here we can check what we wanted about the Server certificate */

X509_free (scert);

/*****************************************************/
/*                                                   */
/* Exchanging messages */
/*                                                   */
/*****************************************************/

err = SSL_write (ssl, "Is someone there?", strlen("Is someone there?")); CHK_SSL(err);

err = SSL_read (ssl, buff, sizeof(buff) - 1); CHK_SSL(err);
buff[err] = '\0';
printf ("Read %d characters:'%s'\n", err, buff);
SSL_shutdown (ssl); /* sending the SSL/TLS end*/

/* Freeing resources */

closesocket (sd);
SSL_free (ssl);
SSL_CTX_free (ctx);
}


If you want to download the client and Server projects, click here. Source Files

2 comments:

Izhar Ul Islam Khan said...

In client code there is no certificate provided.I think becuase of that i am getting this error "The client hasn't certificate".

Kindly post the solution

Izhar Ul Islam Khan said...
This comment has been removed by the author.