root/tinkering/A5Util/a5faster.cpp

Revision 191, 6.3 KB (checked in by frank, 6 weeks ago)

Keep up the changes.

Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <iostream>
4
5#include "Bidirectional.h"
6#include "SSDlookup.h"
7#include "../a5_cpu/A5CpuStubs.h"
8
9#include <map>
10#include <assert.h>
11
12
13static uint64_t kr02_whitening(uint64_t key)
14{
15    int i;
16    uint64_t white = 0;
17    uint64_t bits = 0x93cbc4077efddc15ULL;
18    uint64_t b = 0x1;
19    while (b) {
20        if (b & key) {
21            white ^= bits;
22        }
23        bits = (bits<<1)|(bits>>63);
24        b = b << 1;
25    }
26    return white;
27}
28
29static uint64_t kr02_mergebits(uint64_t key)
30{
31    uint64_t r = 0ULL;
32    uint64_t b = 1ULL;
33    unsigned int i;
34
35    for(i=0;i<64;i++) {
36        if (key&b) {
37            r |= 1ULL << (((i<<1)&0x3e)|(i>>5));
38        }
39        b = b << 1;
40    }
41    return r;
42}
43
44void ApplyIndexFunc(uint64_t& start_index, int bits)
45{
46    uint64_t w = kr02_whitening(start_index);
47    start_index = kr02_mergebits((w<<bits)|start_index);
48}
49
50
51int main(int argc, char* argv[] )
52{
53    unsigned char cipherstream[15];
54
55    if (argc<5) {
56        printf("usage %s challenge.file id index.file device\n", argv[0]);
57        return 0;
58    }
59
60    int id = atoi(argv[2]);
61
62    FILE* fd = fopen(argv[1], "rb");
63   
64    if (fd==NULL) {
65        printf("Could not open %s for reading.\n", argv[1]);
66    }
67
68    SSDlookup tl(argv[3],argv[4]);
69    Bidirectional back;
70
71    printf("Table id is %i\n", id );
72    /* Last argument is number of CPU cores to use */
73    A5CpuInit(8, 12, 4);
74
75    std::map<uint64_t, uint32_t> searches;
76    std::map<uint64_t, uint32_t> search_count;
77    std::map<uint64_t, uint32_t>::iterator it;
78    std::map<uint64_t, uint64_t>::iterator it2;
79    std::map<uint64_t, uint32_t>::iterator it3;
80    std::map<uint64_t,uint32_t> framemap;
81    std::map<uint64_t,uint64_t> ciphermap;
82
83    int frameno = 0;
84    int remain = 0;
85    int keysearch = 0;
86
87    for(;;) {
88        uint64_t cipher;
89
90        size_t num = fread(cipherstream, sizeof(unsigned char), 15, fd );
91        if (num!=15) break;  // EOF
92        frameno++;
93
94        // if (frameno<9958) continue;
95        // if (frameno>5) break;
96
97        for(int i=0; i<8; i++) {
98            cipher = (cipher << 8) | cipherstream[i];
99        }
100        int nextbit = 64;
101
102
103        /**
104         * NB there are 51 possible states to examine
105         * but we only do 50 for consistent coverage
106         * figures. ( 50 can be changed to 51 fo 2%
107         * better chance of key recovery)
108         */
109        for(int i=0; i<51; i++) {
110            // std::cout << std::hex << "Looking at " << cipher << "\n";
111            uint64_t rev = Bidirectional::ReverseBits( cipher );
112
113            for(int j =0; j < 8; j++) {
114                A5CpuSubmit(rev, j, id, NULL);
115                remain++;
116            }
117            it = framemap.find(rev);
118            assert(it==framemap.end());
119            framemap[rev] = frameno*8*64+i*8+7;
120            ciphermap[rev] = cipher;
121
122            unsigned char bit = cipherstream[nextbit/8];
123
124            bit = (bit>>(7-(nextbit&0x07))) & 0x01;
125            cipher = (cipher << 1) | bit;
126           
127            nextbit++;
128            fflush(stdout);
129        }
130    }
131
132    int numseeks = 0;
133    printf("Churning the cipher.\n");
134
135    while( (remain+keysearch) > 0 ) {
136        uint64_t result;
137        uint64_t dummy;
138        uint64_t stop_val;
139        int start_rnd;
140        if (A5CpuPopResult(dummy, stop_val, start_rnd, NULL)) {
141            it = searches.find( dummy );
142            if (it != searches.end() ) {
143                /* This was a keysearch that was issued */
144                keysearch--;
145                frameno = (it->second)/8;
146                int i = frameno&0x3f;
147                frameno = frameno/64;
148                if (start_rnd<0) {
149                    stop_val = Bidirectional::ReverseBits(stop_val);
150                    printf("#### Found potential key (bits: %i)####\n", i);
151                    std::cout << std::hex << stop_val << "\n";
152                    printf("#### Stepping back to mix ####\n");
153                    stop_val = back.Forwards(stop_val, 100, NULL);
154                    back.ClockBack( stop_val, 100+i );
155                    printf("### Frame is %i ###\n", frameno);
156                }
157                it3 = search_count.find(dummy);
158                assert(it3!=search_count.end());
159                int count = it3->second - 1;
160                if (count) {
161                    it3->second = count;
162                } else {
163                    search_count.erase(it3);
164                    searches.erase(it);
165                }
166            } else {
167                /* End point, do table lookup */
168                // std::cout << std::hex << "check " << stop_val << "\n";
169                int hits = tl.FindEndpoint(stop_val);
170                it = framemap.find(dummy);
171                it2 = ciphermap.find(dummy);
172                assert(it2!=ciphermap.end());
173                assert(it!=framemap.end());
174                numseeks++;
175                uint32_t cnt = (it->second&0x07) - 1;
176                if (cnt<0) {
177                    framemap.erase(it);
178                } else {
179                    it->second = (it->second & 0xfffffff8) + cnt;
180                }
181                if (hits) {
182                    for (int j=0;j<hits; j++) {
183                        uint64_t start_search;
184                        tl.PopResult(start_search);
185                        /* Issue a new keysearch */
186                        uint64_t search_rev = start_search;
187                        ApplyIndexFunc(search_rev, 34);
188                        A5CpuKeySearch(search_rev, it2->second, 0, 8, id, NULL );
189                        searches[search_rev] = it->second;
190                        it = framemap.find(search_rev);
191                        assert(it==framemap.end());
192                        /* Keep track of how many searches are issued for this
193                         * piece of plaintext. */
194                        it = search_count.find( search_rev );
195                        if (it!=search_count.end()) {
196                            int count = it->second;
197                            it->second = count + 1;
198                        } else {
199                            search_count[search_rev] = 1;
200                        }
201                        keysearch++;
202                    }
203                }
204                remain--;
205            }
206        }
207        usleep(1000);
208    }
209
210    // printf("%i seeks to disk performed\n",numseeks);
211
212    fclose(fd);
213}
Note: See TracBrowser for help on using the browser.