/* * Worldvisions Tunnel Vision Software: * Copyright (C) 1997-2002 Net Integration Technologies, Inc. * * A 'counter mode' cryptography engine abstraction. */ #include "wvcountermode.h" WvCounterModeEncoder::WvCounterModeEncoder(WvEncoder *_keycrypt, const void *_counter, size_t _countersize) : keycrypt(_keycrypt), counter(NULL) { setcounter(_counter, _countersize); } WvCounterModeEncoder::~WvCounterModeEncoder() { delete keycrypt; deletev counter; } void WvCounterModeEncoder::setcounter(const void *_counter, size_t _countersize) { deletev counter; counter = new unsigned char[_countersize]; countersize = _countersize; memcpy(counter, _counter, countersize); } void WvCounterModeEncoder::getcounter(void *_counter) const { memcpy(_counter, counter, countersize); } void WvCounterModeEncoder::incrcounter() { for (size_t i = 0; i < countersize && ! ++counter[i]; ++i); } bool WvCounterModeEncoder::_encode(WvBuf &inbuf, WvBuf &outbuf, bool flush) { bool success = true; size_t avail = inbuf.used(); size_t offset = outbuf.used(); // generate a key stream size_t len; for (len = avail; len >= countersize; len -= countersize) { counterbuf.reset(counter, countersize); success = keycrypt->encode(counterbuf, outbuf, true); if (! success) break; incrcounter(); } if (flush && len != 0 && success) { counterbuf.reset(counter, countersize); success = keycrypt->encode(counterbuf, outbuf, true); if (success) { outbuf.unalloc(countersize - len); len = 0; incrcounter(); } else outbuf.unalloc(outbuf.used() - offset - avail); } avail -= len; // XOR in the data while (avail > 0) { len = outbuf.optpeekable(offset); unsigned char *dataout = outbuf.mutablepeek(offset, len); size_t lenopt = inbuf.optgettable(); if (len > lenopt) len = lenopt; const unsigned char *datain = inbuf.get(len); if (len >= avail) { len = avail; avail = 0; } else { avail -= len; offset += len; } while (len-- > 0) *(dataout++) ^= *(datain++); } return success; }