077163a82aa7ff636b38703b2c03658e13bdcdbe
[strongswan.git] / src / charon / plugins / eap_sim_file / eap_sim_file_card.c
1 /*
2 * Copyright (C) 2008-2009 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
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>.
9 *
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
13 * for more details.
14 */
15
16 #include "eap_sim_file_card.h"
17
18 #include <daemon.h>
19 #include <utils/hashtable.h>
20
21 typedef struct private_eap_sim_file_card_t private_eap_sim_file_card_t;
22
23 /**
24 * Private data of an eap_sim_file_card_t object.
25 */
26 struct private_eap_sim_file_card_t {
27
28 /**
29 * Public eap_sim_file_card_t interface.
30 */
31 eap_sim_file_card_t public;
32
33 /**
34 * source of triplets
35 */
36 eap_sim_file_triplets_t *triplets;
37
38 /**
39 * Permanent -> pseudonym mappings
40 */
41 hashtable_t *pseudonym;
42
43 /**
44 * Permanent -> reauth_data_t mappings
45 */
46 hashtable_t *reauth;
47
48 /**
49 * Reverse pseudonym -> permanent mappings
50 */
51 hashtable_t *permanent;
52 };
53
54 typedef struct {
55 /** currently used reauthentication identity */
56 identification_t *id;
57 /** associated permanent identity */
58 identification_t *permanent;
59 /** counter value */
60 u_int16_t counter;
61 /** master key */
62 char mk[HASH_SIZE_SHA1];
63 } reauth_data_t;
64
65 /**
66 * hashtable hash function
67 */
68 static u_int hash(identification_t *key)
69 {
70 return chunk_hash(key->get_encoding(key));
71 }
72
73 /**
74 * hashtable equals function
75 */
76 static bool equals(identification_t *key1, identification_t *key2)
77 {
78 return key1->equals(key1, key2);
79 }
80
81 /**
82 * Implementation of sim_card_t.get_triplet
83 */
84 static bool get_triplet(private_eap_sim_file_card_t *this,
85 identification_t *id, char *rand, char *sres, char *kc)
86 {
87 enumerator_t *enumerator;
88 identification_t *cand;
89 char *c_rand, *c_sres, *c_kc;
90
91 DBG2(DBG_CFG, "looking for triplet: %Y rand %b", id, rand, SIM_RAND_LEN);
92
93 enumerator = this->triplets->create_enumerator(this->triplets);
94 while (enumerator->enumerate(enumerator, &cand, &c_rand, &c_sres, &c_kc))
95 {
96 DBG2(DBG_CFG, "got a triplet: %Y rand %b\nsres %b\n kc %b", cand,
97 c_rand, SIM_RAND_LEN, c_sres, SIM_SRES_LEN, c_kc, SIM_KC_LEN);
98 if (id->matches(id, cand))
99 {
100 if (memeq(c_rand, rand, SIM_RAND_LEN))
101 {
102 DBG2(DBG_CFG, " => triplet matches");
103 memcpy(sres, c_sres, SIM_SRES_LEN);
104 memcpy(kc, c_kc, SIM_KC_LEN);
105 enumerator->destroy(enumerator);
106 return TRUE;
107 }
108 }
109 }
110 enumerator->destroy(enumerator);
111 return FALSE;
112 }
113
114 /**
115 * Implementation of sim_card_t.get_pseudonym
116 */
117 static identification_t *get_pseudonym(private_eap_sim_file_card_t *this,
118 identification_t *id)
119 {
120 identification_t *pseudonym;
121
122 pseudonym = this->pseudonym->get(this->pseudonym, id);
123 if (pseudonym)
124 {
125 return pseudonym->clone(pseudonym);
126 }
127 return NULL;
128 }
129
130 /**
131 * Implementation of sim_card_t.set_pseudonym
132 */
133 static void set_pseudonym(private_eap_sim_file_card_t *this,
134 identification_t *id, identification_t *pseudonym)
135 {
136 identification_t *permanent;
137
138 /* create new entries */
139 id = id->clone(id);
140 pseudonym = pseudonym->clone(pseudonym);
141 permanent = this->permanent->put(this->permanent, pseudonym, id);
142 pseudonym = this->pseudonym->put(this->pseudonym, id, pseudonym);
143
144 /* delete old entries */
145 DESTROY_IF(permanent);
146 DESTROY_IF(pseudonym);
147 }
148
149 /**
150 * Implementation of sim_card_t.get_reauth
151 */
152 static identification_t *get_reauth(private_eap_sim_file_card_t *this,
153 identification_t *id, char mk[HASH_SIZE_SHA1],
154 u_int16_t *counter)
155 {
156 reauth_data_t *data;
157 identification_t *reauth;
158
159 /* look up reauthentication data */
160 data = this->reauth->remove(this->reauth, id);
161 if (!data)
162 {
163 return NULL;
164 }
165 *counter = ++data->counter;
166 memcpy(mk, data->mk, HASH_SIZE_SHA1);
167 reauth = data->id;
168 data->permanent->destroy(data->permanent);
169 free(data);
170 return reauth;
171 }
172
173 /**
174 * Implementation of sim_card_t.set_reauth
175 */
176 static void set_reauth(private_eap_sim_file_card_t *this,
177 identification_t *id, identification_t* next,
178 char mk[HASH_SIZE_SHA1], u_int16_t counter)
179 {
180 reauth_data_t *data;
181
182 data = this->reauth->get(this->reauth, id);
183 if (data)
184 {
185 data->id->destroy(data->id);
186 }
187 else
188 {
189 data = malloc_thing(reauth_data_t);
190 data->permanent = id->clone(id);
191 this->reauth->put(this->reauth, data->permanent, data);
192 }
193 data->counter = counter;
194 data->id = next->clone(next);
195 memcpy(data->mk, mk, HASH_SIZE_SHA1);
196 }
197
198 /**
199 * Implementation of sim_card_t.get_quintuplet
200 */
201 static bool get_quintuplet()
202 {
203 return NOT_SUPPORTED;
204 }
205
206 /**
207 * Implementation of eap_sim_file_card_t.destroy.
208 */
209 static void destroy(private_eap_sim_file_card_t *this)
210 {
211 enumerator_t *enumerator;
212 identification_t *id;
213 reauth_data_t *data;
214 void *key;
215
216 enumerator = this->pseudonym->create_enumerator(this->pseudonym);
217 while (enumerator->enumerate(enumerator, &key, &id))
218 {
219 id->destroy(id);
220 }
221 enumerator->destroy(enumerator);
222
223 enumerator = this->permanent->create_enumerator(this->permanent);
224 while (enumerator->enumerate(enumerator, &key, &id))
225 {
226 id->destroy(id);
227 }
228 enumerator->destroy(enumerator);
229
230 enumerator = this->reauth->create_enumerator(this->reauth);
231 while (enumerator->enumerate(enumerator, &key, &data))
232 {
233 data->id->destroy(data->id);
234 data->permanent->destroy(data->permanent);
235 free(data);
236 }
237 enumerator->destroy(enumerator);
238
239 this->pseudonym->destroy(this->pseudonym);
240 this->permanent->destroy(this->permanent);
241 this->reauth->destroy(this->reauth);
242 free(this);
243 }
244
245 /**
246 * See header
247 */
248 eap_sim_file_card_t *eap_sim_file_card_create(eap_sim_file_triplets_t *triplets)
249 {
250 private_eap_sim_file_card_t *this = malloc_thing(private_eap_sim_file_card_t);
251
252 this->public.card.get_triplet = (bool(*)(sim_card_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))get_triplet;
253 this->public.card.get_quintuplet = (status_t(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_LEN]))get_quintuplet;
254 this->public.card.resync = (bool(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))return_false;
255 this->public.card.get_pseudonym = (identification_t*(*)(sim_card_t*, identification_t *perm))get_pseudonym;
256 this->public.card.set_pseudonym = (void(*)(sim_card_t*, identification_t *id, identification_t *pseudonym))set_pseudonym;
257 this->public.card.get_reauth = (identification_t*(*)(sim_card_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))get_reauth;
258 this->public.card.set_reauth = (void(*)(sim_card_t*, identification_t *id, identification_t* next, char mk[HASH_SIZE_SHA1], u_int16_t counter))set_reauth;
259 this->public.destroy = (void(*)(eap_sim_file_card_t*))destroy;
260
261 this->triplets = triplets;
262 this->pseudonym = hashtable_create((void*)hash, (void*)equals, 0);
263 this->permanent = hashtable_create((void*)hash, (void*)equals, 0);
264 this->reauth = hashtable_create((void*)hash, (void*)equals, 0);
265
266 return &this->public;
267 }
268