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 int GWEN_Padd_PaddWithIso9796_2(GWEN_BUFFER *buf, int dstSize){
00143 unsigned int diff;
00144 char *p;
00145 int i;
00146
00147 if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)+12) {
00148
00149 return GWEN_ERROR_INVALID;
00150 }
00151
00152
00153 GWEN_Buffer_AppendByte(buf, 0xbc);
00154
00155
00156 GWEN_Buffer_Rewind(buf);
00157
00158
00159 diff=dstSize-GWEN_Buffer_GetUsedBytes(buf)-11+1;
00160 if (GWEN_Buffer_InsertRoom(buf, 1+diff+1+8)) {
00161 DBG_ERROR(GWEN_LOGDOMAIN,
00162 "Could not insert room for %d bytes",
00163 1+diff+1+8);
00164 return GWEN_ERROR_GENERIC;
00165 }
00166
00167
00168 p=GWEN_Buffer_GetStart(buf);
00169 *(p++)=0x60;
00170
00171
00172 for (i=0; i<diff; i++)
00173 *(p++)=0x0;
00174 *(p++)=0x01;
00175
00176
00177 GWEN_Crypt_Random(2, (uint8_t*)p, 8);
00178 for (i=0; i<8; i++) {
00179 if (*p==0)
00180
00181 *p=0xff;
00182 p++;
00183 }
00184
00185 return 0;
00186 }
00187
00188
00189 int GWEN_Padd_UnpaddWithIso9796_2(GWEN_BUFFER *buf){
00190 uint32_t l;
00191 uint32_t realSize;
00192 const uint8_t *p;
00193
00194 l=GWEN_Buffer_GetUsedBytes(buf);
00195 if (l<11) {
00196 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too few bytes");
00197 return GWEN_ERROR_INVALID;
00198 }
00199
00200 p=(const uint8_t*)GWEN_Buffer_GetStart(buf);
00201 if (*p!=0x60) {
00202 DBG_ERROR(GWEN_LOGDOMAIN, "First byte is not a 0x60");
00203 return GWEN_ERROR_BAD_DATA;
00204 }
00205 p++;
00206 l=0;
00207 while(*p==0x00) {
00208 l++;
00209 p++;
00210 }
00211 if (*p!=0x01) {
00212
00213 return GWEN_ERROR_BAD_DATA;
00214 }
00215
00216 realSize=GWEN_Buffer_GetUsedBytes(buf)-11-l;
00217 GWEN_Buffer_Crop(buf, 10+l, realSize);
00218
00219 return 0;
00220 }
00221
00222
00223
00224 int GWEN_Padd_PaddWithAnsiX9_23(GWEN_BUFFER *src) {
00225 unsigned char paddLength;
00226 unsigned int i;
00227
00228 paddLength=8-(GWEN_Buffer_GetUsedBytes(src) % 8);
00229 for (i=0; i<paddLength; i++)
00230 GWEN_Buffer_AppendByte(src, paddLength);
00231 return 0;
00232 }
00233
00234
00235
00236 int GWEN_Padd_UnpaddWithAnsiX9_23(GWEN_BUFFER *src) {
00237 const char *p;
00238 unsigned int lastpos;
00239 unsigned char paddLength;
00240
00241 lastpos=GWEN_Buffer_GetUsedBytes(src);
00242 if (lastpos<8) {
00243 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00244 return -1;
00245 }
00246 lastpos--;
00247
00248 p=GWEN_Buffer_GetStart(src)+lastpos;
00249 paddLength=*p;
00250 if (paddLength<1 || paddLength>8) {
00251 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid padding (%d bytes ?)", paddLength);
00252 return -1;
00253 }
00254 GWEN_Buffer_Crop(src, 0, GWEN_Buffer_GetUsedBytes(src)-paddLength);
00255 GWEN_Buffer_SetPos(src, lastpos-paddLength);
00256 return 0;
00257 }
00258
00259
00260
00261 int GWEN_Padd_PaddWithPkcs1Bt1(GWEN_BUFFER *buf, int dstSize){
00262 unsigned int diff;
00263 char *p;
00264
00265 if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)) {
00266 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data");
00267 return GWEN_ERROR_INVALID;
00268 }
00269 diff=dstSize-GWEN_Buffer_GetUsedBytes(buf);
00270 if (diff<11) {
00271
00272
00273 DBG_ERROR(GWEN_LOGDOMAIN,
00274 "Buffer contains too many bytes (diff is <11)");
00275 return GWEN_ERROR_INVALID;
00276 }
00277
00278
00279 GWEN_Buffer_Rewind(buf);
00280 if (GWEN_Buffer_InsertRoom(buf, diff)) {
00281 DBG_ERROR(GWEN_LOGDOMAIN, "Could not insert room for %d bytes", diff);
00282 return GWEN_ERROR_GENERIC;
00283 }
00284
00285 p=GWEN_Buffer_GetStart(buf);
00286 *(p++)=0x00;
00287 *(p++)=0x01;
00288 if (diff>3) {
00289 memset(p, 0xff, diff-3);
00290 p+=diff-3;
00291 }
00292 *(p++)=0x00;
00293
00294 return 0;
00295 }
00296
00297
00298
00299 int GWEN_Padd_PaddWithPkcs1Bt2(GWEN_BUFFER *buf, int dstSize){
00300 unsigned int diff;
00301 char *p;
00302 int i;
00303
00304 if ((unsigned int)dstSize<GWEN_Buffer_GetUsedBytes(buf)) {
00305 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer contains too much data");
00306 return GWEN_ERROR_INVALID;
00307 }
00308 diff=dstSize-GWEN_Buffer_GetUsedBytes(buf);
00309 if (diff<11) {
00310
00311
00312 DBG_ERROR(GWEN_LOGDOMAIN,
00313 "Buffer contains too many bytes (diff is <11)");
00314 return GWEN_ERROR_INVALID;
00315 }
00316
00317
00318 GWEN_Buffer_Rewind(buf);
00319 if (GWEN_Buffer_InsertRoom(buf, diff)) {
00320 DBG_ERROR(GWEN_LOGDOMAIN, "Could not insert room for %d bytes", diff);
00321 return GWEN_ERROR_GENERIC;
00322 }
00323
00324 p=GWEN_Buffer_GetStart(buf);
00325 *(p++)=0x00;
00326 *(p++)=0x02;
00327 GWEN_Crypt_Random(2, (uint8_t*)p, diff-3);
00328 for (i=0; i<diff-3; i++) {
00329 if (*p==0)
00330
00331 *p=0xff;
00332 p++;
00333 }
00334 *(p++)=0x00;
00335
00336 return 0;
00337 }
00338
00339
00340
00341 int GWEN_Padd__UnpaddWithPkcs1Bt1Or2(GWEN_BUFFER *buf) {
00342 char *p;
00343 uint32_t len;
00344 uint32_t paddBytes;
00345
00346 assert(buf);
00347 len=GWEN_Buffer_GetUsedBytes(buf);
00348 assert(len);
00349
00350 p=GWEN_Buffer_GetStart(buf);
00351 if (*p==0) {
00352 p++;
00353 len--;
00354 }
00355 if (len<11) {
00356 DBG_ERROR(GWEN_LOGDOMAIN, "Too few bytes left (%d)", len);
00357 return GWEN_ERROR_INVALID;
00358 }
00359
00360 if (*p!=0x01 && *p!=0x02) {
00361 DBG_ERROR(GWEN_LOGDOMAIN, "Unsupported block type %02x", *p);
00362 return GWEN_ERROR_INVALID;
00363 }
00364 p++; len--;
00365
00366
00367 paddBytes=0;
00368 while(*p!=0x00 && len) {
00369 p++; len--;
00370 paddBytes++;
00371 }
00372
00373 if (*p!=0x00) {
00374 DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding");
00375 return GWEN_ERROR_INVALID;
00376 }
00377 p++; len--;
00378
00379 if (paddBytes<8) {
00380
00381 DBG_ERROR(GWEN_LOGDOMAIN, "Bad padding (too few padding bytes)");
00382 return GWEN_ERROR_INVALID;
00383 }
00384
00385 GWEN_Buffer_Crop(buf, GWEN_Buffer_GetUsedBytes(buf)-len, len);
00386
00387 return 0;
00388 }
00389
00390
00391
00392 int GWEN_Padd_UnpaddWithPkcs1Bt1(GWEN_BUFFER *src){
00393 return GWEN_Padd__UnpaddWithPkcs1Bt1Or2(src);
00394 }
00395
00396
00397
00398 int GWEN_Padd_UnpaddWithPkcs1Bt2(GWEN_BUFFER *src){
00399 return GWEN_Padd__UnpaddWithPkcs1Bt1Or2(src);
00400 }
00401
00402
00403
00404 int GWEN_Padd_ApplyPaddAlgo(const GWEN_CRYPT_PADDALGO *a, GWEN_BUFFER *buf) {
00405 int rv;
00406 unsigned int diff;
00407 unsigned int bsize;
00408 unsigned int dstSize;
00409 unsigned int chunkSize;
00410 GWEN_CRYPT_PADDALGOID aid;
00411
00412 assert(a);
00413 assert(buf);
00414
00415 aid=GWEN_Crypt_PaddAlgo_GetId(a);
00416 if (aid==GWEN_Crypt_PaddAlgoId_None)
00417
00418 return 0;
00419
00420 chunkSize=GWEN_Crypt_PaddAlgo_GetPaddSize(a);
00421 if (chunkSize==0) {
00422 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid chunk size (0)");
00423 return GWEN_ERROR_INVALID;
00424 }
00425
00426 bsize=GWEN_Buffer_GetUsedBytes(buf);
00427 dstSize=bsize+(chunkSize-1);
00428 dstSize=(dstSize/chunkSize)*chunkSize;
00429 diff=dstSize-bsize;
00430
00431 DBG_INFO(GWEN_LOGDOMAIN, "Padding with algo \"%s\"",
00432 GWEN_Crypt_PaddAlgoId_toString(aid));
00433
00434 switch(aid) {
00435 case GWEN_Crypt_PaddAlgoId_None:
00436 rv=0;
00437 break;
00438
00439 case GWEN_Crypt_PaddAlgoId_Iso9796_1A4:
00440 if (dstSize>96) {
00441 DBG_ERROR(GWEN_LOGDOMAIN,
00442 "Padding size must be <=96 bytes (is %d)",
00443 dstSize);
00444 return GWEN_ERROR_INVALID;
00445 }
00446 rv=GWEN_Padd_PaddWithISO9796(buf);
00447 break;
00448
00449 case GWEN_Crypt_PaddAlgoId_Pkcs1_1:
00450 rv=GWEN_Padd_PaddWithPkcs1Bt1(buf, dstSize);
00451 break;
00452
00453 case GWEN_Crypt_PaddAlgoId_Pkcs1_2:
00454 rv=GWEN_Padd_PaddWithPkcs1Bt2(buf, dstSize);
00455 break;
00456
00457 case GWEN_Crypt_PaddAlgoId_LeftZero:
00458 rv=GWEN_Buffer_FillLeftWithBytes(buf, 0, diff);
00459 break;
00460
00461 case GWEN_Crypt_PaddAlgoId_RightZero:
00462 rv=GWEN_Buffer_FillWithBytes(buf, 0, diff);
00463 break;
00464
00465 case GWEN_Crypt_PaddAlgoId_AnsiX9_23:
00466 return GWEN_Padd_PaddWithAnsiX9_23(buf);
00467
00468 case GWEN_Crypt_PaddAlgoId_Iso9796_2:
00469 return GWEN_Padd_PaddWithIso9796_2(buf, dstSize);
00470
00471 case GWEN_Crypt_PaddAlgoId_Iso9796_1:
00472 default:
00473 DBG_INFO(GWEN_LOGDOMAIN, "Algo-Type %d (%s) not supported",
00474 aid, GWEN_Crypt_PaddAlgoId_toString(aid));
00475 return GWEN_ERROR_NOT_AVAILABLE;
00476 }
00477
00478 if (rv) {
00479 DBG_ERROR(GWEN_LOGDOMAIN, "Error padding with algo %d (%s)",
00480 aid, GWEN_Crypt_PaddAlgoId_toString(aid));
00481 return GWEN_ERROR_GENERIC;
00482 }
00483
00484 return rv;
00485 }
00486
00487
00488
00489 int GWEN_Padd_UnapplyPaddAlgo(const GWEN_CRYPT_PADDALGO *a, GWEN_BUFFER *buf){
00490 int rv;
00491 GWEN_CRYPT_PADDALGOID aid;
00492
00493 assert(a);
00494 assert(buf);
00495
00496 aid=GWEN_Crypt_PaddAlgo_GetId(a);
00497 DBG_INFO(GWEN_LOGDOMAIN, "Unpadding with algo \"%s\"",
00498 GWEN_Crypt_PaddAlgoId_toString(aid));
00499
00500 switch(aid) {
00501 case GWEN_Crypt_PaddAlgoId_None:
00502 rv=0;
00503 break;
00504
00505 case GWEN_Crypt_PaddAlgoId_Pkcs1_1:
00506 rv=GWEN_Padd_UnpaddWithPkcs1Bt1(buf);
00507 break;
00508
00509 case GWEN_Crypt_PaddAlgoId_Pkcs1_2:
00510 rv=GWEN_Padd_UnpaddWithPkcs1Bt2(buf);
00511 break;
00512
00513 case GWEN_Crypt_PaddAlgoId_AnsiX9_23:
00514 return GWEN_Padd_UnpaddWithAnsiX9_23(buf);
00515
00516 case GWEN_Crypt_PaddAlgoId_Iso9796_2:
00517 return GWEN_Padd_UnpaddWithIso9796_2(buf);
00518
00519 case GWEN_Crypt_PaddAlgoId_Iso9796_1:
00520 case GWEN_Crypt_PaddAlgoId_LeftZero:
00521 case GWEN_Crypt_PaddAlgoId_RightZero:
00522 case GWEN_Crypt_PaddAlgoId_Iso9796_1A4:
00523 default:
00524 DBG_INFO(GWEN_LOGDOMAIN, "Algo-Type %d (%s) not supported",
00525 aid, GWEN_Crypt_PaddAlgoId_toString(aid));
00526 return GWEN_ERROR_NOT_AVAILABLE;
00527 }
00528
00529 if (rv) {
00530 DBG_ERROR(GWEN_LOGDOMAIN, "Error padding with algo %d (%s)",
00531 aid, GWEN_Crypt_PaddAlgoId_toString(aid));
00532 return GWEN_ERROR_GENERIC;
00533 }
00534
00535 return rv;
00536 }
00537
00538
00539
00540
00541
00542