Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_functions.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: #include "eap_aka_3gpp2_functions.h"
17:
18: #include <gmp.h>
19: #include <limits.h>
20:
21: #include <daemon.h>
22:
23: typedef struct private_eap_aka_3gpp2_functions_t private_eap_aka_3gpp2_functions_t;
24:
25: /**
26: * Private data of an eap_aka_3gpp2_functions_t object.
27: */
28: struct private_eap_aka_3gpp2_functions_t {
29:
30: /**
31: * Public eap_aka_3gpp2_functions_t interface.
32: */
33: eap_aka_3gpp2_functions_t public;
34:
35: /**
36: * Used keyed SHA1 function, as PRF
37: */
38: prf_t *prf;
39: };
40:
41: #define AKA_PAYLOAD_LEN 64
42:
43: #define F1 0x42
44: #define F1STAR 0x43
45: #define F2 0x44
46: #define F3 0x45
47: #define F4 0x46
48: #define F5 0x47
49: #define F5STAR 0x48
50:
51: /** Family key, as proposed in S.S0055 */
52: static chunk_t fmk = chunk_from_chars(0x41, 0x48, 0x41, 0x47);
53:
54: /**
55: * Binary representation of the polynomial T^160 + T^5 + T^3 + T^2 + 1
56: */
57: static uint8_t g[] = {
58: 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60: 0x00, 0x00, 0x00, 0x00, 0x2d
61: };
62:
63: /**
64: * Predefined random bits from the RAND Corporation book
65: */
66: static uint8_t a_def[] = {
67: 0x9d, 0xe9, 0xc9, 0xc8, 0xef, 0xd5, 0x78, 0x11,
68: 0x48, 0x23, 0x14, 0x01, 0x90, 0x1f, 0x2d, 0x49,
69: 0x3f, 0x4c, 0x63, 0x65
70: };
71:
72: /**
73: * Predefined random bits from the RAND Corporation book
74: */
75: static uint8_t b_def[] = {
76: 0x75, 0xef, 0xd1, 0x5c, 0x4b, 0x8f, 0x8f, 0x51,
77: 0x4e, 0xf3, 0xbc, 0xc3, 0x79, 0x4a, 0x76, 0x5e,
78: 0x7e, 0xec, 0x45, 0xe0
79: };
80:
81: /**
82: * Multiply two mpz_t with bits interpreted as polynomials.
83: */
84: static void mpz_mul_poly(mpz_t r, mpz_t a, mpz_t b)
85: {
86: mpz_t bm, rm;
87: int current = 0, shifted = 0, shift;
88:
89: mpz_init_set(bm, b);
90: mpz_init_set_ui(rm, 0);
91: /* scan through a, for each found bit: */
92: while ((current = mpz_scan1(a, current)) != ULONG_MAX)
93: {
94: /* XOR shifted b into r */
95: shift = current - shifted;
96: mpz_mul_2exp(bm, bm, shift);
97: shifted += shift;
98: mpz_xor(rm, rm, bm);
99: current++;
100: }
101:
102: mpz_swap(r, rm);
103: mpz_clear(rm);
104: mpz_clear(bm);
105: }
106:
107: /**
108: * Calculate the sum of a + b interpreted as polynomials.
109: */
110: static void mpz_add_poly(mpz_t res, mpz_t a, mpz_t b)
111: {
112: /* addition of polynomials is just the XOR */
113: mpz_xor(res, a, b);
114: }
115:
116: /**
117: * Calculate the remainder of a/b interpreted as polynomials.
118: */
119: static void mpz_mod_poly(mpz_t r, mpz_t a, mpz_t b)
120: {
121: /* Example:
122: * a = 10001010
123: * b = 00000101
124: */
125: int a_bit, b_bit, diff;
126: mpz_t bm, am;
127:
128: mpz_init_set(am, a);
129: mpz_init(bm);
130:
131: a_bit = mpz_sizeinbase(a, 2);
132: b_bit = mpz_sizeinbase(b, 2);
133:
134: /* don't do anything if b > a */
135: if (a_bit >= b_bit)
136: {
137: /* shift b left to align up most significant "1" to a:
138: * a = 10001010
139: * b = 10100000
140: */
141: mpz_mul_2exp(bm, b, a_bit - b_bit);
142: do
143: {
144: /* XOR b into a, this kills the most significant "1":
145: * a = 00101010
146: */
147: mpz_xor(am, am, bm);
148: /* find the next most significant "1" in a, and align up b:
149: * a = 00101010
150: * b = 00101000
151: */
152: diff = a_bit - mpz_sizeinbase(am, 2);
153: mpz_div_2exp(bm, bm, diff);
154: a_bit -= diff;
155: }
156: while (b_bit <= mpz_sizeinbase(bm, 2));
157: /* While b is not shifted to its original value */
158: }
159: /* after another iteration:
160: * a = 00000010
161: * which is the polynomial modulo
162: */
163:
164: mpz_swap(r, am);
165: mpz_clear(am);
166: mpz_clear(bm);
167: }
168:
169: /**
170: * Step 3 of the various fx() functions:
171: * XOR the key into the SHA1 IV
172: */
173: static bool step3(prf_t *prf, u_char k[AKA_K_LEN],
174: u_char payload[AKA_PAYLOAD_LEN], uint8_t h[HASH_SIZE_SHA1])
175: {
176: /* use the keyed hasher to build the hash */
177: return prf->set_key(prf, chunk_create(k, AKA_K_LEN)) &&
178: prf->get_bytes(prf, chunk_create(payload, AKA_PAYLOAD_LEN), h);
179: }
180:
181: /**
182: * Step 4 of the various fx() functions:
183: * Polynomial whiten calculations
184: */
185: static void step4(u_char x[HASH_SIZE_SHA1])
186: {
187: mpz_t xm, am, bm, gm;
188:
189: mpz_init(xm);
190: mpz_init(am);
191: mpz_init(bm);
192: mpz_init(gm);
193:
194: mpz_import(xm, HASH_SIZE_SHA1, 1, 1, 1, 0, x);
195: mpz_import(am, sizeof(a_def), 1, 1, 1, 0, a_def);
196: mpz_import(bm, sizeof(b_def), 1, 1, 1, 0, b_def);
197: mpz_import(gm, sizeof(g), 1, 1, 1, 0, g);
198:
199: mpz_mul_poly(xm, am, xm);
200: mpz_add_poly(xm, bm, xm);
201: mpz_mod_poly(xm, xm, gm);
202:
203: mpz_export(x, NULL, 1, HASH_SIZE_SHA1, 1, 0, xm);
204:
205: mpz_clear(xm);
206: mpz_clear(am);
207: mpz_clear(bm);
208: mpz_clear(gm);
209: }
210:
211: /**
212: * Calculation function for f2(), f3(), f4()
213: */
214: static bool fx(prf_t *prf, u_char f, u_char k[AKA_K_LEN],
215: u_char rand[AKA_RAND_LEN], u_char out[AKA_MAC_LEN])
216: {
217: u_char payload[AKA_PAYLOAD_LEN];
218: u_char h[HASH_SIZE_SHA1];
219: u_char i;
220:
221: for (i = 0; i < 2; i++)
222: {
223: memset(payload, 0x5c, AKA_PAYLOAD_LEN);
224: payload[11] ^= f;
225: memxor(payload + 12, fmk.ptr, fmk.len);
226: memxor(payload + 24, rand, AKA_RAND_LEN);
227:
228: payload[3] ^= i;
229: payload[19] ^= i;
230: payload[35] ^= i;
231: payload[51] ^= i;
232:
233: if (!step3(prf, k, payload, h))
234: {
235: return FALSE;
236: }
237: step4(h);
238: memcpy(out + i * 8, h, 8);
239: }
240: return TRUE;
241: }
242:
243: /**
244: * Calculation function of f1() and f1star()
245: */
246: static bool f1x(prf_t *prf, uint8_t f, u_char k[AKA_K_LEN],
247: u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
248: u_char amf[AKA_AMF_LEN], u_char mac[AKA_MAC_LEN])
249: {
250: /* generate MAC = f1(FMK, SQN, RAND, AMF)
251: * K is loaded into hashers IV; FMK, RAND, SQN, AMF are XORed in a 512-bit
252: * payload which gets hashed
253: */
254: u_char payload[AKA_PAYLOAD_LEN];
255: u_char h[HASH_SIZE_SHA1];
256:
257: memset(payload, 0x5c, AKA_PAYLOAD_LEN);
258: payload[11] ^= f;
259: memxor(payload + 12, fmk.ptr, fmk.len);
260: memxor(payload + 16, rand, AKA_RAND_LEN);
261: memxor(payload + 34, sqn, AKA_SQN_LEN);
262: memxor(payload + 42, amf, AKA_AMF_LEN);
263:
264: if (!step3(prf, k, payload, h))
265: {
266: return FALSE;
267: }
268: step4(h);
269: memcpy(mac, h, AKA_MAC_LEN);
270: return TRUE;
271: }
272:
273: /**
274: * Calculation function of f5() and f5star()
275: */
276: static bool f5x(prf_t *prf, u_char f, u_char k[AKA_K_LEN],
277: u_char rand[AKA_RAND_LEN], u_char ak[AKA_AK_LEN])
278: {
279: u_char payload[AKA_PAYLOAD_LEN];
280: u_char h[HASH_SIZE_SHA1];
281:
282: memset(payload, 0x5c, AKA_PAYLOAD_LEN);
283: payload[11] ^= f;
284: memxor(payload + 12, fmk.ptr, fmk.len);
285: memxor(payload + 16, rand, AKA_RAND_LEN);
286:
287: if (!step3(prf, k, payload, h))
288: {
289: return FALSE;
290: }
291: step4(h);
292: memcpy(ak, h, AKA_AK_LEN);
293: return TRUE;
294: }
295:
296: /**
297: * Calculate MAC from RAND, SQN, AMF using K
298: */
299: METHOD(eap_aka_3gpp2_functions_t, f1, bool,
300: private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
301: u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
302: u_char amf[AKA_AMF_LEN], u_char mac[AKA_MAC_LEN])
303: {
304: if (f1x(this->prf, F1, k, rand, sqn, amf, mac))
305: {
306: DBG3(DBG_IKE, "MAC %b", mac, AKA_MAC_LEN);
307: return TRUE;
308: }
309: return FALSE;
310: }
311:
312: /**
313: * Calculate MACS from RAND, SQN, AMF using K
314: */
315: METHOD(eap_aka_3gpp2_functions_t, f1star, bool,
316: private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
317: u_char rand[AKA_RAND_LEN], u_char sqn[AKA_SQN_LEN],
318: u_char amf[AKA_AMF_LEN], u_char macs[AKA_MAC_LEN])
319: {
320: if (f1x(this->prf, F1STAR, k, rand, sqn, amf, macs))
321: {
322: DBG3(DBG_IKE, "MACS %b", macs, AKA_MAC_LEN);
323: return TRUE;
324: }
325: return FALSE;
326: }
327:
328: /**
329: * Calculate RES from RAND using K
330: */
331: METHOD(eap_aka_3gpp2_functions_t, f2, bool,
332: private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
333: u_char rand[AKA_RAND_LEN], u_char res[AKA_RES_MAX])
334: {
335: if (fx(this->prf, F2, k, rand, res))
336: {
337: DBG3(DBG_IKE, "RES %b", res, AKA_RES_MAX);
338: return TRUE;
339: }
340: return FALSE;
341: }
342:
343: /**
344: * Calculate CK from RAND using K
345: */
346: METHOD(eap_aka_3gpp2_functions_t, f3, bool,
347: private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
348: u_char rand[AKA_RAND_LEN], u_char ck[AKA_CK_LEN])
349: {
350: if (fx(this->prf, F3, k, rand, ck))
351: {
352: DBG3(DBG_IKE, "CK %b", ck, AKA_CK_LEN);
353: return TRUE;
354: }
355: return FALSE;
356: }
357:
358: /**
359: * Calculate IK from RAND using K
360: */
361: METHOD(eap_aka_3gpp2_functions_t, f4, bool,
362: private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
363: u_char rand[AKA_RAND_LEN], u_char ik[AKA_IK_LEN])
364: {
365: if (fx(this->prf, F4, k, rand, ik))
366: {
367: DBG3(DBG_IKE, "IK %b", ik, AKA_IK_LEN);
368: return TRUE;
369: }
370: return FALSE;
371: }
372:
373: /**
374: * Calculate AK from a RAND using K
375: */
376: METHOD(eap_aka_3gpp2_functions_t, f5, bool,
377: private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
378: u_char rand[AKA_RAND_LEN], u_char ak[AKA_AK_LEN])
379: {
380: if (f5x(this->prf, F5, k, rand, ak))
381: {
382: DBG3(DBG_IKE, "AK %b", ak, AKA_AK_LEN);
383: return TRUE;
384: }
385: return FALSE;
386: }
387:
388: /**
389: * Calculate AKS from a RAND using K
390: */
391: METHOD(eap_aka_3gpp2_functions_t, f5star, bool,
392: private_eap_aka_3gpp2_functions_t *this, u_char k[AKA_K_LEN],
393: u_char rand[AKA_RAND_LEN], u_char aks[AKA_AK_LEN])
394: {
395: if (f5x(this->prf, F5STAR, k, rand, aks))
396: {
397: DBG3(DBG_IKE, "AKS %b", aks, AKA_AK_LEN);
398: return TRUE;
399: }
400: return FALSE;
401: }
402:
403: METHOD(eap_aka_3gpp2_functions_t, destroy, void,
404: private_eap_aka_3gpp2_functions_t *this)
405: {
406: this->prf->destroy(this->prf);
407: free(this);
408: }
409:
410: /**
411: * See header
412: */
413: eap_aka_3gpp2_functions_t *eap_aka_3gpp2_functions_create()
414: {
415: private_eap_aka_3gpp2_functions_t *this;
416:
417: INIT(this,
418: .public = {
419: .f1 = _f1,
420: .f1star = _f1star,
421: .f2 = _f2,
422: .f3 = _f3,
423: .f4 = _f4,
424: .f5 = _f5,
425: .f5star = _f5star,
426: .destroy = _destroy,
427: },
428: .prf = lib->crypto->create_prf(lib->crypto, PRF_KEYED_SHA1),
429: );
430: if (!this->prf)
431: {
432: DBG1(DBG_CFG, "%N not supported, unable to use 3GPP2 algorithm",
433: pseudo_random_function_names, PRF_KEYED_SHA1);
434: free(this);
435: return NULL;
436: }
437: return &this->public;
438: }
439:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>