Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_sim/eap_sim_peer.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2007-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_sim_peer.h"
                     17: 
                     18: #include <daemon.h>
                     19: 
                     20: #include <simaka_message.h>
                     21: #include <simaka_manager.h>
                     22: 
                     23: /* number of tries we do authenticate */
                     24: #define MAX_TRIES 3
                     25: 
                     26: /* number of triplets for one authentication */
                     27: #define TRIPLET_COUNT 3
                     28: 
                     29: /** length of the AT_NONCE_MT nonce value */
                     30: #define NONCE_LEN 16
                     31: 
                     32: typedef struct private_eap_sim_peer_t private_eap_sim_peer_t;
                     33: 
                     34: /**
                     35:  * Private data of an eap_sim_peer_t object.
                     36:  */
                     37: struct private_eap_sim_peer_t {
                     38: 
                     39:        /**
                     40:         * Public authenticator_t interface.
                     41:         */
                     42:        eap_sim_peer_t public;
                     43: 
                     44:        /**
                     45:         * SIM backend manager
                     46:         */
                     47:        simaka_manager_t *mgr;
                     48: 
                     49:        /**
                     50:         * permanent ID of peer
                     51:         */
                     52:        identification_t *permanent;
                     53: 
                     54:        /**
                     55:         * Pseudonym identity the peer uses
                     56:         */
                     57:        identification_t *pseudonym;
                     58: 
                     59:        /**
                     60:         * Reauthentication identity the peer uses
                     61:         */
                     62:        identification_t *reauth;
                     63: 
                     64:        /**
                     65:         * EAP message identifier
                     66:         */
                     67:        uint8_t identifier;
                     68: 
                     69:        /**
                     70:         * EAP-SIM crypto helper
                     71:         */
                     72:        simaka_crypto_t *crypto;
                     73: 
                     74:        /**
                     75:         * how many times we try to authenticate
                     76:         */
                     77:        int tries;
                     78: 
                     79:        /**
                     80:         * version list received from server
                     81:         */
                     82:        chunk_t version_list;
                     83: 
                     84:        /**
                     85:         * Nonce value used in AT_NONCE_MT/AT_NONCE_S
                     86:         */
                     87:        chunk_t nonce;
                     88: 
                     89:        /**
                     90:         * MSK, used for EAP-SIM based IKEv2 authentication
                     91:         */
                     92:        chunk_t msk;
                     93: 
                     94:        /**
                     95:         * Master key, if reauthentication is used
                     96:         */
                     97:        char mk[HASH_SIZE_SHA1];
                     98: 
                     99:        /**
                    100:         * Counter value if reauthentication is used
                    101:         */
                    102:        uint16_t counter;
                    103: };
                    104: 
                    105: /* version of SIM protocol we speak */
                    106: static chunk_t version = chunk_from_chars(0x00,0x01);
                    107: 
                    108: /**
                    109:  * Generate a payload from a message, destroy message
                    110:  */
                    111: static bool generate_payload(simaka_message_t *message, chunk_t data,
                    112:                                                         eap_payload_t **out)
                    113: {
                    114:        chunk_t chunk;
                    115:        bool ok;
                    116: 
                    117:        ok = message->generate(message, data, &chunk);
                    118:        if (ok)
                    119:        {
                    120:                *out = eap_payload_create_data_own(chunk);
                    121:        }
                    122:        message->destroy(message);
                    123:        return ok;
                    124: }
                    125: 
                    126: /**
                    127:  * Create a SIM_CLIENT_ERROR
                    128:  */
                    129: static bool create_client_error(private_eap_sim_peer_t *this,
                    130:                                                                simaka_client_error_t code, eap_payload_t **out)
                    131: {
                    132:        simaka_message_t *message;
                    133:        uint16_t encoded;
                    134: 
                    135:        DBG1(DBG_IKE, "sending client error '%N'", simaka_client_error_names, code);
                    136: 
                    137:        message = simaka_message_create(FALSE, this->identifier, EAP_SIM,
                    138:                                                                        SIM_CLIENT_ERROR, this->crypto);
                    139:        encoded = htons(code);
                    140:        message->add_attribute(message, AT_CLIENT_ERROR_CODE,
                    141:                                                   chunk_create((char*)&encoded, sizeof(encoded)));
                    142:        return generate_payload(message, chunk_empty, out);
                    143: }
                    144: 
                    145: /**
                    146:  * process an EAP-SIM/Request/Start message
                    147:  */
                    148: static status_t process_start(private_eap_sim_peer_t *this,
                    149:                                                          simaka_message_t *in, eap_payload_t **out)
                    150: {
                    151:        simaka_message_t *message;
                    152:        enumerator_t *enumerator;
                    153:        simaka_attribute_t type;
                    154:        chunk_t data, id = chunk_empty;
                    155:        rng_t *rng;
                    156:        bool supported = FALSE;
                    157:        simaka_attribute_t id_req = 0;
                    158: 
                    159:        /* reset previously uses reauthentication/pseudonym data */
                    160:        this->crypto->clear_keys(this->crypto);
                    161:        DESTROY_IF(this->pseudonym);
                    162:        this->pseudonym = NULL;
                    163:        DESTROY_IF(this->reauth);
                    164:        this->reauth = NULL;
                    165: 
                    166:        enumerator = in->create_attribute_enumerator(in);
                    167:        while (enumerator->enumerate(enumerator, &type, &data))
                    168:        {
                    169:                switch (type)
                    170:                {
                    171:                        case AT_VERSION_LIST:
                    172:                        {
                    173:                                free(this->version_list.ptr);
                    174:                                this->version_list = chunk_clone(data);
                    175:                                while (data.len >= version.len)
                    176:                                {
                    177:                                        if (memeq(data.ptr, version.ptr, version.len))
                    178:                                        {
                    179:                                                supported = TRUE;
                    180:                                                break;
                    181:                                        }
                    182:                                }
                    183:                                break;
                    184:                        }
                    185:                        case AT_ANY_ID_REQ:
                    186:                        case AT_FULLAUTH_ID_REQ:
                    187:                        case AT_PERMANENT_ID_REQ:
                    188:                                id_req = type;
                    189:                                break;
                    190:                        default:
                    191:                                if (!simaka_attribute_skippable(type))
                    192:                                {
                    193:                                        enumerator->destroy(enumerator);
                    194:                                        if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
                    195:                                        {
                    196:                                                return FAILED;
                    197:                                        }
                    198:                                        return NEED_MORE;
                    199:                                }
                    200:                                break;
                    201:                }
                    202:        }
                    203:        enumerator->destroy(enumerator);
                    204: 
                    205:        if (!supported)
                    206:        {
                    207:                DBG1(DBG_IKE, "server does not support EAP-SIM version number 1");
                    208:                if (!create_client_error(this, SIM_UNSUPPORTED_VERSION, out))
                    209:                {
                    210:                        return FAILED;
                    211:                }
                    212:                return NEED_MORE;
                    213:        }
                    214: 
                    215:        switch (id_req)
                    216:        {
                    217:                case AT_ANY_ID_REQ:
                    218:                        this->reauth = this->mgr->card_get_reauth(this->mgr,
                    219:                                                                        this->permanent, this->mk, &this->counter);
                    220:                        if (this->reauth)
                    221:                        {
                    222:                                id = this->reauth->get_encoding(this->reauth);
                    223:                                break;
                    224:                        }
                    225:                        /* FALL */
                    226:                case AT_FULLAUTH_ID_REQ:
                    227:                        this->pseudonym = this->mgr->card_get_pseudonym(this->mgr,
                    228:                                                                                                                        this->permanent);
                    229:                        if (this->pseudonym)
                    230:                        {
                    231:                                id = this->pseudonym->get_encoding(this->pseudonym);
                    232:                                break;
                    233:                        }
                    234:                        /* FALL */
                    235:                case AT_PERMANENT_ID_REQ:
                    236:                        id = this->permanent->get_encoding(this->permanent);
                    237:                        break;
                    238:                default:
                    239:                        break;
                    240:        }
                    241: 
                    242:        /* generate AT_NONCE_MT value */
                    243:        rng = this->crypto->get_rng(this->crypto);
                    244:        free(this->nonce.ptr);
                    245:        if (!rng->allocate_bytes(rng, NONCE_LEN, &this->nonce))
                    246:        {
                    247:                return FAILED;
                    248:        }
                    249: 
                    250:        message = simaka_message_create(FALSE, this->identifier, EAP_SIM,
                    251:                                                                        SIM_START, this->crypto);
                    252:        if (!this->reauth)
                    253:        {
                    254:                message->add_attribute(message, AT_SELECTED_VERSION, version);
                    255:                message->add_attribute(message, AT_NONCE_MT, this->nonce);
                    256:        }
                    257:        if (id.len)
                    258:        {
                    259:                message->add_attribute(message, AT_IDENTITY, id);
                    260:        }
                    261:        if (!generate_payload(message, chunk_empty, out))
                    262:        {
                    263:                return FAILED;
                    264:        }
                    265:        return NEED_MORE;
                    266: }
                    267: 
                    268: /**
                    269:  * process an EAP-SIM/Request/Challenge message
                    270:  */
                    271: static status_t process_challenge(private_eap_sim_peer_t *this,
                    272:                                                                  simaka_message_t *in, eap_payload_t **out)
                    273: {
                    274:        simaka_message_t *message;
                    275:        enumerator_t *enumerator;
                    276:        simaka_attribute_t type;
                    277:        chunk_t data, rands = chunk_empty, kcs, kc, sreses, sres, mk;
                    278:        identification_t *id;
                    279: 
                    280:        if (this->tries-- <= 0)
                    281:        {
                    282:                /* give up without notification. This hack is required as some buggy
                    283:                 * server implementations won't respect our client-error. */
                    284:                return FAILED;
                    285:        }
                    286: 
                    287:        enumerator = in->create_attribute_enumerator(in);
                    288:        while (enumerator->enumerate(enumerator, &type, &data))
                    289:        {
                    290:                switch (type)
                    291:                {
                    292:                        case AT_RAND:
                    293:                                rands = data;
                    294:                                break;
                    295:                        default:
                    296:                                if (!simaka_attribute_skippable(type))
                    297:                                {
                    298:                                        enumerator->destroy(enumerator);
                    299:                                        if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
                    300:                                        {
                    301:                                                return FAILED;
                    302:                                        }
                    303:                                        return NEED_MORE;
                    304:                                }
                    305:                                break;
                    306:                }
                    307:        }
                    308:        enumerator->destroy(enumerator);
                    309: 
                    310:        /* excepting two or three RAND, each 16 bytes. We require two valid
                    311:         * and different RANDs */
                    312:        if ((rands.len != 2 * SIM_RAND_LEN && rands.len != 3 * SIM_RAND_LEN) ||
                    313:                memeq_const(rands.ptr, rands.ptr + SIM_RAND_LEN, SIM_RAND_LEN))
                    314:        {
                    315:                DBG1(DBG_IKE, "no valid AT_RAND received");
                    316:                if (!create_client_error(this, SIM_INSUFFICIENT_CHALLENGES, out))
                    317:                {
                    318:                        return FAILED;
                    319:                }
                    320:                return NEED_MORE;
                    321:        }
                    322:        /* get two or three KCs/SRESes from SIM using RANDs */
                    323:        kcs = kc = chunk_alloca(rands.len / 2);
                    324:        sreses = sres = chunk_alloca(rands.len / 4);
                    325:        while (rands.len >= SIM_RAND_LEN)
                    326:        {
                    327:                if (!this->mgr->card_get_triplet(this->mgr, this->permanent,
                    328:                                                                                 rands.ptr, sres.ptr, kc.ptr))
                    329:                {
                    330:                        DBG1(DBG_IKE, "unable to get EAP-SIM triplet");
                    331:                        if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
                    332:                        {
                    333:                                return FAILED;
                    334:                        }
                    335:                        return NEED_MORE;
                    336:                }
                    337:                DBG3(DBG_IKE, "got triplet for RAND %b\n  Kc %b\n  SRES %b",
                    338:                         rands.ptr, SIM_RAND_LEN, sres.ptr, SIM_SRES_LEN, kc.ptr, SIM_KC_LEN);
                    339:                kc = chunk_skip(kc, SIM_KC_LEN);
                    340:                sres = chunk_skip(sres, SIM_SRES_LEN);
                    341:                rands = chunk_skip(rands, SIM_RAND_LEN);
                    342:        }
                    343: 
                    344:        id = this->permanent;
                    345:        if (this->pseudonym)
                    346:        {
                    347:                id = this->pseudonym;
                    348:        }
                    349:        data = chunk_cata("cccc", kcs, this->nonce, this->version_list, version);
                    350:        chunk_clear(&this->msk);
                    351:        if (!this->crypto->derive_keys_full(this->crypto, id, data, &mk, &this->msk))
                    352:        {
                    353:                return FAILED;
                    354:        }
                    355:        memcpy(this->mk, mk.ptr, mk.len);
                    356:        chunk_clear(&mk);
                    357: 
                    358:        /* Verify AT_MAC attribute, signature is over "EAP packet | NONCE_MT", and
                    359:         * parse() again after key derivation, reading encrypted attributes */
                    360:        if (!in->verify(in, this->nonce) || !in->parse(in))
                    361:        {
                    362:                if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
                    363:                {
                    364:                        return FAILED;
                    365:                }
                    366:                return NEED_MORE;
                    367:        }
                    368: 
                    369:        enumerator = in->create_attribute_enumerator(in);
                    370:        while (enumerator->enumerate(enumerator, &type, &data))
                    371:        {
                    372:                switch (type)
                    373:                {
                    374:                        case AT_NEXT_REAUTH_ID:
                    375:                                this->counter = 0;
                    376:                                id = identification_create_from_data(data);
                    377:                                this->mgr->card_set_reauth(this->mgr, this->permanent, id,
                    378:                                                                                   this->mk, this->counter);
                    379:                                id->destroy(id);
                    380:                                break;
                    381:                        case AT_NEXT_PSEUDONYM:
                    382:                                id = identification_create_from_data(data);
                    383:                                this->mgr->card_set_pseudonym(this->mgr, this->permanent, id);
                    384:                                id->destroy(id);
                    385:                                break;
                    386:                        default:
                    387:                                break;
                    388:                }
                    389:        }
                    390:        enumerator->destroy(enumerator);
                    391: 
                    392:        /* build response with AT_MAC, built over "EAP packet | n*SRES" */
                    393:        message = simaka_message_create(FALSE, this->identifier, EAP_SIM,
                    394:                                                                        SIM_CHALLENGE, this->crypto);
                    395:        if (!generate_payload(message, sreses, out))
                    396:        {
                    397:                return FAILED;
                    398:        }
                    399:        return NEED_MORE;
                    400: }
                    401: 
                    402: /**
                    403:  * Check if a received counter value is acceptable
                    404:  */
                    405: static bool counter_too_small(private_eap_sim_peer_t *this, chunk_t chunk)
                    406: {
                    407:        uint16_t counter;
                    408: 
                    409:        memcpy(&counter, chunk.ptr, sizeof(counter));
                    410:        counter = htons(counter);
                    411:        return counter < this->counter;
                    412: }
                    413: 
                    414: /**
                    415:  * process an EAP-SIM/Request/Re-Authentication message
                    416:  */
                    417: static status_t process_reauthentication(private_eap_sim_peer_t *this,
                    418:                                                                        simaka_message_t *in, eap_payload_t **out)
                    419: {
                    420:        simaka_message_t *message;
                    421:        enumerator_t *enumerator;
                    422:        simaka_attribute_t type;
                    423:        chunk_t data, counter = chunk_empty, nonce = chunk_empty, id = chunk_empty;
                    424: 
                    425:        if (!this->reauth)
                    426:        {
                    427:                DBG1(DBG_IKE, "received %N, but not expected",
                    428:                         simaka_subtype_names, SIM_REAUTHENTICATION);
                    429:                if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
                    430:                {
                    431:                        return FAILED;
                    432:                }
                    433:                return NEED_MORE;
                    434:        }
                    435: 
                    436:        if (!this->crypto->derive_keys_reauth(this->crypto,
                    437:                                                                        chunk_create(this->mk, HASH_SIZE_SHA1)))
                    438:        {
                    439:                return FAILED;
                    440:        }
                    441: 
                    442:        /* verify MAC and parse again with decryption key */
                    443:        if (!in->verify(in, chunk_empty) || !in->parse(in))
                    444:        {
                    445:                if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
                    446:                {
                    447:                        return FAILED;
                    448:                }
                    449:                return NEED_MORE;
                    450:        }
                    451: 
                    452:        enumerator = in->create_attribute_enumerator(in);
                    453:        while (enumerator->enumerate(enumerator, &type, &data))
                    454:        {
                    455:                switch (type)
                    456:                {
                    457:                        case AT_COUNTER:
                    458:                                counter = data;
                    459:                                break;
                    460:                        case AT_NONCE_S:
                    461:                                nonce = data;
                    462:                                break;
                    463:                        case AT_NEXT_REAUTH_ID:
                    464:                                id = data;
                    465:                                break;
                    466:                        default:
                    467:                                if (!simaka_attribute_skippable(type))
                    468:                                {
                    469:                                        enumerator->destroy(enumerator);
                    470:                                        if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
                    471:                                        {
                    472:                                                return FAILED;
                    473:                                        }
                    474:                                        return NEED_MORE;
                    475:                                }
                    476:                                break;
                    477:                }
                    478:        }
                    479:        enumerator->destroy(enumerator);
                    480: 
                    481:        if (!nonce.len || !counter.len)
                    482:        {
                    483:                DBG1(DBG_IKE, "EAP-SIM/Request/Re-Authentication message incomplete");
                    484:                if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
                    485:                {
                    486:                        return FAILED;
                    487:                }
                    488:                return NEED_MORE;
                    489:        }
                    490: 
                    491:        message = simaka_message_create(FALSE, this->identifier, EAP_SIM,
                    492:                                                                        SIM_REAUTHENTICATION, this->crypto);
                    493:        if (counter_too_small(this, counter))
                    494:        {
                    495:                DBG1(DBG_IKE, "reauthentication counter too small");
                    496:                message->add_attribute(message, AT_COUNTER_TOO_SMALL, chunk_empty);
                    497:        }
                    498:        else
                    499:        {
                    500:                chunk_clear(&this->msk);
                    501:                if (!this->crypto->derive_keys_reauth_msk(this->crypto,
                    502:                                                this->reauth, counter, nonce,
                    503:                                                chunk_create(this->mk, HASH_SIZE_SHA1), &this->msk))
                    504:                {
                    505:                        message->destroy(message);
                    506:                        return FAILED;
                    507:                }
                    508:                if (id.len)
                    509:                {
                    510:                        identification_t *reauth;
                    511: 
                    512:                        reauth = identification_create_from_data(data);
                    513:                        this->mgr->card_set_reauth(this->mgr, this->permanent, reauth,
                    514:                                                                           this->mk, this->counter);
                    515:                        reauth->destroy(reauth);
                    516:                }
                    517:        }
                    518:        message->add_attribute(message, AT_COUNTER, counter);
                    519:        if (!generate_payload(message, nonce, out))
                    520:        {
                    521:                return FAILED;
                    522:        }
                    523:        return NEED_MORE;
                    524: }
                    525: 
                    526: /**
                    527:  * process an EAP-SIM/Request/Notification message
                    528:  */
                    529: static status_t process_notification(private_eap_sim_peer_t *this,
                    530:                                                                         simaka_message_t *in, eap_payload_t **out)
                    531: {
                    532:        simaka_message_t *message;
                    533:        enumerator_t *enumerator;
                    534:        simaka_attribute_t type;
                    535:        chunk_t data;
                    536:        bool success = TRUE;
                    537: 
                    538:        enumerator = in->create_attribute_enumerator(in);
                    539:        while (enumerator->enumerate(enumerator, &type, &data))
                    540:        {
                    541:                if (type == AT_NOTIFICATION)
                    542:                {
                    543:                        uint16_t code;
                    544: 
                    545:                        memcpy(&code, data.ptr, sizeof(code));
                    546:                        code = ntohs(code);
                    547: 
                    548:                        /* test success bit */
                    549:                        if (!(data.ptr[0] & 0x80))
                    550:                        {
                    551:                                DBG1(DBG_IKE, "received EAP-SIM notification error '%N'",
                    552:                                         simaka_notification_names, code);
                    553:                        }
                    554:                        else
                    555:                        {
                    556:                                DBG1(DBG_IKE, "received EAP-SIM notification '%N'",
                    557:                                         simaka_notification_names, code);
                    558:                        }
                    559:                }
                    560:                else if (!simaka_attribute_skippable(type))
                    561:                {
                    562:                        success = FALSE;
                    563:                        break;
                    564:                }
                    565:        }
                    566:        enumerator->destroy(enumerator);
                    567: 
                    568:        if (success)
                    569:        {       /* empty notification reply */
                    570:                message = simaka_message_create(FALSE, this->identifier, EAP_SIM,
                    571:                                                                                SIM_NOTIFICATION, this->crypto);
                    572:                if (!generate_payload(message, chunk_empty, out))
                    573:                {
                    574:                        return FAILED;
                    575:                }
                    576:        }
                    577:        else
                    578:        {
                    579:                if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
                    580:                {
                    581:                        return FAILED;
                    582:                }
                    583:        }
                    584:        return NEED_MORE;
                    585: }
                    586: 
                    587: METHOD(eap_method_t, process, status_t,
                    588:        private_eap_sim_peer_t *this, eap_payload_t *in, eap_payload_t **out)
                    589: {
                    590:        simaka_message_t *message;
                    591:        status_t status;
                    592: 
                    593:        /* store received EAP message identifier */
                    594:        this->identifier = in->get_identifier(in);
                    595: 
                    596:        message = simaka_message_create_from_payload(in->get_data(in), this->crypto);
                    597:        if (!message)
                    598:        {
                    599:                if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
                    600:                {
                    601:                        return FAILED;
                    602:                }
                    603:                return NEED_MORE;
                    604:        }
                    605:        if (!message->parse(message))
                    606:        {
                    607:                message->destroy(message);
                    608:                if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
                    609:                {
                    610:                        return FAILED;
                    611:                }
                    612:                return NEED_MORE;
                    613:        }
                    614:        switch (message->get_subtype(message))
                    615:        {
                    616:                case SIM_START:
                    617:                        status = process_start(this, message, out);
                    618:                        break;
                    619:                case SIM_CHALLENGE:
                    620:                        status = process_challenge(this, message, out);
                    621:                        break;
                    622:                case SIM_REAUTHENTICATION:
                    623:                        status = process_reauthentication(this, message, out);
                    624:                        break;
                    625:                case SIM_NOTIFICATION:
                    626:                        status = process_notification(this, message, out);
                    627:                        break;
                    628:                default:
                    629:                        DBG1(DBG_IKE, "unable to process EAP-SIM subtype %N",
                    630:                                 simaka_subtype_names, message->get_subtype(message));
                    631:                        if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
                    632:                        {
                    633:                                status = FAILED;
                    634:                        }
                    635:                        else
                    636:                        {
                    637:                                status = NEED_MORE;
                    638:                        }
                    639:                        break;
                    640:        }
                    641:        message->destroy(message);
                    642:        return status;
                    643: }
                    644: 
                    645: METHOD(eap_method_t, initiate, status_t,
                    646:        private_eap_sim_peer_t *this, eap_payload_t **out)
                    647: {
                    648:        /* peer never initiates */
                    649:        return FAILED;
                    650: }
                    651: 
                    652: METHOD(eap_method_t, get_type, eap_type_t,
                    653:        private_eap_sim_peer_t *this, uint32_t *vendor)
                    654: {
                    655:        *vendor = 0;
                    656:        return EAP_SIM;
                    657: }
                    658: 
                    659: METHOD(eap_method_t, get_msk, status_t,
                    660:        private_eap_sim_peer_t *this, chunk_t *msk)
                    661: {
                    662:        if (this->msk.ptr)
                    663:        {
                    664:                *msk = this->msk;
                    665:                return SUCCESS;
                    666:        }
                    667:        return FAILED;
                    668: }
                    669: 
                    670: METHOD(eap_method_t, get_identifier, uint8_t,
                    671:        private_eap_sim_peer_t *this)
                    672: {
                    673:        return this->identifier;
                    674: }
                    675: 
                    676: METHOD(eap_method_t, set_identifier, void,
                    677:        private_eap_sim_peer_t *this, uint8_t identifier)
                    678: {
                    679:        this->identifier = identifier;
                    680: }
                    681: 
                    682: METHOD(eap_method_t, is_mutual, bool,
                    683:        private_eap_sim_peer_t *this)
                    684: {
                    685:        return TRUE;
                    686: }
                    687: 
                    688: METHOD(eap_method_t, destroy, void,
                    689:        private_eap_sim_peer_t *this)
                    690: {
                    691:        this->permanent->destroy(this->permanent);
                    692:        DESTROY_IF(this->pseudonym);
                    693:        DESTROY_IF(this->reauth);
                    694:        this->crypto->destroy(this->crypto);
                    695:        free(this->version_list.ptr);
                    696:        free(this->nonce.ptr);
                    697:        free(this->msk.ptr);
                    698:        free(this);
                    699: }
                    700: 
                    701: /*
                    702:  * Described in header.
                    703:  */
                    704: eap_sim_peer_t *eap_sim_peer_create(identification_t *server,
                    705:                                                                        identification_t *peer)
                    706: {
                    707:        private_eap_sim_peer_t *this;
                    708: 
                    709:        INIT(this,
                    710:                .public = {
                    711:                        .interface = {
                    712:                                .initiate = _initiate,
                    713:                                .process = _process,
                    714:                                .get_type = _get_type,
                    715:                                .is_mutual = _is_mutual,
                    716:                                .get_msk = _get_msk,
                    717:                                .get_identifier = _get_identifier,
                    718:                                .set_identifier = _set_identifier,
                    719:                                .destroy = _destroy,
                    720:                        },
                    721:                },
                    722:                .crypto = simaka_crypto_create(EAP_SIM),
                    723:                .mgr = lib->get(lib, "sim-manager"),
                    724:        );
                    725: 
                    726:        if (!this->crypto)
                    727:        {
                    728:                free(this);
                    729:                return NULL;
                    730:        }
                    731: 
                    732:        this->permanent = peer->clone(peer);
                    733:        this->tries = MAX_TRIES;
                    734: 
                    735:        return &this->public;
                    736: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>