IBR-DTNSuite
0.8
|
00001 /* 00002 * CipherStream.cpp 00003 * 00004 * Created on: 13.07.2010 00005 * Author: morgenro 00006 */ 00007 00008 #include "ibrcommon/ssl/CipherStream.h" 00009 00010 namespace ibrcommon 00011 { 00012 CipherStream::CipherStream(std::ostream &stream, const CipherMode mode, const size_t buffer) 00013 : std::ostream(this), _stream(stream), _mode(mode), data_buf_(new char[buffer]), data_size_(buffer) 00014 { 00015 setp(data_buf_, data_buf_ + data_size_ - 1); 00016 } 00017 00018 CipherStream::~CipherStream() 00019 { 00020 delete[] data_buf_; 00021 } 00022 00023 void CipherStream::encrypt(std::iostream& stream) 00024 { 00025 char buf[4096]; 00026 while (!stream.eof()) 00027 { 00028 std::ios::pos_type pos = stream.tellg(); 00029 00030 stream.read((char*)&buf, 4096); 00031 size_t bytes = stream.gcount(); 00032 00033 encrypt(buf, bytes); 00034 00035 // clear the error flags if we reached the end of the file 00036 // but need to write some data 00037 if (stream.eof() && (bytes > 0)) stream.clear(); 00038 00039 stream.seekp(pos, std::ios::beg); 00040 stream.write((char*)&buf, bytes); 00041 } 00042 00043 stream.flush(); 00044 encrypt_final(); 00045 } 00046 00047 void CipherStream::decrypt(std::iostream& stream) 00048 { 00049 char buf[4096]; 00050 while (!stream.eof()) 00051 { 00052 std::ios::pos_type pos = stream.tellg(); 00053 00054 stream.read((char*)&buf, 4096); 00055 size_t bytes = stream.gcount(); 00056 00057 decrypt(buf, bytes); 00058 00059 // clear the error flags if we reached the end of the file 00060 // but need to write some data 00061 if (stream.eof() && (bytes > 0)) stream.clear(); 00062 00063 stream.seekp(pos, std::ios::beg); 00064 stream.write((char*)&buf, bytes); 00065 } 00066 00067 stream.flush(); 00068 decrypt_final(); 00069 } 00070 00071 int CipherStream::sync() 00072 { 00073 int ret = std::char_traits<char>::eq_int_type(this->overflow( 00074 std::char_traits<char>::eof()), std::char_traits<char>::eof()) ? -1 00075 : 0; 00076 00077 // do cipher stuff 00078 switch (_mode) 00079 { 00080 case CIPHER_ENCRYPT: 00081 encrypt_final(); 00082 break; 00083 00084 case CIPHER_DECRYPT: 00085 decrypt_final(); 00086 break; 00087 } 00088 00089 return ret; 00090 } 00091 00092 std::char_traits<char>::int_type CipherStream::overflow(std::char_traits<char>::int_type c) 00093 { 00094 char *ibegin = data_buf_; 00095 char *iend = pptr(); 00096 00097 // mark the buffer as free 00098 setp(data_buf_, data_buf_ + data_size_ - 1); 00099 00100 if (!std::char_traits<char>::eq_int_type(c, std::char_traits<char>::eof())) 00101 { 00102 *iend++ = std::char_traits<char>::to_char_type(c); 00103 } 00104 00105 // if there is nothing to send, just return 00106 if ((iend - ibegin) == 0) 00107 { 00108 return std::char_traits<char>::not_eof(c); 00109 } 00110 00111 // do cipher stuff 00112 switch (_mode) 00113 { 00114 case CIPHER_ENCRYPT: 00115 encrypt(data_buf_, (iend - ibegin)); 00116 break; 00117 00118 case CIPHER_DECRYPT: 00119 decrypt(data_buf_, (iend - ibegin)); 00120 break; 00121 } 00122 00123 // write result to stream 00124 _stream.write(data_buf_, (iend - ibegin)); 00125 00126 return std::char_traits<char>::not_eof(c); 00127 } 00128 }