00001
00002
00003
00004
00005
00006
00007
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
00108 GWEN_Buffer_AppendBytes(tbuf1,
00109 (const char*) GWEN_Crypt_KeyBlowFish_GetKeyDataPtr(ck),
00110 BLOWFISH_KEYSIZE);
00111 GWEN_Crypt_Key_free(ck);
00112
00113
00114 tmpbufptr=tbuf2;
00115 tbuf2=tbuf1;
00116 tbuf1=tmpbufptr;
00117
00118 GWEN_Buffer_Reset(tbuf1);
00119 p=(uint8_t*)GWEN_Buffer_GetStart(tbuf2);
00120 len=GWEN_Buffer_GetUsedBytes(tbuf2);
00121 }
00122
00123
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
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
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
00210 tmpbufptr=tbuf2;
00211 tbuf2=tbuf1;
00212 tbuf1=tmpbufptr;
00213
00214 GWEN_Buffer_Reset(tbuf1);
00215 p=(const uint8_t*)GWEN_Buffer_GetStart(tbuf2);
00216 len=GWEN_Buffer_GetUsedBytes(tbuf2);
00217 }
00218
00219
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
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
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
00274 GWEN_Buffer_AppendByte(tbuf, (slen>>8) & 0xff);
00275 GWEN_Buffer_AppendByte(tbuf, slen & 0xff);
00276
00277
00278 GWEN_Buffer_AppendBytes(tbuf, (const char*) src, slen);
00279
00280
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
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
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
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
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
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
00376 p+=2+lDest;
00377 len-=2+lDest;
00378
00379
00380 if (len<(BLOWFISH_KEYSIZE*cryptIterations)) {
00381 DBG_ERROR(GWEN_LOGDOMAIN, "Data too small");
00382 return GWEN_ERROR_INVALID;
00383 }
00384
00385
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
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
00412 rv=GWEN_Padd_UnpaddWithIso9796_2(tbuf2);
00413 if (rv<0) {
00414 GWEN_Buffer_free(tbuf2);
00415 return rv;
00416 }
00417
00418
00419 p=(const uint8_t*) GWEN_Buffer_GetStart(tbuf2);
00420 len=GWEN_Buffer_GetUsedBytes(tbuf2);
00421
00422
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
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