gwenhywfar 5.10.1
smalltresor.c
Go to the documentation of this file.
1/***************************************************************************
2 begin : Wed May 11 2010
3 copyright : (C) 2010 by Martin Preuss
4 email : martin@libchipcard.de
5
6 ***************************************************************************
7 * Please see toplevel file COPYING for license details *
8 ***************************************************************************/
9
10#ifdef HAVE_CONFIG_H
11# include <config.h>
12#endif
13
14#define DISABLE_DEBUGLOG
15
16
17#include "smalltresor.h"
18
19#include <gwenhywfar/mdigest.h>
20#include <gwenhywfar/cryptkey.h>
21#include <gwenhywfar/cryptdefs.h>
22#include <gwenhywfar/cryptkeysym.h>
23#include <gwenhywfar/padd.h>
24#include <gwenhywfar/text.h>
25#include <gwenhywfar/debug.h>
26
27
28
29#define BLOWFISH_KEYSIZE 32
30
31
32
33
34static int _encodeData(const uint8_t *ptr,
35 uint32_t len,
36 uint8_t *pOutData,
37 uint32_t *pOutLen,
38 const uint8_t *pKey)
39{
41 int rv;
42
45 pKey, BLOWFISH_KEYSIZE);
46 if (!k) {
47 DBG_ERROR(GWEN_LOGDOMAIN, "Could not create key");
48 return GWEN_ERROR_ENCRYPT;
49 }
50
52 ptr, len,
53 pOutData, pOutLen);
54 if (rv<0) {
55 DBG_ERROR(GWEN_LOGDOMAIN, "Error on GWEN_Crypt_Key_Encipher(len=%d, *outLen=%d): %d",
56 len, *pOutLen, rv);
58 return rv;
59 }
61
62 return 0;
63}
64
65
66
67static int _encode(const uint8_t *p, uint32_t len, GWEN_BUFFER *buf, int iterations)
68{
69 GWEN_BUFFER *tbuf1;
70 GWEN_BUFFER *tbuf2;
71 int i;
72 int rv;
73 uint8_t *pDest;
74 uint32_t lDest;
75
76 tbuf1=GWEN_Buffer_new(0, 256, 0, 1);
77 tbuf2=GWEN_Buffer_new(0, 256, 0, 1);
78
79 for (i=0; i<iterations; i++) {
80 GWEN_BUFFER *tmpbufptr;
82
85 3);
86 if (ck==NULL) {
88 GWEN_Buffer_free(tbuf2);
89 GWEN_Buffer_free(tbuf1);
91 }
92
93 lDest=len;
94 GWEN_Buffer_AllocRoom(tbuf1, lDest);
95 pDest=(uint8_t *)GWEN_Buffer_GetPosPointer(tbuf1);
96
97 rv=GWEN_Crypt_Key_Encipher(ck, p, len, pDest, &lDest);
98 if (rv<0) {
99 DBG_ERROR(GWEN_LOGDOMAIN, "Error on GWEN_Crypt_Key_Encipher(len=%d): %d", len, rv);
101 GWEN_Buffer_free(tbuf2);
102 GWEN_Buffer_free(tbuf1);
103 return rv;
104 }
105
106 GWEN_Buffer_IncrementPos(tbuf1, lDest);
108
109 /* append key */
111 (const char *) GWEN_Crypt_KeyBlowFish_GetKeyDataPtr(ck),
114
115 /* swap buffers */
116 tmpbufptr=tbuf2;
117 tbuf2=tbuf1;
118 tbuf1=tmpbufptr;
119 /* reset buffer 1, point to buffer 2 for next iteration */
120 GWEN_Buffer_Reset(tbuf1);
121 p=(uint8_t *)GWEN_Buffer_GetStart(tbuf2);
122 len=GWEN_Buffer_GetUsedBytes(tbuf2);
123 }
124
125 /* add data from last round to buffer */
126 GWEN_Buffer_AppendBytes(buf, (const char *) p, len);
127
128 GWEN_Buffer_free(tbuf2);
129 GWEN_Buffer_free(tbuf1);
130
131 return 0;
132}
133
134
135
136static int _addRandomBytes(GWEN_BUFFER *dst, int withLength)
137{
138 uint8_t v1[2];
139 uint16_t len;
140
141 GWEN_Crypt_Random(3, v1, sizeof(v1));
142 len=((v1[0]<<8)+v1[1]) & 0x3fff;
143
144 if (withLength) {
145 GWEN_Buffer_AppendByte(dst, (len>>8) & 0xff);
146 GWEN_Buffer_AppendByte(dst, len & 0xff);
147 }
148 GWEN_Buffer_AllocRoom(dst, len);
149 GWEN_Crypt_Random(3, (uint8_t *) GWEN_Buffer_GetPosPointer(dst), len);
150 GWEN_Buffer_IncrementPos(dst, len);
152
153 return 0;
154}
155
156
157
158static int _decodeData(const uint8_t *ptr,
159 uint32_t len,
160 uint8_t *pOutData,
161 uint32_t *pOutLen,
162 const uint8_t *pKey)
163{
165 int rv;
166
169 pKey, BLOWFISH_KEYSIZE);
170 if (!k) {
171 return GWEN_ERROR_DECRYPT;
172 }
173
174 rv=GWEN_Crypt_Key_Decipher(k, ptr, len, pOutData, pOutLen);
176 if (rv)
177 return rv;
178 return 0;
179}
180
181
182
183static int _decode(const uint8_t *p, uint32_t len, GWEN_BUFFER *dst, int iterations)
184{
185 GWEN_BUFFER *tbuf1;
186 GWEN_BUFFER *tbuf2;
187 int i;
188 int rv;
189 uint8_t *pDest;
190 uint32_t lDest;
191 uint8_t key[BLOWFISH_KEYSIZE];
192
193 tbuf1=GWEN_Buffer_new(0, 256, 0, 1);
194 tbuf2=GWEN_Buffer_new(0, 256, 0, 1);
195
196 for (i=0; i<iterations; i++) {
197 GWEN_BUFFER *tmpbufptr;
198
199 /* last 16 bytes are the key for the next data */
200 memmove(key, p+(len-sizeof(key)), sizeof(key));
201 len-=sizeof(key);
202 lDest=len;
203 GWEN_Buffer_AllocRoom(tbuf1, lDest);
204 pDest=(uint8_t *)GWEN_Buffer_GetPosPointer(tbuf1);
205 /* only unpadd for last loop */
206 rv=_decodeData(p, len, pDest, &lDest, key);
207 if (rv) {
208 GWEN_Buffer_free(tbuf2);
209 GWEN_Buffer_free(tbuf1);
210 return rv;
211 }
212 GWEN_Buffer_IncrementPos(tbuf1, lDest);
214 /* swap buffers */
215 tmpbufptr=tbuf2;
216 tbuf2=tbuf1;
217 tbuf1=tmpbufptr;
218 /* reset buffer 1, point to buffer 2 for next iteration */
219 GWEN_Buffer_Reset(tbuf1);
220 p=(const uint8_t *)GWEN_Buffer_GetStart(tbuf2);
221 len=GWEN_Buffer_GetUsedBytes(tbuf2);
222 }
223
224 /* return buffer */
228 GWEN_Buffer_free(tbuf2);
229 GWEN_Buffer_free(tbuf1);
230
231 return 0;
232}
233
234
235
236
237
238
239int GWEN_SmallTresor_Encrypt(const uint8_t *src,
240 uint32_t slen,
241 const char *password,
242 GWEN_BUFFER *dst,
243 int passwordIterations,
244 int cryptIterations)
245{
246 GWEN_BUFFER *tbuf;
247 GWEN_BUFFER *xbuf;
248 uint32_t x;
249 const uint8_t *p;
250 uint8_t *pDest;
251 uint32_t lDest;
252 uint32_t len;
253 int rv;
254 GWEN_MDIGEST *md;
255 uint8_t salt[128];
256 uint8_t key[BLOWFISH_KEYSIZE];
257
258 /* first derive the key from the given password */
259 GWEN_Crypt_Random(3, salt, sizeof(salt));
261 rv=GWEN_MDigest_PBKDF2(md, password, salt, sizeof(salt), key, BLOWFISH_KEYSIZE, passwordIterations);
262 if (rv<0) {
263 DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
265 return rv;
266 }
268
269 tbuf=GWEN_Buffer_new(0, slen+(cryptIterations*BLOWFISH_KEYSIZE), 0, 1);
270
271 /* add random bytes at the beginning */
272 rv=_addRandomBytes(tbuf, 1);
273 if (rv<0) {
274 DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
275 GWEN_Buffer_free(tbuf);
276 return rv;
277 }
278
279 /* add length of data */
280 GWEN_Buffer_AppendByte(tbuf, (slen>>8) & 0xff);
281 GWEN_Buffer_AppendByte(tbuf, slen & 0xff);
282
283 /* add data itself */
284 GWEN_Buffer_AppendBytes(tbuf, (const char *) src, slen);
285
286 /* add random bytes at the end (without length marker) */
287 rv=_addRandomBytes(tbuf, 0);
288 if (rv<0) {
289 DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
290 GWEN_Buffer_free(tbuf);
291 return rv;
292 }
293
294 /* padd using iso 9796_2 */
295 len=GWEN_Buffer_GetUsedBytes(tbuf);
296 x=(len+7+12) & ~0x7;
297 rv=GWEN_Padd_PaddWithIso9796_2(tbuf, x);
298 if (rv<0) {
299 DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
300 GWEN_Buffer_free(tbuf);
301 return rv;
302 }
303
304 /* actually encode the data into xbuf */
305 xbuf=GWEN_Buffer_new(0, GWEN_Buffer_GetUsedBytes(tbuf)+(cryptIterations*BLOWFISH_KEYSIZE), 0, 1);
306 rv=_encode((const uint8_t *) GWEN_Buffer_GetStart(tbuf),
308 xbuf,
309 cryptIterations);
310 if (rv<0) {
311 DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
312 GWEN_Buffer_free(xbuf);
313 GWEN_Buffer_free(tbuf);
314 return rv;
315 }
316 GWEN_Buffer_free(tbuf);
317
318 /* append salt (including length) to dst buffer */
319 len=sizeof(salt);
320 GWEN_Buffer_AppendByte(dst, (len>>8) & 0xff);
321 GWEN_Buffer_AppendByte(dst, len & 0xff);
322 GWEN_Buffer_AppendBytes(dst, (const char *) salt, len);
323
324 /* final round */
325 p=(const uint8_t *) GWEN_Buffer_GetStart(xbuf);
326 len=GWEN_Buffer_GetUsedBytes(xbuf);
327
328 GWEN_Buffer_AllocRoom(dst, len);
329 pDest=(uint8_t *)GWEN_Buffer_GetPosPointer(dst);
330 lDest=len;
331 rv=_encodeData(p, len, pDest, &lDest, key);
332 if (rv<0) {
333 GWEN_Buffer_free(xbuf);
334 return rv;
335 }
336 GWEN_Buffer_IncrementPos(dst, lDest);
338
339 GWEN_Buffer_free(xbuf);
340
341 return 0;
342}
343
344
345
346int GWEN_SmallTresor_Decrypt(const uint8_t *p,
347 uint32_t len,
348 const char *password,
349 GWEN_BUFFER *dst,
350 int passwordIterations,
351 int cryptIterations)
352{
353 GWEN_BUFFER *tbuf1;
354 GWEN_BUFFER *tbuf2;
355 int rv;
356 uint8_t *pDest;
357 uint32_t lDest;
358 GWEN_MDIGEST *md;
359 uint8_t key[BLOWFISH_KEYSIZE];
360
361 if (len<2) {
362 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid data length");
363 return GWEN_ERROR_INVALID;
364 }
365
366 /* first derive the key from the given password */
367 lDest=(p[0]<<8)+p[1];
368 if (lDest>len-2) {
369 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid salt length");
370 return GWEN_ERROR_BAD_DATA;
371 }
372
374 rv=GWEN_MDigest_PBKDF2(md, password, p+2, lDest, key, BLOWFISH_KEYSIZE, passwordIterations);
375 if (rv<0) {
376 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
378 return rv;
379 }
381
382 /* remove salt from input */
383 p+=2+lDest;
384 len-=2+lDest;
385
386 /* check size */
387 if (len<(BLOWFISH_KEYSIZE*cryptIterations)) {
388 DBG_ERROR(GWEN_LOGDOMAIN, "Data too small");
389 return GWEN_ERROR_INVALID;
390 }
391
392 /* now decrypt first round */
393 tbuf1=GWEN_Buffer_new(0, len, 0, 1);
394 GWEN_Buffer_AllocRoom(tbuf1, len);
395
396 pDest=(uint8_t *)GWEN_Buffer_GetPosPointer(tbuf1);
397 lDest=len;
398 rv=_decodeData(p, len, pDest, &lDest, key);
399 if (rv<0) {
400 GWEN_Buffer_free(tbuf1);
401 return rv;
402 }
403 GWEN_Buffer_IncrementPos(tbuf1, lDest);
405
406 /* decode the next rounds */
407 p=(const uint8_t *) GWEN_Buffer_GetStart(tbuf1);
408 len=GWEN_Buffer_GetUsedBytes(tbuf1);
409 tbuf2=GWEN_Buffer_new(0, len, 0, 1);
410 rv=_decode(p, len, tbuf2, cryptIterations);
411 if (rv<0) {
412 GWEN_Buffer_free(tbuf2);
413 GWEN_Buffer_free(tbuf1);
414 return rv;
415 }
416 GWEN_Buffer_free(tbuf1);
417
418 /* unpadd */
420 if (rv<0) {
421 GWEN_Buffer_free(tbuf2);
422 return rv;
423 }
424
425 /* extract data */
426 p=(const uint8_t *) GWEN_Buffer_GetStart(tbuf2);
427 len=GWEN_Buffer_GetUsedBytes(tbuf2);
428
429 /* skip random bytes at the beginning */
430 lDest=(p[0]<<8)+p[1];
431 if (lDest>len-2) {
432 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid random area length");
433 GWEN_Buffer_free(tbuf2);
434 return GWEN_ERROR_BAD_DATA;
435 }
436 p+=2+lDest;
437 len-=2+lDest;
438
439 /* get size of data */
440 lDest=(p[0]<<8)+p[1];
441 if (lDest>len-2) {
442 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid data length");
443 GWEN_Buffer_free(tbuf2);
444 return GWEN_ERROR_BAD_DATA;
445 }
446 p+=2;
447 len-=2;
448 GWEN_Buffer_AppendBytes(dst, (const char *) p, lDest);
449
450 GWEN_Buffer_free(tbuf2);
451
452 return 0;
453}
454
455
456
457
458
459
460
#define NULL
Definition: binreloc.c:300
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:42
int GWEN_Buffer_IncrementPos(GWEN_BUFFER *bf, uint32_t i)
Definition: buffer.c:452
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:650
int GWEN_Buffer_AdjustUsedBytes(GWEN_BUFFER *bf)
Definition: buffer.c:469
char * GWEN_Buffer_GetPosPointer(const GWEN_BUFFER *bf)
Definition: buffer.c:549
int GWEN_Buffer_AppendBytes(GWEN_BUFFER *bf, const char *buffer, uint32_t size)
Definition: buffer.c:361
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:89
uint32_t GWEN_Buffer_GetUsedBytes(const GWEN_BUFFER *bf)
Definition: buffer.c:277
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
int GWEN_Buffer_AllocRoom(GWEN_BUFFER *bf, uint32_t size)
Definition: buffer.c:285
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:394
@ GWEN_Crypt_CryptMode_Cbc
Definition: cryptalgo.h:60
void GWEN_Crypt_Random(int quality, uint8_t *buffer, uint32_t len)
Definition: cryptdefs.c:551
int GWEN_Crypt_Key_Decipher(GWEN_CRYPT_KEY *k, const uint8_t *pInData, uint32_t inLen, uint8_t *pOutData, uint32_t *pOutLen)
Definition: cryptkey.c:318
void GWEN_Crypt_Key_free(GWEN_CRYPT_KEY *k)
Definition: cryptkey.c:154
int GWEN_Crypt_Key_Encipher(GWEN_CRYPT_KEY *k, const uint8_t *pInData, uint32_t inLen, uint8_t *pOutData, uint32_t *pOutLen)
Definition: cryptkey.c:303
struct GWEN_CRYPT_KEY GWEN_CRYPT_KEY
Definition: cryptkey.h:26
GWEN_CRYPT_KEY * GWEN_Crypt_KeyBlowFish_fromData(GWEN_CRYPT_CRYPTMODE mode, int keySize, const uint8_t *kd, uint32_t kl)
Definition: cryptkeysym.c:687
uint8_t * GWEN_Crypt_KeyBlowFish_GetKeyDataPtr(const GWEN_CRYPT_KEY *k)
Definition: cryptkeysym.c:720
GWEN_CRYPT_KEY * GWEN_Crypt_KeyBlowFish_Generate(GWEN_CRYPT_CRYPTMODE mode, int keySize, int quality)
Definition: cryptkeysym.c:677
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
#define GWEN_ERROR_ENCRYPT
Definition: error.h:101
#define GWEN_ERROR_INTERNAL
Definition: error.h:125
#define GWEN_ERROR_INVALID
Definition: error.h:67
#define GWEN_ERROR_BAD_DATA
Definition: error.h:121
#define GWEN_ERROR_DECRYPT
Definition: error.h:102
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
#define GWEN_LOGDOMAIN
Definition: logger.h:35
void GWEN_MDigest_free(GWEN_MDIGEST *md)
Definition: mdigest.c:54
int GWEN_MDigest_PBKDF2(GWEN_MDIGEST *md, const char *password, const uint8_t *pSalt, uint32_t lSalt, uint8_t *pKey, uint32_t lKey, uint32_t iterations)
Definition: mdigest.c:255
struct GWEN_MDIGEST GWEN_MDIGEST
Definition: mdigest.h:25
GWENHYWFAR_API GWEN_MDIGEST * GWEN_MDigest_Sha256_new(void)
Definition: mdigestgc.c:194
int GWEN_Padd_PaddWithIso9796_2(GWEN_BUFFER *buf, int dstSize)
Definition: padd.c:148
int GWEN_Padd_UnpaddWithIso9796_2(GWEN_BUFFER *buf)
Definition: padd.c:196
static int _decode(const uint8_t *p, uint32_t len, GWEN_BUFFER *dst, int iterations)
Definition: smalltresor.c:183
#define BLOWFISH_KEYSIZE
Definition: smalltresor.c:29
static int _decodeData(const uint8_t *ptr, uint32_t len, uint8_t *pOutData, uint32_t *pOutLen, const uint8_t *pKey)
Definition: smalltresor.c:158
static int _encode(const uint8_t *p, uint32_t len, GWEN_BUFFER *buf, int iterations)
Definition: smalltresor.c:67
static int _encodeData(const uint8_t *ptr, uint32_t len, uint8_t *pOutData, uint32_t *pOutLen, const uint8_t *pKey)
Definition: smalltresor.c:34
static int _addRandomBytes(GWEN_BUFFER *dst, int withLength)
Definition: smalltresor.c:136
int GWEN_SmallTresor_Encrypt(const uint8_t *src, uint32_t slen, const char *password, GWEN_BUFFER *dst, int passwordIterations, int cryptIterations)
Definition: smalltresor.c:239
int GWEN_SmallTresor_Decrypt(const uint8_t *p, uint32_t len, const char *password, GWEN_BUFFER *dst, int passwordIterations, int cryptIterations)
Definition: smalltresor.c:346