cryptdefs.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003                              -------------------
00004     cvs         : $Id: crypttoken.h 1113 2007-01-10 09:14:16Z martin $
00005     begin       : Wed Mar 16 2005
00006     copyright   : (C) 2005 by Martin Preuss
00007     email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *          Please see toplevel file COPYING for license details           *
00011  ***************************************************************************/
00012 
00013 #ifdef HAVE_CONFIG_H
00014 # include <config.h>
00015 #endif
00016 
00017 
00018 #include "cryptdefs_p.h"
00019 #include <gwenhywfar/misc.h>
00020 #include <gwenhywfar/debug.h>
00021 
00022 #include <gwenhywfar/mdigest.h>
00023 
00024 #include <gcrypt.h>
00025 
00026 
00027 
00028 
00029 GWEN_CRYPT_PINTYPE GWEN_Crypt_PinType_fromString(const char *s) {
00030   assert(s);
00031   if (strcasecmp(s, "none")==0)
00032     return GWEN_Crypt_PinType_None;
00033   else if (strcasecmp(s, "access")==0)
00034     return GWEN_Crypt_PinType_Access;
00035   else if (strcasecmp(s, "manage")==0)
00036     return GWEN_Crypt_PinType_Manage;
00037   return GWEN_Crypt_PinType_Unknown;
00038 }
00039 
00040 
00041 
00042 const char *GWEN_Crypt_PinType_toString(GWEN_CRYPT_PINTYPE pt) {
00043   switch(pt) {
00044   case GWEN_Crypt_PinType_None:
00045     return "none";
00046   case GWEN_Crypt_PinType_Access:
00047     return "access";
00048   case GWEN_Crypt_PinType_Manage:
00049     return "manage";
00050   default:
00051     return "unknown";
00052   }
00053 }
00054 
00055 
00056 
00057 GWEN_CRYPT_PINENCODING GWEN_Crypt_PinEncoding_fromString(const char *s) {
00058   assert(s);
00059   if (strcasecmp(s, "none")==0)
00060     return GWEN_Crypt_PinEncoding_None;
00061   else if (strcasecmp(s, "bin")==0)
00062     return GWEN_Crypt_PinEncoding_Bin;
00063   else if (strcasecmp(s, "bcd")==0)
00064     return GWEN_Crypt_PinEncoding_Bcd;
00065   else if (strcasecmp(s, "ascii")==0)
00066     return GWEN_Crypt_PinEncoding_Ascii;
00067   else if (strcasecmp(s, "fpin2")==0)
00068     return GWEN_Crypt_PinEncoding_FPin2;
00069   return GWEN_Crypt_PinEncoding_Unknown;
00070 }
00071 
00072 
00073 
00074 const char *GWEN_Crypt_PinEncoding_toString(GWEN_CRYPT_PINENCODING pe) {
00075   switch(pe) {
00076   case GWEN_Crypt_PinEncoding_None:
00077     return "none";
00078   case GWEN_Crypt_PinEncoding_Bin:
00079     return "bin";
00080   case GWEN_Crypt_PinEncoding_Bcd:
00081     return "bcd";
00082   case GWEN_Crypt_PinEncoding_Ascii:
00083     return "ascii";
00084   case GWEN_Crypt_PinEncoding_FPin2:
00085     return "fpin2";
00086   default:
00087     return "unknown";
00088   }
00089 }
00090 
00091 
00092 
00093 int GWEN_Crypt__TransformFromBCD(unsigned char *buffer,
00094                                  unsigned int bufLength,
00095                                  unsigned int *pinLength) {
00096   unsigned char *newBuf;
00097   unsigned char *p;
00098   unsigned int newSize;
00099   unsigned int i;
00100   unsigned int cnt=0;
00101 
00102   if (*pinLength==0)
00103     return 0;
00104 
00105   newSize=*pinLength*2;
00106   newBuf=(unsigned char*)malloc(newSize);
00107   p=newBuf;
00108   for (i=0; i<*pinLength; i++) {
00109     unsigned char c1;
00110     unsigned char c2;
00111 
00112     c1=buffer[i];
00113     /* 1st digit */
00114     c2=(c1 & 0xf0)>>4;
00115     if (c2==0x0f)
00116       break;
00117     *(p++)=c2+'0';
00118     cnt++;
00119     /* 2nd digit */
00120     c2=(c1 & 0x0f);
00121     if (c2==0x0f)
00122       break;
00123     *(p++)=c2+'0';
00124     cnt++;
00125   }
00126 
00127   if (cnt>bufLength) {
00128     DBG_ERROR(GWEN_LOGDOMAIN, "Converted pin is too long (%d>%d)",
00129               cnt, bufLength);
00130     free(newBuf);
00131     return GWEN_ERROR_BUFFER_OVERFLOW;
00132   }
00133 
00134   memset(buffer, 0, bufLength);
00135   memmove(buffer, newBuf, cnt);
00136   *pinLength=cnt;
00137   free(newBuf);
00138   return 0;
00139 }
00140 
00141 
00142 
00143 int GWEN_Crypt__TransformFromFPIN2(unsigned char *buffer,
00144                                    unsigned int bufLength,
00145                                    unsigned int *pinLength) {
00146   unsigned char *newBuf;
00147   unsigned char *p;
00148   unsigned int newSize;
00149   unsigned int i;
00150   unsigned int cnt=0;
00151   unsigned int len;
00152 
00153   if (*pinLength<8) {
00154     DBG_ERROR(GWEN_LOGDOMAIN, "Pin too small to be a FPIN2 (%d<8)", *pinLength);
00155     return GWEN_ERROR_INVALID;
00156   }
00157   len=(buffer[0] & 0x0f);
00158   newSize=len*2;
00159   newBuf=(unsigned char*)malloc(newSize);
00160   p=newBuf;
00161   for (i=1; i<8; i++) {
00162     unsigned char c1;
00163     unsigned char c2;
00164 
00165     if (cnt>=len)
00166       break;
00167 
00168     c1=buffer[i];
00169     /* 1st digit */
00170     c2=(c1 & 0xf0)>>4;
00171     if (c2==0x0f)
00172       break;
00173     *(p++)=c2+'0';
00174     cnt++;
00175     if (cnt>=len)
00176       break;
00177 
00178     /* 2nd digit */
00179     c2=(c1 & 0x0f);
00180     if (c2==0x0f)
00181       break;
00182     *(p++)=c2+'0';
00183     cnt++;
00184   }
00185 
00186   if (cnt>bufLength) {
00187     DBG_ERROR(GWEN_LOGDOMAIN, "Converted pin is too long (%d>%d)",
00188               cnt, bufLength);
00189     free(newBuf);
00190     return GWEN_ERROR_BUFFER_OVERFLOW;
00191   }
00192 
00193   memset(buffer, 0, bufLength);
00194   memmove(buffer, newBuf, cnt);
00195   *pinLength=cnt;
00196   return 0;
00197 }
00198 
00199 
00200 
00201 int GWEN_Crypt__TransformFromBin(unsigned char *buffer,
00202                                  unsigned int bufLength,
00203                                  unsigned int *pinLength) {
00204   unsigned int i;
00205   unsigned char *newBuf;
00206   unsigned char *p;
00207   unsigned int newSize;
00208 
00209   if (*pinLength==0)
00210     return 0;
00211 
00212   newSize=*pinLength;
00213   newBuf=(unsigned char*)malloc(newSize);
00214   p=newBuf;
00215 
00216   for (i=0; i<*pinLength; i++) {
00217     unsigned char c;
00218 
00219     c=buffer[i];
00220     if (c>9) {
00221       DBG_ERROR(GWEN_LOGDOMAIN, "Invalid element in pin (a digit > 9)");
00222       free(newBuf);
00223       return GWEN_ERROR_INVALID;
00224     }
00225     *p=c+'0';
00226   }
00227   memset(buffer, 0, bufLength);
00228   memmove(buffer, newBuf, *pinLength);
00229   free(newBuf);
00230 
00231   return 0;
00232 }
00233 
00234 
00235 
00236 int GWEN_Crypt__TransformToBCD(unsigned char *buffer,
00237                                unsigned int bufLength,
00238                                unsigned int *pinLength) {
00239   unsigned char *newBuf;
00240   unsigned char *p;
00241   unsigned int newSize;
00242   unsigned int i;
00243   unsigned int cnt=0;
00244 
00245   newSize=*pinLength/2+1;
00246   newBuf=(unsigned char*)malloc(newSize);
00247   memset(newBuf, 0xff, newSize);
00248   p=newBuf;
00249   i=0;
00250   while (i<*pinLength) {
00251     unsigned char c1;
00252     unsigned char c2;
00253 
00254     /* 1st digit */
00255     c1=buffer[i];
00256     if (c1<'0' || c1>'9') {
00257       DBG_ERROR(GWEN_LOGDOMAIN, "Invalid element in pin (a non-number character)");
00258       free(newBuf);
00259       return GWEN_ERROR_INVALID;
00260     }
00261     c1-='0';
00262     c1=c1<<4;
00263     *p=c1+0x0f; /* don't incement yet */
00264     cnt++; /* only increment once !! */
00265     i++;
00266     if (i>=*pinLength)
00267       break;
00268 
00269     /* 2nd digit */
00270     c2=buffer[i];
00271     if (c2<'0' || c2>'9') {
00272       DBG_ERROR(GWEN_LOGDOMAIN, "Invalid element in pin (a non-number character)");
00273       free(newBuf);
00274       return GWEN_ERROR_INVALID;
00275     }
00276     c2-='0';
00277     c1|=(c2 & 0x0f);
00278     *(p++)=c1;
00279     i++;
00280   }
00281 
00282   if (cnt>bufLength) {
00283     DBG_ERROR(GWEN_LOGDOMAIN, "Converted pin is too long (%d>%d)",
00284               cnt, bufLength);
00285     free(newBuf);
00286     return GWEN_ERROR_BUFFER_OVERFLOW;
00287   }
00288 
00289   memset(buffer, 0, bufLength);
00290   for (i=0; i<cnt; i++)
00291     buffer[i]=newBuf[i];
00292   *pinLength=cnt;
00293   free(newBuf);
00294   return 0;
00295 }
00296 
00297 
00298 
00299 int GWEN_Crypt__TransformToFPIN2(unsigned char *buffer,
00300                                  unsigned int bufLength,
00301                                  unsigned int *pinLength) {
00302   unsigned char *newBuf;
00303   unsigned char *p;
00304   unsigned int newSize;
00305   unsigned int i;
00306 
00307   if (*pinLength>14) {
00308     DBG_ERROR(GWEN_LOGDOMAIN, "Pin too long for FPIN2 (%d>14)",
00309               *pinLength);
00310     return GWEN_ERROR_INVALID;
00311   }
00312   if (8>bufLength) {
00313     DBG_ERROR(GWEN_LOGDOMAIN, "Converted pin is too long (8>%d)",
00314               bufLength);
00315     return GWEN_ERROR_BUFFER_OVERFLOW;
00316   }
00317 
00318   newSize=8;
00319   newBuf=(unsigned char*)malloc(newSize);
00320   memset(newBuf, 0xff, newSize);
00321   p=newBuf;
00322   *(p++)=0x20+*pinLength;
00323   i=0;
00324   while (i<*pinLength) {
00325     unsigned char c1;
00326     unsigned char c2;
00327 
00328     /* 1st digit */
00329     c1=buffer[i];
00330     if (c1<'0' || c1>'9') {
00331       DBG_ERROR(GWEN_LOGDOMAIN, "Invalid element in pin (a non-number character)");
00332       free(newBuf);
00333       return GWEN_ERROR_INVALID;
00334     }
00335     c1-='0';
00336     c1=c1<<4;
00337     *p=c1+0x0f; /* don't incement yet */
00338     i++;
00339     if (i>=*pinLength)
00340       break;
00341 
00342     /* 2nd digit */
00343     c2=buffer[i];
00344     if (c2<'0' || c2>'9') {
00345       DBG_ERROR(GWEN_LOGDOMAIN, "Invalid element in pin (a non-number character)");
00346       free(newBuf);
00347       return GWEN_ERROR_INVALID;
00348     }
00349     c2-='0';
00350     c1|=(c2 & 0x0f);
00351     *(p++)=c1;
00352     i++;
00353   }
00354 
00355   memset(buffer, 0, bufLength);
00356   for (i=0; i<8; i++)
00357     buffer[i]=newBuf[i];
00358   *pinLength=8;
00359   free(newBuf);
00360   return 0;
00361 
00362 }
00363 
00364 
00365 
00366 int GWEN_Crypt__TransformToBin(unsigned char *buffer,
00367                                unsigned int bufLength,
00368                                unsigned int *pinLength) {
00369   unsigned int i;
00370   unsigned char *newBuf;
00371   unsigned char *p;
00372   unsigned int newSize;
00373 
00374   if (*pinLength==0)
00375     return 0;
00376 
00377   newSize=*pinLength;
00378   newBuf=(unsigned char*)malloc(newSize);
00379   p=newBuf;
00380 
00381   for (i=0; i<*pinLength; i++) {
00382     unsigned char c;
00383 
00384     c=buffer[i];
00385     if (c<'0' || c>'9') {
00386       DBG_ERROR(GWEN_LOGDOMAIN, "Invalid element in pin (a non-number character)");
00387       free(newBuf);
00388       return GWEN_ERROR_INVALID;
00389     }
00390     *(p++)=c-'0';
00391   }
00392   memset(buffer, 0, bufLength);
00393   memmove(buffer, newBuf, *pinLength);
00394   free(newBuf);
00395 
00396   return 0;
00397 }
00398 
00399 
00400 
00401 int GWEN_Crypt_TransformPin(GWEN_CRYPT_PINENCODING peSrc,
00402                             GWEN_CRYPT_PINENCODING peDst,
00403                             unsigned char *buffer,
00404                             unsigned int bufLength,
00405                             unsigned int *pinLength) {
00406   int rv;
00407 
00408   if (peSrc==peDst)
00409     return 0;
00410 
00411   switch(peSrc) {
00412   case GWEN_Crypt_PinEncoding_Bin:
00413     rv=GWEN_Crypt__TransformFromBin(buffer, bufLength, pinLength);
00414     break;
00415   case GWEN_Crypt_PinEncoding_Bcd:
00416     rv=GWEN_Crypt__TransformFromBCD(buffer, bufLength, pinLength);
00417     break;
00418   case GWEN_Crypt_PinEncoding_Ascii:
00419     rv=0;
00420     break;
00421   case GWEN_Crypt_PinEncoding_FPin2:
00422     rv=GWEN_Crypt__TransformFromFPIN2(buffer, bufLength, pinLength);
00423     break;
00424   default:
00425     DBG_ERROR(GWEN_LOGDOMAIN,
00426               "Unhandled source encoding \"%s\"",
00427               GWEN_Crypt_PinEncoding_toString(peSrc));
00428     return GWEN_ERROR_INVALID;
00429   }
00430   if (rv) {
00431     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00432     return rv;
00433   }
00434 
00435   switch(peDst) {
00436   case GWEN_Crypt_PinEncoding_Bin:
00437     rv=GWEN_Crypt__TransformToBin(buffer, bufLength, pinLength);
00438     break;
00439   case GWEN_Crypt_PinEncoding_Bcd:
00440     rv=GWEN_Crypt__TransformToBCD(buffer, bufLength, pinLength);
00441     break;
00442   case GWEN_Crypt_PinEncoding_Ascii:
00443     rv=0;
00444     break;
00445   case GWEN_Crypt_PinEncoding_FPin2:
00446     rv=GWEN_Crypt__TransformToFPIN2(buffer, bufLength, pinLength);
00447     break;
00448   default:
00449     DBG_ERROR(GWEN_LOGDOMAIN,
00450               "Unhandled destination encoding \"%s\"",
00451               GWEN_Crypt_PinEncoding_toString(peDst));
00452     return GWEN_ERROR_INVALID;
00453   }
00454   if (rv) {
00455     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00456     return rv;
00457   }
00458 
00459   return 0;
00460 }
00461 
00462 
00463 
00464 
00465 static int GWEN_Crypt__KeyDataFromText(const char *text,
00466                                        unsigned char *buffer,
00467                                        unsigned int bufLength) {
00468   GWEN_MDIGEST *md;
00469   int rv;
00470 
00471   assert(text);
00472   assert(buffer);
00473   assert(bufLength);
00474 
00475   switch(bufLength) {
00476   case 16: md=GWEN_MDigest_Md5_new(); break;
00477   case 20: md=GWEN_MDigest_Rmd160_new(); break;
00478   default:
00479     DBG_ERROR(GWEN_LOGDOMAIN, "Bad size (%d)", bufLength);
00480     return GWEN_ERROR_BAD_SIZE;
00481   }
00482 
00483   rv=GWEN_MDigest_Begin(md);
00484   if (rv) {
00485     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00486     GWEN_MDigest_free(md);
00487     return rv;
00488   }
00489 
00490   rv=GWEN_MDigest_Update(md,
00491                          (const uint8_t*)text,
00492                          strlen(text));
00493   if (rv) {
00494     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00495     GWEN_MDigest_free(md);
00496     return rv;
00497   }
00498 
00499   rv=GWEN_MDigest_End(md);
00500   if (rv) {
00501     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00502     GWEN_MDigest_free(md);
00503     return rv;
00504   }
00505 
00506   /* get hash, copy it to given buffer */
00507   memmove(buffer, GWEN_MDigest_GetDigestPtr(md), bufLength);
00508 
00509   /* cleanup, return */
00510   GWEN_MDigest_free(md);
00511   return 0;
00512 }
00513 
00514 
00515 
00516 int GWEN_Crypt_KeyDataFromText(const char *text,
00517                                unsigned char *buffer,
00518                                unsigned int bufLength) {
00519   if (bufLength==24) {
00520     int rv;
00521 
00522     rv=GWEN_Crypt__KeyDataFromText(text, buffer, 16);
00523     if (rv)
00524       return rv;
00525     memmove(buffer+16, buffer, 8);
00526     return rv;
00527   }
00528   else
00529     return GWEN_Crypt__KeyDataFromText(text, buffer, bufLength);
00530 }
00531 
00532 
00533 
00534 void GWEN_Crypt_Random(int quality, uint8_t *buffer, uint32_t len) {
00535   uint8_t *data;
00536   enum gcry_random_level q;
00537 
00538   switch(quality) {
00539   case 0:  q=GCRY_WEAK_RANDOM; break;
00540   case 1:  q=GCRY_STRONG_RANDOM; break;
00541   case 2:
00542   default: q=GCRY_VERY_STRONG_RANDOM; break;
00543   }
00544 
00545   data=gcry_random_bytes(len,  q);
00546   assert(data);
00547   memmove(buffer, data, len);
00548   memset(data, 0, len);
00549   free(data);
00550 }
00551 
00552 
00553 
00554 
00555 
00556