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.c | 223 |
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 | |||
7 | unsigned char key1[4] = {0x57, 0xF9, 0x3A, 0xC1}; /* Level 1 key */ | ||
8 | unsigned char key2[4] = {0xA4, 0xD3, 0x67, 0x9C}; /* Level 2 key */ | ||
9 | |||
10 | /* 4-bit substitution boxes */ | ||
11 | unsigned char sbox_h[0x10] = | ||
12 | {0x09, 0x02, 0x04, 0x06, 0x08, 0x07, 0x05, 0x03, 0x01, 0x00, | ||
13 | 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; | ||
14 | unsigned char sbox_l[0x10] = | ||
15 | {0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, | ||
16 | 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; | ||
17 | |||
18 | unsigned char sbox[0x100]; /* 8-bit substitution box */ | ||
19 | |||
20 | char digit[] = "0123456789ABCDEF"; | ||
21 | |||
22 | /* Convert hex digit to binary value */ | ||
23 | int 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) */ | ||
33 | int 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 */ | ||
49 | int 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 */ | ||
65 | void 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 */ | ||
73 | void 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) */ | ||
87 | void 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 | |||
102 | void 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) */ | ||
116 | void 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) */ | ||
132 | void 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) */ | ||
140 | void 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 | |||
147 | int 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 | } | ||