comparison comlib/cl_imei.c @ 0:75a11d740a02

initial import of gsm-fw from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 09 Jun 2016 00:02:41 +0000
parents
children c0f2d21307d1
comparison
equal deleted inserted replaced
-1:000000000000 0:75a11d740a02
1 /*
2 +-----------------------------------------------------------------------------
3 | Project : COMLIB
4 | Modul : cl_imei.c
5 +-----------------------------------------------------------------------------
6 | Copyright 2002 Texas Instruments Berlin, AG
7 | All rights reserved.
8 |
9 | This file is confidential and a trade secret of Texas
10 | Instruments Berlin, AG
11 | The receipt of or possession of this file does not convey
12 | any rights to reproduce or disclose its contents or to
13 | manufacture, use, or sell anything it may describe, in
14 | whole, or in part, without the specific written consent of
15 | Texas Instruments Berlin, AG.
16 +-----------------------------------------------------------------------------
17 | Purpose : Definitions of common library functions: IMEI decryption with
18 DES algorithm
19 +-----------------------------------------------------------------------------
20 */
21 /*
22 * Version 1.0
23 */
24
25 /**********************************************************************************/
26
27 /*
28 NOTE:
29 */
30
31 /**********************************************************************************/
32
33 #ifndef CL_IMEI_C
34 #define CL_IMEI_C
35
36 #include "config.h"
37 #include "fixedconf.h"
38
39 #include "typedefs.h"
40 #include "vsi.h" /* to get a lot of macros */
41
42 #include "../services/ffs/ffs.h"
43 #include "../bsp/mem.h"
44 #include "pcm.h"
45
46 #include "cl_imei.h"
47 #include "cl_des.h"
48 #include <string.h>
49
50 static UBYTE stored_imei[CL_IMEI_SIZE]; /* when the imei is read once, the value
51 is stored in this buffer */
52 static UBYTE imei_flag = 0; /* this flag indicates, if IMEI was successful read
53 and is stored in the stored_imei buffer */
54
55 /* Default IMEISV for D-Sample 00440000-350-111-20 */
56 const UBYTE C_DEFAULT_IMEISV_DSAMPLE[CL_IMEI_SIZE] =
57 {0x00, 0x44, 0x00, 0x00, 0x35, 0x01, 0x11, 0x20};
58 #define CL_IMEI_FFS_PATH "/etc/IMEISV"
59
60 /*==== FUNCTIONS ==================================================*/
61
62 #if CONFIG_TARGET_PIRELLI
63 /*
64 +------------------------------------------------------------------------------
65 | Function : get_dieID
66 +------------------------------------------------------------------------------
67 | Description : the function reads the Die-ID from base band processor and
68 | extracts it from 4 BYTEs to 8 BYTEs.
69 |
70 | Parameters : inBufSize - size of buffer where to store Die ID, min.8 BYTE
71 | *outBufPtr - pointer to buffer where to store the Die ID
72 | Return : void
73 +------------------------------------------------------------------------------
74 */
75 LOCAL void get_dieID(USHORT inBufSize, UBYTE *outBufPtr)
76 {
77 int i;
78 USHORT *outBuf16 = (USHORT*)&outBufPtr[0];
79 volatile USHORT *reg_p = (USHORT *) CL_IMEI_DIE_ID_REG;
80
81 TRACE_FUNCTION("get_dieID()");
82
83 if(inBufSize < CL_IMEI_DIE_ID_SIZE){
84 TRACE_ERROR("CL IMEI ERROR: buffer size for Die ID to short!");
85 }
86 #ifdef IMEI_DEBUG
87 TRACE_EVENT_P1("CL IMEI INFO: Die-ID address(0x%x)", CL_IMEI_DIE_ID_REG);
88 #endif
89 for (i = 0; i < CL_IMEI_DIE_ID_SIZE; i++) {
90 /* Die ID is 4 BYTE long, extract it to 8 BYTE. */
91 outBuf16[i] = (USHORT)(*(UINT8*)(reg_p)++);
92 }
93 }
94
95 extern int pirelli_read_factory_record(uint32 offset, void *userbuf,
96 T_FFS_SIZE size, int has_chksum);
97
98 #define PIRELLI_IMEI_OFFSET 0x504
99
100 /*
101 +------------------------------------------------------------------------------
102 | Function : pirelli_get_imeisv
103 +------------------------------------------------------------------------------
104 | Description : This function attempts to read and decrypt a valid IMEISV
105 | record from Pirelli's factory data block.
106 |
107 | Parameters : inBufSize - size of buffer where to store IMEI, min. 8 BYTE
108 | *outBufPtr - pointer to buffer where to store the IMEI
109 | Return : 0 - OK
110 | <0 - ERROR
111 +------------------------------------------------------------------------------
112 */
113 LOCAL BYTE pirelli_get_imeisv (USHORT inBufSize, UBYTE *outBufPtr)
114 {
115 UBYTE isdid_buf[CL_IMEI_ISDID_SIZE];
116 UBYTE r_dieId[CL_DES_KEY_SIZE]; /* read Die ID */
117 UBYTE d_dieId[CL_DES_KEY_SIZE]; /* deciphered Die ID */
118 SHORT ret;
119
120 TRACE_FUNCTION("pirelli_get_imeisv()");
121
122 if(inBufSize < CL_IMEI_SIZE){
123 TRACE_ERROR("CL IMEI ERROR: buffer size for IMEI to short!");
124 return CL_IMEI_ERROR;
125 }
126
127 /*
128 * Read ISDID(enciphered IMEISV+DieID) from FFS.
129 * (changed to read from Pirelli's factory data block instead)
130 */
131 if((ret = pirelli_read_factory_record(PIRELLI_IMEI_OFFSET, isdid_buf,
132 CL_IMEI_ISDID_SIZE, 0)) >= EFFS_OK)
133 {
134 /*
135 * Read Die ID for using as DES key
136 */
137 get_dieID(CL_DES_KEY_SIZE, r_dieId);
138 /*
139 * Call DES algorithm routine
140 */
141 /* decipher first 8 BYTEs */
142 cl_des(&isdid_buf[0], r_dieId, outBufPtr, CL_DES_DECRYPTION);
143 /* decipher the rest 8 BYTEs */
144 cl_des(&isdid_buf[CL_DES_BUFFER_SIZE], r_dieId, d_dieId, CL_DES_DECRYPTION);
145 if(!memcmp(d_dieId, r_dieId, CL_DES_KEY_SIZE))
146 {
147 /* Die ID is valid */
148 ret = CL_IMEI_OK;
149 } else {/* Die ID is corrupted */
150 char pr_buf[126];
151 TRACE_ERROR("CL IMEI ERROR: Die ID is corrupted");
152 sprintf(pr_buf,"Read DieID: %02x %02x %02x %02x %02x %02x %02x %02x",
153 r_dieId[0], r_dieId[1], r_dieId[2], r_dieId[3],
154 r_dieId[4], r_dieId[5], r_dieId[6], r_dieId[7]);
155 TRACE_ERROR(pr_buf);
156 sprintf(pr_buf,"Deciphered DieID: %02x %02x %02x %02x %02x %02x %02x %02x",
157 d_dieId[0], d_dieId[1], d_dieId[2], d_dieId[3],
158 d_dieId[4], d_dieId[5], d_dieId[6], d_dieId[7]);
159 TRACE_ERROR(pr_buf);
160
161 ret = CL_IMEI_INVALID_DIE_ID;
162 }
163 } else {
164 ret = CL_IMEI_READ_IMEI_FAILED;
165 }
166
167 return ret;
168
169 }/* pirelli_get_imeisv() */
170 #endif /* CONFIG_TARGET_PIRELLI */
171
172
173 /*
174 +------------------------------------------------------------------------------
175 | Function : cl_get_imeisv
176 +------------------------------------------------------------------------------
177 | Description : Common IMEI getter function
178 |
179 | Parameters : imeiBufSize - size of buffer where to store IMEI, min 8 BYTEs
180 | *imeiBufPtr - pointer to buffer where to store the IMEI
181 | imeiType - indicates, if the IMEI should be read from
182 | FFS/Secure ROM (value=CL_IMEI_GET_SECURE_IMEI) or
183 | if the already read and stored IMEI (if available)
184 | should be delivered (value=CL_IMEI_GET_STORED_IMEI)
185 | The second option should be used only by ACI or
186 | BMI to show the IMEISV on mobile's display or
187 | in terminal window, e.g. if user calls *#06#.
188 | For IMEI Control reason (used by ACI), the value
189 | has to be CL_IMEI_CONTROL_IMEI
190 | Return : OK - 0
191 | ERROR - negative values
192 +------------------------------------------------------------------------------
193 */
194 extern BYTE cl_get_imeisv(USHORT imeiBufSize, UBYTE *imeiBufPtr, UBYTE imeiType)
195 {
196 #if CONFIG_MOKOFFS
197 USHORT ret;
198 UBYTE version;
199 UBYTE buf[SIZE_EF_IMEI];
200 #else
201 BYTE ret;
202 #endif
203
204 TRACE_FUNCTION("cl_get_imeisv()");
205
206 /*
207 * The user has required a stored IMEI. If it has been already read
208 * and stored, so return stored IMEI
209 */
210 if((imeiType == CL_IMEI_GET_STORED_IMEI) && (imei_flag == 1)){
211 memcpy(imeiBufPtr, stored_imei, CL_IMEI_SIZE);
212 return CL_IMEI_OK;
213 }
214 /*
215 * The user has required a "secure" IMEI. How we get it depends on what
216 * platform we are running on.
217 */
218
219 #if CONFIG_MOKOFFS
220 /*
221 * Running on Openmoko GTA0x and using the original FFS.
222 * Get the nibble-swapped IMEI record from PCM.
223 */
224 ret = pcm_ReadFile ((UBYTE *)EF_IMEI_ID, SIZE_EF_IMEI, buf, &version);
225 if(ret == PCM_OK){
226 TRACE_EVENT("CL IMEI INFO: return IMEI-SV number from ffs:/pcm/IMEI");
227 /*
228 * swap digits
229 */
230 imeiBufPtr[0] = ((buf[0] & 0xf0) >> 4) | ((buf[0] & 0x0f) << 4);
231 imeiBufPtr[1] = ((buf[1] & 0xf0) >> 4) | ((buf[1] & 0x0f) << 4);
232 imeiBufPtr[2] = ((buf[2] & 0xf0) >> 4) | ((buf[2] & 0x0f) << 4);
233 imeiBufPtr[3] = ((buf[3] & 0xf0) >> 4) | ((buf[3] & 0x0f) << 4);
234 imeiBufPtr[4] = ((buf[4] & 0xf0) >> 4) | ((buf[4] & 0x0f) << 4);
235 imeiBufPtr[5] = ((buf[5] & 0xf0) >> 4) | ((buf[5] & 0x0f) << 4);
236 imeiBufPtr[6] = ((buf[6] & 0xf0) >> 4) | ((buf[6] & 0x0f) << 4);
237 imeiBufPtr[7] = ((buf[7] & 0xf0) >> 4) | ((buf[7] & 0x0f) << 4);
238 /* store IMEI */
239 memcpy(stored_imei, imeiBufPtr, CL_IMEI_SIZE);
240 imei_flag = 1;
241 }else{
242 /*
243 * pcm_ReadFile() can't really fail, as it merely reads out of a
244 * RAM buffer that was filled earlier, either from FFS or from
245 * compiled-in defaults. But TI's original code had the following
246 * error handling clause, so I kept it.
247 */
248 TRACE_EVENT("CL IMEI INFO: return default IMEI-SV number");
249 memcpy(imeiBufPtr, C_DEFAULT_IMEISV_DSAMPLE, CL_IMEI_SIZE);
250 }
251 return CL_IMEI_OK;
252 #else
253
254 /*
255 * Regular FreeCalypso configuration, not MokoFFS.
256 * We try to get the IMEISV from the following sources, in this order:
257 *
258 * /etc/IMEISV (sensible nibble order, not encrypted)
259 * Pirelli's encrypted IMEI record (Pirelli target only)
260 * hard-coded fallback and error indication
261 */
262
263 if (ffs_file_read(CL_IMEI_FFS_PATH, imeiBufPtr, CL_IMEI_SIZE) >= EFFS_OK) {
264 memcpy(stored_imei, imeiBufPtr, CL_IMEI_SIZE);
265 imei_flag = 1;
266 return CL_IMEI_OK;
267 }
268 #if CONFIG_TARGET_PIRELLI
269 ret = pirelli_get_imeisv (imeiBufSize, imeiBufPtr);
270 if (ret == CL_IMEI_OK) {
271 imei_flag = 1;
272 return ret;
273 }
274 #else
275 ret = CL_IMEI_READ_IMEI_FAILED;
276 #endif
277 TRACE_ERROR("CL IMEI FATAL ERROR: IMEI not available!");
278 memcpy(imeiBufPtr, C_DEFAULT_IMEISV_DSAMPLE, CL_IMEI_SIZE);
279 return ret;
280 #endif /* CONFIG_MOKOFFS */
281 }
282
283 #endif /* CL_IMEI_C */