It is strange that HP's code sample for SSL/BIO programming
http://h71000.www7.hp.com/doc/83final/ba554_90007/ch05s03.html
http://h71000.www7.hp.com/doc/83final/ba554_90007/ch05s04.html
readily compile without error in my Xperia ARM with Fedora 20 and 21 armhfp image.
In Fedora 20 x86, the same code got error about converting char to some struct .
Compile them with
gcc -lssl -lcrypto client.c . You need to yum install openssl-devel first.
Generate cert and key with openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
client.c
#include
#include
#include
#include
#include
#ifdef __VMS
#include
#include
#include
#else
#include
#include
#include
#include
#endif
#include
#include
#include
#define RETURN_NULL(x) \
if ((x) == NULL) \
exit(1)
#define RETURN_ERR(err, s) \
if ((err) == -1) { \
perror(s); \
exit(1); \
}
#define RETURN_SSL(err) \
if ((err) == -1) { \
ERR_print_errors_fp(stderr); \
exit(1); \
}
static int verify_callback(int ok, X509_STORE_CTX *ctx);
#define RSA_CLIENT_CERT "client.crt"
#define RSA_CLIENT_KEY "client.key"
#define ON 1
#define OFF 0
void main() {
int err;
int sock;
struct sockaddr_in server_addr;
char *str;
char buf[4096];
char hello[80];
SSL_CTX *ctx;
SSL *ssl;
SSL_METHOD *meth;
X509 *server_cert;
EVP_PKEY *pkey;
short int s_port = 5555;
const char *s_ipaddr = "127.0.0.1";
/*----------------------------------------------------------*/
printf("Message to be sent to the SSL server: ");
fgets(hello, 80, stdin);
/* Load encryption & hashing algorithms for the SSL program */
SSL_library_init();
/* Load the error strings for SSL & CRYPTO APIs */
SSL_load_error_strings();
/* Create an SSL_METHOD structure (choose an SSL/TLS protocol version) */
meth = SSLv3_method();
/* Create an SSL_CTX structure */
ctx = SSL_CTX_new(meth);
RETURN_NULL(ctx);
/* ------------------------------------------------------------- */
/* Set up a TCP socket */
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
RETURN_ERR(sock, "socket");
memset(&server_addr, '\0', sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(s_port); /* Server Port number */
server_addr.sin_addr.s_addr = inet_addr(s_ipaddr); /* Server IP */
/* Establish a TCP/IP connection to the SSL client */
err = connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
RETURN_ERR(err, "connect");
/* ----------------------------------------------- */
/* An SSL structure is created */
ssl = SSL_new(ctx);
RETURN_NULL(ssl);
/* Assign the socket into the SSL structure (SSL and socket without BIO) */
SSL_set_fd(ssl, sock);
/* Perform SSL Handshake on the SSL client */
err = SSL_connect(ssl);
RETURN_SSL(err);
/* Informational output (optional) */
printf("SSL connection using %s\n", SSL_get_cipher(ssl));
/* Get the server's certificate (optional) */
server_cert = SSL_get_peer_certificate(ssl);
if (server_cert != NULL) {
printf("Server certificate:\n");
str = X509_NAME_oneline(X509_get_subject_name(server_cert), 0, 0);
RETURN_NULL(str);
printf("\t subject: %s\n", str);
free(str);
str = X509_NAME_oneline(X509_get_issuer_name(server_cert), 0, 0);
RETURN_NULL(str);
printf("\t issuer: %s\n", str);
free(str);
X509_free(server_cert);
} else
printf("The SSL server does not have certificate.\n");
/*-------- DATA EXCHANGE - send message and receive reply. -------*/
/* Send data to the SSL server */
err = SSL_write(ssl, hello, strlen(hello));
RETURN_SSL(err);
/* Receive data from the SSL server */
err = SSL_read(ssl, buf, sizeof(buf) - 1);
RETURN_SSL(err);
buf[err] = '\0';
printf("Received %d chars:'%s'\n", err, buf);
/*--------------- SSL closure ---------------*/
/* Shutdown the client side of the SSL connection */
err = SSL_shutdown(ssl);
RETURN_SSL(err);
/* Terminate communication on a socket */
err = close(sock);
RETURN_ERR(err, "close");
/* Free the SSL structure */
SSL_free(ssl);
/* Free the SSL_CTX structure */
SSL_CTX_free(ctx);
}
server.c
#include
#include
#include
#include
#include
#include
#ifdef __VMS
#include
#include
#include
#include
#else
#include
#include
#include
#include
#endif
#include
#include
#include
#define RSA_SERVER_CERT "server.crt"
#define RSA_SERVER_KEY "server.key"
#define ON 1
#define OFF 0
#define RETURN_NULL(x) \
if ((x) == NULL) \
exit(1)
#define RETURN_ERR(err, s) \
if ((err) == -1) { \
perror(s); \
exit(1); \
}
#define RETURN_SSL(err) \
if ((err) == -1) { \
ERR_print_errors_fp(stderr); \
exit(1); \
}
void main() {
int err;
int listen_sock;
int sock;
struct sockaddr_in sa_serv;
struct sockaddr_in sa_cli;
size_t client_len;
char *str;
char buf[4096];
SSL_CTX *ctx;
SSL *ssl;
SSL_METHOD *meth;
X509 *client_cert = NULL;
short int s_port = 5555;
/*----------------------------------------------------------------*/
/* Load encryption & hashing algorithms for the SSL program */
SSL_library_init();
/* Load the error strings for SSL & CRYPTO APIs */
SSL_load_error_strings();
/* Create a SSL_METHOD structure (choose a SSL/TLS protocol version) */
meth = SSLv3_method();
/* Create a SSL_CTX structure */
ctx = SSL_CTX_new(meth);
if (!ctx) {
ERR_print_errors_fp(stderr);
exit(1);
}
/* Load the server certificate into the SSL_CTX structure */
if (SSL_CTX_use_certificate_file(ctx, RSA_SERVER_CERT, SSL_FILETYPE_PEM) <=
0) {
ERR_print_errors_fp(stderr);
exit(1);
}
/* Load the private-key corresponding to the server certificate */
if (SSL_CTX_use_PrivateKey_file(ctx, RSA_SERVER_KEY, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(1);
}
/* Check if the server certificate and private-key matches */
if (!SSL_CTX_check_private_key(ctx)) {
fprintf(stderr, "Private key does not match the certificate public key\n");
exit(1);
}
/* ----------------------------------------------- */
/* Set up a TCP socket */
listen_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
RETURN_ERR(listen_sock, "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(s_port); /* Server Port number */
err = bind(listen_sock, (struct sockaddr *)&sa_serv, sizeof(sa_serv));
RETURN_ERR(err, "bind");
/* Wait for an incoming TCP connection. */
err = listen(listen_sock, 5);
RETURN_ERR(err, "listen");
client_len = sizeof(sa_cli);
/* Socket for a TCP/IP connection is created */
sock = accept(listen_sock, (struct sockaddr *)&sa_cli, &client_len);
RETURN_ERR(sock, "accept");
close(listen_sock);
printf("Connection from %lx, port %x\n", sa_cli.sin_addr.s_addr,
sa_cli.sin_port);
/* ----------------------------------------------- */
/* TCP connection is ready. */
/* A SSL structure is created */
ssl = SSL_new(ctx);
RETURN_NULL(ssl);
/* Assign the socket into the SSL structure (SSL and socket without BIO) */
SSL_set_fd(ssl, sock);
/* Perform SSL Handshake on the SSL server */
err = SSL_accept(ssl);
RETURN_SSL(err);
/* Informational output (optional) */
printf("SSL connection using %s\n", SSL_get_cipher(ssl));
/*------- DATA EXCHANGE - Receive message and send reply. -------*/
/* Receive data from the SSL client */
err = SSL_read(ssl, buf, sizeof(buf) - 1);
RETURN_SSL(err);
buf[err] = '\0';
printf("Received %d chars:'%s'\n", err, buf);
/* Send data to the SSL client */
err = SSL_write(ssl, "This message is from the SSL server",
strlen("This message is from the SSL server"));
RETURN_SSL(err);
/*--------------- SSL closure ---------------*/
/* Shutdown this side (server) of the connection. */
err = SSL_shutdown(ssl);
RETURN_SSL(err);
/* Terminate communication on a socket */
err = close(sock);
RETURN_ERR(err, "close");
/* Free the SSL structure */
SSL_free(ssl);
/* Free the SSL_CTX structure */
SSL_CTX_free(ctx);
}