LCOV - code coverage report
Current view: top level - src/eap_server - eap_server_aka.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1393793999 Lines: 441 669 65.9 %
Date: 2014-03-02 Functions: 31 35 88.6 %
Branches: 198 344 57.6 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * hostapd / EAP-AKA (RFC 4187) and EAP-AKA' (RFC 5448)
       3                 :            :  * Copyright (c) 2005-2012, 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                 :            : 
       9                 :            : #include "includes.h"
      10                 :            : 
      11                 :            : #include "common.h"
      12                 :            : #include "crypto/sha256.h"
      13                 :            : #include "crypto/crypto.h"
      14                 :            : #include "crypto/random.h"
      15                 :            : #include "eap_common/eap_sim_common.h"
      16                 :            : #include "eap_server/eap_i.h"
      17                 :            : #include "eap_server/eap_sim_db.h"
      18                 :            : 
      19                 :            : 
      20                 :            : struct eap_aka_data {
      21                 :            :         u8 mk[EAP_SIM_MK_LEN];
      22                 :            :         u8 nonce_s[EAP_SIM_NONCE_S_LEN];
      23                 :            :         u8 k_aut[EAP_AKA_PRIME_K_AUT_LEN];
      24                 :            :         u8 k_encr[EAP_SIM_K_ENCR_LEN];
      25                 :            :         u8 k_re[EAP_AKA_PRIME_K_RE_LEN]; /* EAP-AKA' only */
      26                 :            :         u8 msk[EAP_SIM_KEYING_DATA_LEN];
      27                 :            :         u8 emsk[EAP_EMSK_LEN];
      28                 :            :         u8 rand[EAP_AKA_RAND_LEN];
      29                 :            :         u8 autn[EAP_AKA_AUTN_LEN];
      30                 :            :         u8 ck[EAP_AKA_CK_LEN];
      31                 :            :         u8 ik[EAP_AKA_IK_LEN];
      32                 :            :         u8 res[EAP_AKA_RES_MAX_LEN];
      33                 :            :         size_t res_len;
      34                 :            :         enum {
      35                 :            :                 IDENTITY, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE
      36                 :            :         } state;
      37                 :            :         char *next_pseudonym;
      38                 :            :         char *next_reauth_id;
      39                 :            :         u16 counter;
      40                 :            :         struct eap_sim_reauth *reauth;
      41                 :            :         int auts_reported; /* whether the current AUTS has been reported to the
      42                 :            :                             * eap_sim_db */
      43                 :            :         u16 notification;
      44                 :            :         int use_result_ind;
      45                 :            : 
      46                 :            :         struct wpabuf *id_msgs;
      47                 :            :         int pending_id;
      48                 :            :         u8 eap_method;
      49                 :            :         u8 *network_name;
      50                 :            :         size_t network_name_len;
      51                 :            :         u16 kdf;
      52                 :            :         int identity_round;
      53                 :            :         char permanent[20]; /* Permanent username */
      54                 :            : };
      55                 :            : 
      56                 :            : 
      57                 :            : static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data);
      58                 :            : 
      59                 :            : 
      60                 :         34 : static const char * eap_aka_state_txt(int state)
      61                 :            : {
      62   [ +  +  +  +  :         34 :         switch (state) {
                +  -  - ]
      63                 :            :         case IDENTITY:
      64                 :          8 :                 return "IDENTITY";
      65                 :            :         case CHALLENGE:
      66                 :         14 :                 return "CHALLENGE";
      67                 :            :         case REAUTH:
      68                 :          4 :                 return "REAUTH";
      69                 :            :         case SUCCESS:
      70                 :          6 :                 return "SUCCESS";
      71                 :            :         case FAILURE:
      72                 :          2 :                 return "FAILURE";
      73                 :            :         case NOTIFICATION:
      74                 :          0 :                 return "NOTIFICATION";
      75                 :            :         default:
      76                 :         34 :                 return "Unknown?!";
      77                 :            :         }
      78                 :            : }
      79                 :            : 
      80                 :            : 
      81                 :         17 : static void eap_aka_state(struct eap_aka_data *data, int state)
      82                 :            : {
      83                 :         17 :         wpa_printf(MSG_DEBUG, "EAP-AKA: %s -> %s",
      84                 :         17 :                    eap_aka_state_txt(data->state),
      85                 :            :                    eap_aka_state_txt(state));
      86                 :         17 :         data->state = state;
      87                 :         17 : }
      88                 :            : 
      89                 :            : 
      90                 :         20 : static int eap_aka_check_identity_reauth(struct eap_sm *sm,
      91                 :            :                                          struct eap_aka_data *data,
      92                 :            :                                          const char *username)
      93                 :            : {
      94 [ +  + ][ +  + ]:         20 :         if (data->eap_method == EAP_TYPE_AKA_PRIME &&
      95                 :         10 :             username[0] != EAP_AKA_PRIME_REAUTH_ID_PREFIX)
      96                 :          9 :                 return 0;
      97 [ +  + ][ +  + ]:         11 :         if (data->eap_method == EAP_TYPE_AKA &&
      98                 :         10 :             username[0] != EAP_AKA_REAUTH_ID_PREFIX)
      99                 :          9 :                 return 0;
     100                 :            : 
     101                 :          2 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth username '%s'", username);
     102                 :          2 :         data->reauth = eap_sim_db_get_reauth_entry(sm->eap_sim_db_priv,
     103                 :            :                                                    username);
     104         [ -  + ]:          2 :         if (data->reauth == NULL) {
     105                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown reauth identity - "
     106                 :            :                            "request full auth identity");
     107                 :            :                 /* Remain in IDENTITY state for another round */
     108                 :          0 :                 return 0;
     109                 :            :         }
     110                 :            : 
     111                 :          2 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast re-authentication");
     112                 :          2 :         os_strlcpy(data->permanent, data->reauth->permanent,
     113                 :            :                    sizeof(data->permanent));
     114                 :          2 :         data->counter = data->reauth->counter;
     115         [ +  + ]:          2 :         if (data->eap_method == EAP_TYPE_AKA_PRIME) {
     116                 :          1 :                 os_memcpy(data->k_encr, data->reauth->k_encr,
     117                 :            :                           EAP_SIM_K_ENCR_LEN);
     118                 :          1 :                 os_memcpy(data->k_aut, data->reauth->k_aut,
     119                 :            :                           EAP_AKA_PRIME_K_AUT_LEN);
     120                 :          1 :                 os_memcpy(data->k_re, data->reauth->k_re,
     121                 :            :                           EAP_AKA_PRIME_K_RE_LEN);
     122                 :            :         } else {
     123                 :          1 :                 os_memcpy(data->mk, data->reauth->mk, EAP_SIM_MK_LEN);
     124                 :            :         }
     125                 :            : 
     126                 :          2 :         eap_aka_state(data, REAUTH);
     127                 :         20 :         return 1;
     128                 :            : }
     129                 :            : 
     130                 :            : 
     131                 :          8 : static void eap_aka_check_identity(struct eap_sm *sm,
     132                 :            :                                    struct eap_aka_data *data)
     133                 :            : {
     134                 :            :         char *username;
     135                 :            : 
     136                 :            :         /* Check if we already know the identity from EAP-Response/Identity */
     137                 :            : 
     138                 :          8 :         username = sim_get_username(sm->identity, sm->identity_len);
     139         [ -  + ]:          8 :         if (username == NULL)
     140                 :          0 :                 return;
     141                 :            : 
     142         [ +  + ]:          8 :         if (eap_aka_check_identity_reauth(sm, data, username) > 0) {
     143                 :          2 :                 os_free(username);
     144                 :            :                 /*
     145                 :            :                  * Since re-auth username was recognized, skip AKA/Identity
     146                 :            :                  * exchange.
     147                 :            :                  */
     148                 :          2 :                 return;
     149                 :            :         }
     150                 :            : 
     151 [ +  + ][ +  - ]:          6 :         if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
     152         [ +  + ]:          6 :              username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
     153         [ -  + ]:          3 :             (data->eap_method == EAP_TYPE_AKA &&
     154                 :          3 :              username[0] == EAP_AKA_PSEUDONYM_PREFIX)) {
     155                 :            :                 const char *permanent;
     156                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
     157                 :            :                            username);
     158                 :          0 :                 permanent = eap_sim_db_get_permanent(
     159                 :            :                         sm->eap_sim_db_priv, username);
     160         [ #  # ]:          0 :                 if (permanent == NULL) {
     161                 :          0 :                         os_free(username);
     162                 :          0 :                         wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
     163                 :            :                                    "identity - request permanent identity");
     164                 :            :                         /* Remain in IDENTITY state for another round */
     165                 :          0 :                         return;
     166                 :            :                 }
     167                 :          0 :                 os_strlcpy(data->permanent, permanent,
     168                 :            :                            sizeof(data->permanent));
     169                 :            :                 /*
     170                 :            :                  * Since pseudonym username was recognized, skip AKA/Identity
     171                 :            :                  * exchange.
     172                 :            :                  */
     173                 :          0 :                 eap_aka_fullauth(sm, data);
     174                 :            :         }
     175                 :            : 
     176                 :          8 :         os_free(username);
     177                 :            : }
     178                 :            : 
     179                 :            : 
     180                 :          4 : static void * eap_aka_init(struct eap_sm *sm)
     181                 :            : {
     182                 :            :         struct eap_aka_data *data;
     183                 :            : 
     184         [ -  + ]:          4 :         if (sm->eap_sim_db_priv == NULL) {
     185                 :          0 :                 wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
     186                 :          0 :                 return NULL;
     187                 :            :         }
     188                 :            : 
     189                 :          4 :         data = os_zalloc(sizeof(*data));
     190         [ -  + ]:          4 :         if (data == NULL)
     191                 :          0 :                 return NULL;
     192                 :            : 
     193                 :          4 :         data->eap_method = EAP_TYPE_AKA;
     194                 :            : 
     195                 :          4 :         data->state = IDENTITY;
     196                 :          4 :         data->pending_id = -1;
     197                 :          4 :         eap_aka_check_identity(sm, data);
     198                 :            : 
     199                 :          4 :         return data;
     200                 :            : }
     201                 :            : 
     202                 :            : 
     203                 :            : #ifdef EAP_SERVER_AKA_PRIME
     204                 :          4 : static void * eap_aka_prime_init(struct eap_sm *sm)
     205                 :            : {
     206                 :            :         struct eap_aka_data *data;
     207                 :            :         /* TODO: make ANID configurable; see 3GPP TS 24.302 */
     208                 :          4 :         char *network_name = "WLAN";
     209                 :            : 
     210         [ -  + ]:          4 :         if (sm->eap_sim_db_priv == NULL) {
     211                 :          0 :                 wpa_printf(MSG_WARNING, "EAP-AKA: eap_sim_db not configured");
     212                 :          0 :                 return NULL;
     213                 :            :         }
     214                 :            : 
     215                 :          4 :         data = os_zalloc(sizeof(*data));
     216         [ -  + ]:          4 :         if (data == NULL)
     217                 :          0 :                 return NULL;
     218                 :            : 
     219                 :          4 :         data->eap_method = EAP_TYPE_AKA_PRIME;
     220                 :          4 :         data->network_name = (u8 *) os_strdup(network_name);
     221         [ -  + ]:          4 :         if (data->network_name == NULL) {
     222                 :          0 :                 os_free(data);
     223                 :          0 :                 return NULL;
     224                 :            :         }
     225                 :            : 
     226                 :          4 :         data->network_name_len = os_strlen(network_name);
     227                 :            : 
     228                 :          4 :         data->state = IDENTITY;
     229                 :          4 :         data->pending_id = -1;
     230                 :          4 :         eap_aka_check_identity(sm, data);
     231                 :            : 
     232                 :          4 :         return data;
     233                 :            : }
     234                 :            : #endif /* EAP_SERVER_AKA_PRIME */
     235                 :            : 
     236                 :            : 
     237                 :          8 : static void eap_aka_reset(struct eap_sm *sm, void *priv)
     238                 :            : {
     239                 :          8 :         struct eap_aka_data *data = priv;
     240                 :          8 :         os_free(data->next_pseudonym);
     241                 :          8 :         os_free(data->next_reauth_id);
     242                 :          8 :         wpabuf_free(data->id_msgs);
     243                 :          8 :         os_free(data->network_name);
     244                 :          8 :         os_free(data);
     245                 :          8 : }
     246                 :            : 
     247                 :            : 
     248                 :         12 : static int eap_aka_add_id_msg(struct eap_aka_data *data,
     249                 :            :                               const struct wpabuf *msg)
     250                 :            : {
     251         [ -  + ]:         12 :         if (msg == NULL)
     252                 :          0 :                 return -1;
     253                 :            : 
     254         [ +  + ]:         12 :         if (data->id_msgs == NULL) {
     255                 :          6 :                 data->id_msgs = wpabuf_dup(msg);
     256         [ -  + ]:          6 :                 return data->id_msgs == NULL ? -1 : 0;
     257                 :            :         }
     258                 :            : 
     259         [ -  + ]:          6 :         if (wpabuf_resize(&data->id_msgs, wpabuf_len(msg)) < 0)
     260                 :          0 :                 return -1;
     261                 :          6 :         wpabuf_put_buf(data->id_msgs, msg);
     262                 :            : 
     263                 :         12 :         return 0;
     264                 :            : }
     265                 :            : 
     266                 :            : 
     267                 :          9 : static void eap_aka_add_checkcode(struct eap_aka_data *data,
     268                 :            :                                   struct eap_sim_msg *msg)
     269                 :            : {
     270                 :            :         const u8 *addr;
     271                 :            :         size_t len;
     272                 :            :         u8 hash[SHA256_MAC_LEN];
     273                 :            : 
     274                 :          9 :         wpa_printf(MSG_DEBUG, "   AT_CHECKCODE");
     275                 :            : 
     276         [ +  + ]:          9 :         if (data->id_msgs == NULL) {
     277                 :            :                 /*
     278                 :            :                  * No EAP-AKA/Identity packets were exchanged - send empty
     279                 :            :                  * checkcode.
     280                 :            :                  */
     281                 :          2 :                 eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, NULL, 0);
     282                 :          9 :                 return;
     283                 :            :         }
     284                 :            : 
     285                 :            :         /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
     286                 :          7 :         addr = wpabuf_head(data->id_msgs);
     287                 :          7 :         len = wpabuf_len(data->id_msgs);
     288                 :          7 :         wpa_hexdump(MSG_MSGDUMP, "EAP-AKA: AT_CHECKCODE data", addr, len);
     289         [ +  + ]:          7 :         if (data->eap_method == EAP_TYPE_AKA_PRIME)
     290                 :          3 :                 sha256_vector(1, &addr, &len, hash);
     291                 :            :         else
     292                 :          4 :                 sha1_vector(1, &addr, &len, hash);
     293                 :            : 
     294         [ +  + ]:          7 :         eap_sim_msg_add(msg, EAP_SIM_AT_CHECKCODE, 0, hash,
     295                 :          7 :                         data->eap_method == EAP_TYPE_AKA_PRIME ?
     296                 :            :                         EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN);
     297                 :            : }
     298                 :            : 
     299                 :            : 
     300                 :          4 : static int eap_aka_verify_checkcode(struct eap_aka_data *data,
     301                 :            :                                     const u8 *checkcode, size_t checkcode_len)
     302                 :            : {
     303                 :            :         const u8 *addr;
     304                 :            :         size_t len;
     305                 :            :         u8 hash[SHA256_MAC_LEN];
     306                 :            :         size_t hash_len;
     307                 :            : 
     308         [ -  + ]:          4 :         if (checkcode == NULL)
     309                 :          0 :                 return -1;
     310                 :            : 
     311         [ -  + ]:          4 :         if (data->id_msgs == NULL) {
     312         [ #  # ]:          0 :                 if (checkcode_len != 0) {
     313                 :          0 :                         wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer "
     314                 :            :                                    "indicates that AKA/Identity messages were "
     315                 :            :                                    "used, but they were not");
     316                 :          0 :                         return -1;
     317                 :            :                 }
     318                 :          0 :                 return 0;
     319                 :            :         }
     320                 :            : 
     321         [ +  + ]:          4 :         hash_len = data->eap_method == EAP_TYPE_AKA_PRIME ?
     322                 :            :                 EAP_AKA_PRIME_CHECKCODE_LEN : EAP_AKA_CHECKCODE_LEN;
     323                 :            : 
     324         [ -  + ]:          4 :         if (checkcode_len != hash_len) {
     325                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Checkcode from peer indicates "
     326                 :            :                            "that AKA/Identity message were not used, but they "
     327                 :            :                            "were");
     328                 :          0 :                 return -1;
     329                 :            :         }
     330                 :            : 
     331                 :            :         /* Checkcode is SHA1 hash over all EAP-AKA/Identity packets. */
     332                 :          4 :         addr = wpabuf_head(data->id_msgs);
     333                 :          4 :         len = wpabuf_len(data->id_msgs);
     334         [ +  + ]:          4 :         if (data->eap_method == EAP_TYPE_AKA_PRIME)
     335                 :          2 :                 sha256_vector(1, &addr, &len, hash);
     336                 :            :         else
     337                 :          2 :                 sha1_vector(1, &addr, &len, hash);
     338                 :            : 
     339         [ -  + ]:          4 :         if (os_memcmp(hash, checkcode, hash_len) != 0) {
     340                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
     341                 :          0 :                 return -1;
     342                 :            :         }
     343                 :            : 
     344                 :          4 :         return 0;
     345                 :            : }
     346                 :            : 
     347                 :            : 
     348                 :          6 : static struct wpabuf * eap_aka_build_identity(struct eap_sm *sm,
     349                 :            :                                               struct eap_aka_data *data, u8 id)
     350                 :            : {
     351                 :            :         struct eap_sim_msg *msg;
     352                 :            :         struct wpabuf *buf;
     353                 :            : 
     354                 :          6 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity");
     355                 :          6 :         msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
     356                 :            :                                EAP_AKA_SUBTYPE_IDENTITY);
     357                 :          6 :         data->identity_round++;
     358         [ +  - ]:          6 :         if (data->identity_round == 1) {
     359                 :            :                 /*
     360                 :            :                  * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is
     361                 :            :                  * ignored and the AKA/Identity is used to request the
     362                 :            :                  * identity.
     363                 :            :                  */
     364                 :          6 :                 wpa_printf(MSG_DEBUG, "   AT_ANY_ID_REQ");
     365                 :          6 :                 eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0);
     366         [ #  # ]:          0 :         } else if (data->identity_round > 3) {
     367                 :            :                 /* Cannot use more than three rounds of Identity messages */
     368                 :          0 :                 eap_sim_msg_free(msg);
     369                 :          0 :                 return NULL;
     370 [ #  # ][ #  # ]:          0 :         } else if (sm->identity && sm->identity_len > 0 &&
                 [ #  # ]
     371         [ #  # ]:          0 :                    (sm->identity[0] == EAP_AKA_REAUTH_ID_PREFIX ||
     372                 :          0 :                     sm->identity[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX)) {
     373                 :            :                 /* Reauth id may have expired - try fullauth */
     374                 :          0 :                 wpa_printf(MSG_DEBUG, "   AT_FULLAUTH_ID_REQ");
     375                 :          0 :                 eap_sim_msg_add(msg, EAP_SIM_AT_FULLAUTH_ID_REQ, 0, NULL, 0);
     376                 :            :         } else {
     377                 :          0 :                 wpa_printf(MSG_DEBUG, "   AT_PERMANENT_ID_REQ");
     378                 :          0 :                 eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
     379                 :            :         }
     380                 :          6 :         buf = eap_sim_msg_finish(msg, NULL, NULL, 0);
     381         [ -  + ]:          6 :         if (eap_aka_add_id_msg(data, buf) < 0) {
     382                 :          0 :                 wpabuf_free(buf);
     383                 :          0 :                 return NULL;
     384                 :            :         }
     385                 :          6 :         data->pending_id = id;
     386                 :          6 :         return buf;
     387                 :            : }
     388                 :            : 
     389                 :            : 
     390                 :          9 : static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data,
     391                 :            :                               struct eap_sim_msg *msg, u16 counter,
     392                 :            :                               const u8 *nonce_s)
     393                 :            : {
     394                 :          9 :         os_free(data->next_pseudonym);
     395         [ +  + ]:          9 :         if (nonce_s == NULL) {
     396                 :          7 :                 data->next_pseudonym =
     397         [ +  + ]:          7 :                         eap_sim_db_get_next_pseudonym(
     398                 :            :                                 sm->eap_sim_db_priv,
     399                 :          7 :                                 data->eap_method == EAP_TYPE_AKA_PRIME ?
     400                 :            :                                 EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA);
     401                 :            :         } else {
     402                 :            :                 /* Do not update pseudonym during re-authentication */
     403                 :          2 :                 data->next_pseudonym = NULL;
     404                 :            :         }
     405                 :          9 :         os_free(data->next_reauth_id);
     406         [ +  - ]:          9 :         if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) {
     407                 :          9 :                 data->next_reauth_id =
     408         [ +  + ]:          9 :                         eap_sim_db_get_next_reauth_id(
     409                 :            :                                 sm->eap_sim_db_priv,
     410                 :          9 :                                 data->eap_method == EAP_TYPE_AKA_PRIME ?
     411                 :            :                                 EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA);
     412                 :            :         } else {
     413                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication "
     414                 :            :                            "count exceeded - force full authentication");
     415                 :          0 :                 data->next_reauth_id = NULL;
     416                 :            :         }
     417                 :            : 
     418 [ +  + ][ -  + ]:          9 :         if (data->next_pseudonym == NULL && data->next_reauth_id == NULL &&
                 [ #  # ]
     419         [ #  # ]:          0 :             counter == 0 && nonce_s == NULL)
     420                 :          0 :                 return 0;
     421                 :            : 
     422                 :          9 :         wpa_printf(MSG_DEBUG, "   AT_IV");
     423                 :          9 :         wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
     424                 :          9 :         eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
     425                 :            : 
     426         [ +  + ]:          9 :         if (counter > 0) {
     427                 :          2 :                 wpa_printf(MSG_DEBUG, "   *AT_COUNTER (%u)", counter);
     428                 :          2 :                 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
     429                 :            :         }
     430                 :            : 
     431         [ +  + ]:          9 :         if (nonce_s) {
     432                 :          2 :                 wpa_printf(MSG_DEBUG, "   *AT_NONCE_S");
     433                 :          2 :                 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s,
     434                 :            :                                 EAP_SIM_NONCE_S_LEN);
     435                 :            :         }
     436                 :            : 
     437         [ +  + ]:          9 :         if (data->next_pseudonym) {
     438                 :          7 :                 wpa_printf(MSG_DEBUG, "   *AT_NEXT_PSEUDONYM (%s)",
     439                 :            :                            data->next_pseudonym);
     440                 :          7 :                 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM,
     441                 :          7 :                                 os_strlen(data->next_pseudonym),
     442                 :          7 :                                 (u8 *) data->next_pseudonym,
     443                 :          7 :                                 os_strlen(data->next_pseudonym));
     444                 :            :         }
     445                 :            : 
     446         [ +  - ]:          9 :         if (data->next_reauth_id) {
     447                 :          9 :                 wpa_printf(MSG_DEBUG, "   *AT_NEXT_REAUTH_ID (%s)",
     448                 :            :                            data->next_reauth_id);
     449                 :          9 :                 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID,
     450                 :          9 :                                 os_strlen(data->next_reauth_id),
     451                 :          9 :                                 (u8 *) data->next_reauth_id,
     452                 :          9 :                                 os_strlen(data->next_reauth_id));
     453                 :            :         }
     454                 :            : 
     455         [ -  + ]:          9 :         if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
     456                 :          0 :                 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt "
     457                 :            :                            "AT_ENCR_DATA");
     458                 :          0 :                 return -1;
     459                 :            :         }
     460                 :            : 
     461                 :          9 :         return 0;
     462                 :            : }
     463                 :            : 
     464                 :            : 
     465                 :          7 : static struct wpabuf * eap_aka_build_challenge(struct eap_sm *sm,
     466                 :            :                                                struct eap_aka_data *data,
     467                 :            :                                                u8 id)
     468                 :            : {
     469                 :            :         struct eap_sim_msg *msg;
     470                 :            : 
     471                 :          7 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge");
     472                 :          7 :         msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
     473                 :            :                                EAP_AKA_SUBTYPE_CHALLENGE);
     474                 :          7 :         wpa_printf(MSG_DEBUG, "   AT_RAND");
     475                 :          7 :         eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, data->rand, EAP_AKA_RAND_LEN);
     476                 :          7 :         wpa_printf(MSG_DEBUG, "   AT_AUTN");
     477                 :          7 :         eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN);
     478         [ +  + ]:          7 :         if (data->eap_method == EAP_TYPE_AKA_PRIME) {
     479         [ -  + ]:          3 :                 if (data->kdf) {
     480                 :            :                         /* Add the selected KDF into the beginning */
     481                 :          0 :                         wpa_printf(MSG_DEBUG, "   AT_KDF");
     482                 :          0 :                         eap_sim_msg_add(msg, EAP_SIM_AT_KDF, data->kdf,
     483                 :            :                                         NULL, 0);
     484                 :            :                 }
     485                 :          3 :                 wpa_printf(MSG_DEBUG, "   AT_KDF");
     486                 :          3 :                 eap_sim_msg_add(msg, EAP_SIM_AT_KDF, EAP_AKA_PRIME_KDF,
     487                 :            :                                 NULL, 0);
     488                 :          3 :                 wpa_printf(MSG_DEBUG, "   AT_KDF_INPUT");
     489                 :          3 :                 eap_sim_msg_add(msg, EAP_SIM_AT_KDF_INPUT,
     490                 :          3 :                                 data->network_name_len,
     491                 :          3 :                                 data->network_name, data->network_name_len);
     492                 :            :         }
     493                 :            : 
     494         [ -  + ]:          7 :         if (eap_aka_build_encr(sm, data, msg, 0, NULL)) {
     495                 :          0 :                 eap_sim_msg_free(msg);
     496                 :          0 :                 return NULL;
     497                 :            :         }
     498                 :            : 
     499                 :          7 :         eap_aka_add_checkcode(data, msg);
     500                 :            : 
     501         [ +  - ]:          7 :         if (sm->eap_sim_aka_result_ind) {
     502                 :          7 :                 wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
     503                 :          7 :                 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
     504                 :            :         }
     505                 :            : 
     506                 :            : #ifdef EAP_SERVER_AKA_PRIME
     507         [ +  + ]:          7 :         if (data->eap_method == EAP_TYPE_AKA) {
     508                 :          4 :                 u16 flags = 0;
     509                 :            :                 int i;
     510                 :          4 :                 int aka_prime_preferred = 0;
     511                 :            : 
     512                 :          4 :                 i = 0;
     513 [ +  - ][ +  - ]:          4 :                 while (sm->user && i < EAP_MAX_METHODS &&
                 [ -  + ]
     514         [ +  - ]:          4 :                        (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
     515                 :          4 :                         sm->user->methods[i].method != EAP_TYPE_NONE)) {
     516         [ +  - ]:          4 :                         if (sm->user->methods[i].vendor == EAP_VENDOR_IETF) {
     517         [ +  - ]:          4 :                                 if (sm->user->methods[i].method ==
     518                 :            :                                     EAP_TYPE_AKA)
     519                 :          4 :                                         break;
     520         [ #  # ]:          0 :                                 if (sm->user->methods[i].method ==
     521                 :            :                                     EAP_TYPE_AKA_PRIME) {
     522                 :          0 :                                         aka_prime_preferred = 1;
     523                 :          0 :                                         break;
     524                 :            :                                 }
     525                 :            :                         }
     526                 :          0 :                         i++;
     527                 :            :                 }
     528                 :            : 
     529         [ -  + ]:          4 :                 if (aka_prime_preferred)
     530                 :          0 :                         flags |= EAP_AKA_BIDDING_FLAG_D;
     531                 :          4 :                 eap_sim_msg_add(msg, EAP_SIM_AT_BIDDING, flags, NULL, 0);
     532                 :            :         }
     533                 :            : #endif /* EAP_SERVER_AKA_PRIME */
     534                 :            : 
     535                 :          7 :         wpa_printf(MSG_DEBUG, "   AT_MAC");
     536                 :          7 :         eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
     537                 :          7 :         return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
     538                 :            : }
     539                 :            : 
     540                 :            : 
     541                 :          2 : static struct wpabuf * eap_aka_build_reauth(struct eap_sm *sm,
     542                 :            :                                             struct eap_aka_data *data, u8 id)
     543                 :            : {
     544                 :            :         struct eap_sim_msg *msg;
     545                 :            : 
     546                 :          2 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication");
     547                 :            : 
     548         [ -  + ]:          2 :         if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN))
     549                 :          0 :                 return NULL;
     550                 :          2 :         wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S",
     551                 :          2 :                         data->nonce_s, EAP_SIM_NONCE_S_LEN);
     552                 :            : 
     553         [ +  + ]:          2 :         if (data->eap_method == EAP_TYPE_AKA_PRIME) {
     554                 :          1 :                 eap_aka_prime_derive_keys_reauth(data->k_re, data->counter,
     555                 :          1 :                                                  sm->identity,
     556                 :            :                                                  sm->identity_len,
     557                 :          1 :                                                  data->nonce_s,
     558                 :          1 :                                                  data->msk, data->emsk);
     559                 :            :         } else {
     560                 :          1 :                 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
     561                 :          1 :                                     data->msk, data->emsk);
     562                 :          1 :                 eap_sim_derive_keys_reauth(data->counter, sm->identity,
     563                 :          1 :                                            sm->identity_len, data->nonce_s,
     564                 :          1 :                                            data->mk, data->msk, data->emsk);
     565                 :            :         }
     566                 :            : 
     567                 :          2 :         msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
     568                 :            :                                EAP_AKA_SUBTYPE_REAUTHENTICATION);
     569                 :            : 
     570         [ -  + ]:          2 :         if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) {
     571                 :          0 :                 eap_sim_msg_free(msg);
     572                 :          0 :                 return NULL;
     573                 :            :         }
     574                 :            : 
     575                 :          2 :         eap_aka_add_checkcode(data, msg);
     576                 :            : 
     577         [ +  - ]:          2 :         if (sm->eap_sim_aka_result_ind) {
     578                 :          2 :                 wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
     579                 :          2 :                 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
     580                 :            :         }
     581                 :            : 
     582                 :          2 :         wpa_printf(MSG_DEBUG, "   AT_MAC");
     583                 :          2 :         eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
     584                 :          2 :         return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
     585                 :            : }
     586                 :            : 
     587                 :            : 
     588                 :          0 : static struct wpabuf * eap_aka_build_notification(struct eap_sm *sm,
     589                 :            :                                                   struct eap_aka_data *data,
     590                 :            :                                                   u8 id)
     591                 :            : {
     592                 :            :         struct eap_sim_msg *msg;
     593                 :            : 
     594                 :          0 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification");
     595                 :          0 :         msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
     596                 :            :                                EAP_AKA_SUBTYPE_NOTIFICATION);
     597                 :          0 :         wpa_printf(MSG_DEBUG, "   AT_NOTIFICATION (%d)", data->notification);
     598                 :          0 :         eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification,
     599                 :            :                         NULL, 0);
     600         [ #  # ]:          0 :         if (data->use_result_ind) {
     601         [ #  # ]:          0 :                 if (data->reauth) {
     602                 :          0 :                         wpa_printf(MSG_DEBUG, "   AT_IV");
     603                 :          0 :                         wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
     604                 :          0 :                         eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
     605                 :            :                                                    EAP_SIM_AT_ENCR_DATA);
     606                 :          0 :                         wpa_printf(MSG_DEBUG, "   *AT_COUNTER (%u)",
     607                 :          0 :                                    data->counter);
     608                 :          0 :                         eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
     609                 :            :                                         NULL, 0);
     610                 :            : 
     611         [ #  # ]:          0 :                         if (eap_sim_msg_add_encr_end(msg, data->k_encr,
     612                 :            :                                                      EAP_SIM_AT_PADDING)) {
     613                 :          0 :                                 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to "
     614                 :            :                                            "encrypt AT_ENCR_DATA");
     615                 :          0 :                                 eap_sim_msg_free(msg);
     616                 :          0 :                                 return NULL;
     617                 :            :                         }
     618                 :            :                 }
     619                 :            : 
     620                 :          0 :                 wpa_printf(MSG_DEBUG, "   AT_MAC");
     621                 :          0 :                 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
     622                 :            :         }
     623                 :          0 :         return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
     624                 :            : }
     625                 :            : 
     626                 :            : 
     627                 :         15 : static struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id)
     628                 :            : {
     629                 :         15 :         struct eap_aka_data *data = priv;
     630                 :            : 
     631                 :         15 :         data->auts_reported = 0;
     632   [ +  +  +  -  :         15 :         switch (data->state) {
                      - ]
     633                 :            :         case IDENTITY:
     634                 :          6 :                 return eap_aka_build_identity(sm, data, id);
     635                 :            :         case CHALLENGE:
     636                 :          7 :                 return eap_aka_build_challenge(sm, data, id);
     637                 :            :         case REAUTH:
     638                 :          2 :                 return eap_aka_build_reauth(sm, data, id);
     639                 :            :         case NOTIFICATION:
     640                 :          0 :                 return eap_aka_build_notification(sm, data, id);
     641                 :            :         default:
     642                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
     643                 :          0 :                            "buildReq", data->state);
     644                 :          0 :                 break;
     645                 :            :         }
     646                 :         15 :         return NULL;
     647                 :            : }
     648                 :            : 
     649                 :            : 
     650                 :         15 : static Boolean eap_aka_check(struct eap_sm *sm, void *priv,
     651                 :            :                              struct wpabuf *respData)
     652                 :            : {
     653                 :         15 :         struct eap_aka_data *data = priv;
     654                 :            :         const u8 *pos;
     655                 :            :         size_t len;
     656                 :            : 
     657                 :         15 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
     658                 :            :                                &len);
     659 [ -  + ][ +  - ]:         15 :         if (pos == NULL || len < 3) {
     660                 :          0 :                 wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame");
     661                 :          0 :                 return TRUE;
     662                 :            :         }
     663                 :            : 
     664                 :         15 :         return FALSE;
     665                 :            : }
     666                 :            : 
     667                 :            : 
     668                 :         22 : static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype)
     669                 :            : {
     670 [ +  - ][ +  + ]:         22 :         if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR ||
     671                 :            :             subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT)
     672                 :          2 :                 return FALSE;
     673                 :            : 
     674   [ +  +  +  -  :         20 :         switch (data->state) {
                      - ]
     675                 :            :         case IDENTITY:
     676         [ -  + ]:         12 :                 if (subtype != EAP_AKA_SUBTYPE_IDENTITY) {
     677                 :          0 :                         wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
     678                 :            :                                    "subtype %d", subtype);
     679                 :          0 :                         return TRUE;
     680                 :            :                 }
     681                 :         12 :                 break;
     682                 :            :         case CHALLENGE:
     683 [ +  + ][ -  + ]:          6 :                 if (subtype != EAP_AKA_SUBTYPE_CHALLENGE &&
     684                 :            :                     subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
     685                 :          0 :                         wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
     686                 :            :                                    "subtype %d", subtype);
     687                 :          0 :                         return TRUE;
     688                 :            :                 }
     689                 :          6 :                 break;
     690                 :            :         case REAUTH:
     691         [ -  + ]:          2 :                 if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) {
     692                 :          0 :                         wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
     693                 :            :                                    "subtype %d", subtype);
     694                 :          0 :                         return TRUE;
     695                 :            :                 }
     696                 :          2 :                 break;
     697                 :            :         case NOTIFICATION:
     698         [ #  # ]:          0 :                 if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) {
     699                 :          0 :                         wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response "
     700                 :            :                                    "subtype %d", subtype);
     701                 :          0 :                         return TRUE;
     702                 :            :                 }
     703                 :          0 :                 break;
     704                 :            :         default:
     705                 :          0 :                 wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for "
     706                 :          0 :                            "processing a response", data->state);
     707                 :          0 :                 return TRUE;
     708                 :            :         }
     709                 :            : 
     710                 :         22 :         return FALSE;
     711                 :            : }
     712                 :            : 
     713                 :            : 
     714                 :         12 : static void eap_aka_determine_identity(struct eap_sm *sm,
     715                 :            :                                        struct eap_aka_data *data)
     716                 :            : {
     717                 :            :         char *username;
     718                 :            : 
     719                 :         12 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity",
     720                 :         12 :                           sm->identity, sm->identity_len);
     721                 :            : 
     722                 :         12 :         username = sim_get_username(sm->identity, sm->identity_len);
     723         [ -  + ]:         12 :         if (username == NULL) {
     724                 :          0 :                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
     725                 :          0 :                 eap_aka_state(data, NOTIFICATION);
     726                 :          0 :                 return;
     727                 :            :         }
     728                 :            : 
     729         [ -  + ]:         12 :         if (eap_aka_check_identity_reauth(sm, data, username) > 0) {
     730                 :          0 :                 os_free(username);
     731                 :          0 :                 return;
     732                 :            :         }
     733                 :            : 
     734 [ +  + ][ +  - ]:         12 :         if (((data->eap_method == EAP_TYPE_AKA_PRIME &&
     735         [ +  + ]:         12 :               username[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX) ||
     736         [ -  + ]:          6 :              (data->eap_method == EAP_TYPE_AKA &&
     737         [ #  # ]:          0 :               username[0] == EAP_AKA_REAUTH_ID_PREFIX)) &&
     738                 :          0 :             data->identity_round == 1) {
     739                 :            :                 /* Remain in IDENTITY state for another round to request full
     740                 :            :                  * auth identity since we did not recognize reauth id */
     741                 :          0 :                 os_free(username);
     742                 :          0 :                 return;
     743                 :            :         }
     744                 :            : 
     745 [ +  + ][ +  - ]:         12 :         if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
     746         [ +  + ]:         12 :              username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
     747         [ -  + ]:          6 :             (data->eap_method == EAP_TYPE_AKA &&
     748                 :          0 :              username[0] == EAP_AKA_PSEUDONYM_PREFIX)) {
     749                 :            :                 const char *permanent;
     750                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
     751                 :            :                            username);
     752                 :          0 :                 permanent = eap_sim_db_get_permanent(
     753                 :            :                         sm->eap_sim_db_priv, username);
     754                 :          0 :                 os_free(username);
     755         [ #  # ]:          0 :                 if (permanent == NULL) {
     756                 :          0 :                         wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
     757                 :            :                                    "identity - request permanent identity");
     758                 :            :                         /* Remain in IDENTITY state for another round */
     759                 :          0 :                         return;
     760                 :            :                 }
     761                 :          0 :                 os_strlcpy(data->permanent, permanent,
     762                 :            :                            sizeof(data->permanent));
     763 [ +  + ][ -  + ]:         12 :         } else if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
     764         [ +  - ]:          6 :                     username[0] == EAP_AKA_PRIME_PERMANENT_PREFIX) ||
     765         [ +  - ]:          6 :                    (data->eap_method == EAP_TYPE_AKA &&
     766                 :          6 :                     username[0] == EAP_AKA_PERMANENT_PREFIX)) {
     767                 :         12 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent username '%s'",
     768                 :            :                            username);
     769                 :         12 :                 os_strlcpy(data->permanent, username, sizeof(data->permanent));
     770                 :         12 :                 os_free(username);
     771                 :            :         } else {
     772                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized username '%s'",
     773                 :            :                            username);
     774                 :          0 :                 os_free(username);
     775                 :          0 :                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
     776                 :          0 :                 eap_aka_state(data, NOTIFICATION);
     777                 :          0 :                 return;
     778                 :            :         }
     779                 :            : 
     780                 :         12 :         eap_aka_fullauth(sm, data);
     781                 :            : }
     782                 :            : 
     783                 :            : 
     784                 :         14 : static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data)
     785                 :            : {
     786                 :            :         size_t identity_len;
     787                 :            :         int res;
     788                 :            : 
     789                 :         14 :         res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, data->permanent,
     790                 :         14 :                                       data->rand, data->autn, data->ik,
     791                 :         14 :                                       data->ck, data->res, &data->res_len, sm);
     792         [ +  + ]:         14 :         if (res == EAP_SIM_DB_PENDING) {
     793                 :          7 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
     794                 :            :                            "not yet available - pending request");
     795                 :          7 :                 sm->method_pending = METHOD_PENDING_WAIT;
     796                 :          7 :                 return;
     797                 :            :         }
     798                 :            : 
     799                 :            : #ifdef EAP_SERVER_AKA_PRIME
     800         [ +  + ]:          7 :         if (data->eap_method == EAP_TYPE_AKA_PRIME) {
     801                 :            :                 /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the
     802                 :            :                  * needed 6-octet SQN ^AK for CK',IK' derivation */
     803                 :          3 :                 eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik,
     804                 :          3 :                                                  data->autn,
     805                 :          3 :                                                  data->network_name,
     806                 :            :                                                  data->network_name_len);
     807                 :            :         }
     808                 :            : #endif /* EAP_SERVER_AKA_PRIME */
     809                 :            : 
     810                 :          7 :         data->reauth = NULL;
     811                 :          7 :         data->counter = 0; /* reset re-auth counter since this is full auth */
     812                 :            : 
     813         [ -  + ]:          7 :         if (res != 0) {
     814                 :          0 :                 wpa_printf(MSG_INFO, "EAP-AKA: Failed to get AKA "
     815                 :            :                            "authentication data for the peer");
     816                 :          0 :                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
     817                 :          0 :                 eap_aka_state(data, NOTIFICATION);
     818                 :          0 :                 return;
     819                 :            :         }
     820         [ -  + ]:          7 :         if (sm->method_pending == METHOD_PENDING_WAIT) {
     821                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
     822                 :            :                            "available - abort pending wait");
     823                 :          0 :                 sm->method_pending = METHOD_PENDING_NONE;
     824                 :            :         }
     825                 :            : 
     826                 :          7 :         identity_len = sm->identity_len;
     827 [ +  - ][ -  + ]:          7 :         while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') {
     828                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null "
     829                 :            :                            "character from identity");
     830                 :          0 :                 identity_len--;
     831                 :            :         }
     832                 :          7 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation",
     833                 :          7 :                           sm->identity, identity_len);
     834                 :            : 
     835         [ +  + ]:          7 :         if (data->eap_method == EAP_TYPE_AKA_PRIME) {
     836                 :          3 :                 eap_aka_prime_derive_keys(sm->identity, identity_len, data->ik,
     837                 :          3 :                                           data->ck, data->k_encr, data->k_aut,
     838                 :          3 :                                           data->k_re, data->msk, data->emsk);
     839                 :            :         } else {
     840                 :          4 :                 eap_aka_derive_mk(sm->identity, identity_len, data->ik,
     841                 :          4 :                                   data->ck, data->mk);
     842                 :          4 :                 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut,
     843                 :          4 :                                     data->msk, data->emsk);
     844                 :            :         }
     845                 :            : 
     846                 :         14 :         eap_aka_state(data, CHALLENGE);
     847                 :            : }
     848                 :            : 
     849                 :            : 
     850                 :         12 : static void eap_aka_process_identity(struct eap_sm *sm,
     851                 :            :                                      struct eap_aka_data *data,
     852                 :            :                                      struct wpabuf *respData,
     853                 :            :                                      struct eap_sim_attrs *attr)
     854                 :            : {
     855                 :            :         u8 *new_identity;
     856                 :            : 
     857                 :         12 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity");
     858                 :            : 
     859 [ +  - ][ -  + ]:         12 :         if (attr->mac || attr->iv || attr->encr_data) {
                 [ +  - ]
     860                 :          0 :                 wpa_printf(MSG_WARNING, "EAP-AKA: Unexpected attribute "
     861                 :            :                            "received in EAP-Response/AKA-Identity");
     862                 :          0 :                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
     863                 :          0 :                 eap_aka_state(data, NOTIFICATION);
     864                 :          0 :                 return;
     865                 :            :         }
     866                 :            : 
     867                 :            :         /*
     868                 :            :          * We always request identity with AKA/Identity, so the peer is
     869                 :            :          * required to have replied with one.
     870                 :            :          */
     871 [ +  - ][ -  + ]:         12 :         if (!attr->identity || attr->identity_len == 0) {
     872                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Peer did not provide any "
     873                 :            :                            "identity");
     874                 :          0 :                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
     875                 :          0 :                 eap_aka_state(data, NOTIFICATION);
     876                 :          0 :                 return;
     877                 :            :         }
     878                 :            : 
     879                 :         12 :         new_identity = os_malloc(attr->identity_len);
     880         [ -  + ]:         12 :         if (new_identity == NULL) {
     881                 :          0 :                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
     882                 :          0 :                 eap_aka_state(data, NOTIFICATION);
     883                 :          0 :                 return;
     884                 :            :         }
     885                 :         12 :         os_free(sm->identity);
     886                 :         12 :         sm->identity = new_identity;
     887                 :         12 :         os_memcpy(sm->identity, attr->identity, attr->identity_len);
     888                 :         12 :         sm->identity_len = attr->identity_len;
     889                 :            : 
     890                 :         12 :         eap_aka_determine_identity(sm, data);
     891         [ +  + ]:         12 :         if (eap_get_id(respData) == data->pending_id) {
     892                 :          6 :                 data->pending_id = -1;
     893                 :         12 :                 eap_aka_add_id_msg(data, respData);
     894                 :            :         }
     895                 :            : }
     896                 :            : 
     897                 :            : 
     898                 :          6 : static int eap_aka_verify_mac(struct eap_aka_data *data,
     899                 :            :                               const struct wpabuf *req,
     900                 :            :                               const u8 *mac, const u8 *extra,
     901                 :            :                               size_t extra_len)
     902                 :            : {
     903         [ +  + ]:          6 :         if (data->eap_method == EAP_TYPE_AKA_PRIME)
     904                 :          3 :                 return eap_sim_verify_mac_sha256(data->k_aut, req, mac, extra,
     905                 :            :                                                  extra_len);
     906                 :          6 :         return eap_sim_verify_mac(data->k_aut, req, mac, extra, extra_len);
     907                 :            : }
     908                 :            : 
     909                 :            : 
     910                 :          4 : static void eap_aka_process_challenge(struct eap_sm *sm,
     911                 :            :                                       struct eap_aka_data *data,
     912                 :            :                                       struct wpabuf *respData,
     913                 :            :                                       struct eap_sim_attrs *attr)
     914                 :            : {
     915                 :          4 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge");
     916                 :            : 
     917                 :            : #ifdef EAP_SERVER_AKA_PRIME
     918                 :            : #if 0
     919                 :            :         /* KDF negotiation; to be enabled only after more than one KDF is
     920                 :            :          * supported */
     921                 :            :         if (data->eap_method == EAP_TYPE_AKA_PRIME &&
     922                 :            :             attr->kdf_count == 1 && attr->mac == NULL) {
     923                 :            :                 if (attr->kdf[0] != EAP_AKA_PRIME_KDF) {
     924                 :            :                         wpa_printf(MSG_WARNING, "EAP-AKA': Peer selected "
     925                 :            :                                    "unknown KDF");
     926                 :            :                         data->notification =
     927                 :            :                                 EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
     928                 :            :                         eap_aka_state(data, NOTIFICATION);
     929                 :            :                         return;
     930                 :            :                 }
     931                 :            : 
     932                 :            :                 data->kdf = attr->kdf[0];
     933                 :            : 
     934                 :            :                 /* Allow negotiation to continue with the selected KDF by
     935                 :            :                  * sending another Challenge message */
     936                 :            :                 wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf);
     937                 :            :                 return;
     938                 :            :         }
     939                 :            : #endif
     940                 :            : #endif /* EAP_SERVER_AKA_PRIME */
     941                 :            : 
     942   [ +  -  -  + ]:          8 :         if (attr->checkcode &&
     943                 :          4 :             eap_aka_verify_checkcode(data, attr->checkcode,
     944                 :            :                                      attr->checkcode_len)) {
     945                 :          0 :                 wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the "
     946                 :            :                            "message");
     947                 :          0 :                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
     948                 :          0 :                 eap_aka_state(data, NOTIFICATION);
     949                 :          0 :                 return;
     950                 :            :         }
     951   [ +  -  -  + ]:          8 :         if (attr->mac == NULL ||
     952                 :          4 :             eap_aka_verify_mac(data, respData, attr->mac, NULL, 0)) {
     953                 :          0 :                 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
     954                 :            :                            "did not include valid AT_MAC");
     955                 :          0 :                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
     956                 :          0 :                 eap_aka_state(data, NOTIFICATION);
     957                 :          0 :                 return;
     958                 :            :         }
     959                 :            : 
     960                 :            :         /*
     961                 :            :          * AT_RES is padded, so verify that there is enough room for RES and
     962                 :            :          * that the RES length in bits matches with the expected RES.
     963                 :            :          */
     964 [ +  - ][ +  - ]:          4 :         if (attr->res == NULL || attr->res_len < data->res_len ||
                 [ +  - ]
     965         [ -  + ]:          4 :             attr->res_len_bits != data->res_len * 8 ||
     966                 :          4 :             os_memcmp(attr->res, data->res, data->res_len) != 0) {
     967                 :          0 :                 wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not "
     968                 :            :                            "include valid AT_RES (attr len=%lu, res len=%lu "
     969                 :            :                            "bits, expected %lu bits)",
     970                 :            :                            (unsigned long) attr->res_len,
     971                 :            :                            (unsigned long) attr->res_len_bits,
     972                 :          0 :                            (unsigned long) data->res_len * 8);
     973                 :          0 :                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
     974                 :          0 :                 eap_aka_state(data, NOTIFICATION);
     975                 :          0 :                 return;
     976                 :            :         }
     977                 :            : 
     978                 :          4 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Challenge response includes the "
     979                 :            :                    "correct AT_MAC");
     980 [ -  + ][ +  - ]:          4 :         if (sm->eap_sim_aka_result_ind && attr->result_ind) {
     981                 :          0 :                 data->use_result_ind = 1;
     982                 :          0 :                 data->notification = EAP_SIM_SUCCESS;
     983                 :          0 :                 eap_aka_state(data, NOTIFICATION);
     984                 :            :         } else
     985                 :          4 :                 eap_aka_state(data, SUCCESS);
     986                 :            : 
     987         [ +  - ]:          4 :         if (data->next_pseudonym) {
     988                 :          4 :                 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, data->permanent,
     989                 :            :                                          data->next_pseudonym);
     990                 :          4 :                 data->next_pseudonym = NULL;
     991                 :            :         }
     992         [ +  - ]:          4 :         if (data->next_reauth_id) {
     993         [ +  + ]:          4 :                 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
     994                 :            : #ifdef EAP_SERVER_AKA_PRIME
     995                 :          2 :                         eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
     996                 :          2 :                                                     data->permanent,
     997                 :            :                                                     data->next_reauth_id,
     998                 :          2 :                                                     data->counter + 1,
     999                 :          2 :                                                     data->k_encr, data->k_aut,
    1000                 :          2 :                                                     data->k_re);
    1001                 :            : #endif /* EAP_SERVER_AKA_PRIME */
    1002                 :            :                 } else {
    1003                 :          2 :                         eap_sim_db_add_reauth(sm->eap_sim_db_priv,
    1004                 :          2 :                                               data->permanent,
    1005                 :            :                                               data->next_reauth_id,
    1006                 :          2 :                                               data->counter + 1,
    1007                 :          2 :                                               data->mk);
    1008                 :            :                 }
    1009                 :          4 :                 data->next_reauth_id = NULL;
    1010                 :            :         }
    1011                 :            : }
    1012                 :            : 
    1013                 :            : 
    1014                 :          2 : static void eap_aka_process_sync_failure(struct eap_sm *sm,
    1015                 :            :                                          struct eap_aka_data *data,
    1016                 :            :                                          struct wpabuf *respData,
    1017                 :            :                                          struct eap_sim_attrs *attr)
    1018                 :            : {
    1019                 :          2 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Synchronization-Failure");
    1020                 :            : 
    1021         [ -  + ]:          2 :         if (attr->auts == NULL) {
    1022                 :          0 :                 wpa_printf(MSG_WARNING, "EAP-AKA: Synchronization-Failure "
    1023                 :            :                            "message did not include valid AT_AUTS");
    1024                 :          0 :                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    1025                 :          0 :                 eap_aka_state(data, NOTIFICATION);
    1026                 :          0 :                 return;
    1027                 :            :         }
    1028                 :            : 
    1029                 :            :         /* Avoid re-reporting AUTS when processing pending EAP packet by
    1030                 :            :          * maintaining a local flag stating whether this AUTS has already been
    1031                 :            :          * reported. */
    1032   [ +  +  -  + ]:          3 :         if (!data->auts_reported &&
    1033                 :          1 :             eap_sim_db_resynchronize(sm->eap_sim_db_priv, data->permanent,
    1034                 :          1 :                                      attr->auts, data->rand)) {
    1035                 :          0 :                 wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed");
    1036                 :          0 :                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    1037                 :          0 :                 eap_aka_state(data, NOTIFICATION);
    1038                 :          0 :                 return;
    1039                 :            :         }
    1040                 :          2 :         data->auts_reported = 1;
    1041                 :            : 
    1042                 :            :         /* Remain in CHALLENGE state to re-try after resynchronization */
    1043                 :          2 :         eap_aka_fullauth(sm, data);
    1044                 :            : }
    1045                 :            : 
    1046                 :            : 
    1047                 :          2 : static void eap_aka_process_reauth(struct eap_sm *sm,
    1048                 :            :                                    struct eap_aka_data *data,
    1049                 :            :                                    struct wpabuf *respData,
    1050                 :            :                                    struct eap_sim_attrs *attr)
    1051                 :            : {
    1052                 :            :         struct eap_sim_attrs eattr;
    1053                 :          2 :         u8 *decrypted = NULL;
    1054                 :            : 
    1055                 :          2 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication");
    1056                 :            : 
    1057   [ +  -  -  + ]:          4 :         if (attr->mac == NULL ||
    1058                 :          2 :             eap_aka_verify_mac(data, respData, attr->mac, data->nonce_s,
    1059                 :            :                                EAP_SIM_NONCE_S_LEN)) {
    1060                 :          0 :                 wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
    1061                 :            :                            "did not include valid AT_MAC");
    1062                 :          0 :                 goto fail;
    1063                 :            :         }
    1064                 :            : 
    1065 [ +  - ][ -  + ]:          2 :         if (attr->encr_data == NULL || attr->iv == NULL) {
    1066                 :          0 :                 wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
    1067                 :            :                            "message did not include encrypted data");
    1068                 :          0 :                 goto fail;
    1069                 :            :         }
    1070                 :            : 
    1071                 :          2 :         decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
    1072                 :            :                                        attr->encr_data_len, attr->iv, &eattr,
    1073                 :            :                                        0);
    1074         [ -  + ]:          2 :         if (decrypted == NULL) {
    1075                 :          0 :                 wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
    1076                 :            :                            "data from reauthentication message");
    1077                 :          0 :                 goto fail;
    1078                 :            :         }
    1079                 :            : 
    1080         [ -  + ]:          2 :         if (eattr.counter != data->counter) {
    1081                 :          0 :                 wpa_printf(MSG_WARNING, "EAP-AKA: Re-authentication message "
    1082                 :            :                            "used incorrect counter %u, expected %u",
    1083                 :          0 :                            eattr.counter, data->counter);
    1084                 :          0 :                 goto fail;
    1085                 :            :         }
    1086                 :          2 :         os_free(decrypted);
    1087                 :          2 :         decrypted = NULL;
    1088                 :            : 
    1089                 :          2 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response includes "
    1090                 :            :                    "the correct AT_MAC");
    1091                 :            : 
    1092         [ -  + ]:          2 :         if (eattr.counter_too_small) {
    1093                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response "
    1094                 :            :                            "included AT_COUNTER_TOO_SMALL - starting full "
    1095                 :            :                            "authentication");
    1096                 :          0 :                 eap_aka_fullauth(sm, data);
    1097                 :          0 :                 return;
    1098                 :            :         }
    1099                 :            : 
    1100 [ +  - ][ -  + ]:          2 :         if (sm->eap_sim_aka_result_ind && attr->result_ind) {
    1101                 :          0 :                 data->use_result_ind = 1;
    1102                 :          0 :                 data->notification = EAP_SIM_SUCCESS;
    1103                 :          0 :                 eap_aka_state(data, NOTIFICATION);
    1104                 :            :         } else
    1105                 :          2 :                 eap_aka_state(data, SUCCESS);
    1106                 :            : 
    1107         [ +  - ]:          2 :         if (data->next_reauth_id) {
    1108         [ +  + ]:          2 :                 if (data->eap_method == EAP_TYPE_AKA_PRIME) {
    1109                 :            : #ifdef EAP_SERVER_AKA_PRIME
    1110                 :          1 :                         eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
    1111                 :          1 :                                                     data->permanent,
    1112                 :            :                                                     data->next_reauth_id,
    1113                 :          1 :                                                     data->counter + 1,
    1114                 :          1 :                                                     data->k_encr, data->k_aut,
    1115                 :          1 :                                                     data->k_re);
    1116                 :            : #endif /* EAP_SERVER_AKA_PRIME */
    1117                 :            :                 } else {
    1118                 :          1 :                         eap_sim_db_add_reauth(sm->eap_sim_db_priv,
    1119                 :          1 :                                               data->permanent,
    1120                 :            :                                               data->next_reauth_id,
    1121                 :          1 :                                               data->counter + 1,
    1122                 :          1 :                                               data->mk);
    1123                 :            :                 }
    1124                 :          2 :                 data->next_reauth_id = NULL;
    1125                 :            :         } else {
    1126                 :          0 :                 eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
    1127                 :          0 :                 data->reauth = NULL;
    1128                 :            :         }
    1129                 :            : 
    1130                 :          2 :         return;
    1131                 :            : 
    1132                 :            : fail:
    1133                 :          0 :         data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    1134                 :          0 :         eap_aka_state(data, NOTIFICATION);
    1135                 :          0 :         eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
    1136                 :          0 :         data->reauth = NULL;
    1137                 :          2 :         os_free(decrypted);
    1138                 :            : }
    1139                 :            : 
    1140                 :            : 
    1141                 :          0 : static void eap_aka_process_client_error(struct eap_sm *sm,
    1142                 :            :                                          struct eap_aka_data *data,
    1143                 :            :                                          struct wpabuf *respData,
    1144                 :            :                                          struct eap_sim_attrs *attr)
    1145                 :            : {
    1146                 :          0 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d",
    1147                 :            :                    attr->client_error_code);
    1148 [ #  # ][ #  # ]:          0 :         if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
    1149                 :          0 :                 eap_aka_state(data, SUCCESS);
    1150                 :            :         else
    1151                 :          0 :                 eap_aka_state(data, FAILURE);
    1152                 :          0 : }
    1153                 :            : 
    1154                 :            : 
    1155                 :          2 : static void eap_aka_process_authentication_reject(
    1156                 :            :         struct eap_sm *sm, struct eap_aka_data *data,
    1157                 :            :         struct wpabuf *respData, struct eap_sim_attrs *attr)
    1158                 :            : {
    1159                 :          2 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Client rejected authentication");
    1160                 :          2 :         eap_aka_state(data, FAILURE);
    1161                 :          2 : }
    1162                 :            : 
    1163                 :            : 
    1164                 :          0 : static void eap_aka_process_notification(struct eap_sm *sm,
    1165                 :            :                                          struct eap_aka_data *data,
    1166                 :            :                                          struct wpabuf *respData,
    1167                 :            :                                          struct eap_sim_attrs *attr)
    1168                 :            : {
    1169                 :          0 :         wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification");
    1170 [ #  # ][ #  # ]:          0 :         if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
    1171                 :          0 :                 eap_aka_state(data, SUCCESS);
    1172                 :            :         else
    1173                 :          0 :                 eap_aka_state(data, FAILURE);
    1174                 :          0 : }
    1175                 :            : 
    1176                 :            : 
    1177                 :         22 : static void eap_aka_process(struct eap_sm *sm, void *priv,
    1178                 :            :                             struct wpabuf *respData)
    1179                 :            : {
    1180                 :         22 :         struct eap_aka_data *data = priv;
    1181                 :            :         const u8 *pos, *end;
    1182                 :            :         u8 subtype;
    1183                 :            :         size_t len;
    1184                 :            :         struct eap_sim_attrs attr;
    1185                 :            : 
    1186                 :         22 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, respData,
    1187                 :            :                                &len);
    1188 [ -  + ][ +  - ]:         22 :         if (pos == NULL || len < 3)
    1189                 :          0 :                 return;
    1190                 :            : 
    1191                 :         22 :         end = pos + len;
    1192                 :         22 :         subtype = *pos;
    1193                 :         22 :         pos += 3;
    1194                 :            : 
    1195         [ -  + ]:         22 :         if (eap_aka_subtype_ok(data, subtype)) {
    1196                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized or unexpected "
    1197                 :            :                            "EAP-AKA Subtype in EAP Response");
    1198                 :          0 :                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    1199                 :          0 :                 eap_aka_state(data, NOTIFICATION);
    1200                 :          0 :                 return;
    1201                 :            :         }
    1202                 :            : 
    1203 [ +  + ][ -  + ]:         22 :         if (eap_sim_parse_attr(pos, end, &attr,
    1204                 :         22 :                                data->eap_method == EAP_TYPE_AKA_PRIME ? 2 : 1,
    1205                 :            :                                0)) {
    1206                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Failed to parse attributes");
    1207                 :          0 :                 data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
    1208                 :          0 :                 eap_aka_state(data, NOTIFICATION);
    1209                 :          0 :                 return;
    1210                 :            :         }
    1211                 :            : 
    1212         [ -  + ]:         22 :         if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR) {
    1213                 :          0 :                 eap_aka_process_client_error(sm, data, respData, &attr);
    1214                 :          0 :                 return;
    1215                 :            :         }
    1216                 :            : 
    1217         [ +  + ]:         22 :         if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) {
    1218                 :          2 :                 eap_aka_process_authentication_reject(sm, data, respData,
    1219                 :            :                                                       &attr);
    1220                 :          2 :                 return;
    1221                 :            :         }
    1222                 :            : 
    1223   [ +  +  +  -  :         20 :         switch (data->state) {
                      - ]
    1224                 :            :         case IDENTITY:
    1225                 :         12 :                 eap_aka_process_identity(sm, data, respData, &attr);
    1226                 :         12 :                 break;
    1227                 :            :         case CHALLENGE:
    1228         [ +  + ]:          6 :                 if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) {
    1229                 :          2 :                         eap_aka_process_sync_failure(sm, data, respData,
    1230                 :            :                                                      &attr);
    1231                 :            :                 } else {
    1232                 :          4 :                         eap_aka_process_challenge(sm, data, respData, &attr);
    1233                 :            :                 }
    1234                 :          6 :                 break;
    1235                 :            :         case REAUTH:
    1236                 :          2 :                 eap_aka_process_reauth(sm, data, respData, &attr);
    1237                 :          2 :                 break;
    1238                 :            :         case NOTIFICATION:
    1239                 :          0 :                 eap_aka_process_notification(sm, data, respData, &attr);
    1240                 :          0 :                 break;
    1241                 :            :         default:
    1242                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown state %d in "
    1243                 :          0 :                            "process", data->state);
    1244                 :         22 :                 break;
    1245                 :            :         }
    1246                 :            : }
    1247                 :            : 
    1248                 :            : 
    1249                 :         24 : static Boolean eap_aka_isDone(struct eap_sm *sm, void *priv)
    1250                 :            : {
    1251                 :         24 :         struct eap_aka_data *data = priv;
    1252 [ +  + ][ +  + ]:         24 :         return data->state == SUCCESS || data->state == FAILURE;
    1253                 :            : }
    1254                 :            : 
    1255                 :            : 
    1256                 :          8 : static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len)
    1257                 :            : {
    1258                 :          8 :         struct eap_aka_data *data = priv;
    1259                 :            :         u8 *key;
    1260                 :            : 
    1261         [ +  + ]:          8 :         if (data->state != SUCCESS)
    1262                 :          2 :                 return NULL;
    1263                 :            : 
    1264                 :          6 :         key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
    1265         [ -  + ]:          6 :         if (key == NULL)
    1266                 :          0 :                 return NULL;
    1267                 :          6 :         os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
    1268                 :          6 :         *len = EAP_SIM_KEYING_DATA_LEN;
    1269                 :          8 :         return key;
    1270                 :            : }
    1271                 :            : 
    1272                 :            : 
    1273                 :          0 : static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
    1274                 :            : {
    1275                 :          0 :         struct eap_aka_data *data = priv;
    1276                 :            :         u8 *key;
    1277                 :            : 
    1278         [ #  # ]:          0 :         if (data->state != SUCCESS)
    1279                 :          0 :                 return NULL;
    1280                 :            : 
    1281                 :          0 :         key = os_malloc(EAP_EMSK_LEN);
    1282         [ #  # ]:          0 :         if (key == NULL)
    1283                 :          0 :                 return NULL;
    1284                 :          0 :         os_memcpy(key, data->emsk, EAP_EMSK_LEN);
    1285                 :          0 :         *len = EAP_EMSK_LEN;
    1286                 :          0 :         return key;
    1287                 :            : }
    1288                 :            : 
    1289                 :            : 
    1290                 :         10 : static Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv)
    1291                 :            : {
    1292                 :         10 :         struct eap_aka_data *data = priv;
    1293                 :         10 :         return data->state == SUCCESS;
    1294                 :            : }
    1295                 :            : 
    1296                 :            : 
    1297                 :          2 : int eap_server_aka_register(void)
    1298                 :            : {
    1299                 :            :         struct eap_method *eap;
    1300                 :            :         int ret;
    1301                 :            : 
    1302                 :          2 :         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
    1303                 :            :                                       EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
    1304         [ -  + ]:          2 :         if (eap == NULL)
    1305                 :          0 :                 return -1;
    1306                 :            : 
    1307                 :          2 :         eap->init = eap_aka_init;
    1308                 :          2 :         eap->reset = eap_aka_reset;
    1309                 :          2 :         eap->buildReq = eap_aka_buildReq;
    1310                 :          2 :         eap->check = eap_aka_check;
    1311                 :          2 :         eap->process = eap_aka_process;
    1312                 :          2 :         eap->isDone = eap_aka_isDone;
    1313                 :          2 :         eap->getKey = eap_aka_getKey;
    1314                 :          2 :         eap->isSuccess = eap_aka_isSuccess;
    1315                 :          2 :         eap->get_emsk = eap_aka_get_emsk;
    1316                 :            : 
    1317                 :          2 :         ret = eap_server_method_register(eap);
    1318         [ -  + ]:          2 :         if (ret)
    1319                 :          0 :                 eap_server_method_free(eap);
    1320                 :          2 :         return ret;
    1321                 :            : }
    1322                 :            : 
    1323                 :            : 
    1324                 :            : #ifdef EAP_SERVER_AKA_PRIME
    1325                 :          2 : int eap_server_aka_prime_register(void)
    1326                 :            : {
    1327                 :            :         struct eap_method *eap;
    1328                 :            :         int ret;
    1329                 :            : 
    1330                 :          2 :         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
    1331                 :            :                                       EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME,
    1332                 :            :                                       "AKA'");
    1333         [ -  + ]:          2 :         if (eap == NULL)
    1334                 :          0 :                 return -1;
    1335                 :            : 
    1336                 :          2 :         eap->init = eap_aka_prime_init;
    1337                 :          2 :         eap->reset = eap_aka_reset;
    1338                 :          2 :         eap->buildReq = eap_aka_buildReq;
    1339                 :          2 :         eap->check = eap_aka_check;
    1340                 :          2 :         eap->process = eap_aka_process;
    1341                 :          2 :         eap->isDone = eap_aka_isDone;
    1342                 :          2 :         eap->getKey = eap_aka_getKey;
    1343                 :          2 :         eap->isSuccess = eap_aka_isSuccess;
    1344                 :          2 :         eap->get_emsk = eap_aka_get_emsk;
    1345                 :            : 
    1346                 :          2 :         ret = eap_server_method_register(eap);
    1347         [ -  + ]:          2 :         if (ret)
    1348                 :          0 :                 eap_server_method_free(eap);
    1349                 :            : 
    1350                 :          2 :         return ret;
    1351                 :            : }
    1352                 :            : #endif /* EAP_SERVER_AKA_PRIME */

Generated by: LCOV version 1.9