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 
34 static int _encodeData(const uint8_t *ptr,
35  uint32_t len,
36  uint8_t *pOutData,
37  uint32_t *pOutLen,
38  const uint8_t *pKey)
39 {
40  GWEN_CRYPT_KEY *k;
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 
67 static 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;
81  GWEN_CRYPT_KEY *ck;
82 
85  3);
86  if (ck==NULL) {
87  DBG_ERROR(GWEN_LOGDOMAIN, "here");
88  GWEN_Buffer_free(tbuf2);
89  GWEN_Buffer_free(tbuf1);
90  return GWEN_ERROR_INTERNAL;
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 
136 static 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 
158 static int _decodeData(const uint8_t *ptr,
159  uint32_t len,
160  uint8_t *pOutData,
161  uint32_t *pOutLen,
162  const uint8_t *pKey)
163 {
164  GWEN_CRYPT_KEY *k;
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 
183 static 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 */
226  GWEN_Buffer_GetStart(tbuf2),
227  GWEN_Buffer_GetUsedBytes(tbuf2));
228  GWEN_Buffer_free(tbuf2);
229  GWEN_Buffer_free(tbuf1);
230 
231  return 0;
232 }
233 
234 
235 
236 
237 
238 
239 int 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);
264  GWEN_MDigest_free(md);
265  return rv;
266  }
267  GWEN_MDigest_free(md);
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 
346 int 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);
377  GWEN_MDigest_free(md);
378  return rv;
379  }
380  GWEN_MDigest_free(md);
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 
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
void GWEN_MDigest_free(GWEN_MDIGEST *md)
Definition: mdigest.c:54
int GWEN_Buffer_AllocRoom(GWEN_BUFFER *bf, uint32_t size)
Definition: buffer.c:285
#define GWEN_ERROR_INVALID
Definition: error.h:67
uint32_t GWEN_Buffer_GetUsedBytes(const GWEN_BUFFER *bf)
Definition: buffer.c:277
void GWEN_Crypt_Key_free(GWEN_CRYPT_KEY *k)
Definition: cryptkey.c:154
#define NULL
Definition: binreloc.c:300
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
int GWEN_Buffer_AdjustUsedBytes(GWEN_BUFFER *bf)
Definition: buffer.c:469
#define BLOWFISH_KEYSIZE
Definition: smalltresor.c:29
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
#define GWEN_LOGDOMAIN
Definition: logger.h:35
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:42
char * GWEN_Buffer_GetPosPointer(const GWEN_BUFFER *bf)
Definition: buffer.c:549
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:650
int GWEN_Buffer_IncrementPos(GWEN_BUFFER *bf, uint32_t i)
Definition: buffer.c:452
#define GWEN_ERROR_DECRYPT
Definition: error.h:102
static int _decodeData(const uint8_t *ptr, uint32_t len, uint8_t *pOutData, uint32_t *pOutLen, const uint8_t *pKey)
Definition: smalltresor.c:158
#define GWEN_ERROR_BAD_DATA
Definition: error.h:121
GWEN_CRYPT_KEY * GWEN_Crypt_KeyBlowFish_Generate(GWEN_CRYPT_CRYPTMODE mode, int keySize, int quality)
Definition: cryptkeysym.c:677
int GWEN_Padd_UnpaddWithIso9796_2(GWEN_BUFFER *buf)
Definition: padd.c:196
static int _encode(const uint8_t *p, uint32_t len, GWEN_BUFFER *buf, int iterations)
Definition: smalltresor.c:67
struct GWEN_MDIGEST GWEN_MDIGEST
Definition: mdigest.h:25
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:394
int GWEN_Padd_PaddWithIso9796_2(GWEN_BUFFER *buf, int dstSize)
Definition: padd.c:148
struct GWEN_CRYPT_KEY GWEN_CRYPT_KEY
Definition: cryptkey.h:26
static int _encodeData(const uint8_t *ptr, uint32_t len, uint8_t *pOutData, uint32_t *pOutLen, const uint8_t *pKey)
Definition: smalltresor.c:34
uint8_t * GWEN_Crypt_KeyBlowFish_GetKeyDataPtr(const GWEN_CRYPT_KEY *k)
Definition: cryptkeysym.c:720
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:89
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
void GWEN_Crypt_Random(int quality, uint8_t *buffer, uint32_t len)
Definition: cryptdefs.c:551
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
GWEN_CRYPT_KEY * GWEN_Crypt_KeyBlowFish_fromData(GWEN_CRYPT_CRYPTMODE mode, int keySize, const uint8_t *kd, uint32_t kl)
Definition: cryptkeysym.c:687
GWENHYWFAR_API GWEN_MDIGEST * GWEN_MDigest_Sha256_new(void)
Definition: mdigestgc.c:194
static int _addRandomBytes(GWEN_BUFFER *dst, int withLength)
Definition: smalltresor.c:136
static int _decode(const uint8_t *p, uint32_t len, GWEN_BUFFER *dst, int iterations)
Definition: smalltresor.c:183
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
int GWEN_Buffer_AppendBytes(GWEN_BUFFER *bf, const char *buffer, uint32_t size)
Definition: buffer.c:361
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
#define GWEN_ERROR_INTERNAL
Definition: error.h:125
#define GWEN_ERROR_ENCRYPT
Definition: error.h:101
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