20 #ifndef _ANCH_CRYPTO_BC_MODOP_H_    21 #define _ANCH_CRYPTO_BC_MODOP_H_    23 #include "crypto/cipher/invalidBlockException.hpp"    29 #include <condition_variable>    33 #include "threadPool.hpp"    48     template<
typename Derived, 
typename Cipher>
    56       bool _cipherParallelizable;
    59       bool _decipherParallelizable;
    62       unsigned int _nbThread;
    65       std::mutex _streamMutex;
    68       std::condition_variable _writeBlock;
    71       std::atomic<uint32_t> _endIdx;
    74       std::atomic<uint32_t> _writeIdx;
    77       std::atomic<bool> _error;
    80       std::ostream* _stream;
    95                                  bool decipherParallelizable,
    96                                  unsigned int nbThread = 1):
    97         _cipherParallelizable(cipherParallelizable),
    98         _decipherParallelizable(decipherParallelizable),
   104         if(nbThread == 0 && (cipherParallelizable || decipherParallelizable)) {
   105           _nbThread = std::thread::hardware_concurrency();
   134                   std::ostream& output,
   135                   const std::string& key) {
   136         if(input && output) {
   138           if(!_cipherParallelizable || _nbThread == 1) {
   139             cipherSequentially(input, output, key);
   142             cipherInParallel(input, output, key);
   157                     std::ostream& output,
   158                     const std::string& key) {
   159         if(input && output) {
   160           std::array<uint8_t,Cipher::getBlockSize()> prevData = 
reset();
   161           if(!_decipherParallelizable || _nbThread == 1) {
   162             decipherSequentially(input, output, key, prevData);
   165             decipherInParallel(input, output, key, prevData);
   185       virtual std::size_t 
cipherBlock(std::array<uint8_t,Cipher::getBlockSize()>& input,
   186                                       std::streamsize nbRead,
   187                                       std::array<uint8_t,Cipher::getBlockSize()>& output,
   205       virtual std::size_t 
decipherBlock(std::array<uint8_t,Cipher::getBlockSize()>& input,
   206                                         std::array<uint8_t,Cipher::getBlockSize()>& prevInput,
   207                                         std::streamsize nbRead,
   209                                         std::array<uint8_t,Cipher::getBlockSize()>& output,
   218       virtual const std::array<uint8_t,Cipher::getBlockSize()>& 
reset() = 0;
   228       inline void cipherSequentially(std::istream& input,
   229                                      std::ostream& output,
   230                                      const std::string& key) {
   231         Cipher 
cipher(reinterpret_cast<const uint8_t*>(key.data()));
   232         std::array<uint8_t, Cipher::getBlockSize()> data;
   233         std::array<uint8_t, Cipher::getBlockSize()> out;
   235         while(!input.eof()) {
   236           input.read(reinterpret_cast<char*>(data.data()), Cipher::getBlockSize());
   237           std::streamsize nbRead = input.gcount();
   241           std::size_t nbBlocks = 
cipherBlock(data, nbRead, out, index, cipher);
   242           for(std::size_t i = 0 ; i < nbBlocks ; ++i) {
   257       inline void cipherInParallel(std::istream& input,
   258                                    std::ostream& output,
   259                                    const std::string& key) {
   260         std::array<uint8_t,Cipher::getBlockSize()>* data = 
new std::array<uint8_t,Cipher::getBlockSize()>[_nbThread];
   261         std::array<uint8_t,Cipher::getBlockSize()>* result = 
new std::array<uint8_t,Cipher::getBlockSize()>[_nbThread];
   262         std::size_t* nbWrite = 
new std::size_t[_nbThread];
   264         std::deque<std::thread> threads;
   265         std::vector<Cipher> ciph;
   266         ciph.push_back(Cipher(reinterpret_cast<const uint8_t*>(key.data())));
   267         for(std::size_t i = 1 ; i < _nbThread ; ++i) {
   268           ciph.push_back(Cipher(ciph[0]));
   270         while(!input.eof()) {
   271           for(std::size_t i = 0 ; i < _nbThread ; ++i) {
   272             input.read(reinterpret_cast<char*>(data[i].data()), Cipher::getBlockSize());
   273             std::streamsize nbRead = input.gcount();
   277             threads.push_back(std::thread(&Derived::deferredCipherBlock,
   284                                           std::ref(nbWrite[i])));
   285             if(nbRead != Cipher::getBlockSize()) {
   289           for(uint32_t i = 0 ; !threads.empty() ; ++i) {
   290             std::thread& th = threads.front();
   292             for(uint32_t j = 0 ; j < nbWrite[i] ; ++j) {
   293               output << result[i][j];
   313       void decipherSequentially(std::istream& input,
   314                                 std::ostream& output,
   315                                 const std::string& key,
   316                                 std::array<uint8_t,Cipher::getBlockSize()>& prevData) {
   317         Cipher 
cipher(reinterpret_cast<const uint8_t*>(key.data()));
   318         std::array<uint8_t,Cipher::getBlockSize()> out;
   319         std::array<uint8_t,Cipher::getBlockSize()> data;
   320         std::array<uint8_t,Cipher::getBlockSize()> cipherData;
   321         input.read(reinterpret_cast<char*>(data.data()), Cipher::getBlockSize());
   322         std::streamsize nbRead = input.gcount();
   326           std::size_t read = nbRead;
   327           input.read(reinterpret_cast<char*>(data.data()), Cipher::getBlockSize());
   329           std::size_t end = 
decipherBlock(cipherData, prevData, read, input.eof(), out, index, 
cipher);
   330           for(std::size_t i = 0 ; i < end ; ++i) {
   334           prevData = cipherData;
   335           nbRead = input.gcount();
   338         } 
while(nbRead != 0);
   350       inline void decipherInParallel(std::istream& input,
   351                                      std::ostream& output,
   352                                      const std::string& key,
   353                                      std::array<uint8_t,Cipher::getBlockSize()>& prevData) {
   354         std::array<uint8_t,Cipher::getBlockSize()>* data = 
new std::array<uint8_t,Cipher::getBlockSize()>[_nbThread + 1];
   355         std::array<uint8_t,Cipher::getBlockSize()>* result = 
new std::array<uint8_t,Cipher::getBlockSize()>[_nbThread];
   356         std::size_t* nbWrite = 
new std::size_t[_nbThread];
   358         std::deque<std::thread> threads;
   359         std::vector<Cipher> ciph;
   360         ciph.push_back(Cipher(reinterpret_cast<const uint8_t*>(key.data())));
   361         for(std::size_t i = 1 ; i < _nbThread ; ++i) {
   362           ciph.push_back(Cipher(ciph[0]));
   364         bool lastBlock = 
false;
   365         input.read(reinterpret_cast<char*>(data[0].data()), Cipher::getBlockSize());
   366         std::size_t nbRead = input.gcount();
   368           for(std::size_t i = 0, idx = 1 ; i < _nbThread ; ++i, ++idx) {
   369             input.read(reinterpret_cast<char*>(data[idx].data()), Cipher::getBlockSize());
   370             std::streamsize nextCount = input.gcount();
   374             threads.push_back(std::thread(&Derived::deferredDecipherBlock,
   383                                           std::ref(nbWrite[i])));
   390           for(uint32_t i = 0 ; !threads.empty() ; ++i) {
   391             std::thread& th = threads.front();
   393             for(uint32_t j = 0 ; j < nbWrite[i] ; ++j) {
   394               output << result[i][j];
   401           data[0] = data[_nbThread];
   402         } 
while(!input.eof() && !lastBlock);
   418       void deferredCipherBlock(uint32_t index,
   419                                std::array<uint8_t,Cipher::getBlockSize()>& input,
   420                                std::streamsize nbRead,
   421                                std::array<uint8_t,Cipher::getBlockSize()>& output,
   423                                std::size_t& nbWrite) {
   424         nbWrite = 
cipherBlock(input, nbRead, output, index, cipher);
   436       virtual void deferredDecipherBlock(uint32_t index,
   437                                          std::array<uint8_t, Cipher::getBlockSize()>& input,
   438                                          std::array<uint8_t, Cipher::getBlockSize()> prevInput,
   439                                          std::streamsize nbRead,
   441                                          std::array<uint8_t, Cipher::getBlockSize()>& output,
   443                                          std::size_t& nbWrite) {
   445           nbWrite = 
decipherBlock(input, prevInput, nbRead, lastBlock, output, index, cipher);
   461         _nbThread = nbThread;
   470 #endif // _ANCH_CRYPTO_BC_MODOP_H_ void setNbThread(unsigned int nbThread)
Definition: bcModOp.hpp:460
virtual std::size_t cipherBlock(std::array< uint8_t, Cipher::getBlockSize()> &input, std::streamsize nbRead, std::array< uint8_t, Cipher::getBlockSize()> &output, uint32_t index, Cipher &cipher)=0
BlockCipherModeOfOperation(bool cipherParallelizable, bool decipherParallelizable, unsigned int nbThread=1)
Definition: bcModOp.hpp:94
Exception on receiving an invalid block. 
Definition: invalidBlockException.hpp:39
virtual std::size_t decipherBlock(std::array< uint8_t, Cipher::getBlockSize()> &input, std::array< uint8_t, Cipher::getBlockSize()> &prevInput, std::streamsize nbRead, bool lastBlock, std::array< uint8_t, Cipher::getBlockSize()> &output, uint32_t index, Cipher &cipher)=0
Thread pool utility class. 
Definition: threadPool.hpp:45
AnCH framework base namespace. 
Definition: base64.hpp:28
void cipher(std::istream &input, std::ostream &output, const std::string &key)
Definition: bcModOp.hpp:133
Block cipher mode of operation interface. 
Definition: bcModOp.hpp:49
void decipher(std::istream &input, std::ostream &output, const std::string &key)
Definition: bcModOp.hpp:156
virtual const std::array< uint8_t, Cipher::getBlockSize()> & reset()=0
virtual ~BlockCipherModeOfOperation()
Definition: bcModOp.hpp:118