gwenhywfar 4.0.3
|
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