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