summaryrefslogtreecommitdiffabout
path: root/gammu/emb/gammu/depend/siemens/chiffre.c
Unidiff
Diffstat (limited to 'gammu/emb/gammu/depend/siemens/chiffre.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/gammu/depend/siemens/chiffre.c223
1 files changed, 223 insertions, 0 deletions
diff --git a/gammu/emb/gammu/depend/siemens/chiffre.c b/gammu/emb/gammu/depend/siemens/chiffre.c
new file mode 100644
index 0000000..65a06ba
--- a/dev/null
+++ b/gammu/emb/gammu/depend/siemens/chiffre.c
@@ -0,0 +1,223 @@
1/* xsiemens.c */
2/* Siemens service code generator */
3/* (C) Ivan Gorinov, 30.09.2002 */
4
5#include "chiffre.h"
6
7unsigned char key1[4] = {0x57, 0xF9, 0x3A, 0xC1}; /* Level 1 key */
8unsigned char key2[4] = {0xA4, 0xD3, 0x67, 0x9C}; /* Level 2 key */
9
10/* 4-bit substitution boxes */
11unsigned char sbox_h[0x10] =
12{0x09, 0x02, 0x04, 0x06, 0x08, 0x07, 0x05, 0x03, 0x01, 0x00,
13 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
14unsigned char sbox_l[0x10] =
15{0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
16 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
17
18unsigned char sbox[0x100]; /* 8-bit substitution box */
19
20char digit[] = "0123456789ABCDEF";
21
22/* Convert hex digit to binary value */
23int from_hex(int c)
24{
25 int i;
26
27 for(i = 0; i < 0x10; i++) if(c == digit[i]) break;
28 if (i >= 0x10) i = -1;
29 return i;
30}
31
32/* Convert binary value to string (decimal) */
33int bin2dec(char *s, int n, unsigned long l)
34{
35 int c, i, j;
36
37 j = n;
38 s[j] = 0;
39 for(i = 0; i < n; i++) {
40 c = l % 10;
41 l /= 10;
42 c = digit[c];
43 s[--j] = c;
44 }
45 return j;
46}
47
48/* Convert two 4-bit boxes to one 8-bit */
49int initbox(void)
50{
51 int i, j, k, x;
52
53 k = 0;
54 for(i = 0; i < 0x10; i++) {
55 x = sbox_h[i] << 4;
56 for(j = 0; j < 0x10; j++) {
57 sbox[k] = sbox_l[j] | x;
58 k++;
59 }
60 }
61 return 0;
62}
63
64/* Substitution */
65void subst(unsigned char *b, unsigned char *a, int n)
66{
67 int i;
68
69 for(i = 0; i < n; i++) b[i] = sbox[a[i]];
70}
71
72/* Xor N bytes with Z, inverting every odd byte */
73void xxstr(unsigned char *b, unsigned char *a, int n, int z)
74{
75 int i;
76
77 for(i = 0; i < n; i++) {
78 if(i & 1) {
79 b[i] = (~a[i]) ^ z;
80 } else {
81 b[i] = a[i] ^ z;
82 }
83 }
84}
85
86/* Encryption (1 iteration) */
87void ec_f(unsigned char *a, int n, int z)
88{
89 unsigned char bc[0x20], bs[0x10], bx[0x10];
90 int n2, i;
91
92 for(i = 0; i < n; i++) bc[i] = a[i];
93 n2 = n >> 1;
94 subst(bs, a, n2);
95 xxstr(bx, bs, n2, z);
96 for(i = 0; i < n2; i++) {
97 a[i] = bx[i] ^ bc[i+n2];
98 a[i+n2] = bc[i];
99 }
100}
101
102void ec_f_bak(unsigned char *a, int n, int z)
103{
104 unsigned char bc[0x20], bs[0x10], bx[0x10];
105 int n2, i;
106
107 n2 = n >> 1;
108 for(i = 0; i < n2; i++) bc[i+n2] = a[i];
109 subst(bs, bc + n2, n2);
110 xxstr(bx, bs, n2, z);
111 for(i = 0; i < n2; i++) bc[i] = bx[i] ^ a[i+n2];
112 for(i = 0; i < n; i++) a[i] = bc[i];
113}
114
115/* Decryption (1 iteration) */
116void dc_f(unsigned char *a, int n, int z)
117{
118 unsigned char bc[0x20], bs[0x10], bx[0x10];
119 int n2, i;
120
121 for(i = 0; i < n; i++) bc[i] = a[i];
122 n2 = n >> 1;
123 subst(bs, a + n2, n2);
124 xxstr(bx, bs, n2, z);
125 for(i = 0; i < n2; i++) {
126 a[i] = bc[i+n2];
127 a[i+n2] = bx[i] ^ bc[i];
128 }
129}
130
131/* Encryption (IMSI -> code) */
132void ss_encrypt(unsigned char *a, int n, unsigned char *key)
133{
134 int i;
135
136 for(i = 0; i < 4; i++) ec_f_bak(a, n, key[i]);
137}
138
139/* Decryption (code -> IMSI) */
140void ss_decrypt(unsigned char *a, int n, unsigned char *key)
141{
142 int i;
143
144 for(i = 0; i < 4; i++) dc_f(a, n, key[3-i]);
145}
146
147int siemens_code(char *str_imsi, char *str_code, int level)
148{
149 unsigned char array[8];
150 unsigned char xcode[8];
151 unsigned char test[8];
152 unsigned long l0, l1;
153 unsigned char *key;
154 int x, c, i, j;
155
156 if(!str_code) return -1;
157 str_code[0] = 0;
158
159 initbox();
160
161 switch(level) {
162 case 1: key = key1; break;
163 case 2: key = key2; break;
164 default: return -1;
165 }
166
167 /* Check the length of IMSI */
168 for(i = 0; i < 32; i++) if(!str_imsi[i]) break;
169 if(i == 0) return -1;
170 if(i >= 32) return -1;
171
172 /* Convert last 12 digits to 6 bytes [2-7] */
173 for(j = 7; j >= 2; j--) {
174 if (i == 0) {
175 c = 0x0F;
176 } else {
177 c = str_imsi[--i];
178 c = from_hex(c);
179 if(c < 0) return -1;
180 }
181 x = c;
182 if(i == 0) {
183 c = 0x0F;
184 } else {
185 c = str_imsi[--i];
186 c = from_hex(c);
187 if(c < 0) return -1;
188 }
189 x = (x << 4) | c;
190 array[j] = x;
191 }
192
193 /* This byte is never checked by firmware */
194 array[1] = 0;
195
196 /* Byte [0] <- checksum */
197 x = 0;
198 for(i = 1; i < 8; i++) x ^= array[i];
199 array[0] = x;
200
201 for(i = 0; i < 8; i++) xcode[i] = array[i];
202
203 /* Make the code */
204 ss_encrypt(xcode, 8, key);
205
206 /* The test */
207 for(i = 0; i < 8; i++) test[i] = xcode[i];
208 ss_decrypt(test, 8, key);
209 for(i = 0; i < 8; i++) if(test[i] != array[i]) break;
210 if(i < 8) return -1;
211
212 /* Convert to strings */
213 l0 = 0;
214 for(i = 3; i >= 0; i--) l0 = (l0 << 8) | xcode[i];
215
216 l1 = 0;
217 for(i = 7; i >= 4; i--) l1 = (l1 << 8) | xcode[i];
218
219 bin2dec(str_code, 10, l0);
220 bin2dec(str_code + 10, 10, l1);
221
222 return 0;
223}