Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_aka_3gpp/eap_aka_3gpp_card.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008-2009 Martin Willi
3: * HSR 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: * Copyright (C) 2015 Thomas Strangert
17: * Polystar System AB, Sweden
18: *
19: * Permission is hereby granted, free of charge, to any person obtaining a copy
20: * of this software and associated documentation files (the "Software"), to deal
21: * in the Software without restriction, including without limitation the rights
22: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23: * copies of the Software, and to permit persons to whom the Software is
24: * furnished to do so, subject to the following conditions:
25: *
26: * The above copyright notice and this permission notice shall be included in
27: * all copies or substantial portions of the Software.
28: *
29: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35: * THE SOFTWARE.
36: */
37:
38: #include "eap_aka_3gpp_card.h"
39:
40: #include <daemon.h>
41:
42: typedef struct private_eap_aka_3gpp_card_t private_eap_aka_3gpp_card_t;
43:
44: /**
45: * Private data of an eap_aka_3gpp_card_t object.
46: */
47: struct private_eap_aka_3gpp_card_t {
48:
49: /**
50: * Public eap_aka_3gpp_card_t interface.
51: */
52: eap_aka_3gpp_card_t public;
53:
54: /**
55: * AKA functions
56: */
57: eap_aka_3gpp_functions_t *f;
58:
59: /**
60: * do sequence number checking?
61: */
62: bool seq_check;
63:
64: /**
65: * SQN stored in this pseudo-USIM
66: */
67: uint8_t sqn[AKA_SQN_LEN];
68: };
69:
70: METHOD(simaka_card_t, get_quintuplet, status_t,
71: private_eap_aka_3gpp_card_t *this, identification_t *id,
72: char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN],
73: char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len)
74: {
75: uint8_t *amf, *mac;
76: uint8_t k[AKA_K_LEN], opc[AKA_OPC_LEN], ak[AKA_AK_LEN], sqn[AKA_SQN_LEN],
77: xmac[AKA_MAC_LEN];
78:
79: if (!eap_aka_3gpp_get_k_opc(id, k, opc))
80: {
81: DBG1(DBG_IKE, "no EAP key found for %Y to authenticate with AKA", id);
82: return FAILED;
83: }
84: DBG4(DBG_IKE, "EAP key found for id %Y, using K %b and OPc %b", id, k,
85: AKA_K_LEN, opc, AKA_OPC_LEN);
86:
87: /* AUTN = SQN xor AK | AMF | MAC */
88: memcpy(sqn, autn, AKA_SQN_LEN);
89: amf = autn + AKA_SQN_LEN;
90: mac = autn + AKA_SQN_LEN + AKA_AMF_LEN;
91: DBG3(DBG_IKE, "received AUTN %b", autn, AKA_AUTN_LEN);
92: DBG3(DBG_IKE, "received AMF %b", amf, AKA_AMF_LEN);
93: DBG3(DBG_IKE, "received MAC %b", mac, AKA_MAC_LEN);
94:
95: /* generate RES, CK, IK, AK from received RAND */
96: DBG3(DBG_IKE, "received RAND %b", rand, AKA_RAND_LEN);
97: if (!this->f->f2345(this->f, k, opc, rand, res, ck, ik, ak))
98: {
99: return FAILED;
100: }
101: *res_len = AKA_RES_LEN;
102: DBG3(DBG_IKE, "using RES %b", res, AKA_RES_LEN);
103: DBG3(DBG_IKE, "using CK %b", ck, AKA_CK_LEN);
104: DBG3(DBG_IKE, "using IK %b", ik, AKA_IK_LEN);
105: DBG3(DBG_IKE, "using AK %b", ak, AKA_AK_LEN);
106:
107: /* XOR anonymity key AK into SQN to decrypt it */
108: memxor(sqn, ak, AKA_SQN_LEN);
109: DBG3(DBG_IKE, "using SQN %b", sqn, AKA_SQN_LEN);
110:
111: /* calculate expected MAC and compare against received one */
112: if (!this->f->f1(this->f, k, opc, rand, sqn, amf, xmac))
113: {
114: return FAILED;
115: }
116: if (!memeq_const(mac, xmac, AKA_MAC_LEN))
117: {
118: DBG1(DBG_IKE, "received MAC does not match XMAC");
119: DBG3(DBG_IKE, "MAC %b\nXMAC %b", mac, AKA_MAC_LEN, xmac, AKA_MAC_LEN);
120: return FAILED;
121: }
122: DBG3(DBG_IKE, "MAC equals XMAC %b", mac, AKA_MAC_LEN);
123:
124: if (this->seq_check && memcmp(this->sqn, sqn, AKA_SQN_LEN) >= 0)
125: {
126: DBG3(DBG_IKE, "received SQN %b\ncurrent SQN %b",
127: sqn, AKA_SQN_LEN, this->sqn, AKA_SQN_LEN);
128: return INVALID_STATE;
129: }
130:
131: /* update stored SQN to the received one */
132: memcpy(this->sqn, sqn, AKA_SQN_LEN);
133:
134: return SUCCESS;
135: }
136:
137: METHOD(simaka_card_t, resync, bool,
138: private_eap_aka_3gpp_card_t *this, identification_t *id,
139: char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN])
140: {
141: uint8_t amf[AKA_AMF_LEN], k[AKA_K_LEN], opc[AKA_OPC_LEN], aks[AKA_AK_LEN],
142: macs[AKA_MAC_LEN];
143:
144: if (!eap_aka_3gpp_get_k_opc(id, k, opc))
145: {
146: DBG1(DBG_IKE, "no EAP key found for %Y to resync AKA", id);
147: return FALSE;
148: }
149: DBG4(DBG_IKE, "EAP key found for id %Y, using K %b and OPc %b to resync AKA",
150: id, k, AKA_K_LEN, opc, AKA_OPC_LEN);
151:
152: /* AMF is set to zero in resync */
153: memset(amf, 0, AKA_AMF_LEN);
154: if (!this->f->f5star(this->f, k, opc, rand, aks) ||
155: !this->f->f1star(this->f, k, opc, rand, this->sqn, amf, macs))
156: {
157: return FALSE;
158: }
159: /* AUTS = SQN xor AKS | MACS */
160: memcpy(auts, this->sqn, AKA_SQN_LEN);
161: memxor(auts, aks, AKA_AK_LEN);
162: memcpy(auts + AKA_AK_LEN, macs, AKA_MAC_LEN);
163: DBG3(DBG_IKE, "generated AUTS %b", auts, AKA_AUTN_LEN);
164:
165: return TRUE;
166: }
167:
168: METHOD(eap_aka_3gpp_card_t, destroy, void,
169: private_eap_aka_3gpp_card_t *this)
170: {
171: free(this);
172: }
173:
174: /**
175: * See header
176: */
177: eap_aka_3gpp_card_t *eap_aka_3gpp_card_create(eap_aka_3gpp_functions_t *f)
178: {
179: private_eap_aka_3gpp_card_t *this;
180:
181: INIT(this,
182: .public = {
183: .card = {
184: .get_triplet = (void*)return_false,
185: .get_quintuplet = _get_quintuplet,
186: .resync = _resync,
187: .get_pseudonym = (void*)return_null,
188: .set_pseudonym = (void*)nop,
189: .get_reauth = (void*)return_null,
190: .set_reauth = (void*)nop,
191: },
192: .destroy = _destroy,
193: },
194: .f = f,
195: .seq_check = lib->settings->get_bool(lib->settings,
196: "%s.plugins.eap-aka-3gpp.seq_check",
197: #ifdef SEQ_CHECK /* handle legacy compile time configuration as default */
198: TRUE,
199: #else /* !SEQ_CHECK */
200: FALSE,
201: #endif /* SEQ_CHECK */
202: lib->ns),
203: );
204:
205: eap_aka_3gpp_get_sqn(this->sqn, 0);
206:
207: return &this->public;
208: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>