Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 163 - (hide 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 chapuni 1 /***********************************************************************
2     *
3 chapuni 26 * file: mty.c
4 chapuni 1 *
5 chapuni 2 * まあ、待て屋。
6 chapuni 1 *
7     * $Id$
8     *
9     */
10    
11     #include <assert.h>
12     #include <ctype.h>
13 chapuni 24 #include <errno.h>
14 chapuni 9 #include <limits.h>
15 chapuni 24 #include <stdarg.h>
16 chapuni 20 #include <stddef.h>
17 chapuni 1 #include <stdio.h>
18     #include <stdlib.h>
19     #include <string.h>
20     #include <time.h>
21 notanpe 148 #include <sys/types.h>
22 chapuni 10
23     #if defined(WIN32)
24    
25     #include <windows.h>
26 notanpe 148 #include <process.h>
27 chapuni 10 #include <sys/timeb.h>
28    
29     #elif defined(__GNUC__)
30    
31     #include <sys/time.h>
32    
33     #endif
34    
35 chapuni 26 #include "config.h"
36 chapuni 39 #include "cp932.h"
37 chapuni 1 #include "crypt64.h"
38 chapuni 41 #include "desconst.h"
39 chapuni 46 #include "expr_parse.h"
40     #include "scoreboard.h"
41     #include "synth.h"
42 chapuni 74 #include "tr64.h"
43 chapuni 26 #include "translate.h"
44 notanpe 148 #include "util.h"
45 chapuni 99 #include "wdict.h"
46 chapuni 1
47 chapuni 39 #if USE_DT
48     #include "dt4.h"
49     #endif
50    
51 chapuni 1 /* 鍵クラス */
52 chapuni 41 static
53 chapuni 1 struct
54     {
55 notanpe 148 unsigned short map[256];
56 chapuni 1 } kcls[8 + 8];
57    
58 chapuni 26
59     /* 拡張鍵クラス */
60 chapuni 1 #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 notanpe 148 key_make_map(uint8_t *key, int n)
75 chapuni 1 {
76     int i, j;
77     unsigned c = kcls[n].map[key[n]];
78    
79 chapuni 39 #if USE_DT
80 chapuni 1 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 chapuni 39 #endif
169 chapuni 1
170     /* 最後の部分は class map を生成する必要ナシ */
171     if (n >= 6)
172     return;
173    
174     for (i = 0; i < 256; i++)
175     {
176 chapuni 25 unsigned bm = 0;
177 chapuni 1 #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 chapuni 39 #if USE_DT
213 chapuni 1 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 chapuni 39 #endif
244 chapuni 1
245     /* マップから文字を拾ってセット */
246     unsigned
247     key_set(int n, unsigned ch)
248     {
249     int cnt = 0, i;
250    
251 chapuni 39 #if USE_DT
252 chapuni 1 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 chapuni 39 #endif
268 chapuni 1
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 chapuni 6 int i, j;
317 chapuni 1 if (!((vk | sk) & 0x7F))
318     return;
319    
320     for (i = 0; i < 7; i++)
321     {
322 chapuni 6 if (n == 7 && i < N_STRIDE) continue;
323 chapuni 1 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 chapuni 6 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 chapuni 1 }
335     else
336     {
337     assert(o >= 28);
338     assert(o < 56);
339 chapuni 6 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 chapuni 1 }
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 chapuni 10 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 chapuni 1 }
357     else
358     {
359     assert(o >= 28);
360     assert(o < 56);
361 chapuni 10 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 chapuni 1 }
366     }
367     }
368     }
369    
370     /* 指定されたクラスの開始値にリセット
371     直前の文字のクラスに縛られる */
372     int
373 notanpe 148 key_reset(uint8_t *key, int n)
374 chapuni 1 {
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 notanpe 148 if (n >= KEY_SHUFFLE_POS)
386 chapuni 1 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 notanpe 148 key_make_map(key, n);
396 chapuni 1
397 notanpe 148 return key_reset(key, n + 1);
398 chapuni 1 }
399    
400     /* 指定された鍵空間の中で、キーをひとつ進める
401     安全にインクリメントできた場合 true を返す */
402     static
403     int
404 notanpe 148 key_inc(uint8_t *key, int n)
405 chapuni 1 {
406     if (n >= 8)
407     return 0;
408     else if (n == 7)
409     {
410 chapuni 6 /* 最後のバイト */
411 notanpe 148 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 chapuni 1 }
419 notanpe 148 else if (key_inc(key, n + 1)
420 chapuni 1 /*
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 chapuni 39 #if USE_DT
436 chapuni 1 /* 辞書語はインクリメントしていい約束にする */
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 chapuni 39 #endif
525 chapuni 1
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 notanpe 148 {
542     key[n] = 0xFF; /* 次に突入させないため */
543     return 0;
544     }
545 chapuni 1 }
546    
547     if (kcls[n].map[key[n]])
548     {
549 notanpe 148 key_make_map(key, n);
550     key_reset(key, n + 1);
551 chapuni 1 return 1;
552     }
553     }
554     }
555    
556     /* 鍵を完全にリセットする
557     Saltもセットし直す */
558     static
559     void
560 notanpe 148 key_init(uint8_t *key)
561 chapuni 1 {
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 notanpe 148 key_reset(key, 0);
620 chapuni 1 }
621    
622     /***************************************************************
623     *
624 chapuni 122 * 固定キーの生成
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 chapuni 123 #if DEBUG>=2
646 chapuni 122 printf("%d:%d->%2d: %08X%08X\n",
647     N_Q, i, o,
648     (unsigned)(m >> 32),
649     (unsigned)m);
650 chapuni 123 #endif
651 chapuni 122 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 chapuni 1 * Salt のセット
670     * オペランドのオフセットを書き換えて回ってるので注意
671     *
672     */
673    
674 chapuni 9 #if N_STRIDE == 6
675 notanpe 148 #define C(c,i,j,o) (*(int8_t *)((c) + (loo - crypt64_pro) + los[6 * (i) + (j) + (o)]))
676 chapuni 9 #elif N_STRIDE == 7
677 notanpe 148 #define C(c,i,j,o) (*(int32_t *)((c) + (loo - crypt64_pro) + los[6 * (i) + (j) + (o)]))
678 chapuni 6 #endif
679    
680 chapuni 1 void
681 notanpe 148 set_salt(CODE_T *code,
682     uint8_t const *k)
683 chapuni 1 {
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 chapuni 6 //printf("Salt %d:%d %+3d:%+3d",
707     printf("Salt %d:%d %08lX:%08lX",
708 chapuni 1 i, j,
709 chapuni 6 C(code, i, j, 0),
710     C(code, i, j, 24));
711 chapuni 1 #endif
712     if (s & (1 << j))
713     {
714 chapuni 6 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 chapuni 1 }
717     else
718     {
719 chapuni 6 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 chapuni 1 }
722 chapuni 6 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 chapuni 1 #if DEBUG>=2
725 chapuni 6 //printf(" => %+3d:%+3d\n",
726     printf(" => %08lX:%08lX\n",
727     C(code, i, j, 0),
728     C(code, i, j, 24));
729 chapuni 1 #endif
730     }
731     }
732     }
733    
734     static
735 notanpe 120 uint32_t
736 notanpe 148 usec(void)
737 notanpe 119 {
738 notanpe 120 static uint32_t epoch = 0;
739     uint32_t sec, msec;
740    
741 notanpe 119 #if !defined(WIN32)
742     struct timeval tv;
743     gettimeofday(&tv, NULL);
744 notanpe 120 sec = tv.tv_sec;
745     msec = tv.tv_usec / 10000;
746 notanpe 119 #else
747     struct timeb tm;
748     ftime(&tm);
749 notanpe 120 sec = tm.time;
750     msec = tm.millitm / 10;
751 notanpe 119 #endif
752 notanpe 120
753     if ( epoch == 0 ) {
754     epoch = sec;
755     }
756    
757     return ((sec - epoch) * 100 + msec);
758 notanpe 119 }
759    
760     static
761 chapuni 24 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 chapuni 1 /***************************************************************
777     *
778 notanpe 148 * バッチ処理用パケット
779 chapuni 1 *
780     */
781    
782 notanpe 148 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 chapuni 1
793 notanpe 148 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 chapuni 1 int
921 notanpe 148 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 chapuni 1 main(int argc, char *argv[])
1284     {
1285 chapuni 74 int i;
1286 chapuni 1 int mincnt;
1287 chapuni 77 int nblk_hit, nblk_total;
1288 chapuni 84 int nap_hit, nap_total;
1289 notanpe 148 CODE_T *code = NULL;
1290     off_t code_cmp;
1291 chapuni 1 FILE *ofp;
1292 chapuni 46 FILE *sfp; /* scoreboard */
1293     struct ITREE *root_expr;
1294 notanpe 148 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 chapuni 1 int cr;
1305 notanpe 146 #ifdef KEYCHECK
1306 notanpe 150 #define KCCNT 1000000
1307 notanpe 146 unsigned int ok, ng;
1308 notanpe 150 #endif /* KEYCHECK */
1309 notanpe 163 #ifdef SELFS
1310     #define TIME_LIMIT 1 * 60 * 60 * 100 /* 一時間 */
1311     #define HIT_LIMIT 10
1312     int hitcnt;
1313     #endif /* SELFS */
1314 chapuni 1
1315 notanpe 148 /* 鍵文字列 */
1316     uint8_t key[8 + 8];
1317    
1318 chapuni 74 int xhash_loaded;
1319    
1320 notanpe 120 #define LOOP_FACTOR 128000 /* こんなもんでいいか */
1321 notanpe 119 #define UPDATE_INTERVAL 8 /* 速度表示の間隔 秒 */
1322 notanpe 120 #define AVG_SPD 480000 /* 平均速度の初期値 trips/s */
1323 notanpe 115 struct status {
1324 notanpe 120 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 notanpe 115 } status;
1330 notanpe 120 uint32_t upd_int = AVG_SPD * UPDATE_INTERVAL;
1331 notanpe 119 /*
1332 notanpe 120 平均速度 (trips/s) * UPDATE_INTERVAL が UINT32_MAX を超えると発狂する。
1333     UINT32_MAX = 4294967295, 平均速度 = 100Mtrips/s なら、
1334     4294967295 / (100 * 1000 * 1000) = 42.949 秒まで。(和良
1335 notanpe 119 LOOP_FACTOR が平均速度より十分小さければ、ほぼ指定間隔になる。
1336 notanpe 120 LOOP_FACTOR * UINT32_MAX + LOOP_FACOTR 個検索するとオーバーフローする。w
1337 notanpe 119 */
1338 chapuni 1
1339     #if 0
1340     if (argc < 2)
1341     {
1342     fprintf(stderr, "式きぼんぬ\n");
1343     return 1;
1344     }
1345     #endif
1346    
1347 notanpe 130 /* 魔改造 いきなり優先度下げ */
1348     #if defined(WIN32)
1349     SetPriorityClass( GetCurrentProcess(), IDLE_PRIORITY_CLASS );
1350     #endif
1351    
1352 chapuni 10 assert((1 << N_STRIDE) == N_ALU * ALU_BITS);
1353    
1354 chapuni 46 /* タゲ読み込み */
1355     root_expr = expr_parse("target.txt");
1356 chapuni 2
1357 notanpe 148 /* コードを生成・展開
1358     起動予定スレッド数に応じて
1359     生成するコードを変える */
1360 chapuni 46 sfp = scoreboard_open();
1361 notanpe 148 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 chapuni 2
1375 notanpe 148 /* 比較器のみを生成(前半) */
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 chapuni 46 /* コードをメモリに貼り付ける */
1390     code = scoreboard_map(sfp);
1391 chapuni 1
1392     /* キーの初期化 */
1393 notanpe 150 /* 魔改造 起動時刻が同じでも乱数系列が変わるように */
1394     srand(time(NULL)-getpid());
1395 notanpe 148 key_init(key);
1396 chapuni 1 set_salt(code, key);
1397    
1398 notanpe 148 /* 演算パケットを作成 */
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 chapuni 1 #endif
1422 notanpe 148 #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 chapuni 1
1435 notanpe 148 /* 自分自身の残りの設定を、あとでやる */
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 chapuni 24 if ((ofp = fopen("log.txt", "at")) == NULL)
1464     {
1465     perror("log.txt");
1466     return errno;
1467     }
1468 chapuni 1
1469 chapuni 24 setvbuf(ofp, NULL, _IONBF, BUFSIZ); /* XXX MSVCRT では _IOLBF が期待通りに動作しない */
1470    
1471 chapuni 1 mincnt = 0x7FFFFFFF;
1472 chapuni 77 nblk_hit = nblk_total = 0;
1473 chapuni 84 nap_hit = nap_total = 0;
1474 chapuni 1 cr = 0;
1475 notanpe 120 memset( &status, 0, sizeof( struct status ) );
1476 notanpe 119 status.startTime = status.lastTime = usec();
1477 notanpe 146 #ifdef KEYCHECK
1478     ok = ng = 0;
1479 notanpe 150 #endif /* KEYCHECK */
1480 chapuni 1 /* 探索ループだぞっと */
1481 notanpe 163 #ifdef SELFS
1482     hitcnt = 0;
1483     #endif /* SELFS */
1484 chapuni 1 for (;;)
1485     {
1486 notanpe 148 struct PACKET_CRYPT64 *pkt_c;
1487 chapuni 121 uint64_t cnt;
1488     int cnt1, cnt2;
1489 chapuni 1 int k, kk;
1490    
1491 notanpe 148 /* 比較器候補(may be NULL)
1492     先にキューから取り出す */
1493     pkt_c = q_cmp[WRAP(rp_cmp, NQ_CMP)];
1494     if (pkt_c != NULL)
1495 chapuni 1 {
1496 notanpe 148 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 chapuni 1 }
1503    
1504 notanpe 148 /* 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 chapuni 14 /* 呼ぶ!
1626     LR 初期化は、サブモジュール内で行うべし
1627     FASTCALL に準じた呼び出しのため、
1628     ホントはいろいろレジスタが破壊されるハズ…なんだが。 */
1629 notanpe 148 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 chapuni 42
1647 chapuni 46 #if DEBUG>=1
1648 chapuni 121 cnt2 = (int32_t)(cnt >> 32);
1649     cnt1 = (int32_t)cnt;
1650     if (mincnt > cnt1 && cnt1 > 0)
1651 chapuni 1 {
1652 chapuni 121 mincnt = cnt1;
1653 chapuni 1 if (cr)
1654     fprintf(stderr, "\n");
1655     cr = 0;
1656 chapuni 121 fprintf(stderr, "cycle=%6d/%6d\n", cnt1, cnt2);
1657 chapuni 1 }
1658 chapuni 46 #endif
1659 chapuni 1
1660 notanpe 148 /* ヒットしたときの処理
1661     key および lr は pkt_c に
1662     合致判定は pkt_hit に入っているハズ */
1663 chapuni 74 xhash_loaded = 0;
1664 chapuni 6 for (kk = 0; kk < N_ALU; kk++)
1665 chapuni 1 {
1666 chapuni 6 ALU_T t;
1667 chapuni 84 if (!(kk & (N_ALU / N_Q - 1)))
1668 chapuni 77 nblk_total++, xhash_loaded = 0;
1669 chapuni 9
1670 notanpe 148 t = pkt_hit->param64.hit[HIT_ANY].a[kk];
1671 notanpe 146 #ifndef KEYCHECK
1672 chapuni 1 if (!t)
1673     continue;
1674 notanpe 150 #endif /* KEYCHECK */
1675 chapuni 9
1676 chapuni 84 nap_total += ALU_BITS;
1677    
1678 chapuni 6 for (k = 0; k < ALU_BITS; k++)
1679 chapuni 1 {
1680 chapuni 74 static uint64_t xhash[64];
1681 chapuni 1 char hash[16];
1682 notanpe 148 uint8_t buf[32];
1683 notanpe 130 time_t tloc;
1684 chapuni 9
1685 notanpe 146 #ifndef KEYCHECK
1686 chapuni 9 if (!(t & ((ALU_T)1 << k)))
1687 chapuni 1 continue;
1688 notanpe 150 #endif /* KEYCHECK */
1689 chapuni 9
1690 chapuni 84 nap_hit++;
1691    
1692 chapuni 74 /* 転置 */
1693     if (!xhash_loaded)
1694     {
1695 chapuni 77 nblk_hit++;
1696 notanpe 148 CALL_TR64(&pkt_c->param64.lr[0][0].q[kk / (N_ALU / N_Q)], xhash);
1697 chapuni 74 xhash_loaded = 1;
1698     }
1699    
1700 notanpe 146 #ifndef KEYCHECK
1701 chapuni 74 /* 辞書を調べる */
1702 notanpe 148 if (!((pkt_hit->param64.hit[HIT_BOOL].a[kk] & ((ALU_T)1 << k))
1703     || wdict_ishit(pkt_hit->param64.hit,
1704 chapuni 99 kk, k,
1705     xhash[(ALU_BITS * kk + k) & 0x3F])))
1706 chapuni 74 continue;
1707 notanpe 150 #endif /* KEYCHECK */
1708 chapuni 74
1709 chapuni 1 for (i = 1; i < 11; i++)
1710     {
1711     unsigned c = 0;
1712 chapuni 74 c = (xhash[(ALU_BITS * kk + k) & 63] >> (6 * (i - 1))) & 0x3F; /* XXX */
1713     hash[i - 1] = C64[c];
1714 chapuni 1 }
1715     hash[10] = 0;
1716    
1717 notanpe 148 memcpy(buf, pkt_c->uk.key, 8);
1718 chapuni 1 buf[8] = buf[9] = 0;
1719 chapuni 10 buf[7] = (buf[7] & -(1 << N_STRIDE) & 0x7F) + ALU_BITS * kk + k;
1720 notanpe 150 #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 notanpe 130 time( &tloc );
1741 chapuni 1 if (translate(buf, 0, 1))
1742     {
1743 notanpe 146 #ifdef KEYCHECK
1744     ok++;
1745 notanpe 150 if ( ok + ng >= KCCNT ) {
1746     printf( "\nok = %u, ng = %u\n", ok, ng );
1747 notanpe 146 exit( 1 );
1748     }
1749 notanpe 150 #endif /* KEYCHECK */
1750     #ifndef KEYCHECK
1751 chapuni 1 if (cr)
1752     fprintf(stderr, "\n");
1753     cr = 0;
1754 notanpe 148 #if DEBUG>=1
1755     fprintf(stderr, "%3d:", pkt_c - pkts);
1756     #endif
1757 notanpe 130 /* 魔改造 ヒットした日時を表示 */
1758 chapuni 24 log_printf(ofp,
1759 notanpe 130 "◆%s #%-10.10s(%02X %02X %02X %02X %02X %02X %02X %02X/%02X) %s",
1760 chapuni 24 hash,
1761     buf,
1762     buf[0], buf[1], buf[2], buf[3],
1763     buf[4], buf[5], buf[6], buf[7],
1764 notanpe 130 buf[8], ctime(&tloc) );
1765 notanpe 150 #endif /* not KEYCHECK */
1766 chapuni 1 }
1767     else
1768     {
1769 notanpe 146 #ifdef KEYCHECK
1770     ng++;
1771 notanpe 150 if ( ok + ng >= KCCNT ) {
1772     printf( "\nok = %u, ng = %u\n", ok, ng );
1773 notanpe 146 exit( 1 );
1774     }
1775 notanpe 150 #endif /* KEYCHECK */
1776     #ifndef KEYCHECK
1777 notanpe 130 /* 魔改造 failed も表示する */
1778 chapuni 1 if (cr)
1779     fprintf(stderr, "\n");
1780     cr = 0;
1781 notanpe 148 #if DEBUG>=1
1782     fprintf(stderr, "%3d:", pkt_c - pkts);
1783     #endif
1784 chapuni 24 log_printf(ofp,
1785 notanpe 130 "◆%s (%02X %02X %02X %02X %02X %02X %02X %02X ) %s",
1786 chapuni 24 hash,
1787     buf[0], buf[1], buf[2], buf[3],
1788 notanpe 130 buf[4], buf[5], buf[6], buf[7], ctime(&tloc) );
1789 notanpe 150 #endif /* not KEYCHECK */
1790 chapuni 1 }
1791 notanpe 163 #ifdef SELFS
1792     hitcnt++;
1793     if ( hitcnt >= HIT_LIMIT ) {
1794     exit( 0 );
1795 chapuni 1 }
1796 notanpe 163 #endif /* SELFS */
1797     }
1798 chapuni 1 }
1799    
1800 notanpe 115 status.loop += N_ALU * ALU_BITS;
1801 notanpe 119 if ( status.loop >= upd_int )
1802 chapuni 1 {
1803 notanpe 119 /*
1804 notanpe 120 ここで更新間隔のチェックをすれば、高速マシンで誤差の大きい速度表示が
1805     出るのを防げる。
1806 notanpe 119 だがそれをすると普通のマシンでムダな usec() 呼び出しをすることになる。
1807     だからやらない。決して手抜きではない。
1808     */
1809 notanpe 120 uint32_t curTime, diffTime;
1810     int a, b, c;
1811 notanpe 119
1812 notanpe 120 #ifdef SPDEBUG
1813     putchar( '\n' );
1814     printf( "mloop = %d, loop = %d\n", status.mloop, status.loop );
1815     #endif
1816     curTime = usec();
1817 notanpe 163 #ifdef SELFS
1818     if ( curTime > TIME_LIMIT ) {
1819     exit( 0 );
1820     }
1821     #endif /* SELFS */
1822 notanpe 120 diffTime = curTime - status.lastTime;
1823     b = (status.loop - status.lastloop) * 100 / diffTime;
1824 notanpe 115 status.mloop += ( status.loop / LOOP_FACTOR );
1825     status.loop %= LOOP_FACTOR;
1826 notanpe 120 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 notanpe 119 upd_int = b * UPDATE_INTERVAL;
1844 notanpe 120 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 chapuni 77 #if DEBUG>=1
1862 notanpe 119 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 chapuni 77 #endif
1875 notanpe 119 fprintf( stderr,
1876 notanpe 120 "%6dktrips/s [%6d.%03dktrips/s]\r",
1877     a, b / 1000, b % 1000 );
1878 notanpe 130 /* 魔改造 速度表示は残さない */
1879     cr = 0;
1880 chapuni 1 }
1881     }
1882    
1883     return 0;
1884     }
1885    
1886 chapuni 2 /*
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