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