]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa/src/eap_server/eap_server_pax.c
Update hostapd/wpa_supplicant to 2.8 to fix multiple vulnerabilities.
[FreeBSD/FreeBSD.git] / contrib / wpa / src / eap_server / eap_server_pax.c
1 /*
2  * hostapd / EAP-PAX (RFC 4746) server
3  * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "crypto/random.h"
13 #include "eap_server/eap_i.h"
14 #include "eap_common/eap_pax_common.h"
15
16 /*
17  * Note: only PAX_STD subprotocol is currently supported
18  *
19  * TODO: Add support with PAX_SEC with the mandatory to implement ciphersuite
20  * (HMAC_SHA1_128, IANA DH Group 14 (2048 bits), RSA-PKCS1-V1_5) and
21  * recommended ciphersuite (HMAC_SHA256_128, IANA DH Group 15 (3072 bits),
22  * RSAES-OAEP).
23  */
24
25 struct eap_pax_data {
26         enum { PAX_STD_1, PAX_STD_3, SUCCESS, FAILURE } state;
27         u8 mac_id;
28         union {
29                 u8 e[2 * EAP_PAX_RAND_LEN];
30                 struct {
31                         u8 x[EAP_PAX_RAND_LEN]; /* server rand */
32                         u8 y[EAP_PAX_RAND_LEN]; /* client rand */
33                 } r;
34         } rand;
35         u8 ak[EAP_PAX_AK_LEN];
36         u8 mk[EAP_PAX_MK_LEN];
37         u8 ck[EAP_PAX_CK_LEN];
38         u8 ick[EAP_PAX_ICK_LEN];
39         u8 mid[EAP_PAX_MID_LEN];
40         int keys_set;
41         char *cid;
42         size_t cid_len;
43 };
44
45
46 static void * eap_pax_init(struct eap_sm *sm)
47 {
48         struct eap_pax_data *data;
49
50         data = os_zalloc(sizeof(*data));
51         if (data == NULL)
52                 return NULL;
53         data->state = PAX_STD_1;
54         /*
55          * TODO: make this configurable once EAP_PAX_HMAC_SHA256_128 is
56          * supported
57          */
58         data->mac_id = EAP_PAX_MAC_HMAC_SHA1_128;
59
60         return data;
61 }
62
63
64 static void eap_pax_reset(struct eap_sm *sm, void *priv)
65 {
66         struct eap_pax_data *data = priv;
67         os_free(data->cid);
68         bin_clear_free(data, sizeof(*data));
69 }
70
71
72 static struct wpabuf * eap_pax_build_std_1(struct eap_sm *sm,
73                                            struct eap_pax_data *data, u8 id)
74 {
75         struct wpabuf *req;
76         struct eap_pax_hdr *pax;
77         u8 *pos;
78
79         wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (sending)");
80
81         if (random_get_bytes(data->rand.r.x, EAP_PAX_RAND_LEN)) {
82                 wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data");
83                 data->state = FAILURE;
84                 return NULL;
85         }
86
87         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX,
88                             sizeof(*pax) + 2 + EAP_PAX_RAND_LEN +
89                             EAP_PAX_ICV_LEN, EAP_CODE_REQUEST, id);
90         if (req == NULL) {
91                 wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory "
92                            "request");
93                 data->state = FAILURE;
94                 return NULL;
95         }
96
97         pax = wpabuf_put(req, sizeof(*pax));
98         pax->op_code = EAP_PAX_OP_STD_1;
99         pax->flags = 0;
100         pax->mac_id = data->mac_id;
101         pax->dh_group_id = EAP_PAX_DH_GROUP_NONE;
102         pax->public_key_id = EAP_PAX_PUBLIC_KEY_NONE;
103
104         wpabuf_put_be16(req, EAP_PAX_RAND_LEN);
105         wpabuf_put_data(req, data->rand.r.x, EAP_PAX_RAND_LEN);
106         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: A = X (server rand)",
107                     data->rand.r.x, EAP_PAX_RAND_LEN);
108
109         pos = wpabuf_put(req, EAP_PAX_MAC_LEN);
110         if (eap_pax_mac(data->mac_id, (u8 *) "", 0,
111                         wpabuf_mhead(req), wpabuf_len(req) - EAP_PAX_ICV_LEN,
112                         NULL, 0, NULL, 0, pos) < 0) {
113                 wpa_printf(MSG_ERROR, "EAP-PAX: Failed to calculate ICV");
114                 data->state = FAILURE;
115                 wpabuf_free(req);
116                 return NULL;
117         }
118         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN);
119
120         return req;
121 }
122
123
124 static struct wpabuf * eap_pax_build_std_3(struct eap_sm *sm,
125                                            struct eap_pax_data *data, u8 id)
126 {
127         struct wpabuf *req;
128         struct eap_pax_hdr *pax;
129         u8 *pos;
130
131         wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-3 (sending)");
132
133         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX,
134                             sizeof(*pax) + 2 + EAP_PAX_MAC_LEN +
135                             EAP_PAX_ICV_LEN, EAP_CODE_REQUEST, id);
136         if (req == NULL) {
137                 wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory "
138                            "request");
139                 data->state = FAILURE;
140                 return NULL;
141         }
142
143         pax = wpabuf_put(req, sizeof(*pax));
144         pax->op_code = EAP_PAX_OP_STD_3;
145         pax->flags = 0;
146         pax->mac_id = data->mac_id;
147         pax->dh_group_id = EAP_PAX_DH_GROUP_NONE;
148         pax->public_key_id = EAP_PAX_PUBLIC_KEY_NONE;
149
150         wpabuf_put_be16(req, EAP_PAX_MAC_LEN);
151         pos = wpabuf_put(req, EAP_PAX_MAC_LEN);
152         if (eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN,
153                         data->rand.r.y, EAP_PAX_RAND_LEN,
154                         (u8 *) data->cid, data->cid_len, NULL, 0, pos) < 0) {
155                 wpa_printf(MSG_ERROR, "EAP-PAX: Failed to calculate MAC");
156                 data->state = FAILURE;
157                 wpabuf_free(req);
158                 return NULL;
159         }
160         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)",
161                     pos, EAP_PAX_MAC_LEN);
162
163         /* Optional ADE could be added here, if needed */
164
165         pos = wpabuf_put(req, EAP_PAX_MAC_LEN);
166         if (eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
167                         wpabuf_mhead(req), wpabuf_len(req) - EAP_PAX_ICV_LEN,
168                         NULL, 0, NULL, 0, pos) < 0) {
169                 wpa_printf(MSG_ERROR, "EAP-PAX: Failed to calculate ICV");
170                 data->state = FAILURE;
171                 wpabuf_free(req);
172                 return NULL;
173         }
174         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN);
175
176         return req;
177 }
178
179
180 static struct wpabuf * eap_pax_buildReq(struct eap_sm *sm, void *priv, u8 id)
181 {
182         struct eap_pax_data *data = priv;
183
184         switch (data->state) {
185         case PAX_STD_1:
186                 return eap_pax_build_std_1(sm, data, id);
187         case PAX_STD_3:
188                 return eap_pax_build_std_3(sm, data, id);
189         default:
190                 wpa_printf(MSG_DEBUG, "EAP-PAX: Unknown state %d in buildReq",
191                            data->state);
192                 break;
193         }
194         return NULL;
195 }
196
197
198 static Boolean eap_pax_check(struct eap_sm *sm, void *priv,
199                              struct wpabuf *respData)
200 {
201         struct eap_pax_data *data = priv;
202         struct eap_pax_hdr *resp;
203         const u8 *pos;
204         size_t len, mlen;
205         u8 icvbuf[EAP_PAX_ICV_LEN], *icv;
206
207         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len);
208         if (pos == NULL || len < sizeof(*resp) + EAP_PAX_ICV_LEN) {
209                 wpa_printf(MSG_INFO, "EAP-PAX: Invalid frame");
210                 return TRUE;
211         }
212
213         mlen = sizeof(struct eap_hdr) + 1 + len;
214         resp = (struct eap_pax_hdr *) pos;
215
216         wpa_printf(MSG_DEBUG, "EAP-PAX: received frame: op_code 0x%x "
217                    "flags 0x%x mac_id 0x%x dh_group_id 0x%x "
218                    "public_key_id 0x%x",
219                    resp->op_code, resp->flags, resp->mac_id, resp->dh_group_id,
220                    resp->public_key_id);
221         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: received payload",
222                     (u8 *) (resp + 1), len - sizeof(*resp) - EAP_PAX_ICV_LEN);
223
224         if (data->state == PAX_STD_1 &&
225             resp->op_code != EAP_PAX_OP_STD_2) {
226                 wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX_STD-2 - "
227                            "ignore op %d", resp->op_code);
228                 return TRUE;
229         }
230
231         if (data->state == PAX_STD_3 &&
232             resp->op_code != EAP_PAX_OP_ACK) {
233                 wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX-ACK - "
234                            "ignore op %d", resp->op_code);
235                 return TRUE;
236         }
237
238         if (resp->op_code != EAP_PAX_OP_STD_2 &&
239             resp->op_code != EAP_PAX_OP_ACK) {
240                 wpa_printf(MSG_DEBUG, "EAP-PAX: Unknown op_code 0x%x",
241                            resp->op_code);
242         }
243
244         if (data->mac_id != resp->mac_id) {
245                 wpa_printf(MSG_DEBUG, "EAP-PAX: Expected MAC ID 0x%x, "
246                            "received 0x%x", data->mac_id, resp->mac_id);
247                 return TRUE;
248         }
249
250         if (resp->dh_group_id != EAP_PAX_DH_GROUP_NONE) {
251                 wpa_printf(MSG_INFO, "EAP-PAX: Expected DH Group ID 0x%x, "
252                            "received 0x%x", EAP_PAX_DH_GROUP_NONE,
253                            resp->dh_group_id);
254                 return TRUE;
255         }
256
257         if (resp->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) {
258                 wpa_printf(MSG_INFO, "EAP-PAX: Expected Public Key ID 0x%x, "
259                            "received 0x%x", EAP_PAX_PUBLIC_KEY_NONE,
260                            resp->public_key_id);
261                 return TRUE;
262         }
263
264         if (resp->flags & EAP_PAX_FLAGS_MF) {
265                 /* TODO: add support for reassembling fragments */
266                 wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported");
267                 return TRUE;
268         }
269
270         if (resp->flags & EAP_PAX_FLAGS_CE) {
271                 wpa_printf(MSG_INFO, "EAP-PAX: Unexpected CE flag");
272                 return TRUE;
273         }
274
275         if (data->keys_set) {
276                 if (len - sizeof(*resp) < EAP_PAX_ICV_LEN) {
277                         wpa_printf(MSG_INFO, "EAP-PAX: No ICV in the packet");
278                         return TRUE;
279                 }
280                 icv = wpabuf_mhead_u8(respData) + mlen - EAP_PAX_ICV_LEN;
281                 wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", icv, EAP_PAX_ICV_LEN);
282                 if (eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
283                                 wpabuf_mhead(respData),
284                                 wpabuf_len(respData) - EAP_PAX_ICV_LEN,
285                                 NULL, 0, NULL, 0, icvbuf) < 0 ||
286                     os_memcmp_const(icvbuf, icv, EAP_PAX_ICV_LEN) != 0) {
287                         wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV");
288                         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV",
289                                     icvbuf, EAP_PAX_ICV_LEN);
290                         return TRUE;
291                 }
292         }
293
294         return FALSE;
295 }
296
297
298 static void eap_pax_process_std_2(struct eap_sm *sm,
299                                   struct eap_pax_data *data,
300                                   struct wpabuf *respData)
301 {
302         struct eap_pax_hdr *resp;
303         u8 mac[EAP_PAX_MAC_LEN], icvbuf[EAP_PAX_ICV_LEN];
304         const u8 *pos;
305         size_t len, left, cid_len;
306         int i;
307
308         if (data->state != PAX_STD_1)
309                 return;
310
311         wpa_printf(MSG_DEBUG, "EAP-PAX: Received PAX_STD-2");
312
313         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len);
314         if (pos == NULL || len < sizeof(*resp) + EAP_PAX_ICV_LEN)
315                 return;
316
317         resp = (struct eap_pax_hdr *) pos;
318         pos = (u8 *) (resp + 1);
319         left = len - sizeof(*resp);
320
321         if (left < 2 + EAP_PAX_RAND_LEN ||
322             WPA_GET_BE16(pos) != EAP_PAX_RAND_LEN) {
323                 wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (B)");
324                 return;
325         }
326         pos += 2;
327         left -= 2;
328         os_memcpy(data->rand.r.y, pos, EAP_PAX_RAND_LEN);
329         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)",
330                     data->rand.r.y, EAP_PAX_RAND_LEN);
331         pos += EAP_PAX_RAND_LEN;
332         left -= EAP_PAX_RAND_LEN;
333
334         if (left < 2 || (size_t) 2 + WPA_GET_BE16(pos) > left) {
335                 wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (CID)");
336                 return;
337         }
338         cid_len = WPA_GET_BE16(pos);
339         if (cid_len > 1500) {
340                 wpa_printf(MSG_INFO, "EAP-PAX: Too long CID");
341                 return;
342         }
343         data->cid_len = cid_len;
344         os_free(data->cid);
345         data->cid = os_memdup(pos + 2, data->cid_len);
346         if (data->cid == NULL) {
347                 wpa_printf(MSG_INFO, "EAP-PAX: Failed to allocate memory for "
348                            "CID");
349                 return;
350         }
351         pos += 2 + data->cid_len;
352         left -= 2 + data->cid_len;
353         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID",
354                           (u8 *) data->cid, data->cid_len);
355
356         if (left < 2 + EAP_PAX_MAC_LEN ||
357             WPA_GET_BE16(pos) != EAP_PAX_MAC_LEN) {
358                 wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (MAC_CK)");
359                 return;
360         }
361         pos += 2;
362         left -= 2;
363         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(A, B, CID)",
364                     pos, EAP_PAX_MAC_LEN);
365
366         if (eap_user_get(sm, (u8 *) data->cid, data->cid_len, 0) < 0) {
367                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: unknown CID",
368                                   (u8 *) data->cid, data->cid_len);
369                 data->state = FAILURE;
370                 return;
371         }
372
373         for (i = 0;
374              i < EAP_MAX_METHODS &&
375                      (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
376                       sm->user->methods[i].method != EAP_TYPE_NONE);
377              i++) {
378                 if (sm->user->methods[i].vendor == EAP_VENDOR_IETF &&
379                     sm->user->methods[i].method == EAP_TYPE_PAX)
380                         break;
381         }
382
383         if (i >= EAP_MAX_METHODS ||
384             sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
385             sm->user->methods[i].method != EAP_TYPE_PAX) {
386                 wpa_hexdump_ascii(MSG_DEBUG,
387                                   "EAP-PAX: EAP-PAX not enabled for CID",
388                                   (u8 *) data->cid, data->cid_len);
389                 data->state = FAILURE;
390                 return;
391         }
392
393         if (sm->user->password == NULL ||
394             sm->user->password_len != EAP_PAX_AK_LEN) {
395                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: invalid password in "
396                                   "user database for CID",
397                                   (u8 *) data->cid, data->cid_len);
398                 data->state = FAILURE;
399                 return;
400         }
401         os_memcpy(data->ak, sm->user->password, EAP_PAX_AK_LEN);
402
403         if (eap_pax_initial_key_derivation(data->mac_id, data->ak,
404                                            data->rand.e, data->mk, data->ck,
405                                            data->ick, data->mid) < 0) {
406                 wpa_printf(MSG_INFO, "EAP-PAX: Failed to complete initial "
407                            "key derivation");
408                 data->state = FAILURE;
409                 return;
410         }
411         data->keys_set = 1;
412
413         if (eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN,
414                         data->rand.r.x, EAP_PAX_RAND_LEN,
415                         data->rand.r.y, EAP_PAX_RAND_LEN,
416                         (u8 *) data->cid, data->cid_len, mac) < 0 ||
417             os_memcmp_const(mac, pos, EAP_PAX_MAC_LEN) != 0) {
418                 wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(A, B, CID) in "
419                            "PAX_STD-2");
420                 wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected MAC_CK(A, B, CID)",
421                             mac, EAP_PAX_MAC_LEN);
422                 data->state = FAILURE;
423                 return;
424         }
425
426         pos += EAP_PAX_MAC_LEN;
427         left -= EAP_PAX_MAC_LEN;
428
429         if (left < EAP_PAX_ICV_LEN) {
430                 wpa_printf(MSG_INFO, "EAP-PAX: Too short ICV (%lu) in "
431                            "PAX_STD-2", (unsigned long) left);
432                 return;
433         }
434         wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN);
435         if (eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
436                         wpabuf_head(respData),
437                         wpabuf_len(respData) - EAP_PAX_ICV_LEN, NULL, 0,
438                         NULL, 0, icvbuf) < 0 ||
439             os_memcmp_const(icvbuf, pos, EAP_PAX_ICV_LEN) != 0) {
440                 wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV in PAX_STD-2");
441                 wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV",
442                             icvbuf, EAP_PAX_ICV_LEN);
443                 return;
444         }
445         pos += EAP_PAX_ICV_LEN;
446         left -= EAP_PAX_ICV_LEN;
447
448         if (left > 0) {
449                 wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload",
450                             pos, left);
451         }
452
453         data->state = PAX_STD_3;
454 }
455
456
457 static void eap_pax_process_ack(struct eap_sm *sm,
458                                 struct eap_pax_data *data,
459                                 struct wpabuf *respData)
460 {
461         if (data->state != PAX_STD_3)
462                 return;
463
464         wpa_printf(MSG_DEBUG, "EAP-PAX: Received PAX-ACK - authentication "
465                    "completed successfully");
466         data->state = SUCCESS;
467 }
468
469
470 static void eap_pax_process(struct eap_sm *sm, void *priv,
471                             struct wpabuf *respData)
472 {
473         struct eap_pax_data *data = priv;
474         struct eap_pax_hdr *resp;
475         const u8 *pos;
476         size_t len;
477
478         if (sm->user == NULL || sm->user->password == NULL) {
479                 wpa_printf(MSG_INFO, "EAP-PAX: Plaintext password not "
480                            "configured");
481                 data->state = FAILURE;
482                 return;
483         }
484
485         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len);
486         if (pos == NULL || len < sizeof(*resp))
487                 return;
488
489         resp = (struct eap_pax_hdr *) pos;
490
491         switch (resp->op_code) {
492         case EAP_PAX_OP_STD_2:
493                 eap_pax_process_std_2(sm, data, respData);
494                 break;
495         case EAP_PAX_OP_ACK:
496                 eap_pax_process_ack(sm, data, respData);
497                 break;
498         }
499 }
500
501
502 static Boolean eap_pax_isDone(struct eap_sm *sm, void *priv)
503 {
504         struct eap_pax_data *data = priv;
505         return data->state == SUCCESS || data->state == FAILURE;
506 }
507
508
509 static u8 * eap_pax_getKey(struct eap_sm *sm, void *priv, size_t *len)
510 {
511         struct eap_pax_data *data = priv;
512         u8 *key;
513
514         if (data->state != SUCCESS)
515                 return NULL;
516
517         key = os_malloc(EAP_MSK_LEN);
518         if (key == NULL)
519                 return NULL;
520
521         *len = EAP_MSK_LEN;
522         eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
523                     "Master Session Key", data->rand.e, 2 * EAP_PAX_RAND_LEN,
524                     EAP_MSK_LEN, key);
525
526         return key;
527 }
528
529
530 static u8 * eap_pax_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
531 {
532         struct eap_pax_data *data = priv;
533         u8 *key;
534
535         if (data->state != SUCCESS)
536                 return NULL;
537
538         key = os_malloc(EAP_EMSK_LEN);
539         if (key == NULL)
540                 return NULL;
541
542         *len = EAP_EMSK_LEN;
543         eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
544                     "Extended Master Session Key",
545                     data->rand.e, 2 * EAP_PAX_RAND_LEN,
546                     EAP_EMSK_LEN, key);
547
548         return key;
549 }
550
551
552 static Boolean eap_pax_isSuccess(struct eap_sm *sm, void *priv)
553 {
554         struct eap_pax_data *data = priv;
555         return data->state == SUCCESS;
556 }
557
558
559 static u8 * eap_pax_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
560 {
561         struct eap_pax_data *data = priv;
562         u8 *sid;
563
564         if (data->state != SUCCESS)
565                 return NULL;
566
567         sid = os_malloc(1 + EAP_PAX_MID_LEN);
568         if (sid == NULL)
569                 return NULL;
570
571         *len = 1 + EAP_PAX_MID_LEN;
572         sid[0] = EAP_TYPE_PAX;
573         os_memcpy(sid + 1, data->mid, EAP_PAX_MID_LEN);
574
575         return sid;
576 }
577
578
579 int eap_server_pax_register(void)
580 {
581         struct eap_method *eap;
582
583         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
584                                       EAP_VENDOR_IETF, EAP_TYPE_PAX, "PAX");
585         if (eap == NULL)
586                 return -1;
587
588         eap->init = eap_pax_init;
589         eap->reset = eap_pax_reset;
590         eap->buildReq = eap_pax_buildReq;
591         eap->check = eap_pax_check;
592         eap->process = eap_pax_process;
593         eap->isDone = eap_pax_isDone;
594         eap->getKey = eap_pax_getKey;
595         eap->isSuccess = eap_pax_isSuccess;
596         eap->get_emsk = eap_pax_get_emsk;
597         eap->getSessionId = eap_pax_get_session_id;
598
599         return eap_server_method_register(eap);
600 }