Develop and Download Open Source Software

Browse Subversion Repository

Contents of /branches/mty-makai/mty.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 163 - (show annotations) (download) (as text)
Fri Jun 1 13:48:31 2007 UTC (16 years, 10 months ago) by notanpe
File MIME type: text/x-csrc
File size: 40612 byte(s)
セルフサービスモードへの一歩
1 /***********************************************************************
2 *
3 * file: mty.c
4 *
5 * まあ、待て屋。
6 *
7 * $Id$
8 *
9 */
10
11 #include <assert.h>
12 #include <ctype.h>
13 #include <errno.h>
14 #include <limits.h>
15 #include <stdarg.h>
16 #include <stddef.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <time.h>
21 #include <sys/types.h>
22
23 #if defined(WIN32)
24
25 #include <windows.h>
26 #include <process.h>
27 #include <sys/timeb.h>
28
29 #elif defined(__GNUC__)
30
31 #include <sys/time.h>
32
33 #endif
34
35 #include "config.h"
36 #include "cp932.h"
37 #include "crypt64.h"
38 #include "desconst.h"
39 #include "expr_parse.h"
40 #include "scoreboard.h"
41 #include "synth.h"
42 #include "tr64.h"
43 #include "translate.h"
44 #include "util.h"
45 #include "wdict.h"
46
47 #if USE_DT
48 #include "dt4.h"
49 #endif
50
51 /* 鍵クラス */
52 static
53 struct
54 {
55 unsigned short map[256];
56 } kcls[8 + 8];
57
58
59 /* 拡張鍵クラス */
60 #define KCLS_DT0 64
61 #define KCLS_DT1 128
62 #define KCLS_K2 256
63
64 #if USE_DT
65 /* 鍵キメ用辞書インデクス */
66 struct DT *kd[8 + 8];
67
68 /* 辞書インデクス */
69 struct DT *dtidx[0x100 + 1];
70 #endif
71
72 /* 指定されたクラスと入っているキーから、classify を行う */
73 void
74 key_make_map(uint8_t *key, int n)
75 {
76 int i, j;
77 unsigned c = kcls[n].map[key[n]];
78
79 #if USE_DT
80 if (3 <= n && n < 7 && kd[n - 3])
81 {
82 /* 辞書のケツの文字。後ろにナニヤラキャラクタが来る */
83 c = kd[n - 3]->c[0];
84 if ((0x81 <= c && c <= 0x9F)
85 || (0xE0 <= c && c <= 0xFC))
86 c = KCLS_K2;
87 else
88 c = (cp932[256 * key[n]]
89 | cp932[256 * (key[n] ^ 0x80)]);
90 #if DEBUG>=1
91 printf("*n=%d, key=%02X, cls=%04X\n",
92 n,
93 key[n],
94 c);
95 #endif
96 }
97 else if (2 <= n && n < 6 && kd[n - 2])
98 {
99 return;
100 }
101 else if (1 <= n && n < 5 && kd[n - 1])
102 {
103 return;
104 }
105 else if (1 <= n && n < 5 && !kd[n - 1]
106 //&& (c & KCLS_K2)
107 && (c & KCLS_DT1))
108 {
109 /* 漢字2文字を拾っていきまつ */
110 #if DEBUG>=1
111 printf("(%d)%02X %02X(%02X:%02X:%02X:%02X)\n",
112 n, key[n - 1], key[n],
113 cp932[(256 * key[n - 1] + key[n])],
114 cp932[(256 * key[n - 1] + key[n]) ^ 0x0080],
115 cp932[(256 * key[n - 1] + key[n]) ^ 0x8000],
116 cp932[(256 * key[n - 1] + key[n]) ^ 0x8080]);
117 #endif
118 if (n != 1 && n != 2
119 && (cp932[(256 * key[n - 1] + key[n]) ^ 0x0080] & KCLS_DT1))
120 key[n] ^= 0x80;
121 else if (n != 2 && n != 3
122 && (cp932[(256 * key[n - 1] + key[n]) ^ 0x8000] & KCLS_DT1))
123 key[n - 1] ^= 0x80;
124 else if (n > 3 && (cp932[(256 * key[n - 1] + key[n]) ^ 0x8080] & KCLS_DT1))
125 key[n - 1] ^= 0x80, key[n] ^= 0x80;
126 if (cp932[256 * key[n - 1] + key[n]] & KCLS_DT1)
127 {
128 for (kd[n - 1] = dtidx[key[n - 1]];
129 kd[n - 1]->c[1] != key[n];
130 kd[n - 1]++)
131 assert(kd[n - 1]->c[0] == key[n - 1]);
132 #if DEBUG>=1
133 printf("(%02X%02X:%02X%02X)%c%c%c%c\n",
134 kd[n - 1]->c[0],
135 kd[n - 1]->c[1],
136 kd[n - 1]->c[2],
137 kd[n - 1]->c[3],
138 kd[n - 1]->c[0],
139 kd[n - 1]->c[1],
140 kd[n - 1]->c[2],
141 kd[n - 1]->c[3]);
142 #endif
143 return;
144 }
145 }
146 else if (n < 4 && (c & KCLS_DT0) && kd[n] == NULL)
147 {
148 /* カタカナ埋め込みいきます */
149 assert(kd[n] == NULL);
150 #if DEBUG>=1
151 printf("n=%d, key=%02X\n", n, key[n]);
152 #endif
153 kd[n] = dtidx[key[n]];
154 if (!kd[n]
155 && !(n == 1 || n == 2)
156 && dtidx[key[n] ^ 0x80])
157 {
158 key[n] ^= 0x80;
159 kd[n] = dtidx[key[n]];
160 }
161 if (kd[n])
162 return;
163 }
164 else
165 {
166 kd[n] = NULL;
167 }
168 #endif
169
170 /* 最後の部分は class map を生成する必要ナシ */
171 if (n >= 6)
172 return;
173
174 for (i = 0; i < 256; i++)
175 {
176 unsigned bm = 0;
177 #if 1
178 if (c & KCLS_K1)
179 {
180 if (cp932[256 * key[n] + i] & KCLS_K1)
181 bm |= KCLS_K2 | (cp932[256 * key[n] + i] & KCLS_DT1);
182 if (cp932[256 * (key[n] ^ 0x80) + i] & KCLS_K1)
183 bm |= KCLS_K2 | (cp932[256 * (key[n] ^ 0x80) + i] & KCLS_DT1);
184 #if 0
185 bm |= ((cp932[256 * key[n] + i] & KCLS_K1)
186 || (cp932[256 * (key[n] ^ 0x80) + i] & KCLS_K1)
187 ? KCLS_K2 : 0);
188 #endif
189 }
190 if (c & (KCLS_AN | KCLS_KA | KCLS_K2))
191 for (j = 0; j < 256; j++)
192 {
193 bm |= cp932[256 * i + j] & (KCLS_AN | KCLS_KA | KCLS_K1
194 | KCLS_DT0);
195 #if 0
196 if (j >= 127 && !(n == 0 || n == 1))
197 break;
198 #endif
199 }
200 kcls[n + 1].map[i] = bm;
201 #endif
202 if (i >= 128 && !(n == 0 || n == 1))
203 kcls[n + 1].map[i - 128] |= kcls[n + 1].map[i];
204 }
205
206 if (n < 6)
207 kcls[n + 1].map[0x00] = kcls[n + 1].map[0x80] = 0;
208 if (n == 6)
209 kcls[7].map[0x00] |= KCLS_AN;
210 }
211
212 #if USE_DT
213 unsigned
214 dt_get(int kdn,
215 int xn,
216 int n,
217 int ch)
218 {
219 int i;
220 #if DEBUG>=1
221 printf("*dt_get(%d)%c%c%c%c(%02X%02X:%02X%02X)->ch=%d",
222 n,
223 kd[kdn]->c[0], kd[kdn]->c[1], kd[kdn]->c[2], kd[kdn]->c[3],
224 kd[kdn]->c[0], kd[kdn]->c[1], kd[kdn]->c[2], kd[kdn]->c[3],
225 ch);
226 #endif
227 /* まずは数える */
228 for (i = 0;
229 kd[kdn][i].c[xn] == kd[kdn]->c[xn];
230 i++)
231 ;
232 assert(i > 0);
233 kd[kdn] += ch % i;
234 #if DEBUG>=1
235 printf("/%d\n dt_get: %c%c%c%c(%02X%02X:%02X%02X)->ch=%d\n",
236 i,
237 kd[kdn]->c[0], kd[kdn]->c[1], kd[kdn]->c[2], kd[kdn]->c[3],
238 kd[kdn]->c[0], kd[kdn]->c[1], kd[kdn]->c[2], kd[kdn]->c[3],
239 ch);
240 #endif
241 return kd[kdn]->c[n];
242 }
243 #endif
244
245 /* マップから文字を拾ってセット */
246 unsigned
247 key_set(int n, unsigned ch)
248 {
249 int cnt = 0, i;
250
251 #if USE_DT
252 if (3 <= n && n < 7 && kd[n - 3])
253 {
254 return dt_get(n - 3, 2, 3, ch);
255 return kd[n - 3]->c[3];
256 }
257 else if (2 <= n && n < 6 && kd[n - 2])
258 {
259 return dt_get(n - 2, 1, 2, ch);
260 return kd[n - 2]->c[2];
261 }
262 else if (1 <= n && n < 5 && kd[n - 1])
263 {
264 return dt_get(n - 1, 0, 1, ch);
265 return kd[n - 1]->c[1];
266 }
267 #endif
268
269 #if DEBUG>=3
270 if (cnt == 0)
271 {
272 printf("n=%d, ch=%d, (n-1)=%02X\n", n, ch, key[n - 1]);
273 int j;
274 for (i = 0; i < 16; i++)
275 {
276 printf("map[0x%02X] =", 16 * i);
277 for (j = 0; j < 16; j++)
278 printf(" %03X", kcls[n].map[16 * i + j]);
279 printf("\n");
280 }
281 }
282 #endif
283 for (i = 0; i < 256; i++)
284 {
285 if (kcls[n].map[i])
286 {
287 if (ch-- == 0)
288 return i;
289 cnt++;
290 }
291 if (n != 1 && n != 2 && i >= 127)
292 break;
293 }
294 /* 見つからなかったのでもいっぺん */
295 assert(cnt > 0);
296 ch %= cnt;
297 for (i = 0; i < 256; i++)
298 if (kcls[n].map[i])
299 {
300 if (ch-- == 0)
301 return i;
302 }
303 assert(!"not matched");
304 return 0;
305 }
306
307 /* bitwise key をセット */
308 static
309 void
310 key_set64(struct KEY *key64,
311 int n,
312 unsigned k,
313 unsigned vk,
314 unsigned sk)
315 {
316 int i, j;
317 if (!((vk | sk) & 0x7F))
318 return;
319
320 for (i = 0; i < 7; i++)
321 {
322 if (n == 7 && i < N_STRIDE) continue;
323 if (sk & (1 << i))
324 {
325 /* セット */
326 int o = tr_pc1[n][6 - i] - 1;
327 if (o < 28)
328 {
329 assert(o >= 0);
330 for (j = 0; j < N_ALU; j++)
331 key64->k[0][0][o].a[j]
332 = key64->k[0][1][o].a[j]
333 = -!!(k & (1 << i));
334 }
335 else
336 {
337 assert(o >= 28);
338 assert(o < 56);
339 for (j = 0; j < N_ALU; j++)
340 key64->k[1][0][o - 28].a[j]
341 = key64->k[1][1][o - 28].a[j]
342 = -!!(k & (1 << i));
343 }
344 }
345 else if (vk & (1 << i))
346 {
347 /* 反転 */
348 int o = tr_pc1[n][6 - i] - 1;
349 if (o < 28)
350 {
351 assert(o >= 0);
352 for (j = 0; j < N_ALU; j++)
353 key64->k[0][0][o].a[j]
354 = key64->k[0][1][o].a[j]
355 = ~key64->k[0][0][o].a[j];
356 }
357 else
358 {
359 assert(o >= 28);
360 assert(o < 56);
361 for (j = 0; j < N_ALU; j++)
362 key64->k[1][0][o - 28].a[j]
363 = key64->k[1][1][o - 28].a[j]
364 = ~key64->k[1][0][o - 28].a[j];
365 }
366 }
367 }
368 }
369
370 /* 指定されたクラスの開始値にリセット
371 直前の文字のクラスに縛られる */
372 int
373 key_reset(uint8_t *key, int n)
374 {
375 if (n >= 8)
376 return 1;
377 if (n == 7)
378 {
379 key[7] = 0;
380 return 1;
381 }
382
383 /* 0-2 文字目はランダムに決める
384 3 文字目以降は初期値に */
385 if (n >= KEY_SHUFFLE_POS)
386 key[n] = key_set(n, 0);
387 else
388 key[n] = key_set(n, rand());
389
390 #if DEBUG>=3
391 printf("key[%d]=%02X ncls=%04X\n", n, key[n], kcls[n].map[key[n]]);
392 #endif
393
394 /* セットされた文字を元に、次キャラの文字クラスを決める */
395 key_make_map(key, n);
396
397 return key_reset(key, n + 1);
398 }
399
400 /* 指定された鍵空間の中で、キーをひとつ進める
401 安全にインクリメントできた場合 true を返す */
402 static
403 int
404 key_inc(uint8_t *key, int n)
405 {
406 if (n >= 8)
407 return 0;
408 else if (n == 7)
409 {
410 /* 最後のバイト */
411 uint8_t o_k = (key[7] + (1 << N_STRIDE)) & 0x7F;
412 if (!o_k)
413 return 0; /* インクリメントできなかったときは次へ進めず待つ */
414
415 /* 進める */
416 key[7] = o_k;
417 return 1;
418 }
419 else if (key_inc(key, n + 1)
420 /*
421 && key_inc(n + 1)
422 && key_inc(n + 1)
423 && key_inc(n + 1)*/
424 )
425 return 1;
426
427 /* Salt はインクリメントしない約束にする */
428 if (n == 1 || n == 2)
429 return 1;
430
431 #if DEBUG>=3
432 printf("key_inc(n=%d,ck=%02X)\n", n, key[n]);
433 #endif
434
435 #if USE_DT
436 /* 辞書語はインクリメントしていい約束にする */
437 if (3 <= n && n < 7 && kd[n - 3])
438 {
439 if ((key[n - 3] & 0x7F) == ((kd[n - 3] + 1)->c[0] & 0x7F)
440 && (key[n - 2] & 0x7F) == ((kd[n - 3] + 1)->c[1] & 0x7F)
441 && (key[n - 1] & 0x7F) == ((kd[n - 3] + 1)->c[2] & 0x7F))
442 {
443 memcpy(&key[n - 3], &(++kd[n - 3])->c[0], 4);
444 #if DEBUG>=2
445 printf(">dt_get:%c%c%c%c(%02X%02X:%02X%02X)\n",
446 kd[n - 3]->c[0], kd[n - 3]->c[1], kd[n - 3]->c[2], kd[n - 3]->c[3],
447 kd[n - 3]->c[0], kd[n - 3]->c[1], kd[n - 3]->c[2], kd[n - 3]->c[3]);
448 #endif
449 return 1;
450 }
451 else
452 {
453 return 0;
454 }
455 }
456 else if (2 <= n && n < 6 && kd[n - 2])
457 {
458 if ((key[n - 2] & 0x7F) == ((kd[n - 2] + 1)->c[0] & 0x7F)
459 && (key[n - 1] & 0x7F) == ((kd[n - 2] + 1)->c[1] & 0x7F))
460 {
461 memcpy(&key[n - 2], &(++kd[n - 2])->c[0], 4);
462 #if DEBUG>=2
463 printf(">dt_get:%c%c%c%c(%02X%02X:%02X%02X)\n",
464 kd[n - 2]->c[0], kd[n - 2]->c[1], kd[n - 2]->c[2], kd[n - 2]->c[3],
465 kd[n - 2]->c[0], kd[n - 2]->c[1], kd[n - 2]->c[2], kd[n - 2]->c[3]);
466 #endif
467 return 1;
468 }
469 else
470 {
471 return 0;
472 }
473 if (kd[n - 2]->c[0] == key[n - 2])
474 return 1;
475 else
476 return 0;
477 }
478 else if (1 <= n && n < 5 && kd[n - 1])
479 {
480 unsigned c2 = kd[n - 1]->c[0];
481 if ((0x81 <= c2 && c2 <= 0x9F)
482 || (0xE0 <= c2 && c2 <= 0xFC))
483 {
484 kd[n - 1] = NULL;
485 #if 0
486 if (!(n == 1 && n == 2))
487 key[n] &= 0x7F;
488 if (!(n == 2 && n == 3))
489 key[n - 1] &= 0x7F;
490 #endif
491 key_make_map(n - 1);
492 }
493 else if ((key[n - 1] & 0x7F) == ((kd[n - 1] + 1)->c[0] & 0x7F))
494 {
495 memcpy(&key[n - 1], &(++kd[n - 1])->c[0], 4);
496 #if DEBUG>=2
497 printf(">dt_get:%c%c%c%c(%02X%02X:%02X%02X)\n",
498 kd[n - 1]->c[0], kd[n - 1]->c[1], kd[n - 1]->c[2], kd[n - 1]->c[3],
499 kd[n - 1]->c[0], kd[n - 1]->c[1], kd[n - 1]->c[2], kd[n - 1]->c[3]);
500 #endif
501 return 1;
502 }
503 else
504 {
505 return 0;
506 }
507 #if 0
508 if (kd[n - 1]->c[0] == key[n - 1])
509 return 1;
510 else
511 return 0;
512 #endif
513 }
514 else if (n < 4 && kd[n])
515 {
516 if (0 && kd[n]->c[0] == key[n])
517 return 1;
518 kd[n] = NULL;
519 #if 0
520 if (!(n == 1 || n == 2))
521 key[n] &= 0x7F;
522 #endif
523 }
524 #endif
525
526 /* 実際に増やしてみる */
527 assert(n >= 3);
528 for (;;)
529 {
530 if (n <= 3
531 && !(key[n] & 0x80)
532 && kcls[n].map[key[n] ^ 0x80] & (KCLS_DT0))
533 {
534 /* 半角カタカナの1バイト目 */
535 key[n] ^= 0x80;
536 }
537 else
538 {
539 key[n] = (key[n] & 0x7F) + 1;
540 if (key[n] >= 0x80)
541 {
542 key[n] = 0xFF; /* 次に突入させないため */
543 return 0;
544 }
545 }
546
547 if (kcls[n].map[key[n]])
548 {
549 key_make_map(key, n);
550 key_reset(key, n + 1);
551 return 1;
552 }
553 }
554 }
555
556 /* 鍵を完全にリセットする
557 Saltもセットし直す */
558 static
559 void
560 key_init(uint8_t *key)
561 {
562 int i, j;
563
564 #if USE_DT
565 /* 辞書を、インデクスを作りながらマップにはめこんで逝く
566 辞書はコード順昇順に並んでるものとする */
567 for (i = 0; i < dtcnt; i++)
568 {
569 unsigned c = dt[i].c[0];
570
571 assert(dt[i].c[0]
572 && dt[i].c[1]
573 && dt[i].c[2]
574 && dt[i].c[3]);
575
576 /* BSD 鯖でしにそうな文字は残念ながら除外 */
577 assert((dt[i].c[0] & 0x7F)
578 && (dt[i].c[1] & 0x7F)
579 && (dt[i].c[2] & 0x7F)
580 && (dt[i].c[3] & 0x7F));
581
582 /* インデクス */
583 if (!dtidx[c])
584 dtidx[c] = &dt[i];
585
586 if ((0x81 <= c && c <= 0x9F)
587 || (0xE0 <= c && c <= 0xFC))
588 {
589 /* 全角なので、2バイトきまった時点で立てる */
590 cp932[256 * c + dt[i].c[1]] |= KCLS_DT1;
591 }
592 else if (0xA1 <= c && c <= 0xDF)
593 {
594 /* 半角カナ */
595 for (j = 0; j < 256; j++)
596 cp932[256 * c + j] |= KCLS_DT0;
597 }
598 }
599 /* ケツ、ちうか番人 */
600 dtidx[0x100] = &dt[i];
601 #endif
602
603 key[8] = 0;
604
605 /* 初期マップを組む */
606 for (i = 0; i < 256; i++)
607 {
608 unsigned bm = 0;
609 kcls[0].map[i] = 0;
610 for (j = 0; j < 256; j++)
611 bm |= cp932[256 * i + j];
612 kcls[0].map[i] = bm & (KCLS_AN | KCLS_KA | KCLS_K1
613 | KCLS_DT0
614 );
615 if (i >= 128)
616 kcls[0].map[i - 128] |= kcls[0].map[i];
617 }
618
619 key_reset(key, 0);
620 }
621
622 /***************************************************************
623 *
624 * 固定キーの生成
625 *
626 * 一見 Big Endian に非対応のように見えるだろうが
627 * 随所でに散らばっている kludge により
628 * ALU_T が 64 ビットである限り、これで問題なく動く。
629 *
630 */
631
632 static
633 void
634 key_init_sk(struct KEY *key)
635 {
636 int i, j;
637 int o;
638 uint64_t m;
639
640 for (i = 5, m = 0xFFFFFFFF00000000ULL;
641 i >= 0;
642 m ^= (m >> (1 << --i)))
643 {
644 o = tr_pc1[7][6 - i] - 1;
645 #if DEBUG>=2
646 printf("%d:%d->%2d: %08X%08X\n",
647 N_Q, i, o,
648 (unsigned)(m >> 32),
649 (unsigned)m);
650 #endif
651 for (j = 0; j < N_Q; j++)
652 if (o < 28)
653 key->k[0][0][o ].q[j] = key->k[0][1][o ].q[j] = m;
654 else
655 key->k[1][0][o - 28].q[j] = key->k[1][1][o - 28].q[j] = m;
656 }
657 #if N_STRIDE==7
658 /* bit 6 は Little Endian として扱う */
659 o = 0;
660 assert(tr_pc1[7][0] - 1 == o);
661 assert(N_Q == 2);
662 key->k[0][0][o].q[0] = key->k[0][1][o].q[0] = 0x0000000000000000ULL;
663 key->k[0][0][o].q[1] = key->k[0][1][o].q[1] = 0xFFFFFFFFFFFFFFFFULL;
664 #endif
665 }
666
667 /***************************************************************
668 *
669 * Salt のセット
670 * オペランドのオフセットを書き換えて回ってるので注意
671 *
672 */
673
674 #if N_STRIDE == 6
675 #define C(c,i,j,o) (*(int8_t *)((c) + (loo - crypt64_pro) + los[6 * (i) + (j) + (o)]))
676 #elif N_STRIDE == 7
677 #define C(c,i,j,o) (*(int32_t *)((c) + (loo - crypt64_pro) + los[6 * (i) + (j) + (o)]))
678 #endif
679
680 void
681 set_salt(CODE_T *code,
682 uint8_t const *k)
683 {
684 int i, j;
685
686 for (i = 0; i < 2; i++)
687 {
688 unsigned s = k[1 + i] & 255;
689 if (s > 'z')
690 s = 0;
691 else if (s >= 'a')
692 s = s - 'a' + 2 + 10 + 26;
693 else if (s >= 'A')
694 s = s - 'A' + 2 + 10;
695 else if (s >= '.')
696 s = s - '.';
697 else
698 s = 0;
699
700 #if DEBUG>=1
701 printf("Salt %d:%3o\n", i, s & 63);
702 #endif
703 for (j = 0; j < 6; j++)
704 {
705 #if DEBUG>=2
706 //printf("Salt %d:%d %+3d:%+3d",
707 printf("Salt %d:%d %08lX:%08lX",
708 i, j,
709 C(code, i, j, 0),
710 C(code, i, j, 24));
711 #endif
712 if (s & (1 << j))
713 {
714 C(code, i, j, 0) = sizeof(WS_T) * (((4 * i + j + 15) & 31) - 16);
715 C(code, i, j, 24) = sizeof(WS_T) * (((4 * i + j - 1) & 31) - 16);
716 }
717 else
718 {
719 C(code, i, j, 0) = sizeof(WS_T) * (((4 * i + j - 1) & 31) - 16);
720 C(code, i, j, 24) = sizeof(WS_T) * (((4 * i + j + 15) & 31) - 16);
721 }
722 C(code, i, j, 12) = sizeof(WS_T) * (((4 * i + j + 7) & 31) - 16);
723 C(code, i, j, 36) = sizeof(WS_T) * (((4 * i + j + 23) & 31) - 16);
724 #if DEBUG>=2
725 //printf(" => %+3d:%+3d\n",
726 printf(" => %08lX:%08lX\n",
727 C(code, i, j, 0),
728 C(code, i, j, 24));
729 #endif
730 }
731 }
732 }
733
734 static
735 uint32_t
736 usec(void)
737 {
738 static uint32_t epoch = 0;
739 uint32_t sec, msec;
740
741 #if !defined(WIN32)
742 struct timeval tv;
743 gettimeofday(&tv, NULL);
744 sec = tv.tv_sec;
745 msec = tv.tv_usec / 10000;
746 #else
747 struct timeb tm;
748 ftime(&tm);
749 sec = tm.time;
750 msec = tm.millitm / 10;
751 #endif
752
753 if ( epoch == 0 ) {
754 epoch = sec;
755 }
756
757 return ((sec - epoch) * 100 + msec);
758 }
759
760 static
761 int
762 log_printf(FILE *ofp, char const *fmt, ...)
763 {
764 int r;
765 va_list ap;
766 va_start(ap, fmt);
767 vfprintf(stdout, fmt, ap);
768 r = vfprintf(ofp, fmt, ap);
769 va_end(ap);
770 if (r > 0)
771 return r;
772 perror("log_printf");
773 exit(errno);
774 }
775
776 /***************************************************************
777 *
778 * バッチ処理用パケット
779 *
780 */
781
782 struct PACKET_CRYPT64
783 {
784 union
785 {
786 uint8_t key[8]; /* 最後にセットしたキー */
787 SLICE pad;
788 } uk;
789 struct KEY key64;
790 struct PARAM param64; /* 最後尾の要素では、PARAM::hit[]が可変長 */
791 };
792
793 static
794 struct PACKET_CRYPT64 *
795 packet_create(int n, /* パケット数 */
796 int tn, /* 末尾要素にて必要なワーク数 */
797 uint8_t const *ini_key)
798 {
799 int i;
800 int siz;
801 void *p;
802 struct PACKET_CRYPT64 *pkts;
803 assert(IS_POWER2(sizeof(struct PACKET_CRYPT64)));
804 assert(n >= 1);
805
806 siz = (sizeof(WS_T) - 1
807 + (n - 1) * sizeof(struct PACKET_CRYPT64)
808 + offsetof(struct PACKET_CRYPT64, param64.hit[tn]));
809 p = calloc(siz, 1);
810 /* バンダリあわせ */
811 pkts = (struct PACKET_CRYPT64 *)(((intptr_t)p
812 + sizeof(WS_T) - 1)
813 & -sizeof(WS_T));
814 #if DEBUG>=1
815 fprintf(stderr,
816 "packet(n=%d,tn=%d) %d allocated; %p aligned to %p\n",
817 n, tn,
818 siz, p, pkts);
819 #endif
820
821 /* 内部の初期化
822 コピーして回るのは、厳密には
823 最終要素のケツを破ってしまうことになるので
824 どうせ速度も要求されないしベタコード */
825 for (i = 0; i < n; i++)
826 {
827 int j;
828
829 /* t[16] は、内部演算で使用する、all 1 が入っている */
830 memset(&pkts[i].param64.t[T_INV], -1, sizeof(SLICE));
831
832 /* 固定キーの生成 */
833 key_init_sk(&pkts[i].key64);
834
835 /* キースケジュールをここに押し込めておく
836 従来は crypt64.S 内で完結するように引いていた */
837 for (j = 0; j < 28; j++)
838 pkts[i].key64.ks[j].a[0] = sizeof(WS_T) * ks_ls[j];
839
840 /* 念のため、鍵をここで落ち着けておく(不要?) */
841 for (j = 0; j < 8; j++)
842 key_set64(&pkts[i].key64, j, pkts[i].uk.key[j] = ini_key[j], 0, 0x7F);
843 }
844
845 return pkts;
846 }
847
848 /***************************************************************
849 *
850 * thread
851 *
852 */
853
854 #define NQ_CRYPT 64
855 #define NQ_CMP 32
856
857 #if defined(__GNUC__)
858
859 typedef int32_t ATOMWORD_T;
860
861 #define LOCK_INC(p) \
862 asm volatile ("lock incl %0" \
863 : "=m"(*(p)) \
864 : /*nil*/ \
865 : "memory")
866
867 #define LOCK_DEC(p) \
868 asm volatile ("lock decl %0" \
869 : "=m"(*(p)) \
870 : /*nil*/ \
871 : "memory")
872
873 #define LOCK_CAS(pd,s,r) \
874 ({ ATOMWORD_T a; \
875 asm volatile ("lock cmpxchg %2,%1" \
876 : "=a"(a) \
877 : "m"(*(pd)), "r"(s), "0"(r) \
878 : "memory");a;})
879
880 #define LOCK_CASP(pd,s,r) \
881 ({ void *a; \
882 asm volatile ("lock cmpxchg %2,%1" \
883 : "=a"(a) \
884 : "m"(*(pd)), "r"(s), "0"(r) \
885 : "memory");a;})
886
887
888 #elif defined(WIN32)
889
890 typedef LONG ATOMWORD_T;
891
892 #define LOCK_INC(p) InterlockedIncrement((LONG *)(p))
893 #define LOCK_DEC(p) InterlockedDecrement((LONG *)(p))
894 #define LOCK_CAS(pd,s,r) InterlockedCompareExchange((LONG *)(pd), s, r)
895 #define LOCK_CASP(pd,s,r) InterlockedCompareExchangePointer((PVOID *)(pd), (PVOID)(s), (PVOID)r)
896
897 #else
898 #error "configuration not implemented"
899 #endif
900
901 #if defined(WIN32)
902
903 typedef DWORD THREAD_TIMEOUT_T;
904
905 #define THREAD_INFINITE INFINITE
906
907 typedef HANDLE THREAD_TH_T;
908 typedef HANDLE THREAD_EV_T;
909
910 #define thread_sleep(n) Sleep(n)
911 #define thread_create(th, proc, arg) {(th) = (HANDLE)_beginthread(proc, 8192, arg);}
912 #define thread_create_event(ev, f) {(ev) = CreateEvent(NULL, TRUE, f, NULL);}
913 #define thread_signal_event(ev) SetEvent(ev)
914 #define thread_clear_event(ev) ResetEvent(ev)
915 #define thread_get_tid() GetCurrentThread()
916 #define thread_set_priority(tid,n) SetThreadPriority(tid, n)
917 #define thread_set_affinity(tid,m) SetThreadAffinityMask(tid, (DWORD_PTR)1 << (m))
918
919 static
920 int
921 thread_wait_event(THREAD_EV_T ev, DWORD tmo)
922 {
923 DWORD r = WaitForSingleObject(ev, tmo);
924 return (r < 0
925 ? r
926 : (r == WAIT_TIMEOUT
927 ? -1
928 : r));
929 }
930
931 #elif defined(_POSIX_SOURCE) || defined(FREEBSD) || defined(SOLARIS)
932
933 #include <pthread.h>
934 #include <unistd.h>
935
936 typedef int THREAD_TIMEOUT_T;
937
938 #define THREAD_INFINITE INT_MAX
939
940 #if defined(THREAD_PRIORITY_BELOW_NOROMAL) || defined(THREAD_PRIORITY_IDLE)
941 #error "unsupported implementation"
942 #endif
943
944 #define THREAD_PRIORITY_NORMAL 14
945 #define THREAD_PRIORITY_BELOW_NORMAL 15
946 #define THREAD_PRIORITY_IDLE 16
947
948 typedef pthread_t THREAD_TH_T;
949 typedef struct
950 {
951 pthread_mutex_t m;
952 pthread_cond_t c;
953 int volatile f;
954 } THREAD_EV_T;
955
956 #define thread_sleep(n) (usleep(1000 * (n)) != EINVAL || sleep((n) / 1000))
957 #define thread_create(th, proc, arg) thread_create_p(&(th), proc, arg)
958 #define thread_create_event(ev, f) thread_create_event_p(&(ev), f)
959 #define thread_signal_event(ev) thread_set_event_p(&(ev), 1)
960 #define thread_clear_event(ev) thread_set_event_p(&(ev), 0)
961 #define thread_wait_event(ev,tmo) thread_wait_event_p(&(ev), tmo)
962
963 static
964 void
965 thread_create_p(pthread_t *th, NORETURN (*proc)(void *), void *param)
966 {
967 pthread_create(th, NULL, (void *(*)(void *))proc, param);
968 }
969
970 static
971 void
972 thread_create_event_p(THREAD_EV_T *ev, int f)
973 {
974 ev->f = f;
975 pthread_cond_init(&ev->c, NULL);
976 pthread_mutex_init(&ev->m, NULL);
977 }
978
979 static
980 void
981 thread_set_event_p(THREAD_EV_T *ev, int f)
982 {
983 pthread_mutex_lock(&ev->m);
984 if (ev->f != f)
985 {
986 ev->f = f;
987 pthread_cond_broadcast(&ev->c);
988 }
989 pthread_mutex_unlock(&ev->m);
990 }
991
992 static
993 int
994 thread_wait_event_p(THREAD_EV_T *ev, int a_tmo)
995 {
996 int timeout = a_tmo;
997 struct timeval now;
998 struct timespec tmo;
999 int r;
1000
1001 pthread_mutex_lock(&ev->m);
1002
1003 /* 現在時刻からタイムアウト時刻を求める
1004 めんどくせー */
1005 gettimeofday(&now, NULL);
1006 tmo.tv_sec = now.tv_sec + (timeout / 1000);
1007 timeout %= 1000;
1008 timeout *= 1000;
1009 if (now.tv_usec >= 1000000 - timeout)
1010 {
1011 timeout -= 1000000;
1012 tmo.tv_sec++;
1013 }
1014 tmo.tv_nsec = 1000 * (now.tv_usec + timeout);
1015 r = 0;
1016 while (!ev->f)
1017 {
1018 r = pthread_cond_timedwait(&ev->c, &ev->m, &tmo);
1019 if (r == ETIMEDOUT
1020 && a_tmo < THREAD_INFINITE)
1021 break;
1022 }
1023
1024 pthread_mutex_unlock(&ev->m);
1025
1026 return (r == ETIMEDOUT
1027 ? (ETIMEDOUT < 0 ? ETIMEDOUT : -1)
1028 : 0);
1029 }
1030
1031 #if defined(__linux__)
1032
1033 /* デフォルトスケジューリングポリシーでは
1034 優先度設定したりアイドルスレッド起こしても
1035 おもしろくないので、そのへんは今後の研究課題。 */
1036
1037 #include <linux/unistd.h>
1038 _syscall0(pid_t,gettid)
1039
1040 #define thread_get_tid() gettid()
1041
1042 static
1043 int thread_set_affinity(pid_t tid, int i)
1044 {
1045 cpu_set_t m;
1046 CPU_ZERO(&m);
1047 CPU_SET(i, &m);
1048 return sched_setaffinity(tid, sizeof(m), &m);
1049 }
1050
1051 #else
1052
1053 /* POSIX では、スレッド単位のスケジューリングに介入できない。 */
1054
1055 #endif
1056
1057 #else
1058 #error "configuration not supported"
1059 #endif
1060
1061 struct THREAD_PARAM
1062 {
1063 /* 以下は共通情報のコピー */
1064 CODE_T *code;
1065 THREAD_EV_T event_ks_activated;
1066 ATOMWORD_T volatile *p_nidle; /* 待ちに入ったら増加 */
1067
1068 /* 以下はスレッド固有 */
1069 #ifdef thread_set_priority
1070 THREAD_TH_T th;
1071 int pri;
1072 #endif
1073 };
1074
1075 static
1076 volatile ATOMWORD_T wp_crypt, rp_crypt;
1077 static
1078 struct PACKET_CRYPT64 *volatile q_crypt[NQ_CRYPT];
1079
1080 static
1081 volatile ATOMWORD_T wp_cmp, rp_cmp;
1082 static
1083 struct PACKET_CRYPT64 *volatile q_cmp[NQ_CMP];
1084
1085 static
1086 uint64_t
1087 thread_avail(void)
1088 {
1089 #if !USE_MT
1090
1091 return 0x1U;
1092
1093 #elif defined(WIN32) /* Win32 API */
1094 DWORD_PTR mask, mask_s;
1095 if (!GetProcessAffinityMask(GetCurrentProcess(),
1096 &mask,
1097 &mask_s)
1098 || !mask
1099 || !mask_s)
1100 return 0x1U;
1101 #if DEBUG>=1
1102 fprintf(stderr,
1103 "m=%08X s=%08X\n",
1104 (unsigned)mask,
1105 (unsigned)mask_s);
1106 #endif
1107 if (popcnt64(mask_s) == 1)
1108 /* 何も言うまい */;
1109 else if (mask == mask_s)
1110 fprintf(stderr,
1111 "通常の%d倍とはよく言ったものです。\n",
1112 popcnt64(mask));
1113 else
1114 fprintf(stderr,
1115 "最高速力の%g倍の力でてきとうにがんばるよ。\n",
1116 (double)popcnt64(mask) / popcnt64(mask_s));
1117 return mask;
1118
1119 #elif defined(__linux__) /* sched.h 拡張 */
1120
1121 int i;
1122 uint64_t m = 0;
1123 cpu_set_t am;
1124 if (sched_getaffinity(getpid(), sizeof(am), &am) < 0)
1125 return 0x1U;
1126
1127 for (i = 0; i < 64 && i < CPU_SETSIZE; i++)
1128 if (CPU_ISSET(i, &am))
1129 m |= 1ULL << i;
1130
1131 return m;
1132
1133 #elif defined( FREEBSD )
1134
1135 #include <sys/sysctl.h>
1136
1137 int i;
1138 uint64_t m;
1139 int nCPU;
1140 int mib[2];
1141 size_t len;
1142
1143 mib[0] = CTL_HW;
1144 mib[1] = HW_NCPU;
1145 len = sizeof( nCPU );
1146 sysctl( mib, 2, &nCPU, &len, NULL, 0 );
1147 m = (1ULL << nCPU) - 1;
1148
1149 return m;
1150
1151 #elif defined( SOLARIS )
1152
1153 #include <sys/unistd.h>
1154 #include <sys/processor.h>
1155
1156 uint64_t m;
1157 processorid_t i, cpuid_max;
1158
1159 m = 0;
1160 cpuid_max = sysconf( _SC_CPUID_MAX );
1161 for ( i = 0; i <= cpuid_max; i++ ) {
1162 if ( p_online( i, P_STATUS ) == P_ONLINE ) {
1163 m |= 1ULL << i;
1164 }
1165 }
1166
1167 return m;
1168
1169 #else
1170
1171 /* XXX プロセッサ数を調べ上げてください */
1172 return 0x01U;
1173
1174 #endif
1175 }
1176
1177 static
1178 NORETURN
1179 thread_crypt64(void *a_param)
1180 {
1181 struct THREAD_PARAM *param = a_param;
1182 CODE_T *code = param->code;
1183 struct PACKET_CRYPT64 *pkt;
1184 #ifdef thread_set_priority
1185 THREAD_TH_T th = thread_get_tid();
1186 thread_set_priority(th, param->pri);
1187 #endif
1188
1189 for(;;)
1190 {
1191 ATOMWORD_T rp;
1192 ATOMWORD_T wp;
1193
1194 /* キューから要求を取り出す */
1195 for (;;)
1196 {
1197 while ((rp = rp_crypt,
1198 WRAP(wp_crypt, NQ_CRYPT) == WRAP(rp, NQ_CRYPT)
1199 /*|| q_crypt[WRAP(rp, NQ_CRYPT)] == NULL*/))
1200 {
1201 THREAD_TIMEOUT_T tmo = (WRAP(wp_crypt, NQ_CRYPT) == WRAP(rp, NQ_CRYPT)
1202 ? THREAD_INFINITE
1203 : 1);
1204 int r;
1205
1206 /* 寝た; auto reset */
1207 if (tmo == THREAD_INFINITE)
1208 {
1209 LOCK_INC(param->p_nidle);
1210 }
1211
1212 /* 要求待ち */
1213 r = thread_wait_event(param->event_ks_activated, tmo);
1214
1215 if (tmo == THREAD_INFINITE)
1216 {
1217 /* 起こされた */
1218 LOCK_DEC(param->p_nidle);
1219 }
1220 else if (r >= 0)
1221 {
1222 /* もうちょっと寝てみる */
1223 thread_sleep(tmo);
1224 }
1225
1226 /* 自らの優先度を戻す
1227 (外からブーストされてるかも) */
1228 #ifdef thread_set_priority
1229 if (r >= 0)
1230 thread_set_priority(th, param->pri);
1231 #endif
1232 }
1233
1234 if (LOCK_CAS(&rp_crypt, rp + 1, rp) != rp)
1235 continue;
1236 rp = WRAP(rp, NQ_CRYPT);
1237 break;
1238 }
1239
1240 pkt = q_crypt[rp];
1241 assert(pkt != NULL);
1242 pkt = LOCK_CASP(&q_crypt[rp], NULL, pkt);
1243 assert(pkt != NULL);
1244
1245 /* 実行してみる */
1246 CALL_CRYPT64(code, &pkt->key64, &pkt->param64);
1247
1248 /* 結果をキューにたたき込む */
1249 for (;;)
1250 {
1251 while ((wp = wp_cmp,
1252 WRAP(rp_cmp - 1, NQ_CMP) == WRAP(wp, NQ_CMP))
1253 || q_cmp[WRAP(wp, NQ_CMP)] != NULL)
1254 {
1255 #if DEBUG>=1
1256 fprintf(stderr,
1257 "q_cmp stalled(%d,%d) %p\n",
1258 (unsigned)WRAP(wp, NQ_CMP),
1259 (unsigned)WRAP(rp_cmp - 1, NQ_CMP),
1260 q_cmp[WRAP(wp, NQ_CMP)]);
1261 #endif
1262 thread_sleep(1);
1263 }
1264
1265 if (LOCK_CAS(&wp_cmp, wp + 1, wp) != wp)
1266 continue;
1267 wp = WRAP(wp, NQ_CMP);
1268 break;
1269 }
1270
1271 pkt = LOCK_CASP(&q_cmp[wp], pkt, NULL);
1272 assert(pkt == NULL);
1273 }
1274 }
1275
1276 /***************************************************************
1277 *
1278 * メインループとか
1279 *
1280 */
1281
1282 int
1283 main(int argc, char *argv[])
1284 {
1285 int i;
1286 int mincnt;
1287 int nblk_hit, nblk_total;
1288 int nap_hit, nap_total;
1289 CODE_T *code = NULL;
1290 off_t code_cmp;
1291 FILE *ofp;
1292 FILE *sfp; /* scoreboard */
1293 struct ITREE *root_expr;
1294 uint64_t proc_mask;
1295 int ks_activated;
1296 THREAD_EV_T event_ks_activated;
1297 static ATOMWORD_T volatile nidle;
1298 struct THREAD_PARAM *threads = NULL;
1299 int nthreads;
1300 int npkts;
1301 struct PACKET_CRYPT64 *pkts, *pkt_hit;
1302 uint64_t pkts_vacant;
1303 int tn;
1304 int cr;
1305 #ifdef KEYCHECK
1306 #define KCCNT 1000000
1307 unsigned int ok, ng;
1308 #endif /* KEYCHECK */
1309 #ifdef SELFS
1310 #define TIME_LIMIT 1 * 60 * 60 * 100 /* 一時間 */
1311 #define HIT_LIMIT 10
1312 int hitcnt;
1313 #endif /* SELFS */
1314
1315 /* 鍵文字列 */
1316 uint8_t key[8 + 8];
1317
1318 int xhash_loaded;
1319
1320 #define LOOP_FACTOR 128000 /* こんなもんでいいか */
1321 #define UPDATE_INTERVAL 8 /* 速度表示の間隔 秒 */
1322 #define AVG_SPD 480000 /* 平均速度の初期値 trips/s */
1323 struct status {
1324 uint32_t startTime; /* 開始時刻 ミリ秒 */
1325 uint32_t lastTime; /* 最後に表示した時刻 ミリ秒 */
1326 uint32_t loop; /* 総検索個数 % LOOP_FACTOR */
1327 uint32_t mloop; /* 総検索個数 / LOOP_FACTOR */
1328 uint32_t lastloop; /* 最後に表示した時の loop */
1329 } status;
1330 uint32_t upd_int = AVG_SPD * UPDATE_INTERVAL;
1331 /*
1332 平均速度 (trips/s) * UPDATE_INTERVAL が UINT32_MAX を超えると発狂する。
1333 UINT32_MAX = 4294967295, 平均速度 = 100Mtrips/s なら、
1334 4294967295 / (100 * 1000 * 1000) = 42.949 秒まで。(和良
1335 LOOP_FACTOR が平均速度より十分小さければ、ほぼ指定間隔になる。
1336 LOOP_FACTOR * UINT32_MAX + LOOP_FACOTR 個検索するとオーバーフローする。w
1337 */
1338
1339 #if 0
1340 if (argc < 2)
1341 {
1342 fprintf(stderr, "式きぼんぬ\n");
1343 return 1;
1344 }
1345 #endif
1346
1347 /* 魔改造 いきなり優先度下げ */
1348 #if defined(WIN32)
1349 SetPriorityClass( GetCurrentProcess(), IDLE_PRIORITY_CLASS );
1350 #endif
1351
1352 assert((1 << N_STRIDE) == N_ALU * ALU_BITS);
1353
1354 /* タゲ読み込み */
1355 root_expr = expr_parse("target.txt");
1356
1357 /* コードを生成・展開
1358 起動予定スレッド数に応じて
1359 生成するコードを変える */
1360 sfp = scoreboard_open();
1361 fwrite(crypt64_pro, 1, crypt64_cmp_pro - crypt64_pro, sfp); /* prologue & コアループ */
1362 proc_mask = thread_avail();
1363 if (proc_mask == 1U)
1364 {
1365 /* single */
1366 npkts = 1;
1367 pkts_vacant = 1;
1368 code_cmp = 0;
1369 }
1370 else
1371 {
1372 /* multi */
1373 fwrite(crypt64_ep, 1, crypt64_ep_end - crypt64_ep, sfp); /* epilogue */
1374
1375 /* 比較器のみを生成(前半) */
1376 code_cmp = ftell(sfp);
1377 fseek(sfp, (-code_cmp) & 63, SEEK_CUR);
1378 code_cmp = ftell(sfp);
1379 fwrite(crypt64_pro, 1, crypt64_crypt - crypt64_pro, sfp); /* prologue */
1380 npkts = 64;
1381 pkts_vacant = (uint64_t)-1; /* (1 << 64) - 1 を計算したくない */
1382 }
1383
1384 /* 比較部を生成 */
1385 fwrite(crypt64_cmp_pro, 1, crypt64_cmp_ep - crypt64_cmp_pro, sfp); /* 比較器準備 */
1386 tn = synth_synthesize(sfp, root_expr);
1387 fwrite(crypt64_cmp_ep, 1, crypt64_ep_end - crypt64_cmp_ep, sfp); /* epilogue */
1388
1389 /* コードをメモリに貼り付ける */
1390 code = scoreboard_map(sfp);
1391
1392 /* キーの初期化 */
1393 /* 魔改造 起動時刻が同じでも乱数系列が変わるように */
1394 srand(time(NULL)-getpid());
1395 key_init(key);
1396 set_salt(code, key);
1397
1398 /* 演算パケットを作成 */
1399 pkts = packet_create(npkts, tn, key);
1400 pkt_hit = &pkts[npkts - 1];
1401
1402 /* 働くおじさんを量産 */
1403 thread_create_event(event_ks_activated, 1);
1404 ks_activated = 1;
1405 nthreads = 0;
1406 if (code_cmp)
1407 {
1408 THREAD_TH_T h;
1409 int ots = -1;
1410 threads = calloc(2 * popcnt64(proc_mask), sizeof(*threads));
1411 for (i = 0; proc_mask; i++, proc_mask >>= 1)
1412 if (proc_mask & 1)
1413 {
1414 if (ots < 0)
1415 {
1416 /* 自分自身のスケジューリング
1417 こーゆー系のアプリは低めに設定するのが吉(かも) */
1418 #ifdef WIN32
1419 h = GetCurrentProcess();
1420 SetPriorityClass(h, BELOW_NORMAL_PRIORITY_CLASS);
1421 #endif
1422 #if defined(thread_set_priority)
1423 /* 心の隙間お埋めします */
1424 threads[nthreads].code = code;
1425 threads[nthreads].event_ks_activated = event_ks_activated;
1426 threads[nthreads].p_nidle = &nidle;
1427 threads[nthreads].pri = THREAD_PRIORITY_IDLE;
1428 thread_create(h, thread_crypt64, &threads[nthreads]);
1429 threads[nthreads].th = h;
1430 nthreads++;
1431 #endif
1432 if (!code_cmp)
1433 break;
1434
1435 /* 自分自身の残りの設定を、あとでやる */
1436 ots = i;
1437 }
1438 else
1439 {
1440 /* 他スレッドは、やや低めの優先度で。 */
1441 threads[nthreads].code = code;
1442 threads[nthreads].event_ks_activated = event_ks_activated;
1443 threads[nthreads].p_nidle = &nidle;
1444 #ifdef thread_set_priority
1445 threads[nthreads].pri = THREAD_PRIORITY_BELOW_NORMAL;
1446 #endif
1447 thread_create(h, thread_crypt64, &threads[nthreads]);
1448 #ifdef thread_set_priority
1449 threads[nthreads].th = h;
1450 #endif
1451 #ifdef thread_get_tid
1452 thread_set_affinity(h, i);
1453 #endif
1454 nthreads++;
1455 }
1456 }
1457 #ifdef thread_get_tid
1458 if (ots)
1459 thread_set_affinity(thread_get_tid(), ots);
1460 #endif
1461 }
1462
1463 if ((ofp = fopen("log.txt", "at")) == NULL)
1464 {
1465 perror("log.txt");
1466 return errno;
1467 }
1468
1469 setvbuf(ofp, NULL, _IONBF, BUFSIZ); /* XXX MSVCRT では _IOLBF が期待通りに動作しない */
1470
1471 mincnt = 0x7FFFFFFF;
1472 nblk_hit = nblk_total = 0;
1473 nap_hit = nap_total = 0;
1474 cr = 0;
1475 memset( &status, 0, sizeof( struct status ) );
1476 status.startTime = status.lastTime = usec();
1477 #ifdef KEYCHECK
1478 ok = ng = 0;
1479 #endif /* KEYCHECK */
1480 /* 探索ループだぞっと */
1481 #ifdef SELFS
1482 hitcnt = 0;
1483 #endif /* SELFS */
1484 for (;;)
1485 {
1486 struct PACKET_CRYPT64 *pkt_c;
1487 uint64_t cnt;
1488 int cnt1, cnt2;
1489 int k, kk;
1490
1491 /* 比較器候補(may be NULL)
1492 先にキューから取り出す */
1493 pkt_c = q_cmp[WRAP(rp_cmp, NQ_CMP)];
1494 if (pkt_c != NULL)
1495 {
1496 pkt_c = LOCK_CASP(&q_cmp[WRAP(rp_cmp, NQ_CMP)], NULL, pkt_c);
1497 assert(pkt_c != NULL);
1498 LOCK_INC(&rp_cmp);
1499
1500 /* パケットを vacant に回しておく */
1501 pkts_vacant |= 1ULL << (pkt_c - pkts);
1502 }
1503
1504 /* Saltチェンジ待ち */
1505 if (!ks_activated)
1506 {
1507 int tmo = (pkt_c != NULL
1508 ? 0 /* poll */
1509 : 1);
1510 thread_sleep(tmo);
1511 if (nidle == nthreads)
1512 {
1513 assert(WRAP(rp_crypt, NQ_CRYPT) == WRAP(wp_crypt, NQ_CRYPT));
1514 /* Salt チェンジが可能 */
1515 set_salt(code, key);
1516 if (code_cmp)
1517 thread_signal_event(event_ks_activated);
1518 ks_activated = 1;
1519 }
1520 }
1521
1522 /* 鍵をキューにたたき込みまくる */
1523 if (!ks_activated)
1524 {
1525 /* 鍵を登録しない */
1526 ;
1527 }
1528 else for (i = npkts - 1; i >= 0; i--)
1529 if (pkts_vacant & (1ULL << i))
1530 {
1531 int j;
1532
1533 if (i == npkts - 1)
1534 {
1535 /* 前段で、働くおじさんから
1536 結果をもらっていたら、何もしない */
1537 if (pkt_c != NULL)
1538 continue;
1539 }
1540 else
1541 {
1542 /* 前段で取り出したばかりの
1543 働くおじさんは、尊重する */
1544 if (&pkts[i] == pkt_c)
1545 continue;
1546
1547 /* queue full の場合は見送る */
1548 if (WRAP(wp_crypt, NQ_CRYPT) == WRAP(rp_crypt - 1, NQ_CRYPT)
1549 || q_crypt[WRAP(wp_crypt, NQ_CRYPT)] != NULL)
1550 break;
1551 }
1552
1553 /* 鍵のセット */
1554 for (j = 0; j < 8; j++)
1555 {
1556 key_set64(&pkts[i].key64, j, key[j], key[j] ^ pkts[i].uk.key[j], 0);
1557 pkts[i].uk.key[j] = key[j];
1558 }
1559
1560 if (i == npkts - 1)
1561 {
1562 /* 次段で CRYPT64->CMP */
1563 assert(pkt_c == NULL);
1564 pkt_c = &pkts[i];
1565 assert(pkt_c == pkt_hit);
1566 }
1567 else
1568 {
1569 /* キューにたたき込む */
1570 while (LOCK_CASP(&q_crypt[WRAP(wp_crypt, NQ_CRYPT)], &pkts[i], NULL) != NULL)
1571 {
1572 /* 設計上はここに来ない */
1573 #if DEBUG>=1
1574 fprintf(stderr,
1575 "[XXX] q_crypt を汚してるのは誰だ? (rp=%3d, wp=%3d, v=%08X%08X)\n",
1576 (unsigned)WRAP(rp_crypt, NQ_CRYPT),
1577 (unsigned)WRAP(wp_crypt, NQ_CRYPT),
1578 (unsigned)(pkts_vacant >> 32),
1579 (unsigned)pkts_vacant);
1580 thread_sleep(1000);
1581 #endif
1582 thread_sleep(1);
1583 }
1584 LOCK_INC(&wp_crypt);
1585 pkts_vacant ^= 1ULL << i;
1586 assert(!(pkts_vacant & (1ULL << i))); /* 削れ */
1587 }
1588
1589 /* 鍵増加はこんなところに移動! */
1590 assert(ks_activated);
1591 if (!key_inc(key, 6) && !key_inc(key, KEY_SHUFFLE_POS))
1592 {
1593 /* 鍵のシャッフル
1594 q_crypt が捌けるまで、set_salt() はできない */
1595 #if DEBUG>=1
1596 fprintf(stderr, "********************************SHUFFLE!\n");
1597 #endif
1598 thread_clear_event(event_ks_activated);
1599 key_reset(key, 0);
1600
1601 /* キューの鍵が捌けるまでアイドル状態に */
1602 ks_activated = 0;
1603
1604 /* スレッドをブーストして回る */
1605 #ifdef thread_set_priority
1606 for (j = 0; j < nthreads; j++)
1607 {
1608 assert(threads != NULL);
1609 thread_set_priority(threads[j].th, THREAD_PRIORITY_NORMAL);
1610 }
1611 #endif
1612
1613 /* ループ続行はもはや不要 */
1614 break;
1615 }
1616 }
1617
1618 /* することがなくなっている場合 */
1619 if (pkt_c == NULL)
1620 {
1621 assert(!ks_activated);
1622 continue;
1623 }
1624
1625 /* 呼ぶ!
1626 LR 初期化は、サブモジュール内で行うべし
1627 FASTCALL に準じた呼び出しのため、
1628 ホントはいろいろレジスタが破壊されるハズ…なんだが。 */
1629 if (pkt_c != pkt_hit)
1630 {
1631 cnt = CALL_CMP64(code + code_cmp,
1632 pkt_hit->param64.hit,
1633 pkt_c->param64.lr);
1634 }
1635 else
1636 {
1637 /* ようやく自スレッドで回せる */
1638 cnt = CALL_CRYPT64(code,
1639 &pkt_c->key64,
1640 &pkt_c->param64);
1641 if (code_cmp)
1642 cnt = CALL_CMP64(code + code_cmp,
1643 pkt_c->param64.hit,
1644 pkt_c->param64.lr);
1645 }
1646
1647 #if DEBUG>=1
1648 cnt2 = (int32_t)(cnt >> 32);
1649 cnt1 = (int32_t)cnt;
1650 if (mincnt > cnt1 && cnt1 > 0)
1651 {
1652 mincnt = cnt1;
1653 if (cr)
1654 fprintf(stderr, "\n");
1655 cr = 0;
1656 fprintf(stderr, "cycle=%6d/%6d\n", cnt1, cnt2);
1657 }
1658 #endif
1659
1660 /* ヒットしたときの処理
1661 key および lr は pkt_c に
1662 合致判定は pkt_hit に入っているハズ */
1663 xhash_loaded = 0;
1664 for (kk = 0; kk < N_ALU; kk++)
1665 {
1666 ALU_T t;
1667 if (!(kk & (N_ALU / N_Q - 1)))
1668 nblk_total++, xhash_loaded = 0;
1669
1670 t = pkt_hit->param64.hit[HIT_ANY].a[kk];
1671 #ifndef KEYCHECK
1672 if (!t)
1673 continue;
1674 #endif /* KEYCHECK */
1675
1676 nap_total += ALU_BITS;
1677
1678 for (k = 0; k < ALU_BITS; k++)
1679 {
1680 static uint64_t xhash[64];
1681 char hash[16];
1682 uint8_t buf[32];
1683 time_t tloc;
1684
1685 #ifndef KEYCHECK
1686 if (!(t & ((ALU_T)1 << k)))
1687 continue;
1688 #endif /* KEYCHECK */
1689
1690 nap_hit++;
1691
1692 /* 転置 */
1693 if (!xhash_loaded)
1694 {
1695 nblk_hit++;
1696 CALL_TR64(&pkt_c->param64.lr[0][0].q[kk / (N_ALU / N_Q)], xhash);
1697 xhash_loaded = 1;
1698 }
1699
1700 #ifndef KEYCHECK
1701 /* 辞書を調べる */
1702 if (!((pkt_hit->param64.hit[HIT_BOOL].a[kk] & ((ALU_T)1 << k))
1703 || wdict_ishit(pkt_hit->param64.hit,
1704 kk, k,
1705 xhash[(ALU_BITS * kk + k) & 0x3F])))
1706 continue;
1707 #endif /* KEYCHECK */
1708
1709 for (i = 1; i < 11; i++)
1710 {
1711 unsigned c = 0;
1712 c = (xhash[(ALU_BITS * kk + k) & 63] >> (6 * (i - 1))) & 0x3F; /* XXX */
1713 hash[i - 1] = C64[c];
1714 }
1715 hash[10] = 0;
1716
1717 memcpy(buf, pkt_c->uk.key, 8);
1718 buf[8] = buf[9] = 0;
1719 buf[7] = (buf[7] & -(1 << N_STRIDE) & 0x7F) + ALU_BITS * kk + k;
1720 #ifdef KEYCHECK
1721 {
1722 #include <crypt.h>
1723 char *res;
1724 char salt[3];
1725 static unsigned char saltTable[] =
1726 ".............................................../0123456789ABCDEF"
1727 "GABCDEFGHIJKLMNOPQRSTUVWXYZabcdefabcdefghijklmnopqrstuvwxyz....."
1728 "................................................................"
1729 "................................................................";
1730 salt[2] = '\0';
1731 salt[0] = saltTable[buf[1]];
1732 salt[1] = saltTable[buf[2]];
1733 res = crypt( buf, salt );
1734 if ( strcmp( res+3, hash ) != 0 ) {
1735 printf( "res+3 = <%s>, hash = <%s>\n", res+3, hash );
1736 exit( 0 );
1737 }
1738 }
1739 #endif /* KEYCHECK */
1740 time( &tloc );
1741 if (translate(buf, 0, 1))
1742 {
1743 #ifdef KEYCHECK
1744 ok++;
1745 if ( ok + ng >= KCCNT ) {
1746 printf( "\nok = %u, ng = %u\n", ok, ng );
1747 exit( 1 );
1748 }
1749 #endif /* KEYCHECK */
1750 #ifndef KEYCHECK
1751 if (cr)
1752 fprintf(stderr, "\n");
1753 cr = 0;
1754 #if DEBUG>=1
1755 fprintf(stderr, "%3d:", pkt_c - pkts);
1756 #endif
1757 /* 魔改造 ヒットした日時を表示 */
1758 log_printf(ofp,
1759 "◆%s #%-10.10s(%02X %02X %02X %02X %02X %02X %02X %02X/%02X) %s",
1760 hash,
1761 buf,
1762 buf[0], buf[1], buf[2], buf[3],
1763 buf[4], buf[5], buf[6], buf[7],
1764 buf[8], ctime(&tloc) );
1765 #endif /* not KEYCHECK */
1766 }
1767 else
1768 {
1769 #ifdef KEYCHECK
1770 ng++;
1771 if ( ok + ng >= KCCNT ) {
1772 printf( "\nok = %u, ng = %u\n", ok, ng );
1773 exit( 1 );
1774 }
1775 #endif /* KEYCHECK */
1776 #ifndef KEYCHECK
1777 /* 魔改造 failed も表示する */
1778 if (cr)
1779 fprintf(stderr, "\n");
1780 cr = 0;
1781 #if DEBUG>=1
1782 fprintf(stderr, "%3d:", pkt_c - pkts);
1783 #endif
1784 log_printf(ofp,
1785 "◆%s (%02X %02X %02X %02X %02X %02X %02X %02X ) %s",
1786 hash,
1787 buf[0], buf[1], buf[2], buf[3],
1788 buf[4], buf[5], buf[6], buf[7], ctime(&tloc) );
1789 #endif /* not KEYCHECK */
1790 }
1791 #ifdef SELFS
1792 hitcnt++;
1793 if ( hitcnt >= HIT_LIMIT ) {
1794 exit( 0 );
1795 }
1796 #endif /* SELFS */
1797 }
1798 }
1799
1800 status.loop += N_ALU * ALU_BITS;
1801 if ( status.loop >= upd_int )
1802 {
1803 /*
1804 ここで更新間隔のチェックをすれば、高速マシンで誤差の大きい速度表示が
1805 出るのを防げる。
1806 だがそれをすると普通のマシンでムダな usec() 呼び出しをすることになる。
1807 だからやらない。決して手抜きではない。
1808 */
1809 uint32_t curTime, diffTime;
1810 int a, b, c;
1811
1812 #ifdef SPDEBUG
1813 putchar( '\n' );
1814 printf( "mloop = %d, loop = %d\n", status.mloop, status.loop );
1815 #endif
1816 curTime = usec();
1817 #ifdef SELFS
1818 if ( curTime > TIME_LIMIT ) {
1819 exit( 0 );
1820 }
1821 #endif /* SELFS */
1822 diffTime = curTime - status.lastTime;
1823 b = (status.loop - status.lastloop) * 100 / diffTime;
1824 status.mloop += ( status.loop / LOOP_FACTOR );
1825 status.loop %= LOOP_FACTOR;
1826 diffTime = curTime - status.startTime;
1827 if ( diffTime >= 1000000000 ) {
1828 c = 1000000;
1829 } else if ( diffTime >= 100000000 ) {
1830 c = 100000;
1831 } else if ( diffTime >= 10000000 ) {
1832 c = 10000;
1833 } else if ( diffTime >= 1000000 ) {
1834 c = 1000;
1835 } else if ( diffTime >= 100000 ) {
1836 c = 100;
1837 } else if ( diffTime >= 10000 ) {
1838 c = 10;
1839 } else {
1840 c = 1;
1841 }
1842 a = status.mloop * (LOOP_FACTOR / (10 * c)) / (diffTime / c);
1843 upd_int = b * UPDATE_INTERVAL;
1844 upd_int = upd_int / LOOP_FACTOR * LOOP_FACTOR;
1845 #ifdef SPDEBUG
1846 {
1847 #ifndef USE_MMX
1848 double d;
1849 d = ((double)status.mloop * LOOP_FACTOR / 1000.0) / ((double)diffTime / 100.0);
1850 printf( "d = %f\n", d );
1851 #endif
1852 printf( "mloop = %d, loop = %d\n", status.mloop, status.loop );
1853 printf( "%d - %d = %d\n", curTime, status.startTime, curTime - status.startTime );
1854 printf( "%d - %d = %d\n", curTime, status.lastTime, curTime - status.lastTime );
1855 printf( "c = %d\n", c );
1856 printf( "upd_int = %d\n", upd_int );
1857 }
1858 #endif
1859 status.lastTime = curTime;
1860 status.lastloop = status.loop;
1861 #if DEBUG>=1
1862 fprintf(stderr,
1863 "%5d/%5d(%3d%%)",
1864 nblk_hit, nblk_total, 100 * nblk_hit / nblk_total);
1865 nblk_hit = nblk_total = 0;
1866 if (nap_total)
1867 fprintf(stderr,
1868 " %5d/%5d(%3d%%)",
1869 nap_hit, nap_total, 100 * nap_hit / nap_total);
1870 else
1871 fprintf(stderr,
1872 " -----/-----(---%%)");
1873 nap_hit = nap_total = 0;
1874 #endif
1875 fprintf( stderr,
1876 "%6dktrips/s [%6d.%03dktrips/s]\r",
1877 a, b / 1000, b % 1000 );
1878 /* 魔改造 速度表示は残さない */
1879 cr = 0;
1880 }
1881 }
1882
1883 return 0;
1884 }
1885
1886 /*
1887 * Local Variables:
1888 * tab-width: 4
1889 * End:
1890 *
1891 * EOF */

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Rev URL

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26