|
IBR-DTNSuite 0.6
|
00001 #include "ibrcommon/ssl/AES128Stream.h" 00002 #include "ibrcommon/Logger.h" 00003 #include <openssl/rand.h> 00004 #include <cstring> 00005 #include <netinet/in.h> 00006 00007 namespace ibrcommon 00008 { 00009 AES128Stream::AES128Stream(const CipherMode mode, std::ostream& output, const unsigned char key[key_size_in_bytes], const u_int32_t salt) 00010 : CipherStream(output, mode) 00011 { 00012 // init gcm and load the key into the context 00013 if (gcm_init_and_key(key, key_size_in_bytes, &_ctx)) 00014 IBRCOMMON_LOGGER(critical) << "failed to initialize aes gcm context" << IBRCOMMON_LOGGER_ENDL; 00015 00016 // convert the salt to network byte order 00017 _gcm_iv.salt = htonl(salt); 00018 00019 // generate a random IV 00020 if (!RAND_bytes(_gcm_iv.initialisation_vector, iv_len)) 00021 IBRCOMMON_LOGGER(critical) << "failed to create initialization vector" << IBRCOMMON_LOGGER_ENDL; 00022 00023 // copy the IV to a local array 00024 for (unsigned int i = 0; i < iv_len; i++) 00025 _used_initialisation_vector[i] = _gcm_iv.initialisation_vector[i]; 00026 00027 // init the GCM message 00028 gcm_init_message(reinterpret_cast<unsigned char *>(&_gcm_iv), sizeof(gcm_iv), &_ctx); 00029 } 00030 00031 AES128Stream::AES128Stream(const CipherMode mode, std::ostream& output, const unsigned char key[key_size_in_bytes], const u_int32_t salt, const unsigned char iv[iv_len]) 00032 : CipherStream(output, mode) 00033 { 00034 // init gcm and load the key into the context 00035 if (gcm_init_and_key(key, key_size_in_bytes, &_ctx)) 00036 IBRCOMMON_LOGGER(critical) << "failed to initialize aes gcm context" << IBRCOMMON_LOGGER_ENDL; 00037 00038 // convert the salt to network byte order 00039 _gcm_iv.salt = htonl(salt); 00040 00041 // copy the IV to local variables 00042 for (unsigned int i = 0; i < iv_len; i++) 00043 { 00044 _gcm_iv.initialisation_vector[i] = iv[i]; 00045 _used_initialisation_vector[i] = iv[i]; 00046 } 00047 00048 // init the GCM message 00049 gcm_init_message(reinterpret_cast<unsigned char *>(&_gcm_iv), sizeof(gcm_iv), &_ctx); 00050 } 00051 00052 AES128Stream::~AES128Stream() 00053 { 00054 // close the GCM context 00055 gcm_end(&_ctx); 00056 } 00057 00058 void AES128Stream::getIV(unsigned char (&to_iv)[iv_len]) const 00059 { 00060 for (unsigned int i = 0; i < iv_len; i++) 00061 to_iv[i] = _used_initialisation_vector[i]; 00062 } 00063 00064 void AES128Stream::getTag(unsigned char (&to_tag)[tag_len]) 00065 { 00066 ret_type rr = gcm_compute_tag((unsigned char*)to_tag, tag_len, &_ctx); 00067 00068 if (rr != RETURN_OK) 00069 throw ibrcommon::Exception("tag generation failed"); 00070 } 00071 00072 bool AES128Stream::verify(const unsigned char (&verify_tag)[tag_len]) 00073 { 00074 try { 00075 // compute the current tag 00076 unsigned char tag[tag_len]; getTag(tag); 00077 00078 // compare the tags 00079 return (::memcmp(tag, verify_tag, tag_len) == 0); 00080 } catch (const ibrcommon::Exception&) { 00081 return false; 00082 } 00083 } 00084 00085 void AES128Stream::encrypt(char *buf, const size_t size) 00086 { 00087 gcm_encrypt(reinterpret_cast<unsigned char *>(buf), size, &_ctx); 00088 } 00089 00090 void AES128Stream::decrypt(char *buf, const size_t size) 00091 { 00092 gcm_decrypt(reinterpret_cast<unsigned char *>(buf), size, &_ctx); 00093 } 00094 }