padd.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003  -------------------
00004  cvs         : $Id$
00005  begin       : Mon Jan 05 2004
00006  copyright   : (C) 2004 by Martin Preuss
00007  email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU Lesser General Public            *
00013  *   License as published by the Free Software Foundation; either          *
00014  *   version 2.1 of the License, or (at your option) any later version.    *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00024  *   MA  02111-1307  USA                                                   *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 
00029 #ifdef HAVE_CONFIG_H
00030 # include <config.h>
00031 #endif
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_23(GWEN_BUFFER *src) {
00228   unsigned char paddLength;
00229   unsigned int i;
00230 
00231   paddLength=8-(GWEN_Buffer_GetUsedBytes(src) % 8);
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_23(GWEN_BUFFER *src) {
00240   const char *p;
00241   unsigned int lastpos;
00242   unsigned char paddLength;
00243 
00244   lastpos=GWEN_Buffer_GetUsedBytes(src);
00245   if (lastpos<8) {
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>8) {
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_PaddWithPkcs1Bt1(GWEN_BUFFER *buf, int dstSize){
00265   unsigned int diff;
00266   char *p;
00267 
00268   if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)) {
00269     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data");
00270     return GWEN_ERROR_INVALID;
00271   }
00272   diff=dstSize-GWEN_Buffer_GetUsedBytes(buf);
00273   if (diff<11) {
00274     /* honour minimum padding length for BT 1 of 8 bytes, plus the
00275      * leading and the trailing zero and the block type identifier */
00276     DBG_ERROR(GWEN_LOGDOMAIN,
00277               "Buffer contains too many bytes (diff is <11)");
00278     return GWEN_ERROR_INVALID;
00279   }
00280 
00281   /* reset position to 0 */
00282   GWEN_Buffer_Rewind(buf);
00283   if (GWEN_Buffer_InsertRoom(buf, diff)) {
00284     DBG_ERROR(GWEN_LOGDOMAIN, "Could not insert room for %d bytes", diff);
00285     return GWEN_ERROR_GENERIC;
00286   }
00287 
00288   p=GWEN_Buffer_GetStart(buf);
00289   *(p++)=0x00;
00290   *(p++)=0x01; /* block type 01 */
00291   if (diff>3) {
00292     memset(p, 0xff, diff-3);
00293     p+=diff-3;
00294   }
00295   *(p++)=0x00;
00296 
00297   return 0;
00298 }
00299 
00300 
00301 
00302 int GWEN_Padd_PaddWithPkcs1Bt2(GWEN_BUFFER *buf, int dstSize){
00303   unsigned int diff;
00304   char *p;
00305   int i;
00306 
00307   if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)) {
00308     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data");
00309     return GWEN_ERROR_INVALID;
00310   }
00311   diff=dstSize-GWEN_Buffer_GetUsedBytes(buf);
00312   if (diff<11) {
00313     /* honour minimum padding length for BT 1 of 8 bytes, plus the
00314      * leading and the trailing zero and the block type identifier */
00315     DBG_ERROR(GWEN_LOGDOMAIN,
00316               "Buffer contains too many bytes (diff is <11)");
00317     return GWEN_ERROR_INVALID;
00318   }
00319 
00320   /* reset position to 0 */
00321   GWEN_Buffer_Rewind(buf);
00322   if (GWEN_Buffer_InsertRoom(buf, diff)) {
00323     DBG_ERROR(GWEN_LOGDOMAIN, "Could not insert room for %d bytes", diff);
00324     return GWEN_ERROR_GENERIC;
00325   }
00326 
00327   p=GWEN_Buffer_GetStart(buf);
00328   *(p++)=0x00;
00329   *(p++)=0x02; /* block type 02 */
00330   GWEN_Crypt_Random(2, (uint8_t*)p, diff-3);
00331   for (i=0; i<diff-3; i++) {
00332     if (*p==0)
00333       /* TODO: Need to find a better but yet fast way */
00334       *p=0xff;
00335     p++;
00336   }
00337   *(p++)=0x00;
00338 
00339   return 0;
00340 }
00341 
00342 
00343 
00344 int GWEN_Padd__UnpaddWithPkcs1Bt1Or2(GWEN_BUFFER *buf) {
00345   char *p;
00346   uint32_t len;
00347   uint32_t paddBytes;
00348 
00349   assert(buf);
00350   len=GWEN_Buffer_GetUsedBytes(buf);
00351   assert(len);
00352 
00353   p=GWEN_Buffer_GetStart(buf);
00354   if  (*p==0) {
00355     p++;
00356     len--;
00357   }
00358   if (len<11) {
00359     DBG_ERROR(GWEN_LOGDOMAIN, "Too few bytes left (%d)", len);
00360     return GWEN_ERROR_INVALID;
00361   }
00362 
00363   if (*p!=0x01 && *p!=0x02) {
00364     DBG_ERROR(GWEN_LOGDOMAIN, "Unsupported block type %02x", *p);
00365     return GWEN_ERROR_INVALID;
00366   }
00367   p++; len--;
00368 
00369   /* skip padding bytes */
00370   paddBytes=0;
00371   while(*p!=0x00 && len) {
00372     p++; len--;
00373     paddBytes++;
00374   }
00375 
00376   if (*p!=0x00) {
00377     DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding");
00378     return GWEN_ERROR_INVALID;
00379   }
00380   p++; len--;
00381 
00382   if (paddBytes<8) {
00383     /* at least 8 padding bytes are needed */
00384     DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding (too few padding bytes)");
00385     return GWEN_ERROR_INVALID;
00386   }
00387 
00388   GWEN_Buffer_Crop(buf, GWEN_Buffer_GetUsedBytes(buf)-len, len);
00389 
00390   return 0;
00391 }
00392 
00393 
00394 
00395 int GWEN_Padd_UnpaddWithPkcs1Bt1(GWEN_BUFFER *src){
00396   return GWEN_Padd__UnpaddWithPkcs1Bt1Or2(src);
00397 }
00398 
00399 
00400 
00401 int GWEN_Padd_UnpaddWithPkcs1Bt2(GWEN_BUFFER *src){
00402   return GWEN_Padd__UnpaddWithPkcs1Bt1Or2(src);
00403 }
00404 
00405 
00406 
00407 int GWEN_Padd_MGF1(uint8_t *pDestBuffer,
00408                    uint32_t lDestBuffer,
00409                    const uint8_t *pSeed,
00410                    uint32_t lSeed,
00411                    GWEN_MDIGEST *md) {
00412     uint32_t bytesLeft=lDestBuffer;
00413     uint32_t i;
00414     uint8_t counter[4];
00415     uint8_t *p;
00416 
00417     p=pDestBuffer;
00418 
00419     for (i=0; bytesLeft>0; i++) {
00420       int rv;
00421       uint32_t l;
00422 
00423       counter[0]= (uint8_t)((i>>24) & 0xff);
00424       counter[1]= (uint8_t)((i>>16) & 0xff);
00425       counter[2]= (uint8_t)((i>>8) & 0xff);
00426       counter[3]= (uint8_t)(i & 0xff);
00427 
00428       rv=GWEN_MDigest_Begin(md);
00429       if (rv<0) {
00430         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00431         return rv;
00432       }
00433 
00434       rv=GWEN_MDigest_Update(md, pSeed, lSeed);
00435       if (rv<0) {
00436         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00437         return rv;
00438       }
00439 
00440       rv=GWEN_MDigest_Update(md, counter, 4);
00441       if (rv<0) {
00442         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00443         return rv;
00444       }
00445 
00446       rv=GWEN_MDigest_End(md);
00447       if (rv<0) {
00448         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00449         return rv;
00450       }
00451 
00452       l=GWEN_MDigest_GetDigestSize(md);
00453       if (bytesLeft<l)
00454         l=bytesLeft;
00455       memmove(p, GWEN_MDigest_GetDigestPtr(md), l);
00456       bytesLeft-=l;
00457       p+=l;
00458     }
00459 
00460     return 0;
00461 }
00462 
00463 
00464 
00465 int GWEN_Padd_AddPkcs1Pss(uint8_t *pDestBuffer,
00466                           uint32_t lDestBuffer,
00467                           uint32_t nbits,
00468                           const uint8_t *pHash,
00469                           uint32_t lHash,
00470                           uint32_t lSalt,
00471                           GWEN_MDIGEST *md) {
00472   uint32_t emLen;
00473   uint8_t *pSalt=NULL;
00474   uint8_t *pDB;
00475   uint8_t *pDbMask;
00476   uint32_t x;
00477   uint32_t i;
00478   uint8_t *p;
00479   int rv;
00480   uint8_t hashMBar[64];
00481   int numberOfBitsInByte0;
00482 
00483   emLen=nbits/8;
00484   if (nbits%8)
00485     emLen++;
00486 
00487   /* adjust emLen because the maximum number of bits in emLen is length of modulus-1 */
00488   numberOfBitsInByte0=((nbits-1) & 0x07);
00489   if (numberOfBitsInByte0==0) {
00490     *(pDestBuffer++)=0;
00491     emLen--;
00492   }
00493 
00494   /* generate salt */
00495   pSalt=(uint8_t*) malloc(lSalt);
00496   assert(pSalt);
00497   GWEN_Crypt_Random(2, pSalt, lSalt);
00498 
00499   /* M'=00 00 00 00 00 00 00 00 | HASH(M) | SALT */
00500   rv=GWEN_MDigest_Begin(md);
00501   if (rv<0) {
00502     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00503     free(pSalt);
00504     return rv;
00505   }
00506 
00507   rv=GWEN_MDigest_Update(md, nullarray, 8);
00508   if (rv<0) {
00509     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00510     free(pSalt);
00511     return rv;
00512   }
00513 
00514   rv=GWEN_MDigest_Update(md, pHash, lHash);
00515   if (rv<0) {
00516     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00517     free(pSalt);
00518     return rv;
00519   }
00520 
00521   rv=GWEN_MDigest_Update(md, pSalt, lSalt);
00522   if (rv<0) {
00523     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00524     free(pSalt);
00525     return rv;
00526   }
00527 
00528   rv=GWEN_MDigest_End(md);
00529   if (rv<0) {
00530     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00531     free(pSalt);
00532     return rv;
00533   }
00534   /* hashMBar=HASH(M') */
00535   memmove(hashMBar,
00536           GWEN_MDigest_GetDigestPtr(md),
00537           GWEN_MDigest_GetDigestSize(md));
00538 
00539   /* generate DB (PS | '01' | SALT) */
00540   x=emLen-GWEN_MDigest_GetDigestSize(md)-lSalt-2;
00541   pDB=(uint8_t*)malloc(emLen);
00542   assert(pDB);
00543   p=pDB;
00544   memset(p, 0, x);
00545   p+=x;
00546   *(p++)=0x01;
00547   memmove(p, pSalt, lSalt);
00548   p+=lSalt;
00549 
00550   /* create DBMask */
00551   x=emLen-GWEN_MDigest_GetDigestSize(md)-1;
00552   pDbMask=(uint8_t*)malloc(x);
00553   rv=GWEN_Padd_MGF1(pDbMask, x,
00554                     hashMBar, GWEN_MDigest_GetDigestSize(md),
00555                     md);
00556   if (rv<0) {
00557     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00558     free(pDbMask);
00559     free(pDB);
00560     free(pSalt);
00561     return rv;
00562   }
00563 
00564   /* created maskedDB in destination buffer */
00565   p=pDestBuffer;
00566   for (i=0; i<x; i++)
00567     *(p++)=pDB[i] ^ pDbMask[i];
00568 
00569   /* append hashMBar */
00570   memmove(p, hashMBar, GWEN_MDigest_GetDigestSize(md));
00571   p+=GWEN_MDigest_GetDigestSize(md);
00572   /* append '0xbc' */
00573   *(p++)=0xbc;
00574 
00575   /* adjust first byte */
00576   if (numberOfBitsInByte0)
00577     pDestBuffer[0] &= 0xff >> (8-numberOfBitsInByte0);
00578 
00579   free(pDbMask);
00580   free(pDB);
00581   free(pSalt);
00582 
00583   return emLen;
00584 }
00585 
00586 
00587 
00588 int GWEN_Padd_VerifyPkcs1Pss(const uint8_t *pSrcBuffer,
00589                              uint32_t lSrcBuffer,
00590                              uint32_t nbits,
00591                              const uint8_t *pHash,
00592                              uint32_t lHash,
00593                              uint32_t lSalt,
00594                              GWEN_MDIGEST *md) {
00595   uint32_t emLen;
00596   const uint8_t *pSalt;
00597   uint8_t *pDB;
00598   uint32_t x;
00599   uint32_t i;
00600   int rv;
00601   const uint8_t *hashMBar;
00602   int numberOfBitsInByte0;
00603 
00604   emLen=nbits/8;
00605   if (nbits%8)
00606     emLen++;
00607 
00608   /* check for leading bits to be zero */
00609   numberOfBitsInByte0=((nbits-1) & 0x07);
00610 
00611   if (numberOfBitsInByte0==0) {
00612     pSrcBuffer++;
00613     emLen--;
00614   }
00615   else {
00616     if (pSrcBuffer[0] & (0xff << numberOfBitsInByte0)) {
00617       DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: leading bits must be zero (%d)", numberOfBitsInByte0);
00618       return GWEN_ERROR_BAD_DATA;
00619     }
00620   }
00621 
00622   /* check for key length */
00623   if (emLen < (GWEN_MDigest_GetDigestSize(md)+lSalt+2)) {
00624     DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: Key too small for data");
00625     return GWEN_ERROR_BAD_DATA;
00626   }
00627 
00628   /* check for length of provided data */
00629   if (lSrcBuffer < emLen) {
00630     DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: Provided data too small (is %d, expected %d)",
00631               lSrcBuffer, emLen);
00632     return GWEN_ERROR_BAD_DATA;
00633   }
00634 
00635   /* get DB (PS | '01' | SALT) */
00636   x=emLen-GWEN_MDigest_GetDigestSize(md)-1;
00637 
00638   pDB=(uint8_t*)malloc(x);
00639   hashMBar=pSrcBuffer+x;
00640   rv=GWEN_Padd_MGF1(pDB, x,
00641                     hashMBar, GWEN_MDigest_GetDigestSize(md),
00642                     md);
00643   if (rv<0) {
00644     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00645     free(pDB);
00646     return rv;
00647   }
00648 
00649   /* un-XOR DB using DBMask from source buffer (EM) */
00650   for (i=0; i<x; i++)
00651     pDB[i] ^= pSrcBuffer[i];
00652 
00653   /* check for leading bits */
00654   if (numberOfBitsInByte0)
00655     pDB[0] &= (0xff >> (8-numberOfBitsInByte0));
00656 
00657   /* pDB now contains PS | '01' | SALT */
00658 
00659   /* recover salt: skip all '00' and wait for '01' */
00660   for (i=0; (i<(x-1) && pDB[i]==0); i++);
00661   /* i now points to a byte which is not zero, expect it to be '01' */
00662   if (pDB[i]!=0x01) {
00663     DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: byte 0x01 missing before salt");
00664     free(pDB);
00665     return GWEN_ERROR_BAD_DATA;
00666   }
00667   i++;
00668 
00669   /* check for length of salt */
00670   if ((x-i)!=lSalt) {
00671     DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: bad length for salt (is %d, should be %d)",
00672               x-i, lSalt);
00673     free(pDB);
00674     return GWEN_ERROR_BAD_DATA;
00675   }
00676 
00677   /* get pointer to salt */
00678   pSalt=pDB+i;
00679 
00680   /* M'=00 00 00 00 00 00 00 00 | HASH(M) | SALT */
00681   rv=GWEN_MDigest_Begin(md);
00682   if (rv<0) {
00683     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00684     free(pDB);
00685     return rv;
00686   }
00687 
00688   rv=GWEN_MDigest_Update(md, nullarray, 8);
00689   if (rv<0) {
00690     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00691     free(pDB);
00692     return rv;
00693   }
00694 
00695   if (lHash) {
00696     rv=GWEN_MDigest_Update(md, pHash, lHash);
00697     if (rv<0) {
00698       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00699       free(pDB);
00700       return rv;
00701     }
00702   }
00703 
00704   rv=GWEN_MDigest_Update(md, pSalt, lSalt);
00705   if (rv<0) {
00706     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00707     free(pDB);
00708     return rv;
00709   }
00710 
00711   rv=GWEN_MDigest_End(md);
00712   if (rv<0) {
00713     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00714     free(pDB);
00715     return rv;
00716   }
00717   if (memcmp(hashMBar,
00718              GWEN_MDigest_GetDigestPtr(md),
00719              GWEN_MDigest_GetDigestSize(md))!=0) {
00720     DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding: hash does not match");
00721 
00722     free(pDB);
00723     return GWEN_ERROR_VERIFY;
00724   }
00725 
00726   free(pDB);
00727 
00728   DBG_INFO(GWEN_LOGDOMAIN, "Hash ok.");
00729   return 0;
00730 }
00731 
00732 
00733 
00734 int GWEN_Padd_ApplyPaddAlgo(const GWEN_CRYPT_PADDALGO *a, GWEN_BUFFER *buf) {
00735   int rv;
00736   unsigned int diff;
00737   unsigned int bsize;
00738   unsigned int dstSize;
00739   unsigned int chunkSize;
00740   GWEN_CRYPT_PADDALGOID aid;
00741 
00742   assert(a);
00743   assert(buf);
00744 
00745   aid=GWEN_Crypt_PaddAlgo_GetId(a);
00746   if (aid==GWEN_Crypt_PaddAlgoId_None)
00747     /* short return if there is no padding to be done */
00748     return 0;
00749 
00750   chunkSize=GWEN_Crypt_PaddAlgo_GetPaddSize(a);
00751   if (chunkSize==0) {
00752     DBG_ERROR(GWEN_LOGDOMAIN, "Invalid chunk size (0)");
00753     return GWEN_ERROR_INVALID;
00754   }
00755 
00756   bsize=GWEN_Buffer_GetUsedBytes(buf);
00757   dstSize=bsize+(chunkSize-1);
00758   dstSize=(dstSize/chunkSize)*chunkSize;
00759   diff=dstSize-bsize;
00760 
00761   DBG_INFO(GWEN_LOGDOMAIN, "Padding with algo \"%s\"",
00762            GWEN_Crypt_PaddAlgoId_toString(aid));
00763 
00764   switch(aid) {
00765   case GWEN_Crypt_PaddAlgoId_None:
00766     rv=0;
00767     break;
00768 
00769   case GWEN_Crypt_PaddAlgoId_Iso9796_1A4:
00770     if (dstSize>96) {
00771       DBG_ERROR(GWEN_LOGDOMAIN,
00772                 "Padding size must be <=96 bytes (is %d)",
00773                 dstSize);
00774       return GWEN_ERROR_INVALID;
00775     }
00776     rv=GWEN_Padd_PaddWithISO9796(buf);
00777     break;
00778 
00779   case GWEN_Crypt_PaddAlgoId_Pkcs1_1:
00780     rv=GWEN_Padd_PaddWithPkcs1Bt1(buf, dstSize);
00781     break;
00782 
00783   case GWEN_Crypt_PaddAlgoId_Pkcs1_2:
00784     rv=GWEN_Padd_PaddWithPkcs1Bt2(buf, dstSize);
00785     break;
00786 
00787   case GWEN_Crypt_PaddAlgoId_LeftZero:
00788     rv=GWEN_Buffer_FillLeftWithBytes(buf, 0, diff);
00789     break;
00790 
00791   case GWEN_Crypt_PaddAlgoId_RightZero:
00792     rv=GWEN_Buffer_FillWithBytes(buf, 0, diff);
00793     break;
00794 
00795   case GWEN_Crypt_PaddAlgoId_AnsiX9_23:
00796     return GWEN_Padd_PaddWithAnsiX9_23(buf);
00797 
00798   case GWEN_Crypt_PaddAlgoId_Iso9796_2:
00799     return GWEN_Padd_PaddWithIso9796_2(buf, dstSize);
00800 
00801   case GWEN_Crypt_PaddAlgoId_Iso9796_1:
00802   default:
00803     DBG_INFO(GWEN_LOGDOMAIN, "Algo-Type %d (%s) not supported",
00804              aid, GWEN_Crypt_PaddAlgoId_toString(aid));
00805     return GWEN_ERROR_NOT_AVAILABLE;
00806   }
00807 
00808   if (rv) {
00809     DBG_ERROR(GWEN_LOGDOMAIN, "Error padding with algo %d (%s)",
00810               aid, GWEN_Crypt_PaddAlgoId_toString(aid));
00811     return GWEN_ERROR_GENERIC;
00812   }
00813 
00814   return rv;
00815 }
00816 
00817 
00818 
00819 int GWEN_Padd_UnapplyPaddAlgo(const GWEN_CRYPT_PADDALGO *a, GWEN_BUFFER *buf){
00820   int rv;
00821   GWEN_CRYPT_PADDALGOID aid;
00822 
00823   assert(a);
00824   assert(buf);
00825 
00826   aid=GWEN_Crypt_PaddAlgo_GetId(a);
00827   DBG_INFO(GWEN_LOGDOMAIN, "Unpadding with algo \"%s\"",
00828            GWEN_Crypt_PaddAlgoId_toString(aid));
00829 
00830   switch(aid) {
00831   case GWEN_Crypt_PaddAlgoId_None:
00832     rv=0;
00833     break;
00834 
00835   case GWEN_Crypt_PaddAlgoId_Pkcs1_1:
00836     rv=GWEN_Padd_UnpaddWithPkcs1Bt1(buf);
00837     break;
00838 
00839   case GWEN_Crypt_PaddAlgoId_Pkcs1_2:
00840     rv=GWEN_Padd_UnpaddWithPkcs1Bt2(buf);
00841     break;
00842 
00843   case GWEN_Crypt_PaddAlgoId_AnsiX9_23:
00844     return GWEN_Padd_UnpaddWithAnsiX9_23(buf);
00845 
00846   case GWEN_Crypt_PaddAlgoId_Iso9796_2:
00847     return GWEN_Padd_UnpaddWithIso9796_2(buf);
00848 
00849   case GWEN_Crypt_PaddAlgoId_Iso9796_1:
00850   case GWEN_Crypt_PaddAlgoId_LeftZero:
00851   case GWEN_Crypt_PaddAlgoId_RightZero:
00852   case GWEN_Crypt_PaddAlgoId_Iso9796_1A4:
00853   default:
00854     DBG_INFO(GWEN_LOGDOMAIN, "Algo-Type %d (%s) not supported",
00855              aid, GWEN_Crypt_PaddAlgoId_toString(aid));
00856     return GWEN_ERROR_NOT_AVAILABLE;
00857   }
00858 
00859   if (rv) {
00860     DBG_ERROR(GWEN_LOGDOMAIN, "Error padding with algo %d (%s)",
00861               aid, GWEN_Crypt_PaddAlgoId_toString(aid));
00862     return GWEN_ERROR_GENERIC;
00863   }
00864 
00865   return rv;
00866 }
00867 
00868 
00869 
00870 
00871 
00872 

Generated on Mon Jan 25 12:56:02 2010 for gwenhywfar by  doxygen 1.5.6