WvStreams
|
00001 /* 00002 * Worldvisions Tunnel Vision Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * A 'counter mode' cryptography engine abstraction. 00006 */ 00007 #include "wvcountermode.h" 00008 00009 00010 WvCounterModeEncoder::WvCounterModeEncoder(WvEncoder *_keycrypt, 00011 const void *_counter, size_t _countersize) : 00012 keycrypt(_keycrypt), counter(NULL) 00013 { 00014 setcounter(_counter, _countersize); 00015 } 00016 00017 00018 WvCounterModeEncoder::~WvCounterModeEncoder() 00019 { 00020 delete keycrypt; 00021 deletev counter; 00022 } 00023 00024 00025 void WvCounterModeEncoder::setcounter(const void *_counter, size_t _countersize) 00026 { 00027 deletev counter; 00028 counter = new unsigned char[_countersize]; 00029 countersize = _countersize; 00030 memcpy(counter, _counter, countersize); 00031 } 00032 00033 00034 void WvCounterModeEncoder::getcounter(void *_counter) const 00035 { 00036 memcpy(_counter, counter, countersize); 00037 } 00038 00039 00040 void WvCounterModeEncoder::incrcounter() 00041 { 00042 for (size_t i = 0; i < countersize && ! ++counter[i]; ++i); 00043 } 00044 00045 00046 bool WvCounterModeEncoder::_encode(WvBuf &inbuf, WvBuf &outbuf, 00047 bool flush) 00048 { 00049 bool success = true; 00050 size_t avail = inbuf.used(); 00051 size_t offset = outbuf.used(); 00052 00053 // generate a key stream 00054 size_t len; 00055 for (len = avail; len >= countersize; len -= countersize) 00056 { 00057 counterbuf.reset(counter, countersize); 00058 success = keycrypt->encode(counterbuf, outbuf, true); 00059 if (! success) break; 00060 incrcounter(); 00061 } 00062 if (flush && len != 0 && success) 00063 { 00064 counterbuf.reset(counter, countersize); 00065 success = keycrypt->encode(counterbuf, outbuf, true); 00066 if (success) 00067 { 00068 outbuf.unalloc(countersize - len); 00069 len = 0; 00070 incrcounter(); 00071 } 00072 else 00073 outbuf.unalloc(outbuf.used() - offset - avail); 00074 } 00075 avail -= len; 00076 00077 // XOR in the data 00078 while (avail > 0) 00079 { 00080 len = outbuf.optpeekable(offset); 00081 unsigned char *dataout = outbuf.mutablepeek(offset, len); 00082 size_t lenopt = inbuf.optgettable(); 00083 if (len > lenopt) 00084 len = lenopt; 00085 const unsigned char *datain = inbuf.get(len); 00086 00087 if (len >= avail) 00088 { 00089 len = avail; 00090 avail = 0; 00091 } 00092 else 00093 { 00094 avail -= len; 00095 offset += len; 00096 } 00097 while (len-- > 0) 00098 *(dataout++) ^= *(datain++); 00099 } 00100 return success; 00101 }