Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2008-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_3gpp2_card.h"
        !            17: 
        !            18: #include <daemon.h>
        !            19: 
        !            20: typedef struct private_eap_aka_3gpp2_card_t private_eap_aka_3gpp2_card_t;
        !            21: 
        !            22: /**
        !            23:  * Private data of an eap_aka_3gpp2_card_t object.
        !            24:  */
        !            25: struct private_eap_aka_3gpp2_card_t {
        !            26: 
        !            27:        /**
        !            28:         * Public eap_aka_3gpp2_card_t interface.
        !            29:         */
        !            30:        eap_aka_3gpp2_card_t public;
        !            31: 
        !            32:        /**
        !            33:         * AKA functions
        !            34:         */
        !            35:        eap_aka_3gpp2_functions_t *f;
        !            36: 
        !            37:        /**
        !            38:         * do sequence number checking?
        !            39:         */
        !            40:        bool seq_check;
        !            41: 
        !            42:        /**
        !            43:         * SQN stored in this pseudo-USIM
        !            44:         */
        !            45:        char sqn[AKA_SQN_LEN];
        !            46: };
        !            47: 
        !            48: /**
        !            49:  * Functions from eap_aka_3gpp2_provider.c
        !            50:  */
        !            51: bool eap_aka_3gpp2_get_k(identification_t *id, char k[AKA_K_LEN]);
        !            52: void eap_aka_3gpp2_get_sqn(char sqn[AKA_SQN_LEN], int offset);
        !            53: 
        !            54: METHOD(simaka_card_t, get_quintuplet, status_t,
        !            55:        private_eap_aka_3gpp2_card_t *this, identification_t *id,
        !            56:        char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN],
        !            57:        char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len)
        !            58: {
        !            59:        char *amf, *mac;
        !            60:        char k[AKA_K_LEN], ak[AKA_AK_LEN], sqn[AKA_SQN_LEN], xmac[AKA_MAC_LEN];
        !            61: 
        !            62:        if (!eap_aka_3gpp2_get_k(id, k))
        !            63:        {
        !            64:                DBG1(DBG_IKE, "no EAP key found for %Y to authenticate with AKA", id);
        !            65:                return FAILED;
        !            66:        }
        !            67: 
        !            68:        /* AUTN = SQN xor AK | AMF | MAC */
        !            69:        DBG3(DBG_IKE, "received autn %b", autn, AKA_AUTN_LEN);
        !            70:        DBG3(DBG_IKE, "using K %b", k, AKA_K_LEN);
        !            71:        DBG3(DBG_IKE, "using rand %b", rand, AKA_RAND_LEN);
        !            72:        memcpy(sqn, autn, AKA_SQN_LEN);
        !            73:        amf = autn + AKA_SQN_LEN;
        !            74:        mac = autn + AKA_SQN_LEN + AKA_AMF_LEN;
        !            75: 
        !            76:        /* XOR anonymity key AK into SQN to decrypt it */
        !            77:        if (!this->f->f5(this->f, k, rand, ak))
        !            78:        {
        !            79:                return FAILED;
        !            80:        }
        !            81:        DBG3(DBG_IKE, "using ak %b", ak, AKA_AK_LEN);
        !            82:        memxor(sqn, ak, AKA_SQN_LEN);
        !            83:        DBG3(DBG_IKE, "using sqn %b", sqn, AKA_SQN_LEN);
        !            84: 
        !            85:        /* calculate expected MAC and compare against received one */
        !            86:        if (!this->f->f1(this->f, k, rand, sqn, amf, xmac))
        !            87:        {
        !            88:                return FAILED;
        !            89:        }
        !            90:        if (!memeq_const(mac, xmac, AKA_MAC_LEN))
        !            91:        {
        !            92:                DBG1(DBG_IKE, "received MAC does not match XMAC");
        !            93:                DBG3(DBG_IKE, "MAC %b\nXMAC %b", mac, AKA_MAC_LEN, xmac, AKA_MAC_LEN);
        !            94:                return FAILED;
        !            95:        }
        !            96: 
        !            97:        if (this->seq_check && memcmp(this->sqn, sqn, AKA_SQN_LEN) >= 0)
        !            98:        {
        !            99:                DBG3(DBG_IKE, "received SQN %b\ncurrent SQN %b",
        !           100:                         sqn, AKA_SQN_LEN, this->sqn, AKA_SQN_LEN);
        !           101:                return INVALID_STATE;
        !           102:        }
        !           103: 
        !           104:        /* update stored SQN to the received one */
        !           105:        memcpy(this->sqn, sqn, AKA_SQN_LEN);
        !           106: 
        !           107:        /* CK/IK, calculate RES */
        !           108:        if (!this->f->f3(this->f, k, rand, ck) ||
        !           109:                !this->f->f4(this->f, k, rand, ik) ||
        !           110:                !this->f->f2(this->f, k, rand, res))
        !           111:        {
        !           112:                return FAILED;
        !           113:        }
        !           114:        *res_len = AKA_RES_MAX;
        !           115: 
        !           116:        return SUCCESS;
        !           117: }
        !           118: 
        !           119: METHOD(simaka_card_t, resync, bool,
        !           120:        private_eap_aka_3gpp2_card_t *this, identification_t *id,
        !           121:        char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN])
        !           122: {
        !           123:        char amf[AKA_AMF_LEN], k[AKA_K_LEN], aks[AKA_AK_LEN], macs[AKA_MAC_LEN];
        !           124: 
        !           125:        if (!eap_aka_3gpp2_get_k(id, k))
        !           126:        {
        !           127:                DBG1(DBG_IKE, "no EAP key found for %Y to resync AKA", id);
        !           128:                return FALSE;
        !           129:        }
        !           130: 
        !           131:        /* AMF is set to zero in resync */
        !           132:        memset(amf, 0, AKA_AMF_LEN);
        !           133:        if (!this->f->f5star(this->f, k, rand, aks) ||
        !           134:                !this->f->f1star(this->f, k, rand, this->sqn, amf, macs))
        !           135:        {
        !           136:                return FALSE;
        !           137:        }
        !           138:        /* AUTS = SQN xor AKS | MACS */
        !           139:        memcpy(auts, this->sqn, AKA_SQN_LEN);
        !           140:        memxor(auts, aks, AKA_AK_LEN);
        !           141:        memcpy(auts + AKA_AK_LEN, macs, AKA_MAC_LEN);
        !           142: 
        !           143:        return TRUE;
        !           144: }
        !           145: 
        !           146: METHOD(eap_aka_3gpp2_card_t, destroy, void,
        !           147:        private_eap_aka_3gpp2_card_t *this)
        !           148: {
        !           149:        free(this);
        !           150: }
        !           151: 
        !           152: /**
        !           153:  * See header
        !           154:  */
        !           155: eap_aka_3gpp2_card_t *eap_aka_3gpp2_card_create(eap_aka_3gpp2_functions_t *f)
        !           156: {
        !           157:        private_eap_aka_3gpp2_card_t *this;
        !           158: 
        !           159:        INIT(this,
        !           160:                .public = {
        !           161:                        .card = {
        !           162:                                .get_triplet = (void*)return_false,
        !           163:                                .get_quintuplet = _get_quintuplet,
        !           164:                                .resync = _resync,
        !           165:                                .get_pseudonym = (void*)return_null,
        !           166:                                .set_pseudonym = (void*)nop,
        !           167:                                .get_reauth = (void*)return_null,
        !           168:                                .set_reauth = (void*)nop,
        !           169:                        },
        !           170:                        .destroy = _destroy,
        !           171:                },
        !           172:                .f = f,
        !           173:                .seq_check = lib->settings->get_bool(lib->settings,
        !           174:                                                                        "%s.plugins.eap-aka-3gpp2.seq_check",
        !           175: #ifdef SEQ_CHECK /* handle legacy compile time configuration as default */
        !           176:                                                                        TRUE,
        !           177: #else /* !SEQ_CHECK */
        !           178:                                                                        FALSE,
        !           179: #endif /* SEQ_CHECK */
        !           180:                                                                        lib->ns),
        !           181:        );
        !           182: 
        !           183:        eap_aka_3gpp2_get_sqn(this->sqn, 0);
        !           184: 
        !           185:        return &this->public;
        !           186: }

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