Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_aka/eap_aka_peer.c, revision 1.1.1.1

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

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