Return to eap_aka_3gpp_card.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_card.h" 39: 40: #include <daemon.h> 41: 42: typedef struct private_eap_aka_3gpp_card_t private_eap_aka_3gpp_card_t; 43: 44: /** 45: * Private data of an eap_aka_3gpp_card_t object. 46: */ 47: struct private_eap_aka_3gpp_card_t { 48: 49: /** 50: * Public eap_aka_3gpp_card_t interface. 51: */ 52: eap_aka_3gpp_card_t public; 53: 54: /** 55: * AKA functions 56: */ 57: eap_aka_3gpp_functions_t *f; 58: 59: /** 60: * do sequence number checking? 61: */ 62: bool seq_check; 63: 64: /** 65: * SQN stored in this pseudo-USIM 66: */ 67: uint8_t sqn[AKA_SQN_LEN]; 68: }; 69: 70: METHOD(simaka_card_t, get_quintuplet, status_t, 71: private_eap_aka_3gpp_card_t *this, identification_t *id, 72: char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], 73: char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len) 74: { 75: uint8_t *amf, *mac; 76: uint8_t k[AKA_K_LEN], opc[AKA_OPC_LEN], ak[AKA_AK_LEN], sqn[AKA_SQN_LEN], 77: xmac[AKA_MAC_LEN]; 78: 79: if (!eap_aka_3gpp_get_k_opc(id, k, opc)) 80: { 81: DBG1(DBG_IKE, "no EAP key found for %Y to authenticate with AKA", id); 82: return FAILED; 83: } 84: DBG4(DBG_IKE, "EAP key found for id %Y, using K %b and OPc %b", id, k, 85: AKA_K_LEN, opc, AKA_OPC_LEN); 86: 87: /* AUTN = SQN xor AK | AMF | MAC */ 88: memcpy(sqn, autn, AKA_SQN_LEN); 89: amf = autn + AKA_SQN_LEN; 90: mac = autn + AKA_SQN_LEN + AKA_AMF_LEN; 91: DBG3(DBG_IKE, "received AUTN %b", autn, AKA_AUTN_LEN); 92: DBG3(DBG_IKE, "received AMF %b", amf, AKA_AMF_LEN); 93: DBG3(DBG_IKE, "received MAC %b", mac, AKA_MAC_LEN); 94: 95: /* generate RES, CK, IK, AK from received RAND */ 96: DBG3(DBG_IKE, "received RAND %b", rand, AKA_RAND_LEN); 97: if (!this->f->f2345(this->f, k, opc, rand, res, ck, ik, ak)) 98: { 99: return FAILED; 100: } 101: *res_len = AKA_RES_LEN; 102: DBG3(DBG_IKE, "using RES %b", res, AKA_RES_LEN); 103: DBG3(DBG_IKE, "using CK %b", ck, AKA_CK_LEN); 104: DBG3(DBG_IKE, "using IK %b", ik, AKA_IK_LEN); 105: DBG3(DBG_IKE, "using AK %b", ak, AKA_AK_LEN); 106: 107: /* XOR anonymity key AK into SQN to decrypt it */ 108: memxor(sqn, ak, AKA_SQN_LEN); 109: DBG3(DBG_IKE, "using SQN %b", sqn, AKA_SQN_LEN); 110: 111: /* calculate expected MAC and compare against received one */ 112: if (!this->f->f1(this->f, k, opc, rand, sqn, amf, xmac)) 113: { 114: return FAILED; 115: } 116: if (!memeq_const(mac, xmac, AKA_MAC_LEN)) 117: { 118: DBG1(DBG_IKE, "received MAC does not match XMAC"); 119: DBG3(DBG_IKE, "MAC %b\nXMAC %b", mac, AKA_MAC_LEN, xmac, AKA_MAC_LEN); 120: return FAILED; 121: } 122: DBG3(DBG_IKE, "MAC equals XMAC %b", mac, AKA_MAC_LEN); 123: 124: if (this->seq_check && memcmp(this->sqn, sqn, AKA_SQN_LEN) >= 0) 125: { 126: DBG3(DBG_IKE, "received SQN %b\ncurrent SQN %b", 127: sqn, AKA_SQN_LEN, this->sqn, AKA_SQN_LEN); 128: return INVALID_STATE; 129: } 130: 131: /* update stored SQN to the received one */ 132: memcpy(this->sqn, sqn, AKA_SQN_LEN); 133: 134: return SUCCESS; 135: } 136: 137: METHOD(simaka_card_t, resync, bool, 138: private_eap_aka_3gpp_card_t *this, identification_t *id, 139: char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]) 140: { 141: uint8_t amf[AKA_AMF_LEN], k[AKA_K_LEN], opc[AKA_OPC_LEN], aks[AKA_AK_LEN], 142: macs[AKA_MAC_LEN]; 143: 144: if (!eap_aka_3gpp_get_k_opc(id, k, opc)) 145: { 146: DBG1(DBG_IKE, "no EAP key found for %Y to resync AKA", id); 147: return FALSE; 148: } 149: DBG4(DBG_IKE, "EAP key found for id %Y, using K %b and OPc %b to resync AKA", 150: id, k, AKA_K_LEN, opc, AKA_OPC_LEN); 151: 152: /* AMF is set to zero in resync */ 153: memset(amf, 0, AKA_AMF_LEN); 154: if (!this->f->f5star(this->f, k, opc, rand, aks) || 155: !this->f->f1star(this->f, k, opc, rand, this->sqn, amf, macs)) 156: { 157: return FALSE; 158: } 159: /* AUTS = SQN xor AKS | MACS */ 160: memcpy(auts, this->sqn, AKA_SQN_LEN); 161: memxor(auts, aks, AKA_AK_LEN); 162: memcpy(auts + AKA_AK_LEN, macs, AKA_MAC_LEN); 163: DBG3(DBG_IKE, "generated AUTS %b", auts, AKA_AUTN_LEN); 164: 165: return TRUE; 166: } 167: 168: METHOD(eap_aka_3gpp_card_t, destroy, void, 169: private_eap_aka_3gpp_card_t *this) 170: { 171: free(this); 172: } 173: 174: /** 175: * See header 176: */ 177: eap_aka_3gpp_card_t *eap_aka_3gpp_card_create(eap_aka_3gpp_functions_t *f) 178: { 179: private_eap_aka_3gpp_card_t *this; 180: 181: INIT(this, 182: .public = { 183: .card = { 184: .get_triplet = (void*)return_false, 185: .get_quintuplet = _get_quintuplet, 186: .resync = _resync, 187: .get_pseudonym = (void*)return_null, 188: .set_pseudonym = (void*)nop, 189: .get_reauth = (void*)return_null, 190: .set_reauth = (void*)nop, 191: }, 192: .destroy = _destroy, 193: }, 194: .f = f, 195: .seq_check = lib->settings->get_bool(lib->settings, 196: "%s.plugins.eap-aka-3gpp.seq_check", 197: #ifdef SEQ_CHECK /* handle legacy compile time configuration as default */ 198: TRUE, 199: #else /* !SEQ_CHECK */ 200: FALSE, 201: #endif /* SEQ_CHECK */ 202: lib->ns), 203: ); 204: 205: eap_aka_3gpp_get_sqn(this->sqn, 0); 206: 207: return &this->public; 208: }