Removed strayed code fragment
[strongswan.git] / src / charon / plugins / eap_aka_3gpp2 / eap_aka_3gpp2_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_aka_3gpp2_card.h"
17
18 #include <daemon.h>
19
20 typedef struct private_eap_aka_3gpp2_card_t private_eap_aka_3gpp2_card_t;
21
22 /**
23 * Private data of an eap_aka_3gpp2_card_t object.
24 */
25 struct private_eap_aka_3gpp2_card_t {
26
27 /**
28 * Public eap_aka_3gpp2_card_t interface.
29 */
30 eap_aka_3gpp2_card_t public;
31
32 /**
33 * AKA functions
34 */
35 eap_aka_3gpp2_functions_t *f;
36
37 /**
38 * do sequence number checking?
39 */
40 bool seq_check;
41
42 /**
43 * SQN stored in this pseudo-USIM
44 */
45 char sqn[AKA_SQN_LEN];
46 };
47
48 /**
49 * Functions from eap_aka_3gpp2_provider.c
50 */
51 bool eap_aka_3gpp2_get_k(identification_t *id, char k[AKA_K_LEN]);
52 void eap_aka_3gpp2_get_sqn(char sqn[AKA_SQN_LEN], int offset);
53
54 /**
55 * Implementation of sim_card_t.get_quintuplet
56 */
57 static status_t get_quintuplet(private_eap_aka_3gpp2_card_t *this,
58 identification_t *id, char rand[AKA_RAND_LEN],
59 char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN],
60 char ik[AKA_IK_LEN], char res[AKA_RES_MAX],
61 int *res_len)
62 {
63 char *amf, *mac;
64 char k[AKA_K_LEN], ak[AKA_AK_LEN], sqn[AKA_SQN_LEN], xmac[AKA_MAC_LEN];
65
66 if (!eap_aka_3gpp2_get_k(id, k))
67 {
68 DBG1(DBG_IKE, "no EAP key found for %Y to authenticate with AKA", id);
69 return FAILED;
70 }
71
72 /* AUTN = SQN xor AK | AMF | MAC */
73 DBG3(DBG_IKE, "received autn %b", autn, AKA_AUTN_LEN);
74 DBG3(DBG_IKE, "using K %b", k, AKA_K_LEN);
75 DBG3(DBG_IKE, "using rand %b", rand, AKA_RAND_LEN);
76 memcpy(sqn, autn, AKA_SQN_LEN);
77 amf = autn + AKA_SQN_LEN;
78 mac = autn + AKA_SQN_LEN + AKA_AMF_LEN;
79
80 /* XOR anonymity key AK into SQN to decrypt it */
81 this->f->f5(this->f, k, rand, ak);
82 DBG3(DBG_IKE, "using ak %b", ak, AKA_AK_LEN);
83 memxor(sqn, ak, AKA_SQN_LEN);
84 DBG3(DBG_IKE, "using sqn %b", sqn, AKA_SQN_LEN);
85
86 /* calculate expected MAC and compare against received one */
87 this->f->f1(this->f, k, rand, sqn, amf, xmac);
88 if (!memeq(mac, xmac, AKA_MAC_LEN))
89 {
90 DBG1(DBG_IKE, "received MAC does not match XMAC");
91 DBG3(DBG_IKE, "MAC %b\nXMAC %b", mac, AKA_MAC_LEN, xmac, AKA_MAC_LEN);
92 return FAILED;
93 }
94
95 if (this->seq_check && memcmp(this->sqn, sqn, AKA_SQN_LEN) >= 0)
96 {
97 DBG3(DBG_IKE, "received SQN %b\ncurrent SQN %b",
98 sqn, AKA_SQN_LEN, this->sqn, AKA_SQN_LEN);
99 return INVALID_STATE;
100 }
101
102 /* update stored SQN to the received one */
103 memcpy(this->sqn, sqn, AKA_SQN_LEN);
104
105 /* CK/IK */
106 this->f->f3(this->f, k, rand, ck);
107 this->f->f4(this->f, k, rand, ik);
108 /* calculate RES */
109 this->f->f2(this->f, k, rand, res);
110 *res_len = AKA_RES_MAX;
111
112 return SUCCESS;
113 }
114
115 /**
116 * Implementation of sim_card_t.resync
117 */
118 static bool resync(private_eap_aka_3gpp2_card_t *this, identification_t *id,
119 char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN])
120 {
121 char amf[AKA_AMF_LEN], k[AKA_K_LEN], aks[AKA_AK_LEN], macs[AKA_MAC_LEN];
122
123 if (!eap_aka_3gpp2_get_k(id, k))
124 {
125 DBG1(DBG_IKE, "no EAP key found for %Y to resync AKA", id);
126 return FALSE;
127 }
128
129 /* AMF is set to zero in resync */
130 memset(amf, 0, AKA_AMF_LEN);
131 this->f->f5star(this->f, k, rand, aks);
132 this->f->f1star(this->f, k, rand, this->sqn, amf, macs);
133 /* AUTS = SQN xor AKS | MACS */
134 memcpy(auts, this->sqn, AKA_SQN_LEN);
135 memxor(auts, aks, AKA_AK_LEN);
136 memcpy(auts + AKA_AK_LEN, macs, AKA_MAC_LEN);
137
138 return TRUE;
139 }
140
141 /**
142 * Implementation of eap_aka_3gpp2_card_t.destroy.
143 */
144 static void destroy(private_eap_aka_3gpp2_card_t *this)
145 {
146 free(this);
147 }
148
149 /**
150 * See header
151 */
152 eap_aka_3gpp2_card_t *eap_aka_3gpp2_card_create(eap_aka_3gpp2_functions_t *f)
153 {
154 private_eap_aka_3gpp2_card_t *this = malloc_thing(private_eap_aka_3gpp2_card_t);
155
156 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]))return_false;
157 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_MAX], int *res_len))get_quintuplet;
158 this->public.card.resync = (bool(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))resync;
159 this->public.card.get_pseudonym = (identification_t*(*)(sim_card_t*, identification_t *id))return_null;
160 this->public.card.set_pseudonym = (void(*)(sim_card_t*, identification_t *id, identification_t *pseudonym))nop;
161 this->public.card.get_reauth = (identification_t*(*)(sim_card_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))return_null;
162 this->public.card.set_reauth = (void(*)(sim_card_t*, identification_t *id, identification_t* next, char mk[HASH_SIZE_SHA1], u_int16_t counter))nop;
163 this->public.destroy = (void(*)(eap_aka_3gpp2_card_t*))destroy;
164
165 this->f = f;
166 this->seq_check = lib->settings->get_bool(lib->settings,
167 "charon.plugins.eap-aka-3gpp2.seq_check",
168 #ifdef SEQ_CHECK /* handle legacy compile time configuration as default */
169 TRUE);
170 #else /* !SEQ_CHECK */
171 FALSE);
172 #endif /* SEQ_CHECK */
173
174 eap_aka_3gpp2_get_sqn(this->sqn, 0);
175
176 return &this->public;
177 }
178