dear all i made an application a client server the client send a
certificate request and server reply with the certificate and it creates a
encrypted shared key and some data and sign the digest of the shared key
and data

my problem is

1- in SignDigest() in  EVP_DigestSignFinal(mdctx, NULL, signlen); function
return an error No source available for "EVP_PKEY_sign() at 0xb7ede098"

i don't know the reason for this error it should return the length of the
sign only????

then i reserve a location in memory with this size

please help me


-- 
Warmest regards and best wishes for a good health,*urs sincerely *
*mero*
//============================================================================
// Name        : certificate.cpp
// Author      : Amir
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include "server.h"
#include "client.h"
using namespace std;

int main()
{
	clock_t start, end;
	double msecs;

	start = clock();

	Client clientest;
    Server servertest;

    X509 *cert;
    cert = servertest.CreateCertificate(clientest.MakeSignedCertReq());

    clientest.SetCert(cert);
    clientest.CertConverter();
    X509 *test;
    test = clientest.GetCert();
    servertest.CheckCert(cert);
    int serial = 0;
    serial = clientest.ExtractCertSerial();
    cout<<"client serial is "<<serial<<endl;

    servertest.SetSharedKey();
    servertest.EncryptSharedKey(cert);

    unsigned char enckey[RSA_KEY_SIZE];
    servertest.GetEncryptedKey(enckey,RSA_KEY_SIZE);

    clientest.DecryptSharedKey(enckey);

    servertest.SetData(DATA_SIZE);
    servertest.SetDigestData();
    servertest.CreateDigest();
    servertest.SignDigest();

	end = clock();
	msecs = ((double) (end - start)) * 1000 / CLOCKS_PER_SEC;
	cout<<"time is "<<msecs<<"msec"<<endl;

	return 0;
}
/*
 * client.cc
 *
 *  Created on: Sep 17, 2014
 *      Author: amirale32
 */

#include "client.h"

 Client :: Client()
 {
	  m_myCertReq = X509_REQ_new();
	  m_myCert = X509_new();
	  m_name = X509_NAME_new();
	  m_rsa_keyPair = RSA_new();
	  m_puk  = EVP_PKEY_new();
	  GenerateRSAKeyPair();
 }

 Client :: ~Client()
 {
	  X509_REQ_free(m_myCertReq);
	  X509_free(m_myCert);
	  RSA_free(m_rsa_keyPair);
 }

 void
 Client :: GenerateRSAKeyPair ( )
 {
     m_rsa_keyPair = RSA_generate_key((8*RSA_KEY_SIZE),RSA_F4,NULL,NULL);
     BIO *pubout = NULL;
     const char szPath[MAX_FILE_NAME_SIZE] = "clrsa.pem";
     pubout = BIO_new_file(szPath,"wb");
     PEM_write_bio_RSAPublicKey (pubout , m_rsa_keyPair);
     BIO_free(pubout);

}

 void
 Client::SetPublicKey()
 {
	 EVP_PKEY_assign_RSA(m_puk,m_rsa_keyPair);
     BIO *out = NULL;
     const char szPath[MAX_FILE_NAME_SIZE] = "cpuky.pem";
     out = BIO_new_file(szPath,"wb");
     PEM_write_bio_PUBKEY(out,m_puk);
 }

 X509_REQ*
 Client::MakeSignedCertReq()
 {
	 //adds all digest algorithms to the table
	 OpenSSL_add_all_digests();
	 SetPublicKey();
	 //include the public key in the req
	 X509_REQ_set_pubkey(m_myCertReq,m_puk);
	 //set the subject name of the request
	 m_name=X509_REQ_get_subject_name(m_myCertReq);
	 //set the request
	 X509_NAME_add_entry_by_txt(m_name,"C",MBSTRING_ASC, (const unsigned char *)"UK", -1, -1, 0);
	 X509_NAME_add_entry_by_txt(m_name,"CN",MBSTRING_ASC, (const unsigned char *)"OpenSSL Group", -1, -1, 0);
	 //sign the req
	 X509_REQ_sign(m_myCertReq,m_puk,EVP_sha1());
	 BIO *out = NULL;
	 const char szPath[MAX_FILE_NAME_SIZE] = "req.pem";
	 out = BIO_new_file(szPath,"wb");
	 PEM_write_bio_X509_REQ(out,m_myCertReq);
	 BIO_free(out);
	 return m_myCertReq;
}

 void
 Client::SetCert(X509 *cert)
 {
	 m_myCert =  cert;
	 BIO *out = NULL;
	 const char szPath[MAX_FILE_NAME_SIZE] = "clcrt.pem";
	 out = BIO_new_file(szPath,"wb");
	 PEM_write_bio_X509 (out , cert);
}

 int
 Client::CertConverter()
 {
	 int len = i2d_X509(m_myCert, NULL);
	 unsigned char *buf, *p;
	 buf = (unsigned char *)OPENSSL_malloc(len);
	 p = buf;
	 i2d_X509(m_myCert, &p);
	 unsigned char certarray[len];
	 for (int i = 0 ; i<len ; i++)
	 {
		 certarray[i] = *(p-len+i);
	 }
	 cout<<"cert len is "<<len<<endl;
	 cout << "converted client cert is"<<endl;
	 for (int j = 0 ; j<len ; j++)
	 {
	     	printf("0x%.2x ", certarray[j]);
	 }
	 cout<<endl;

	 X509 *certtest;
	 unsigned char *buf1;
	 buf1 = certarray;
	 const unsigned char *p1 = buf1;
	 p1 = buf1;
	 certtest = d2i_X509(NULL, &p1, CERT_SIZE);

	 FILE * fcert;
	 fcert = fopen("certarray.pem", "wb");
	 PEM_write_X509(
	     fcert,    //write the certificate to the file we've opened
	     certtest  //our certificate
	 );
	 return 0;
}

 X509*
 Client::GetCert()
 {
	 return m_myCert;
}

 int
 Client::ExtractCertSerial()
 {
	 int serial = 0;
	 unsigned char **out = NULL;
	 ASN1_INTEGER *asn1_serial = NULL;

	 asn1_serial = X509_get_serialNumber(m_myCert);
	 serial = i2d_ASN1_INTEGER(asn1_serial, out);
	 return (serial);
}

void
Client::DecryptSharedKey(unsigned char encryptedkey[])
{
	int padding = RSA_PKCS1_PADDING;
    RSA_private_decrypt(RSA_KEY_SIZE,encryptedkey,m_DecryptedSharedKey,m_rsa_keyPair,padding);

    cout<<" shared key after decryption is "<<endl;
    for (int i = 0 ; i<SHARED_KEY_SIZE ; i++)
    {
    	printf("0x%.2x ", m_DecryptedSharedKey[i]);
    }
    cout<<endl;
}
 /*
void
Client::SignData()
{
	int padding = RSA_PKCS1_PADDING;
	RSA_private_encrypt(DATA_SIZE, m_Data, m_signedData, m_rsa_keyPair , padding);
    cout<<"sign data is "<<endl;

    for (int i = 0 ; i <RSA_KEY_SIZE;i++)
    {
    	printf("0x%.2x ", m_signedData[i]);
    }
    cout<<endl;
}
*/
/*
 * client.h
 *
 *  Created on: Sep 17, 2014
 *      Author: amirale32
 */

#ifndef CLIENT_H_
#define CLIENT_H_

#define MAX_FILE_NAME_SIZE 20
#define RSA_KEY_SIZE 256 //bytes
#define CERT_SIZE 727
#define SHARED_KEY_SIZE 32 //bytes
#define DIGEST_SIZE 20
#define DATA_SIZE    13
#define SIGNED_DATA_SIZE 20

#include <stdlib.h>
#include <stdio.h>
#include <openssl/rsa.h>
#include <openssl/conf.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/sha.h>
#include "server.h"

 class Client
 {
   public:

   Client();
   ~Client();

   void GenerateRSAKeyPair ();
   void SetPublicKey ();

   X509_REQ *MakeSignedCertReq();
   void SetCert (X509 *cert);
   X509 *GetCert();
   int CertConverter ();
   int ExtractCertSerial ();

   void DecryptSharedKey (unsigned char encryptedkey []);

   private:

   X509_REQ         *m_myCertReq;
   X509             *m_myCert;
   X509_NAME        *m_name;
   RSA              *m_rsa_keyPair;
   EVP_PKEY         *m_puk;
   unsigned char     m_DecryptedSharedKey[SHARED_KEY_SIZE];
 };



#endif /* CLIENT_H_ */
#include "server.h"

 Server::Server()
 {
	  m_myCert = X509_new();
	  m_caKeyPairs = RSA_new();
	  m_pukey  = EVP_PKEY_new();
	  m_issuerName = X509_NAME_new();
	  GenerateMyKeyPairs();
	  CreateMyCertificate();
 }

 Server::~Server()
 {
	  X509_free(m_myCert);
	  RSA_free(m_caKeyPairs);
	  X509_NAME_free(m_issuerName);
 }

 X509*
 Server::CreateCertificate(X509_REQ* req)
 {
	 X509 *m_req_reply;
	 m_req_reply = X509_new();
	 X509_NAME *subject = NULL;
	 EVP_PKEY *pkey = NULL;
	 //check Request signature matches the certificate request
	 pkey = X509_REQ_get_pubkey(req);

	 ASN1_INTEGER_set(X509_get_serialNumber(m_req_reply), 2);

	 X509_gmtime_adj(X509_get_notBefore(m_req_reply), 0);
	 X509_gmtime_adj(X509_get_notAfter(m_req_reply), 31536000L);

	 X509_set_pubkey(m_req_reply, pkey);

	 X509_NAME *issuerSubject = X509_get_subject_name(m_myCert);

	 X509_set_issuer_name(m_req_reply, issuerSubject);

	 //extract the subject of the request
	 subject = X509_REQ_get_subject_name(req);
	 X509_set_subject_name(m_req_reply, subject);

	 X509_get_subject_name(m_req_reply);

	 X509_sign(m_req_reply, m_pukey, EVP_sha1());
	 return m_req_reply;
 }

 void
 Server::CreateMyCertificate()
 {
     // we use rsa pairs and assign it into evp_key
	 SetPublicKey();
	 // properties of the certificate
	 //set the serial number
	 ASN1_INTEGER_set(X509_get_serialNumber(m_myCert), 1);
	 //set the time validity
	 X509_gmtime_adj(X509_get_notBefore(m_myCert), 0);
	 X509_gmtime_adj(X509_get_notAfter(m_myCert), 31536000L);
	 //set the public key of the cert to be signed
	 X509_set_pubkey(m_myCert, m_pukey);
     //this is a self-signed certificate, we set the name of the issuer to the name of the subject
	 m_issuerName = X509_get_subject_name(m_myCert);

	 X509_NAME_add_entry_by_txt(m_issuerName, "C",  MBSTRING_ASC,
	                            (unsigned char *)"CA", -1, -1, 0);
	 X509_NAME_add_entry_by_txt(m_issuerName, "O",  MBSTRING_ASC,
	                            (unsigned char *)"MyCompany Inc.", -1, -1, 0);
	 X509_NAME_add_entry_by_txt(m_issuerName, "CN", MBSTRING_ASC,
	                            (unsigned char *)"localhost", -1, -1, 0);

     //set the issuer name
	 X509_set_issuer_name(m_myCert, m_issuerName);
	 //sign the cert
	 X509_sign(m_myCert, m_pukey, EVP_sha1());

	 FILE * fcert;
	 fcert = fopen("cacert.pem", "wb");
	 PEM_write_X509(
	     fcert,   /* write the certificate to the file we've opened */
	     m_myCert /* our certificate */
	 );
 }

 void
 Server::GenerateMyKeyPairs()
 {
	 m_caKeyPairs = RSA_generate_key((8*RSA_KEY_SIZE),RSA_F4 , NULL , NULL);
     BIO *pubout = NULL;
     const char szPath[MAX_FILE_NAME_SIZE] = "carsa.pem";
     pubout = BIO_new_file(szPath,"wb");
     PEM_write_bio_RSAPublicKey (pubout , m_caKeyPairs);
     BIO_free(pubout);
}

 void
 Server::SetPublicKey()
 {
	 EVP_PKEY_assign_RSA(m_pukey,m_caKeyPairs);

	 BIO *out = NULL;
	 const char szPath[MAX_FILE_NAME_SIZE] = "caevp.pem";
	 out = BIO_new_file(szPath,"wb");

	 EVP_PKEY_print_private(out, m_pukey,
	                                0, NULL);
	 BIO_free(out);
	 out = BIO_new_file("prkey.pem","wb");

	 PEM_write_bio_PrivateKey(
	     out,                  /* write the key to the file we've opened */
		 m_pukey,               /* our key from earlier */
	     EVP_des_ede3_cbc(), /* default cipher for encrypting the key on disk */
	     (unsigned char *)"replace_me",       /* passphrase required for decrypting the key on disk */
	     10,                 /* length of the passphrase string */
	     NULL,               /* callback for requesting a password */
	     NULL                /* data to pass to the callback */
	 );

 }

 void
 Server::SetSharedKey()
 {
 	cout<<"shared key is "<<endl;
 	for (int i = 0; i<SHARED_KEY_SIZE ; i++)
 	{
 	m_sharedKey[i] = i;
 	printf("0x%.2x ", m_sharedKey[i]);
 	}
 	cout<<endl;
 }

 void
 Server::EncryptSharedKey(X509 *clientcert)
 {
 	int padding = RSA_PKCS1_PADDING;
 	RSA *m_clrsa_keyPair = NULL;
 	EVP_PKEY *pkey = NULL;
 	pkey = X509_get_pubkey(clientcert);
 	m_clrsa_keyPair = EVP_PKEY_get1_RSA(pkey);
 	RSA_public_encrypt(SHARED_KEY_SIZE,m_sharedKey,m_encryptedSharedKey,m_clrsa_keyPair,padding);
     cout<<"encrypted shared key is "<<endl;
     for (int i = 0 ; i<RSA_KEY_SIZE ; i++)
     {
     	printf("0x%.2x ", m_encryptedSharedKey[i]);
     }
     cout<<endl;
 }

 void
 Server::GetEncryptedKey(unsigned char encryptedkey[], int size)
 {
	 for (int i = 0 ; i<size ; i++)
	 {
		 encryptedkey [i] = m_encryptedSharedKey [i];
	 }
 }


 int
 Server::CheckCert(X509* clientcert)
 {

	 int status = 0;
	 X509_STORE_CTX *ctx = X509_STORE_CTX_new();

     //store the trusted cert into ctx
	 X509_STORE *store = X509_STORE_new();
	 X509_STORE_add_cert(store, m_myCert);

     //put the trusted cert and cert then verify it
	 X509_STORE_CTX_init(ctx,store, clientcert, NULL);
	 status  = X509_verify_cert(ctx);

	 if (status == 1)
	 {
		 cout<<"verified succesfully"<<endl;
	 }
	 else
	 {
		 cout<<"verifiy fail"<<endl;
		 cout << X509_verify_cert_error_string(X509_STORE_CTX_get_error(ctx));
	 }
	 return status;
}

void
Server::SetData(int size)
{
	cout<<"data is "<<endl;
	for (int i = 0 ; i<size ; i++)
	{
		m_Data[i]=i;
    	printf("0x%.2x ", m_Data[i]);
	}
	cout<<endl;
}

void
Server::SetDigestData()
{
	 for (int i = 0; i<DATA_SIZE ; i++)
	 {
		 m_digestData[i] = m_Data[i];
	 }
	 for (int j = 0 ; j <RSA_KEY_SIZE ; j++ )
	 {
		 m_digestData[(DATA_SIZE+j)] = m_encryptedSharedKey[j];
	 }
	 cout <<"digest data is"<<endl;
	 for (int k = 0 ; k< (DATA_SIZE + RSA_KEY_SIZE ); k++)
	 {
	     	printf("0x%.2x ", m_digestData[k]);
	 }
	 cout<<endl;
}

void
Server::CreateDigest()
{
	  OpenSSL_add_all_ciphers();
	  OpenSSL_add_all_digests();

	SHA1(m_digestData, (DATA_SIZE + RSA_KEY_SIZE), m_digest);

	cout<<"digest is "<<endl;
	for (int i = 0; i < DIGEST_SIZE; i++)
	{
     	printf("0x%.2x ", m_digest[i]);
	}
	cout<<endl;
}

void
Server::SignDigest()
{
	  OpenSSL_add_all_ciphers();
	  OpenSSL_add_all_digests();

	  //create private key
	  EVP_PKEY *priv_key = NULL;
	  priv_key = EVP_PKEY_new();
	  EVP_PKEY_set1_RSA(priv_key,m_caKeyPairs);

	cout<<"i'm in sign digest"<<endl;
/*
	BIO *sgerr = NULL;
	const char szPath[MAX_FILE_NAME_SIZE] = "sgerr.pem";
	sgerr = BIO_new_file(szPath,"wb");

	cout<<"input digest is "<<endl;
	for (int i = 0; i < DIGEST_SIZE; i++)
	{
     	printf("0x%.2x ", m_digest[i]);
	}
	cout<<endl;
*/
	size_t *signlen = NULL;
    unsigned char *sign = NULL;
    //create message digest context
	EVP_MD_CTX *mdctx = NULL;
	mdctx = EVP_MD_CTX_create();
	//Initialize the DigestSign operation
	EVP_DigestSignInit(mdctx, NULL, EVP_sha1(), NULL, priv_key);
	//update with the message
	EVP_DigestSignUpdate(mdctx, m_digestData,(DATA_SIZE + RSA_KEY_SIZE));
	//Finalise the DigestSign operation
	EVP_DigestSignFinal(mdctx, NULL, signlen);
    sign = (unsigned char *)OPENSSL_malloc(signlen);
	EVP_DigestSignFinal(mdctx, sign, signlen);

	//cout<<"sign length is "<<(*signlen)<<endl;



	//unsigned int *siglen = NULL;
	//assert (1 == RSA_sign(NID_sha1,m_digest, DIGEST_SIZE,m_signedDigest,siglen,m_caKeyPairs));

   // ERR_print_errors(sgerr);
    //BIO_free(sgerr);
/*
	//cout <<"sig len is "<<(*siglen)<<endl;
	cout<<"signed digest is "<<endl;
	for (int i = 0; i < RSA_KEY_SIZE; i++)
	{
     	printf("0x%.2x ", m_signedDigest[i]);
	}
	cout<<endl;
	*/
}

/*
 * server.cc
 *
 *  Created on: Sep 17, 2014
 *      Author: amirale32
 */




/*
 * server.h
 *
 *  Created on: Sep 17, 2014
 *      Author: amirale32
 */

#ifndef SERVER_H_
#define SERVER_H_

#include <stdlib.h>
#include <iostream>
#include <stdio.h>
#include <assert.h>
#include <openssl/asn1.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/conf.h>
#include <openssl/err.h>
#include  "client.h"
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>

using namespace std;
class Client;
 class Server
 {
 public:

	 Server();
	 ~Server();

	 X509 *CreateCertificate (X509_REQ *req);
	 void CreateMyCertificate();

	 void GenerateMyKeyPairs ( );
	 void SetPublicKey ();

	 void SetSharedKey();
	 void EncryptSharedKey(X509 *clientcert);

	 void GetEncryptedKey (unsigned char encryptedkey [],int size);

	 int CheckCert (X509 *clientcert);

	 void SetData(int size);
	 void SetDigestData();

	 void CreateDigest();

	 void SignDigest();

 private:

	 X509             *m_myCert;
	 RSA              *m_caKeyPairs;
	 EVP_PKEY         *m_pukey;
	 X509_NAME        *m_issuerName;
	 unsigned char     m_encryptedSharedKey[RSA_KEY_SIZE];
	 unsigned char     m_sharedKey[SHARED_KEY_SIZE];
	 unsigned char     m_Data[DATA_SIZE];
	 unsigned char     m_digestData[DATA_SIZE + RSA_KEY_SIZE];
	 unsigned char     m_digest[DIGEST_SIZE ];
	 unsigned char     m_signedDigest[RSA_KEY_SIZE];
 };



#endif /* SERVER_H_ */

Reply via email to