]> git.stg.codes - stg.git/blob - stglibs/crypto.lib/bfstream.cpp
21a0d55d88d88416dce8e9c332296edc19b3cf1e
[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 bool (* 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               m_ok(true)
28         {
29         InitContext(key.c_str(), key.length(), &m_ctx);
30         memset(m_buffer, 0, sizeof(m_buffer));
31         }
32
33         void Put(const void * data, size_t size, bool last)
34         {
35         size_t dataSize = m_ptr - m_buffer;
36         if (dataSize + size > sizeof(m_buffer))
37             {
38             memcpy(m_ptr, data, sizeof(m_buffer) - dataSize); // Fill buffer
39             size -= sizeof(m_buffer) - dataSize; // Adjust size
40             data = static_cast<const char *>(data) + sizeof(m_buffer) - dataSize; // Adjust data pointer
41             m_proc(m_buffer, m_buffer, sizeof(m_buffer), &m_ctx); // Process
42             m_ok = m_ok && m_callback(m_buffer, sizeof(m_buffer), m_data); // Consume
43             m_ptr = m_buffer;
44             }
45         if (!m_ok)
46             return;
47         memcpy(m_ptr, data, size);
48         m_ptr += size;
49         m_tryConsume(last);
50         }
51
52         bool isOk() const { return m_ok; }
53
54     private:
55         char m_buffer[BUFFER_SIZE];
56         char * m_ptr;
57         CALLBACK m_callback;
58         void * m_data;
59         BLOWFISH_CTX m_ctx;
60         PROC m_proc;
61         bool m_ok;
62
63         void m_tryConsume(bool last)
64         {
65         size_t dataSize = (m_ptr - m_buffer) & ~7;
66         size_t remainder = m_ptr - m_buffer - dataSize;
67         if (last && remainder > 0)
68             {
69             dataSize += 8;
70             remainder = 0;
71             }
72         if (dataSize == 0)
73             return;
74         m_proc(m_buffer, m_buffer, dataSize, &m_ctx);
75         m_ok = m_ok && m_callback(m_buffer, dataSize, m_data);
76         if (!m_ok)
77             return;
78         if (remainder > 0)
79             memmove(m_buffer, m_buffer + dataSize, remainder);
80         m_ptr = m_buffer + remainder;
81         }
82 };
83
84 } // namespace anonymous
85
86 using STG::ENCRYPT_STREAM;
87 using STG::DECRYPT_STREAM;
88
89 class ENCRYPT_STREAM::IMPL : public COMMON
90 {
91     public:
92         IMPL(const std::string & key, CALLBACK callback, void * data)
93             : COMMON(key, callback, data, EncryptString)
94         {}
95 };
96
97 class DECRYPT_STREAM::IMPL : public COMMON
98 {
99     public:
100         IMPL(const std::string & key, CALLBACK callback, void * data)
101             : COMMON(key, callback, data, DecryptString)
102         {}
103 };
104
105 ENCRYPT_STREAM::ENCRYPT_STREAM(const std::string & key, CALLBACK callback, void * data)
106     : m_impl(new IMPL(key, callback, data))
107 {}
108
109 ENCRYPT_STREAM::~ENCRYPT_STREAM()
110 {
111 delete m_impl;
112 }
113
114 void ENCRYPT_STREAM::Put(const void * data, size_t size, bool last)
115 {
116 m_impl->Put(data, size, last);
117 }
118
119 bool ENCRYPT_STREAM::isOk() const
120 {
121 return m_impl->isOk();
122 }
123
124 DECRYPT_STREAM::DECRYPT_STREAM(const std::string & key, CALLBACK callback, void * data)
125     : m_impl(new IMPL(key, callback, data))
126 {}
127
128 DECRYPT_STREAM::~DECRYPT_STREAM()
129 {
130 delete m_impl;
131 }
132
133 void DECRYPT_STREAM::Put(const void * data, size_t size, bool last)
134 {
135 m_impl->Put(data, size, last);
136 }
137
138 bool DECRYPT_STREAM::isOk() const
139 {
140 return m_impl->isOk();
141 }