eap_sim_common.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205
  1. /*
  2. * EAP peer/server: EAP-SIM/AKA/AKA' shared routines
  3. * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "includes.h"
  9. #include "common.h"
  10. #include "wpabuf.h"
  11. #include "crypto/aes_wrap.h"
  12. #include "crypto/crypto.h"
  13. #include "crypto/sha1.h"
  14. #include "crypto/sha256.h"
  15. #include "crypto/random.h"
  16. #include "eap_common/eap_defs.h"
  17. #include "eap_common/eap_sim_common.h"
  18. static int eap_sim_prf(const u8 *key, u8 *x, size_t xlen)
  19. {
  20. return fips186_2_prf(key, EAP_SIM_MK_LEN, x, xlen);
  21. }
  22. void eap_sim_derive_mk(const u8 *identity, size_t identity_len,
  23. const u8 *nonce_mt, u16 selected_version,
  24. const u8 *ver_list, size_t ver_list_len,
  25. int num_chal, const u8 *kc, u8 *mk)
  26. {
  27. u8 sel_ver[2];
  28. const unsigned char *addr[5];
  29. size_t len[5];
  30. addr[0] = identity;
  31. len[0] = identity_len;
  32. addr[1] = kc;
  33. len[1] = num_chal * EAP_SIM_KC_LEN;
  34. addr[2] = nonce_mt;
  35. len[2] = EAP_SIM_NONCE_MT_LEN;
  36. addr[3] = ver_list;
  37. len[3] = ver_list_len;
  38. addr[4] = sel_ver;
  39. len[4] = 2;
  40. WPA_PUT_BE16(sel_ver, selected_version);
  41. /* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */
  42. sha1_vector(5, addr, len, mk);
  43. wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN);
  44. }
  45. void eap_aka_derive_mk(const u8 *identity, size_t identity_len,
  46. const u8 *ik, const u8 *ck, u8 *mk)
  47. {
  48. const u8 *addr[3];
  49. size_t len[3];
  50. addr[0] = identity;
  51. len[0] = identity_len;
  52. addr[1] = ik;
  53. len[1] = EAP_AKA_IK_LEN;
  54. addr[2] = ck;
  55. len[2] = EAP_AKA_CK_LEN;
  56. /* MK = SHA1(Identity|IK|CK) */
  57. sha1_vector(3, addr, len, mk);
  58. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", ik, EAP_AKA_IK_LEN);
  59. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", ck, EAP_AKA_CK_LEN);
  60. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", mk, EAP_SIM_MK_LEN);
  61. }
  62. int eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk, u8 *emsk)
  63. {
  64. u8 buf[EAP_SIM_K_ENCR_LEN + EAP_SIM_K_AUT_LEN +
  65. EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN], *pos;
  66. if (eap_sim_prf(mk, buf, sizeof(buf)) < 0) {
  67. wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys");
  68. return -1;
  69. }
  70. pos = buf;
  71. os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN);
  72. pos += EAP_SIM_K_ENCR_LEN;
  73. os_memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN);
  74. pos += EAP_SIM_K_AUT_LEN;
  75. os_memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN);
  76. pos += EAP_SIM_KEYING_DATA_LEN;
  77. os_memcpy(emsk, pos, EAP_EMSK_LEN);
  78. wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_encr",
  79. k_encr, EAP_SIM_K_ENCR_LEN);
  80. wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_aut",
  81. k_aut, EAP_SIM_K_AUT_LEN);
  82. wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material (MSK)",
  83. msk, EAP_SIM_KEYING_DATA_LEN);
  84. wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN);
  85. os_memset(buf, 0, sizeof(buf));
  86. return 0;
  87. }
  88. int eap_sim_derive_keys_reauth(u16 _counter,
  89. const u8 *identity, size_t identity_len,
  90. const u8 *nonce_s, const u8 *mk, u8 *msk,
  91. u8 *emsk)
  92. {
  93. u8 xkey[SHA1_MAC_LEN];
  94. u8 buf[EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN + 32];
  95. u8 counter[2];
  96. const u8 *addr[4];
  97. size_t len[4];
  98. while (identity_len > 0 && identity[identity_len - 1] == 0) {
  99. wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop null "
  100. "character from the end of identity");
  101. identity_len--;
  102. }
  103. addr[0] = identity;
  104. len[0] = identity_len;
  105. addr[1] = counter;
  106. len[1] = 2;
  107. addr[2] = nonce_s;
  108. len[2] = EAP_SIM_NONCE_S_LEN;
  109. addr[3] = mk;
  110. len[3] = EAP_SIM_MK_LEN;
  111. WPA_PUT_BE16(counter, _counter);
  112. wpa_printf(MSG_DEBUG, "EAP-SIM: Deriving keying data from reauth");
  113. wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity",
  114. identity, identity_len);
  115. wpa_hexdump(MSG_DEBUG, "EAP-SIM: counter", counter, 2);
  116. wpa_hexdump(MSG_DEBUG, "EAP-SIM: NONCE_S", nonce_s,
  117. EAP_SIM_NONCE_S_LEN);
  118. wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN);
  119. /* XKEY' = SHA1(Identity|counter|NONCE_S|MK) */
  120. sha1_vector(4, addr, len, xkey);
  121. wpa_hexdump(MSG_DEBUG, "EAP-SIM: XKEY'", xkey, SHA1_MAC_LEN);
  122. if (eap_sim_prf(xkey, buf, sizeof(buf)) < 0) {
  123. wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys");
  124. return -1;
  125. }
  126. if (msk) {
  127. os_memcpy(msk, buf, EAP_SIM_KEYING_DATA_LEN);
  128. wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material (MSK)",
  129. msk, EAP_SIM_KEYING_DATA_LEN);
  130. }
  131. if (emsk) {
  132. os_memcpy(emsk, buf + EAP_SIM_KEYING_DATA_LEN, EAP_EMSK_LEN);
  133. wpa_hexdump(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN);
  134. }
  135. os_memset(buf, 0, sizeof(buf));
  136. return 0;
  137. }
  138. int eap_sim_verify_mac(const u8 *k_aut, const struct wpabuf *req,
  139. const u8 *mac, const u8 *extra, size_t extra_len)
  140. {
  141. unsigned char hmac[SHA1_MAC_LEN];
  142. const u8 *addr[2];
  143. size_t len[2];
  144. u8 *tmp;
  145. if (mac == NULL || wpabuf_len(req) < EAP_SIM_MAC_LEN ||
  146. mac < wpabuf_head_u8(req) ||
  147. mac > wpabuf_head_u8(req) + wpabuf_len(req) - EAP_SIM_MAC_LEN)
  148. return -1;
  149. tmp = os_memdup(wpabuf_head(req), wpabuf_len(req));
  150. if (tmp == NULL)
  151. return -1;
  152. addr[0] = tmp;
  153. len[0] = wpabuf_len(req);
  154. addr[1] = extra;
  155. len[1] = extra_len;
  156. /* HMAC-SHA1-128 */
  157. os_memset(tmp + (mac - wpabuf_head_u8(req)), 0, EAP_SIM_MAC_LEN);
  158. wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - msg",
  159. tmp, wpabuf_len(req));
  160. wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - extra data",
  161. extra, extra_len);
  162. wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Verify MAC - K_aut",
  163. k_aut, EAP_SIM_K_AUT_LEN);
  164. hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
  165. wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC: MAC",
  166. hmac, EAP_SIM_MAC_LEN);
  167. os_free(tmp);
  168. return (os_memcmp_const(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
  169. }
  170. void eap_sim_add_mac(const u8 *k_aut, const u8 *msg, size_t msg_len, u8 *mac,
  171. const u8 *extra, size_t extra_len)
  172. {
  173. unsigned char hmac[SHA1_MAC_LEN];
  174. const u8 *addr[2];
  175. size_t len[2];
  176. addr[0] = msg;
  177. len[0] = msg_len;
  178. addr[1] = extra;
  179. len[1] = extra_len;
  180. /* HMAC-SHA1-128 */
  181. os_memset(mac, 0, EAP_SIM_MAC_LEN);
  182. wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - msg", msg, msg_len);
  183. wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - extra data",
  184. extra, extra_len);
  185. wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Add MAC - K_aut",
  186. k_aut, EAP_SIM_K_AUT_LEN);
  187. hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
  188. os_memcpy(mac, hmac, EAP_SIM_MAC_LEN);
  189. wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC: MAC",
  190. mac, EAP_SIM_MAC_LEN);
  191. }
  192. #if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
  193. static void prf_prime(const u8 *k, const char *seed1,
  194. const u8 *seed2, size_t seed2_len,
  195. const u8 *seed3, size_t seed3_len,
  196. u8 *res, size_t res_len)
  197. {
  198. const u8 *addr[5];
  199. size_t len[5];
  200. u8 hash[SHA256_MAC_LEN];
  201. u8 iter;
  202. /*
  203. * PRF'(K,S) = T1 | T2 | T3 | T4 | ...
  204. * T1 = HMAC-SHA-256 (K, S | 0x01)
  205. * T2 = HMAC-SHA-256 (K, T1 | S | 0x02)
  206. * T3 = HMAC-SHA-256 (K, T2 | S | 0x03)
  207. * T4 = HMAC-SHA-256 (K, T3 | S | 0x04)
  208. * ...
  209. */
  210. addr[0] = hash;
  211. len[0] = 0;
  212. addr[1] = (const u8 *) seed1;
  213. len[1] = os_strlen(seed1);
  214. addr[2] = seed2;
  215. len[2] = seed2_len;
  216. addr[3] = seed3;
  217. len[3] = seed3_len;
  218. addr[4] = &iter;
  219. len[4] = 1;
  220. iter = 0;
  221. while (res_len) {
  222. size_t hlen;
  223. iter++;
  224. hmac_sha256_vector(k, 32, 5, addr, len, hash);
  225. len[0] = SHA256_MAC_LEN;
  226. hlen = res_len > SHA256_MAC_LEN ? SHA256_MAC_LEN : res_len;
  227. os_memcpy(res, hash, hlen);
  228. res += hlen;
  229. res_len -= hlen;
  230. }
  231. }
  232. void eap_aka_prime_derive_keys(const u8 *identity, size_t identity_len,
  233. const u8 *ik, const u8 *ck, u8 *k_encr,
  234. u8 *k_aut, u8 *k_re, u8 *msk, u8 *emsk)
  235. {
  236. u8 key[EAP_AKA_IK_LEN + EAP_AKA_CK_LEN];
  237. u8 keys[EAP_SIM_K_ENCR_LEN + EAP_AKA_PRIME_K_AUT_LEN +
  238. EAP_AKA_PRIME_K_RE_LEN + EAP_MSK_LEN + EAP_EMSK_LEN];
  239. u8 *pos;
  240. /*
  241. * MK = PRF'(IK'|CK',"EAP-AKA'"|Identity)
  242. * K_encr = MK[0..127]
  243. * K_aut = MK[128..383]
  244. * K_re = MK[384..639]
  245. * MSK = MK[640..1151]
  246. * EMSK = MK[1152..1663]
  247. */
  248. os_memcpy(key, ik, EAP_AKA_IK_LEN);
  249. os_memcpy(key + EAP_AKA_IK_LEN, ck, EAP_AKA_CK_LEN);
  250. prf_prime(key, "EAP-AKA'", identity, identity_len, NULL, 0,
  251. keys, sizeof(keys));
  252. pos = keys;
  253. os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN);
  254. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_encr",
  255. k_encr, EAP_SIM_K_ENCR_LEN);
  256. pos += EAP_SIM_K_ENCR_LEN;
  257. os_memcpy(k_aut, pos, EAP_AKA_PRIME_K_AUT_LEN);
  258. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_aut",
  259. k_aut, EAP_AKA_PRIME_K_AUT_LEN);
  260. pos += EAP_AKA_PRIME_K_AUT_LEN;
  261. os_memcpy(k_re, pos, EAP_AKA_PRIME_K_RE_LEN);
  262. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': K_re",
  263. k_re, EAP_AKA_PRIME_K_RE_LEN);
  264. pos += EAP_AKA_PRIME_K_RE_LEN;
  265. os_memcpy(msk, pos, EAP_MSK_LEN);
  266. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': MSK", msk, EAP_MSK_LEN);
  267. pos += EAP_MSK_LEN;
  268. os_memcpy(emsk, pos, EAP_EMSK_LEN);
  269. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': EMSK", emsk, EAP_EMSK_LEN);
  270. }
  271. int eap_aka_prime_derive_keys_reauth(const u8 *k_re, u16 counter,
  272. const u8 *identity, size_t identity_len,
  273. const u8 *nonce_s, u8 *msk, u8 *emsk)
  274. {
  275. u8 seed3[2 + EAP_SIM_NONCE_S_LEN];
  276. u8 keys[EAP_MSK_LEN + EAP_EMSK_LEN];
  277. u8 *pos;
  278. /*
  279. * MK = PRF'(K_re,"EAP-AKA' re-auth"|Identity|counter|NONCE_S)
  280. * MSK = MK[0..511]
  281. * EMSK = MK[512..1023]
  282. */
  283. WPA_PUT_BE16(seed3, counter);
  284. os_memcpy(seed3 + 2, nonce_s, EAP_SIM_NONCE_S_LEN);
  285. prf_prime(k_re, "EAP-AKA' re-auth", identity, identity_len,
  286. seed3, sizeof(seed3),
  287. keys, sizeof(keys));
  288. pos = keys;
  289. os_memcpy(msk, pos, EAP_MSK_LEN);
  290. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': MSK", msk, EAP_MSK_LEN);
  291. pos += EAP_MSK_LEN;
  292. os_memcpy(emsk, pos, EAP_EMSK_LEN);
  293. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': EMSK", emsk, EAP_EMSK_LEN);
  294. os_memset(keys, 0, sizeof(keys));
  295. return 0;
  296. }
  297. int eap_sim_verify_mac_sha256(const u8 *k_aut, const struct wpabuf *req,
  298. const u8 *mac, const u8 *extra, size_t extra_len)
  299. {
  300. unsigned char hmac[SHA256_MAC_LEN];
  301. const u8 *addr[2];
  302. size_t len[2];
  303. u8 *tmp;
  304. if (mac == NULL || wpabuf_len(req) < EAP_SIM_MAC_LEN ||
  305. mac < wpabuf_head_u8(req) ||
  306. mac > wpabuf_head_u8(req) + wpabuf_len(req) - EAP_SIM_MAC_LEN)
  307. return -1;
  308. tmp = os_memdup(wpabuf_head(req), wpabuf_len(req));
  309. if (tmp == NULL)
  310. return -1;
  311. addr[0] = tmp;
  312. len[0] = wpabuf_len(req);
  313. addr[1] = extra;
  314. len[1] = extra_len;
  315. /* HMAC-SHA-256-128 */
  316. os_memset(tmp + (mac - wpabuf_head_u8(req)), 0, EAP_SIM_MAC_LEN);
  317. wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC - msg",
  318. tmp, wpabuf_len(req));
  319. wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC - extra data",
  320. extra, extra_len);
  321. wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA': Verify MAC - K_aut",
  322. k_aut, EAP_AKA_PRIME_K_AUT_LEN);
  323. hmac_sha256_vector(k_aut, EAP_AKA_PRIME_K_AUT_LEN, 2, addr, len, hmac);
  324. wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Verify MAC: MAC",
  325. hmac, EAP_SIM_MAC_LEN);
  326. os_free(tmp);
  327. return (os_memcmp_const(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
  328. }
  329. void eap_sim_add_mac_sha256(const u8 *k_aut, const u8 *msg, size_t msg_len,
  330. u8 *mac, const u8 *extra, size_t extra_len)
  331. {
  332. unsigned char hmac[SHA256_MAC_LEN];
  333. const u8 *addr[2];
  334. size_t len[2];
  335. addr[0] = msg;
  336. len[0] = msg_len;
  337. addr[1] = extra;
  338. len[1] = extra_len;
  339. /* HMAC-SHA-256-128 */
  340. os_memset(mac, 0, EAP_SIM_MAC_LEN);
  341. wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC - msg", msg, msg_len);
  342. wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC - extra data",
  343. extra, extra_len);
  344. wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA': Add MAC - K_aut",
  345. k_aut, EAP_AKA_PRIME_K_AUT_LEN);
  346. hmac_sha256_vector(k_aut, EAP_AKA_PRIME_K_AUT_LEN, 2, addr, len, hmac);
  347. os_memcpy(mac, hmac, EAP_SIM_MAC_LEN);
  348. wpa_hexdump(MSG_MSGDUMP, "EAP-AKA': Add MAC: MAC",
  349. mac, EAP_SIM_MAC_LEN);
  350. }
  351. void eap_aka_prime_derive_ck_ik_prime(u8 *ck, u8 *ik, const u8 *sqn_ak,
  352. const u8 *network_name,
  353. size_t network_name_len)
  354. {
  355. u8 key[EAP_AKA_CK_LEN + EAP_AKA_IK_LEN];
  356. u8 hash[SHA256_MAC_LEN];
  357. const u8 *addr[5];
  358. size_t len[5];
  359. u8 fc;
  360. u8 l0[2], l1[2];
  361. /* 3GPP TS 33.402 V8.0.0
  362. * (CK', IK') = F(CK, IK, <access network identity>)
  363. */
  364. /* TODO: CK', IK' generation should really be moved into the actual
  365. * AKA procedure with network name passed in there and option to use
  366. * AMF separation bit = 1 (3GPP TS 33.401). */
  367. /* Change Request 33.402 CR 0033 to version 8.1.1 from
  368. * 3GPP TSG-SA WG3 Meeting #53 in September 2008:
  369. *
  370. * CK' || IK' = HMAC-SHA-256(Key, S)
  371. * S = FC || P0 || L0 || P1 || L1 || ... || Pn || Ln
  372. * Key = CK || IK
  373. * FC = 0x20
  374. * P0 = access network identity (3GPP TS 24.302)
  375. * L0 = length of acceess network identity (2 octets, big endian)
  376. * P1 = SQN xor AK (if AK is not used, AK is treaded as 000..0
  377. * L1 = 0x00 0x06
  378. */
  379. fc = 0x20;
  380. wpa_printf(MSG_DEBUG, "EAP-AKA': Derive (CK',IK') from (CK,IK)");
  381. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK", ck, EAP_AKA_CK_LEN);
  382. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK", ik, EAP_AKA_IK_LEN);
  383. wpa_printf(MSG_DEBUG, "EAP-AKA': FC = 0x%x", fc);
  384. wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': P0 = Access network identity",
  385. network_name, network_name_len);
  386. wpa_hexdump(MSG_DEBUG, "EAP-AKA': P1 = SQN xor AK", sqn_ak, 6);
  387. os_memcpy(key, ck, EAP_AKA_CK_LEN);
  388. os_memcpy(key + EAP_AKA_CK_LEN, ik, EAP_AKA_IK_LEN);
  389. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': Key = CK || IK",
  390. key, sizeof(key));
  391. addr[0] = &fc;
  392. len[0] = 1;
  393. addr[1] = network_name;
  394. len[1] = network_name_len;
  395. WPA_PUT_BE16(l0, network_name_len);
  396. addr[2] = l0;
  397. len[2] = 2;
  398. addr[3] = sqn_ak;
  399. len[3] = 6;
  400. WPA_PUT_BE16(l1, 6);
  401. addr[4] = l1;
  402. len[4] = 2;
  403. hmac_sha256_vector(key, sizeof(key), 5, addr, len, hash);
  404. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': KDF output (CK' || IK')",
  405. hash, sizeof(hash));
  406. os_memcpy(ck, hash, EAP_AKA_CK_LEN);
  407. os_memcpy(ik, hash + EAP_AKA_CK_LEN, EAP_AKA_IK_LEN);
  408. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': CK'", ck, EAP_AKA_CK_LEN);
  409. wpa_hexdump_key(MSG_DEBUG, "EAP-AKA': IK'", ik, EAP_AKA_IK_LEN);
  410. }
  411. #endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */
  412. int eap_sim_parse_attr(const u8 *start, const u8 *end,
  413. struct eap_sim_attrs *attr, int aka, int encr)
  414. {
  415. const u8 *pos = start, *apos;
  416. size_t alen, plen, i, list_len;
  417. os_memset(attr, 0, sizeof(*attr));
  418. attr->id_req = NO_ID_REQ;
  419. attr->notification = -1;
  420. attr->counter = -1;
  421. attr->selected_version = -1;
  422. attr->client_error_code = -1;
  423. while (pos < end) {
  424. if (pos + 2 > end) {
  425. wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow(1)");
  426. return -1;
  427. }
  428. wpa_printf(MSG_MSGDUMP, "EAP-SIM: Attribute: Type=%d Len=%d",
  429. pos[0], pos[1] * 4);
  430. if (pos + pos[1] * 4 > end) {
  431. wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow "
  432. "(pos=%p len=%d end=%p)",
  433. pos, pos[1] * 4, end);
  434. return -1;
  435. }
  436. if (pos[1] == 0) {
  437. wpa_printf(MSG_INFO, "EAP-SIM: Attribute underflow");
  438. return -1;
  439. }
  440. apos = pos + 2;
  441. alen = pos[1] * 4 - 2;
  442. wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Attribute data",
  443. apos, alen);
  444. switch (pos[0]) {
  445. case EAP_SIM_AT_RAND:
  446. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RAND");
  447. apos += 2;
  448. alen -= 2;
  449. if ((!aka && (alen % GSM_RAND_LEN)) ||
  450. (aka && alen != EAP_AKA_RAND_LEN)) {
  451. wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RAND"
  452. " (len %lu)",
  453. (unsigned long) alen);
  454. return -1;
  455. }
  456. attr->rand = apos;
  457. attr->num_chal = alen / GSM_RAND_LEN;
  458. break;
  459. case EAP_SIM_AT_AUTN:
  460. wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTN");
  461. if (!aka) {
  462. wpa_printf(MSG_DEBUG, "EAP-SIM: "
  463. "Unexpected AT_AUTN");
  464. return -1;
  465. }
  466. apos += 2;
  467. alen -= 2;
  468. if (alen != EAP_AKA_AUTN_LEN) {
  469. wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTN"
  470. " (len %lu)",
  471. (unsigned long) alen);
  472. return -1;
  473. }
  474. attr->autn = apos;
  475. break;
  476. case EAP_SIM_AT_PADDING:
  477. if (!encr) {
  478. wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
  479. "AT_PADDING");
  480. return -1;
  481. }
  482. wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_PADDING");
  483. for (i = 2; i < alen; i++) {
  484. if (apos[i] != 0) {
  485. wpa_printf(MSG_INFO, "EAP-SIM: (encr) "
  486. "AT_PADDING used a non-zero"
  487. " padding byte");
  488. wpa_hexdump(MSG_DEBUG, "EAP-SIM: "
  489. "(encr) padding bytes",
  490. apos + 2, alen - 2);
  491. return -1;
  492. }
  493. }
  494. break;
  495. case EAP_SIM_AT_NONCE_MT:
  496. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NONCE_MT");
  497. if (alen != 2 + EAP_SIM_NONCE_MT_LEN) {
  498. wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
  499. "AT_NONCE_MT length");
  500. return -1;
  501. }
  502. attr->nonce_mt = apos + 2;
  503. break;
  504. case EAP_SIM_AT_PERMANENT_ID_REQ:
  505. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_PERMANENT_ID_REQ");
  506. attr->id_req = PERMANENT_ID;
  507. break;
  508. case EAP_SIM_AT_MAC:
  509. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_MAC");
  510. if (alen != 2 + EAP_SIM_MAC_LEN) {
  511. wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_MAC "
  512. "length");
  513. return -1;
  514. }
  515. attr->mac = apos + 2;
  516. break;
  517. case EAP_SIM_AT_NOTIFICATION:
  518. if (alen != 2) {
  519. wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
  520. "AT_NOTIFICATION length %lu",
  521. (unsigned long) alen);
  522. return -1;
  523. }
  524. attr->notification = apos[0] * 256 + apos[1];
  525. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NOTIFICATION %d",
  526. attr->notification);
  527. break;
  528. case EAP_SIM_AT_ANY_ID_REQ:
  529. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ANY_ID_REQ");
  530. attr->id_req = ANY_ID;
  531. break;
  532. case EAP_SIM_AT_IDENTITY:
  533. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IDENTITY");
  534. plen = WPA_GET_BE16(apos);
  535. apos += 2;
  536. alen -= 2;
  537. if (plen > alen) {
  538. wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
  539. "AT_IDENTITY (Actual Length %lu, "
  540. "remaining length %lu)",
  541. (unsigned long) plen,
  542. (unsigned long) alen);
  543. return -1;
  544. }
  545. attr->identity = apos;
  546. attr->identity_len = plen;
  547. break;
  548. case EAP_SIM_AT_VERSION_LIST:
  549. if (aka) {
  550. wpa_printf(MSG_DEBUG, "EAP-AKA: "
  551. "Unexpected AT_VERSION_LIST");
  552. return -1;
  553. }
  554. list_len = apos[0] * 256 + apos[1];
  555. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_VERSION_LIST");
  556. if (list_len < 2 || list_len > alen - 2) {
  557. wpa_printf(MSG_WARNING, "EAP-SIM: Invalid "
  558. "AT_VERSION_LIST (list_len=%lu "
  559. "attr_len=%lu)",
  560. (unsigned long) list_len,
  561. (unsigned long) alen);
  562. return -1;
  563. }
  564. attr->version_list = apos + 2;
  565. attr->version_list_len = list_len;
  566. break;
  567. case EAP_SIM_AT_SELECTED_VERSION:
  568. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION");
  569. if (alen != 2) {
  570. wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
  571. "AT_SELECTED_VERSION length %lu",
  572. (unsigned long) alen);
  573. return -1;
  574. }
  575. attr->selected_version = apos[0] * 256 + apos[1];
  576. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION "
  577. "%d", attr->selected_version);
  578. break;
  579. case EAP_SIM_AT_FULLAUTH_ID_REQ:
  580. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_FULLAUTH_ID_REQ");
  581. attr->id_req = FULLAUTH_ID;
  582. break;
  583. case EAP_SIM_AT_COUNTER:
  584. if (!encr) {
  585. wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
  586. "AT_COUNTER");
  587. return -1;
  588. }
  589. if (alen != 2) {
  590. wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
  591. "AT_COUNTER (alen=%lu)",
  592. (unsigned long) alen);
  593. return -1;
  594. }
  595. attr->counter = apos[0] * 256 + apos[1];
  596. wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_COUNTER %d",
  597. attr->counter);
  598. break;
  599. case EAP_SIM_AT_COUNTER_TOO_SMALL:
  600. if (!encr) {
  601. wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
  602. "AT_COUNTER_TOO_SMALL");
  603. return -1;
  604. }
  605. if (alen != 2) {
  606. wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
  607. "AT_COUNTER_TOO_SMALL (alen=%lu)",
  608. (unsigned long) alen);
  609. return -1;
  610. }
  611. wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
  612. "AT_COUNTER_TOO_SMALL");
  613. attr->counter_too_small = 1;
  614. break;
  615. case EAP_SIM_AT_NONCE_S:
  616. if (!encr) {
  617. wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
  618. "AT_NONCE_S");
  619. return -1;
  620. }
  621. wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
  622. "AT_NONCE_S");
  623. if (alen != 2 + EAP_SIM_NONCE_S_LEN) {
  624. wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
  625. "AT_NONCE_S (alen=%lu)",
  626. (unsigned long) alen);
  627. return -1;
  628. }
  629. attr->nonce_s = apos + 2;
  630. break;
  631. case EAP_SIM_AT_CLIENT_ERROR_CODE:
  632. if (alen != 2) {
  633. wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
  634. "AT_CLIENT_ERROR_CODE length %lu",
  635. (unsigned long) alen);
  636. return -1;
  637. }
  638. attr->client_error_code = apos[0] * 256 + apos[1];
  639. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_CLIENT_ERROR_CODE "
  640. "%d", attr->client_error_code);
  641. break;
  642. case EAP_SIM_AT_IV:
  643. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IV");
  644. if (alen != 2 + EAP_SIM_MAC_LEN) {
  645. wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_IV "
  646. "length %lu", (unsigned long) alen);
  647. return -1;
  648. }
  649. attr->iv = apos + 2;
  650. break;
  651. case EAP_SIM_AT_ENCR_DATA:
  652. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ENCR_DATA");
  653. attr->encr_data = apos + 2;
  654. attr->encr_data_len = alen - 2;
  655. if (attr->encr_data_len % 16) {
  656. wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
  657. "AT_ENCR_DATA length %lu",
  658. (unsigned long)
  659. attr->encr_data_len);
  660. return -1;
  661. }
  662. break;
  663. case EAP_SIM_AT_NEXT_PSEUDONYM:
  664. if (!encr) {
  665. wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
  666. "AT_NEXT_PSEUDONYM");
  667. return -1;
  668. }
  669. wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
  670. "AT_NEXT_PSEUDONYM");
  671. plen = apos[0] * 256 + apos[1];
  672. if (plen > alen - 2) {
  673. wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid"
  674. " AT_NEXT_PSEUDONYM (actual"
  675. " len %lu, attr len %lu)",
  676. (unsigned long) plen,
  677. (unsigned long) alen);
  678. return -1;
  679. }
  680. attr->next_pseudonym = pos + 4;
  681. attr->next_pseudonym_len = plen;
  682. break;
  683. case EAP_SIM_AT_NEXT_REAUTH_ID:
  684. if (!encr) {
  685. wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
  686. "AT_NEXT_REAUTH_ID");
  687. return -1;
  688. }
  689. wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
  690. "AT_NEXT_REAUTH_ID");
  691. plen = apos[0] * 256 + apos[1];
  692. if (plen > alen - 2) {
  693. wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid"
  694. " AT_NEXT_REAUTH_ID (actual"
  695. " len %lu, attr len %lu)",
  696. (unsigned long) plen,
  697. (unsigned long) alen);
  698. return -1;
  699. }
  700. attr->next_reauth_id = pos + 4;
  701. attr->next_reauth_id_len = plen;
  702. break;
  703. case EAP_SIM_AT_RES:
  704. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RES");
  705. attr->res_len_bits = WPA_GET_BE16(apos);
  706. apos += 2;
  707. alen -= 2;
  708. if (!aka || alen < EAP_AKA_MIN_RES_LEN ||
  709. alen > EAP_AKA_MAX_RES_LEN) {
  710. wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RES "
  711. "(len %lu)",
  712. (unsigned long) alen);
  713. return -1;
  714. }
  715. attr->res = apos;
  716. attr->res_len = alen;
  717. break;
  718. case EAP_SIM_AT_AUTS:
  719. wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTS");
  720. if (!aka) {
  721. wpa_printf(MSG_DEBUG, "EAP-SIM: "
  722. "Unexpected AT_AUTS");
  723. return -1;
  724. }
  725. if (alen != EAP_AKA_AUTS_LEN) {
  726. wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTS"
  727. " (len %lu)",
  728. (unsigned long) alen);
  729. return -1;
  730. }
  731. attr->auts = apos;
  732. break;
  733. case EAP_SIM_AT_CHECKCODE:
  734. wpa_printf(MSG_DEBUG, "EAP-AKA: AT_CHECKCODE");
  735. if (!aka) {
  736. wpa_printf(MSG_DEBUG, "EAP-SIM: "
  737. "Unexpected AT_CHECKCODE");
  738. return -1;
  739. }
  740. apos += 2;
  741. alen -= 2;
  742. if (alen != 0 && alen != EAP_AKA_CHECKCODE_LEN &&
  743. alen != EAP_AKA_PRIME_CHECKCODE_LEN) {
  744. wpa_printf(MSG_INFO, "EAP-AKA: Invalid "
  745. "AT_CHECKCODE (len %lu)",
  746. (unsigned long) alen);
  747. return -1;
  748. }
  749. attr->checkcode = apos;
  750. attr->checkcode_len = alen;
  751. break;
  752. case EAP_SIM_AT_RESULT_IND:
  753. if (encr) {
  754. wpa_printf(MSG_ERROR, "EAP-SIM: Encrypted "
  755. "AT_RESULT_IND");
  756. return -1;
  757. }
  758. if (alen != 2) {
  759. wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
  760. "AT_RESULT_IND (alen=%lu)",
  761. (unsigned long) alen);
  762. return -1;
  763. }
  764. wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RESULT_IND");
  765. attr->result_ind = 1;
  766. break;
  767. #if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
  768. case EAP_SIM_AT_KDF_INPUT:
  769. if (aka != 2) {
  770. wpa_printf(MSG_INFO, "EAP-AKA: Unexpected "
  771. "AT_KDF_INPUT");
  772. return -1;
  773. }
  774. wpa_printf(MSG_DEBUG, "EAP-AKA: AT_KDF_INPUT");
  775. plen = WPA_GET_BE16(apos);
  776. apos += 2;
  777. alen -= 2;
  778. if (plen > alen) {
  779. wpa_printf(MSG_INFO, "EAP-AKA': Invalid "
  780. "AT_KDF_INPUT (Actual Length %lu, "
  781. "remaining length %lu)",
  782. (unsigned long) plen,
  783. (unsigned long) alen);
  784. return -1;
  785. }
  786. attr->kdf_input = apos;
  787. attr->kdf_input_len = plen;
  788. break;
  789. case EAP_SIM_AT_KDF:
  790. if (aka != 2) {
  791. wpa_printf(MSG_INFO, "EAP-AKA: Unexpected "
  792. "AT_KDF");
  793. return -1;
  794. }
  795. wpa_printf(MSG_DEBUG, "EAP-AKA: AT_KDF");
  796. if (alen != 2) {
  797. wpa_printf(MSG_INFO, "EAP-AKA': Invalid "
  798. "AT_KDF (len %lu)",
  799. (unsigned long) alen);
  800. return -1;
  801. }
  802. if (attr->kdf_count == EAP_AKA_PRIME_KDF_MAX) {
  803. wpa_printf(MSG_DEBUG, "EAP-AKA': Too many "
  804. "AT_KDF attributes - ignore this");
  805. break;
  806. }
  807. attr->kdf[attr->kdf_count] = WPA_GET_BE16(apos);
  808. attr->kdf_count++;
  809. break;
  810. case EAP_SIM_AT_BIDDING:
  811. wpa_printf(MSG_DEBUG, "EAP-AKA: AT_BIDDING");
  812. if (alen != 2) {
  813. wpa_printf(MSG_INFO, "EAP-AKA: Invalid "
  814. "AT_BIDDING (len %lu)",
  815. (unsigned long) alen);
  816. return -1;
  817. }
  818. attr->bidding = apos;
  819. break;
  820. #endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */
  821. default:
  822. if (pos[0] < 128) {
  823. wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized "
  824. "non-skippable attribute %d",
  825. pos[0]);
  826. return -1;
  827. }
  828. wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized skippable"
  829. " attribute %d ignored", pos[0]);
  830. break;
  831. }
  832. pos += pos[1] * 4;
  833. }
  834. wpa_printf(MSG_DEBUG, "EAP-SIM: Attributes parsed successfully "
  835. "(aka=%d encr=%d)", aka, encr);
  836. return 0;
  837. }
  838. u8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data,
  839. size_t encr_data_len, const u8 *iv,
  840. struct eap_sim_attrs *attr, int aka)
  841. {
  842. u8 *decrypted;
  843. if (!iv) {
  844. wpa_printf(MSG_INFO, "EAP-SIM: Encrypted data, but no IV");
  845. return NULL;
  846. }
  847. decrypted = os_memdup(encr_data, encr_data_len);
  848. if (decrypted == NULL)
  849. return NULL;
  850. if (aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len)) {
  851. os_free(decrypted);
  852. return NULL;
  853. }
  854. wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA",
  855. decrypted, encr_data_len);
  856. if (eap_sim_parse_attr(decrypted, decrypted + encr_data_len, attr,
  857. aka, 1)) {
  858. wpa_printf(MSG_INFO, "EAP-SIM: (encr) Failed to parse "
  859. "decrypted AT_ENCR_DATA");
  860. os_free(decrypted);
  861. return NULL;
  862. }
  863. return decrypted;
  864. }
  865. #define EAP_SIM_INIT_LEN 128
  866. struct eap_sim_msg {
  867. struct wpabuf *buf;
  868. size_t mac, iv, encr; /* index from buf */
  869. };
  870. struct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype)
  871. {
  872. struct eap_sim_msg *msg;
  873. struct eap_hdr *eap;
  874. u8 *pos;
  875. msg = os_zalloc(sizeof(*msg));
  876. if (msg == NULL)
  877. return NULL;
  878. msg->buf = wpabuf_alloc(EAP_SIM_INIT_LEN);
  879. if (msg->buf == NULL) {
  880. os_free(msg);
  881. return NULL;
  882. }
  883. eap = wpabuf_put(msg->buf, sizeof(*eap));
  884. eap->code = code;
  885. eap->identifier = id;
  886. pos = wpabuf_put(msg->buf, 4);
  887. *pos++ = type;
  888. *pos++ = subtype;
  889. *pos++ = 0; /* Reserved */
  890. *pos++ = 0; /* Reserved */
  891. return msg;
  892. }
  893. struct wpabuf * eap_sim_msg_finish(struct eap_sim_msg *msg, int type,
  894. const u8 *k_aut,
  895. const u8 *extra, size_t extra_len)
  896. {
  897. struct eap_hdr *eap;
  898. struct wpabuf *buf;
  899. if (msg == NULL)
  900. return NULL;
  901. eap = wpabuf_mhead(msg->buf);
  902. eap->length = host_to_be16(wpabuf_len(msg->buf));
  903. #if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
  904. if (k_aut && msg->mac && type == EAP_TYPE_AKA_PRIME) {
  905. eap_sim_add_mac_sha256(k_aut, (u8 *) wpabuf_head(msg->buf),
  906. wpabuf_len(msg->buf),
  907. (u8 *) wpabuf_mhead(msg->buf) +
  908. msg->mac, extra, extra_len);
  909. } else
  910. #endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */
  911. if (k_aut && msg->mac) {
  912. eap_sim_add_mac(k_aut, (u8 *) wpabuf_head(msg->buf),
  913. wpabuf_len(msg->buf),
  914. (u8 *) wpabuf_mhead(msg->buf) + msg->mac,
  915. extra, extra_len);
  916. }
  917. buf = msg->buf;
  918. os_free(msg);
  919. return buf;
  920. }
  921. void eap_sim_msg_free(struct eap_sim_msg *msg)
  922. {
  923. if (msg) {
  924. wpabuf_free(msg->buf);
  925. os_free(msg);
  926. }
  927. }
  928. u8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr,
  929. const u8 *data, size_t len)
  930. {
  931. int attr_len = 2 + len;
  932. int pad_len;
  933. u8 *start;
  934. if (msg == NULL)
  935. return NULL;
  936. pad_len = (4 - attr_len % 4) % 4;
  937. attr_len += pad_len;
  938. if (wpabuf_resize(&msg->buf, attr_len))
  939. return NULL;
  940. start = wpabuf_put(msg->buf, 0);
  941. wpabuf_put_u8(msg->buf, attr);
  942. wpabuf_put_u8(msg->buf, attr_len / 4);
  943. wpabuf_put_data(msg->buf, data, len);
  944. if (pad_len)
  945. os_memset(wpabuf_put(msg->buf, pad_len), 0, pad_len);
  946. return start;
  947. }
  948. u8 * eap_sim_msg_add(struct eap_sim_msg *msg, u8 attr, u16 value,
  949. const u8 *data, size_t len)
  950. {
  951. int attr_len = 4 + len;
  952. int pad_len;
  953. u8 *start;
  954. if (msg == NULL)
  955. return NULL;
  956. pad_len = (4 - attr_len % 4) % 4;
  957. attr_len += pad_len;
  958. if (wpabuf_resize(&msg->buf, attr_len))
  959. return NULL;
  960. start = wpabuf_put(msg->buf, 0);
  961. wpabuf_put_u8(msg->buf, attr);
  962. wpabuf_put_u8(msg->buf, attr_len / 4);
  963. wpabuf_put_be16(msg->buf, value);
  964. if (data)
  965. wpabuf_put_data(msg->buf, data, len);
  966. else
  967. wpabuf_put(msg->buf, len);
  968. if (pad_len)
  969. os_memset(wpabuf_put(msg->buf, pad_len), 0, pad_len);
  970. return start;
  971. }
  972. u8 * eap_sim_msg_add_mac(struct eap_sim_msg *msg, u8 attr)
  973. {
  974. u8 *pos = eap_sim_msg_add(msg, attr, 0, NULL, EAP_SIM_MAC_LEN);
  975. if (pos)
  976. msg->mac = (pos - wpabuf_head_u8(msg->buf)) + 4;
  977. return pos;
  978. }
  979. int eap_sim_msg_add_encr_start(struct eap_sim_msg *msg, u8 attr_iv,
  980. u8 attr_encr)
  981. {
  982. u8 *pos = eap_sim_msg_add(msg, attr_iv, 0, NULL, EAP_SIM_IV_LEN);
  983. if (pos == NULL)
  984. return -1;
  985. msg->iv = (pos - wpabuf_head_u8(msg->buf)) + 4;
  986. if (random_get_bytes(wpabuf_mhead_u8(msg->buf) + msg->iv,
  987. EAP_SIM_IV_LEN)) {
  988. msg->iv = 0;
  989. return -1;
  990. }
  991. pos = eap_sim_msg_add(msg, attr_encr, 0, NULL, 0);
  992. if (pos == NULL) {
  993. msg->iv = 0;
  994. return -1;
  995. }
  996. msg->encr = pos - wpabuf_head_u8(msg->buf);
  997. return 0;
  998. }
  999. int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, int attr_pad)
  1000. {
  1001. size_t encr_len;
  1002. if (msg == NULL || k_encr == NULL || msg->iv == 0 || msg->encr == 0)
  1003. return -1;
  1004. encr_len = wpabuf_len(msg->buf) - msg->encr - 4;
  1005. if (encr_len % 16) {
  1006. u8 *pos;
  1007. int pad_len = 16 - (encr_len % 16);
  1008. if (pad_len < 4) {
  1009. wpa_printf(MSG_WARNING, "EAP-SIM: "
  1010. "eap_sim_msg_add_encr_end - invalid pad_len"
  1011. " %d", pad_len);
  1012. return -1;
  1013. }
  1014. wpa_printf(MSG_DEBUG, " *AT_PADDING");
  1015. pos = eap_sim_msg_add(msg, attr_pad, 0, NULL, pad_len - 4);
  1016. if (pos == NULL)
  1017. return -1;
  1018. os_memset(pos + 4, 0, pad_len - 4);
  1019. encr_len += pad_len;
  1020. }
  1021. wpa_printf(MSG_DEBUG, " (AT_ENCR_DATA data len %lu)",
  1022. (unsigned long) encr_len);
  1023. wpabuf_mhead_u8(msg->buf)[msg->encr + 1] = encr_len / 4 + 1;
  1024. return aes_128_cbc_encrypt(k_encr, wpabuf_head_u8(msg->buf) + msg->iv,
  1025. wpabuf_mhead_u8(msg->buf) + msg->encr + 4,
  1026. encr_len);
  1027. }
  1028. void eap_sim_report_notification(void *msg_ctx, int notification, int aka)
  1029. {
  1030. #ifndef CONFIG_NO_STDOUT_DEBUG
  1031. const char *type = aka ? "AKA" : "SIM";
  1032. #endif /* CONFIG_NO_STDOUT_DEBUG */
  1033. switch (notification) {
  1034. case EAP_SIM_GENERAL_FAILURE_AFTER_AUTH:
  1035. wpa_printf(MSG_WARNING, "EAP-%s: General failure "
  1036. "notification (after authentication)", type);
  1037. break;
  1038. case EAP_SIM_TEMPORARILY_DENIED:
  1039. wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: "
  1040. "User has been temporarily denied access to the "
  1041. "requested service", type);
  1042. break;
  1043. case EAP_SIM_NOT_SUBSCRIBED:
  1044. wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: "
  1045. "User has not subscribed to the requested service",
  1046. type);
  1047. break;
  1048. case EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH:
  1049. wpa_printf(MSG_WARNING, "EAP-%s: General failure "
  1050. "notification (before authentication)", type);
  1051. break;
  1052. case EAP_SIM_SUCCESS:
  1053. wpa_printf(MSG_INFO, "EAP-%s: Successful authentication "
  1054. "notification", type);
  1055. break;
  1056. default:
  1057. if (notification >= 32768) {
  1058. wpa_printf(MSG_INFO, "EAP-%s: Unrecognized "
  1059. "non-failure notification %d",
  1060. type, notification);
  1061. } else {
  1062. wpa_printf(MSG_WARNING, "EAP-%s: Unrecognized "
  1063. "failure notification %d",
  1064. type, notification);
  1065. }
  1066. }
  1067. }