00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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 <string.h>
00039 #include <stdlib.h>
00040
00041
00042
00043
00044
00045
00046
00047
00048 unsigned char GWEN_Padd_permutate(unsigned char input) {
00049 unsigned char leftNibble;
00050 unsigned char rightNibble;
00051 static const unsigned char lookUp[2][16] =
00052 {{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
00053 {14,3,5,8,9,4,2,15,0,13,11,6,7,10,12,1}};
00054
00055 rightNibble = input & 15;
00056 leftNibble = input & 240;
00057 leftNibble = leftNibble / 16;
00058 rightNibble = lookUp[1][rightNibble];
00059 leftNibble = lookUp[1][leftNibble];
00060 leftNibble = leftNibble * 16;
00061
00062 return leftNibble + rightNibble;
00063 }
00064
00065
00066
00067
00068
00069
00070
00071 int GWEN_Padd_PaddWithISO9796(GWEN_BUFFER *src) {
00072 unsigned char *p;
00073 unsigned int l;
00074 unsigned int i;
00075 unsigned char buffer[GWEN_PADD_ISO9796_KEYSIZE];
00076 unsigned char hash[20];
00077 unsigned char c;
00078
00079 p=(unsigned char*)GWEN_Buffer_GetStart(src);
00080 l=GWEN_Buffer_GetUsedBytes(src);
00081 memmove(hash, p, l);
00082
00083
00084 if (GWEN_Buffer_AppendBytes(src, (const char*)hash, l)) {
00085 DBG_INFO(GWEN_LOGDOMAIN, "here");
00086 return -1;
00087 }
00088
00089 if (GWEN_Buffer_AppendBytes(src, (const char*)hash, l)) {
00090 DBG_INFO(GWEN_LOGDOMAIN, "here");
00091 return -1;
00092 }
00093
00094
00095 if (GWEN_Buffer_Crop(src, 20, 40)) {
00096 DBG_INFO(GWEN_LOGDOMAIN, "here");
00097 return -1;
00098 }
00099
00100 memset(buffer, 0, sizeof(buffer));
00101
00102
00103 p=(unsigned char*)GWEN_Buffer_GetStart(src);
00104 for (i=0; i<=47; i++) {
00105 int j1, j2, j3;
00106
00107 j1=1 + sizeof(buffer) - (2*i);
00108 j2=40-i;
00109 j3=sizeof(buffer) - (2*i);
00110
00111 if (j1>=0 && j1<(int)sizeof(buffer) && j2>=0) {
00112 buffer[j1]=p[j2];
00113 }
00114 if (j3>=0 && j3<(int)sizeof(buffer) && j2>=0) {
00115 buffer[j3]=GWEN_Padd_permutate(p[j2]);
00116 }
00117 }
00118
00119
00120 memmove(buffer, buffer+(sizeof(buffer)-16), 16);
00121
00122 p=buffer;
00123
00124 c=p[sizeof(buffer)-1];
00125 c = (c & 15) * 16;
00126 c += 6;
00127 p[sizeof(buffer)-1]=c;
00128 p[0] = p[0] & 127;
00129 p[0] = p[0] | 64;
00130 p[sizeof(buffer) - 40] = p[sizeof(buffer) - 40] ^ 1;
00131
00132 GWEN_Buffer_Reset(src);
00133 if (GWEN_Buffer_AppendBytes(src, (const char*)buffer, sizeof(buffer))) {
00134 DBG_INFO(GWEN_LOGDOMAIN, "here");
00135 return -1;
00136 }
00137
00138 return 0;
00139 }
00140
00141
00142
00143 int GWEN_Padd_PaddWithIso9796_2(GWEN_BUFFER *buf, int dstSize){
00144 unsigned int diff;
00145 char *p;
00146 int i;
00147
00148 if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)+31) {
00149 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data");
00150 return GWEN_ERROR_INVALID;
00151 }
00152
00153
00154 GWEN_Buffer_AppendByte(buf, 0xbc);
00155
00156
00157 GWEN_Buffer_Rewind(buf);
00158
00159
00160 diff=dstSize-31;
00161 if (GWEN_Buffer_InsertRoom(buf, 1+diff+1+8)) {
00162 DBG_ERROR(GWEN_LOGDOMAIN,
00163 "Could not insert room for %d bytes",
00164 1+diff+1+8);
00165 return GWEN_ERROR_GENERIC;
00166 }
00167
00168
00169 p=GWEN_Buffer_GetStart(buf);
00170 *(p++)=0x60;
00171
00172
00173 for (i=0; i<diff; i++)
00174 *(p++)=0x0;
00175 *(p++)=0x01;
00176
00177
00178 GWEN_Crypt_Random(2, (uint8_t*)p, 8);
00179 for (i=0; i<8; i++) {
00180 if (*p==0)
00181
00182 *p=0xff;
00183 p++;
00184 }
00185 *(p++)=0x01;
00186
00187 return 0;
00188 }
00189
00190
00191
00192 int GWEN_Padd_UnpaddWithIso9796_2(GWEN_BUFFER *buf){
00193 uint32_t l;
00194
00195 l=GWEN_Buffer_GetUsedBytes(buf);
00196 if (l<31) {
00197 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too few bytes");
00198 return GWEN_ERROR_INVALID;
00199 }
00200
00201 GWEN_Buffer_Crop(buf, l-21, 20);
00202
00203 return 0;
00204 }
00205
00206
00207
00208
00209 int GWEN_Padd_PaddWithAnsiX9_23(GWEN_BUFFER *src) {
00210 unsigned char paddLength;
00211 unsigned int i;
00212
00213 paddLength=8-(GWEN_Buffer_GetUsedBytes(src) % 8);
00214 for (i=0; i<paddLength; i++)
00215 GWEN_Buffer_AppendByte(src, paddLength);
00216 return 0;
00217 }
00218
00219
00220
00221 int GWEN_Padd_UnpaddWithAnsiX9_23(GWEN_BUFFER *src) {
00222 const char *p;
00223 unsigned int lastpos;
00224 unsigned char paddLength;
00225
00226 lastpos=GWEN_Buffer_GetUsedBytes(src);
00227 if (lastpos<8) {
00228 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00229 return -1;
00230 }
00231 lastpos--;
00232
00233 p=GWEN_Buffer_GetStart(src)+lastpos;
00234 paddLength=*p;
00235 if (paddLength<1 || paddLength>8) {
00236 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid padding (%d bytes ?)", paddLength);
00237 return -1;
00238 }
00239 GWEN_Buffer_Crop(src, 0, GWEN_Buffer_GetUsedBytes(src)-paddLength);
00240 GWEN_Buffer_SetPos(src, lastpos-paddLength);
00241 return 0;
00242 }
00243
00244
00245
00246 int GWEN_Padd_PaddWithPkcs1Bt1(GWEN_BUFFER *buf, int dstSize){
00247 unsigned int diff;
00248 char *p;
00249
00250 if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)) {
00251 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data");
00252 return GWEN_ERROR_INVALID;
00253 }
00254 diff=dstSize-GWEN_Buffer_GetUsedBytes(buf);
00255 if (diff<11) {
00256
00257
00258 DBG_ERROR(GWEN_LOGDOMAIN,
00259 "Buffer contains too many bytes (diff is <11)");
00260 return GWEN_ERROR_INVALID;
00261 }
00262
00263
00264 GWEN_Buffer_Rewind(buf);
00265 if (GWEN_Buffer_InsertRoom(buf, diff)) {
00266 DBG_ERROR(GWEN_LOGDOMAIN, "Could not insert room for %d bytes", diff);
00267 return GWEN_ERROR_GENERIC;
00268 }
00269
00270 p=GWEN_Buffer_GetStart(buf);
00271 *(p++)=0x00;
00272 *(p++)=0x01;
00273 if (diff>3) {
00274 memset(p, 0xff, diff-3);
00275 p+=diff-3;
00276 }
00277 *(p++)=0x00;
00278
00279 return 0;
00280 }
00281
00282
00283
00284 int GWEN_Padd_PaddWithPkcs1Bt2(GWEN_BUFFER *buf, int dstSize){
00285 unsigned int diff;
00286 char *p;
00287 int i;
00288
00289 if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)) {
00290 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data");
00291 return GWEN_ERROR_INVALID;
00292 }
00293 diff=dstSize-GWEN_Buffer_GetUsedBytes(buf);
00294 if (diff<11) {
00295
00296
00297 DBG_ERROR(GWEN_LOGDOMAIN,
00298 "Buffer contains too many bytes (diff is <11)");
00299 return GWEN_ERROR_INVALID;
00300 }
00301
00302
00303 GWEN_Buffer_Rewind(buf);
00304 if (GWEN_Buffer_InsertRoom(buf, diff)) {
00305 DBG_ERROR(GWEN_LOGDOMAIN, "Could not insert room for %d bytes", diff);
00306 return GWEN_ERROR_GENERIC;
00307 }
00308
00309 p=GWEN_Buffer_GetStart(buf);
00310 *(p++)=0x00;
00311 *(p++)=0x02;
00312 GWEN_Crypt_Random(2, (uint8_t*)p, diff-3);
00313 for (i=0; i<diff-3; i++) {
00314 if (*p==0)
00315
00316 *p=0xff;
00317 p++;
00318 }
00319 *(p++)=0x00;
00320
00321 return 0;
00322 }
00323
00324
00325
00326 int GWEN_Padd__UnpaddWithPkcs1Bt1Or2(GWEN_BUFFER *buf) {
00327 char *p;
00328 uint32_t len;
00329 uint32_t paddBytes;
00330
00331 assert(buf);
00332 len=GWEN_Buffer_GetUsedBytes(buf);
00333 assert(len);
00334
00335 p=GWEN_Buffer_GetStart(buf);
00336 if (*p==0) {
00337 p++;
00338 len--;
00339 }
00340 if (len<11) {
00341 DBG_ERROR(GWEN_LOGDOMAIN, "Too few bytes left (%d)", len);
00342 return GWEN_ERROR_INVALID;
00343 }
00344
00345 if (*p!=0x01 && *p!=0x02) {
00346 DBG_ERROR(GWEN_LOGDOMAIN, "Unsupported block type %02x", *p);
00347 return GWEN_ERROR_INVALID;
00348 }
00349 p++; len--;
00350
00351
00352 paddBytes=0;
00353 while(*p!=0x00 && len) {
00354 p++; len--;
00355 paddBytes++;
00356 }
00357
00358 if (*p!=0x00) {
00359 DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding");
00360 return GWEN_ERROR_INVALID;
00361 }
00362 p++; len--;
00363
00364 if (paddBytes<8) {
00365
00366 DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding (too few padding bytes)");
00367 return GWEN_ERROR_INVALID;
00368 }
00369
00370 GWEN_Buffer_Crop(buf, GWEN_Buffer_GetUsedBytes(buf)-len, len);
00371
00372 return 0;
00373 }
00374
00375
00376
00377 int GWEN_Padd_UnpaddWithPkcs1Bt1(GWEN_BUFFER *src){
00378 return GWEN_Padd__UnpaddWithPkcs1Bt1Or2(src);
00379 }
00380
00381
00382
00383 int GWEN_Padd_UnpaddWithPkcs1Bt2(GWEN_BUFFER *src){
00384 return GWEN_Padd__UnpaddWithPkcs1Bt1Or2(src);
00385 }
00386
00387
00388
00389 int GWEN_Padd_ApplyPaddAlgo(const GWEN_CRYPT_PADDALGO *a, GWEN_BUFFER *buf) {
00390 int rv;
00391 unsigned int diff;
00392 unsigned int bsize;
00393 unsigned int dstSize;
00394 unsigned int chunkSize;
00395 GWEN_CRYPT_PADDALGOID aid;
00396
00397 assert(a);
00398 assert(buf);
00399
00400 aid=GWEN_Crypt_PaddAlgo_GetId(a);
00401 if (aid==GWEN_Crypt_PaddAlgoId_None)
00402
00403 return 0;
00404
00405 chunkSize=GWEN_Crypt_PaddAlgo_GetPaddSize(a);
00406 if (chunkSize==0) {
00407 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid chunk size (0)");
00408 return GWEN_ERROR_INVALID;
00409 }
00410
00411 bsize=GWEN_Buffer_GetUsedBytes(buf);
00412 dstSize=bsize+(chunkSize-1);
00413 dstSize=(dstSize/chunkSize)*chunkSize;
00414 diff=dstSize-bsize;
00415
00416 DBG_INFO(GWEN_LOGDOMAIN, "Padding with algo \"%s\"",
00417 GWEN_Crypt_PaddAlgoId_toString(aid));
00418
00419 switch(aid) {
00420 case GWEN_Crypt_PaddAlgoId_None:
00421 rv=0;
00422 break;
00423
00424 case GWEN_Crypt_PaddAlgoId_Iso9796_1A4:
00425 if (dstSize>96) {
00426 DBG_ERROR(GWEN_LOGDOMAIN,
00427 "Padding size must be <=96 bytes (is %d)",
00428 dstSize);
00429 return GWEN_ERROR_INVALID;
00430 }
00431 rv=GWEN_Padd_PaddWithISO9796(buf);
00432 break;
00433
00434 case GWEN_Crypt_PaddAlgoId_Pkcs1_1:
00435 rv=GWEN_Padd_PaddWithPkcs1Bt1(buf, dstSize);
00436 break;
00437
00438 case GWEN_Crypt_PaddAlgoId_Pkcs1_2:
00439 rv=GWEN_Padd_PaddWithPkcs1Bt2(buf, dstSize);
00440 break;
00441
00442 case GWEN_Crypt_PaddAlgoId_LeftZero:
00443 rv=GWEN_Buffer_FillLeftWithBytes(buf, 0, diff);
00444 break;
00445
00446 case GWEN_Crypt_PaddAlgoId_RightZero:
00447 rv=GWEN_Buffer_FillWithBytes(buf, 0, diff);
00448 break;
00449
00450 case GWEN_Crypt_PaddAlgoId_AnsiX9_23:
00451 return GWEN_Padd_PaddWithAnsiX9_23(buf);
00452
00453 case GWEN_Crypt_PaddAlgoId_Iso9796_2:
00454 return GWEN_Padd_PaddWithIso9796_2(buf, dstSize);
00455
00456 case GWEN_Crypt_PaddAlgoId_Iso9796_1:
00457 default:
00458 DBG_INFO(GWEN_LOGDOMAIN, "Algo-Type %d (%s) not supported",
00459 aid, GWEN_Crypt_PaddAlgoId_toString(aid));
00460 return GWEN_ERROR_NOT_AVAILABLE;
00461 }
00462
00463 if (rv) {
00464 DBG_ERROR(GWEN_LOGDOMAIN, "Error padding with algo %d (%s)",
00465 aid, GWEN_Crypt_PaddAlgoId_toString(aid));
00466 return GWEN_ERROR_GENERIC;
00467 }
00468
00469 return rv;
00470 }
00471
00472
00473
00474 int GWEN_Padd_UnapplyPaddAlgo(const GWEN_CRYPT_PADDALGO *a, GWEN_BUFFER *buf){
00475 int rv;
00476 GWEN_CRYPT_PADDALGOID aid;
00477
00478 assert(a);
00479 assert(buf);
00480
00481 aid=GWEN_Crypt_PaddAlgo_GetId(a);
00482 DBG_INFO(GWEN_LOGDOMAIN, "Unpadding with algo \"%s\"",
00483 GWEN_Crypt_PaddAlgoId_toString(aid));
00484
00485 switch(aid) {
00486 case GWEN_Crypt_PaddAlgoId_None:
00487 rv=0;
00488 break;
00489
00490 case GWEN_Crypt_PaddAlgoId_Pkcs1_1:
00491 rv=GWEN_Padd_UnpaddWithPkcs1Bt1(buf);
00492 break;
00493
00494 case GWEN_Crypt_PaddAlgoId_Pkcs1_2:
00495 rv=GWEN_Padd_UnpaddWithPkcs1Bt2(buf);
00496 break;
00497
00498 case GWEN_Crypt_PaddAlgoId_AnsiX9_23:
00499 return GWEN_Padd_UnpaddWithAnsiX9_23(buf);
00500
00501 case GWEN_Crypt_PaddAlgoId_Iso9796_2:
00502 return GWEN_Padd_UnpaddWithIso9796_2(buf);
00503
00504 case GWEN_Crypt_PaddAlgoId_Iso9796_1:
00505 case GWEN_Crypt_PaddAlgoId_LeftZero:
00506 case GWEN_Crypt_PaddAlgoId_RightZero:
00507 case GWEN_Crypt_PaddAlgoId_Iso9796_1A4:
00508 default:
00509 DBG_INFO(GWEN_LOGDOMAIN, "Algo-Type %d (%s) not supported",
00510 aid, GWEN_Crypt_PaddAlgoId_toString(aid));
00511 return GWEN_ERROR_NOT_AVAILABLE;
00512 }
00513
00514 if (rv) {
00515 DBG_ERROR(GWEN_LOGDOMAIN, "Error padding with algo %d (%s)",
00516 aid, GWEN_Crypt_PaddAlgoId_toString(aid));
00517 return GWEN_ERROR_GENERIC;
00518 }
00519
00520 return rv;
00521 }
00522
00523
00524
00525
00526
00527