r3077 - in trunk/libmcrypto: include/libmcrypto include/libmcrypto/gnutls include/libmcrypto/openssl source source/gnutls source/openssl

mikma at minisip.org mikma at minisip.org
Tue Jan 2 11:19:23 CET 2007


Author: mikma
Date: 2007-01-02 11:19:23 +0100 (Tue, 02 Jan 2007)
New Revision: 3077

Modified:
   trunk/libmcrypto/include/libmcrypto/cert.h
   trunk/libmcrypto/include/libmcrypto/gnutls/cert.h
   trunk/libmcrypto/include/libmcrypto/openssl/cert.h
   trunk/libmcrypto/source/cert.cxx
   trunk/libmcrypto/source/gnutls/cert.cxx
   trunk/libmcrypto/source/openssl/cert.cxx
Log:
Add gtls implementation of RSA public-key encryption/decryption
using libgcrypt.


Modified: trunk/libmcrypto/include/libmcrypto/cert.h
===================================================================
--- trunk/libmcrypto/include/libmcrypto/cert.h	2007-01-01 21:19:46 UTC (rev 3076)
+++ trunk/libmcrypto/include/libmcrypto/cert.h	2007-01-02 10:19:23 UTC (rev 3077)
@@ -106,7 +106,7 @@
 					    int enckeylgth,
 					    unsigned char *iv)=0;
 
-		virtual bool private_decrypt(unsigned char *data, int size,
+		virtual bool private_decrypt(const unsigned char *data, int size,
 					     unsigned char *retdata, int *retsize)=0;
 	protected:
 		priv_key();
@@ -155,10 +155,10 @@
 		virtual int verif_sign( unsigned char * data, int data_length,
 					unsigned char * sign, int sign_length )=0;
 
-		virtual bool public_encrypt(unsigned char *data, int size,
+		virtual bool public_encrypt(const unsigned char *data, int size,
 					    unsigned char *retdata, int *retsize)=0;
 
-		int private_decrypt(unsigned char *data, int size,
+		int private_decrypt(const unsigned char *data, int size,
 				    unsigned char *retdata, int *retsize);
 
 		virtual std::string get_name()=0;

Modified: trunk/libmcrypto/include/libmcrypto/gnutls/cert.h
===================================================================
--- trunk/libmcrypto/include/libmcrypto/gnutls/cert.h	2007-01-01 21:19:46 UTC (rev 3076)
+++ trunk/libmcrypto/include/libmcrypto/gnutls/cert.h	2007-01-02 10:19:23 UTC (rev 3077)
@@ -37,9 +37,34 @@
 
 
 #include<gnutls/x509.h>
+#include<gcrypt.h>
 
 class gtls_certificate;
 
+class gtls_rsa_priv{
+	public:
+		gtls_rsa_priv( gnutls_x509_privkey_t aKey );
+		~gtls_rsa_priv();
+
+		bool decrypt( const unsigned char *data, int size,
+			      unsigned char *retdata, int *retsize) const;
+
+	private:
+		gcry_sexp_t m_key;
+};
+
+class gtls_rsa_pub{
+	public:
+		gtls_rsa_pub( gnutls_x509_crt_t aCert );
+		~gtls_rsa_pub();
+
+		bool encrypt( const unsigned char *data, int size,
+			      unsigned char *retdata, int *retsize) const;
+
+	private:
+		gcry_sexp_t m_key;
+};
+
 class LIBMCRYPTO_API gtls_ca_db_item: public ca_db_item{
 	public:
 		gtls_ca_db_item();
@@ -90,13 +115,14 @@
 				    int enckeylgth,
 				    unsigned char *iv);
 
-		bool private_decrypt(unsigned char *data, int size,
+		bool private_decrypt( const unsigned char *data, int size,
 				     unsigned char *retdata, int *retsize);
 
 		gnutls_x509_privkey_t get_private_key(){return privateKey;};
 
 	private:
 		gnutls_x509_privkey_t privateKey;
+		gtls_rsa_priv *rsaPriv;
 		std::string pk_file;
 };
 
@@ -121,7 +147,7 @@
 		int verif_sign( unsigned char * data, int data_length,
 				unsigned char * sign, int sign_length );
 
-		bool public_encrypt(unsigned char *data, int size,
+		bool public_encrypt( const unsigned char *data, int size,
 				    unsigned char *retdata, int *retsize);
 
 		std::string get_name();
@@ -139,6 +165,7 @@
 
 	private:
 		gnutls_x509_crt_t cert;
+		gtls_rsa_pub *rsaKey;
 };
 
 class gtls_certificate_chain: public certificate_chain{

Modified: trunk/libmcrypto/include/libmcrypto/openssl/cert.h
===================================================================
--- trunk/libmcrypto/include/libmcrypto/openssl/cert.h	2007-01-01 21:19:46 UTC (rev 3076)
+++ trunk/libmcrypto/include/libmcrypto/openssl/cert.h	2007-01-02 10:19:23 UTC (rev 3077)
@@ -88,7 +88,7 @@
 				    int enckeylgth,
 				    unsigned char *iv);
 
-		bool private_decrypt(unsigned char *data, int size,
+		bool private_decrypt(const unsigned char *data, int size,
 				     unsigned char *retdata, int *retsize);
 
 		EVP_PKEY * get_openssl_private_key(){return private_key;};
@@ -123,7 +123,7 @@
 		int verif_sign( unsigned char * data, int data_length,
 				unsigned char * sign, int sign_length );
 
-		bool public_encrypt(unsigned char *data, int size,
+		bool public_encrypt(const unsigned char *data, int size,
 				    unsigned char *retdata, int *retsize);
 
 		std::string get_name();

Modified: trunk/libmcrypto/source/cert.cxx
===================================================================
--- trunk/libmcrypto/source/cert.cxx	2007-01-01 21:19:46 UTC (rev 3076)
+++ trunk/libmcrypto/source/cert.cxx	2007-01-02 10:19:23 UTC (rev 3077)
@@ -73,7 +73,7 @@
 	return m_pk->sign_data( data, data_length, sign, sign_length );
 }
 
-int certificate::private_decrypt(unsigned char *data, int size,
+int certificate::private_decrypt(const unsigned char *data, int size,
 				 unsigned char *retdata, int *retsize){
 	return m_pk->private_decrypt( data, size, retdata, retsize );
 }

Modified: trunk/libmcrypto/source/gnutls/cert.cxx
===================================================================
--- trunk/libmcrypto/source/gnutls/cert.cxx	2007-01-01 21:19:46 UTC (rev 3076)
+++ trunk/libmcrypto/source/gnutls/cert.cxx	2007-01-02 10:19:23 UTC (rev 3077)
@@ -26,6 +26,7 @@
 
 #include<libmcrypto/gnutls/cert.h>
 #include<gnutls/x509.h>
+#include<gcrypt.h>
 
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -41,7 +42,7 @@
 	throw Exception(msg.c_str());
 
 
-gtls_certificate::gtls_certificate():cert(NULL){
+gtls_certificate::gtls_certificate():cert(NULL),rsaKey(NULL){
         gnutls_global_init();
 }
 
@@ -99,12 +100,319 @@
 	return new gtls_certificate_chain();
 }
 
+
+// 
+// gtls_rsa_priv
+// 
+gtls_rsa_priv::gtls_rsa_priv( gnutls_x509_privkey_t aKey ):m_key(NULL){
+	gcry_error_t err;
+	gnutls_datum_t n[6];
+	int i;
+
+	memset(n, 0, sizeof(n));
+
+	if( gnutls_x509_privkey_export_rsa_raw( aKey, &n[0], &n[1], &n[2],
+						&n[3], &n[4], &n[5] )){
+		// TODO change to gtls_exception
+		throw certificate_exception_pkey("Private key invalid" );
+	}
+
+	gcry_mpi_t mpi[6];
+
+	memset(mpi, 0, sizeof(mpi));
+	for( i = 0; i < 6; i++ ){
+		size_t nscanned = 0;
+
+		err = gcry_mpi_scan( &mpi[i], GCRYMPI_FMT_USG,
+				     n[i].data, n[i].size, &nscanned );
+		gnutls_free( n[i].data );
+		n[i].data = NULL;
+		if( err ){
+			for( int j = 0; j < 6; j++ ){
+				if( n[j].data ){
+					gnutls_free( n[j].data );
+					n[j].data = NULL;
+				}
+			}
+
+			throw certificate_exception_pkey("Private key parameter invalid" );
+		}
+	}
+
+//      RSA private-key sexp format
+// 	(private-key
+// 	 (rsa
+// 	  (n n-mpi)
+// 	  (e e-mpi)
+// 	  (d d-mpi)
+// 	  (p p-mpi)
+// 	  (q q-mpi)
+// 	  (u u-mpi)
+
+	err = gcry_sexp_build( &m_key, NULL,
+			       "(private-key(rsa (n %m)(e %m)(d %m)(p %m)(q %m)(u %m)))",
+			       mpi[0], mpi[1], mpi[2], mpi[4], mpi[3], mpi[5]);
+
+	for( i = 0; i < 6; i++ ){
+		gcry_mpi_release( mpi[i] );
+		mpi[i] = NULL;
+	}
+
+	if( err ){
+		throw certificate_exception_pkey("Private key parameters invalid" );
+	}
+}
+
+gtls_rsa_priv::~gtls_rsa_priv(){
+	if( m_key ){
+		gcry_sexp_release( m_key );
+		m_key = NULL;
+	}
+}
+
+bool gtls_rsa_priv::decrypt( const unsigned char *data, int size,
+			     unsigned char *retdata, int *retsize) const{
+	gcry_error_t err;
+	bool ret = false;
+	gcry_mpi_t cipher_mpi = NULL;
+	gcry_sexp_t cipher = NULL;
+	gcry_sexp_t plain = NULL;
+	gcry_mpi_t datampi = NULL;
+	unsigned char *ptr = NULL;
+	size_t ptrsize = 0;
+	size_t pos = 0;
+	int len = 0;
+
+	err = gcry_mpi_scan(&cipher_mpi, GCRYMPI_FMT_USG, data, size, NULL);
+	if( err ){
+		goto error;
+	}
+
+	err = gcry_sexp_build( &cipher, NULL,
+			       "(enc-val(flags)(rsa(a %m)))",
+			       cipher_mpi );
+
+	if( err ){
+		goto error;
+	}
+
+	err = gcry_pk_decrypt( &plain, cipher, m_key );
+
+	if( err ){
+		goto error;
+	}
+
+	// gcry_pk_decrypt result:
+	// (value plaintext)
+
+	datampi = gcry_sexp_nth_mpi( plain, 1, GCRYMPI_FMT_NONE );
+
+	if( !datampi ){
+		goto error;
+	}
+
+	err = gcry_mpi_aprint( GCRYMPI_FMT_USG, &ptr, &ptrsize, datampi );
+
+	if( err ){
+		goto error;
+	}
+
+	// PKCS1 version 1.5 padding (RFC 2313)
+	// RSA input value = 00 || BT || PS || 00 || D.
+	// BT = 02 (public-key operation)
+	// PS = k-3-||D|| random octets
+
+	if( ptr[0] != 0x02 ){
+		goto error;
+	}
+
+	if( ptrsize < 4 ){
+		goto error;
+	}
+
+	pos = strnlen( (char*)ptr + 1, ptrsize - 1 ) + 2;
+	len = ptrsize - pos;
+
+	// Skip zeros at the beginning
+	while( !ptr[pos] && len > 0 ){
+		len--;
+		pos++;
+	}
+
+	if( *retsize < len ){
+		goto error;
+	}
+
+	*retsize = len;
+	memcpy( retdata, ptr + pos, len );
+
+	ret = true;
+
+  error:
+	if( cipher_mpi ){
+		gcry_mpi_release( cipher_mpi );
+	}
+	if( cipher ){
+		gcry_sexp_release( cipher );
+	}
+	if( plain ){
+		gcry_sexp_release( plain );
+	}
+	if( datampi ){
+		gcry_mpi_release( datampi );
+	}
+	if( ptr ){
+		gcry_free( ptr );
+	}
+
+	return ret;
+}
+
+//
+// gtls_rsa_pub
+// 
+gtls_rsa_pub::gtls_rsa_pub( gnutls_x509_crt_t aCert ):m_key(NULL){
+	gcry_error_t err;
+	gnutls_datum_t n;
+	gnutls_datum_t e;
+
+	memset(&n, 0, sizeof(n));
+	memset(&e, 0, sizeof(e));
+
+	if( gnutls_x509_crt_get_pk_rsa_raw( aCert, &n, &e ) ){
+		throw certificate_exception_init( "Can't get RSA key from cert" );
+	}
+
+	gcry_mpi_t n_mpi = NULL;
+	size_t nscanned = 0;
+	err = gcry_mpi_scan( &n_mpi, GCRYMPI_FMT_USG,
+			     n.data, n.size, &nscanned );
+
+	gcry_free( n.data );
+	n.data = NULL;
+
+	if( err ){
+		gcry_free( e.data );
+		throw certificate_exception_init( "Invalid public key m parameter" );
+	}
+
+	gcry_mpi_t e_mpi = NULL;
+	err = gcry_mpi_scan( &e_mpi, GCRYMPI_FMT_USG,
+			     e.data, e.size, &nscanned );
+	gcry_free( e.data );
+	e.data = NULL;
+
+	if( err ){
+		gcry_mpi_release( e_mpi );
+		throw certificate_exception_init( "Invalid public key e parameter" );
+	}
+
+	size_t erroff = 0;
+	
+	err = gcry_sexp_build( &m_key, &erroff,
+			       "(key-data(public-key(rsa (n %m)(e %m))))",
+			       n_mpi, e_mpi );
+
+	gcry_mpi_release( n_mpi );
+	n_mpi = NULL;
+	gcry_mpi_release( e_mpi );
+	e_mpi = NULL;
+
+	if( err ){
+		throw certificate_exception_init( "Invalid public key parameters" );
+	}
+}
+
+gtls_rsa_pub::~gtls_rsa_pub(){
+	if( m_key ){
+		gcry_sexp_release( m_key );
+		m_key = NULL;
+	}
+}
+
+bool gtls_rsa_pub::encrypt( const unsigned char *data, int size,
+			    unsigned char *retdata, int *retsize) const{
+	bool ret = false;
+	gcry_error_t err;
+	gcry_mpi_t data_mpi = NULL;
+	gcry_sexp_t cipher = NULL;
+	gcry_sexp_t data_sexp = NULL;
+	gcry_sexp_t rsa = NULL;
+	gcry_sexp_t a = NULL;
+	gcry_mpi_t datampi = NULL;
+	size_t erroff = 0;
+	size_t len = 0;
+
+	if( gcry_mpi_scan(&data_mpi, GCRYMPI_FMT_USG, data, size, NULL ) ){
+		goto error;
+	}
+
+	if( gcry_sexp_build( &data_sexp, &erroff,
+			     "(data(flags pkcs1)(value %m))",
+			     data_mpi ) ){
+		goto error;
+	}
+
+	if( err = gcry_pk_encrypt( &cipher, data_sexp, m_key ) ){
+		goto error;
+	}
+
+// 	(enc-val
+// 	 (rsa
+// 	  (a a-mpi)))
+
+	rsa = gcry_sexp_nth( cipher, 1 );
+	if( !rsa ){
+		goto error;
+	}
+
+	a = gcry_sexp_nth( rsa, 1 );
+	if( !a ){
+		goto error;
+	}
+
+	if( !(datampi = gcry_sexp_nth_mpi( a, 1, GCRYMPI_FMT_USG )) ){
+		goto error;
+	}
+
+	if( gcry_mpi_print( GCRYMPI_FMT_USG, 
+			    (unsigned char*)retdata,
+			    *retsize, &len, datampi ) ){
+		goto error;
+	}
+
+	*retsize = len;
+	ret = true;
+
+  error:
+	if( data_mpi )
+		gcry_mpi_release( data_mpi );
+	if( cipher )
+		gcry_sexp_release( cipher );
+	if( data_sexp )
+		gcry_sexp_release( data_sexp );
+	if( rsa )
+		gcry_sexp_release( rsa );
+	if( a )
+		gcry_sexp_release( a );
+	if( datampi )
+		gcry_mpi_release( datampi );
+
+	return ret;
+}
+
+
 gtls_priv_key::~gtls_priv_key(){
 	if( privateKey != NULL ){
 		gnutls_x509_privkey_deinit( privateKey );
 	}
 	
 	privateKey = NULL;
+
+	if( rsaPriv ){
+		delete rsaPriv;
+		rsaPriv = NULL;
+	}
 }
 
 const string &gtls_priv_key::get_file() const{
@@ -113,13 +421,13 @@
 
 
 // Read PEM-encoded certificate from a file
-gtls_certificate::gtls_certificate( const string certFilename ){
+gtls_certificate::gtls_certificate( const string certFilename ):rsaKey(NULL){
         gnutls_global_init();
 	openFromFile( certFilename );
 }
 
 // Import DER-encoded certificate from memory
-gtls_certificate::gtls_certificate( unsigned char * derCert, int length ){
+gtls_certificate::gtls_certificate( unsigned char * derCert, int length ):rsaKey(NULL){
         int ret;
         gnutls_datum certData;
 	
@@ -142,6 +450,12 @@
 			"Could not import the given certificate" );
         }
 
+	if( rsaKey ){
+		delete rsaKey;
+		rsaKey = NULL;
+	}
+
+	rsaKey = new gtls_rsa_pub( cert );
 }
 	
 gtls_certificate::~gtls_certificate(){
@@ -150,7 +464,11 @@
 	}
 	
 	cert = NULL;
-	
+
+	if( rsaKey ){
+		delete rsaKey;
+		rsaKey = NULL;
+	}
 }
 
 // Read PEM-encoded certificate from a file
@@ -207,6 +525,13 @@
         close( fd );
 
 	file = fileName;
+
+	if( rsaKey ){
+		delete rsaKey;
+		rsaKey = NULL;
+	}
+
+	rsaKey = new gtls_rsa_pub( cert );
 }
 
 int gtls_priv_key::sign_data( unsigned char * data, int dataLength,
@@ -244,17 +569,17 @@
 }
 
 int gtls_certificate::verif_sign( unsigned char * data, int data_length,
-				  unsigned char * sign, int sign_length ){
+				  unsigned char * sign, int sign_length )
 {
 	int err;
 	gnutls_datum dataStruct;
 	gnutls_datum signStruct;
 
 	dataStruct.data = data;
-	dataStruct.size = dataLength;
+	dataStruct.size = data_length;
 	
 	signStruct.data = sign;
-	signStruct.size = signLength;
+	signStruct.size = sign_length;
 	
 	if( cert == NULL ){
 		throw certificate_exception(
@@ -264,11 +589,14 @@
 	err = gnutls_x509_crt_verify_data( cert, 0, &dataStruct, &signStruct );
 
 	return err;
-}
+ }
 
-bool gtls_certificate::public_encrypt(unsigned char *data, int size,
+bool gtls_certificate::public_encrypt( const unsigned char *data, int size,
 				      unsigned char *retdata, int *retsize){
-	UNIMPLEMENTED;
+	if( !rsaKey )
+		return false;
+
+	return rsaKey->encrypt( data, size, retdata, retsize );
 }
 
 int gtls_certificate::get_der_length(){
@@ -516,6 +844,7 @@
         close( fd );
 
 	pk_file = file;
+	rsaPriv = new gtls_rsa_priv( privateKey );
 }
 
 // Import DER-encoded private key from memory
@@ -600,12 +929,14 @@
 	UNIMPLEMENTED;
 }
 
-bool gtls_priv_key::private_decrypt(unsigned char *data, int size,
+bool gtls_priv_key::private_decrypt( const unsigned char *data, int size,
 				    unsigned char *retdata, int *retsize){
-	UNIMPLEMENTED;
+	if( !rsaPriv )
+		return false;
+	
+	return rsaPriv->decrypt( data, size, retdata, retsize );
 }
 
-
 // 
 // End of gtls_certificate
 // 

Modified: trunk/libmcrypto/source/openssl/cert.cxx
===================================================================
--- trunk/libmcrypto/source/openssl/cert.cxx	2007-01-01 21:19:46 UTC (rev 3076)
+++ trunk/libmcrypto/source/openssl/cert.cxx	2007-01-02 10:19:23 UTC (rev 3077)
@@ -339,7 +339,7 @@
 	return err;
 }
 	
-bool ossl_priv_key::private_decrypt( unsigned char *data, int size,
+bool ossl_priv_key::private_decrypt( const unsigned char *data, int size,
 				    unsigned char *retdata, int *retsize ){
 	//adding PKE payload
 	RSA* rsa = EVP_PKEY_get1_RSA( private_key );
@@ -370,15 +370,16 @@
 	return true;
 }
 
-bool ossl_certificate::public_encrypt( unsigned char *data, int size,
+bool ossl_certificate::public_encrypt( const unsigned char *data, int size,
 				      unsigned char *retdata, int *retsize ){
 	//adding PKE payload
 	EVP_PKEY *public_key = X509_get_pubkey( cert );
 	RSA* rsa = EVP_PKEY_get1_RSA( public_key );
 
-// 	if( size >= RSA_size( rsa ) - 11 ){
-// 		return false;
-// 	}
+	if( size >= RSA_size( rsa ) - 11 ){
+		cerr << "RSA_public_encrypt: data size to large: " << size << ">=" << RSA_size(rsa)-11 << endl;
+		return false;
+	}
 
 	if( RSA_size( rsa ) > *retsize ){
 		cerr << "RSA_public_encrypt: buffer to small ("



More information about the Minisip-devel mailing list