source: proiecte/HadoopA51/docs/a5/a5-1.c @ 166

Last change on this file since 166 was 166, checked in by (none), 14 years ago

HadoopA51: imported git repository from github

File size: 10.8 KB
Line 
1#include <stdint.h>
2#include <stdlib.h>
3/*
4 * A pedagogical implementation of A5/1.
5 *
6 * Copyright (C) 1998-1999: Marc Briceno, Ian Goldberg, and David Wagner
7 *
8 * The source code below is optimized for instructional value and clarity.
9 * Performance will be terrible, but that's not the point.
10 * The algorithm is written in the C programming language to avoid ambiguities
11 * inherent to the English language. Complain to the 9th Circuit of Appeals
12 * if you have a problem with that.
13 *
14 * This software may be export-controlled by US law.
15 *
16 * This software is free for commercial and non-commercial use as long as
17 * the following conditions are aheared to.
18 * Copyright remains the authors' and as such any Copyright notices in
19 * the code are not to be removed.
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 *
24 * 1. Redistributions of source code must retain the copyright
25 *    notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 *    notice, this list of conditions and the following disclaimer in the
28 *    documentation and/or other materials provided with the distribution.
29 *
30 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 *
42 * The license and distribution terms for any publicly available version or
43 * derivative of this code cannot be changed.  i.e. this code cannot simply be
44 * copied and put under another distribution license
45 * [including the GNU Public License.]
46 *
47 * Background: The Global System for Mobile communications is the most widely
48 * deployed cellular telephony system in the world. GSM makes use of
49 * four core cryptographic algorithms, neither of which has been published by
50 * the GSM MOU. This failure to subject the algorithms to public review is all 
51 * the more puzzling given that over 100 million GSM
52 * subscribers are expected to rely on the claimed security of the system.
53 *
54 * The four core GSM algorithms are:
55 * A3           authentication algorithm
56 * A5/1         "strong" over-the-air voice-privacy algorithm
57 * A5/2         "weak" over-the-air voice-privacy algorithm
58 * A8           voice-privacy key generation algorithm
59 *
60 * In April of 1998, our group showed that COMP128, the algorithm used by the
61 * overwhelming majority of GSM providers for both A3 and A8
62 * functionality was fatally flawed and allowed for cloning of GSM mobile
63 * phones.
64 * Furthermore, we demonstrated that all A8 implementations we could locate,
65 * including the few that did not use COMP128 for key generation, had been
66 * deliberately weakened by reducing the keyspace from 64 bits to 54 bits.
67 * The remaining 10 bits are simply set to zero!
68 *
69 * See http://www.scard.org/gsm for additional information.
70 *
71 * The question so far unanswered is if A5/1, the "stronger" of the two
72 * widely deployed voice-privacy algorithm is at least as strong as the
73 * key. Meaning: "Does A5/1 have a work factor of at least 54 bits"?
74 * Absent a publicly available A5/1 reference implementation, this question
75 * could not be answered. We hope that our reference implementation below,
76 * which has been verified against official A5/1 test vectors, will provide
77 * the cryptographic community with the base on which to construct the
78 * answer to this important question.
79 *
80 * Initial indications about the strength of A5/1 are not encouraging.
81 * A variant of A5, while not A5/1 itself, has been estimated to have a
82 * work factor of well below 54 bits. See http://jya.com/crack-a5.htm for
83 * background information and references.
84 *
85 * With COMP128 broken and A5/1 published below, we will now turn our attention
86 * to A5/2. The latter has been acknowledged by the GSM community to have
87 * been specifically designed by intelligence agencies for lack of security.
88 *
89 * We hope to publish A5/2 later this year.
90 *
91 * -- Marc Briceno      <marc@scard.org>
92 *    Voice:            +1 (925) 798-4042
93 *
94 */
95
96
97#include <stdio.h>
98
99/* Masks for the three shift registers */
100#define R1MASK  0x07FFFF /* 19 bits, numbered 0..18 */
101#define R2MASK  0x3FFFFF /* 22 bits, numbered 0..21 */
102#define R3MASK  0x7FFFFF /* 23 bits, numbered 0..22 */
103
104/* Middle bit of each of the three shift registers, for clock control */
105#define R1MID   0x000100 /* bit 8 */
106#define R2MID   0x000400 /* bit 10 */
107#define R3MID   0x000400 /* bit 10 */
108
109/* Feedback taps, for clocking the shift registers.
110 * These correspond to the primitive polynomials
111 * x^19 + x^5 + x^2 + x + 1, x^22 + x + 1,
112 * and x^23 + x^15 + x^2 + x + 1. */
113#define R1TAPS  0x072000 /* bits 18,17,16,13 */
114#define R2TAPS  0x300000 /* bits 21,20 */
115#define R3TAPS  0x700080 /* bits 22,21,20,7 */
116
117/* Output taps, for output generation */
118#define R1OUT   0x040000 /* bit 18 (the high bit) */
119#define R2OUT   0x200000 /* bit 21 (the high bit) */
120#define R3OUT   0x400000 /* bit 22 (the high bit) */
121
122typedef unsigned char byte;
123typedef unsigned long word;
124typedef word bit;
125
126/* Calculate the parity of a 32-bit word, i.e. the sum of its bits modulo 2 */
127bit parity(word x) {
128        x ^= x>>16;
129        x ^= x>>8;
130        x ^= x>>4;
131        x ^= x>>2;
132        x ^= x>>1;
133        return x&1;
134}
135
136/* Clock one shift register */
137word clockone(word reg, word mask, word taps) {
138        word t = reg & taps;
139        reg = (reg << 1) & mask;
140        reg |= parity(t);
141        return reg;
142}
143
144/* The three shift registers.  They're in global variables to make the code
145 * easier to understand.
146 * A better implementation would not use global variables. */
147word R1, R2, R3;
148
149/* Look at the middle bits of R1,R2,R3, take a vote, and
150 * return the majority value of those 3 bits. */
151bit majority() {
152        int sum;
153        sum = parity(R1&R1MID) + parity(R2&R2MID) + parity(R3&R3MID);
154        if (sum >= 2)
155                return 1;
156        else
157                return 0;
158}
159
160/* Clock two or three of R1,R2,R3, with clock control
161 * according to their middle bits.
162 * Specifically, we clock Ri whenever Ri's middle bit
163 * agrees with the majority value of the three middle bits.*/
164void clock() {
165        bit maj = majority();
166        if (((R1&R1MID)!=0) == maj)
167                R1 = clockone(R1, R1MASK, R1TAPS);
168        if (((R2&R2MID)!=0) == maj)
169                R2 = clockone(R2, R2MASK, R2TAPS);
170        if (((R3&R3MID)!=0) == maj)
171                R3 = clockone(R3, R3MASK, R3TAPS);
172}
173
174/* Clock all three of R1,R2,R3, ignoring their middle bits.
175 * This is only used for key setup. */
176void clockallthree() {
177        R1 = clockone(R1, R1MASK, R1TAPS);
178        R2 = clockone(R2, R2MASK, R2TAPS);
179        R3 = clockone(R3, R3MASK, R3TAPS);
180}
181
182/* Generate an output bit from the current state.
183 * You grab a bit from each register via the output generation taps;
184 * then you XOR the resulting three bits. */
185bit getbit() {
186        return parity(R1&R1OUT)^parity(R2&R2OUT)^parity(R3&R3OUT);
187}
188
189/* Do the A5/1 key setup.  This routine accepts a 64-bit key and
190 * a 22-bit frame number. */
191void keysetup(byte key[8], word frame) {
192        int i;
193        bit keybit, framebit;
194
195        /* Zero out the shift registers. */
196        R1 = R2 = R3 = 0;
197
198        /* Load the key into the shift registers,
199         * LSB of first byte of key array first,
200         * clocking each register once for every
201         * key bit loaded.  (The usual clock
202         * control rule is temporarily disabled.) */
203        for (i=0; i<64; i++) {
204                clockallthree(); /* always clock */
205                keybit = (key[i/8] >> (i&7)) & 1; /* The i-th bit of the key */
206                R1 ^= keybit; R2 ^= keybit; R3 ^= keybit;
207        }
208
209        /* Load the frame number into the shift
210         * registers, LSB first,
211         * clocking each register once for every
212         * key bit loaded.  (The usual clock
213         * control rule is still disabled.) */
214        for (i=0; i<22; i++) {
215                clockallthree(); /* always clock */
216                framebit = (frame >> i) & 1; /* The i-th bit of the frame # */
217                R1 ^= framebit; R2 ^= framebit; R3 ^= framebit;
218        }
219
220        /* Run the shift registers for 100 clocks
221         * to mix the keying material and frame number
222         * together with output generation disabled,
223         * so that there is sufficient avalanche.
224         * We re-enable the majority-based clock control
225         * rule from now on. */
226        for (i=0; i<100; i++) {
227                clock();
228        }
229
230        /* Now the key is properly set up. */
231}
232       
233/* Generate output.  We generate 228 bits of
234 * keystream output.  The first 114 bits is for
235 * the A->B frame; the next 114 bits is for the
236 * B->A frame.  You allocate a 15-byte buffer
237 * for each direction, and this function fills
238 * it in. */
239void run(byte AtoBkeystream[], byte BtoAkeystream[]) {
240        int i;
241
242        /* Zero out the output buffers. */
243        for (i=0; i<=113/8; i++)
244                AtoBkeystream[i] = BtoAkeystream[i] = 0;
245       
246        /* Generate 114 bits of keystream for the
247         * A->B direction.  Store it, MSB first. */
248        for (i=0; i<114; i++) {
249                clock();
250                AtoBkeystream[i/8] |= getbit() << (7-(i&7));
251        }
252
253        /* Generate 114 bits of keystream for the
254         * B->A direction.  Store it, MSB first. */
255        for (i=0; i<114; i++) {
256                clock();
257                BtoAkeystream[i/8] |= getbit() << (7-(i&7));
258        }
259}
260
261/* Test the code by comparing it against
262 * a known-good test vector. */
263void test() {
264        byte key[8] = {0x12, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
265        word frame = 0x134;
266        byte goodAtoB[15] = { 0x53, 0x4E, 0xAA, 0x58, 0x2F, 0xE8, 0x15,
267                              0x1A, 0xB6, 0xE1, 0x85, 0x5A, 0x72, 0x8C, 0x00 };
268        byte goodBtoA[15] = { 0x24, 0xFD, 0x35, 0xA3, 0x5D, 0x5F, 0xB6,
269                              0x52, 0x6D, 0x32, 0xF9, 0x06, 0xDF, 0x1A, 0xC0 };
270        byte AtoB[15], BtoA[15];
271        int i, failed=0;
272
273        keysetup(key, frame);
274        uint64_t s = R1 << 23 + 22 | R2 << 23 | R3;
275        printf("%x %x %x 0x%llx\n", R1, R2, R3, s);
276        run(AtoB, BtoA);
277
278        /* Compare against the test vector. */
279        for (i=0; i<15; i++)
280                if (AtoB[i] != goodAtoB[i])
281                        failed = 1;
282        for (i=0; i<15; i++)
283                if (BtoA[i] != goodBtoA[i])
284                        failed = 1;
285
286        /* Print some debugging output. */
287        printf("key: 0x");
288        for (i=0; i<8; i++)
289                printf("%02X", key[i]);
290        printf("\n");
291        printf("frame number: 0x%06X\n", (unsigned int)frame);
292        printf("known good output:\n");
293        printf(" A->B: 0x");
294        for (i=0; i<15; i++)
295                printf("%02X", goodAtoB[i]);
296        printf("  B->A: 0x");
297        for (i=0; i<15; i++)
298                printf("%02X", goodBtoA[i]);
299        printf("\n");
300        printf("observed output:\n");
301        printf(" A->B: 0x");
302        for (i=0; i<15; i++)
303                printf("%02X", AtoB[i]);
304        printf("  B->A: 0x");
305        for (i=0; i<15; i++)
306                printf("%02X", BtoA[i]);
307        printf("\n");
308       
309        if (!failed) {
310                printf("Self-check succeeded: everything looks ok.\n");
311                return;
312        } else {
313                /* Problems!  The test vectors didn't compare*/
314                printf("\nI don't know why this broke; contact the authors.\n");
315                exit(1);
316        }
317}
318
319int main(void) {
320        test();
321        return 0;
322}
Note: See TracBrowser for help on using the repository browser.