Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_aka_3gpp/eap_aka_3gpp_functions.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2017 Tobias Brunner
3: * Copyright (C) 2008-2009 Martin Willi
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2 of the License, or (at your
9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: * for more details.
15: */
16: /*
17: * Copyright (C) 2015 Thomas Strangert
18: * Polystar System AB, Sweden
19: *
20: * Permission is hereby granted, free of charge, to any person obtaining a copy
21: * of this software and associated documentation files (the "Software"), to deal
22: * in the Software without restriction, including without limitation the rights
23: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24: * copies of the Software, and to permit persons to whom the Software is
25: * furnished to do so, subject to the following conditions:
26: *
27: * The above copyright notice and this permission notice shall be included in
28: * all copies or substantial portions of the Software.
29: *
30: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36: * THE SOFTWARE.
37: */
38:
39: #include "eap_aka_3gpp_functions.h"
40:
41: #include <limits.h>
42: #include <ctype.h>
43: #include <daemon.h>
44:
45: typedef struct private_eap_aka_3gpp_functions_t private_eap_aka_3gpp_functions_t;
46:
47: /**
48: * Private data of an eap_aka_3gpp_functions_t object.
49: */
50: struct private_eap_aka_3gpp_functions_t {
51:
52: /**
53: * Public eap_aka_3gpp_functions_t interface.
54: */
55: eap_aka_3gpp_functions_t public;
56:
57: /**
58: * AES instance
59: */
60: crypter_t *crypter;
61: };
62:
63: /*
64: * Described in header
65: */
66: bool eap_aka_3gpp_get_k_opc(identification_t *id, uint8_t k[AKA_K_LEN],
67: uint8_t opc[AKA_OPC_LEN])
68: {
69: shared_key_t *shared;
70: chunk_t key;
71:
72: shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, id, NULL);
73: if (!shared)
74: {
75: return FALSE;
76: }
77: key = shared->get_key(shared);
78:
79: if (key.len == AKA_K_LEN)
80: {
81: memcpy(k, key.ptr, AKA_K_LEN);
82: /* set OPc to a neutral default value, harmless to XOR with */
83: memset(opc, '\0', AKA_OPC_LEN);
84: }
85: else if (key.len == AKA_K_LEN + AKA_OPC_LEN)
86: {
87: memcpy(k, key.ptr, AKA_K_LEN);
88: memcpy(opc, key.ptr + AKA_K_LEN, AKA_OPC_LEN);
89: }
90: else
91: {
92: DBG1(DBG_IKE, "invalid EAP K or K+OPc key found for %Y to authenticate "
93: "with AKA, should be a %d or %d byte long binary value", id,
94: AKA_K_LEN, AKA_K_LEN + AKA_OPC_LEN);
95: shared->destroy(shared);
96: return FALSE;
97: }
98: shared->destroy(shared);
99: return TRUE;
100: }
101:
102: /*
103: * Described in header
104: */
105: void eap_aka_3gpp_get_sqn(uint8_t sqn[AKA_SQN_LEN], int offset)
106: {
107: timeval_t time;
108:
109: gettimeofday(&time, NULL);
110: /* set sqn to an integer containing 4 bytes seconds + 2 bytes usecs */
111: time.tv_sec = htonl(time.tv_sec + offset);
112: /* usec's are never larger than 0x000f423f, so we shift the 12 first bits */
113: time.tv_usec = htonl(time.tv_usec << 12);
114: memcpy(sqn, (uint8_t*)&time.tv_sec + sizeof(time_t) - 4, 4);
115: memcpy(sqn + 4, &time.tv_usec, 2);
116: }
117:
118: static bool f1andf1star(private_eap_aka_3gpp_functions_t *this,
119: const uint8_t k[AKA_K_LEN], const uint8_t opc[AKA_OPC_LEN],
120: const uint8_t rand[AKA_RAND_LEN], const uint8_t sqn[AKA_SQN_LEN],
121: const uint8_t amf[AKA_AMF_LEN], uint8_t mac[16])
122: {
123: uint8_t i, data[16], in[16], iv[16] = { 0 };
124:
125: if (!this->crypter->set_key(this->crypter,
126: chunk_create((uint8_t*)k, AKA_K_LEN)))
127: {
128: return FALSE;
129: }
130:
131: /* XOR RAND and OPc */
132: memcpy(data, rand, sizeof(data));
133: memxor(data, opc, sizeof(data));
134: if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
135: chunk_create(iv, sizeof(iv)), NULL))
136: {
137: return FALSE;
138: }
139:
140: /* concatenate SQN || AMF ||SQN || AMF */
141: memcpy(in, sqn, 6);
142: memcpy(&in[6], amf, 2);
143: memcpy(&in[8], in, 8);
144:
145: /* XOR opc and in, rotate by r1=64, and XOR
146: * on the constant c1 (which is all zeroes) and finally the output above */
147: for (i = 0; i < 16; i++)
148: {
149: data[(i + 8) % 16] ^= in[i] ^ opc[i];
150: }
151: if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
152: chunk_create(iv, sizeof(iv)), NULL))
153: {
154: return FALSE;
155: }
156: memxor(data, opc, sizeof(data));
157: memcpy(mac, data, 16);
158: return TRUE;
159: }
160:
161: METHOD(eap_aka_3gpp_functions_t, f1, bool,
162: private_eap_aka_3gpp_functions_t *this, const uint8_t k[AKA_K_LEN],
163: const uint8_t opc[AKA_OPC_LEN], const uint8_t rand[AKA_RAND_LEN],
164: const uint8_t sqn[AKA_SQN_LEN], const uint8_t amf[AKA_AMF_LEN],
165: uint8_t maca[AKA_MAC_LEN])
166: {
167: uint8_t mac[16];
168:
169: if (!f1andf1star(this, k, opc, rand, sqn, amf, mac))
170: {
171: return FALSE;
172: }
173: /* only diff between f1 and f1* is here:
174: * f1 uses bytes 0-7 as MAC-A
175: * f1* uses bytes 8-15 as MAC-S */
176: memcpy(maca, mac, AKA_MAC_LEN);
177: return TRUE;
178: }
179:
180: METHOD(eap_aka_3gpp_functions_t, f1star, bool,
181: private_eap_aka_3gpp_functions_t *this, const uint8_t k[AKA_K_LEN],
182: const uint8_t opc[AKA_OPC_LEN], const uint8_t rand[AKA_RAND_LEN],
183: const uint8_t sqn[AKA_SQN_LEN], const uint8_t amf[AKA_AMF_LEN],
184: uint8_t macs[AKA_MAC_LEN])
185: {
186: uint8_t mac[16];
187:
188: if (!f1andf1star(this, k, opc, rand, sqn, amf, mac))
189: {
190: return FALSE;
191: }
192: /* only diff between f1 and f1* is here:
193: * f1 uses bytes 0-7 as MAC-A
194: * f1* uses bytes 8-15 as MAC-S */
195: memcpy(macs, &mac[8], AKA_MAC_LEN);
196: return TRUE;
197: }
198:
199: METHOD(eap_aka_3gpp_functions_t, f2345, bool,
200: private_eap_aka_3gpp_functions_t *this, const uint8_t k[AKA_K_LEN],
201: const uint8_t opc[AKA_OPC_LEN], const uint8_t rand[AKA_RAND_LEN],
202: uint8_t res[AKA_RES_LEN], uint8_t ck[AKA_CK_LEN], uint8_t ik[AKA_IK_LEN],
203: uint8_t ak[AKA_AK_LEN])
204: {
205: uint8_t data[16], iv[16] = { 0 };
206: chunk_t temp;
207: uint8_t i;
208:
209: if (!this->crypter->set_key(this->crypter,
210: chunk_create((uint8_t*)k, AKA_K_LEN)))
211: {
212: return FALSE;
213: }
214:
215: /* XOR RAND and OPc */
216: memcpy(data, rand, sizeof(data));
217: memxor(data, opc, sizeof(data));
218: if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
219: chunk_create(iv, sizeof(iv)), &temp))
220: {
221: return FALSE;
222: }
223:
224: /* to obtain output block OUT2: XOR OPc and TEMP,
225: * rotate by r2=0, and XOR on the constant c2 (which is all zeroes except
226: * that the last bit is 1). */
227: for (i = 0; i < 16; i++)
228: {
229: data[i] = temp.ptr[i] ^ opc[i];
230: }
231: data[15] ^= 1;
232:
233: if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
234: chunk_create(iv, sizeof(iv)), NULL))
235: {
236: chunk_free(&temp);
237: return FALSE;
238: }
239: memxor(data, opc, sizeof(data));
240:
241: /* f5 output */
242: memcpy(ak, data, 6);
243: /* f2 output */
244: memcpy(res, &data[8], 8);
245:
246: /* to obtain output block OUT3: XOR OPc and TEMP,
247: * rotate by r3=32, and XOR on the constant c3 (which
248: * is all zeroes except that the next to last bit is 1) */
249: for (i = 0; i < 16; i++)
250: {
251: data[(i + 12) % 16] = temp.ptr[i] ^ opc[i];
252: }
253: data[15] ^= 2;
254:
255: if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
256: chunk_create(iv, sizeof(iv)), NULL))
257: {
258: chunk_free(&temp);
259: return FALSE;
260: }
261: memxor(data, opc, sizeof(data));
262:
263: /* f3 output */
264: memcpy(ck, data, 16);
265:
266: /* to obtain output block OUT4: XOR OPc and TEMP,
267: * rotate by r4=64, and XOR on the constant c4 (which
268: * is all zeroes except that the 2nd from last bit is 1). */
269: for (i = 0; i < 16; i++)
270: {
271: data[(i + 8) % 16] = temp.ptr[i] ^ opc[i];
272: }
273: data[15] ^= 4;
274:
275: if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
276: chunk_create(iv, sizeof(iv)), NULL))
277: {
278: chunk_free(&temp);
279: return FALSE;
280: }
281: memxor(data, opc, sizeof(data));
282: /* f4 output */
283: memcpy(ik, data, 16);
284: chunk_free(&temp);
285: return TRUE;
286:
287: }
288:
289: METHOD(eap_aka_3gpp_functions_t, f5star, bool,
290: private_eap_aka_3gpp_functions_t *this, const uint8_t k[AKA_K_LEN],
291: const uint8_t opc[AKA_OPC_LEN], const uint8_t rand[AKA_RAND_LEN],
292: uint8_t aks[AKA_AK_LEN])
293: {
294: uint8_t i, data[16], iv[16] = { 0 };
295: chunk_t temp;
296:
297: if (!this->crypter->set_key(this->crypter,
298: chunk_create((uint8_t*)k, AKA_K_LEN)))
299: {
300: return FALSE;
301: }
302:
303: /* XOR RAND and OPc */
304: memcpy(data, rand, sizeof(data));
305: memxor(data, opc, sizeof(data));
306: if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
307: chunk_create(iv, sizeof(iv)), &temp))
308: {
309: return FALSE;
310: }
311:
312: /* to obtain output block OUT5: XOR OPc and the output above,
313: * rotate by r5=96, and XOR on the constant c5 (which
314: * is all zeroes except that the 3rd from last bit is 1). */
315: for (i = 0; i < 16; i++)
316: {
317: data[(i + 4) % 16] = temp.ptr[i] ^ opc[i];
318: }
319: data[15] ^= 8;
320: chunk_free(&temp);
321:
322: if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
323: chunk_create(iv, sizeof(iv)), NULL))
324: {
325: return FALSE;
326: }
327: memxor(data, opc, sizeof(data));
328: memcpy(aks, data, 6);
329: return TRUE;
330: }
331:
332: METHOD(eap_aka_3gpp_functions_t, destroy, void,
333: private_eap_aka_3gpp_functions_t *this)
334: {
335: this->crypter->destroy(this->crypter);
336: free(this);
337: }
338:
339: /**
340: * See header
341: */
342: eap_aka_3gpp_functions_t *eap_aka_3gpp_functions_create()
343: {
344: private_eap_aka_3gpp_functions_t *this;
345:
346: INIT(this,
347: .public = {
348: .f1 = _f1,
349: .f1star = _f1star,
350: .f2345 = _f2345,
351: .f5star = _f5star,
352: .destroy = _destroy,
353: },
354: .crypter = lib->crypto->create_crypter(lib->crypto, ENCR_AES_CBC, 16),
355: );
356: if (!this->crypter)
357: {
358: DBG1(DBG_IKE, "%N not supported, unable to use 3GPP algorithm",
359: encryption_algorithm_names, ENCR_AES_CBC);
360: free(this);
361: return NULL;
362: }
363: return &this->public;
364: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>