gwenhywfar  4.3.1
smalltresor.c
Go to the documentation of this file.
00001 /***************************************************************************
00002     begin       : Wed May 11 2010
00003     copyright   : (C) 2010 by Martin Preuss
00004     email       : martin@libchipcard.de
00005 
00006  ***************************************************************************
00007  *          Please see toplevel file COPYING for license details           *
00008  ***************************************************************************/
00009 
00010 #ifdef HAVE_CONFIG_H
00011 # include <config.h>
00012 #endif
00013 
00014 #define DISABLE_DEBUGLOG
00015 
00016 
00017 #include "smalltresor.h"
00018 
00019 #include <gwenhywfar/mdigest.h>
00020 #include <gwenhywfar/cryptkey.h>
00021 #include <gwenhywfar/cryptdefs.h>
00022 #include <gwenhywfar/cryptkeysym.h>
00023 #include <gwenhywfar/padd.h>
00024 #include <gwenhywfar/text.h>
00025 #include <gwenhywfar/debug.h>
00026 
00027 
00028 
00029 #define BLOWFISH_KEYSIZE 32
00030 
00031 
00032 
00033 
00034 static int _encodeData(const uint8_t *ptr,
00035                        uint32_t len,
00036                        uint8_t *pOutData,
00037                        uint32_t *pOutLen,
00038                        const uint8_t *pKey) {
00039   GWEN_CRYPT_KEY *k;
00040   int rv;
00041 
00042   k=GWEN_Crypt_KeyBlowFish_fromData(GWEN_Crypt_CryptMode_Cbc,
00043                                     BLOWFISH_KEYSIZE,
00044                                     pKey, BLOWFISH_KEYSIZE);
00045   if (!k) {
00046     DBG_ERROR(GWEN_LOGDOMAIN, "Could not create key");
00047     return GWEN_ERROR_ENCRYPT;
00048   }
00049 
00050   rv=GWEN_Crypt_Key_Encipher(k,
00051                              ptr, len,
00052                              pOutData, pOutLen);
00053   if (rv<0) {
00054     DBG_ERROR(GWEN_LOGDOMAIN, "Error on GWEN_Crypt_Key_Encipher(len=%d, *outLen=%d): %d",
00055               len, *pOutLen, rv);
00056     GWEN_Crypt_Key_free(k);
00057     return rv;
00058   }
00059   GWEN_Crypt_Key_free(k);
00060 
00061   return 0;
00062 }
00063 
00064 
00065 
00066 static int _encode(const uint8_t *p, uint32_t len, GWEN_BUFFER *buf, int iterations) {
00067   GWEN_BUFFER *tbuf1;
00068   GWEN_BUFFER *tbuf2;
00069   int i;
00070   int rv;
00071   uint8_t *pDest;
00072   uint32_t lDest;
00073 
00074   tbuf1=GWEN_Buffer_new(0, 256, 0, 1);
00075   tbuf2=GWEN_Buffer_new(0, 256, 0, 1);
00076 
00077   for (i=0; i<iterations; i++) {
00078     GWEN_BUFFER *tmpbufptr;
00079     GWEN_CRYPT_KEY *ck;
00080 
00081     ck=GWEN_Crypt_KeyBlowFish_Generate(GWEN_Crypt_CryptMode_Cbc,
00082                                        BLOWFISH_KEYSIZE,
00083                                        3);
00084     if (ck==NULL) {
00085       DBG_ERROR(GWEN_LOGDOMAIN, "here");
00086       GWEN_Buffer_free(tbuf2);
00087       GWEN_Buffer_free(tbuf1);
00088       return GWEN_ERROR_INTERNAL;
00089     }
00090 
00091     lDest=len;
00092     GWEN_Buffer_AllocRoom(tbuf1, lDest);
00093     pDest=(uint8_t*)GWEN_Buffer_GetPosPointer(tbuf1);
00094 
00095     rv=GWEN_Crypt_Key_Encipher(ck, p, len, pDest, &lDest);
00096     if (rv<0) {
00097       DBG_ERROR(GWEN_LOGDOMAIN, "Error on GWEN_Crypt_Key_Encipher(len=%d): %d", len, rv);
00098       GWEN_Crypt_Key_free(ck);
00099       GWEN_Buffer_free(tbuf2);
00100       GWEN_Buffer_free(tbuf1);
00101       return rv;
00102     }
00103 
00104     GWEN_Buffer_IncrementPos(tbuf1, lDest);
00105     GWEN_Buffer_AdjustUsedBytes(tbuf1);
00106 
00107     /* append key */
00108     GWEN_Buffer_AppendBytes(tbuf1,
00109                             (const char*) GWEN_Crypt_KeyBlowFish_GetKeyDataPtr(ck),
00110                             BLOWFISH_KEYSIZE);
00111     GWEN_Crypt_Key_free(ck);
00112 
00113     /* swap buffers */
00114     tmpbufptr=tbuf2;
00115     tbuf2=tbuf1;
00116     tbuf1=tmpbufptr;
00117     /* reset buffer 1, point to buffer 2 for next iteration */
00118     GWEN_Buffer_Reset(tbuf1);
00119     p=(uint8_t*)GWEN_Buffer_GetStart(tbuf2);
00120     len=GWEN_Buffer_GetUsedBytes(tbuf2);
00121   }
00122 
00123   /* add data from last round to buffer */
00124   GWEN_Buffer_AppendBytes(buf, (const char*) p, len);
00125 
00126   GWEN_Buffer_free(tbuf2);
00127   GWEN_Buffer_free(tbuf1);
00128 
00129   return 0;
00130 }
00131 
00132 
00133 
00134 static int _addRandomBytes(GWEN_BUFFER *dst, int withLength) {
00135   uint8_t v1[2];
00136   uint16_t len;
00137 
00138   GWEN_Crypt_Random(3, v1, sizeof(v1));
00139   len=((v1[0]<<8)+v1[1]) & 0x3fff;
00140 
00141   if (withLength) {
00142     GWEN_Buffer_AppendByte(dst, (len>>8) & 0xff);
00143     GWEN_Buffer_AppendByte(dst, len & 0xff);
00144   }
00145   GWEN_Buffer_AllocRoom(dst, len);
00146   GWEN_Crypt_Random(3, (uint8_t*) GWEN_Buffer_GetPosPointer(dst), len);
00147   GWEN_Buffer_IncrementPos(dst, len);
00148   GWEN_Buffer_AdjustUsedBytes(dst);
00149 
00150   return 0;
00151 }
00152 
00153 
00154 
00155 static int _decodeData(const uint8_t *ptr,
00156                        uint32_t len,
00157                        uint8_t *pOutData,
00158                        uint32_t *pOutLen,
00159                        const uint8_t *pKey) {
00160   GWEN_CRYPT_KEY *k;
00161   int rv;
00162 
00163   k=GWEN_Crypt_KeyBlowFish_fromData(GWEN_Crypt_CryptMode_Cbc,
00164                                     BLOWFISH_KEYSIZE,
00165                                     pKey, BLOWFISH_KEYSIZE);
00166   if (!k) {
00167     return GWEN_ERROR_DECRYPT;
00168   }
00169 
00170   rv=GWEN_Crypt_Key_Decipher(k, ptr, len, pOutData, pOutLen);
00171   GWEN_Crypt_Key_free(k);
00172   if (rv)
00173     return rv;
00174   return 0;
00175 }
00176 
00177 
00178 
00179 static int _decode(const uint8_t *p, uint32_t len, GWEN_BUFFER *dst, int iterations) {
00180   GWEN_BUFFER *tbuf1;
00181   GWEN_BUFFER *tbuf2;
00182   int i;
00183   int rv;
00184   uint8_t *pDest;
00185   uint32_t lDest;
00186   uint8_t key[BLOWFISH_KEYSIZE];
00187 
00188   tbuf1=GWEN_Buffer_new(0, 256, 0, 1);
00189   tbuf2=GWEN_Buffer_new(0, 256, 0, 1);
00190 
00191   for (i=0; i<iterations; i++) {
00192     GWEN_BUFFER *tmpbufptr;
00193 
00194     /* last 16 bytes are the key for the next data */
00195     memmove(key, p+(len-sizeof(key)), sizeof(key));
00196     len-=sizeof(key);
00197     lDest=len;
00198     GWEN_Buffer_AllocRoom(tbuf1, lDest);
00199     pDest=(uint8_t*)GWEN_Buffer_GetPosPointer(tbuf1);
00200     /* only unpadd for last loop */
00201     rv=_decodeData(p, len, pDest, &lDest, key);
00202     if (rv) {
00203       GWEN_Buffer_free(tbuf2);
00204       GWEN_Buffer_free(tbuf1);
00205       return rv;
00206     }
00207     GWEN_Buffer_IncrementPos(tbuf1, lDest);
00208     GWEN_Buffer_AdjustUsedBytes(tbuf1);
00209     /* swap buffers */
00210     tmpbufptr=tbuf2;
00211     tbuf2=tbuf1;
00212     tbuf1=tmpbufptr;
00213     /* reset buffer 1, point to buffer 2 for next iteration */
00214     GWEN_Buffer_Reset(tbuf1);
00215     p=(const uint8_t*)GWEN_Buffer_GetStart(tbuf2);
00216     len=GWEN_Buffer_GetUsedBytes(tbuf2);
00217   }
00218 
00219   /* return buffer */
00220   GWEN_Buffer_AppendBytes(dst,
00221                           GWEN_Buffer_GetStart(tbuf2),
00222                           GWEN_Buffer_GetUsedBytes(tbuf2));
00223   GWEN_Buffer_free(tbuf2);
00224   GWEN_Buffer_free(tbuf1);
00225 
00226   return 0;
00227 }
00228 
00229 
00230 
00231 
00232 
00233 
00234 int GWEN_SmallTresor_Encrypt(const uint8_t *src,
00235                              uint32_t slen,
00236                              const char *password,
00237                              GWEN_BUFFER *dst,
00238                              int passwordIterations,
00239                              int cryptIterations) {
00240   GWEN_BUFFER *tbuf;
00241   GWEN_BUFFER *xbuf;
00242   uint32_t x;
00243   const uint8_t *p;
00244   uint8_t *pDest;
00245   uint32_t lDest;
00246   uint32_t len;
00247   int rv;
00248   GWEN_MDIGEST *md;
00249   uint8_t salt[128];
00250   uint8_t key[BLOWFISH_KEYSIZE];
00251 
00252   /* first derive the key from the given password */
00253   GWEN_Crypt_Random(3, salt, sizeof(salt));
00254   md=GWEN_MDigest_Sha256_new();
00255   rv=GWEN_MDigest_PBKDF2(md, password, salt, sizeof(salt), key, BLOWFISH_KEYSIZE, passwordIterations);
00256   if (rv<0) {
00257     DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
00258     GWEN_MDigest_free(md);
00259     return rv;
00260   }
00261   GWEN_MDigest_free(md);
00262 
00263   tbuf=GWEN_Buffer_new(0, slen+(cryptIterations*BLOWFISH_KEYSIZE), 0, 1);
00264 
00265   /* add random bytes at the beginning */
00266   rv=_addRandomBytes(tbuf, 1);
00267   if (rv<0) {
00268     DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
00269     GWEN_Buffer_free(tbuf);
00270     return rv;
00271   }
00272 
00273   /* add length of data */
00274   GWEN_Buffer_AppendByte(tbuf, (slen>>8) & 0xff);
00275   GWEN_Buffer_AppendByte(tbuf, slen & 0xff);
00276 
00277   /* add data itself */
00278   GWEN_Buffer_AppendBytes(tbuf, (const char*) src, slen);
00279 
00280   /* add random bytes at the end (without length marker) */
00281   rv=_addRandomBytes(tbuf, 0);
00282   if (rv<0) {
00283     DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
00284     GWEN_Buffer_free(tbuf);
00285     return rv;
00286   }
00287 
00288   /* padd using iso 9796_2 */
00289   len=GWEN_Buffer_GetUsedBytes(tbuf);
00290   x=(len+7+12) & ~0x7;
00291   rv=GWEN_Padd_PaddWithIso9796_2(tbuf, x);
00292   if (rv<0) {
00293     DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
00294     GWEN_Buffer_free(tbuf);
00295     return rv;
00296   }
00297 
00298   /* actually encode the data into xbuf */
00299   xbuf=GWEN_Buffer_new(0, GWEN_Buffer_GetUsedBytes(tbuf)+(cryptIterations*BLOWFISH_KEYSIZE), 0, 1);
00300   rv=_encode((const uint8_t*) GWEN_Buffer_GetStart(tbuf),
00301              GWEN_Buffer_GetUsedBytes(tbuf),
00302              xbuf,
00303              cryptIterations);
00304   if (rv<0) {
00305     DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
00306     GWEN_Buffer_free(xbuf);
00307     GWEN_Buffer_free(tbuf);
00308     return rv;
00309   }
00310   GWEN_Buffer_free(tbuf);
00311 
00312   /* append salt (including length) to dst buffer */
00313   len=sizeof(salt);
00314   GWEN_Buffer_AppendByte(dst, (len>>8) & 0xff);
00315   GWEN_Buffer_AppendByte(dst, len & 0xff);
00316   GWEN_Buffer_AppendBytes(dst, (const char*) salt, len);
00317 
00318   /* final round */
00319   p=(const uint8_t*) GWEN_Buffer_GetStart(xbuf);
00320   len=GWEN_Buffer_GetUsedBytes(xbuf);
00321 
00322   GWEN_Buffer_AllocRoom(dst, len);
00323   pDest=(uint8_t*)GWEN_Buffer_GetPosPointer(dst);
00324   lDest=len;
00325   rv=_encodeData(p, len, pDest, &lDest, key);
00326   if (rv<0) {
00327     GWEN_Buffer_free(xbuf);
00328     return rv;
00329   }
00330   GWEN_Buffer_IncrementPos(dst, lDest);
00331   GWEN_Buffer_AdjustUsedBytes(dst);
00332 
00333   GWEN_Buffer_free(xbuf);
00334 
00335   return 0;
00336 }
00337 
00338 
00339 
00340 int GWEN_SmallTresor_Decrypt(const uint8_t *p,
00341                              uint32_t len,
00342                              const char *password,
00343                              GWEN_BUFFER *dst,
00344                              int passwordIterations,
00345                              int cryptIterations) {
00346   GWEN_BUFFER *tbuf1;
00347   GWEN_BUFFER *tbuf2;
00348   int rv;
00349   uint8_t *pDest;
00350   uint32_t lDest;
00351   GWEN_MDIGEST *md;
00352   uint8_t key[BLOWFISH_KEYSIZE];
00353 
00354   if (len<2) {
00355     DBG_ERROR(GWEN_LOGDOMAIN, "Invalid data length");
00356     return GWEN_ERROR_INVALID;
00357   }
00358 
00359   /* first derive the key from the given password */
00360   lDest=(p[0]<<8)+p[1];
00361   if (lDest>len-2) {
00362     DBG_ERROR(GWEN_LOGDOMAIN, "Invalid salt length");
00363     return GWEN_ERROR_BAD_DATA;
00364   }
00365 
00366   md=GWEN_MDigest_Sha256_new();
00367   rv=GWEN_MDigest_PBKDF2(md, password, p+2, lDest, key, BLOWFISH_KEYSIZE, passwordIterations);
00368   if (rv<0) {
00369     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00370     GWEN_MDigest_free(md);
00371     return rv;
00372   }
00373   GWEN_MDigest_free(md);
00374 
00375   /* remove salt from input */
00376   p+=2+lDest;
00377   len-=2+lDest;
00378 
00379   /* check size */
00380   if (len<(BLOWFISH_KEYSIZE*cryptIterations)) {
00381     DBG_ERROR(GWEN_LOGDOMAIN, "Data too small");
00382     return GWEN_ERROR_INVALID;
00383   }
00384 
00385   /* now decrypt first round */
00386   tbuf1=GWEN_Buffer_new(0, len, 0, 1);
00387   GWEN_Buffer_AllocRoom(tbuf1, len);
00388 
00389   pDest=(uint8_t*)GWEN_Buffer_GetPosPointer(tbuf1);
00390   lDest=len;
00391   rv=_decodeData(p, len, pDest, &lDest, key);
00392   if (rv<0) {
00393     GWEN_Buffer_free(tbuf1);
00394     return rv;
00395   }
00396   GWEN_Buffer_IncrementPos(tbuf1, lDest);
00397   GWEN_Buffer_AdjustUsedBytes(tbuf1);
00398 
00399   /* decode the next rounds */
00400   p=(const uint8_t*) GWEN_Buffer_GetStart(tbuf1);
00401   len=GWEN_Buffer_GetUsedBytes(tbuf1);
00402   tbuf2=GWEN_Buffer_new(0, len, 0, 1);
00403   rv=_decode(p, len, tbuf2, cryptIterations);
00404   if (rv<0) {
00405     GWEN_Buffer_free(tbuf2);
00406     GWEN_Buffer_free(tbuf1);
00407     return rv;
00408   }
00409   GWEN_Buffer_free(tbuf1);
00410 
00411   /* unpadd */
00412   rv=GWEN_Padd_UnpaddWithIso9796_2(tbuf2);
00413   if (rv<0) {
00414     GWEN_Buffer_free(tbuf2);
00415     return rv;
00416   }
00417 
00418   /* extract data */
00419   p=(const uint8_t*) GWEN_Buffer_GetStart(tbuf2);
00420   len=GWEN_Buffer_GetUsedBytes(tbuf2);
00421 
00422   /* skip random bytes at the beginning */
00423   lDest=(p[0]<<8)+p[1];
00424   if (lDest>len-2) {
00425     DBG_ERROR(GWEN_LOGDOMAIN, "Invalid random area length");
00426     GWEN_Buffer_free(tbuf2);
00427     return GWEN_ERROR_BAD_DATA;
00428   }
00429   p+=2+lDest;
00430   len-=2+lDest;
00431 
00432   /* get size of data */
00433   lDest=(p[0]<<8)+p[1];
00434   if (lDest>len-2) {
00435     DBG_ERROR(GWEN_LOGDOMAIN, "Invalid data length");
00436     GWEN_Buffer_free(tbuf2);
00437     return GWEN_ERROR_BAD_DATA;
00438   }
00439   p+=2;
00440   len-=2;
00441   GWEN_Buffer_AppendBytes(dst, (const char*) p, lDest);
00442 
00443   GWEN_Buffer_free(tbuf2);
00444 
00445   return 0;
00446 }
00447 
00448 
00449 
00450 
00451 
00452 
00453