diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index 105e3846a..e02e3a557 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -315,6 +315,7 @@ HEADERS += pqi/authssl.h \ pqi/authgpg.h \ pgp/pgphandler.h \ pgp/pgpkeyutil.h \ + pgp/rsaes.h \ pgp/rscertificate.h \ pqi/p3cfgmgr.h \ pqi/p3peermgr.h \ @@ -569,6 +570,7 @@ SOURCES += util/folderiterator.cc \ util/rsthreads.cc \ util/rsversion.cc \ util/rswin.cc \ + util/rsaes.cc \ util/rsrandom.cc \ util/rstickevent.cc \ diff --git a/libretroshare/src/tests/util/Makefile b/libretroshare/src/tests/util/Makefile index f4fb514b6..1a1a06227 100644 --- a/libretroshare/src/tests/util/Makefile +++ b/libretroshare/src/tests/util/Makefile @@ -9,8 +9,8 @@ OPS_TOP_DIR = ../../../../openpgpsdk/src include $(RS_TOP_DIR)/tests/scripts/config.mk ############################################################### -TESTOBJ = dirtest.o sha1_test.o -TESTS = dirtest sha1_test +TESTOBJ = dirtest.o sha1_test.o aes_test.o +TESTS = dirtest sha1_test aes_test all: tests @@ -18,6 +18,8 @@ sha1_test: sha1_test.o $(CC) $(CFLAGS) -o sha1_test sha1_test.o $(LIBS) dirtest: dirtest.o $(CC) $(CFLAGS) -o dirtest dirtest.o $(LIBS) +dirtest: aes_test.o + $(CC) $(CFLAGS) -o aes_test aes_test.o $(LIBS) ############################################################### include $(RS_TOP_DIR)/tests/scripts/rules.mk diff --git a/libretroshare/src/tests/util/aes_test.cc b/libretroshare/src/tests/util/aes_test.cc new file mode 100644 index 000000000..f97fc9c5b --- /dev/null +++ b/libretroshare/src/tests/util/aes_test.cc @@ -0,0 +1,110 @@ + +/* + * "$Id: dirtest.cc,v 1.1 2007-02-19 20:08:30 rmf24 Exp $" + * + * RetroShare C++ Interface. + * + * Copyright 2012-2012 by Cyril Soler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "retroshare@lunamutt.com". + * + */ + + + +#include "util/rsaes.h" +#include "util/utest.h" +#include + +#include +#include +#include +#include + +void printHelp(int argc,char *argv[]) +{ + std::cerr << argv[0] << ": tests AES encryption/decryption functions." << std::endl; + std::cerr << "Usage: " << argv[0] << std::endl ; +} + +void printHex(unsigned char *data,uint32_t length) +{ + static const char outh[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ; + static const char outl[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' } ; + + for(uint32_t j = 0; j < length; j++) + { + std::cerr << outh[ (data[j]>>4) ] ; + std::cerr << outh[ data[j] & 0xf ] ; + } +} + + +INITTEST() ; + +int main(int argc,char *argv[]) +{ + std::string inputfile ; + argstream as(argc,argv) ; + + as >> help() ; + + as.defaultErrorHandling() ; + + std::cerr << "Testing AES crypt" << std::endl; + + std::string source_string = "This is a very secret string ;-)" ; + std::cerr << "Input string: length=" << source_string.length() << ", s=\"" << source_string << "\"" << std::endl; + + unsigned char key_data[16] ; + unsigned char salt[8] ; + + for(int i=0;i<16;++i) + key_data[i] = lrand48() & 0xff ; + + for(int i=0;i<50;++i) + { + for(int j=0;j<8;++j) + salt[j] = lrand48() & 0xff ; + + unsigned char output_data[source_string.size() + 1 + 16] ; + uint32_t output_data_length = source_string.size() + 1 + 16 ; + + CHECK(RsAes::aes_crypt_8_16( (const uint8_t*)source_string.c_str(),source_string.length()+1,key_data,salt,output_data,output_data_length)) ; + + std::cerr << "Round " << i << " salt=" ; + printHex(salt,8) ; + std::cerr << ": " << "output_length = " << output_data_length << ", encrypted string = " ; + printHex(output_data,output_data_length) ; + std::cerr << std::endl; + + unsigned char output_data2[output_data_length + 1 + 16] ; + uint32_t output_data_length2 = output_data_length + 1 + 16 ; + + CHECK(RsAes::aes_decrypt_8_16(output_data,output_data_length,key_data,salt,output_data2,output_data_length2)) ; + +// std::cerr << " output_length = " << output_data_length2 << ", decrypted string = " ; +// printHex(output_data2,output_data_length2) ; +// std::cerr << std::endl; + + CHECK(std::string( (const char *)output_data2,output_data_length2) == source_string) ; + } + + FINALREPORT("Sha1Test") ; + return TESTRESULT() ; +} + diff --git a/libretroshare/src/util/rsaes.cc b/libretroshare/src/util/rsaes.cc new file mode 100644 index 000000000..e1e9d0af1 --- /dev/null +++ b/libretroshare/src/util/rsaes.cc @@ -0,0 +1,118 @@ +/* + * libretroshare/src/utils: rsaes.cc + * + * AES crptography for RetroShare. + * + * Copyright 2013 by Cyril Soler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "csoler@users.sourceforge.net". + * + */ + +#include +#include + +#include "rsaes.h" + +bool RsAes::aes_crypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key_data[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length) +{ + int nrounds = 5; + uint8_t key[32], iv[32]; + + /* + * Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material. + * nrounds is the number of times the we hash the material. More rounds are more secure but + * slower. + */ + int i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, 16, nrounds, key, iv); + + if (i != 32) + { + printf("Key size is %d bits - should be 256 bits\n", i); + return false ; + } + + EVP_CIPHER_CTX e_ctx ; + EVP_CIPHER_CTX_init(&e_ctx); + EVP_EncryptInit_ex(&e_ctx, EVP_aes_256_cbc(), NULL, key, iv); + + /* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 bytes */ + int c_len = input_data_length + AES_BLOCK_SIZE ; + int f_len = 0; + + if(output_data_length < (uint32_t)c_len) + return false ; + + output_data_length = c_len ; + + /* update ciphertext, c_len is filled with the length of ciphertext generated, + *len is the size of plaintext in bytes */ + + EVP_EncryptUpdate(&e_ctx, output_data, &c_len, input_data, input_data_length); + + /* update ciphertext with the final remaining bytes */ + EVP_EncryptFinal_ex(&e_ctx, const_cast(input_data)+c_len, &f_len); + + output_data_length = c_len + f_len; + + return true; +} + +bool RsAes::aes_decrypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key_data[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length) +{ + int nrounds = 5; + uint8_t key[32], iv[32]; + + /* + * Gen key & IV for AES 256 CBC mode. A SHA1 digest is used to hash the supplied key material. + * nrounds is the number of times the we hash the material. More rounds are more secure but + * slower. + */ + int i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt, key_data, 16, nrounds, key, iv); + + if (i != 32) + { + printf("Key size is %d bits - should be 256 bits\n", i); + return false ; + } + + EVP_CIPHER_CTX e_ctx ; + EVP_CIPHER_CTX_init(&e_ctx); + EVP_DecryptInit_ex(&e_ctx, EVP_aes_256_cbc(), NULL, key, iv); + + /* max ciphertext len for a n bytes of plaintext is n + AES_BLOCK_SIZE -1 bytes */ + int c_len = input_data_length + AES_BLOCK_SIZE ; + int f_len = 0; + + if(output_data_length < (uint32_t)c_len) + return false ; + + output_data_length = c_len ; + + /* update ciphertext, c_len is filled with the length of ciphertext generated, + *len is the size of plaintext in bytes */ + + EVP_DecryptUpdate(&e_ctx, output_data, &c_len, input_data, input_data_length); + + /* update ciphertext with the final remaining bytes */ + EVP_DecryptFinal_ex(&e_ctx, const_cast(input_data)+c_len, &f_len); + + output_data_length = c_len + f_len; + + return true; +} + diff --git a/libretroshare/src/util/rsaes.h b/libretroshare/src/util/rsaes.h new file mode 100644 index 000000000..8acf082ce --- /dev/null +++ b/libretroshare/src/util/rsaes.h @@ -0,0 +1,43 @@ +/* + * libretroshare/src/utils: rsaescrypt.h + * + * AES crptography for RetroShare. + * + * Copyright 2013 by Cyril Soler + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License Version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + * + * Please report all bugs and problems to "csoler@users.sourceforge.net". + * + */ + +#include + +class RsAes +{ + public: + // Crypt/decrypt data using a 16 bytes key and a 8 bytes salt. + // + // output_data allocation is left to the client. The size should be at least input_data_length+16 bytes. + // + // Return value: + // true: encryption/decryption ok + // + // false: encryption/decryption went bad. Check buffer size. + // + static bool aes_crypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length) ; + static bool aes_decrypt_8_16(const uint8_t *input_data,uint32_t input_data_length,uint8_t key[16],uint8_t salt[8],uint8_t *output_data,uint32_t& output_data_length) ; +}; +