IBR-DTNSuite 0.6

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 <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 }