gwenhywfar
4.3.1
|
00001 /*************************************************************************** 00002 begin : Mon Jan 05 2004 00003 copyright : (C) 2004 by Martin Preuss 00004 email : martin@libchipcard.de 00005 00006 *************************************************************************** 00007 * * 00008 * This library is free software; you can redistribute it and/or * 00009 * modify it under the terms of the GNU Lesser General Public * 00010 * License as published by the Free Software Foundation; either * 00011 * version 2.1 of the License, or (at your option) any later version. * 00012 * * 00013 * This library is distributed in the hope that it will be useful, * 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00016 * Lesser General Public License for more details. * 00017 * * 00018 * You should have received a copy of the GNU Lesser General Public * 00019 * License along with this library; if not, write to the Free Software * 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * 00021 * MA 02111-1307 USA * 00022 * * 00023 ***************************************************************************/ 00024 00025 00026 #ifdef HAVE_CONFIG_H 00027 # include <config.h> 00028 #endif 00029 00030 #define DISABLE_DEBUGLOG 00031 00032 00033 #include "padd_p.h" 00034 #include <gwenhywfar/misc.h> 00035 #include <gwenhywfar/debug.h> 00036 #include <gwenhywfar/error.h> 00037 #include <gwenhywfar/cryptdefs.h> 00038 #include <gwenhywfar/text.h> 00039 00040 #include <string.h> 00041 #include <stdlib.h> 00042 00043 00044 static uint8_t nullarray[]={0, 0, 0, 0, 0, 0, 0, 0}; 00045 00046 00047 /* 00048 * This code has been taken from OpenHBCI (rsakey.cpp, written by Fabian 00049 * Kaiser) 00050 */ 00051 unsigned char GWEN_Padd_permutate(unsigned char input) { 00052 unsigned char leftNibble; 00053 unsigned char rightNibble; 00054 static const unsigned char lookUp[2][16] = 00055 {{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}, 00056 {14,3,5,8,9,4,2,15,0,13,11,6,7,10,12,1}}; 00057 00058 rightNibble = input & 15; 00059 leftNibble = input & 240; 00060 leftNibble = leftNibble / 16; 00061 rightNibble = lookUp[1][rightNibble]; 00062 leftNibble = lookUp[1][leftNibble]; 00063 leftNibble = leftNibble * 16; 00064 00065 return leftNibble + rightNibble; 00066 } 00067 00068 00069 00070 /* 00071 * The original code (in C++) has been written by Fabian Kaiser for OpenHBCI 00072 * (file rsakey.cpp). Translated to C by Martin Preuss 00073 */ 00074 int GWEN_Padd_PaddWithISO9796(GWEN_BUFFER *src) { 00075 unsigned char *p; 00076 unsigned int l; 00077 unsigned int i; 00078 unsigned char buffer[GWEN_PADD_ISO9796_KEYSIZE]; 00079 unsigned char hash[20]; 00080 unsigned char c; 00081 00082 p=(unsigned char*)GWEN_Buffer_GetStart(src); 00083 l=GWEN_Buffer_GetUsedBytes(src); 00084 memmove(hash, p, l); 00085 00086 /* src+src+src */ 00087 if (GWEN_Buffer_AppendBytes(src, (const char*)hash, l)) { 00088 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00089 return -1; 00090 } 00091 00092 if (GWEN_Buffer_AppendBytes(src, (const char*)hash, l)) { 00093 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00094 return -1; 00095 } 00096 00097 /* src=src(20,40) */ 00098 if (GWEN_Buffer_Crop(src, 20, 40)) { 00099 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00100 return -1; 00101 } 00102 00103 memset(buffer, 0, sizeof(buffer)); 00104 00105 /* append redundancy */ 00106 p=(unsigned char*)GWEN_Buffer_GetStart(src); 00107 for (i=0; i<=47; i++) { 00108 int j1, j2, j3; 00109 00110 j1=1 + sizeof(buffer) - (2*i); 00111 j2=40-i; 00112 j3=sizeof(buffer) - (2*i); 00113 00114 if (j1>=0 && j1<(int)sizeof(buffer) && j2>=0) { 00115 buffer[j1]=p[j2]; 00116 } 00117 if (j3>=0 && j3<(int)sizeof(buffer) && j2>=0) { 00118 buffer[j3]=GWEN_Padd_permutate(p[j2]); 00119 } 00120 } /* for */ 00121 00122 /* copy last 16 bytes to the beginning */ 00123 memmove(buffer, buffer+(sizeof(buffer)-16), 16); 00124 00125 p=buffer; 00126 /* finish */ 00127 c=p[sizeof(buffer)-1]; 00128 c = (c & 15) * 16; 00129 c += 6; 00130 p[sizeof(buffer)-1]=c; 00131 p[0] = p[0] & 127; 00132 p[0] = p[0] | 64; 00133 p[sizeof(buffer) - 40] = p[sizeof(buffer) - 40] ^ 1; 00134 00135 GWEN_Buffer_Reset(src); 00136 if (GWEN_Buffer_AppendBytes(src, (const char*)buffer, sizeof(buffer))) { 00137 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00138 return -1; 00139 } 00140 00141 return 0; 00142 } 00143 00144 00145 int GWEN_Padd_PaddWithIso9796_2(GWEN_BUFFER *buf, int dstSize){ 00146 unsigned int diff; 00147 char *p; 00148 int i; 00149 00150 if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)+12) { 00151 /*DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data");*/ 00152 return GWEN_ERROR_INVALID; 00153 } 00154 00155 /* add trailer */ 00156 GWEN_Buffer_AppendByte(buf, 0xbc); 00157 00158 /* reset position to 0 */ 00159 GWEN_Buffer_Rewind(buf); 00160 00161 /* insert room for header */ 00162 diff=dstSize-GWEN_Buffer_GetUsedBytes(buf)-11+1; 00163 if (GWEN_Buffer_InsertRoom(buf, 1+diff+1+8)) { 00164 DBG_ERROR(GWEN_LOGDOMAIN, 00165 "Could not insert room for %d bytes", 00166 1+diff+1+8); 00167 return GWEN_ERROR_GENERIC; 00168 } 00169 00170 /* insert header and more-data-bit */ 00171 p=GWEN_Buffer_GetStart(buf); 00172 *(p++)=0x60; 00173 00174 /* insert padding field */ 00175 for (i=0; i<diff; i++) 00176 *(p++)=0x0; 00177 *(p++)=0x01; 00178 00179 /* insert 8 random bytes */ 00180 GWEN_Crypt_Random(2, (uint8_t*)p, 8); 00181 for (i=0; i<8; i++) { 00182 if (*p==0) 00183 /* TODO: Need to find a better but yet fast way */ 00184 *p=0xff; 00185 p++; 00186 } 00187 00188 return 0; 00189 } 00190 00191 00192 int GWEN_Padd_UnpaddWithIso9796_2(GWEN_BUFFER *buf){ 00193 uint32_t l; 00194 uint32_t realSize; 00195 const uint8_t *p; 00196 00197 l=GWEN_Buffer_GetUsedBytes(buf); 00198 if (l<11) { 00199 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too few bytes"); 00200 return GWEN_ERROR_INVALID; 00201 } 00202 00203 p=(const uint8_t*)GWEN_Buffer_GetStart(buf); 00204 if (*p!=0x60) { 00205 DBG_ERROR(GWEN_LOGDOMAIN, "First byte is not a 0x60"); 00206 return GWEN_ERROR_BAD_DATA; 00207 } 00208 p++; 00209 l=0; 00210 while(*p==0x00) { 00211 l++; 00212 p++; 00213 } 00214 if (*p!=0x01) { 00215 /*DBG_ERROR(GWEN_LOGDOMAIN, "First byte after padding is not a 0x01");*/ 00216 return GWEN_ERROR_BAD_DATA; 00217 } 00218 00219 realSize=GWEN_Buffer_GetUsedBytes(buf)-11-l; 00220 GWEN_Buffer_Crop(buf, 10+l, realSize); 00221 00222 return 0; 00223 } 00224 00225 00226 00227 int GWEN_Padd_PaddWithAnsiX9_23ToMultipleOf(GWEN_BUFFER *src, int y) { 00228 unsigned char paddLength; 00229 unsigned int i; 00230 00231 paddLength=y-(GWEN_Buffer_GetUsedBytes(src) % y); 00232 for (i=0; i<paddLength; i++) 00233 GWEN_Buffer_AppendByte(src, paddLength); 00234 return 0; 00235 } 00236 00237 00238 00239 int GWEN_Padd_UnpaddWithAnsiX9_23FromMultipleOf(GWEN_BUFFER *src, int y) { 00240 const char *p; 00241 unsigned int lastpos; 00242 unsigned char paddLength; 00243 00244 lastpos=GWEN_Buffer_GetUsedBytes(src); 00245 if (lastpos<y) { 00246 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); 00247 return -1; 00248 } 00249 lastpos--; 00250 00251 p=GWEN_Buffer_GetStart(src)+lastpos; 00252 paddLength=*p; 00253 if (paddLength<1 || paddLength>y) { 00254 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid padding (%d bytes ?)", paddLength); 00255 return -1; 00256 } 00257 GWEN_Buffer_Crop(src, 0, GWEN_Buffer_GetUsedBytes(src)-paddLength); 00258 GWEN_Buffer_SetPos(src, lastpos-paddLength); 00259 return 0; 00260 } 00261 00262 00263 00264 int GWEN_Padd_PaddWithAnsiX9_23(GWEN_BUFFER *src) { 00265 return GWEN_Padd_PaddWithAnsiX9_23ToMultipleOf(src, 8); 00266 } 00267 00268 00269 00270 int GWEN_Padd_UnpaddWithAnsiX9_23(GWEN_BUFFER *src) { 00271 return GWEN_Padd_UnpaddWithAnsiX9_23FromMultipleOf(src, 8); 00272 } 00273 00274 00275 00276 int GWEN_Padd_PaddWithPkcs1Bt1(GWEN_BUFFER *buf, int dstSize){ 00277 unsigned int diff; 00278 char *p; 00279 00280 if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)) { 00281 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data"); 00282 return GWEN_ERROR_INVALID; 00283 } 00284 diff=dstSize-GWEN_Buffer_GetUsedBytes(buf); 00285 if (diff<11) { 00286 /* honour minimum padding length for BT 1 of 8 bytes, plus the 00287 * leading and the trailing zero and the block type identifier */ 00288 DBG_ERROR(GWEN_LOGDOMAIN, 00289 "Buffer contains too many bytes (diff is <11)"); 00290 return GWEN_ERROR_INVALID; 00291 } 00292 00293 /* reset position to 0 */ 00294 GWEN_Buffer_Rewind(buf); 00295 if (GWEN_Buffer_InsertRoom(buf, diff)) { 00296 DBG_ERROR(GWEN_LOGDOMAIN, "Could not insert room for %d bytes", diff); 00297 return GWEN_ERROR_GENERIC; 00298 } 00299 00300 p=GWEN_Buffer_GetStart(buf); 00301 *(p++)=0x00; 00302 *(p++)=0x01; /* block type 01 */ 00303 if (diff>3) { 00304 memset(p, 0xff, diff-3); 00305 p+=diff-3; 00306 } 00307 *(p++)=0x00; 00308 00309 return 0; 00310 } 00311 00312 00313 00314 int GWEN_Padd_PaddWithPkcs1Bt2(GWEN_BUFFER *buf, int dstSize){ 00315 unsigned int diff; 00316 char *p; 00317 int i; 00318 00319 if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)) { 00320 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data"); 00321 return GWEN_ERROR_INVALID; 00322 } 00323 diff=dstSize-GWEN_Buffer_GetUsedBytes(buf); 00324 if (diff<11) { 00325 /* honour minimum padding length for BT 1 of 8 bytes, plus the 00326 * leading and the trailing zero and the block type identifier */ 00327 DBG_ERROR(GWEN_LOGDOMAIN, 00328 "Buffer contains too many bytes (diff is <11)"); 00329 return GWEN_ERROR_INVALID; 00330 } 00331 00332 /* reset position to 0 */ 00333 GWEN_Buffer_Rewind(buf); 00334 if (GWEN_Buffer_InsertRoom(buf, diff)) { 00335 DBG_ERROR(GWEN_LOGDOMAIN, "Could not insert room for %d bytes", diff); 00336 return GWEN_ERROR_GENERIC; 00337 } 00338 00339 p=GWEN_Buffer_GetStart(buf); 00340 *(p++)=0x00; 00341 *(p++)=0x02; /* block type 02 */ 00342 GWEN_Crypt_Random(2, (uint8_t*)p, diff-3); 00343 for (i=0; i<diff-3; i++) { 00344 if (*p==0) 00345 /* TODO: Need to find a better but yet fast way */ 00346 *p=0xff; 00347 p++; 00348 } 00349 *(p++)=0x00; 00350 00351 return 0; 00352 } 00353 00354 00355 00356 int GWEN_Padd__UnpaddWithPkcs1Bt1Or2(GWEN_BUFFER *buf) { 00357 char *p; 00358 uint32_t len; 00359 uint32_t paddBytes; 00360 00361 assert(buf); 00362 len=GWEN_Buffer_GetUsedBytes(buf); 00363 assert(len); 00364 00365 p=GWEN_Buffer_GetStart(buf); 00366 if (*p==0) { 00367 p++; 00368 len--; 00369 } 00370 if (len<11) { 00371 DBG_ERROR(GWEN_LOGDOMAIN, "Too few bytes left (%d)", len); 00372 return GWEN_ERROR_INVALID; 00373 } 00374 00375 if (*p!=0x01 && *p!=0x02) { 00376 DBG_ERROR(GWEN_LOGDOMAIN, "Unsupported block type %02x", *p); 00377 return GWEN_ERROR_INVALID; 00378 } 00379 p++; len--; 00380 00381 /* skip padding bytes */ 00382 paddBytes=0; 00383 while(*p!=0x00 && len) { 00384 p++; len--; 00385 paddBytes++; 00386 } 00387 00388 if (*p!=0x00) { 00389 DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding"); 00390 return GWEN_ERROR_INVALID; 00391 } 00392 p++; len--; 00393 00394 if (paddBytes<8) { 00395 /* at least 8 padding bytes are needed */ 00396 DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding (too few padding bytes)"); 00397 return GWEN_ERROR_INVALID; 00398 } 00399 00400 GWEN_Buffer_Crop(buf, GWEN_Buffer_GetUsedBytes(buf)-len, len); 00401 00402 return 0; 00403 } 00404 00405 00406 00407 int GWEN_Padd_UnpaddWithPkcs1Bt1(GWEN_BUFFER *src){ 00408 return GWEN_Padd__UnpaddWithPkcs1Bt1Or2(src); 00409 } 00410 00411 00412 00413 int GWEN_Padd_UnpaddWithPkcs1Bt2(GWEN_BUFFER *src){ 00414 return GWEN_Padd__UnpaddWithPkcs1Bt1Or2(src); 00415 } 00416 00417 00418 00419 int GWEN_Padd_MGF1(uint8_t *pDestBuffer, 00420 uint32_t lDestBuffer, 00421 const uint8_t *pSeed, 00422 uint32_t lSeed, 00423 GWEN_MDIGEST *md) { 00424 uint32_t bytesLeft=lDestBuffer; 00425 uint32_t i; 00426 uint8_t counter[4]; 00427 uint8_t *p; 00428 00429 p=pDestBuffer; 00430 00431 for (i=0; bytesLeft>0; i++) { 00432 int rv; 00433 uint32_t l; 00434 00435 counter[0]= (uint8_t)((i>>24) & 0xff); 00436 counter[1]= (uint8_t)((i>>16) & 0xff); 00437 counter[2]= (uint8_t)((i>>8) & 0xff); 00438 counter[3]= (uint8_t)(i & 0xff); 00439 00440 rv=GWEN_MDigest_Begin(md); 00441 if (rv<0) { 00442 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00443 return rv; 00444 } 00445 00446 rv=GWEN_MDigest_Update(md, pSeed, lSeed); 00447 if (rv<0) { 00448 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00449 return rv; 00450 } 00451 00452 rv=GWEN_MDigest_Update(md, counter, 4); 00453 if (rv<0) { 00454 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00455 return rv; 00456 } 00457 00458 rv=GWEN_MDigest_End(md); 00459 if (rv<0) { 00460 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00461 return rv; 00462 } 00463 00464 l=GWEN_MDigest_GetDigestSize(md); 00465 if (bytesLeft<l) 00466 l=bytesLeft; 00467 memmove(p, GWEN_MDigest_GetDigestPtr(md), l); 00468 bytesLeft-=l; 00469 p+=l; 00470 } 00471 00472 return 0; 00473 } 00474 00475 00476 00477 int GWEN_Padd_AddPkcs1Pss(uint8_t *pDestBuffer, 00478 uint32_t lDestBuffer, 00479 uint32_t nbits, 00480 const uint8_t *pHash, 00481 uint32_t lHash, 00482 uint32_t lSalt, 00483 GWEN_MDIGEST *md) { 00484 uint32_t emLen; 00485 uint8_t *pSalt=NULL; 00486 uint8_t *pDB; 00487 uint8_t *pDbMask; 00488 uint32_t x; 00489 uint32_t i; 00490 uint8_t *p; 00491 int rv; 00492 uint8_t hashMBar[64]; 00493 int numberOfBitsInByte0; 00494 00495 emLen=nbits/8; 00496 if (nbits%8) 00497 emLen++; 00498 00499 /* adjust emLen because the maximum number of bits in emLen is length of modulus-1 */ 00500 numberOfBitsInByte0=((nbits-1) & 0x07); 00501 if (numberOfBitsInByte0==0) { 00502 *(pDestBuffer++)=0; 00503 emLen--; 00504 } 00505 00506 /* generate salt */ 00507 pSalt=(uint8_t*) malloc(lSalt); 00508 assert(pSalt); 00509 GWEN_Crypt_Random(2, pSalt, lSalt); 00510 00511 /* M'=00 00 00 00 00 00 00 00 | HASH(M) | SALT */ 00512 rv=GWEN_MDigest_Begin(md); 00513 if (rv<0) { 00514 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00515 free(pSalt); 00516 return rv; 00517 } 00518 00519 rv=GWEN_MDigest_Update(md, nullarray, 8); 00520 if (rv<0) { 00521 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00522 free(pSalt); 00523 return rv; 00524 } 00525 00526 rv=GWEN_MDigest_Update(md, pHash, lHash); 00527 if (rv<0) { 00528 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00529 free(pSalt); 00530 return rv; 00531 } 00532 00533 rv=GWEN_MDigest_Update(md, pSalt, lSalt); 00534 if (rv<0) { 00535 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00536 free(pSalt); 00537 return rv; 00538 } 00539 00540 rv=GWEN_MDigest_End(md); 00541 if (rv<0) { 00542 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00543 free(pSalt); 00544 return rv; 00545 } 00546 /* hashMBar=HASH(M') */ 00547 memmove(hashMBar, 00548 GWEN_MDigest_GetDigestPtr(md), 00549 GWEN_MDigest_GetDigestSize(md)); 00550 00551 /* generate DB (PS | '01' | SALT) */ 00552 x=emLen-GWEN_MDigest_GetDigestSize(md)-lSalt-2; 00553 pDB=(uint8_t*)malloc(emLen); 00554 assert(pDB); 00555 p=pDB; 00556 memset(p, 0, x); 00557 p+=x; 00558 *(p++)=0x01; 00559 memmove(p, pSalt, lSalt); 00560 p+=lSalt; 00561 00562 /* create DBMask */ 00563 x=emLen-GWEN_MDigest_GetDigestSize(md)-1; 00564 pDbMask=(uint8_t*)malloc(x); 00565 rv=GWEN_Padd_MGF1(pDbMask, x, 00566 hashMBar, GWEN_MDigest_GetDigestSize(md), 00567 md); 00568 if (rv<0) { 00569 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00570 free(pDbMask); 00571 free(pDB); 00572 free(pSalt); 00573 return rv; 00574 } 00575 00576 /* created maskedDB in destination buffer */ 00577 p=pDestBuffer; 00578 for (i=0; i<x; i++) 00579 *(p++)=pDB[i] ^ pDbMask[i]; 00580 00581 /* append hashMBar */ 00582 memmove(p, hashMBar, GWEN_MDigest_GetDigestSize(md)); 00583 p+=GWEN_MDigest_GetDigestSize(md); 00584 /* append '0xbc' */ 00585 *(p++)=0xbc; 00586 00587 /* adjust first byte */ 00588 if (numberOfBitsInByte0) 00589 pDestBuffer[0] &= 0xff >> (8-numberOfBitsInByte0); 00590 00591 free(pDbMask); 00592 free(pDB); 00593 free(pSalt); 00594 00595 return emLen; 00596 } 00597 00598 00599 00600 int GWEN_Padd_VerifyPkcs1Pss(const uint8_t *pSrcBuffer, 00601 uint32_t lSrcBuffer, 00602 uint32_t nbits, 00603 const uint8_t *pHash, 00604 uint32_t lHash, 00605 uint32_t lSalt, 00606 GWEN_MDIGEST *md) { 00607 uint32_t emLen; 00608 const uint8_t *pSalt; 00609 uint8_t *pDB; 00610 uint32_t x; 00611 uint32_t i; 00612 int rv; 00613 const uint8_t *hashMBar; 00614 int numberOfBitsInByte0; 00615 00616 emLen=nbits/8; 00617 if (nbits%8) 00618 emLen++; 00619 00620 /* check for leading bits to be zero */ 00621 numberOfBitsInByte0=((nbits-1) & 0x07); 00622 00623 if (numberOfBitsInByte0==0) { 00624 pSrcBuffer++; 00625 emLen--; 00626 } 00627 else { 00628 if (pSrcBuffer[0] & (0xff << numberOfBitsInByte0)) { 00629 DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: leading bits must be zero (%d)", numberOfBitsInByte0); 00630 return GWEN_ERROR_BAD_DATA; 00631 } 00632 } 00633 00634 /* check for key length */ 00635 if (emLen < (GWEN_MDigest_GetDigestSize(md)+lSalt+2)) { 00636 DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: Key too small for data"); 00637 return GWEN_ERROR_BAD_DATA; 00638 } 00639 00640 /* check for length of provided data */ 00641 if (lSrcBuffer < emLen) { 00642 DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: Provided data too small (is %d, expected %d)", 00643 lSrcBuffer, emLen); 00644 return GWEN_ERROR_BAD_DATA; 00645 } 00646 00647 /* get DB (PS | '01' | SALT) */ 00648 x=emLen-GWEN_MDigest_GetDigestSize(md)-1; 00649 00650 pDB=(uint8_t*)malloc(x); 00651 hashMBar=pSrcBuffer+x; 00652 rv=GWEN_Padd_MGF1(pDB, x, 00653 hashMBar, GWEN_MDigest_GetDigestSize(md), 00654 md); 00655 if (rv<0) { 00656 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00657 free(pDB); 00658 return rv; 00659 } 00660 00661 /* un-XOR DB using DBMask from source buffer (EM) */ 00662 for (i=0; i<x; i++) 00663 pDB[i] ^= pSrcBuffer[i]; 00664 00665 /* check for leading bits */ 00666 if (numberOfBitsInByte0) 00667 pDB[0] &= (0xff >> (8-numberOfBitsInByte0)); 00668 00669 /* pDB now contains PS | '01' | SALT */ 00670 00671 /* recover salt: skip all '00' and wait for '01' */ 00672 for (i=0; (i<(x-1) && pDB[i]==0); i++); 00673 /* i now points to a byte which is not zero, expect it to be '01' */ 00674 if (pDB[i]!=0x01) { 00675 DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: byte 0x01 missing before salt"); 00676 free(pDB); 00677 return GWEN_ERROR_BAD_DATA; 00678 } 00679 i++; 00680 00681 /* check for length of salt */ 00682 if ((x-i)!=lSalt) { 00683 DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: bad length for salt (is %d, should be %d)", 00684 x-i, lSalt); 00685 free(pDB); 00686 return GWEN_ERROR_BAD_DATA; 00687 } 00688 00689 /* get pointer to salt */ 00690 pSalt=pDB+i; 00691 00692 /* M'=00 00 00 00 00 00 00 00 | HASH(M) | SALT */ 00693 rv=GWEN_MDigest_Begin(md); 00694 if (rv<0) { 00695 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00696 free(pDB); 00697 return rv; 00698 } 00699 00700 rv=GWEN_MDigest_Update(md, nullarray, 8); 00701 if (rv<0) { 00702 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00703 free(pDB); 00704 return rv; 00705 } 00706 00707 if (lHash) { 00708 rv=GWEN_MDigest_Update(md, pHash, lHash); 00709 if (rv<0) { 00710 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00711 free(pDB); 00712 return rv; 00713 } 00714 } 00715 00716 rv=GWEN_MDigest_Update(md, pSalt, lSalt); 00717 if (rv<0) { 00718 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00719 free(pDB); 00720 return rv; 00721 } 00722 00723 rv=GWEN_MDigest_End(md); 00724 if (rv<0) { 00725 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00726 free(pDB); 00727 return rv; 00728 } 00729 if (memcmp(hashMBar, 00730 GWEN_MDigest_GetDigestPtr(md), 00731 GWEN_MDigest_GetDigestSize(md))!=0) { 00732 DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: hash does not match"); 00733 00734 free(pDB); 00735 return GWEN_ERROR_VERIFY; 00736 } 00737 00738 free(pDB); 00739 00740 DBG_INFO(GWEN_LOGDOMAIN, "Hash ok."); 00741 return 0; 00742 } 00743 00744 00745 00746 int GWEN_Padd_ApplyPaddAlgo(const GWEN_CRYPT_PADDALGO *a, GWEN_BUFFER *buf) { 00747 int rv; 00748 unsigned int diff; 00749 unsigned int bsize; 00750 unsigned int dstSize; 00751 unsigned int chunkSize; 00752 GWEN_CRYPT_PADDALGOID aid; 00753 00754 assert(a); 00755 assert(buf); 00756 00757 aid=GWEN_Crypt_PaddAlgo_GetId(a); 00758 if (aid==GWEN_Crypt_PaddAlgoId_None) 00759 /* short return if there is no padding to be done */ 00760 return 0; 00761 00762 chunkSize=GWEN_Crypt_PaddAlgo_GetPaddSize(a); 00763 if (chunkSize==0) { 00764 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid chunk size (0)"); 00765 return GWEN_ERROR_INVALID; 00766 } 00767 00768 bsize=GWEN_Buffer_GetUsedBytes(buf); 00769 dstSize=bsize+(chunkSize-1); 00770 dstSize=(dstSize/chunkSize)*chunkSize; 00771 diff=dstSize-bsize; 00772 00773 DBG_INFO(GWEN_LOGDOMAIN, "Padding with algo \"%s\"", 00774 GWEN_Crypt_PaddAlgoId_toString(aid)); 00775 00776 switch(aid) { 00777 case GWEN_Crypt_PaddAlgoId_None: 00778 rv=0; 00779 break; 00780 00781 case GWEN_Crypt_PaddAlgoId_Iso9796_1A4: 00782 if (dstSize>96) { 00783 DBG_ERROR(GWEN_LOGDOMAIN, 00784 "Padding size must be <=96 bytes (is %d)", 00785 dstSize); 00786 return GWEN_ERROR_INVALID; 00787 } 00788 rv=GWEN_Padd_PaddWithISO9796(buf); 00789 break; 00790 00791 case GWEN_Crypt_PaddAlgoId_Pkcs1_1: 00792 rv=GWEN_Padd_PaddWithPkcs1Bt1(buf, dstSize); 00793 break; 00794 00795 case GWEN_Crypt_PaddAlgoId_Pkcs1_2: 00796 rv=GWEN_Padd_PaddWithPkcs1Bt2(buf, dstSize); 00797 break; 00798 00799 case GWEN_Crypt_PaddAlgoId_LeftZero: 00800 rv=GWEN_Buffer_FillLeftWithBytes(buf, 0, diff); 00801 break; 00802 00803 case GWEN_Crypt_PaddAlgoId_RightZero: 00804 rv=GWEN_Buffer_FillWithBytes(buf, 0, diff); 00805 break; 00806 00807 case GWEN_Crypt_PaddAlgoId_AnsiX9_23: 00808 return GWEN_Padd_PaddWithAnsiX9_23(buf); 00809 00810 case GWEN_Crypt_PaddAlgoId_Iso9796_2: 00811 return GWEN_Padd_PaddWithIso9796_2(buf, dstSize); 00812 00813 case GWEN_Crypt_PaddAlgoId_Iso9796_1: 00814 default: 00815 DBG_INFO(GWEN_LOGDOMAIN, "Algo-Type %d (%s) not supported", 00816 aid, GWEN_Crypt_PaddAlgoId_toString(aid)); 00817 return GWEN_ERROR_NOT_AVAILABLE; 00818 } 00819 00820 if (rv) { 00821 DBG_ERROR(GWEN_LOGDOMAIN, "Error padding with algo %d (%s)", 00822 aid, GWEN_Crypt_PaddAlgoId_toString(aid)); 00823 return GWEN_ERROR_GENERIC; 00824 } 00825 00826 return rv; 00827 } 00828 00829 00830 00831 int GWEN_Padd_UnapplyPaddAlgo(const GWEN_CRYPT_PADDALGO *a, GWEN_BUFFER *buf){ 00832 int rv; 00833 GWEN_CRYPT_PADDALGOID aid; 00834 00835 assert(a); 00836 assert(buf); 00837 00838 aid=GWEN_Crypt_PaddAlgo_GetId(a); 00839 DBG_INFO(GWEN_LOGDOMAIN, "Unpadding with algo \"%s\"", 00840 GWEN_Crypt_PaddAlgoId_toString(aid)); 00841 00842 switch(aid) { 00843 case GWEN_Crypt_PaddAlgoId_None: 00844 rv=0; 00845 break; 00846 00847 case GWEN_Crypt_PaddAlgoId_Pkcs1_1: 00848 rv=GWEN_Padd_UnpaddWithPkcs1Bt1(buf); 00849 break; 00850 00851 case GWEN_Crypt_PaddAlgoId_Pkcs1_2: 00852 rv=GWEN_Padd_UnpaddWithPkcs1Bt2(buf); 00853 break; 00854 00855 case GWEN_Crypt_PaddAlgoId_AnsiX9_23: 00856 return GWEN_Padd_UnpaddWithAnsiX9_23(buf); 00857 00858 case GWEN_Crypt_PaddAlgoId_Iso9796_2: 00859 return GWEN_Padd_UnpaddWithIso9796_2(buf); 00860 00861 case GWEN_Crypt_PaddAlgoId_Iso9796_1: 00862 case GWEN_Crypt_PaddAlgoId_LeftZero: 00863 case GWEN_Crypt_PaddAlgoId_RightZero: 00864 case GWEN_Crypt_PaddAlgoId_Iso9796_1A4: 00865 default: 00866 DBG_INFO(GWEN_LOGDOMAIN, "Algo-Type %d (%s) not supported", 00867 aid, GWEN_Crypt_PaddAlgoId_toString(aid)); 00868 return GWEN_ERROR_NOT_AVAILABLE; 00869 } 00870 00871 if (rv) { 00872 DBG_ERROR(GWEN_LOGDOMAIN, "Error padding with algo %d (%s)", 00873 aid, GWEN_Crypt_PaddAlgoId_toString(aid)); 00874 return GWEN_ERROR_GENERIC; 00875 } 00876 00877 return rv; 00878 } 00879 00880 00881 00882 00883 00884