Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_aka_3gpp/eap_aka_3gpp_provider.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: * 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>