blob: b28a8437204a34b27c829e288921b59746ce29cf [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*! \file comp128.c
2 * COMP128 v1; common/old GSM Authentication Algorithm (A3/A8).
Harald Welteec8b4502010-02-20 20:34:29 +01003 *
4 * This code is inspired by original code from :
5 * Marc Briceno <marc@scard.org>, Ian Goldberg <iang@cs.berkeley.edu>,
6 * and David Wagner <daw@cs.berkeley.edu>
7 *
8 * But it has been fully rewritten from various PDFs found online describing
9 * the algorithm because the licence of the code referenced above was unclear.
10 * A comment snippet from the original code is included below, it describes
11 * where the doc came from and how the algorithm was reverse engineered.
12 *
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020013 * This code derived from a leaked document from the GSM standards.
14 * Some missing pieces were filled in by reverse-engineering a working SIM.
15 * We have verified that this is the correct COMP128 algorithm.
Harald Welteec8b4502010-02-20 20:34:29 +010016 *
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020017 * The first page of the document identifies it as
18 *
19 * _Technical Information: GSM System Security Study_.
20 * 10-1617-01, 10th June 1988.
21 *
22 * The bottom of the title page is marked
23 *
24 * Racal Research Ltd.
25 * Worton Drive, Worton Grange Industrial Estate,
26 * Reading, Berks. RG2 0SB, England.
27 * Telephone: Reading (0734) 868601 Telex: 847152
28 *
29 * The relevant bits are in Part I, Section 20 (pages 66--67). Enjoy!
30 *
31 * Note: There are three typos in the spec (discovered by
32 * reverse-engineering).
33 * - First, "z = (2 * x[n] + x[n]) mod 2^(9-j)" should clearly read
34 * "z = (2 * x[m] + x[n]) mod 2^(9-j)".
35 * - Second, the "k" loop in the "Form bits from bytes" section is severely
36 * botched: the k index should run only from 0 to 3, and clearly the range
37 * on "the (8-k)th bit of byte j" is also off (should be 0..7, not 1..8,
38 * to be consistent with the subsequent section).
39 * - Third, SRES is taken from the first 8 nibbles of x[], not the last 8 as
40 * claimed in the document. (And the document doesn't specify how Kc is
41 * derived, but that was also easily discovered with reverse engineering.)
42 * All of these typos have been corrected in the following code.
43 */
44/*
Harald Welteec8b4502010-02-20 20:34:29 +010045 * (C) 2009 by Sylvain Munaut <tnt@246tNt.com>
46 *
47 * All Rights Reserved
48 *
Harald Weltee08da972017-11-13 01:00:26 +090049 * SPDX-License-Identifier: GPL-2.0+
50 *
Harald Welteec8b4502010-02-20 20:34:29 +010051 * This program is free software; you can redistribute it and/or modify
52 * it under the terms of the GNU General Public License as published by
53 * the Free Software Foundation; either version 2 of the License, or
54 * (at your option) any later version.
55 *
56 * This program is distributed in the hope that it will be useful,
57 * but WITHOUT ANY WARRANTY; without even the implied warranty of
58 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59 * GNU General Public License for more details.
60 *
61 * You should have received a copy of the GNU General Public License along
62 * with this program; if not, write to the Free Software Foundation, Inc.,
63 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
64 *
65 */
66
Harald Welteec8b4502010-02-20 20:34:29 +010067#include <string.h>
68#include <stdint.h>
69
Harald Welte96e2a002017-06-12 21:44:18 +020070/*! \addtogroup auth
71 * @{
Neels Hofmeyr17518fe2017-06-20 04:35:06 +020072 * \file comp128.c */
Harald Welte96e2a002017-06-12 21:44:18 +020073
Harald Welteec8b4502010-02-20 20:34:29 +010074/* The compression tables (just copied ...) */
75static const uint8_t table_0[512] = {
76 102, 177, 186, 162, 2, 156, 112, 75, 55, 25, 8, 12, 251, 193, 246, 188,
77 109, 213, 151, 53, 42, 79, 191, 115, 233, 242, 164, 223, 209, 148, 108, 161,
78 252, 37, 244, 47, 64, 211, 6, 237, 185, 160, 139, 113, 76, 138, 59, 70,
79 67, 26, 13, 157, 63, 179, 221, 30, 214, 36, 166, 69, 152, 124, 207, 116,
80 247, 194, 41, 84, 71, 1, 49, 14, 95, 35, 169, 21, 96, 78, 215, 225,
81 182, 243, 28, 92, 201, 118, 4, 74, 248, 128, 17, 11, 146, 132, 245, 48,
82 149, 90, 120, 39, 87, 230, 106, 232, 175, 19, 126, 190, 202, 141, 137, 176,
83 250, 27, 101, 40, 219, 227, 58, 20, 51, 178, 98, 216, 140, 22, 32, 121,
84 61, 103, 203, 72, 29, 110, 85, 212, 180, 204, 150, 183, 15, 66, 172, 196,
85 56, 197, 158, 0, 100, 45, 153, 7, 144, 222, 163, 167, 60, 135, 210, 231,
86 174, 165, 38, 249, 224, 34, 220, 229, 217, 208, 241, 68, 206, 189, 125, 255,
87 239, 54, 168, 89, 123, 122, 73, 145, 117, 234, 143, 99, 129, 200, 192, 82,
88 104, 170, 136, 235, 93, 81, 205, 173, 236, 94, 105, 52, 46, 228, 198, 5,
89 57, 254, 97, 155, 142, 133, 199, 171, 187, 50, 65, 181, 127, 107, 147, 226,
90 184, 218, 131, 33, 77, 86, 31, 44, 88, 62, 238, 18, 24, 43, 154, 23,
91 80, 159, 134, 111, 9, 114, 3, 91, 16, 130, 83, 10, 195, 240, 253, 119,
92 177, 102, 162, 186, 156, 2, 75, 112, 25, 55, 12, 8, 193, 251, 188, 246,
93 213, 109, 53, 151, 79, 42, 115, 191, 242, 233, 223, 164, 148, 209, 161, 108,
94 37, 252, 47, 244, 211, 64, 237, 6, 160, 185, 113, 139, 138, 76, 70, 59,
95 26, 67, 157, 13, 179, 63, 30, 221, 36, 214, 69, 166, 124, 152, 116, 207,
96 194, 247, 84, 41, 1, 71, 14, 49, 35, 95, 21, 169, 78, 96, 225, 215,
97 243, 182, 92, 28, 118, 201, 74, 4, 128, 248, 11, 17, 132, 146, 48, 245,
98 90, 149, 39, 120, 230, 87, 232, 106, 19, 175, 190, 126, 141, 202, 176, 137,
99 27, 250, 40, 101, 227, 219, 20, 58, 178, 51, 216, 98, 22, 140, 121, 32,
100 103, 61, 72, 203, 110, 29, 212, 85, 204, 180, 183, 150, 66, 15, 196, 172,
101 197, 56, 0, 158, 45, 100, 7, 153, 222, 144, 167, 163, 135, 60, 231, 210,
102 165, 174, 249, 38, 34, 224, 229, 220, 208, 217, 68, 241, 189, 206, 255, 125,
103 54, 239, 89, 168, 122, 123, 145, 73, 234, 117, 99, 143, 200, 129, 82, 192,
104 170, 104, 235, 136, 81, 93, 173, 205, 94, 236, 52, 105, 228, 46, 5, 198,
105 254, 57, 155, 97, 133, 142, 171, 199, 50, 187, 181, 65, 107, 127, 226, 147,
106 218, 184, 33, 131, 86, 77, 44, 31, 62, 88, 18, 238, 43, 24, 23, 154,
107 159, 80, 111, 134, 114, 9, 91, 3, 130, 16, 10, 83, 240, 195, 119, 253,
108}, table_1[256] = {
109 19, 11, 80, 114, 43, 1, 69, 94, 39, 18, 127, 117, 97, 3, 85, 43,
110 27, 124, 70, 83, 47, 71, 63, 10, 47, 89, 79, 4, 14, 59, 11, 5,
111 35, 107, 103, 68, 21, 86, 36, 91, 85, 126, 32, 50, 109, 94, 120, 6,
112 53, 79, 28, 45, 99, 95, 41, 34, 88, 68, 93, 55, 110, 125, 105, 20,
113 90, 80, 76, 96, 23, 60, 89, 64, 121, 56, 14, 74, 101, 8, 19, 78,
114 76, 66, 104, 46, 111, 50, 32, 3, 39, 0, 58, 25, 92, 22, 18, 51,
115 57, 65, 119, 116, 22, 109, 7, 86, 59, 93, 62, 110, 78, 99, 77, 67,
116 12, 113, 87, 98, 102, 5, 88, 33, 38, 56, 23, 8, 75, 45, 13, 75,
117 95, 63, 28, 49, 123, 120, 20, 112, 44, 30, 15, 98, 106, 2, 103, 29,
118 82, 107, 42, 124, 24, 30, 41, 16, 108, 100, 117, 40, 73, 40, 7, 114,
119 82, 115, 36, 112, 12, 102, 100, 84, 92, 48, 72, 97, 9, 54, 55, 74,
120 113, 123, 17, 26, 53, 58, 4, 9, 69, 122, 21, 118, 42, 60, 27, 73,
121 118, 125, 34, 15, 65, 115, 84, 64, 62, 81, 70, 1, 24, 111, 121, 83,
122 104, 81, 49, 127, 48, 105, 31, 10, 6, 91, 87, 37, 16, 54, 116, 126,
123 31, 38, 13, 0, 72, 106, 77, 61, 26, 67, 46, 29, 96, 37, 61, 52,
124 101, 17, 44, 108, 71, 52, 66, 57, 33, 51, 25, 90, 2, 119, 122, 35,
125}, table_2[128] = {
126 52, 50, 44, 6, 21, 49, 41, 59, 39, 51, 25, 32, 51, 47, 52, 43,
127 37, 4, 40, 34, 61, 12, 28, 4, 58, 23, 8, 15, 12, 22, 9, 18,
128 55, 10, 33, 35, 50, 1, 43, 3, 57, 13, 62, 14, 7, 42, 44, 59,
129 62, 57, 27, 6, 8, 31, 26, 54, 41, 22, 45, 20, 39, 3, 16, 56,
130 48, 2, 21, 28, 36, 42, 60, 33, 34, 18, 0, 11, 24, 10, 17, 61,
131 29, 14, 45, 26, 55, 46, 11, 17, 54, 46, 9, 24, 30, 60, 32, 0,
132 20, 38, 2, 30, 58, 35, 1, 16, 56, 40, 23, 48, 13, 19, 19, 27,
133 31, 53, 47, 38, 63, 15, 49, 5, 37, 53, 25, 36, 63, 29, 5, 7,
134}, table_3[64] = {
135 1, 5, 29, 6, 25, 1, 18, 23, 17, 19, 0, 9, 24, 25, 6, 31,
136 28, 20, 24, 30, 4, 27, 3, 13, 15, 16, 14, 18, 4, 3, 8, 9,
137 20, 0, 12, 26, 21, 8, 28, 2, 29, 2, 15, 7, 11, 22, 14, 10,
138 17, 21, 12, 30, 26, 27, 16, 31, 11, 7, 13, 23, 10, 5, 22, 19,
139}, table_4[32] = {
140 15, 12, 10, 4, 1, 14, 11, 7, 5, 0, 14, 7, 1, 2, 13, 8,
141 10, 3, 4, 9, 6, 0, 3, 2, 5, 6, 8, 9, 11, 13, 15, 12,
142};
143
144static const uint8_t *_comp128_table[5] = { table_0, table_1, table_2, table_3, table_4 };
145
146
147static inline void
148_comp128_compression_round(uint8_t *x, int n, const uint8_t *tbl)
149{
150 int i, j, m, a, b, y, z;
151 m = 4 - n;
152 for (i=0; i<(1<<n); i++)
153 for (j=0; j<(1<<m); j++) {
154 a = j + i * (2<<m);
155 b = a + (1<<m);
156 y = (x[a] + (x[b]<<1)) & ((32<<m)-1);
157 z = ((x[a]<<1) + x[b]) & ((32<<m)-1);
158 x[a] = tbl[y];
159 x[b] = tbl[z];
160 }
161}
162
163static inline void
164_comp128_compression(uint8_t *x)
165{
166 int n;
167 for (n=0; n<5; n++)
168 _comp128_compression_round(x, n, _comp128_table[n]);
169}
170
171static inline void
172_comp128_bitsfrombytes(uint8_t *x, uint8_t *bits)
173{
174 int i;
175 memset(bits, 0x00, 128);
176 for (i=0; i<128; i++)
177 if (x[i>>2] & (1<<(3-(i&3))))
178 bits[i] = 1;
179}
180
181static inline void
182_comp128_permutation(uint8_t *x, uint8_t *bits)
183{
184 int i;
185 memset(&x[16], 0x00, 16);
186 for (i=0; i<128; i++)
187 x[(i>>3)+16] |= bits[(i*17) & 127] << (7-(i&7));
188}
189
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200190/*! Perform COMP128v1 algorithm
Harald Welte96e2a002017-06-12 21:44:18 +0200191 * \param[in] ki Secret Key K(i) of subscriber
192 * \param[in] rand Random Challenge
193 * \param[out] sres user-supplied buffer for storing computed SRES value
194 * \param[out] kc user-supplied buffer for storing computed Kc value */
Harald Welteec8b4502010-02-20 20:34:29 +0100195void
Max1f9d8182016-04-21 17:12:40 +0200196comp128v1(const uint8_t *ki, const uint8_t *rand, uint8_t *sres, uint8_t *kc)
Harald Welteec8b4502010-02-20 20:34:29 +0100197{
198 int i;
199 uint8_t x[32], bits[128];
200
201 /* x[16-31] = RAND */
202 memcpy(&x[16], rand, 16);
203
204 /* Round 1-7 */
205 for (i=0; i<7; i++) {
206 /* x[0-15] = Ki */
207 memcpy(x, ki, 16);
208
209 /* Compression */
210 _comp128_compression(x);
211
212 /* FormBitFromBytes */
213 _comp128_bitsfrombytes(x, bits);
214
215 /* Permutation */
216 _comp128_permutation(x, bits);
217 }
218
219 /* Round 8 (final) */
220 /* x[0-15] = Ki */
221 memcpy(x, ki, 16);
222
223 /* Compression */
224 _comp128_compression(x);
225
226 /* Output stage */
227 for (i=0; i<8; i+=2)
228 sres[i>>1] = x[i]<<4 | x[i+1];
229
230 for (i=0; i<12; i+=2)
231 kc[i>>1] = (x[i + 18] << 6) |
232 (x[i + 19] << 2) |
233 (x[i + 20] >> 2);
234
235 kc[6] = (x[30]<<6) | (x[31]<<2);
236 kc[7] = 0;
237}
238
Harald Welte96e2a002017-06-12 21:44:18 +0200239
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200240/*! Perform COMP128v1 algorithm
Harald Welte96e2a002017-06-12 21:44:18 +0200241 * \param[in] ki Secret Key K(i) of subscriber
242 * \param[in] rand Random Challenge
243 * \param[out] sres user-supplied buffer for storing computed SRES value
244 * \param[out] kc user-supplied buffer for storing computed Kc value */
Max1f9d8182016-04-21 17:12:40 +0200245void
246comp128(const uint8_t *ki, const uint8_t *rand, uint8_t *sres, uint8_t *kc)
247{
248 comp128v1(ki, rand, sres, kc);
249}
Harald Welte96e2a002017-06-12 21:44:18 +0200250
251/*! @} */