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