]> git.stg.codes - stg.git/blob - stglibs/crypto.lib/bfstream.cpp
4f376c5d9f5e7d80217ea9ac419328761770b86e
[stg.git] / stglibs / crypto.lib / bfstream.cpp
1 #include "stg/bfstream.h"
2
3 #include "stg/blowfish.h"
4
5 #include <cstring>
6
7 namespace
8 {
9
10 #ifndef BFSTREAM_BUF_SIZE
11 const size_t BUFFER_SIZE = 1024;
12 #else
13 const size_t BUFFER_SIZE = BFSTREAM_BUF_SIZE;
14 #endif
15
16 class COMMON
17 {
18     public:
19         typedef void (* CALLBACK)(const void * block, size_t size, void * data);
20         typedef void (* PROC)(void * dest, const void * source, size_t length, const BLOWFISH_CTX * ctx);
21
22         COMMON(const std::string & key, CALLBACK callback, void * data, PROC proc)
23             : m_ptr(m_buffer),
24               m_callback(callback),
25               m_data(data),
26               m_proc(proc)
27         {
28         InitContext(key.c_str(), key.length(), &m_ctx);
29         }
30
31         void Put(const void * data, size_t size, bool last)
32         {
33         size_t dataSize = m_ptr - m_buffer;
34         if (dataSize + size > sizeof(m_buffer))
35             {
36             memcpy(m_ptr, data, sizeof(m_buffer) - dataSize); // Fill buffer
37             size -= sizeof(m_buffer) - dataSize; // Adjust size
38             data += sizeof(m_buffer) - dataSize; // Adjust data pointer
39             m_proc(m_buffer, m_buffer, sizeof(m_buffer), &m_ctx); // Process
40             m_callback(m_buffer, sizeof(m_buffer), m_data); // Consume
41             m_ptr = m_buffer;
42             }
43         memcpy(m_ptr, data, size);
44         m_ptr += size;
45         m_tryConsume(last);
46         }
47
48     private:
49         char m_buffer[BUFFER_SIZE];
50         char * m_ptr;
51         CALLBACK m_callback;
52         void * m_data;
53         BLOWFISH_CTX m_ctx;
54         PROC m_proc;
55
56         void m_tryConsume(bool last)
57         {
58         size_t dataSize = (m_ptr - m_buffer) & ~7;
59         size_t remainder = m_ptr - m_buffer - dataSize;
60         if (last && remainder > 0)
61             {
62             dataSize += 8;
63             remainder = 0;
64             }
65         if (dataSize == 0)
66             return;
67         m_proc(m_buffer, m_buffer, dataSize, &m_ctx);
68         m_callback(m_buffer, dataSize, m_data);
69         if (remainder > 0)
70             memmove(m_buffer, m_buffer + dataSize, remainder);
71         m_ptr = m_buffer + remainder;
72         }
73 };
74
75 } // namespace anonymous
76
77 using STG::ENCRYPT_STREAM;
78 using STG::DECRYPT_STREAM;
79
80 class ENCRYPT_STREAM::IMPL : public COMMON
81 {
82     public:
83         IMPL(const std::string & key, CALLBACK callback, void * data)
84             : COMMON(key, callback, data, EncryptString)
85         {}
86 };
87
88 class DECRYPT_STREAM::IMPL : public COMMON
89 {
90     public:
91         IMPL(const std::string & key, CALLBACK callback, void * data)
92             : COMMON(key, callback, data, DecryptString)
93         {}
94 };
95
96 ENCRYPT_STREAM::ENCRYPT_STREAM(const std::string & key, CALLBACK callback, void * data)
97     : m_impl(new IMPL(key, callback, data))
98 {}
99
100 ENCRYPT_STREAM::~ENCRYPT_STREAM()
101 {
102 delete m_impl;
103 }
104
105 void ENCRYPT_STREAM::Put(const void * data, size_t size, bool last)
106 {
107 m_impl->Put(data, size, last);
108 }
109
110 DECRYPT_STREAM::DECRYPT_STREAM(const std::string & key, CALLBACK callback, void * data)
111     : m_impl(new IMPL(key, callback, data))
112 {}
113
114 DECRYPT_STREAM::~DECRYPT_STREAM()
115 {
116 delete m_impl;
117 }
118
119 void DECRYPT_STREAM::Put(const void * data, size_t size, bool last)
120 {
121 m_impl->Put(data, size, last);
122 }