ucommon  7.0.0
About: GNU uCommon C++ is a portable and optimized class framework for writing C++ applications that need to use threads and support concurrent synchronization, and that use sockets, XML parsing, object serialization, thread-optimized string and data structure classes, etc..
  Fossies Dox: ucommon-7.0.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

Loading...
Searching...
No Matches
cipher.cpp
Go to the documentation of this file.
1// Copyright (C) 2010-2014 David Sugar, Tycho Softworks.
2// Copyright (C) 2015 Cherokees of Idaho.
3//
4// This file is part of GNU uCommon C++.
5//
6// GNU uCommon C++ is free software: you can redistribute it and/or modify
7// it under the terms of the GNU Lesser General Public License as published
8// by the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// GNU uCommon C++ is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU Lesser General Public License for more details.
15//
16// You should have received a copy of the GNU Lesser General Public License
17// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
18
19#include "local.h"
20
21static const uint8_t *_salt = NULL;
22static unsigned _rounds = 1;
23
24namespace ucommon {
25
27{
28 char algoname[64];
29
30 enum {
31 NONE, CBC, ECB, CFB, OFB
32 } modeid;
33
34 String::set(algoname, sizeof(algoname), cipher);
35 char *fpart = strchr(algoname, '-');
36 char *lpart = strrchr(algoname, '-');
37
38 modeid = NONE;
39
40 if(lpart) {
41 if(fpart != lpart)
42 *(fpart++) = 0;
43 else
44 ++fpart;
45
46 *(lpart++) = 0;
47 if(eq_case(lpart, "cbc"))
48 modeid = CBC;
49 else if(eq_case(lpart, "ecb"))
50 modeid = ECB;
51 else if(eq_case(lpart, "cfb") || eq_case(lpart, "pgp"))
52 modeid = CFB;
53 else if(eq_case(lpart, "ofb"))
54 modeid = OFB;
55 else
56 modeid = NONE;
57 }
58 else if(eq_case(cipher, "aes128") || eq_case(cipher, "aes"))
59 return GNUTLS_CIPHER_AES_128_CBC;
60 else if(eq_case(cipher, "aes256"))
61 return GNUTLS_CIPHER_AES_256_CBC;
62 else if(eq_case(cipher, "aes192"))
63 return GNUTLS_CIPHER_AES_192_CBC;
64 else if(eq_case(cipher, "arcfour") || eq_case(cipher, "arc4"))
65 return GNUTLS_CIPHER_ARCFOUR_128;
66 else if(eq_case(cipher, "des"))
67 return GNUTLS_CIPHER_DES_CBC;
68 else if(eq_case(cipher, "3des"))
69 return GNUTLS_CIPHER_3DES_CBC;
70 else if(eq_case(cipher, "rc2"))
71 return GNUTLS_CIPHER_RC2_40_CBC;
72 else if(eq_case(cipher, "idea"))
73 return GNUTLS_CIPHER_IDEA_PGP_CFB;
74 else if(eq_case(cipher, "twofish") || eq_case(cipher, "2fish"))
75 return GNUTLS_CIPHER_TWOFISH_PGP_CFB;
76 else if(eq_case(cipher, "blowfish"))
77 return GNUTLS_CIPHER_BLOWFISH_PGP_CFB;
78
79 else if(eq_case(algoname, "cast") || eq_case(algoname, "cast5"))
80 return GNUTLS_CIPHER_CAST5_PGP_CFB;
81
82 switch(modeid) {
83 case CFB:
84 if(eq_case(algoname, "aes")) {
85 if(atoi(fpart) == 128)
86 return GNUTLS_CIPHER_AES128_PGP_CFB;
87 if(atoi(fpart) == 192)
88 return GNUTLS_CIPHER_AES192_PGP_CFB;
89 if(atoi(fpart) == 256)
90 return GNUTLS_CIPHER_AES256_PGP_CFB;
91 return 0;
92 }
93
94 if(eq_case(algoname, "idea"))
95 return GNUTLS_CIPHER_IDEA_PGP_CFB;
96 if(eq_case(algoname, "3des"))
97 return GNUTLS_CIPHER_3DES_PGP_CFB;
98 if(eq_case(algoname, "cast") || eq_case(algoname, "cast5"))
99 return GNUTLS_CIPHER_CAST5_PGP_CFB;
100 if(eq_case(algoname, "twofish") || eq_case(algoname, "2fish"))
101 return GNUTLS_CIPHER_TWOFISH_PGP_CFB;
102 if(eq_case(algoname, "blowfish"))
103 return GNUTLS_CIPHER_BLOWFISH_PGP_CFB;
104 if(eq_case(algoname, "sk"))
105 return GNUTLS_CIPHER_SAFER_SK128_PGP_CFB;
106 return 0;
107 case CBC:
108 if(eq_case(algoname, "aes")) {
109 if(atoi(fpart) == 128)
110 return GNUTLS_CIPHER_AES_128_CBC;
111 if(atoi(fpart) == 192)
112 return GNUTLS_CIPHER_AES_192_CBC;
113 if(atoi(fpart) == 256)
114 return GNUTLS_CIPHER_AES_256_CBC;
115 return 0;
116 }
117 if(eq_case(algoname, "camellia")) {
118 if(atoi(fpart) == 128)
119 return GNUTLS_CIPHER_CAMELLIA_128_CBC;
120 if(atoi(fpart) == 256)
121 return GNUTLS_CIPHER_CAMELLIA_256_CBC;
122 return 0;
123 }
124 if(eq_case(algoname, "3des"))
125 return GNUTLS_CIPHER_3DES_CBC;
126 if(eq_case(algoname, "des"))
127 return GNUTLS_CIPHER_DES_CBC;
128 if(eq_case(algoname, "rc2"))
129 return GNUTLS_CIPHER_RC2_40_CBC;
130 return 0;
131 default:
132 if(eq_case(algoname, "arc4") || eq_case(algoname, "arcfour")) {
133 if(atoi(fpart) == 40)
134 return GNUTLS_CIPHER_ARCFOUR_40;
135 if(atoi(fpart) == 128)
136 return GNUTLS_CIPHER_ARCFOUR_128;
137 }
138 return 0;
139 }
140}
141
142void Cipher::Key::assign(const char *text, size_t size, const uint8_t *salt, unsigned count)
143{
144 if(!hashid || !algoid) {
145 keysize = 0;
146 return;
147 }
148
149 size_t kpos = 0, ivpos = 0;
150 size_t mdlen = gnutls_hash_get_len((MD_ID)hashid);
151 size_t tlen = strlen(text);
152
153 if(!hashid || !mdlen) {
154 clear();
155 return;
156 }
157
158 char previous[MAX_DIGEST_HASHSIZE / 8];
159 uint8_t temp[MAX_DIGEST_HASHSIZE / 8];
160 MD_CTX mdc;
161
162 unsigned prior = 0;
163 unsigned loop;
164
165 if(!salt)
166 salt = _salt;
167
168 if(!count)
169 count = _rounds;
170
171 do {
172 gnutls_hash_init(&mdc, (MD_ID)hashid);
173
174 if(prior++)
175 gnutls_hash(mdc, previous, mdlen);
176
177 gnutls_hash(mdc, text, tlen);
178
179 if(salt)
180 gnutls_hash(mdc, salt, 8);
181
182 gnutls_hash_deinit(mdc, previous);
183
184 for(loop = 1; loop < count; ++loop) {
185 memcpy(temp, previous, mdlen);
186 gnutls_hash_fast((MD_ID)hashid, temp, mdlen, previous);
187 }
188
189 size_t pos = 0;
190 while(kpos < keysize && pos < mdlen)
191 keybuf[kpos++] = previous[pos++];
192 while(ivpos < blksize && pos < mdlen)
193 ivbuf[ivpos++] = previous[pos++];
194 } while(kpos < keysize || ivpos < blksize);
195}
196
197void Cipher::Key::assign(const char *text, size_t size)
198{
199 assign(text, size, _salt, _rounds);
200}
201
202void Cipher::Key::options(const uint8_t *salt, unsigned rounds)
203{
204 _salt = salt;
205 _rounds = rounds;
206}
207
208void Cipher::Key::set(const char *cipher, const char *digest)
209{
210 set(cipher);
211
213}
214
215void Cipher::Key::set(const char *cipher)
216{
217 clear();
218
220
221 if(algoid) {
222 blksize = gnutls_cipher_get_block_size((CIPHER_ID)algoid);
223 keysize = gnutls_cipher_get_key_size((CIPHER_ID)algoid);
224 }
225}
226
227void Cipher::push(uint8_t *address, size_t size)
228{
229}
230
232{
233 keys.clear();
234 if(context) {
235 gnutls_cipher_deinit((CIPHER_CTX)context);
236 context = NULL;
237 }
238}
239
240bool Cipher::has(const char *cipher)
241{
242 return __context::map_cipher(cipher) != 0;
243}
244
245void Cipher::set(const key_t key, mode_t mode, uint8_t *address, size_t size)
246{
247 release();
248
249 bufsize = size;
250 bufmode = mode;
251 bufaddr = address;
252
253 memcpy(&keys, key, sizeof(keys));
254 if(!keys.keysize)
255 return;
256
257 gnutls_datum_t keyinfo, ivinfo;
258 keyinfo.data = keys.keybuf;
259 keyinfo.size = keys.keysize;
260 ivinfo.data = keys.ivbuf;
261 ivinfo.size = keys.blksize;
262
263 gnutls_cipher_init((CIPHER_CTX *)&context, (CIPHER_ID)keys.algoid, &keyinfo, &ivinfo);
264}
265
266size_t Cipher::put(const uint8_t *data, size_t size)
267{
268 if(size % keys.iosize() || !bufaddr)
269 return 0;
270
271 size_t count = 0;
272
273 while(bufsize && size + bufpos > bufsize) {
274 size_t diff = bufsize - bufpos;
275 count += put(data, diff);
276 data += diff;
277 size -= diff;
278 }
279
280 switch(bufmode) {
281 case Cipher::ENCRYPT:
282 gnutls_cipher_encrypt2((CIPHER_CTX)context, (void *)data, size, bufaddr + bufpos, size);
283 break;
284 case Cipher::DECRYPT:
285 gnutls_cipher_decrypt2((CIPHER_CTX)context, data, size, bufaddr + bufpos, size);
286 }
287
288 count += size;
289 if(!count) {
290 release();
291 return 0;
292 }
293 bufpos += size;
294 if(bufsize && bufpos >= bufsize) {
296 bufpos = 0;
297 }
298 return count;
299}
300
301size_t Cipher::pad(const uint8_t *data, size_t size)
302{
303 size_t padsz = 0;
304 uint8_t padbuf[64];
305 const uint8_t *ep;
306
307 if(!bufaddr)
308 return 0;
309
310 switch(bufmode) {
311 case DECRYPT:
312 if(size % keys.iosize())
313 return 0;
314 put(data, size);
315 ep = data + size - 1;
316 bufpos -= *ep;
317 size -= *ep;
318 break;
319 case ENCRYPT:
320 padsz = size % keys.iosize();
321 put(data, size - padsz);
322 if(padsz) {
323 memcpy(padbuf, data + size - padsz, padsz);
324 memset(padbuf + padsz, keys.iosize() - padsz, keys.iosize() - padsz);
325 size = (size - padsz) + keys.iosize();
326 }
327 else {
328 size += keys.iosize();
329 memset(padbuf, keys.iosize(), keys.iosize());
330 }
331
332 put((const uint8_t *)padbuf, keys.iosize());
333 zerofill(padbuf, sizeof(padbuf));
334 }
335
336 flush();
337 return size;
338}
339
340} // namespace ucommon
static cipher_t cipher
Definition: car.cpp:42
Cipher key formed by hash algorithm.
Definition: secure.h:302
uint8_t keybuf[512/8]
Definition: secure.h:319
void assign(const char *key, size_t size, const uint8_t *salt, unsigned rounds)
Definition: cipher.cpp:142
uint8_t ivbuf[512/8]
Definition: secure.h:319
void set(const char *cipher)
Definition: cipher.cpp:215
void clear(void)
Definition: common.cpp:570
size_t iosize(void) const
Definition: secure.h:375
static void options(const uint8_t *salt=NULL, unsigned rounds=1)
Definition: cipher.cpp:202
mode_t bufmode
Definition: secure.h:406
size_t size(void) const
Definition: secure.h:483
void * context
Definition: secure.h:408
secure::keybytes key()
Definition: secure.h:432
uint8_t * bufaddr
Definition: secure.h:407
static bool has(const char *name)
Check if a specific cipher is supported.
Definition: cipher.cpp:240
size_t flush(void)
Push a final cipher block.
Definition: common.cpp:602
void release(void)
Definition: cipher.cpp:231
size_t pad(const uint8_t *address, size_t size)
This is used to process any data unaligned to the blocksize at the end of a cipher session.
Definition: cipher.cpp:301
size_t pos(void) const
Definition: secure.h:487
void set(uint8_t *address, size_t size=0)
Definition: common.cpp:633
size_t bufsize
Definition: secure.h:405
size_t bufpos
Definition: secure.h:405
virtual void push(uint8_t *address, size_t size)
Definition: cipher.cpp:227
size_t put(const uint8_t *data, size_t size)
Process cipher data.
Definition: cipher.cpp:266
void set(const char *text)
Set string object to text of a null terminated string.
Definition: string.cpp:802
static int map_cipher(const char *type)
Definition: cipher.cpp:26
static int map_digest(const char *type)
Definition: digest.cpp:35
static const uint8_t * _salt
Definition: cipher.cpp:21
static unsigned _rounds
Definition: cipher.cpp:22
static void digest(const char *path=NULL)
Definition: mdsum.cpp:97
Common namespace for all ucommon objects.
Definition: access.cpp:23
gnutls_digest_algorithm_t MD_ID
Definition: local.h:54
gnutls_cipher_algorithm_t CIPHER_ID
Definition: local.h:57
gnutls_hash_hd_t MD_CTX
Definition: local.h:55
T & clear(T &o)
Definition: generics.h:416
bool eq_case(char const *s1, char const *s2)
Compare two null terminated strings if equal ignoring case.
Definition: string.h:1699
gnutls_cipher_hd_t CIPHER_CTX
Definition: local.h:56
#define MAX_DIGEST_HASHSIZE
Definition: secure.h:54
static bool temp
Definition: zerofill.cpp:29
static void zerofill(void)
Definition: zerofill.cpp:40