gwenhywfar  4.3.1
padd.c
Go to the documentation of this file.
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