IBR-DTNSuite  0.8
ibrcommon/ibrcommon/ssl/RSASHA256Stream.cpp
Go to the documentation of this file.
00001 #include "ibrcommon/ssl/RSASHA256Stream.h"
00002 #include "ibrcommon/Logger.h"
00003 #include <openssl/err.h>
00004 
00005 namespace ibrcommon
00006 {
00007         RSASHA256Stream::RSASHA256Stream(EVP_PKEY * const pkey, bool verify)
00008          : ostream(this), out_buf_(new char[BUFF_SIZE]), _pkey(pkey), _verify(verify), _sign_valid(false)
00009         {
00010                 // Initialize get pointer.  This should be zero so that underflow is called upon first read.
00011                 setp(out_buf_, out_buf_ + BUFF_SIZE - 1);
00012                 EVP_MD_CTX_init(&_ctx);
00013 
00014                 if (!_verify)
00015                 {
00016                         if (!EVP_SignInit_ex(&_ctx, EVP_sha256(), NULL))
00017                         {
00018                                 IBRCOMMON_LOGGER(critical) << "failed to initialize the signature function" << IBRCOMMON_LOGGER_ENDL;
00019                                 ERR_print_errors_fp(stderr);
00020                         }
00021                 }
00022                 else
00023                 {
00024                         if (!EVP_VerifyInit_ex(&_ctx, EVP_sha256(), NULL))
00025                         {
00026                                 IBRCOMMON_LOGGER(critical) << "failed to initialize the verfication function" << IBRCOMMON_LOGGER_ENDL;
00027                                 ERR_print_errors_fp(stderr);
00028                         }
00029                 }
00030         }
00031 
00032         RSASHA256Stream::~RSASHA256Stream()
00033         {
00034                 EVP_MD_CTX_cleanup(&_ctx);
00035                 delete[] out_buf_;
00036         }
00037 
00038         void RSASHA256Stream::reset()
00039         {
00040                 EVP_MD_CTX_cleanup(&_ctx);
00041 
00042                 EVP_MD_CTX_init(&_ctx);
00043 
00044                 if (!_verify)
00045                 {
00046                         if (!EVP_SignInit_ex(&_ctx, EVP_sha256(), NULL))
00047                         {
00048                                 IBRCOMMON_LOGGER(critical) << "failed to initialize the signature function" << IBRCOMMON_LOGGER_ENDL;
00049                                 ERR_print_errors_fp(stderr);
00050                         }
00051                 }
00052                 else
00053                 {
00054                         if (!EVP_VerifyInit_ex(&_ctx, EVP_sha256(), NULL))
00055                         {
00056                                 IBRCOMMON_LOGGER(critical) << "failed to initialize the verfication function" << IBRCOMMON_LOGGER_ENDL;
00057                                 ERR_print_errors_fp(stderr);
00058                         }
00059                 }
00060 
00061                 _sign_valid = false;
00062         }
00063 
00064         const std::pair< const int, const std::string > RSASHA256Stream::getSign()
00065         {
00066                 // check if data was feed into the stream and the sign needs to be
00067                 // recalculated
00068                 if (!_sign_valid)
00069                 {
00070                         sync();
00071                         unsigned char * sign = new unsigned char[EVP_PKEY_size(_pkey)];
00072                         unsigned int size;
00073 
00074                         _return_code = EVP_SignFinal(&_ctx, sign, &size, _pkey);
00075 
00076                         _sign = std::string(reinterpret_cast<const char * const>(sign), size);
00077                         delete [] sign;
00078                         _sign_valid = true;
00079                 }
00080                 return std::pair<const int, const std::string>(_return_code, _sign);
00081         }
00082 
00083         int RSASHA256Stream::getVerification(const std::string& their_sign)
00084         {
00085                 // check if data was feed into the stream and the sign needs to be
00086                 // recalculated
00087                 if (!_sign_valid)
00088                 {
00089                         sync();
00090                         _return_code = EVP_VerifyFinal(&_ctx, reinterpret_cast<const unsigned char *>(their_sign.c_str()), their_sign.size(), _pkey);
00091                         _sign_valid = true;
00092                 }
00093                 return _return_code;
00094         }
00095 
00096         int RSASHA256Stream::sync()
00097         {
00098                 int ret = std::char_traits<char>::eq_int_type(this->overflow(
00099                                 std::char_traits<char>::eof()), std::char_traits<char>::eof()) ? -1
00100                                 : 0;
00101 
00102                 return ret;
00103         }
00104 
00105         RSASHA256Stream::traits::int_type RSASHA256Stream::overflow(RSASHA256Stream::traits::int_type c)
00106         {
00107                 char *ibegin = out_buf_;
00108                 char *iend = pptr();
00109 
00110                 // mark the buffer as free
00111                 setp(out_buf_, out_buf_ + BUFF_SIZE - 1);
00112 
00113                 if (!std::char_traits<char>::eq_int_type(c, std::char_traits<char>::eof()))
00114                 {
00115                         //TODO writing one byte after the buffer?
00116                         *iend++ = std::char_traits<char>::to_char_type(c);
00117                 }
00118 
00119                 // if there is nothing to send, just return
00120                 if ((iend - ibegin) == 0)
00121                 {
00122                         return std::char_traits<char>::not_eof(c);
00123                 }
00124 
00125                 if (!_verify)
00126                         // hashing
00127                 {
00128                         if (!EVP_SignUpdate(&_ctx, reinterpret_cast<unsigned char*>(out_buf_), iend - ibegin))
00129                         {
00130                                 IBRCOMMON_LOGGER(critical) << "failed to feed data into the signature function" << IBRCOMMON_LOGGER_ENDL;
00131                                 ERR_print_errors_fp(stderr);
00132                         }
00133                 }
00134                 else
00135                 {
00136                         if (!EVP_VerifyUpdate(&_ctx, reinterpret_cast<unsigned char*>(out_buf_), iend - ibegin))
00137                         {
00138                                 IBRCOMMON_LOGGER(critical) << "failed to feed data into the verfication function" << IBRCOMMON_LOGGER_ENDL;
00139                                 ERR_print_errors_fp(stderr);
00140                         }
00141                 }
00142 
00143                 return std::char_traits<char>::not_eof(c);
00144         }
00145 }