Return to eap_aka_3gpp_provider.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / eap_aka_3gpp |
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: }