gwenhywfar  4.6.0beta
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  GWEN_CRYPT_KEY *k;
40  int rv;
41 
44  pKey, BLOWFISH_KEYSIZE);
45  if (!k) {
46  DBG_ERROR(GWEN_LOGDOMAIN, "Could not create key");
47  return GWEN_ERROR_ENCRYPT;
48  }
49 
51  ptr, len,
52  pOutData, pOutLen);
53  if (rv<0) {
54  DBG_ERROR(GWEN_LOGDOMAIN, "Error on GWEN_Crypt_Key_Encipher(len=%d, *outLen=%d): %d",
55  len, *pOutLen, rv);
57  return rv;
58  }
60 
61  return 0;
62 }
63 
64 
65 
66 static int _encode(const uint8_t *p, uint32_t len, GWEN_BUFFER *buf, int iterations) {
67  GWEN_BUFFER *tbuf1;
68  GWEN_BUFFER *tbuf2;
69  int i;
70  int rv;
71  uint8_t *pDest;
72  uint32_t lDest;
73 
74  tbuf1=GWEN_Buffer_new(0, 256, 0, 1);
75  tbuf2=GWEN_Buffer_new(0, 256, 0, 1);
76 
77  for (i=0; i<iterations; i++) {
78  GWEN_BUFFER *tmpbufptr;
79  GWEN_CRYPT_KEY *ck;
80 
83  3);
84  if (ck==NULL) {
85  DBG_ERROR(GWEN_LOGDOMAIN, "here");
86  GWEN_Buffer_free(tbuf2);
87  GWEN_Buffer_free(tbuf1);
88  return GWEN_ERROR_INTERNAL;
89  }
90 
91  lDest=len;
92  GWEN_Buffer_AllocRoom(tbuf1, lDest);
93  pDest=(uint8_t*)GWEN_Buffer_GetPosPointer(tbuf1);
94 
95  rv=GWEN_Crypt_Key_Encipher(ck, p, len, pDest, &lDest);
96  if (rv<0) {
97  DBG_ERROR(GWEN_LOGDOMAIN, "Error on GWEN_Crypt_Key_Encipher(len=%d): %d", len, rv);
99  GWEN_Buffer_free(tbuf2);
100  GWEN_Buffer_free(tbuf1);
101  return rv;
102  }
103 
104  GWEN_Buffer_IncrementPos(tbuf1, lDest);
106 
107  /* append key */
109  (const char*) GWEN_Crypt_KeyBlowFish_GetKeyDataPtr(ck),
112 
113  /* swap buffers */
114  tmpbufptr=tbuf2;
115  tbuf2=tbuf1;
116  tbuf1=tmpbufptr;
117  /* reset buffer 1, point to buffer 2 for next iteration */
118  GWEN_Buffer_Reset(tbuf1);
119  p=(uint8_t*)GWEN_Buffer_GetStart(tbuf2);
120  len=GWEN_Buffer_GetUsedBytes(tbuf2);
121  }
122 
123  /* add data from last round to buffer */
124  GWEN_Buffer_AppendBytes(buf, (const char*) p, len);
125 
126  GWEN_Buffer_free(tbuf2);
127  GWEN_Buffer_free(tbuf1);
128 
129  return 0;
130 }
131 
132 
133 
134 static int _addRandomBytes(GWEN_BUFFER *dst, int withLength) {
135  uint8_t v1[2];
136  uint16_t len;
137 
138  GWEN_Crypt_Random(3, v1, sizeof(v1));
139  len=((v1[0]<<8)+v1[1]) & 0x3fff;
140 
141  if (withLength) {
142  GWEN_Buffer_AppendByte(dst, (len>>8) & 0xff);
143  GWEN_Buffer_AppendByte(dst, len & 0xff);
144  }
145  GWEN_Buffer_AllocRoom(dst, len);
146  GWEN_Crypt_Random(3, (uint8_t*) GWEN_Buffer_GetPosPointer(dst), len);
147  GWEN_Buffer_IncrementPos(dst, len);
149 
150  return 0;
151 }
152 
153 
154 
155 static int _decodeData(const uint8_t *ptr,
156  uint32_t len,
157  uint8_t *pOutData,
158  uint32_t *pOutLen,
159  const uint8_t *pKey) {
160  GWEN_CRYPT_KEY *k;
161  int rv;
162 
165  pKey, BLOWFISH_KEYSIZE);
166  if (!k) {
167  return GWEN_ERROR_DECRYPT;
168  }
169 
170  rv=GWEN_Crypt_Key_Decipher(k, ptr, len, pOutData, pOutLen);
172  if (rv)
173  return rv;
174  return 0;
175 }
176 
177 
178 
179 static int _decode(const uint8_t *p, uint32_t len, GWEN_BUFFER *dst, int iterations) {
180  GWEN_BUFFER *tbuf1;
181  GWEN_BUFFER *tbuf2;
182  int i;
183  int rv;
184  uint8_t *pDest;
185  uint32_t lDest;
186  uint8_t key[BLOWFISH_KEYSIZE];
187 
188  tbuf1=GWEN_Buffer_new(0, 256, 0, 1);
189  tbuf2=GWEN_Buffer_new(0, 256, 0, 1);
190 
191  for (i=0; i<iterations; i++) {
192  GWEN_BUFFER *tmpbufptr;
193 
194  /* last 16 bytes are the key for the next data */
195  memmove(key, p+(len-sizeof(key)), sizeof(key));
196  len-=sizeof(key);
197  lDest=len;
198  GWEN_Buffer_AllocRoom(tbuf1, lDest);
199  pDest=(uint8_t*)GWEN_Buffer_GetPosPointer(tbuf1);
200  /* only unpadd for last loop */
201  rv=_decodeData(p, len, pDest, &lDest, key);
202  if (rv) {
203  GWEN_Buffer_free(tbuf2);
204  GWEN_Buffer_free(tbuf1);
205  return rv;
206  }
207  GWEN_Buffer_IncrementPos(tbuf1, lDest);
209  /* swap buffers */
210  tmpbufptr=tbuf2;
211  tbuf2=tbuf1;
212  tbuf1=tmpbufptr;
213  /* reset buffer 1, point to buffer 2 for next iteration */
214  GWEN_Buffer_Reset(tbuf1);
215  p=(const uint8_t*)GWEN_Buffer_GetStart(tbuf2);
216  len=GWEN_Buffer_GetUsedBytes(tbuf2);
217  }
218 
219  /* return buffer */
221  GWEN_Buffer_GetStart(tbuf2),
222  GWEN_Buffer_GetUsedBytes(tbuf2));
223  GWEN_Buffer_free(tbuf2);
224  GWEN_Buffer_free(tbuf1);
225 
226  return 0;
227 }
228 
229 
230 
231 
232 
233 
234 int GWEN_SmallTresor_Encrypt(const uint8_t *src,
235  uint32_t slen,
236  const char *password,
237  GWEN_BUFFER *dst,
238  int passwordIterations,
239  int cryptIterations) {
240  GWEN_BUFFER *tbuf;
241  GWEN_BUFFER *xbuf;
242  uint32_t x;
243  const uint8_t *p;
244  uint8_t *pDest;
245  uint32_t lDest;
246  uint32_t len;
247  int rv;
248  GWEN_MDIGEST *md;
249  uint8_t salt[128];
250  uint8_t key[BLOWFISH_KEYSIZE];
251 
252  /* first derive the key from the given password */
253  GWEN_Crypt_Random(3, salt, sizeof(salt));
255  rv=GWEN_MDigest_PBKDF2(md, password, salt, sizeof(salt), key, BLOWFISH_KEYSIZE, passwordIterations);
256  if (rv<0) {
257  DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
258  GWEN_MDigest_free(md);
259  return rv;
260  }
261  GWEN_MDigest_free(md);
262 
263  tbuf=GWEN_Buffer_new(0, slen+(cryptIterations*BLOWFISH_KEYSIZE), 0, 1);
264 
265  /* add random bytes at the beginning */
266  rv=_addRandomBytes(tbuf, 1);
267  if (rv<0) {
268  DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
269  GWEN_Buffer_free(tbuf);
270  return rv;
271  }
272 
273  /* add length of data */
274  GWEN_Buffer_AppendByte(tbuf, (slen>>8) & 0xff);
275  GWEN_Buffer_AppendByte(tbuf, slen & 0xff);
276 
277  /* add data itself */
278  GWEN_Buffer_AppendBytes(tbuf, (const char*) src, slen);
279 
280  /* add random bytes at the end (without length marker) */
281  rv=_addRandomBytes(tbuf, 0);
282  if (rv<0) {
283  DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
284  GWEN_Buffer_free(tbuf);
285  return rv;
286  }
287 
288  /* padd using iso 9796_2 */
289  len=GWEN_Buffer_GetUsedBytes(tbuf);
290  x=(len+7+12) & ~0x7;
291  rv=GWEN_Padd_PaddWithIso9796_2(tbuf, x);
292  if (rv<0) {
293  DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
294  GWEN_Buffer_free(tbuf);
295  return rv;
296  }
297 
298  /* actually encode the data into xbuf */
299  xbuf=GWEN_Buffer_new(0, GWEN_Buffer_GetUsedBytes(tbuf)+(cryptIterations*BLOWFISH_KEYSIZE), 0, 1);
300  rv=_encode((const uint8_t*) GWEN_Buffer_GetStart(tbuf),
302  xbuf,
303  cryptIterations);
304  if (rv<0) {
305  DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
306  GWEN_Buffer_free(xbuf);
307  GWEN_Buffer_free(tbuf);
308  return rv;
309  }
310  GWEN_Buffer_free(tbuf);
311 
312  /* append salt (including length) to dst buffer */
313  len=sizeof(salt);
314  GWEN_Buffer_AppendByte(dst, (len>>8) & 0xff);
315  GWEN_Buffer_AppendByte(dst, len & 0xff);
316  GWEN_Buffer_AppendBytes(dst, (const char*) salt, len);
317 
318  /* final round */
319  p=(const uint8_t*) GWEN_Buffer_GetStart(xbuf);
320  len=GWEN_Buffer_GetUsedBytes(xbuf);
321 
322  GWEN_Buffer_AllocRoom(dst, len);
323  pDest=(uint8_t*)GWEN_Buffer_GetPosPointer(dst);
324  lDest=len;
325  rv=_encodeData(p, len, pDest, &lDest, key);
326  if (rv<0) {
327  GWEN_Buffer_free(xbuf);
328  return rv;
329  }
330  GWEN_Buffer_IncrementPos(dst, lDest);
332 
333  GWEN_Buffer_free(xbuf);
334 
335  return 0;
336 }
337 
338 
339 
340 int GWEN_SmallTresor_Decrypt(const uint8_t *p,
341  uint32_t len,
342  const char *password,
343  GWEN_BUFFER *dst,
344  int passwordIterations,
345  int cryptIterations) {
346  GWEN_BUFFER *tbuf1;
347  GWEN_BUFFER *tbuf2;
348  int rv;
349  uint8_t *pDest;
350  uint32_t lDest;
351  GWEN_MDIGEST *md;
352  uint8_t key[BLOWFISH_KEYSIZE];
353 
354  if (len<2) {
355  DBG_ERROR(GWEN_LOGDOMAIN, "Invalid data length");
356  return GWEN_ERROR_INVALID;
357  }
358 
359  /* first derive the key from the given password */
360  lDest=(p[0]<<8)+p[1];
361  if (lDest>len-2) {
362  DBG_ERROR(GWEN_LOGDOMAIN, "Invalid salt length");
363  return GWEN_ERROR_BAD_DATA;
364  }
365 
367  rv=GWEN_MDigest_PBKDF2(md, password, p+2, lDest, key, BLOWFISH_KEYSIZE, passwordIterations);
368  if (rv<0) {
369  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
370  GWEN_MDigest_free(md);
371  return rv;
372  }
373  GWEN_MDigest_free(md);
374 
375  /* remove salt from input */
376  p+=2+lDest;
377  len-=2+lDest;
378 
379  /* check size */
380  if (len<(BLOWFISH_KEYSIZE*cryptIterations)) {
381  DBG_ERROR(GWEN_LOGDOMAIN, "Data too small");
382  return GWEN_ERROR_INVALID;
383  }
384 
385  /* now decrypt first round */
386  tbuf1=GWEN_Buffer_new(0, len, 0, 1);
387  GWEN_Buffer_AllocRoom(tbuf1, len);
388 
389  pDest=(uint8_t*)GWEN_Buffer_GetPosPointer(tbuf1);
390  lDest=len;
391  rv=_decodeData(p, len, pDest, &lDest, key);
392  if (rv<0) {
393  GWEN_Buffer_free(tbuf1);
394  return rv;
395  }
396  GWEN_Buffer_IncrementPos(tbuf1, lDest);
398 
399  /* decode the next rounds */
400  p=(const uint8_t*) GWEN_Buffer_GetStart(tbuf1);
401  len=GWEN_Buffer_GetUsedBytes(tbuf1);
402  tbuf2=GWEN_Buffer_new(0, len, 0, 1);
403  rv=_decode(p, len, tbuf2, cryptIterations);
404  if (rv<0) {
405  GWEN_Buffer_free(tbuf2);
406  GWEN_Buffer_free(tbuf1);
407  return rv;
408  }
409  GWEN_Buffer_free(tbuf1);
410 
411  /* unpadd */
413  if (rv<0) {
414  GWEN_Buffer_free(tbuf2);
415  return rv;
416  }
417 
418  /* extract data */
419  p=(const uint8_t*) GWEN_Buffer_GetStart(tbuf2);
420  len=GWEN_Buffer_GetUsedBytes(tbuf2);
421 
422  /* skip random bytes at the beginning */
423  lDest=(p[0]<<8)+p[1];
424  if (lDest>len-2) {
425  DBG_ERROR(GWEN_LOGDOMAIN, "Invalid random area length");
426  GWEN_Buffer_free(tbuf2);
427  return GWEN_ERROR_BAD_DATA;
428  }
429  p+=2+lDest;
430  len-=2+lDest;
431 
432  /* get size of data */
433  lDest=(p[0]<<8)+p[1];
434  if (lDest>len-2) {
435  DBG_ERROR(GWEN_LOGDOMAIN, "Invalid data length");
436  GWEN_Buffer_free(tbuf2);
437  return GWEN_ERROR_BAD_DATA;
438  }
439  p+=2;
440  len-=2;
441  GWEN_Buffer_AppendBytes(dst, (const char*) p, lDest);
442 
443  GWEN_Buffer_free(tbuf2);
444 
445  return 0;
446 }
447 
448 
449 
450 
451 
452 
453