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