2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "simaka_manager.h"
19 #include <utils/linked_list.h>
20 #include <threading/rwlock.h>
22 typedef struct private_simaka_manager_t private_simaka_manager_t
;
25 * Private data of an simaka_manager_t object.
27 struct private_simaka_manager_t
{
30 * Public simaka_manager_t interface.
32 simaka_manager_t
public;
40 * list of added provider
42 linked_list_t
*providers
;
50 * lock for lists above
55 METHOD(simaka_manager_t
, add_card
, void,
56 private_simaka_manager_t
*this, simaka_card_t
*card
)
58 this->lock
->write_lock(this->lock
);
59 this->cards
->insert_last(this->cards
, card
);
60 this->lock
->unlock(this->lock
);
63 METHOD(simaka_manager_t
, remove_card
, void,
64 private_simaka_manager_t
*this, simaka_card_t
*card
)
66 this->lock
->write_lock(this->lock
);
67 this->cards
->remove(this->cards
, card
, NULL
);
68 this->lock
->unlock(this->lock
);
71 METHOD(simaka_manager_t
, card_get_triplet
, bool,
72 private_simaka_manager_t
*this, identification_t
*id
,
73 char rand
[SIM_RAND_LEN
], char sres
[SIM_SRES_LEN
], char kc
[SIM_KC_LEN
])
75 enumerator_t
*enumerator
;
79 this->lock
->read_lock(this->lock
);
80 enumerator
= this->cards
->create_enumerator(this->cards
);
81 while (enumerator
->enumerate(enumerator
, &card
))
83 if (card
->get_triplet(card
, id
, rand
, sres
, kc
))
85 enumerator
->destroy(enumerator
);
86 this->lock
->unlock(this->lock
);
91 enumerator
->destroy(enumerator
);
92 this->lock
->unlock(this->lock
);
93 DBG1(DBG_LIB
, "tried %d SIM cards, but none has triplets for '%Y'",
98 METHOD(simaka_manager_t
, card_get_quintuplet
, status_t
,
99 private_simaka_manager_t
*this, identification_t
*id
, char rand
[AKA_RAND_LEN
],
100 char autn
[AKA_AUTN_LEN
], char ck
[AKA_CK_LEN
], char ik
[AKA_IK_LEN
],
101 char res
[AKA_RES_MAX
], int *res_len
)
103 enumerator_t
*enumerator
;
105 status_t status
= NOT_FOUND
;
108 this->lock
->read_lock(this->lock
);
109 enumerator
= this->cards
->create_enumerator(this->cards
);
110 while (enumerator
->enumerate(enumerator
, &card
))
112 status
= card
->get_quintuplet(card
, id
, rand
, autn
, ck
, ik
, res
, res_len
);
114 { /* try next on error, but not on INVALID_STATE */
117 enumerator
->destroy(enumerator
);
118 this->lock
->unlock(this->lock
);
127 enumerator
->destroy(enumerator
);
128 this->lock
->unlock(this->lock
);
129 DBG1(DBG_LIB
, "tried %d SIM cards, but none has quintuplets for '%Y'",
134 METHOD(simaka_manager_t
, card_resync
, bool,
135 private_simaka_manager_t
*this, identification_t
*id
,
136 char rand
[AKA_RAND_LEN
], char auts
[AKA_AUTS_LEN
])
138 enumerator_t
*enumerator
;
141 this->lock
->read_lock(this->lock
);
142 enumerator
= this->cards
->create_enumerator(this->cards
);
143 while (enumerator
->enumerate(enumerator
, &card
))
145 if (card
->resync(card
, id
, rand
, auts
))
147 enumerator
->destroy(enumerator
);
148 this->lock
->unlock(this->lock
);
152 enumerator
->destroy(enumerator
);
153 this->lock
->unlock(this->lock
);
157 METHOD(simaka_manager_t
, card_set_pseudonym
, void,
158 private_simaka_manager_t
*this, identification_t
*id
,
159 identification_t
*pseudonym
)
161 enumerator_t
*enumerator
;
164 DBG1(DBG_LIB
, "storing pseudonym '%Y' for '%Y'", pseudonym
, id
);
166 this->lock
->read_lock(this->lock
);
167 enumerator
= this->cards
->create_enumerator(this->cards
);
168 while (enumerator
->enumerate(enumerator
, &card
))
170 card
->set_pseudonym(card
, id
, pseudonym
);
172 enumerator
->destroy(enumerator
);
173 this->lock
->unlock(this->lock
);
176 METHOD(simaka_manager_t
, card_get_pseudonym
, identification_t
*,
177 private_simaka_manager_t
*this, identification_t
*id
)
179 enumerator_t
*enumerator
;
181 identification_t
*pseudonym
= NULL
;
183 this->lock
->read_lock(this->lock
);
184 enumerator
= this->cards
->create_enumerator(this->cards
);
185 while (enumerator
->enumerate(enumerator
, &card
))
187 pseudonym
= card
->get_pseudonym(card
, id
);
190 DBG1(DBG_LIB
, "using stored pseudonym identity '%Y' "
191 "instead of '%Y'", pseudonym
, id
);
195 enumerator
->destroy(enumerator
);
196 this->lock
->unlock(this->lock
);
200 METHOD(simaka_manager_t
, card_set_reauth
, void,
201 private_simaka_manager_t
*this, identification_t
*id
, identification_t
*next
,
202 char mk
[HASH_SIZE_SHA1
], u_int16_t counter
)
204 enumerator_t
*enumerator
;
207 DBG1(DBG_LIB
, "storing next reauthentication identity '%Y' for '%Y'",
210 this->lock
->read_lock(this->lock
);
211 enumerator
= this->cards
->create_enumerator(this->cards
);
212 while (enumerator
->enumerate(enumerator
, &card
))
214 card
->set_reauth(card
, id
, next
, mk
, counter
);
216 enumerator
->destroy(enumerator
);
217 this->lock
->unlock(this->lock
);
220 METHOD(simaka_manager_t
, card_get_reauth
, identification_t
*,
221 private_simaka_manager_t
*this, identification_t
*id
, char mk
[HASH_SIZE_SHA1
],
224 enumerator_t
*enumerator
;
226 identification_t
*reauth
= NULL
;
228 this->lock
->read_lock(this->lock
);
229 enumerator
= this->cards
->create_enumerator(this->cards
);
230 while (enumerator
->enumerate(enumerator
, &card
))
232 reauth
= card
->get_reauth(card
, id
, mk
, counter
);
235 DBG1(DBG_LIB
, "using stored reauthentication identity '%Y' "
236 "instead of '%Y'", reauth
, id
);
240 enumerator
->destroy(enumerator
);
241 this->lock
->unlock(this->lock
);
245 METHOD(simaka_manager_t
, add_provider
, void,
246 private_simaka_manager_t
*this, simaka_provider_t
*provider
)
248 this->lock
->write_lock(this->lock
);
249 this->providers
->insert_last(this->providers
, provider
);
250 this->lock
->unlock(this->lock
);
253 METHOD(simaka_manager_t
, remove_provider
, void,
254 private_simaka_manager_t
*this, simaka_provider_t
*provider
)
256 this->lock
->write_lock(this->lock
);
257 this->providers
->remove(this->providers
, provider
, NULL
);
258 this->lock
->unlock(this->lock
);
261 METHOD(simaka_manager_t
, provider_get_triplet
, bool,
262 private_simaka_manager_t
*this, identification_t
*id
,
263 char rand
[SIM_RAND_LEN
], char sres
[SIM_SRES_LEN
], char kc
[SIM_KC_LEN
])
265 enumerator_t
*enumerator
;
266 simaka_provider_t
*provider
;
269 this->lock
->read_lock(this->lock
);
270 enumerator
= this->providers
->create_enumerator(this->providers
);
271 while (enumerator
->enumerate(enumerator
, &provider
))
273 if (provider
->get_triplet(provider
, id
, rand
, sres
, kc
))
275 enumerator
->destroy(enumerator
);
276 this->lock
->unlock(this->lock
);
281 enumerator
->destroy(enumerator
);
282 this->lock
->unlock(this->lock
);
283 DBG1(DBG_LIB
, "tried %d SIM providers, but none had a triplet for '%Y'",
288 METHOD(simaka_manager_t
, provider_get_quintuplet
, bool,
289 private_simaka_manager_t
*this, identification_t
*id
,
290 char rand
[AKA_RAND_LEN
], char xres
[AKA_RES_MAX
], int *xres_len
,
291 char ck
[AKA_CK_LEN
], char ik
[AKA_IK_LEN
], char autn
[AKA_AUTN_LEN
])
293 enumerator_t
*enumerator
;
294 simaka_provider_t
*provider
;
297 this->lock
->read_lock(this->lock
);
298 enumerator
= this->providers
->create_enumerator(this->providers
);
299 while (enumerator
->enumerate(enumerator
, &provider
))
301 if (provider
->get_quintuplet(provider
, id
, rand
, xres
, xres_len
,
304 enumerator
->destroy(enumerator
);
305 this->lock
->unlock(this->lock
);
309 enumerator
->destroy(enumerator
);
310 this->lock
->unlock(this->lock
);
311 DBG1(DBG_LIB
, "tried %d SIM providers, but none had a quintuplet for '%Y'",
316 METHOD(simaka_manager_t
, provider_resync
, bool,
317 private_simaka_manager_t
*this, identification_t
*id
,
318 char rand
[AKA_RAND_LEN
], char auts
[AKA_AUTS_LEN
])
320 enumerator_t
*enumerator
;
321 simaka_provider_t
*provider
;
323 this->lock
->read_lock(this->lock
);
324 enumerator
= this->providers
->create_enumerator(this->providers
);
325 while (enumerator
->enumerate(enumerator
, &provider
))
327 if (provider
->resync(provider
, id
, rand
, auts
))
329 enumerator
->destroy(enumerator
);
330 this->lock
->unlock(this->lock
);
334 enumerator
->destroy(enumerator
);
335 this->lock
->unlock(this->lock
);
339 METHOD(simaka_manager_t
, provider_is_pseudonym
, identification_t
*,
340 private_simaka_manager_t
*this, identification_t
*id
)
342 enumerator_t
*enumerator
;
343 simaka_provider_t
*provider
;
344 identification_t
*permanent
= NULL
;
346 this->lock
->read_lock(this->lock
);
347 enumerator
= this->providers
->create_enumerator(this->providers
);
348 while (enumerator
->enumerate(enumerator
, &provider
))
350 permanent
= provider
->is_pseudonym(provider
, id
);
353 DBG1(DBG_LIB
, "received pseudonym identity '%Y' "
354 "mapping to '%Y'", id
, permanent
);
358 enumerator
->destroy(enumerator
);
359 this->lock
->unlock(this->lock
);
363 METHOD(simaka_manager_t
, provider_gen_pseudonym
, identification_t
*,
364 private_simaka_manager_t
*this, identification_t
*id
)
366 enumerator_t
*enumerator
;
367 simaka_provider_t
*provider
;
368 identification_t
*pseudonym
= NULL
;
370 this->lock
->read_lock(this->lock
);
371 enumerator
= this->providers
->create_enumerator(this->providers
);
372 while (enumerator
->enumerate(enumerator
, &provider
))
374 pseudonym
= provider
->gen_pseudonym(provider
, id
);
377 DBG1(DBG_LIB
, "proposing new pseudonym '%Y'", pseudonym
);
381 enumerator
->destroy(enumerator
);
382 this->lock
->unlock(this->lock
);
386 METHOD(simaka_manager_t
, provider_is_reauth
, identification_t
*,
387 private_simaka_manager_t
*this, identification_t
*id
, char mk
[HASH_SIZE_SHA1
],
390 enumerator_t
*enumerator
;
391 simaka_provider_t
*provider
;
392 identification_t
*permanent
= NULL
;
394 this->lock
->read_lock(this->lock
);
395 enumerator
= this->providers
->create_enumerator(this->providers
);
396 while (enumerator
->enumerate(enumerator
, &provider
))
398 permanent
= provider
->is_reauth(provider
, id
, mk
, counter
);
401 DBG1(DBG_LIB
, "received reauthentication identity '%Y' "
402 "mapping to '%Y'", id
, permanent
);
406 enumerator
->destroy(enumerator
);
407 this->lock
->unlock(this->lock
);
411 METHOD(simaka_manager_t
, provider_gen_reauth
, identification_t
*,
412 private_simaka_manager_t
*this, identification_t
*id
, char mk
[HASH_SIZE_SHA1
])
414 enumerator_t
*enumerator
;
415 simaka_provider_t
*provider
;
416 identification_t
*reauth
= NULL
;
418 this->lock
->read_lock(this->lock
);
419 enumerator
= this->providers
->create_enumerator(this->providers
);
420 while (enumerator
->enumerate(enumerator
, &provider
))
422 reauth
= provider
->gen_reauth(provider
, id
, mk
);
425 DBG1(DBG_LIB
, "proposing new reauthentication identity '%Y'", reauth
);
429 enumerator
->destroy(enumerator
);
430 this->lock
->unlock(this->lock
);
434 METHOD(simaka_manager_t
, add_hooks
, void,
435 private_simaka_manager_t
*this, simaka_hooks_t
*hooks
)
437 this->lock
->write_lock(this->lock
);
438 this->hooks
->insert_last(this->hooks
, hooks
);
439 this->lock
->unlock(this->lock
);
442 METHOD(simaka_manager_t
, remove_hooks
, void,
443 private_simaka_manager_t
*this, simaka_hooks_t
*hooks
)
445 this->lock
->write_lock(this->lock
);
446 this->hooks
->remove(this->hooks
, hooks
, NULL
);
447 this->lock
->unlock(this->lock
);
450 METHOD(simaka_manager_t
, message_hook
, void,
451 private_simaka_manager_t
*this, simaka_message_t
*message
,
452 bool inbound
, bool decrypted
)
454 enumerator_t
*enumerator
;
455 simaka_hooks_t
*hooks
;
457 this->lock
->read_lock(this->lock
);
458 enumerator
= this->hooks
->create_enumerator(this->hooks
);
459 while (enumerator
->enumerate(enumerator
, &hooks
))
461 hooks
->message(hooks
, message
, inbound
, decrypted
);
463 enumerator
->destroy(enumerator
);
464 this->lock
->unlock(this->lock
);
467 METHOD(simaka_manager_t
, key_hook
, void,
468 private_simaka_manager_t
*this, chunk_t k_encr
, chunk_t k_auth
)
470 enumerator_t
*enumerator
;
471 simaka_hooks_t
*hooks
;
473 this->lock
->read_lock(this->lock
);
474 enumerator
= this->hooks
->create_enumerator(this->hooks
);
475 while (enumerator
->enumerate(enumerator
, &hooks
))
477 hooks
->keys(hooks
, k_encr
, k_auth
);
479 enumerator
->destroy(enumerator
);
480 this->lock
->unlock(this->lock
);
483 METHOD(simaka_manager_t
, destroy
, void,
484 private_simaka_manager_t
*this)
486 this->cards
->destroy(this->cards
);
487 this->providers
->destroy(this->providers
);
488 this->hooks
->destroy(this->hooks
);
489 this->lock
->destroy(this->lock
);
496 simaka_manager_t
*simaka_manager_create()
498 private_simaka_manager_t
*this;
502 .add_card
= _add_card
,
503 .remove_card
= _remove_card
,
504 .card_get_triplet
= _card_get_triplet
,
505 .card_get_quintuplet
= _card_get_quintuplet
,
506 .card_resync
= _card_resync
,
507 .card_set_pseudonym
= _card_set_pseudonym
,
508 .card_get_pseudonym
= _card_get_pseudonym
,
509 .card_set_reauth
= _card_set_reauth
,
510 .card_get_reauth
= _card_get_reauth
,
511 .add_provider
= _add_provider
,
512 .remove_provider
= _remove_provider
,
513 .provider_get_triplet
= _provider_get_triplet
,
514 .provider_get_quintuplet
= _provider_get_quintuplet
,
515 .provider_resync
= _provider_resync
,
516 .provider_is_pseudonym
= _provider_is_pseudonym
,
517 .provider_gen_pseudonym
= _provider_gen_pseudonym
,
518 .provider_is_reauth
= _provider_is_reauth
,
519 .provider_gen_reauth
= _provider_gen_reauth
,
520 .add_hooks
= _add_hooks
,
521 .remove_hooks
= _remove_hooks
,
522 .message_hook
= _message_hook
,
523 .key_hook
= _key_hook
,
526 .cards
= linked_list_create(),
527 .providers
= linked_list_create(),
528 .hooks
= linked_list_create(),
529 .lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
532 return &this->public;