00001
00002
00003 const char *PC3CVSID = "$Id: PC3.cc 30949 2009-11-02 16:37:58Z ganis $";
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
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033
00034 #include "PC3.hh"
00035
00036 #define kMASKLAST (0x80000000)
00037 #define kMASKFIRST (0x00000001)
00038
00039 namespace PC3 {
00040
00041
00042
00043
00044
00045
00046 static unsigned int rotl(unsigned int n, unsigned int nl)
00047 {
00048
00049 unsigned int i = 0;
00050
00051 for ( i = 0; i < nl; i++) {
00052 bool bset = ((n & kMASKLAST) == kMASKLAST) ? 1 : 0;
00053 n <<= 1;
00054 if (bset)
00055 n |= kMASKFIRST;
00056 else
00057 n &= ~kMASKFIRST;
00058 }
00059 return n;
00060 }
00061
00062
00063 static unsigned long stream(unsigned int &r1, unsigned long b1)
00064 {
00065 static unsigned long a1 = 0x015a4e35;
00066
00067 b1 = ( b1 * a1 ) + 1;
00068 r1 = rotl( (r1 + (( b1 >> 16 ) & 0x7fff)), (r1%16) );
00069
00070 return b1;
00071 }
00072
00073
00074 static uchar pc3stream(uchar byte, unsigned long *b1,
00075 unsigned int &r1, unsigned int key)
00076 {
00077 unsigned short d;
00078
00079 unsigned long i = 0;
00080 for ( ; i<=(key-1); i++)
00081 b1[i] = stream(r1,b1[i]);
00082
00083 d = byte;
00084 byte = byte^(r1 & 255);
00085 r1 += d;
00086 b1[key-1] = b1[key-1] + d;
00087
00088 return byte;
00089 }
00090
00091
00092 unsigned int pc3init(unsigned int lngkey, uchar *code,
00093 unsigned long *b1, unsigned int &key)
00094 {
00095 unsigned int z,y,x,i;
00096 uchar tab[kPC3MAXRPWLEN],plain;
00097 div_t reste;
00098 unsigned int r1 = 0;
00099
00100 if (lngkey > kPC3MAXRPWLEN) lngkey = kPC3MAXRPWLEN;
00101 if (lngkey < 1) {
00102 lngkey = 1;
00103 strcpy((char *)code,"a");
00104 }
00105
00106 x = lngkey;
00107
00108 for ( i = 0; i < x; i++) {
00109 tab[i] = code[i];
00110 }
00111
00112 reste = div(lngkey,2);
00113 key = reste.quot;
00114 if (reste.rem != 0) key += 1;
00115
00116 y=0;
00117 for ( z = 0; z <= (key-1); z++) {
00118 if ( (z == (key-1)) && (reste.rem != 0) ) {
00119 b1[z]=code[y]*256;
00120 } else {
00121 b1[z] = (code[y]*256) + code[y+1];
00122 y = y+1;
00123 }
00124 y = y+1;
00125 }
00126
00127 unsigned long ii = 0;
00128 for ( ; ii <= (key-1); ii++) {
00129 for( z = 0; z <= ii; z++)
00130 b1[ii] = stream(r1,b1[ii]);
00131 }
00132
00133 for ( i = 0; i < x; i++) {
00134 plain = pc3stream(tab[i],b1,r1,key);
00135 tab[i] = tab[i]^plain;
00136 }
00137 i=i-1;
00138 for ( z = 1; z <= ((x+1)*10); z++) {
00139 plain = pc3stream(tab[i],b1,r1,key);
00140 tab[i] = tab[i]^plain;
00141 i++;
00142 if (i >= x) i = 0;
00143 }
00144
00145 reste = div(lngkey,2);
00146 key = reste.quot;
00147 if (reste.rem != 0) key += 1;
00148
00149 for ( z = 0; z < 128; z++) {
00150 b1[z]=0;
00151 }
00152
00153 y=0;
00154 for (z=0;z<=(key-1);z++)
00155 {
00156 if ( (z==(key-1))&&(reste.rem!=0) )
00157 {
00158 b1[z]=tab[y]*256;
00159 }
00160 else
00161 {
00162 b1[z]=(tab[y]*256)+tab[y+1];
00163 y=y+1;
00164 }
00165 y=y+1;
00166 }
00167
00168 for (z=0;z<x;z++)
00169 {
00170 code[z]=0;
00171 tab[z]=0;
00172 }
00173
00174 r1 = 0;
00175 for ( ii = 0; ii <= (key-1); ii++) {
00176 for ( z = 0; z <= ii; z++)
00177 b1[ii] = stream(r1,b1[ii]);
00178 }
00179 return r1;
00180 }
00181
00182
00183 static void funA(uchar *x, uchar *y, int o)
00184 {
00185 int d = 0;
00186 int v = kPC3SLEN;
00187 for( ; v--;) {
00188 d += x[v]+y[v]*o;
00189 x[v] = d;
00190 d = d>>8;
00191 }
00192 }
00193
00194
00195 static void funS(uchar *x, uchar *m)
00196 {
00197 int v = 0;
00198 for( ; (v < kPC3SLEN-1) && (x[v] == m[v]);)
00199 v++;
00200 if (x[v] >= m[v])
00201 funA(x,m,-1);
00202 }
00203
00204
00205 static void funR(uchar *x)
00206 {
00207 int d = 0;
00208 int v = 0;
00209 for ( ; v < kPC3SLEN; ) {
00210 d |= x[v];
00211 x[v++] = d/2;
00212 d = (d & 1) << 8;
00213 }
00214 }
00215
00216
00217 static void funM(uchar *x, uchar *y, uchar *m)
00218 {
00219 uchar X[1024],Y[1024];
00220
00221 memcpy(X,x,kPC3SLEN);
00222 memcpy(Y,y,kPC3SLEN);
00223 memset(x,0,kPC3SLEN);
00224
00225 int z = kPC3SLEN*8;
00226 for( ; z--; ) {
00227 if (X[kPC3SLEN-1] & 0x1) {
00228 funA(x,Y,1);
00229 funS(x,m);
00230 }
00231 funR(X);
00232 funA(Y,Y,1);
00233 funS(Y,m);
00234 }
00235 }
00236
00237
00238 static int createkey(uchar *rpwd, unsigned int lrpw, uchar *priv)
00239 {
00240
00241 uchar inite[64]={0x94,0x05,0xF4,0x50,0x81,0x79,0x38,0xAB,
00242 0x39,0x81,0x05,0x8C,0xCD,0xE8,0x04,0xDF,
00243 0x6E,0x7C,0xAB,0x07,0x63,0xFE,0x4A,0xD7,
00244 0x47,0x05,0x9D,0x2D,0x73,0xA9,0x38,0xBA,
00245 0xB5,0x48,0x39,0x10,0x0A,0xD8,0xD1,0x5A,
00246 0x9D,0x64,0x74,0xF8,0x8B,0xC5,0x3E,0x9A,
00247 0xBF,0x27,0x55,0x9C,0x0C,0x6A,0x7E,0xD8,
00248 0xA4,0x78,0x96,0x4C,0x96,0xBB,0x3A,0xC3};
00249 unsigned long b1[128] = {0};
00250 uchar code[kPC3MAXRPWLEN];
00251
00252
00253 if (!rpwd || (lrpw <= 0) || !priv) {
00254 return -1;
00255 }
00256
00257
00258 lrpw = (lrpw > (kPC3MAXRPWLEN-2)) ? (kPC3MAXRPWLEN-2) : lrpw;
00259 unsigned int i = 0;
00260 for ( ; i < lrpw; i++)
00261 code[i] = rpwd[i];
00262
00263
00264 code[lrpw] = '\0';
00265 code[lrpw+1] = '\0';
00266
00267 unsigned int key = 0;
00268 unsigned int r1 = pc3init(lrpw+2,code,b1,key);
00269
00270 for ( i = 1; i < kPC3SLEN; i++)
00271 priv[i-1] = pc3stream(inite[i-1],b1,r1,key);
00272
00273
00274 return 0;
00275 }
00276
00277 }
00278
00279
00280
00281
00282
00283 int PC3InitDiPuk(uchar *rpwd, unsigned int lrpw, uchar *pub, uchar *priv)
00284 {
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 if (!rpwd || (lrpw <= 0) || !pub || !priv) {
00304 return -1;
00305 }
00306
00307 uchar prime512[64] = {
00308 0xF5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
00309 0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
00310 0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
00311 0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
00312 0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
00313 0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
00314 0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
00315 0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x2A, 0x05, 0x5F
00316 };
00317 uchar e[kPC3SLEN+1] = {0};
00318 uchar m[kPC3SLEN+1] = {0};
00319 uchar g[kPC3SLEN+1] = {0};
00320
00321 g[kPC3SLEN-1] = 3;
00322 unsigned int pr = 1;
00323 for ( ; pr < kPC3SLEN; pr++)
00324 m[pr] = prime512[pr-1];
00325
00326 if (PC3::createkey(rpwd,lrpw,priv) < 0)
00327 return -1;
00328
00329 for ( pr = 1; pr < kPC3SLEN; pr++)
00330 e[pr] = priv[pr-1];
00331
00332 uchar b[kPC3SLEN] = {0};
00333 b[kPC3SLEN-1] = 1;
00334 int n = kPC3SLEN*8;
00335 for( ; n--; ) {
00336 if ((e[kPC3SLEN-1] & 0x1))
00337 PC3::funM(b,g,m);
00338 PC3::funM(g,g,m);
00339 PC3::funR(e);
00340 }
00341
00342
00343 int i = 1;
00344 for ( ; i < kPC3SLEN; i++)
00345 pub[i-1] = b[i];
00346 pub[kPC3SLEN-1] = 0;
00347
00348
00349 return 0;
00350 }
00351
00352
00353 int PC3DiPukExp(uchar *pub, uchar *priv, uchar *key)
00354 {
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 if (!key || !pub || !priv) {
00373 return -1;
00374 }
00375
00376 uchar prime512[64] = {
00377 0xF5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40,
00378 0x18, 0x11, 0x8D, 0x7C, 0x84, 0xA7, 0x0A, 0x72,
00379 0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
00380 0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB,
00381 0xD0, 0x0A, 0x50, 0x9B, 0x02, 0x46, 0xD3, 0x08,
00382 0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
00383 0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB,
00384 0xA2, 0x5E, 0xC3, 0x55, 0xE9, 0x2A, 0x05, 0x5F
00385 };
00386 uchar e[kPC3SLEN+1] = {0};
00387 uchar m[kPC3SLEN+1] = {0};
00388 uchar g[kPC3SLEN+1] = {0};
00389 uchar b[kPC3SLEN+1] = {0};
00390
00391 unsigned int pr = 1;
00392 for ( ; pr < kPC3SLEN; pr++) {
00393 g[pr] = pub[pr-1];
00394 e[pr] = priv[pr-1];
00395 m[pr] = prime512[pr-1];
00396 }
00397 b[kPC3SLEN-1] = 1;
00398 int n = kPC3SLEN*8;
00399 for ( ; n--;) {
00400 if ((e[kPC3SLEN-1] & 0x1))
00401 PC3::funM(b,g,m);
00402 PC3::funM(g,g,m);
00403 PC3::funR(e);
00404 }
00405
00406
00407 int i = 0;
00408 for ( ; i < kPC3KEYLEN; i++)
00409 key[i] = 0;
00410 for ( i = 1; i < kPC3SLEN; i++) {
00411 key[i%kPC3KEYLEN] = key[i%kPC3KEYLEN]^b[i];
00412 }
00413
00414
00415 return 0;
00416 }