00001
00018 #include "includes.h"
00019
00020 #include "common.h"
00021 #include "crypto.h"
00022 #include "des_i.h"
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00045 #define ROLc(x, y) \
00046 ((((unsigned long) (x) << (unsigned long) ((y) & 31)) | \
00047 (((unsigned long) (x) & 0xFFFFFFFFUL) >> \
00048 (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
00049 #define RORc(x, y) \
00050 (((((unsigned long) (x) & 0xFFFFFFFFUL) >> \
00051 (unsigned long) ((y) & 31)) | \
00052 ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & \
00053 0xFFFFFFFFUL)
00054
00055
00056 static const u32 bytebit[8] =
00057 {
00058 0200, 0100, 040, 020, 010, 04, 02, 01
00059 };
00060
00061 static const u32 bigbyte[24] =
00062 {
00063 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL,
00064 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL,
00065 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL,
00066 0x800UL, 0x400UL, 0x200UL, 0x100UL,
00067 0x80UL, 0x40UL, 0x20UL, 0x10UL,
00068 0x8UL, 0x4UL, 0x2UL, 0x1L
00069 };
00070
00071
00072
00073 static const u8 pc1[56] = {
00074 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
00075 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
00076 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
00077 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
00078 };
00079
00080 static const u8 totrot[16] = {
00081 1, 2, 4, 6,
00082 8, 10, 12, 14,
00083 15, 17, 19, 21,
00084 23, 25, 27, 28
00085 };
00086
00087 static const u8 pc2[48] = {
00088 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
00089 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
00090 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
00091 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
00092 };
00093
00094
00095 static const u32 SP1[64] =
00096 {
00097 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL,
00098 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL,
00099 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL,
00100 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL,
00101 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL,
00102 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL,
00103 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL,
00104 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL,
00105 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL,
00106 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL,
00107 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL,
00108 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL,
00109 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL,
00110 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL,
00111 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL,
00112 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL
00113 };
00114
00115 static const u32 SP2[64] =
00116 {
00117 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL,
00118 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL,
00119 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL,
00120 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL,
00121 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL,
00122 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL,
00123 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL,
00124 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL,
00125 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL,
00126 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL,
00127 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL,
00128 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL,
00129 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL,
00130 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL,
00131 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL,
00132 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL
00133 };
00134
00135 static const u32 SP3[64] =
00136 {
00137 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL,
00138 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL,
00139 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL,
00140 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL,
00141 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL,
00142 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL,
00143 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL,
00144 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL,
00145 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL,
00146 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL,
00147 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL,
00148 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL,
00149 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL,
00150 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL,
00151 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL,
00152 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL
00153 };
00154
00155 static const u32 SP4[64] =
00156 {
00157 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
00158 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL,
00159 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL,
00160 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL,
00161 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL,
00162 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL,
00163 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL,
00164 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL,
00165 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL,
00166 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL,
00167 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL,
00168 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
00169 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL,
00170 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL,
00171 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL,
00172 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL
00173 };
00174
00175 static const u32 SP5[64] =
00176 {
00177 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL,
00178 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL,
00179 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL,
00180 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL,
00181 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL,
00182 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL,
00183 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL,
00184 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL,
00185 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL,
00186 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL,
00187 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL,
00188 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL,
00189 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL,
00190 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL,
00191 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL,
00192 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL
00193 };
00194
00195 static const u32 SP6[64] =
00196 {
00197 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL,
00198 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL,
00199 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL,
00200 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
00201 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL,
00202 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL,
00203 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL,
00204 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL,
00205 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL,
00206 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL,
00207 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
00208 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL,
00209 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL,
00210 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL,
00211 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL,
00212 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL
00213 };
00214
00215 static const u32 SP7[64] =
00216 {
00217 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL,
00218 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL,
00219 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL,
00220 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL,
00221 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL,
00222 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL,
00223 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL,
00224 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL,
00225 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL,
00226 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL,
00227 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL,
00228 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL,
00229 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL,
00230 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL,
00231 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL,
00232 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL
00233 };
00234
00235 static const u32 SP8[64] =
00236 {
00237 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL,
00238 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL,
00239 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL,
00240 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL,
00241 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL,
00242 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL,
00243 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL,
00244 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL,
00245 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL,
00246 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL,
00247 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL,
00248 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL,
00249 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL,
00250 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL,
00251 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL,
00252 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL
00253 };
00254
00255
00256 static void cookey(const u32 *raw1, u32 *keyout)
00257 {
00258 u32 *cook;
00259 const u32 *raw0;
00260 u32 dough[32];
00261 int i;
00262
00263 cook = dough;
00264 for (i = 0; i < 16; i++, raw1++) {
00265 raw0 = raw1++;
00266 *cook = (*raw0 & 0x00fc0000L) << 6;
00267 *cook |= (*raw0 & 0x00000fc0L) << 10;
00268 *cook |= (*raw1 & 0x00fc0000L) >> 10;
00269 *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
00270 *cook = (*raw0 & 0x0003f000L) << 12;
00271 *cook |= (*raw0 & 0x0000003fL) << 16;
00272 *cook |= (*raw1 & 0x0003f000L) >> 4;
00273 *cook++ |= (*raw1 & 0x0000003fL);
00274 }
00275
00276 os_memcpy(keyout, dough, sizeof(dough));
00277 }
00278
00279
00280 static void deskey(const u8 *key, int decrypt, u32 *keyout)
00281 {
00282 u32 i, j, l, m, n, kn[32];
00283 u8 pc1m[56], pcr[56];
00284
00285 for (j = 0; j < 56; j++) {
00286 l = (u32) pc1[j];
00287 m = l & 7;
00288 pc1m[j] = (u8)
00289 ((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0);
00290 }
00291
00292 for (i = 0; i < 16; i++) {
00293 if (decrypt)
00294 m = (15 - i) << 1;
00295 else
00296 m = i << 1;
00297 n = m + 1;
00298 kn[m] = kn[n] = 0L;
00299 for (j = 0; j < 28; j++) {
00300 l = j + (u32) totrot[i];
00301 if (l < 28)
00302 pcr[j] = pc1m[l];
00303 else
00304 pcr[j] = pc1m[l - 28];
00305 }
00306 for (; j < 56; j++) {
00307 l = j + (u32) totrot[i];
00308 if (l < 56)
00309 pcr[j] = pc1m[l];
00310 else
00311 pcr[j] = pc1m[l - 28];
00312 }
00313 for (j = 0; j < 24; j++) {
00314 if ((int) pcr[(int) pc2[j]] != 0)
00315 kn[m] |= bigbyte[j];
00316 if ((int) pcr[(int) pc2[j + 24]] != 0)
00317 kn[n] |= bigbyte[j];
00318 }
00319 }
00320
00321 cookey(kn, keyout);
00322 }
00323
00324
00325 static void desfunc(u32 *block, const u32 *keys)
00326 {
00327 u32 work, right, leftt;
00328 int cur_round;
00329
00330 leftt = block[0];
00331 right = block[1];
00332
00333 work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
00334 right ^= work;
00335 leftt ^= (work << 4);
00336
00337 work = ((leftt >> 16) ^ right) & 0x0000ffffL;
00338 right ^= work;
00339 leftt ^= (work << 16);
00340
00341 work = ((right >> 2) ^ leftt) & 0x33333333L;
00342 leftt ^= work;
00343 right ^= (work << 2);
00344
00345 work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
00346 leftt ^= work;
00347 right ^= (work << 8);
00348
00349 right = ROLc(right, 1);
00350 work = (leftt ^ right) & 0xaaaaaaaaL;
00351
00352 leftt ^= work;
00353 right ^= work;
00354 leftt = ROLc(leftt, 1);
00355
00356 for (cur_round = 0; cur_round < 8; cur_round++) {
00357 work = RORc(right, 4) ^ *keys++;
00358 leftt ^= SP7[work & 0x3fL]
00359 ^ SP5[(work >> 8) & 0x3fL]
00360 ^ SP3[(work >> 16) & 0x3fL]
00361 ^ SP1[(work >> 24) & 0x3fL];
00362 work = right ^ *keys++;
00363 leftt ^= SP8[ work & 0x3fL]
00364 ^ SP6[(work >> 8) & 0x3fL]
00365 ^ SP4[(work >> 16) & 0x3fL]
00366 ^ SP2[(work >> 24) & 0x3fL];
00367
00368 work = RORc(leftt, 4) ^ *keys++;
00369 right ^= SP7[ work & 0x3fL]
00370 ^ SP5[(work >> 8) & 0x3fL]
00371 ^ SP3[(work >> 16) & 0x3fL]
00372 ^ SP1[(work >> 24) & 0x3fL];
00373 work = leftt ^ *keys++;
00374 right ^= SP8[ work & 0x3fL]
00375 ^ SP6[(work >> 8) & 0x3fL]
00376 ^ SP4[(work >> 16) & 0x3fL]
00377 ^ SP2[(work >> 24) & 0x3fL];
00378 }
00379
00380 right = RORc(right, 1);
00381 work = (leftt ^ right) & 0xaaaaaaaaL;
00382 leftt ^= work;
00383 right ^= work;
00384 leftt = RORc(leftt, 1);
00385 work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
00386 right ^= work;
00387 leftt ^= (work << 8);
00388
00389 work = ((leftt >> 2) ^ right) & 0x33333333L;
00390 right ^= work;
00391 leftt ^= (work << 2);
00392 work = ((right >> 16) ^ leftt) & 0x0000ffffL;
00393 leftt ^= work;
00394 right ^= (work << 16);
00395 work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
00396 leftt ^= work;
00397 right ^= (work << 4);
00398
00399 block[0] = right;
00400 block[1] = leftt;
00401 }
00402
00403
00404
00405
00406 void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
00407 {
00408 u8 pkey[8], next, tmp;
00409 int i;
00410 u32 ek[32], work[2];
00411
00412
00413 next = 0;
00414 for (i = 0; i < 7; i++) {
00415 tmp = key[i];
00416 pkey[i] = (tmp >> i) | next | 1;
00417 next = tmp << (7 - i);
00418 }
00419 pkey[i] = next | 1;
00420
00421 deskey(pkey, 0, ek);
00422
00423 work[0] = WPA_GET_BE32(clear);
00424 work[1] = WPA_GET_BE32(clear + 4);
00425 desfunc(work, ek);
00426 WPA_PUT_BE32(cypher, work[0]);
00427 WPA_PUT_BE32(cypher + 4, work[1]);
00428
00429 os_memset(pkey, 0, sizeof(pkey));
00430 os_memset(ek, 0, sizeof(ek));
00431 }
00432
00433
00434 void des_key_setup(const u8 *key, u32 *ek, u32 *dk)
00435 {
00436 deskey(key, 0, ek);
00437 deskey(key, 1, dk);
00438 }
00439
00440
00441 void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt)
00442 {
00443 u32 work[2];
00444 work[0] = WPA_GET_BE32(plain);
00445 work[1] = WPA_GET_BE32(plain + 4);
00446 desfunc(work, ek);
00447 WPA_PUT_BE32(crypt, work[0]);
00448 WPA_PUT_BE32(crypt + 4, work[1]);
00449 }
00450
00451
00452 void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain)
00453 {
00454 u32 work[2];
00455 work[0] = WPA_GET_BE32(crypt);
00456 work[1] = WPA_GET_BE32(crypt + 4);
00457 desfunc(work, dk);
00458 WPA_PUT_BE32(plain, work[0]);
00459 WPA_PUT_BE32(plain + 4, work[1]);
00460 }
00461
00462
00463 void des3_key_setup(const u8 *key, struct des3_key_s *dkey)
00464 {
00465 deskey(key, 0, dkey->ek[0]);
00466 deskey(key + 8, 1, dkey->ek[1]);
00467 deskey(key + 16, 0, dkey->ek[2]);
00468
00469 deskey(key, 1, dkey->dk[2]);
00470 deskey(key + 8, 0, dkey->dk[1]);
00471 deskey(key + 16, 1, dkey->dk[0]);
00472 }
00473
00474
00475 void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt)
00476 {
00477 u32 work[2];
00478
00479 work[0] = WPA_GET_BE32(plain);
00480 work[1] = WPA_GET_BE32(plain + 4);
00481 desfunc(work, key->ek[0]);
00482 desfunc(work, key->ek[1]);
00483 desfunc(work, key->ek[2]);
00484 WPA_PUT_BE32(crypt, work[0]);
00485 WPA_PUT_BE32(crypt + 4, work[1]);
00486 }
00487
00488
00489 void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain)
00490 {
00491 u32 work[2];
00492
00493 work[0] = WPA_GET_BE32(crypt);
00494 work[1] = WPA_GET_BE32(crypt + 4);
00495 desfunc(work, key->dk[0]);
00496 desfunc(work, key->dk[1]);
00497 desfunc(work, key->dk[2]);
00498 WPA_PUT_BE32(plain, work[0]);
00499 WPA_PUT_BE32(plain + 4, work[1]);
00500 }
00501