]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa_supplicant/eap_psk.c
This commit was generated by cvs2svn to compensate for changes in r147462,
[FreeBSD/FreeBSD.git] / contrib / wpa_supplicant / eap_psk.c
1 /*
2  * WPA Supplicant / EAP-PSK (draft-bersani-eap-psk-05.txt)
3  * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18
19 #include "common.h"
20 #include "eap_i.h"
21 #include "wpa_supplicant.h"
22 #include "config_ssid.h"
23 #include "md5.h"
24 #include "aes_wrap.h"
25
26
27 /* draft-bersani-eap-psk-03.txt mode. This is retained for interop testing and
28  * will be removed once an AS that supports draft5 becomes available. */
29 #define EAP_PSK_DRAFT3
30
31 #define EAP_PSK_RAND_LEN 16
32 #define EAP_PSK_MAC_LEN 16
33 #define EAP_PSK_TEK_LEN 16
34 #define EAP_PSK_MSK_LEN 64
35
36 #define EAP_PSK_R_FLAG_CONT 1
37 #define EAP_PSK_R_FLAG_DONE_SUCCESS 2
38 #define EAP_PSK_R_FLAG_DONE_FAILURE 3
39
40 /* EAP-PSK First Message (AS -> Supplicant) */
41 struct eap_psk_hdr_1 {
42         u8 code;
43         u8 identifier;
44         u16 length; /* including code, identifier, and length */
45         u8 type; /* EAP_TYPE_PSK */
46 #ifndef EAP_PSK_DRAFT3
47         u8 flags;
48 #endif /* EAP_PSK_DRAFT3 */
49         u8 rand_s[EAP_PSK_RAND_LEN];
50 #ifndef EAP_PSK_DRAFT3
51         /* Followed by variable length ID_S */
52 #endif /* EAP_PSK_DRAFT3 */
53 } __attribute__ ((packed));
54
55 /* EAP-PSK Second Message (Supplicant -> AS) */
56 struct eap_psk_hdr_2 {
57         u8 code;
58         u8 identifier;
59         u16 length; /* including code, identifier, and length */
60         u8 type; /* EAP_TYPE_PSK */
61 #ifndef EAP_PSK_DRAFT3
62         u8 flags;
63         u8 rand_s[EAP_PSK_RAND_LEN];
64 #endif /* EAP_PSK_DRAFT3 */
65         u8 rand_p[EAP_PSK_RAND_LEN];
66         u8 mac_p[EAP_PSK_MAC_LEN];
67         /* Followed by variable length ID_P */
68 } __attribute__ ((packed));
69
70 /* EAP-PSK Third Message (AS -> Supplicant) */
71 struct eap_psk_hdr_3 {
72         u8 code;
73         u8 identifier;
74         u16 length; /* including code, identifier, and length */
75         u8 type; /* EAP_TYPE_PSK */
76 #ifndef EAP_PSK_DRAFT3
77         u8 flags;
78         u8 rand_s[EAP_PSK_RAND_LEN];
79 #endif /* EAP_PSK_DRAFT3 */
80         u8 mac_s[EAP_PSK_MAC_LEN];
81         /* Followed by variable length PCHANNEL */
82 } __attribute__ ((packed));
83
84 /* EAP-PSK Fourth Message (Supplicant -> AS) */
85 struct eap_psk_hdr_4 {
86         u8 code;
87         u8 identifier;
88         u16 length; /* including code, identifier, and length */
89         u8 type; /* EAP_TYPE_PSK */
90 #ifndef EAP_PSK_DRAFT3
91         u8 flags;
92         u8 rand_s[EAP_PSK_RAND_LEN];
93 #endif /* EAP_PSK_DRAFT3 */
94         /* Followed by variable length PCHANNEL */
95 } __attribute__ ((packed));
96
97
98
99 struct eap_psk_data {
100         enum { PSK_INIT, PSK_MAC_SENT, PSK_DONE } state;
101         u8 rand_s[EAP_PSK_RAND_LEN];
102         u8 rand_p[EAP_PSK_RAND_LEN];
103         u8 ak[16], kdk[16], tek[EAP_PSK_TEK_LEN];
104         u8 *id_s, *id_p;
105         size_t id_s_len, id_p_len;
106         u8 key_data[EAP_PSK_MSK_LEN];
107 };
108
109
110 #define aes_block_size 16
111
112
113 static void eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk)
114 {
115         memset(ak, 0, aes_block_size);
116         aes_128_encrypt_block(psk, ak, ak);
117         memcpy(kdk, ak, aes_block_size);
118         ak[aes_block_size - 1] ^= 0x01;
119         kdk[aes_block_size - 1] ^= 0x02;
120         aes_128_encrypt_block(psk, ak, ak);
121         aes_128_encrypt_block(psk, kdk, kdk);
122 }
123
124
125 static void eap_psk_derive_keys(const u8 *kdk, const u8 *rb, u8 *tek, u8 *msk)
126 {
127         u8 hash[aes_block_size];
128         u8 counter = 1;
129         int i;
130
131         aes_128_encrypt_block(kdk, rb, hash);
132
133         hash[aes_block_size - 1] ^= counter;
134         aes_128_encrypt_block(kdk, hash, tek);
135         hash[aes_block_size - 1] ^= counter;
136         counter++;
137
138         for (i = 0; i < EAP_PSK_MSK_LEN / aes_block_size; i++) {
139                 hash[aes_block_size - 1] ^= counter;
140                 aes_128_encrypt_block(kdk, hash, &msk[i * aes_block_size]);
141                 hash[aes_block_size - 1] ^= counter;
142                 counter++;
143         }
144 }
145
146
147 static void * eap_psk_init(struct eap_sm *sm)
148 {
149         struct wpa_ssid *config = eap_get_config(sm);
150         struct eap_psk_data *data;
151
152         if (config == NULL || !config->eappsk) {
153                 wpa_printf(MSG_INFO, "EAP-PSK: pre-shared key not configured");
154                 return NULL;
155         }
156
157         data = malloc(sizeof(*data));
158         if (data == NULL)
159                 return NULL;
160         memset(data, 0, sizeof(*data));
161         eap_psk_key_setup(config->eappsk, data->ak, data->kdk);
162         wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, 16);
163         wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, 16);
164         data->state = PSK_INIT;
165
166         if (config->nai) {
167                 data->id_p = malloc(config->nai_len);
168                 if (data->id_p)
169                         memcpy(data->id_p, config->nai, config->nai_len);
170                 data->id_p_len = config->nai_len;
171         }
172         if (data->id_p == NULL) {
173                 wpa_printf(MSG_INFO, "EAP-PSK: could not get own identity");
174                 free(data);
175                 return NULL;
176         }
177
178 #ifdef EAP_PSK_DRAFT3
179         if (config->server_nai) {
180                 data->id_s = malloc(config->server_nai_len);
181                 if (data->id_s)
182                         memcpy(data->id_s, config->server_nai,
183                                config->server_nai_len);
184                 data->id_s_len = config->server_nai_len;
185         }
186         if (data->id_s == NULL) {
187                 wpa_printf(MSG_INFO, "EAP-PSK: could not get server identity");
188                 free(data->id_p);
189                 free(data);
190                 return NULL;
191         }
192 #endif /* EAP_PSK_DRAFT3 */
193
194         return data;
195 }
196
197
198 static void eap_psk_deinit(struct eap_sm *sm, void *priv)
199 {
200         struct eap_psk_data *data = priv;
201         free(data->id_s);
202         free(data->id_p);
203         free(data);
204 }
205
206
207 static u8 * eap_psk_process_1(struct eap_sm *sm, struct eap_psk_data *data,
208                               struct eap_method_ret *ret,
209                               u8 *reqData, size_t reqDataLen,
210                               size_t *respDataLen)
211 {
212         struct eap_psk_hdr_1 *hdr1;
213         struct eap_psk_hdr_2 *hdr2;
214         u8 *resp, *buf, *pos;
215         size_t buflen;
216
217         wpa_printf(MSG_DEBUG, "EAP-PSK: in INIT state");
218
219         hdr1 = (struct eap_psk_hdr_1 *) reqData;
220         if (reqDataLen < sizeof(*hdr1) ||
221             be_to_host16(hdr1->length) < sizeof(*hdr1) ||
222             be_to_host16(hdr1->length) > reqDataLen) {
223                 wpa_printf(MSG_INFO, "EAP-PSK: Invalid first message "
224                            "length (%lu %d; expected %lu or more)",
225                            (unsigned long) reqDataLen,
226                            be_to_host16(hdr1->length),
227                            (unsigned long) sizeof(*hdr1));
228                 ret->ignore = TRUE;
229                 return NULL;
230         }
231 #ifndef EAP_PSK_DRAFT3
232         wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr1->flags);
233         if ((hdr1->flags & 0x03) != 0) {
234                 wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 0)",
235                            hdr1->flags & 0x03);
236                 ret->methodState = METHOD_DONE;
237                 ret->decision = DECISION_FAIL;
238                 return NULL;
239         }
240 #endif /* EAP_PSK_DRAFT3 */
241         wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr1->rand_s,
242                     EAP_PSK_RAND_LEN);
243         memcpy(data->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN);
244 #ifndef EAP_PSK_DRAFT3
245         free(data->id_s);
246         data->id_s_len = be_to_host16(hdr1->length) - sizeof(*hdr1);
247         data->id_s = malloc(data->id_s_len);
248         if (data->id_s == NULL) {
249                 wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for "
250                            "ID_S (len=%d)", data->id_s_len);
251                 ret->ignore = TRUE;
252                 return NULL;
253         }
254         memcpy(data->id_s, (u8 *) (hdr1 + 1), data->id_s_len);
255         wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S",
256                           data->id_s, data->id_s_len);
257 #endif /* EAP_PSK_DRAFT3 */
258
259         if (hostapd_get_rand(data->rand_p, EAP_PSK_RAND_LEN)) {
260                 wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data");
261                 ret->ignore = TRUE;
262                 return NULL;
263         }
264
265         *respDataLen = sizeof(*hdr2) + data->id_p_len;
266         resp = malloc(*respDataLen);
267         if (resp == NULL)
268                 return NULL;
269         hdr2 = (struct eap_psk_hdr_2 *) resp;
270         hdr2->code = EAP_CODE_RESPONSE;
271         hdr2->identifier = hdr1->identifier;
272         hdr2->length = host_to_be16(*respDataLen);
273         hdr2->type = EAP_TYPE_PSK;
274 #ifndef EAP_PSK_DRAFT3
275         hdr2->flags = 1; /* T=1 */
276         memcpy(hdr2->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN);
277 #endif /* EAP_PSK_DRAFT3 */
278         memcpy(hdr2->rand_p, data->rand_p, EAP_PSK_RAND_LEN);
279         memcpy((u8 *) (hdr2 + 1), data->id_p, data->id_p_len);
280         /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */
281         buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN;
282         buf = malloc(buflen);
283         if (buf == NULL) {
284                 free(resp);
285                 return NULL;
286         }
287         memcpy(buf, data->id_p, data->id_p_len);
288         pos = buf + data->id_p_len;
289         memcpy(pos, data->id_s, data->id_s_len);
290         pos += data->id_s_len;
291         memcpy(pos, data->rand_s, EAP_PSK_RAND_LEN);
292         pos += EAP_PSK_RAND_LEN;
293         memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN);
294         omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p);
295         free(buf);
296         wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_P", hdr2->rand_p,
297                     EAP_PSK_RAND_LEN);
298         wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", hdr2->mac_p, EAP_PSK_MAC_LEN);
299         wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_P",
300                           (u8 *) (hdr2 + 1), data->id_p_len);
301
302         data->state = PSK_MAC_SENT;
303
304         return resp;
305 }
306
307
308 static u8 * eap_psk_process_3(struct eap_sm *sm, struct eap_psk_data *data,
309                               struct eap_method_ret *ret,
310                               u8 *reqData, size_t reqDataLen,
311                               size_t *respDataLen)
312 {
313         struct eap_psk_hdr_3 *hdr3;
314         struct eap_psk_hdr_4 *hdr4;
315         u8 *resp, *buf, *pchannel, *tag, *msg, nonce[16];
316         u8 mac[EAP_PSK_MAC_LEN];
317         size_t buflen, left;
318         int failed = 0;
319
320         wpa_printf(MSG_DEBUG, "EAP-PSK: in MAC_SENT state");
321
322         hdr3 = (struct eap_psk_hdr_3 *) reqData;
323         left = be_to_host16(hdr3->length);
324         if (left < sizeof(*hdr3) || reqDataLen < left) {
325                 wpa_printf(MSG_INFO, "EAP-PSK: Invalid third message "
326                            "length (%lu %d; expected %lu)",
327                            (unsigned long) reqDataLen,
328                            be_to_host16(hdr3->length),
329                            (unsigned long) sizeof(*hdr3));
330                 ret->ignore = TRUE;
331                 return NULL;
332         }
333         left -= sizeof(*hdr3);
334         pchannel = (u8 *) (hdr3 + 1);
335 #ifndef EAP_PSK_DRAFT3
336         wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr3->flags);
337         if ((hdr3->flags & 0x03) != 2) {
338                 wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 2)",
339                            hdr3->flags & 0x03);
340                 ret->methodState = METHOD_DONE;
341                 ret->decision = DECISION_FAIL;
342                 return NULL;
343         }
344         wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr3->rand_s,
345                     EAP_PSK_RAND_LEN);
346         /* TODO: would not need to store RAND_S since it is available in this
347          * message. For now, since we store this anyway, verify that it matches
348          * with whatever the server is sending. */
349         if (memcmp(hdr3->rand_s, data->rand_s, EAP_PSK_RAND_LEN) != 0) {
350                 wpa_printf(MSG_ERROR, "EAP-PSK: RAND_S did not match");
351                 ret->methodState = METHOD_DONE;
352                 ret->decision = DECISION_FAIL;
353                 return NULL;
354         }
355 #endif /* EAP_PSK_DRAFT3 */
356         wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_S", hdr3->mac_s, EAP_PSK_MAC_LEN);
357         wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL", pchannel, left);
358
359         if (left < 4 + 16 + 1) {
360                 wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in "
361                            "third message (len=%lu, expected 21)",
362                            (unsigned long) left);
363                 ret->ignore = TRUE;
364                 return NULL;
365         }
366
367         /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */
368         buflen = data->id_s_len + EAP_PSK_RAND_LEN;
369         buf = malloc(buflen);
370         if (buf == NULL)
371                 return NULL;
372         memcpy(buf, data->id_s, data->id_s_len);
373         memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN);
374         omac1_aes_128(data->ak, buf, buflen, mac);
375         free(buf);
376         if (memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) {
377                 wpa_printf(MSG_WARNING, "EAP-PSK: Invalid MAC_S in third "
378                            "message");
379                 ret->methodState = METHOD_DONE;
380                 ret->decision = DECISION_FAIL;
381                 return NULL;
382         }
383         wpa_printf(MSG_DEBUG, "EAP-PSK: MAC_S verified successfully");
384
385         eap_psk_derive_keys(data->kdk, data->rand_p, data->tek,
386                             data->key_data);
387         wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN);
388         wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->key_data,
389                         EAP_PSK_MSK_LEN);
390
391         memset(nonce, 0, 12);
392         memcpy(nonce + 12, pchannel, 4);
393         pchannel += 4;
394         left -= 4;
395
396         tag = pchannel;
397         pchannel += 16;
398         left -= 16;
399
400         msg = pchannel;
401
402         wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - nonce",
403                     nonce, sizeof(nonce));
404         wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - hdr", reqData, 5);
405         wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - cipher msg", msg, left);
406
407 #ifdef EAP_PSK_DRAFT3
408         if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce),
409                                 reqData, 5, msg, left, tag))
410 #else /* EAP_PSK_DRAFT3 */
411         if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce),
412                                 reqData, 22, msg, left, tag))
413 #endif /* EAP_PSK_DRAFT3 */
414         {
415                 wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed");
416                 return NULL;
417         }
418         wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message",
419                     msg, left);
420
421         /* Verify R flag */
422         switch (msg[0] >> 6) {
423         case EAP_PSK_R_FLAG_CONT:
424                 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported");
425                 return NULL;
426         case EAP_PSK_R_FLAG_DONE_SUCCESS:
427                 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS");
428                 break;
429         case EAP_PSK_R_FLAG_DONE_FAILURE:
430                 wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE");
431                 wpa_printf(MSG_INFO, "EAP-PSK: Authentication server rejected "
432                            "authentication");
433                 failed = 1;
434                 break;
435         }
436
437         *respDataLen = sizeof(*hdr4) + 4 + 16 + 1;
438         resp = malloc(*respDataLen);
439         if (resp == NULL)
440                 return NULL;
441         hdr4 = (struct eap_psk_hdr_4 *) resp;
442         hdr4->code = EAP_CODE_RESPONSE;
443         hdr4->identifier = hdr3->identifier;
444         hdr4->length = host_to_be16(*respDataLen);
445         hdr4->type = EAP_TYPE_PSK;
446 #ifndef EAP_PSK_DRAFT3
447         hdr4->flags = 3; /* T=3 */
448         memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN);
449 #endif /* EAP_PSK_DRAFT3 */
450         pchannel = (u8 *) (hdr4 + 1);
451
452         /* nonce++ */
453         inc_byte_array(nonce, sizeof(nonce));
454         memcpy(pchannel, nonce + 12, 4);
455
456         pchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6;
457
458         wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (plaintext)",
459                     pchannel + 4 + 16, 1);
460 #ifdef EAP_PSK_DRAFT3
461         aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), resp, 5,
462                             pchannel + 4 + 16, 1, pchannel + 4);
463 #else /* EAP_PSK_DRAFT3 */
464         aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), resp, 22,
465                             pchannel + 4 + 16, 1, pchannel + 4);
466 #endif /* EAP_PSK_DRAFT3 */
467         wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (PCHANNEL)",
468                     pchannel, 4 + 16 + 1);
469
470         wpa_printf(MSG_DEBUG, "EAP-PSK: Completed %ssuccessfully",
471                    failed ? "un" : "");
472         data->state = PSK_DONE;
473         ret->methodState = METHOD_DONE;
474         ret->decision = failed ? DECISION_FAIL : DECISION_UNCOND_SUCC;
475
476         return resp;
477 }
478
479
480 static u8 * eap_psk_process(struct eap_sm *sm, void *priv,
481                             struct eap_method_ret *ret,
482                             u8 *reqData, size_t reqDataLen,
483                             size_t *respDataLen)
484 {
485         struct eap_psk_data *data = priv;
486         struct eap_hdr *req;
487         u8 *pos, *resp = NULL;
488         size_t len;
489
490         req = (struct eap_hdr *) reqData;
491         pos = (u8 *) (req + 1);
492         if (reqDataLen < sizeof(*req) + 1 || *pos != EAP_TYPE_PSK ||
493             (len = be_to_host16(req->length)) > reqDataLen) {
494                 wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame");
495                 ret->ignore = TRUE;
496                 return NULL;
497         }
498
499         ret->ignore = FALSE;
500         ret->methodState = METHOD_CONT;
501         ret->decision = DECISION_FAIL;
502         ret->allowNotifications = TRUE;
503
504         switch (data->state) {
505         case PSK_INIT:
506                 resp = eap_psk_process_1(sm, data, ret, reqData, len,
507                                          respDataLen);
508                 break;
509         case PSK_MAC_SENT:
510                 resp = eap_psk_process_3(sm, data, ret, reqData, len,
511                                          respDataLen);
512                 break;
513         case PSK_DONE:
514                 wpa_printf(MSG_DEBUG, "EAP-PSK: in DONE state - ignore "
515                            "unexpected message");
516                 ret->ignore = TRUE;
517                 return NULL;
518         }
519
520         if (ret->methodState == METHOD_DONE) {
521                 ret->allowNotifications = FALSE;
522         }
523
524         return resp;
525 }
526
527
528 static Boolean eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv)
529 {
530         struct eap_psk_data *data = priv;
531         return data->state == PSK_DONE;
532 }
533
534
535 static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len)
536 {
537         struct eap_psk_data *data = priv;
538         u8 *key;
539
540         if (data->state != PSK_DONE)
541                 return NULL;
542
543         key = malloc(EAP_PSK_MSK_LEN);
544         if (key == NULL)
545                 return NULL;
546
547         *len = EAP_PSK_MSK_LEN;
548         memcpy(key, data->key_data, EAP_PSK_MSK_LEN);
549
550         return key;
551 }
552
553
554 const struct eap_method eap_method_psk =
555 {
556         .method = EAP_TYPE_PSK,
557         .name = "PSK",
558         .init = eap_psk_init,
559         .deinit = eap_psk_deinit,
560         .process = eap_psk_process,
561         .isKeyAvailable = eap_psk_isKeyAvailable,
562         .getKey = eap_psk_getKey,
563 };