Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_aka_3gpp/eap_aka_3gpp_provider.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:  * Copyright (C) 2015 Thomas Strangert
                     17:  * Polystar System AB, Sweden
                     18:  *
                     19:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                     20:  * of this software and associated documentation files (the "Software"), to deal
                     21:  * in the Software without restriction, including without limitation the rights
                     22:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     23:  * copies of the Software, and to permit persons to whom the Software is
                     24:  * furnished to do so, subject to the following conditions:
                     25:  *
                     26:  * The above copyright notice and this permission notice shall be included in
                     27:  * all copies or substantial portions of the Software.
                     28:  *
                     29:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     30:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     31:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                     32:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     33:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     34:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     35:  * THE SOFTWARE.
                     36:  */
                     37: 
                     38: #include "eap_aka_3gpp_provider.h"
                     39: 
                     40: #include <daemon.h>
                     41: 
                     42: typedef struct private_eap_aka_3gpp_provider_t private_eap_aka_3gpp_provider_t;
                     43: 
                     44: /**
                     45:  * Private data of an eap_aka_3gpp_provider_t object.
                     46:  */
                     47: struct private_eap_aka_3gpp_provider_t {
                     48: 
                     49:        /**
                     50:         * Public eap_aka_3gpp_provider_t interface.
                     51:         */
                     52:        eap_aka_3gpp_provider_t public;
                     53: 
                     54:        /**
                     55:         * AKA functions
                     56:         */
                     57:        eap_aka_3gpp_functions_t *f;
                     58: 
                     59:        /**
                     60:         * time based SQN, we use the same for all peers
                     61:         */
                     62:        uint8_t sqn[AKA_SQN_LEN];
                     63: };
                     64: 
                     65: /** Authentication management field, AMF, as defined in 3GPP TS 33.102 V12.2.0
                     66:  *
                     67:  * The 16 bits in the AMF are numbered from "0" to "15" where bit "0" is
                     68:  * the most significant bit and bit "15" is the least significant bit.
                     69:  * Bit "0" is called the "AMF separation bit". It is used for the purposes
                     70:  * of EPS (Evolved Packet System) and is specified in
                     71:  * -   TS 33.401 [28] for E-UTRAN access to EPS;
                     72:  * -   TS 33.402 [29] for non-3GPP access to EPS.
                     73:  * Bits "1" to "7" are reserved for future standardization use.
                     74:  * Bits "1" to "7" shall be set to 0 while not yet specified for a particular use.
                     75:  * Bits "8" to "15" can be used for proprietary purposes.
                     76:  */
                     77: static const uint8_t amf[AKA_AMF_LEN] = {0x80, 0x00};
                     78: 
                     79: METHOD(simaka_provider_t, get_quintuplet, bool,
                     80:        private_eap_aka_3gpp_provider_t *this, identification_t *id,
                     81:        char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len,
                     82:        char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN])
                     83: {
                     84:        rng_t *rng;
                     85:        uint8_t maca[AKA_MAC_LEN], ak[AKA_AK_LEN], k[AKA_K_LEN], opc[AKA_OPC_LEN];
                     86: 
                     87:        /* generate RAND: we use a RNG already registered as f0(). */
                     88:        rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
                     89:        if (!rng || !rng->get_bytes(rng, AKA_RAND_LEN, rand))
                     90:        {
                     91:                DBG1(DBG_IKE, "generating RAND for AKA failed");
                     92:                DESTROY_IF(rng);
                     93:                return FALSE;
                     94:        }
                     95:        rng->destroy(rng);
                     96:        DBG3(DBG_IKE, "generated rand %b", rand, AKA_RAND_LEN);
                     97: 
                     98:        if (!eap_aka_3gpp_get_k_opc(id, k, opc))
                     99:        {
                    100:                DBG1(DBG_IKE, "no EAP key found for %Y to authenticate with AKA", id);
                    101:                return FALSE;
                    102:        }
                    103:        DBG4(DBG_IKE, "EAP key found for id %Y, using K %b and OPc %b", id, k,
                    104:                 AKA_K_LEN, opc, AKA_OPC_LEN);
                    105: 
                    106:        /* generate MAC and XRES, CK, IK, AK */
                    107:        if (!this->f->f1(this->f, k, opc, rand, this->sqn, amf, maca) ||
                    108:            !this->f->f2345(this->f, k, opc, rand, xres, ck, ik, ak))
                    109:        {
                    110:                return FALSE;
                    111:        }
                    112:        *xres_len = AKA_RES_LEN;
                    113: 
                    114:        /* create AUTN = (SQN xor AK) || AMF || MAC */
                    115:        memcpy(autn, this->sqn, AKA_SQN_LEN);
                    116:        memxor(autn, ak, AKA_AK_LEN);
                    117:        memcpy(autn + AKA_SQN_LEN, amf, AKA_AMF_LEN);
                    118:        memcpy(autn + AKA_SQN_LEN + AKA_AMF_LEN, maca, AKA_MAC_LEN);
                    119:        DBG3(DBG_IKE, "AUTN %b", autn, AKA_AUTN_LEN);
                    120: 
                    121:        chunk_increment(chunk_create(this->sqn, AKA_SQN_LEN));
                    122: 
                    123:        return TRUE;
                    124: }
                    125: 
                    126: METHOD(simaka_provider_t, resync, bool,
                    127:        private_eap_aka_3gpp_provider_t *this, identification_t *id,
                    128:        char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN])
                    129: {
                    130:        uint8_t *sqn, *macs;
                    131:        uint8_t aks[AKA_AK_LEN], k[AKA_K_LEN], opc[AKA_OPC_LEN], amfs[AKA_AMF_LEN],
                    132:                        xmacs[AKA_MAC_LEN];
                    133: 
                    134:        if (!eap_aka_3gpp_get_k_opc(id, k, opc))
                    135:        {
                    136:                DBG1(DBG_IKE, "no EAP key found for %Y to authenticate with AKA", id);
                    137:                return FALSE;
                    138:        }
                    139:        DBG4(DBG_IKE, "EAP key found for id %Y, using K %b and OPc %b", id, k,
                    140:                 AKA_K_LEN, opc, AKA_OPC_LEN);
                    141: 
                    142:        /* get SQNms out of the AUTS the card created as:
                    143:         * AUTS = (SQNms xor AKS) || MAC-S */
                    144:        sqn = auts;
                    145:        macs = auts + AKA_SQN_LEN;
                    146:        if (!this->f->f5star(this->f, k, opc, rand, aks))
                    147:        {
                    148:                return FALSE;
                    149:        }
                    150:        memxor(sqn, aks, AKA_AK_LEN);
                    151: 
                    152:        /* generate resync XMAC-S... */
                    153:        memset(amfs, 0, AKA_AMF_LEN);
                    154:        if (!this->f->f1star(this->f, k, opc, rand, sqn, amfs, xmacs))
                    155:        {
                    156:                return FALSE;
                    157:        }
                    158:        /* ...and compare it with the card's MAC-S */
                    159:        if (!memeq_const(xmacs, macs, AKA_MAC_LEN))
                    160:        {
                    161:                DBG1(DBG_IKE, "received MACS does not match XMACS");
                    162:                DBG3(DBG_IKE, "MACS %b XMACS %b",
                    163:                         macs, AKA_MAC_LEN, xmacs, AKA_MAC_LEN);
                    164:                return FALSE;
                    165:        }
                    166:        /* update stored SQN to received SQN + 1 */
                    167:        memcpy(this->sqn, sqn, AKA_SQN_LEN);
                    168:        chunk_increment(chunk_create(this->sqn, AKA_SQN_LEN));
                    169:        return TRUE;
                    170: }
                    171: 
                    172: METHOD(eap_aka_3gpp_provider_t, destroy, void,
                    173:        private_eap_aka_3gpp_provider_t *this)
                    174: {
                    175:        free(this);
                    176: }
                    177: 
                    178: /**
                    179:  * See header
                    180:  */
                    181: eap_aka_3gpp_provider_t *eap_aka_3gpp_provider_create(
                    182:                                                                                                eap_aka_3gpp_functions_t *f)
                    183: {
                    184:        private_eap_aka_3gpp_provider_t *this;
                    185: 
                    186:        INIT(this,
                    187:                .public = {
                    188:                        .provider = {
                    189:                                .get_triplet = (void*)return_false,
                    190:                                .get_quintuplet = _get_quintuplet,
                    191:                                .resync = _resync,
                    192:                                .is_pseudonym = (void*)return_null,
                    193:                                .gen_pseudonym = (void*)return_null,
                    194:                                .is_reauth = (void*)return_null,
                    195:                                .gen_reauth = (void*)return_null,
                    196:                        },
                    197:                        .destroy = _destroy,
                    198:                },
                    199:                .f = f,
                    200:        );
                    201:        /* use an offset to accept clock skew between client/server without resync */
                    202:        eap_aka_3gpp_get_sqn(this->sqn, SQN_TIME_OFFSET);
                    203: 
                    204:        return &this->public;
                    205: }

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