mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 22:02:58 -06:00
Better name when creating generic cypher pointers git-svn-id: svn://ultimatepp.org/upp/trunk@2760 f0d560ea-af0d-0410-9eb7-867de7ffcac7
337 lines
7.6 KiB
C++
337 lines
7.6 KiB
C++
#include "CypherBase.h"
|
|
|
|
NAMESPACE_UPP
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
// CypherFifo class //
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// inserts data
|
|
void CypherFifo::Put(byte const *buf, int len)
|
|
{
|
|
int l = data.GetCount();
|
|
data.AddN(len);
|
|
byte *b = &data.At(l);
|
|
memcpy(b, buf, len);
|
|
}
|
|
|
|
void CypherFifo::Put(String const &s)
|
|
{
|
|
Put((byte const *)~s, s.GetCount());
|
|
}
|
|
|
|
void CypherFifo::Put(byte b)
|
|
{
|
|
data.Add(b);
|
|
}
|
|
|
|
// extract data
|
|
bool CypherFifo::Get(byte *buf, int len)
|
|
{
|
|
if(data.GetCount() < len)
|
|
return false;
|
|
memcpy(buf, &data.At(0), len);
|
|
data.Remove(0, len);
|
|
return true;
|
|
}
|
|
|
|
bool CypherFifo::Get(String &s)
|
|
{
|
|
if(!data.GetCount())
|
|
return false;
|
|
StringBuffer sb;
|
|
sb.Cat((const char *)&data.At(0), data.GetCount());
|
|
data.Clear();
|
|
s = sb;
|
|
return true;
|
|
}
|
|
|
|
bool CypherFifo::Get(byte &b)
|
|
{
|
|
if(!data.GetCount())
|
|
return false;
|
|
b = data.At(0);
|
|
data.Remove(0);
|
|
return true;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
// Cypher class //
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Cypher::Cypher(size_t _blockSize)
|
|
{
|
|
// still no key present
|
|
keyOk = false;
|
|
|
|
// Cypher in IDLE mode at startup
|
|
mode = IDLE;
|
|
|
|
// clears FIFO
|
|
FIFO.Clear();
|
|
|
|
// sets the encryption block size
|
|
blockSize = _blockSize;
|
|
|
|
// resets total stream size
|
|
// should be set BEFORE streaming (decoding)
|
|
// if we want the resulting stream truncated on right length
|
|
// otherwise we get also the pad bytes
|
|
streamSize = 0;
|
|
|
|
}
|
|
|
|
void Cypher::Reset()
|
|
{
|
|
keyOk = false;
|
|
mode = IDLE;
|
|
FIFO.Clear();
|
|
streamSize = 0;
|
|
}
|
|
|
|
// set mode (either STREAM or BLOCK
|
|
// throws an exception if another mode was already active
|
|
void Cypher::SetMode(Mode m)
|
|
{
|
|
// checks if another mode already in progress, if so throws an exception
|
|
if(mode != m && mode != IDLE)
|
|
throw "A different encoding mode was already in progress";
|
|
|
|
// if starting stream mode, allocate block buffer if
|
|
// working with a Block-Cypher
|
|
if(m == STREAM_MODE && mode == IDLE && blockSize > 1)
|
|
{
|
|
// allocates block buffer and set pointer to its start
|
|
blockBuffer.Alloc(blockSize);
|
|
blockBytes = 0;
|
|
|
|
// resets streamedIn and streamedOut values
|
|
streamedIn = streamedOut = 0;
|
|
}
|
|
mode = m;
|
|
}
|
|
|
|
// checks if key was set, otherwise throws an exception
|
|
void Cypher::CheckKey(void)
|
|
{
|
|
if(!keyOk)
|
|
throw "Missing key";
|
|
}
|
|
|
|
// checks buffer size if it must be multiple of block size
|
|
// for Block-Cyphers. Throws an exception if not
|
|
void Cypher::CheckBufSize(size_t bufSize)
|
|
{
|
|
if(blockSize == 1)
|
|
return;
|
|
if(bufSize % blockSize)
|
|
throw "Buffer size mismatch - not a multiple of block size";
|
|
}
|
|
|
|
// rounds buffer size to nearest bigger multiple of block size
|
|
size_t Cypher::RoundBufSize(size_t bufSize)
|
|
{
|
|
size_t rem = bufSize % blockSize;
|
|
if(rem)
|
|
bufSize += blockSize - rem;
|
|
return bufSize;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// key setting
|
|
void Cypher::SetKey(byte const *keyBuf, size_t keyLen, byte const *_nonce, size_t nonceLen)
|
|
{
|
|
nonce.Clear();
|
|
if(!_nonce || !nonceLen)
|
|
{
|
|
for(size_t i = 0; i < 8; i++)
|
|
nonce.Cat(Random() & 0xff);
|
|
}
|
|
else
|
|
{
|
|
for(size_t i = 0; i < nonceLen; i++)
|
|
nonce.Cat(_nonce[i]);
|
|
}
|
|
if(!CypherKey(keyBuf, keyLen, (const byte *)~nonce, nonce.GetCount()))
|
|
throw "Invalid key";
|
|
keyOk = true;
|
|
}
|
|
|
|
void Cypher::SetKey(String const &key, String const &nonce)
|
|
{
|
|
if(IsNull(nonce))
|
|
SetKey((byte const *)~key, key.GetCount(), NULL, 0);
|
|
else
|
|
SetKey((byte const *)~key, key.GetCount(), (byte const *)~nonce, nonce.GetCount());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// encrypt/decrypt functions
|
|
String Cypher::operator()(String const &s)
|
|
{
|
|
// checks if KEY is ok, exception if not
|
|
CheckKey();
|
|
|
|
// sets buffer mode, exception if already in stream mode
|
|
SetMode(BUFFER_MODE);
|
|
|
|
// checks buffer size, exception if not multiple of block size
|
|
CheckBufSize(s.GetCount());
|
|
|
|
StringBuffer sb(s.GetCount());
|
|
CypherCypher((const byte *)~s, (byte *)~sb, s.GetCount());
|
|
return sb;
|
|
}
|
|
|
|
void Cypher::operator()(byte const *sourceBuf, byte *destBuf, size_t bufLen)
|
|
{
|
|
// checks if KEY is ok, exception if not
|
|
CheckKey();
|
|
|
|
// sets buffer mode, exception if already in stream mode
|
|
SetMode(BUFFER_MODE);
|
|
|
|
// checks buffer size, exception if not multiple of block size
|
|
CheckBufSize(bufLen);
|
|
|
|
CypherCypher(sourceBuf, destBuf, bufLen);
|
|
}
|
|
|
|
void Cypher::operator()(byte *buf, size_t bufLen)
|
|
{
|
|
// checks if KEY is ok, exception if not
|
|
CheckKey();
|
|
|
|
// sets buffer mode, exception if already in stream mode
|
|
SetMode(BUFFER_MODE);
|
|
|
|
// checks buffer size, exception if not multiple of block size
|
|
CheckBufSize(bufLen);
|
|
|
|
CypherCypher(buf, buf, bufLen);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// streaming support
|
|
String Cypher::StreamOut(void)
|
|
{
|
|
// checks if KEY is ok, exception if not
|
|
CheckKey();
|
|
|
|
// sets stream mode, exception if already in buffer mode
|
|
SetMode(STREAM_MODE);
|
|
|
|
String res;
|
|
FIFO.Get(res);
|
|
|
|
// if blockSize == 1 OR user didn't set stream size, simple behaviour
|
|
if(blockSize != 1 && streamSize != 0)
|
|
{
|
|
if(streamedOut >= streamSize)
|
|
return "";
|
|
if(streamedOut + res.GetCount() > streamSize)
|
|
res = res.Left(streamSize - streamedOut);
|
|
}
|
|
|
|
// returns encoded buffer from FIFO
|
|
streamedOut += res.GetCount();
|
|
return res;
|
|
}
|
|
|
|
void Cypher::StreamIn(String const &s)
|
|
{
|
|
// checks if KEY is ok, exception if not
|
|
CheckKey();
|
|
|
|
// sets stream mode, exception if already in buffer mode
|
|
SetMode(STREAM_MODE);
|
|
|
|
// simpler streaming if blockSize == 1
|
|
if(blockSize == 1)
|
|
{
|
|
// en/decode string and put into FIFO
|
|
StringBuffer sb(s.GetCount());
|
|
CypherCypher((const byte *)~s, (byte *)~sb, s.GetCount());
|
|
FIFO.Put(sb);
|
|
}
|
|
else
|
|
{
|
|
size_t len = s.GetCount();
|
|
size_t idx = 0;
|
|
|
|
// if block buffer is partially filled, try to finish it before
|
|
if(blockBytes)
|
|
{
|
|
size_t count = min(len, blockSize - blockBytes);
|
|
idx += count;
|
|
len -= count;
|
|
memcpy(blockBuffer + blockBytes, ~s, count);
|
|
blockBytes += count;
|
|
if(blockBytes >= blockSize)
|
|
{
|
|
CypherCypher(blockBuffer, blockBuffer, blockSize);
|
|
FIFO.Put(blockBuffer, blockSize);
|
|
blockBytes = 0;
|
|
}
|
|
}
|
|
|
|
// stream in full block buffers
|
|
if(len)
|
|
{
|
|
// get number of bytes composing FULL blocks
|
|
size_t count = len - (len % blockSize);
|
|
|
|
if(count)
|
|
{
|
|
Buffer<byte> buf(count);
|
|
CypherCypher((const byte *)~s + idx, buf, count);
|
|
FIFO.Put(buf, count);
|
|
len -= count;
|
|
idx += count;
|
|
}
|
|
}
|
|
|
|
// fills block buffer with remaining data, if any
|
|
if(len)
|
|
{
|
|
memcpy(blockBuffer, ~s + idx, len);
|
|
blockBytes = len;
|
|
}
|
|
}
|
|
|
|
// updates number of streamed-in bytes
|
|
streamedIn += s.GetCount();
|
|
}
|
|
|
|
size_t Cypher::Flush(void)
|
|
{
|
|
// checks if KEY is ok, exception if not
|
|
CheckKey();
|
|
|
|
// sets stream mode, exception if already in buffer mode
|
|
SetMode(STREAM_MODE);
|
|
|
|
// nothing to do on Stream-Cyphers, just return stream total size
|
|
if(blockSize == 1)
|
|
return streamedIn;
|
|
|
|
// on block stream, we should pad partial data (if any)
|
|
// and encrypt them; we pad them with plain random data
|
|
if(blockBytes)
|
|
{
|
|
for(size_t i = blockBytes; i < blockSize; i++)
|
|
blockBuffer[i] = (byte)(Random() & 0xff);
|
|
|
|
CypherCypher(blockBuffer, blockBuffer, blockSize);
|
|
FIFO.Put(blockBuffer, blockSize);
|
|
blockBytes = 0;
|
|
}
|
|
|
|
// return the true streamed-in byte count, not the padded one
|
|
return streamedIn;
|
|
|
|
};
|
|
|
|
|
|
END_UPP_NAMESPACE
|