Hi All,
I am a new to SSL. I have installed openssl and using the SSL APIs , I
have written a small client - server
program in C, but SSL_connect fails from client end and SSL_accept fails
from server. I have generated the root CA certificate, which I have used
to sign both the client and server certificate.
I have attached the following files sclient.c, sserver.c ,
client_signed.pem , server_signed.pem and cacert.pem .
Please find the attachment.
Kindly guide me to get the SSL negotations done.
Thank you
naveen
-----BEGIN CERTIFICATE-----
MIIDfzCCAmegAwIBAgIJAN1cwgk8+EEdMA0GCSqGSIb3DQEBBAUAMHYxCzAJBgNV
BAMTAkNBMRIwEAYDVQQIEwlrYXJuYXRha2ExCzAJBgNVBAYTAklOMR8wHQYJKoZI
hvcNAQkBFhBjYUBleGFtcGxlY2Eub3JnMSUwIwYDVQQKExxSb290IENlcnRpZmlj
YXRpb24gQXV0aG9yaXR5MB4XDTA4MTExMzE5MTQxOVoXDTA4MTIxMzE5MTQxOVow
djELMAkGA1UEAxMCQ0ExEjAQBgNVBAgTCWthcm5hdGFrYTELMAkGA1UEBhMCSU4x
HzAdBgkqhkiG9w0BCQEWEGNhQGV4YW1wbGVjYS5vcmcxJTAjBgNVBAoTHFJvb3Qg
Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
ggEKAoIBAQCrxg3yT84mBh284/HoeisVV2Z3x7S0SxGIgkKkpfXeTyaaLawa/BEw
Qt8upF6VjBxkAp72sZib3qxBgMlXqiKttdmAmodISDIeRZkrS6XI3QTg0O/ZbzBj
zdpMf+ZgFXMULlxj/6Q9/FJQJMfLf9sSfpbn+Wq3aRF2gCZarWyJSSm3SVCdqlsT
uu8ysOIo3coPQxaS4ETORPErQchy0wlPMbBQDU6chBVTy+S4KTAUxAfDHh1zm+PH
w7xEi7sH1lkP78jbx5wxUia5YyZzn06i+UHfPGWfEiCIxRKfrVx40peXoXjLmTrr
vSocpruORaDQuU/gqlcpqsYMsYeZkI9xAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8w
DQYJKoZIhvcNAQEEBQADggEBAHWhU1w0hlHG6nHSJe/FkXkD1WrP/UEfGDp3jk8O
EHrOwdHGcnP5t5r0FArjWurYRow2bF9x5AaxG3GnJ4I/PhUK4yGcsLjVluFdBZ3T
vuyULTao5VUA/Dy+jC0cE3VQY4jI17bG3/2A4BQh48hEdsap1Y4G8qBAuOiK7y2E
bJLTCATRnS7oEFWc1iLVNj1iurcFH1P9ctb85Bq4kI1Q1+XgM0RHXL02vP5YFqQb
KKFgmsdi78oTJum5GQFIBVS9MMvoFL1lxBYdnHdneM5e4biNJVIlusGHaa4/ciCP
EkHb/aetpux9O96fVn+n8AAhfowX7nkPtSNRDvFA9f2PSOU=
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 2 (0x2)
Signature Algorithm: md5WithRSAEncryption
Issuer: CN=CA, ST=karnataka, C=IN/[EMAIL PROTECTED], O=Root
Certification Authority
Validity
Not Before: Nov 13 19:33:07 2008 GMT
Not After : Nov 13 19:33:07 2009 GMT
Subject: C=IN, ST=karnataka, O=Internet Widgits Pty Ltd, CN=localhost
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:d1:ef:48:d3:00:29:75:0a:7e:eb:8e:88:13:80:
1a:f4:ce:e7:8e:20:e7:bd:25:85:fd:1b:0c:b0:68:
f9:e0:98:5f:98:d1:52:b6:61:4d:a2:e4:df:c7:d5:
36:5e:62:40:5b:c1:29:bb:82:ab:a0:02:a6:11:bc:
7f:9a:06:20:3c:a7:0b:14:7c:ab:32:1f:93:d4:9b:
98:44:47:9e:8d:e0:83:b3:53:89:5e:b8:78:37:6c:
81:6e:4e:d1:3e:44:33:1e:43:b2:5a:b6:9a:32:6e:
f9:69:79:23:21:61:cd:1f:c7:ab:95:ea:05:d9:6d:
55:3b:0f:70:8c:d3:be:1d:61
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Signature Algorithm: md5WithRSAEncryption
38:a0:c8:ad:53:86:b2:37:36:f7:6e:90:e7:76:53:c3:97:c2:
da:b5:97:0f:7e:95:be:4e:6a:11:ae:af:8b:c6:2c:35:9f:db:
95:36:36:c8:e1:b0:f6:e7:77:f0:24:cc:b6:15:49:b7:17:ba:
52:83:0e:c6:71:5f:34:2b:7a:d1:a0:66:dd:f6:de:67:9d:a6:
c1:66:b3:e4:50:82:a9:99:82:66:6e:22:ca:f7:3a:ae:31:95:
35:55:85:04:ae:3b:d4:41:7c:fb:fa:de:b5:ba:29:0c:92:a4:
eb:dd:71:24:bb:4b:4f:77:04:77:a7:18:8f:7a:27:4c:3f:d9:
74:bd:43:55:36:19:b7:0d:c0:86:8e:02:41:74:31:06:c6:c5:
80:53:de:76:1e:93:61:11:89:e0:63:f7:13:be:0c:20:d2:66:
d6:a7:78:a2:4c:b9:9e:56:ed:a8:3a:a7:d7:d7:75:71:c5:d1:
a1:b0:71:99:3f:99:84:59:5e:2d:cd:5b:32:40:54:85:33:e3:
0c:42:bf:32:06:73:c9:86:89:7a:3a:dc:6f:92:34:c1:d3:47:
dd:50:2e:8d:96:43:0b:39:b3:56:84:c4:ad:7f:39:ba:44:08:
f2:5c:4c:26:a3:14:02:28:89:a2:41:6d:4c:93:dd:d7:44:b0:
41:00:23:c3
-----BEGIN CERTIFICATE-----
MIIC0jCCAbqgAwIBAgIBAjANBgkqhkiG9w0BAQQFADB2MQswCQYDVQQDEwJDQTES
MBAGA1UECBMJa2FybmF0YWthMQswCQYDVQQGEwJJTjEfMB0GCSqGSIb3DQEJARYQ
Y2FAZXhhbXBsZWNhLm9yZzElMCMGA1UEChMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1
dGhvcml0eTAeFw0wODExMTMxOTMzMDdaFw0wOTExMTMxOTMzMDdaMFgxCzAJBgNV
BAYTAklOMRIwEAYDVQQIEwlrYXJuYXRha2ExITAfBgNVBAoTGEludGVybmV0IFdp
ZGdpdHMgUHR5IEx0ZDESMBAGA1UEAxMJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEB
AQUAA4GNADCBiQKBgQDR70jTACl1Cn7rjogTgBr0zueOIOe9JYX9GwywaPngmF+Y
0VK2YU2i5N/H1TZeYkBbwSm7gqugAqYRvH+aBiA8pwsUfKsyH5PUm5hER56N4IOz
U4leuHg3bIFuTtE+RDMeQ7JatpoybvlpeSMhYc0fx6uV6gXZbVU7D3CM074dYQID
AQABow0wCzAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBBAUAA4IBAQA4oMitU4ayNzb3
bpDndlPDl8LatZcPfpW+TmoRrq+Lxiw1n9uVNjbI4bD253fwJMy2FUm3F7pSgw7G
cV80K3rRoGbd9t5nnabBZrPkUIKpmYJmbiLK9zquMZU1VYUErjvUQXz7+t61uikM
kqTr3XEku0tPdwR3pxiPeidMP9l0vUNVNhm3DcCGjgJBdDEGxsWAU952HpNhEYng
Y/cTvgwg0mbWp3iiTLmeVu2oOqfX13VxxdGhsHGZP5mEWV4tzVsyQFSFM+MMQr8y
BnPJhol6OtxvkjTB00fdUC6NlkMLObNWhMStfzm6RAjyXEwmoxQCKImiQW1Mk93X
RLBBACPD
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 4 (0x4)
Signature Algorithm: md5WithRSAEncryption
Issuer: CN=CA, ST=karnataka, C=IN/[EMAIL PROTECTED], O=Root
Certification Authority
Validity
Not Before: Nov 13 19:43:58 2008 GMT
Not After : Nov 13 19:43:58 2009 GMT
Subject: C=IN, ST=karnataka, O=Internet Widgits Pty Ltd, CN=localhost
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:c7:06:65:ce:07:a5:fc:44:d8:7b:dc:f6:e9:57:
0f:47:98:22:6a:70:f9:27:50:ac:db:fe:ff:44:ed:
e8:09:b8:e2:22:29:4a:f5:6d:a5:c0:f9:13:29:01:
c5:47:9b:d2:a3:ce:8d:04:cd:20:88:ef:f0:fc:04:
82:06:50:89:6a:6d:5e:a7:02:97:6d:5e:50:86:59:
50:1f:f9:e9:2f:71:af:ba:79:2b:49:7c:48:cb:86:
1d:cc:7e:63:13:0e:61:27:d9:70:0f:2d:e9:5a:94:
89:ba:7f:c1:59:35:29:c3:6b:95:bb:60:3d:48:16:
be:46:92:c4:04:ef:49:92:91
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Signature Algorithm: md5WithRSAEncryption
3e:83:60:32:da:c6:a9:fa:bc:97:6a:bc:48:0b:94:03:44:87:
79:b6:06:31:b7:70:a3:aa:65:40:5e:c2:94:b3:60:3c:15:28:
2e:71:dd:de:41:a6:41:37:15:f3:08:87:87:f1:c6:97:75:5d:
2b:5f:e8:ff:92:d9:9a:95:fe:3a:43:2b:e5:b9:6f:3e:bd:42:
c7:4e:b6:65:3b:e5:51:fd:65:ff:4a:11:cf:cd:45:f8:03:d7:
82:6a:02:8b:7e:03:48:4e:ab:0f:fe:3d:9f:ce:2d:c5:ac:ca:
5b:9b:42:8d:4f:13:fe:fc:4b:db:a4:c8:c4:ad:14:1d:a8:12:
eb:fb:4e:4a:44:47:35:a4:44:30:9e:73:d4:41:00:87:50:53:
8c:a8:c1:fb:70:a1:3e:10:ee:a7:47:bb:4b:19:ba:96:ae:88:
db:5a:3a:f8:85:51:5e:ba:1f:33:4a:79:ce:2e:d6:e4:be:c1:
a1:48:ec:bf:63:4d:2b:a8:93:b6:bb:76:bd:e0:52:ff:1b:fe:
d6:7d:1c:38:82:f8:86:ae:3f:bb:90:2d:a8:40:c6:ca:22:05:
69:6c:31:41:e6:81:36:fd:a7:92:ec:e6:99:7a:5d:7c:ba:0d:
0f:39:e0:fe:72:68:54:a1:cc:5c:c6:1c:1a:28:f0:ce:d3:4b:
ac:4b:2f:b1
-----BEGIN CERTIFICATE-----
MIIC0jCCAbqgAwIBAgIBBDANBgkqhkiG9w0BAQQFADB2MQswCQYDVQQDEwJDQTES
MBAGA1UECBMJa2FybmF0YWthMQswCQYDVQQGEwJJTjEfMB0GCSqGSIb3DQEJARYQ
Y2FAZXhhbXBsZWNhLm9yZzElMCMGA1UEChMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1
dGhvcml0eTAeFw0wODExMTMxOTQzNThaFw0wOTExMTMxOTQzNThaMFgxCzAJBgNV
BAYTAklOMRIwEAYDVQQIEwlrYXJuYXRha2ExITAfBgNVBAoTGEludGVybmV0IFdp
ZGdpdHMgUHR5IEx0ZDESMBAGA1UEAxMJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEB
AQUAA4GNADCBiQKBgQDHBmXOB6X8RNh73PbpVw9HmCJqcPknUKzb/v9E7egJuOIi
KUr1baXA+RMpAcVHm9Kjzo0EzSCI7/D8BIIGUIlqbV6nApdtXlCGWVAf+ekvca+6
eStJfEjLhh3MfmMTDmEn2XAPLelalIm6f8FZNSnDa5W7YD1IFr5GksQE70mSkQID
AQABow0wCzAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBBAUAA4IBAQA+g2Ay2sap+ryX
arxIC5QDRId5tgYxt3CjqmVAXsKUs2A8FSgucd3eQaZBNxXzCIeH8caXdV0rX+j/
ktmalf46QyvluW8+vULHTrZlO+VR/WX/ShHPzUX4A9eCagKLfgNITqsP/j2fzi3F
rMpbm0KNTxP+/EvbpMjErRQdqBLr+05KREc1pEQwnnPUQQCHUFOMqMH7cKE+EO6n
R7tLGbqWrojbWjr4hVFeuh8zSnnOLtbkvsGhSOy/Y00rqJO2u3a94FL/G/7WfRw4
gviGrj+7kC2oQMbKIgVpbDFB5oE2/aeS7OaZel18ug0POeD+cmhUocxcxhwaKPDO
00usSy+x
-----END CERTIFICATE-----
#include "common.h"
#include "client.h"
BIO *bio_err=0;
int berr_exit(string)
char *string;
{
BIO_printf(bio_err,"%s\n",string);
ERR_print_errors(bio_err);
exit(0);
}
void initialize()
{
SSL_library_init(); /* Registers all ciphers and hash
algorithms used in SSL APIs */
SSL_load_error_strings(); /* Loads error strings for SSL APIs as
well as for Crypto APIs */
bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
}
void setup_client_credentials(SSL_CTX *ctx)
{
/* To load a certificate into the SSL_CTX structure */
if (SSL_CTX_use_certificate_file(ctx, CLIENT_CERT,
SSL_FILETYPE_PEM) <= 0) {
printf("\n Couldn't client certificate file \n");
ERR_print_errors(bio_err); /*ERR_print_errors_fp(stderr)*/
exit(1);
}
printf("\n Loaded the Client certificate \n");
/* To load the client private-key into the SSL context */
if (SSL_CTX_use_PrivateKey_file(ctx, CLIENT_KEY,
SSL_FILETYPE_PEM) <= 0) {
printf("\n Couldn't client key file \n");
ERR_print_errors(bio_err); /*ERR_print_errors_fp(stderr)*/
exit(1);
}
printf("\n Loaded the Client Private key \n");
}
void setup_client_CA_credentials(SSL_CTX *ctx)
{
/* To load a CA certificate into the SSL_CTX structure */
if (!SSL_CTX_load_verify_locations(ctx,CA_CERT,CA_PATH)) {
printf("\n Couldn't read CA list \n");
ERR_print_errors(bio_err); /* ERR_print_errors_fp(stderr)*/
exit(1);
}
printf("\n Loaded the CA certificate \n");
}
int client_sock()
{
int sock;
struct sockaddr_in Addr;
if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
berr_exit("Couldn't create socket");
printf("\n Created Sockets \n");
Addr.sin_family = AF_INET;/* IPV4 address domain*/
Addr.sin_port = htons(PORT);
Addr.sin_addr.s_addr = inet_addr("172.16.8.70");
if(connect(sock,(struct sockaddr *)&Addr,sizeof(Addr))<0)
berr_exit("Couldn't connect socket");
printf("\n Connect was success full \n");
return sock;
}
/* Check that the common name matches the host name*/
void Check_Common_name(SSL *ssl,char *host)
{
X509 *peer;
char peer_CN[256];
/*Check the common name*/
peer=SSL_get_peer_certificate(ssl);
X509_NAME_get_text_by_NID(X509_get_subject_name(peer),
NID_commonName, peer_CN, 256);
printf("\nCommon Name in Certificate = %s \n",peer_CN);
if(strcasecmp(peer_CN,host))
berr_exit("Common name doesn't match host name");
printf("\nCommon name match Host name");
}
void read_write(SSL *ssl,int sock)
{
int width;
int r,c2sl=0,c2s_offset=0;
fd_set readfds,writefds;
int shutdown_wait=0;
char c2s[BUFSIZZ],s2c[BUFSIZZ];
int ofcmode;
/*First we make the socket nonblocking*/
ofcmode=fcntl(sock,F_GETFL,0);
ofcmode|=O_NDELAY;
if(fcntl(sock,F_SETFL,ofcmode))
berr_exit("Couldn't make socket nonblocking");
printf("\n Socket set to nonblocking \n");
width=sock+1;
while(1){
FD_ZERO(&readfds); /* clears all the filedescriptors in the
file descriptor readfds.*/
FD_ZERO(&writefds); /* clears all the filedescriptors in the
file descriptor
writefds. */
FD_SET(sock,&readfds); /* Includes a particular descriptor fd
in readfds */
/* If we've still got data to write then don't try to read */
if(c2sl)
FD_SET(sock,&writefds);
else
FD_SET(fileno(stdin),&readfds);
r=select(width,&readfds,&writefds,0,0);
if(r==0)
continue;
/* Now check if there's data to read */
if(FD_ISSET(sock,&readfds)){
do {
r=SSL_read(ssl,s2c,BUFSIZZ);
switch(SSL_get_error(ssl,r)){
case SSL_ERROR_NONE:
fwrite(s2c,1,r,stdout);
break;
case SSL_ERROR_ZERO_RETURN:
/* End of data */
if(!shutdown_wait)
SSL_shutdown(ssl);
goto end;
break;
case SSL_ERROR_WANT_READ:
break;
default:
berr_exit("SSL read problem");
}
} while (SSL_pending(ssl));
}
/* Check for input on the console*/
if(FD_ISSET(fileno(stdin),&readfds)){
c2sl=read(fileno(stdin),c2s,BUFSIZZ);
if(c2sl==0){
shutdown_wait=1;
if(SSL_shutdown(ssl))
return;
}
c2s_offset=0;
}
/* If we've got data to write then try to write it*/
if(c2sl && FD_ISSET(sock,&writefds)){
r=SSL_write(ssl,c2s+c2s_offset,c2sl);
switch(SSL_get_error(ssl,r)){
/* We wrote something*/
case SSL_ERROR_NONE:
c2sl-=r;
c2s_offset+=r;
break;
/* We would have blocked */
case SSL_ERROR_WANT_WRITE:
break;
/* Some other error */
default:
berr_exit("SSL write problem");
}
}
}
end:
SSL_free(ssl);
close(sock);
return;
}
int main(int argc,char **argv)
{
SSL_CTX *ctx; /* SSL context */
SSL *ssl; /* SSL layer pointer */
BIO *sbio; /* Abstract I/o */
int sock; /* socket fd */
SSL_METHOD *meth;
int ret;
initialize();
// meth = SSLv3_method(); /* Choose an SSL/TLS protocol version */
meth = TLSv1_method(); /* Choose an SSL/TLS protocol version */
ctx = SSL_CTX_new(meth); /* Used to create an SSL_CTX structure */
setup_client_credentials(ctx); /* Loading Certificates */
setup_client_CA_credentials(ctx);
if(!(RAND_load_file(RANDOM,1024*1024)))
berr_exit("Couldn't load randomness");
sock = client_sock(); /* Created the TCP socket for client */
ssl = SSL_new(ctx); /* Newly created SSL structure inherits information
from the SSL_CTX structure */
sbio = BIO_new_socket(socket, BIO_NOCLOSE);/* Creates a socket BIO in
which the TCP/IP socket
is assigned */
SSL_set_bio(ssl, sbio, sbio); /* Assigns the socket BIO into the
SSL
structure */
/* initiate an SSL handshake*/
printf("\n Initiate an SSL handshake \n");
if(SSL_connect(ssl)<=0)
{
// berr_exit("SSL connect error");
ret=0;
printf("\n SSL connect error \n");
SSL_get_error(ssl,ret);
printf("\n ret =%d ",ret);
if(ret == SSL_ERROR_WANT_READ )
printf("\n ERROR return Value SSL_ERROR_WANT_READ \n");
else if(ret == SSL_ERROR_WANT_WRITE)
printf("\n ERROR return Value SSL_ERROR_WANT_READ \n");
else if (ret == 0)
printf("\n Shut down con-trolled and by the specifications of
the TLS/SSL protocol \n");
else if (ret < 0)
printf("\n Shut down was The shutdown was not clean \n");
printf("\n Return value = %d \n",ret);
}
SSL_CTX_set_verify_depth(ctx, 1);
/*explicitly obtain the peer certificat*/
if(SSL_get_peer_certificate(ssl) != NULL)
{
if(SSL_get_verify_result(ssl) == X509_V_OK)
{
printf("\n Client verification with SSL_get_verify_result succeeded
\n");
}
else{
printf("\n Client verification with
SSL_get_verify_result()failed \n");
exit(1);
}
}
else
{
printf("\n The peer certificate was not presented.\n");
}
// Check_Common_name(ssl,COMMON_NAME);
/*Check the validity of cert
from peer*/
read_write(ssl,sock); /* read and write from the SSL */
SSL_CTX_free(ctx); /* Free the SSL context */
}
/* A simple SSL server */
#include "common.h"
#include "server.h"
#include "echo.h"
static int s_server_session_id_context = 1;
BIO *bio_err=0;
static char *pass;
static int password_cb(char *buf,int num,int rwflag,void *userdata);
static void sigpipe_handle(int x);
/* A simple error and exit routine*/
int err_exit(string)
char *string;
{
fprintf(stderr,"%s\n",string);
exit(0);
}
/* Print SSL errors and exit*/
int berr_exit(string)
char *string;
{
BIO_printf(bio_err,"%s\n",string);
ERR_print_errors(bio_err);
exit(0);
}
/*The password code is not thread safe*/
static int password_cb(char *buf,int num,int rwflag,void *userdata)
{
if(num<strlen(pass)+1)
return(0);
strcpy(buf,pass);
return(strlen(pass));
}
static void sigpipe_handle(int x){
}
void destroy_ctx(ctx)
SSL_CTX *ctx;
{
SSL_CTX_free(ctx); /*free the context*/
}
/*
* Before we can call any other OpenSSL APIs in the SSL application
* programs, you must perform initialization using the following SSL APIs.
*/
SSL_CTX *initialize_ctx(keyfile,password)
char *keyfile;
char *password;
{
SSL_METHOD *meth;
SSL_CTX *ctx;
if(!bio_err){
/* Global system initialization*/
SSL_library_init(); /*API registers all ciphers and hash algorithms used
in SSL APIs*/
/*
* This API loads error strings for SSL APIs as well as for
* Crypto APIs. Both SSL and Crypto error strings need to be
* loaded because many SSL applications call some Crypto APIs
* as well as SSL APIs.
*/
SSL_load_error_strings();
/* An error write context */
bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
}
/* Set up a SIGPIPE handler */
signal(SIGPIPE,sigpipe_handle);
/* Create our server SSL context*/
//meth=SSLv3_method(); /*For combined client and server,choose an */
meth=TLSv1_method(); /*For combined client and server,choose an */
/* SSL/TLS protocol version */
ctx=SSL_CTX_new(meth); /*API takes the SSL_METHOD structure as an */
/*argument and creates an SSL_CTX structure */
/* The SSL protocol requires that the server set its own certificate and
key*/
/* Load our keys and certificates in to the SSL structure*/
/* API to load a certificate into an SSL_CTX structure*/
if(!(SSL_CTX_use_certificate_file(ctx,SERVER_CRT,SSL_FILETYPE_PEM))) {
berr_exit("Couldn't read certificate file");
}
/* set the Password to verifiy the certificate */
pass = password;
SSL_CTX_set_default_passwd_cb(ctx,password_cb);
/* Load the server private-key into the SSL context */
if(!(SSL_CTX_use_PrivateKey_file(ctx,SERVER_KEY,SSL_FILETYPE_PEM))){
berr_exit("Couldn't read key file");
}
/* Load the CAs we trust, API loads a CA certificate into the SSL_CTX
structure*/
/* CA_LIST is the name of sertificate in Pem format */
if(!(SSL_CTX_load_verify_locations(ctx,CA_CRT,0))){
berr_exit("Couldn't read CA list");
}
/* Set the verification depth to 1 */
SSL_CTX_set_verify_depth(ctx,1);
/* Load randomness */
if(!(RAND_load_file(RANDOM,1024*1024)))
berr_exit("Couldn't load randomness");
return ctx; /* return the SSL server context */
}
int tcp_listen()
{
int sock;
struct sockaddr_in sin;
int val=1;
if((sock=socket(AF_INET,SOCK_STREAM,0))<0)
err_exit("Couldn't make socket");
memset(&sin,0,sizeof(sin));
sin.sin_addr.s_addr=INADDR_ANY;
sin.sin_family=AF_INET;
sin.sin_port=htons(PORT);
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val));
if(bind(sock,(struct sockaddr *)&sin,sizeof(sin))<0)
berr_exit("Couldn't bind");
listen(sock,5);
return(sock);
}
void generate_eph_rsa_key(ctx)
SSL_CTX *ctx;
{
RSA *rsa;
rsa=RSA_generate_key(512,RSA_F4,NULL,NULL);
if (!SSL_CTX_set_tmp_rsa(ctx,rsa))
berr_exit("Couldn't set RSA key");
RSA_free(rsa);
}
void load_dh_params(ctx,file)
SSL_CTX *ctx;
char *file;
{
DH *ret=0;
BIO *bio;
if ((bio=BIO_new_file(file,"r")) == NULL)
berr_exit("Couldn't open DH file");
ret=PEM_read_bio_DHparams(bio,NULL,NULL,NULL);
BIO_free(bio);
if(SSL_CTX_set_tmp_dh(ctx,ret)<0)
berr_exit("Couldn't set DH parameters");
}
/* Test Program which acts as SSL server */
int main(argc,argv)
int argc;
char **argv;
{
int sock,s;
BIO *sbio;
SSL_CTX *ctx;
SSL *ssl;
int r,ret;
/*
* Build our SSL context
* Before we call any other openSSL
* APIs in the SSL applicationprograms
* we must perform initialization using this APIs.
*/
ctx=initialize_ctx(SERVER_KEY,PASSWORD);
/* Load the DH key parameters 1024 bytes in pem format */
load_dh_params(ctx,DHFILE);
generate_eph_rsa_key(ctx);
/*
* sets the context sid_ctx of length sid_ctx_len within which
* a session can be reused for the ctx object.
*/
SSL_CTX_set_session_id_context(ctx,(void*)&s_server_session_id_context,
sizeof s_server_session_id_context);
/*create a socket and bind to it */
sock = tcp_listen();
/* accept a Client Request */
while(1){
if((s = accept(sock,0,0))<0){
err_exit("Problem accepting");
}
/*
* BIO_new_socket() API creates a socket BIO in which the TCP/IP socket is
* assigned,and the SSL_set_bio() API assigns the socket BIO into the SSL
* structure
*/
/* creates a socket BIO in which the TCP/IP socket is assigned*/
sbio = BIO_new_socket(s,BIO_NOCLOSE);
/* Create a new SSL structure*/
ssl = SSL_new(ctx);
/* assigns the socket BIO into the SSL structure */
SSL_set_bio(ssl,sbio,sbio);
/*
* The SSL handshake is a complicated process that involves significant
* cryptographic key exchanges. However, the handshake can be
* completed by calling SSL_accept() on the SSL server
* and SSL_connect() on the SSL client
*/
if(((r=SSL_accept(ssl)) <= 0)){
// berr_exit("SSL accept error");
printf("SSL accept error r = %d ",r);
ret=0;
SSL_get_error(ssl,ret);
if(ret == SSL_ERROR_NONE)
printf("\n SSL_ERROR_NONE \n");
else if(ret == SSL_ERROR_ZERO_RETURN )
printf("\n SSL_ERROR_ZERO_RETURN \n");
else if (ret == SSL_ERROR_WANT_READ )
printf("\n SSL_ERROR_WANT_READ \n");
else if (ret == SSL_ERROR_WANT_WRITE )
printf("\n SSL_ERROR_WANT_WRITE \n");
else if (ret == SSL_ERROR_WANT_CONNECT )
printf("\n SSL_ERROR_WANT_CONNECT \n");
else if (ret == SSL_ERROR_WANT_ACCEPT )
printf("\nSSL_ERROR_WANT_ACCEPT \n");
else if (ret == SSL_ERROR_WANT_X509_LOOKUP )
printf("\n SSL_ERROR_WANT_X509_LOOKUP \n");
/* else if (ret == SSL_ERROR_SYSCAL)
printf("\n SSL_ERROR_SYSCAL \n");*/
else if (ret == SSL_ERROR_SSL )
printf("\n SSL_ERROR_SSL \n");
else if (ret <0)
printf("\n Shut down was The shutdown was not clean \n");
printf("\n Return value = %d \n",ret);
}
// echo(ssl,s);
}
destroy_ctx(ctx);
exit(0);
}