Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_sim/eap_sim_peer.c, revision 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>