FreeCalypso > hg > tcs211-l1-reconst
comparison g23m/condat/com/src/comlib/sec_drv.c @ 0:509db1a7b7b8
initial import: leo2moko-r1
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 01 Jun 2015 03:24:05 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:509db1a7b7b8 |
---|---|
1 #include "general.h" | |
2 #include "typedefs.h" | |
3 #include "vsi.h" | |
4 #include <stdlib.h> | |
5 #include <string.h> | |
6 #include "sec_drv.h" | |
7 #include "sec_drv_prim.h" | |
8 | |
9 #ifdef FIRSTBOOT_ENABLED | |
10 #include "sec_firstboot.h" | |
11 #endif | |
12 | |
13 | |
14 #define UNLOCKED(status) ((status==SEC_DRV_CAT_STAT_Unlocked)||(status==SEC_DRV_CAT_STAT_PermUnlocked)) | |
15 | |
16 | |
17 /** | |
18 * Resets the phone. | |
19 */ | |
20 static void reset(void) | |
21 { | |
22 UINT16 i; | |
23 | |
24 TRACE("** RESET **"); | |
25 // Setup watchdog timer and let it timeout to make a reset | |
26 *(volatile UINT16*) 0xfffff804 = 0xFFFF; // Timer to watchdog | |
27 *(volatile UINT16*) 0xfffff800 = 0x0080; // Start timer | |
28 // Apparently works it only if we read this register? | |
29 i = *(volatile UINT16*) 0xfffff802; | |
30 *(volatile UINT16*) 0xfffff802 = 0x0001; // Load timer | |
31 } | |
32 | |
33 | |
34 /** | |
35 * Check whether or not we have valid lock data in the flash-area | |
36 * Run first_boot if we've got data, but its not initialized. | |
37 * | |
38 * @param pNumCategories Pointer to UINT8 where the number of | |
39 * categories will be stored. | |
40 * @return SEC_DRV_RET_Ok if theres valid data in the secure area. | |
41 */ | |
42 static T_SEC_DRV_RETURN check_hdr(UINT8 *pNumCategories) | |
43 { | |
44 T_SEC_DRV_RETURN result = SEC_DRV_RET_Ok; | |
45 T_SEC_DRV_GLOBAL_CONF hdr; | |
46 | |
47 TRACE("check_hdr"); | |
48 if (sec_prim_get_global_conf(&hdr)) | |
49 { | |
50 switch (hdr.firstboot_pattern) | |
51 { | |
52 case SEC_PATTERN_INITIALIZED: | |
53 /* Secure area seems to be initialized OK */ | |
54 result = SEC_DRV_RET_Ok; | |
55 if (pNumCategories) | |
56 { | |
57 T_SEC_DRV_CONFIGURATION conf; | |
58 sec_prim_get_configuration(&conf); | |
59 *pNumCategories = conf.NumCategories; | |
60 } | |
61 TRACE("check_hdr - OK"); | |
62 break; | |
63 case SEC_PATTERN_UNINITIALIZED: | |
64 /* We've got new data in the secure area that needs to be processed */ | |
65 #ifdef FIRSTBOOT_ENABLED | |
66 first_boot(); | |
67 #endif | |
68 result = SEC_DRV_RET_NotPresent; | |
69 TRACE("check_hdr - uninitialized"); | |
70 reset(); | |
71 break; | |
72 default: | |
73 /* Secure area seems to contain void data! */ | |
74 result = SEC_DRV_RET_NotPresent; | |
75 if (pNumCategories) *pNumCategories = 0; | |
76 TRACE("check_hdr - void data"); | |
77 break; | |
78 } | |
79 } | |
80 else | |
81 { | |
82 result = SEC_DRV_RET_NotPresent; | |
83 TRACE("check_hdr - void!!!"); | |
84 } | |
85 return result; | |
86 } | |
87 | |
88 | |
89 /** | |
90 * Check if a counter is exceeded. | |
91 * | |
92 * @param pCount Pointer to current value - max value must follow immediately before! | |
93 * @return TRUE if the failure counter has been exceeded | |
94 */ | |
95 static BOOL Counter_Exceeded(UINT8 *pCount) | |
96 { | |
97 pCount--; | |
98 return ((pCount[0] != 0xFF) && (pCount[1] >= pCount[0])); | |
99 } | |
100 | |
101 | |
102 /** | |
103 * Increment a counter if needed. | |
104 * | |
105 * @param pCount Pointer to the counter | |
106 */ | |
107 static void Counter_Increment(UINT8 *pCount) | |
108 { | |
109 if ((*pCount) < 0xFF) | |
110 { | |
111 (*pCount)++; | |
112 } | |
113 } | |
114 | |
115 | |
116 /** | |
117 * Check whether or not a given key-len is ok according to its category. | |
118 * | |
119 * @param rec_num The record number to check the key_length against. | |
120 * @param key_len The key length to check. | |
121 * @return TRUE if the key_len is within specifications for the given | |
122 * record (category) - otherwise FALSE. | |
123 */ | |
124 static BOOL check_key_len(int rec_num, UINT8 key_len) | |
125 { | |
126 if (key_len > SEC_DRV_KEY_MAX_LEN) return FALSE; | |
127 if ((rec_num == SEC_DRV_CAT_NUM_SIM) && (key_len < 6)) return FALSE; | |
128 if ((rec_num != SEC_DRV_CAT_NUM_SIM) && (key_len < 8)) return FALSE; | |
129 return TRUE; | |
130 } | |
131 | |
132 | |
133 /** | |
134 * Transform an unlock key into a special lock key - for use by the | |
135 * non-ETSI lock algorithm. | |
136 * | |
137 * @param pKey Pointer to a key to transform. This also serves as the output | |
138 * buffer. Must be '\0' terminated if shorter than SEC_DRV_KEY_MAX_LEN | |
139 */ | |
140 void calculate_spec_lock_key(char *pKey) | |
141 { | |
142 int len=0; | |
143 int index; | |
144 | |
145 while((len<SEC_DRV_KEY_MAX_LEN) && (pKey[len])) len++; | |
146 len = len & 0xFE; | |
147 for(index=0; index<len; index+=2) | |
148 { | |
149 char ch; | |
150 ch = pKey[index]; | |
151 pKey[index] = pKey[index+1]; | |
152 pKey[index+1] = ch; | |
153 } | |
154 } | |
155 | |
156 | |
157 /** | |
158 * Compare 2 keys up to key_len characters, given the length constraints implied | |
159 * by the category number and check_key_len(). | |
160 * | |
161 * @param rec_num The category number to use when validating key_len. | |
162 * @param pRefKey Pointer to the key to use as reference (origin). | |
163 * @param pKey Pointer to the key to compare against pRefKey. | |
164 * @param key_len The maximum number of chars to use in the compare or 0 (to use all). | |
165 * @return SEC_DRV_RET_KeyWrong if the length constraints are violated, SEC_DRV_RET_Ok | |
166 * if the keys match, otherwise SEC_DRV_RET_KeyMismatch. | |
167 */ | |
168 static T_SEC_DRV_RETURN compare_keys(int rec_num, const char *pRefKey, const char *pKey, UINT8 key_len) | |
169 { | |
170 if (pRefKey[0] == '\0') | |
171 { | |
172 TRACE("compare_keys - old key not present"); | |
173 return SEC_DRV_RET_Ok; | |
174 } | |
175 | |
176 if (key_len == 0) | |
177 { | |
178 /* compare using full length of the keys -> | |
179 to '\0' termination or max SEC_DRV_KEY_MAX_LEN chars... | |
180 whichever comes first */ | |
181 key_len = SEC_DRV_KEY_MAX_LEN; | |
182 } | |
183 /* compare using the specified number of chars */ | |
184 if (!check_key_len(rec_num, key_len) || (pKey==0L) || (pKey[0]=='\0')) return SEC_DRV_RET_KeyWrong; | |
185 return (strncmp(pRefKey, pKey, key_len)==0)? SEC_DRV_RET_Ok : SEC_DRV_RET_KeyMismatch; | |
186 } | |
187 | |
188 | |
189 /** | |
190 * Try to set a new key on a specific category. For this to happen, the new key must | |
191 * meet the length constraints implied by the category, and the current category key | |
192 * must match the given oldkey within the key_len chars (again, remember length | |
193 * constraints). | |
194 * | |
195 * @param rec_num The category number for which to set the key. | |
196 * @param pOldKey Key to compare against current category key. The 2 must match | |
197 * for the new key to be set. | |
198 * @param pNewKey Key to set the category to, if possible. | |
199 * @param key_len Length to use when comparing keys, see check_key_len(). | |
200 * @return SEC_DRV_RET_Ok if the key could be set. | |
201 */ | |
202 static T_SEC_DRV_RETURN set_key(T_SEC_DRV_CONFIGURATION *pConf, int rec_num, const char *pOldKey, const char *pNewKey, UINT8 key_len) | |
203 { | |
204 T_SEC_DRV_RETURN result; | |
205 T_SEC_DRV_KEY key; | |
206 if (sec_prim_get_key(rec_num, &key)) | |
207 { | |
208 result = compare_keys(rec_num, (char *)key.digit, pOldKey, key_len); | |
209 if (result == SEC_DRV_RET_Ok) | |
210 { | |
211 int len = strlen(pNewKey); | |
212 if (check_key_len(rec_num, len)) | |
213 { | |
214 len++; /* convert len into a size! */ | |
215 if (len > SEC_DRV_KEY_MAX_LEN) len = SEC_DRV_KEY_MAX_LEN; | |
216 memcpy(key.digit, pNewKey, len); | |
217 sec_prim_set_key(rec_num, &key); | |
218 } | |
219 else | |
220 { | |
221 /* key must be within specified length according to category */ | |
222 result = SEC_DRV_RET_KeyWrong; | |
223 } | |
224 } | |
225 else | |
226 { | |
227 Counter_Increment(&pConf->FC_Current); | |
228 sec_prim_set_configuration(pConf); | |
229 } | |
230 } | |
231 else | |
232 { | |
233 result = SEC_DRV_RET_NotPresent; | |
234 } | |
235 return result; | |
236 } | |
237 | |
238 | |
239 /** | |
240 * Update all dependant categories. Scanning through a categories dependants, | |
241 * set their status and key if needed. | |
242 * | |
243 * @param pCatHdr Pointer to the category header for the parent category. | |
244 * @param pCatKey Pointer to the key for the parent category. | |
245 */ | |
246 static void update_dependants(const T_SEC_DRV_CAT_HDR *pCatHdr, const T_SEC_DRV_KEY *pCatKey, UINT16 dependMask) | |
247 { | |
248 int dependentCat = 0; | |
249 int dependentBit = 1; | |
250 | |
251 for (; dependentCat<(sizeof(pCatHdr->Dependency)*8); dependentCat++) | |
252 { | |
253 if (pCatHdr->Dependency & dependentBit & dependMask) | |
254 { | |
255 { | |
256 /* set key on dependant iff not already done, and parent has a key */ | |
257 T_SEC_DRV_KEY dependentKey; | |
258 if (sec_prim_get_key(dependentCat, &dependentKey)) | |
259 { | |
260 if (pCatKey->digit[0] != '\0' && dependentKey.digit[0] == '\0') | |
261 { | |
262 sec_prim_set_key(dependentCat, pCatKey); | |
263 } | |
264 } | |
265 } | |
266 { | |
267 /* update status on dependant */ | |
268 T_SEC_DRV_CAT_HDR dependentHdr; | |
269 if (sec_prim_get_cat_header(dependentCat, &dependentHdr)) | |
270 { | |
271 if (dependentHdr.Status != SEC_DRV_CAT_STAT_PermUnlocked) | |
272 { | |
273 dependentHdr.Status = pCatHdr->Status; | |
274 sec_prim_set_cat_header(dependentCat, &dependentHdr); | |
275 } | |
276 } | |
277 } | |
278 } | |
279 dependentBit = dependentBit<<1; | |
280 } | |
281 } | |
282 | |
283 | |
284 /** | |
285 * Get the MEPD configuration. | |
286 * | |
287 * @param ppConfiguration Pointer to pointer where the configuration is stored. | |
288 * @return SEC_DRV_RET_Ok if the configuration could be read. | |
289 */ | |
290 T_SEC_DRV_RETURN sec_get_CFG(T_SEC_DRV_CONFIGURATION **ppConfiguration) | |
291 { | |
292 T_SEC_DRV_RETURN result = check_hdr(0L); | |
293 if (result == SEC_DRV_RET_Ok) | |
294 { | |
295 *ppConfiguration = (T_SEC_DRV_CONFIGURATION *)M_ALLOC(sizeof(T_SEC_DRV_CONFIGURATION)); | |
296 sec_prim_get_configuration(*ppConfiguration); | |
297 } | |
298 else | |
299 { | |
300 *ppConfiguration = 0L; | |
301 } | |
302 return result; | |
303 } | |
304 | |
305 | |
306 /** | |
307 * Compare a key against the one stored for a given category. | |
308 * | |
309 * @param rec_num The category number for which to check the key. | |
310 * @param pKey The key to compare. | |
311 * @param key_len The length of the keys to use in the compare. Subject to constraints. | |
312 * @return SEC_DRV_RET_Ok if the keys match | |
313 */ | |
314 T_SEC_DRV_RETURN sec_cmp_KEY (UINT8 rec_num, const char *pKey, UINT8 key_len) | |
315 { | |
316 T_SEC_DRV_KEY refKey; | |
317 T_SEC_DRV_CONFIGURATION conf; | |
318 UINT8 numCategories=0; | |
319 T_SEC_DRV_RETURN result = check_hdr(&numCategories); | |
320 if (result != SEC_DRV_RET_Ok) | |
321 { | |
322 /* data not present in secure area! */ | |
323 return result; | |
324 } | |
325 | |
326 sec_prim_get_configuration(&conf); | |
327 if (Counter_Exceeded(&conf.FC_Current)) | |
328 { | |
329 result = SEC_DRV_RET_FCExeeded; | |
330 } | |
331 else if (conf.Flags & SEC_DRV_HDR_FLAG_LAM_Unlock) | |
332 { | |
333 result = SEC_DRV_RET_Unknown; | |
334 } | |
335 else if (sec_prim_get_key(rec_num, &refKey)) | |
336 { | |
337 result = compare_keys(rec_num, (char *)refKey.digit, pKey, key_len); | |
338 } | |
339 else | |
340 { | |
341 /* requested data outside configured categories! */ | |
342 result = SEC_DRV_RET_NotPresent; | |
343 } | |
344 return result; | |
345 } | |
346 | |
347 | |
348 /** | |
349 * Try to set a key for a given category. The category must be unlocked prior | |
350 * to this attempt. | |
351 * | |
352 * @param rec_num Category number whoose key should be set. | |
353 * @param pOldKey pointer to current key of the category (or rather what the | |
354 * client believes to be the current key). | |
355 * @param pNewKey Pointer to the key that should be set. | |
356 * @param key_len length to use during key-comparision. | |
357 * @return SEC_DRV_RET_Ok if the key could be set. | |
358 */ | |
359 T_SEC_DRV_RETURN sec_set_KEY (UINT8 rec_num, const char *pOldKey, const char *pNewKey, UINT8 key_len) | |
360 { | |
361 T_SEC_DRV_CONFIGURATION conf; | |
362 UINT8 numCategories=0; | |
363 T_SEC_DRV_CAT_HDR catHdr; | |
364 T_SEC_DRV_RETURN result = check_hdr(&numCategories); | |
365 if (result != SEC_DRV_RET_Ok) | |
366 { | |
367 /* data not present in secure area! */ | |
368 return result; | |
369 } | |
370 | |
371 sec_prim_get_configuration(&conf); | |
372 if (Counter_Exceeded(&conf.FC_Current)) | |
373 { | |
374 result = SEC_DRV_RET_FCExeeded; | |
375 } | |
376 else if (sec_prim_get_cat_header(rec_num, &catHdr)) | |
377 { | |
378 if (UNLOCKED(catHdr.Status) && !(conf.Flags & SEC_DRV_HDR_FLAG_LAM_Unlock)) | |
379 { | |
380 result = set_key(&conf, rec_num, pOldKey, pNewKey, key_len); | |
381 } | |
382 else | |
383 { | |
384 /* category must be unlocked prior to setting a key */ | |
385 result = SEC_DRV_RET_Unknown; | |
386 } | |
387 } | |
388 else | |
389 { | |
390 /* requested data outside configured categories! */ | |
391 result = SEC_DRV_RET_NotPresent; | |
392 } | |
393 return result; | |
394 } | |
395 | |
396 | |
397 /** | |
398 * Set the key for tha failure counter. | |
399 * | |
400 * @param pOldKey The current failure count key. Must match that stored in the | |
401 * secure area for the new key to be set. | |
402 * @param pNewKey The new key to set for the failure counter. | |
403 * @return SEC_DRV_RET_Ok if the key could be set. | |
404 */ | |
405 T_SEC_DRV_RETURN sec_set_FC_KEY (const char *pOldKey, const char *pNewKey) | |
406 { | |
407 T_SEC_DRV_CONFIGURATION conf; | |
408 T_SEC_DRV_RETURN result = check_hdr(0L); | |
409 if (result != SEC_DRV_RET_Ok) | |
410 { | |
411 /* data not present in secure area! */ | |
412 return result; | |
413 } | |
414 | |
415 sec_prim_get_configuration(&conf); | |
416 if (Counter_Exceeded(&conf.FC_Current)) | |
417 { | |
418 result = SEC_DRV_RET_FCExeeded; | |
419 } | |
420 else | |
421 { | |
422 result = set_key(&conf, -1, pOldKey, pNewKey, 0); | |
423 } | |
424 return result; | |
425 } | |
426 | |
427 | |
428 /** | |
429 * Get the record data (both header and body) for a given category. | |
430 * | |
431 * @param rec_num The category number to get the data for. | |
432 * @param ppCategory Pointer to where the result pointer should be stored. | |
433 * @return SEC_DRV_RET_Ok if the record data could be read. | |
434 */ | |
435 T_SEC_DRV_RETURN sec_get_REC (UINT8 rec_num, T_SEC_DRV_CATEGORY **ppCategory) | |
436 { | |
437 UINT8 numCategories=0; | |
438 T_SEC_DRV_RETURN result = check_hdr(&numCategories); | |
439 if (result != SEC_DRV_RET_Ok) | |
440 { | |
441 /* data not present in secure area! */ | |
442 *ppCategory = 0L; | |
443 return result; | |
444 } | |
445 | |
446 if (rec_num < numCategories) | |
447 { | |
448 *ppCategory = (T_SEC_DRV_CATEGORY *)M_ALLOC(sizeof(T_SEC_DRV_CATEGORY)); | |
449 sec_prim_get_cat_header(rec_num, &(*ppCategory)->Header); | |
450 if ((*ppCategory)->Header.DataLen) | |
451 { | |
452 (*ppCategory)->pBody = M_ALLOC((*ppCategory)->Header.DataLen); | |
453 sec_prim_get_cat_body(rec_num, (*ppCategory)->pBody, (*ppCategory)->Header.DataLen); | |
454 } | |
455 else | |
456 { | |
457 (*ppCategory)->pBody = 0L; | |
458 } | |
459 result = SEC_DRV_RET_Ok; | |
460 } | |
461 else | |
462 { | |
463 /* requested data outside configured categories! */ | |
464 *ppCategory = 0L; | |
465 result = SEC_DRV_RET_NotPresent; | |
466 } | |
467 return result; | |
468 } | |
469 | |
470 | |
471 /** | |
472 * Set the body part of a category's data. The data can only be set if the | |
473 * category is unlocked. | |
474 * | |
475 * @param rec_num Category number whose body part should be set. | |
476 * @param pBody Pointer to the body data that should be stored. | |
477 * @return SEC_DRV_RET_Ok if the data could be stored. | |
478 */ | |
479 T_SEC_DRV_RETURN sec_set_REC (UINT8 rec_num, const T_SEC_DRV_CATEGORY *pCategory) | |
480 { | |
481 T_SEC_DRV_CAT_HDR header; | |
482 UINT8 numCategories=0; | |
483 T_SEC_DRV_RETURN result = check_hdr(&numCategories); | |
484 if (result != SEC_DRV_RET_Ok) | |
485 { | |
486 /* data not present in secure area! */ | |
487 return result; | |
488 } | |
489 | |
490 if (sec_prim_get_cat_header(rec_num, &header)) | |
491 { | |
492 if (header.Status == SEC_DRV_CAT_STAT_Unlocked || | |
493 header.Status == SEC_DRV_CAT_STAT_PermUnlocked) | |
494 { | |
495 sec_prim_set_cat_body(rec_num, pCategory->pBody, pCategory->Header.DataLen); | |
496 result = SEC_DRV_RET_Ok; | |
497 } | |
498 else | |
499 { | |
500 /* Category must be unlocked in order to write record data */ | |
501 result = SEC_DRV_RET_Unknown; | |
502 } | |
503 } | |
504 else | |
505 { | |
506 /* requested data outside configured categories! */ | |
507 result = SEC_DRV_RET_NotPresent; | |
508 } | |
509 return result; | |
510 } | |
511 | |
512 | |
513 /** | |
514 * Try to unlock a category. Failure count must not have been exeeded, NAM unlock | |
515 * must not be set and the category must not be linklocked. Also the given key | |
516 * must match the stored key for the category before it is unlocked. | |
517 * | |
518 * @param rec_num Category number that should be unlocked. | |
519 * @param pKey Key that should match the stored category key. | |
520 * @param key_len The maximum number of chars to use in the compare or 0 (to use all). | |
521 * @return SEC_DRV_RET_Ok if the category could be unlocked. | |
522 */ | |
523 T_SEC_DRV_RETURN sec_rec_Unlock (UINT8 rec_num, T_SEC_DRV_UNLOCK_TYPE unlockType, const char *pKey, UINT8 key_len, UINT16 dependMask) | |
524 { | |
525 T_SEC_DRV_CONFIGURATION conf; | |
526 T_SEC_DRV_CAT_HDR catHdr; | |
527 UINT8 numCategories=0; | |
528 T_SEC_DRV_RETURN result = check_hdr(&numCategories); | |
529 if (result != SEC_DRV_RET_Ok) | |
530 { | |
531 /* data not present in secure area! */ | |
532 return result; | |
533 } | |
534 | |
535 sec_prim_get_configuration(&conf); | |
536 if (Counter_Exceeded(&conf.FC_Current)) | |
537 { | |
538 result = SEC_DRV_RET_FCExeeded; | |
539 } | |
540 else if (sec_prim_get_cat_header(rec_num, &catHdr)) | |
541 { | |
542 if (UNLOCKED(catHdr.Status) || | |
543 (conf.Flags & SEC_DRV_HDR_FLAG_LAM_Unlock) || | |
544 (catHdr.Flags & SEC_DRV_CAT_FLAG_LinkLocked)) | |
545 { | |
546 /* NAM or LinkLock failure */ | |
547 result = SEC_DRV_RET_Unknown; | |
548 } | |
549 else | |
550 { | |
551 T_SEC_DRV_KEY catKey; | |
552 sec_prim_get_key(rec_num, &catKey); | |
553 result = compare_keys(rec_num, (char *)catKey.digit, pKey, key_len); | |
554 if (result == SEC_DRV_RET_Ok) | |
555 { | |
556 /* update status */ | |
557 catHdr.Status = (unlockType == TEMPORARY_UNLOCK)? | |
558 SEC_DRV_CAT_STAT_Unlocked : | |
559 SEC_DRV_CAT_STAT_PermUnlocked; | |
560 sec_prim_set_cat_header(rec_num, &catHdr); | |
561 /* update dependants */ | |
562 update_dependants(&catHdr, &catKey, dependMask); | |
563 /* reset failure counter */ | |
564 conf.FC_Current = 0; | |
565 sec_prim_set_configuration(&conf); | |
566 } | |
567 else | |
568 { | |
569 /* Failure comparing keys! - | |
570 update failure counter */ | |
571 Counter_Increment(&conf.FC_Current); | |
572 sec_prim_set_configuration(&conf); | |
573 } | |
574 } | |
575 } | |
576 else | |
577 { | |
578 /* requested data outside configured categories! */ | |
579 result = SEC_DRV_RET_NotPresent; | |
580 } | |
581 return result; | |
582 } | |
583 | |
584 | |
585 static T_SEC_DRV_RETURN lock_record( | |
586 UINT8 rec_num, | |
587 T_SEC_DRV_CAT_HDR *catHdr, | |
588 UINT16 dependMask) | |
589 { | |
590 T_SEC_DRV_KEY catKey; | |
591 catHdr->Status = SEC_DRV_CAT_STAT_Locked; | |
592 sec_prim_get_key(rec_num, &catKey); | |
593 sec_prim_set_cat_header(rec_num, catHdr); | |
594 update_dependants(catHdr, &catKey, dependMask); | |
595 return SEC_DRV_RET_Ok; | |
596 } | |
597 | |
598 | |
599 /** | |
600 * Try to lock a category. Actual algorith depends on flags set for the individual | |
601 * category. | |
602 * | |
603 * @param rec_num Category number that should be locked. | |
604 * @param pKey Key that should match (or be set in) the stored category key. | |
605 * @param key_len The maximum number of chars to use in the compare or 0 (to use all). | |
606 * @return SEC_DRV_RET_Ok if the category could be locked. | |
607 */ | |
608 T_SEC_DRV_RETURN sec_rec_Lock (UINT8 rec_num, const char *pKey, UINT8 key_len, UINT16 dependMask) | |
609 { | |
610 T_SEC_DRV_CAT_HDR catHdr; | |
611 UINT8 numCategories=0; | |
612 T_SEC_DRV_RETURN result = check_hdr(&numCategories); | |
613 if (result != SEC_DRV_RET_Ok) | |
614 { | |
615 /* data not present in secure area! */ | |
616 return result; | |
617 } | |
618 | |
619 if (sec_prim_get_cat_header(rec_num, &catHdr)) | |
620 { | |
621 if (catHdr.Status != SEC_DRV_CAT_STAT_Unlocked) | |
622 { | |
623 /* Status must be unlocked before locking! */ | |
624 result = SEC_DRV_RET_Unknown; | |
625 } | |
626 else | |
627 { | |
628 if (rec_num == SEC_DRV_CAT_NUM_AP) | |
629 { | |
630 result = lock_record(rec_num, &catHdr, dependMask); | |
631 } | |
632 else | |
633 { | |
634 T_SEC_DRV_CONFIGURATION conf; | |
635 sec_prim_get_configuration(&conf); | |
636 if (conf.Flags & SEC_DRV_HDR_FLAG_ETSI_Flag) | |
637 { | |
638 /* ETSI Mode - set the category key */ | |
639 int len = strlen(pKey); | |
640 if (check_key_len(rec_num, len)) | |
641 { | |
642 T_SEC_DRV_KEY key; | |
643 memset(key.digit, 0, SEC_DRV_KEY_MAX_LEN); | |
644 memcpy(key.digit, pKey, len); | |
645 sec_prim_set_key(rec_num, &key); | |
646 result = lock_record(rec_num, &catHdr, dependMask); | |
647 } | |
648 else | |
649 { | |
650 /* Key has wrong length! */ | |
651 result = SEC_DRV_RET_KeyWrong; | |
652 } | |
653 } | |
654 else if (conf.Flags & SEC_DRV_HDR_FLAG_LAM_Unlock) | |
655 { | |
656 /* Non-ETSI, but LAM_unlock is set */ | |
657 result = SEC_DRV_RET_Unknown; | |
658 } | |
659 else | |
660 { | |
661 /* Non-ETSI mode */ | |
662 T_SEC_DRV_KEY key; | |
663 sec_prim_get_key(rec_num, &key); | |
664 if (conf.Flags & SEC_DRV_HDR_FLAG_Spec_Lock_Key) | |
665 { | |
666 /* Special lock key enabled */ | |
667 calculate_spec_lock_key((char *)&key.digit[0]); | |
668 } | |
669 result = compare_keys(rec_num, (char *)key.digit, pKey, key_len); | |
670 if (result == SEC_DRV_RET_Ok) | |
671 { | |
672 result = lock_record(rec_num, &catHdr, dependMask); | |
673 } | |
674 } | |
675 } | |
676 } | |
677 } | |
678 else | |
679 { | |
680 /* requested data outside configured categories! */ | |
681 result = SEC_DRV_RET_NotPresent; | |
682 } | |
683 return result; | |
684 } | |
685 | |
686 | |
687 /** | |
688 * reset the failure counter. The correct key must of course be given. | |
689 * | |
690 * @param pKey The key used to try to reset the failure counter. | |
691 * @key_len Length of the key to use. | |
692 * @return SEC_DRV_RET_Ok if the failure counter could be reset. | |
693 */ | |
694 T_SEC_DRV_RETURN sec_FC_Reset (const char *pKey, UINT8 key_len) | |
695 { | |
696 T_SEC_DRV_KEY refKey; | |
697 T_SEC_DRV_CONFIGURATION conf; | |
698 T_SEC_DRV_RETURN result = check_hdr(0L); | |
699 if (result != SEC_DRV_RET_Ok) | |
700 { | |
701 /* data not present in secure area! */ | |
702 return result; | |
703 } | |
704 | |
705 sec_prim_get_configuration(&conf); | |
706 if (Counter_Exceeded(&conf.FC_Reset_Fail_Current) || | |
707 Counter_Exceeded(&conf.FC_Reset_Success_Current)) | |
708 { | |
709 result = SEC_DRV_RET_FCExeeded; | |
710 } | |
711 else | |
712 { | |
713 sec_prim_get_key(-1, &refKey); | |
714 result = compare_keys(-1, (char *)refKey.digit, pKey, key_len); | |
715 if (result == SEC_DRV_RET_Ok) | |
716 { | |
717 Counter_Increment(&conf.FC_Reset_Success_Current); | |
718 conf.FC_Current = 0; | |
719 } | |
720 else | |
721 { | |
722 Counter_Increment(&conf.FC_Reset_Fail_Current); | |
723 } | |
724 sec_prim_set_configuration(&conf); | |
725 } | |
726 return result; | |
727 } | |
728 | |
729 | |
730 T_SEC_DRV_RETURN sec_FC_Increment(void) | |
731 { | |
732 T_SEC_DRV_RETURN result = SEC_DRV_RET_Ok; | |
733 T_SEC_DRV_CONFIGURATION conf; | |
734 | |
735 sec_prim_get_configuration(&conf); | |
736 if (Counter_Exceeded(&conf.FC_Current)) | |
737 { | |
738 result = SEC_DRV_RET_FCExeeded; | |
739 } | |
740 else | |
741 { | |
742 Counter_Increment(&conf.FC_Current); | |
743 sec_prim_set_configuration(&conf); | |
744 } | |
745 return result; | |
746 } | |
747 |