IBR-DTNSuite  0.8
ibrcommon/ibrcommon/ssl/AES128Stream.cpp
Go to the documentation of this file.
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 }