Authentication.c 42.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
gauthier's avatar
 
gauthier committed
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

/*****************************************************************************
Source      Authentication.c

Version     0.1

Date        2013/03/04

Product     NAS stack

Subsystem   EPS Mobility Management

Author      Frederic Maurel

Description Defines the authentication EMM procedure executed by the
        Non-Access Stratum.

        The purpose of the EPS authentication and key agreement (AKA)
        procedure is to provide mutual authentication between the user
        and the network and to agree on a key KASME. The procedure is
        always initiated and controlled by the network. However, the
        UE can reject the EPS authentication challenge sent by the
        network.

        A partial native EPS security context is established in the
        UE and the network when an EPS authentication is successfully
        performed. The computed key material KASME is used as the
        root for the EPS integrity protection and ciphering key
        hierarchy.

*****************************************************************************/

#include <stdlib.h> // malloc, free
#include <string.h> // memcpy, memcmp, memset
#include <arpa/inet.h> // htons

#include "emm_proc.h"
#include "nas_log.h"
#include "nas_timer.h"

#include "emmData.h"
62
#include "emm_timers.h"
gauthier's avatar
 
gauthier committed
63 64 65

#include "emm_sap.h"
#include "emm_cause.h"
66
#include "emm_timers.h"
gauthier's avatar
 
gauthier committed
67 68 69

#include "usim_api.h"
#include "secu_defs.h"
70
#include "Authentication.h"
gauthier's avatar
 
gauthier committed
71 72 73 74 75 76


/****************************************************************************/
/****************  E X T E R N A L    D E F I N I T I O N S  ****************/
/****************************************************************************/

77 78
extern uint8_t usim_test;

gauthier's avatar
 
gauthier committed
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
/****************************************************************************/
/*******************  L O C A L    D E F I N I T I O N S  *******************/
/****************************************************************************/

/*
 * --------------------------------------------------------------------------
 *  Internal data handled by the authentication procedure in the UE
 * --------------------------------------------------------------------------
 */
/*
 * Timer handlers
 */
static void *_authentication_t3416_handler(void *);
static void *_authentication_t3418_handler(void *);
static void *_authentication_t3420_handler(void *);

/*
 * Abnormal case authentication procedure
 */
98
static int _authentication_abnormal_cases_cde(nas_user_t *user, int emm_cause,
gauthier's avatar
 
gauthier committed
99
    const OctetString *auts);
100
static int _authentication_abnormal_case_f(nas_user_t *user);
gauthier's avatar
 
gauthier committed
101

102 103
static int _authentication_stop_timers(nas_user_t *user);
static int _authentication_start_timers(nas_user_t *user);
gauthier's avatar
 
gauthier committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
static int _authentication_kasme(const OctetString *autn,
                                 const OctetString *ck, const OctetString *ik, const plmn_t *plmn,
                                 OctetString *kasme);

/*
 * --------------------------------------------------------------------------
 *  Internal data handled by the authentication procedure in the MME
 * --------------------------------------------------------------------------
 */

/****************************************************************************/
/******************  E X P O R T E D    F U N C T I O N S  ******************/
/****************************************************************************/

/*
 * --------------------------------------------------------------------------
 *      Authentication procedure executed by the UE
 * --------------------------------------------------------------------------
 */
/****************************************************************************
 **                                                                        **
 ** Name:    emm_proc_authentication_request()                         **
 **                                                                        **
 ** Description: Performs the MME requested authentication procedure.      **
 **                                                                        **
 **              3GPP TS 24.301, section 5.4.2.3                           **
 **      Upon receiving the AUTHENTICATION REQUEST message, the UE **
 **      shall store the received RAND together with the RES re-   **
 **      turned from the USIM in the volatile memory of the ME, to **
 **      avoid a synchronisation failure. The UE shall process the **
 **      authentication challenge data and respond with an AUTHEN- **
 **      TICATION RESPONSE message to the network.                 **
 **                                                                        **
 ** Inputs:  native_ksi:    TRUE if the security context is of type    **
 **             native (for KSIASME)                       **
 **      ksi:       The NAS ket sey identifier                 **
 **      rand:      Authentication parameter RAND              **
 **      autn:      Authentication parameter AUTN              **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **             T3418, T3420                               **
 **                                                                        **
 ***************************************************************************/
148
int emm_proc_authentication_request(nas_user_t *user, int native_ksi, int ksi,
gauthier's avatar
 
gauthier committed
149 150 151 152 153 154
                                    const OctetString *rand,
                                    const OctetString *autn)
{
  LOG_FUNC_IN;

  int rc = RETURNerror;
155
  authentication_data_t *authentication_data = user->authentication_data;
156
  emm_timers_t *emm_timers = user->emm_data->emm_timers;
gauthier's avatar
 
gauthier committed
157 158 159 160 161 162 163

  LOG_TRACE(INFO, "EMM-PROC  - Authentication requested ksi type = %s, ksi = %d", native_ksi ? "native" : "mapped", ksi);

  /* 3GPP TS 24.301, section 5.4.2.1
   * The UE shall proceed with an EPS authentication challenge only if a
   * USIM is present
   */
164
  if (!user->emm_data->usim_is_valid) {
gauthier's avatar
 
gauthier committed
165 166 167 168 169
    LOG_TRACE(WARNING, "EMM-PROC  - USIM is not present or not valid");
    LOG_FUNC_RETURN (RETURNerror);
  }

  /* Stop timer T3418, if running */
170 171 172
  if (emm_timers->T3418.id != NAS_TIMER_INACTIVE_ID) {
    LOG_TRACE(INFO, "EMM-PROC  - Stop timer T3418 (%d)", emm_timers->T3418.id);
    emm_timers->T3418.id = nas_timer_stop(emm_timers->T3418.id);
gauthier's avatar
 
gauthier committed
173 174 175
  }

  /* Stop timer T3420, if running */
176 177 178
  if (emm_timers->T3420.id != NAS_TIMER_INACTIVE_ID) {
    LOG_TRACE(INFO, "EMM-PROC  - Stop timer T3420 (%d)", emm_timers->T3420.id);
    emm_timers->T3420.id = nas_timer_stop(emm_timers->T3420.id);
gauthier's avatar
 
gauthier committed
179 180 181
  }

  /* Setup security keys */
182 183 184
  OctetString ck = {AUTH_CK_SIZE, authentication_data->ck};
  OctetString ik = {AUTH_IK_SIZE, authentication_data->ik};
  OctetString res = {AUTH_RES_SIZE, authentication_data->res};
gauthier's avatar
 
gauthier committed
185

186
  if (memcmp(authentication_data->rand, rand->value, AUTH_CK_SIZE) != 0) {
gauthier's avatar
 
gauthier committed
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
    /*
     * There is no valid stored RAND in the ME or the stored RAND is
     * different from the new received value in the AUTHENTICATION
     * REQUEST message
     */
    OctetString auts;
    auts.length = 0;
    auts.value = (uint8_t *)malloc(AUTH_AUTS_SIZE);

    if (auts.value == NULL) {
      LOG_TRACE(WARNING, "EMM-PROC  - Failed to allocate AUTS parameter");
      LOG_FUNC_RETURN (RETURNerror);
    }

    /* 3GPP TS 33.401, section 6.1.1
     * Get the "separation bit" of the AMF field of AUTN */
    int sbit = AUTH_AMF_SEPARATION_BIT(autn->value[AUTH_AMF_INDEX]);

    if (sbit != 0) {
      /* LW: only 64 bits from the response field are used for the authentication response for this algorithms */
      res.length = 8; /* Bytes */

      /*
       * Perform EPS authentication challenge to check the authenticity
       * of the core network by means of the received AUTN parameter and
       * request the USIM to compute RES, CK and IK for given RAND
       */
214 215
      if(usim_test == 0)
      {
216
        rc = usim_api_authenticate(&user->usim_data, rand, autn, &auts, &res, &ck, &ik);
217 218 219
      }
      else
      {
220
        rc = usim_api_authenticate_test(&user->usim_data, rand, autn, &auts, &res, &ck, &ik);
221
      }
gauthier's avatar
 
gauthier committed
222 223 224 225 226 227 228 229 230 231 232
    }

    if (rc != RETURNok) {
      /*
       * Network authentication not accepted by the UE
       */
      LOG_TRACE(WARNING, "EMM-PROC  - Network authentication failed (%s)",
                (auts.length > 0) ? "SQN failure" :
                (sbit == 0) ? "Non-EPS authentication unacceptable" :
                "MAC code failure");
      /* Delete any previously stored RAND and RES and stop timer T3416 */
233
      emm_proc_authentication_delete(user);
gauthier's avatar
 
gauthier committed
234 235 236 237 238 239

      /* Proceed authentication abnormal cases procedure */
      if (auts.length > 0) {
        /* 3GPP TS 24.301, section 5.4.2.6, case e
         * SQN failure */
        rc = _authentication_abnormal_cases_cde(
240
               user, EMM_CAUSE_SYNCH_FAILURE, &auts);
gauthier's avatar
 
gauthier committed
241 242 243 244
      } else if (sbit == 0) {
        /* 3GPP TS 24.301, section 5.4.2.6, case d
         * Non-EPS authentication unacceptable */
        rc = _authentication_abnormal_cases_cde(
245
               user, EMM_CAUSE_NON_EPS_AUTH_UNACCEPTABLE, NULL);
gauthier's avatar
 
gauthier committed
246 247 248 249
      } else {
        /* 3GPP TS 24.301, section 5.4.2.6, case c
         * MAC code failure */
        rc = _authentication_abnormal_cases_cde(
250
               user, EMM_CAUSE_MAC_FAILURE, NULL);
gauthier's avatar
 
gauthier committed
251 252 253 254 255 256 257 258 259 260 261 262
      }

      /* Free the AUTS parameter */
      free(auts.value);
      LOG_FUNC_RETURN (rc);
    }

    /* Free the AUTS parameter */
    free(auts.value);

    /* Store the new RAND in the volatile memory */
    if (rand->length <= AUTH_RAND_SIZE) {
263
      memcpy(authentication_data->rand, rand->value, rand->length);
gauthier's avatar
 
gauthier committed
264 265 266
    }

    /* Start, or reset and restart timer T3416 */
267 268 269
    if (emm_timers->T3416.id != NAS_TIMER_INACTIVE_ID) {
      LOG_TRACE(INFO, "EMM-PROC  - Stop timer T3416 (%d)", emm_timers->T3416.id);
      emm_timers->T3416.id = nas_timer_stop(emm_timers->T3416.id);
gauthier's avatar
 
gauthier committed
270 271
    }

272
    emm_timers->T3416.id = nas_timer_start(emm_timers->T3416.sec, _authentication_t3416_handler, NULL);
gauthier's avatar
 
gauthier committed
273
    LOG_TRACE(INFO, "EMM-PROC  - Timer T3416 (%d) expires in  %ld seconds",
274
              emm_timers->T3416.id, emm_timers->T3416.sec);
gauthier's avatar
 
gauthier committed
275 276 277 278 279 280 281 282
  }

  /*
   * The stored RAND value is equal to the new received value in the
   * AUTHENTICATION REQUEST message, or the UE has successfully checked
   * the authenticity of the core network
   */
  /* Start any retransmission timers */
283
  rc = _authentication_start_timers(user);
gauthier's avatar
 
gauthier committed
284 285 286 287 288 289 290 291

  if (rc != RETURNok) {
    LOG_TRACE(WARNING, "EMM-PROC  - Failed to start retransmission timers");
    LOG_FUNC_RETURN (RETURNerror);
  }

  /* Setup EMM procedure handler to be executed upon receiving
   * lower layer notification */
292
  rc = emm_proc_lowerlayer_initialize(user->lowerlayer_data, NULL, NULL, NULL, NULL);
gauthier's avatar
 
gauthier committed
293 294 295 296 297 298 299 300 301 302 303 304 305

  if (rc != RETURNok) {
    LOG_TRACE(WARNING,
              "EMM-PROC  - Failed to initialize EMM procedure handler");
    LOG_FUNC_RETURN (RETURNerror);
  }

  /*
   * Notify EMM-AS SAP that Authentication Response message has to be sent
   * to the network
   */
  emm_sap_t emm_sap;
  emm_sap.primitive = EMMAS_SECURITY_RES;
306
  emm_sap.u.emm_as.u.security.guti = user->emm_data->guti;
Frédéric Leroy's avatar
Frédéric Leroy committed
307
  emm_sap.u.emm_as.u.security.ueid = user->ueid;
gauthier's avatar
 
gauthier committed
308 309 310 311 312
  emm_sap.u.emm_as.u.security.msgType = EMM_AS_MSG_TYPE_AUTH;
  emm_sap.u.emm_as.u.security.emm_cause = EMM_CAUSE_SUCCESS;
  emm_sap.u.emm_as.u.security.res = &res;
  /* Setup EPS NAS security data */
  emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx,
313
                           user->emm_data->security, FALSE, TRUE);
314
  rc = emm_sap_send(user, &emm_sap);
gauthier's avatar
 
gauthier committed
315 316 317

  if (rc != RETURNerror) {
    /* Reset the authentication failure counters */
318 319 320
    authentication_data->mac_count = 0;
    authentication_data->umts_count = 0;
    authentication_data->sync_count = 0;
gauthier's avatar
 
gauthier committed
321 322

    /* Create non-current EPS security context */
323 324
    if (user->emm_data->non_current == NULL) {
      user->emm_data->non_current =
gauthier's avatar
 
gauthier committed
325 326 327
        (emm_security_context_t *)malloc(sizeof(emm_security_context_t));
    }

328 329
    if (user->emm_data->non_current) {
      memset(user->emm_data->non_current, 0, sizeof(emm_security_context_t));
gauthier's avatar
 
gauthier committed
330 331 332

      /* Set the security context type */
      if (native_ksi) {
333
        user->emm_data->non_current->type = EMM_KSI_NATIVE;
gauthier's avatar
 
gauthier committed
334
      } else {
335
        user->emm_data->non_current->type = EMM_KSI_MAPPED;
gauthier's avatar
 
gauthier committed
336 337 338
      }

      /* Set the EPS key set identifier */
339
      user->emm_data->non_current->eksi = ksi;
gauthier's avatar
 
gauthier committed
340 341
      /* Derive the Kasme from the authentication challenge using
       * the PLMN identity of the selected PLMN */
342 343 344 345
      user->emm_data->non_current->kasme.length = AUTH_KASME_SIZE;
      user->emm_data->non_current->kasme.value  = malloc(32);
      _authentication_kasme(autn, &ck, &ik, &user->emm_data->splmn,
                            &user->emm_data->non_current->kasme);
gauthier's avatar
 
gauthier committed
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
      /* NAS integrity and cyphering keys are not yet available */
    }
  }

  LOG_FUNC_RETURN (rc);
}

/****************************************************************************
 **                                                                        **
 ** Name:    emm_proc_authentication_reject()                          **
 **                                                                        **
 ** Description: Performs the authentication procedure not accepted by the **
 **      network.                                                  **
 **                                                                        **
 **              3GPP TS 24.301, section 5.4.2.5                           **
 **      Upon receiving an AUTHENTICATION REJECT message, the UE   **
 **      shall abort any EMM signalling procedure, stop any of the **
 **      timers T3410, T3417 or T3430 (if running) and enter state **
 **      EMM-DEREGISTERED.                                         **
 **                                                                        **
 ** Inputs:  None                                                      **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **             T3417, T3430                               **
 **                                                                        **
 ***************************************************************************/
374
int emm_proc_authentication_reject(nas_user_t *user)
gauthier's avatar
 
gauthier committed
375 376 377 378 379
{
  LOG_FUNC_IN;

  emm_sap_t emm_sap;
  int rc;
380
  authentication_data_t *authentication_data = user->authentication_data;
381
  emm_timers_t *emm_timers = user->emm_data->emm_timers;
gauthier's avatar
 
gauthier committed
382 383 384 385

  LOG_TRACE(WARNING, "EMM-PROC  - Authentication not accepted by the network");

  /* Delete any previously stored RAND and RES and stop timer T3416 */
386
  (void) emm_proc_authentication_delete(user);
gauthier's avatar
 
gauthier committed
387 388

  /* Set the EPS update status to EU3 ROAMING NOT ALLOWED */
389
  user->emm_data->status = EU3_ROAMING_NOT_ALLOWED;
gauthier's avatar
 
gauthier committed
390
  /* Delete the stored GUTI */
391
  user->emm_data->guti = NULL;
gauthier's avatar
 
gauthier committed
392
  /* Delete the TAI list */
393
  user->emm_data->ltai.n_tais = 0;
gauthier's avatar
 
gauthier committed
394
  /* Delete the last visited registered TAI */
395
  user->emm_data->tai = NULL;
gauthier's avatar
 
gauthier committed
396 397

  /* Delete the eKSI */
398 399
  if (user->emm_data->security) {
    user->emm_data->security->type = EMM_KSI_NOT_AVAILABLE;
gauthier's avatar
 
gauthier committed
400 401 402
  }

  /* Consider the USIM invalid */
403
  user->emm_data->usim_is_valid = FALSE;
gauthier's avatar
 
gauthier committed
404 405

  /* Stop timer T3410 */
406 407 408
  if (emm_timers->T3410.id != NAS_TIMER_INACTIVE_ID) {
    LOG_TRACE(INFO, "EMM-PROC  - Stop timer T3410 (%d)", emm_timers->T3410.id);
    emm_timers->T3410.id = nas_timer_stop(emm_timers->T3410.id);
gauthier's avatar
 
gauthier committed
409 410 411
  }

  /* Stop timer T3417 */
412 413 414
  if (emm_timers->T3417.id != NAS_TIMER_INACTIVE_ID) {
    LOG_TRACE(INFO, "EMM-PROC  - Stop timer T3417 (%d)", emm_timers->T3417.id);
    emm_timers->T3417.id = nas_timer_stop(emm_timers->T3417.id);
gauthier's avatar
 
gauthier committed
415 416 417
  }

  /* Stop timer T3430 */
418 419 420
  if (emm_timers->T3430.id != NAS_TIMER_INACTIVE_ID) {
    LOG_TRACE(INFO, "EMM-PROC  - Stop timer T3430 (%d)", emm_timers->T3430.id);
    emm_timers->T3430.id = nas_timer_stop(emm_timers->T3430.id);
gauthier's avatar
 
gauthier committed
421 422 423 424
  }

  /* Abort any EMM signalling procedure (prevent the retransmission timers to
   * be restarted) */
425
  authentication_data->timers = 0x00;
gauthier's avatar
 
gauthier committed
426 427 428 429 430

  /*
   * Notify EMM that authentication is not accepted by the network
   */
  emm_sap.primitive = EMMREG_AUTH_REJ;
431
  rc = emm_sap_send(user, &emm_sap);
gauthier's avatar
 
gauthier committed
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456

  LOG_FUNC_RETURN (rc);
}

/****************************************************************************
 **                                                                        **
 ** Name:    emm_proc_authentication_delete()                          **
 **                                                                        **
 ** Description: Deletes the RAND and RES values stored into the volatile  **
 **      memory of the Mobile Equipment and stop timer T3416, if   **
 **      running, upon receipt of a SECURITY MODE COMMAND, SERVICE **
 **      REJECT, TRACKING AREA UPDATE REJECT, TRACKING AREA UPDATE **
 **      ACCEPT or AUTHENTICATION REJECT message; upon expiry of   **
 **      timer  T3416; or if the UE  enters  the  EMM  state  EMM- **
 **      DEREGISTERED or EMM-NULL.                                 **
 **                                                                        **
 **              3GPP TS 24.301, section 5.4.2.3                           **
 **                                                                        **
 ** Inputs:  None                                                      **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **                                                                        **
 ***************************************************************************/
457
int emm_proc_authentication_delete(nas_user_t *user)
gauthier's avatar
 
gauthier committed
458 459
{
  LOG_FUNC_IN;
460
  authentication_data_t *authentication_data = user->authentication_data;
461
  emm_timers_t *emm_timers = user->emm_data->emm_timers;
gauthier's avatar
 
gauthier committed
462 463 464 465

  LOG_TRACE(INFO, "EMM-PROC  - Delete authentication data RAND and RES");

  /* Stop timer T3416, if running */
466 467 468
  if (emm_timers->T3416.id != NAS_TIMER_INACTIVE_ID) {
    LOG_TRACE(INFO, "EMM-PROC  - Stop timer T3416 (%d)", emm_timers->T3416.id);
    emm_timers->T3416.id = nas_timer_stop(emm_timers->T3416.id);
gauthier's avatar
 
gauthier committed
469 470 471
  }

  /* Delete any previously stored RAND and RES */
472 473
  memset(authentication_data->rand, 0, AUTH_RAND_SIZE);
  memset(authentication_data->res, 0, AUTH_RES_SIZE);
gauthier's avatar
 
gauthier committed
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509

  LOG_FUNC_RETURN (RETURNok);
}


/****************************************************************************/
/*********************  L O C A L    F U N C T I O N S  *********************/
/****************************************************************************/

/*
 * --------------------------------------------------------------------------
 *              Timer handlers
 * --------------------------------------------------------------------------
 */

/****************************************************************************
 **                                                                        **
 ** Name:    _authentication_t3416_handler()                           **
 **                                                                        **
 ** Description: T3416 timeout handler                                     **
 **      Upon T3416 timer expiration, the RAND and RES values sto- **
 **      red in the ME shall be deleted.                           **
 **                                                                        **
 **              3GPP TS 24.301, section 5.4.2.3                           **
 **                                                                        **
 ** Inputs:  args:      handler parameters                         **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    None                                       **
 **      Others:    T3416                                      **
 **                                                                        **
 ***************************************************************************/
static void *_authentication_t3416_handler(void *args)
{
  LOG_FUNC_IN;
510
  nas_user_t *user=args;
511
  emm_timers_t *emm_timers = user->emm_data->emm_timers;
gauthier's avatar
 
gauthier committed
512 513 514 515

  LOG_TRACE(WARNING, "EMM-PROC  - T3416 timer expired");

  /* Stop timer T3416 */
516
  emm_timers->T3416.id = nas_timer_stop(emm_timers->T3416.id);
gauthier's avatar
 
gauthier committed
517
  /* Delete previouly stored RAND and RES authentication data */
518
  (void) emm_proc_authentication_delete(user);
gauthier's avatar
 
gauthier committed
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545

  LOG_FUNC_RETURN (NULL);
}

/****************************************************************************
 **                                                                        **
 ** Name:    _authentication_t3418_handler()                           **
 **                                                                        **
 ** Description: T3418 timeout handler                                     **
 **      Upon T3418 timer expiration, the UE shall deem that the   **
 **      source of the  authentication  challenge is not  genuine  **
 **      (authentication not accepted by the UE).                  **
 **                                                                        **
 **              3GPP TS 24.301, section 5.4.2.7, case c                   **
 **                                                                        **
 ** Inputs:  args:      handler parameters                         **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    None                                       **
 **                                                                        **
 ***************************************************************************/
static void *_authentication_t3418_handler(void *args)
{
  LOG_FUNC_IN;

  int rc;
546
  nas_user_t *user=args;
547
  emm_timers_t *emm_timers = user->emm_data->emm_timers;
548
  authentication_data_t *authentication_data = user->authentication_data;
gauthier's avatar
 
gauthier committed
549 550 551 552

  LOG_TRACE(WARNING, "EMM-PROC  - T3418 timer expired");

  /* Stop timer T3418 */
553
  emm_timers->T3418.id = nas_timer_stop(emm_timers->T3418.id);
gauthier's avatar
 
gauthier committed
554
  /* Reset the MAC failure and UMTS challenge failure counters */
555 556
  authentication_data->mac_count = 0;
  authentication_data->umts_count = 0;
gauthier's avatar
 
gauthier committed
557
  /* 3GPP TS 24.301, section 5.4.2.7, case f */
558
  rc = _authentication_abnormal_case_f(user);
gauthier's avatar
 
gauthier committed
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588

  if (rc != RETURNok) {
    LOG_TRACE(WARNING, "EMM-PROC  - Failed to proceed abnormal case f");
  }

  LOG_FUNC_RETURN (NULL);
}

/****************************************************************************
 **                                                                        **
 ** Name:    _authentication_t3420_handler()                           **
 **                                                                        **
 ** Description: T3420 timeout handler                                     **
 **      Upon T3420 timer expiration, the UE shall deem that the   **
 **      network has failed the authentication check.              **
 **                                                                        **
 **              3GPP TS 24.301, section 5.4.2.7, case e                   **
 **                                                                        **
 ** Inputs:  args:      handler parameters                         **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    None                                       **
 **                                                                        **
 ***************************************************************************/
static void *_authentication_t3420_handler(void *args)
{
  LOG_FUNC_IN;

  int rc;
589 590
  nas_user_t *user=args;
  authentication_data_t *authentication_data = user->authentication_data;
591
  emm_timers_t *emm_timers = user->emm_data->emm_timers;
gauthier's avatar
 
gauthier committed
592 593 594 595

  LOG_TRACE(WARNING, "EMM-PROC  - T3420 timer expired");

  /* Stop timer T3420 */
596
  emm_timers->T3420.id = nas_timer_stop(emm_timers->T3420.id);
gauthier's avatar
 
gauthier committed
597
  /* Reset the sync failure counter */
598
  authentication_data->sync_count = 0;
gauthier's avatar
 
gauthier committed
599
  /* 3GPP TS 24.301, section 5.4.2.7, case f */
600
  rc = _authentication_abnormal_case_f(user);
gauthier's avatar
 
gauthier committed
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629

  if (rc != RETURNok) {
    LOG_TRACE(WARNING, "EMM-PROC  - Failed to proceed abnormal case f");
  }

  LOG_FUNC_RETURN (NULL);
}

/*
 * --------------------------------------------------------------------------
 *              Abnormal cases in the UE
 * --------------------------------------------------------------------------
 */

/****************************************************************************
 **                                                                        **
 ** Name:    _authentication_abnormal_cases_cde()                      **
 **                                                                        **
 ** Description: Performs the abnormal case authentication procedure.      **
 **                                                                        **
 **      3GPP TS 24.301, section 5.4.2.7, cases c, d and e         **
 **                                                                        **
 ** Inputs:  emm_cause: EMM cause code                             **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **                                                                        **
 ***************************************************************************/
630
static int _authentication_abnormal_cases_cde(nas_user_t *user, int emm_cause,
gauthier's avatar
 
gauthier committed
631 632 633 634 635
    const OctetString *auts)
{
  LOG_FUNC_IN;

  int rc;
636
  authentication_data_t *authentication_data = user->authentication_data;
637
  emm_timers_t *emm_timers = user->emm_data->emm_timers;
gauthier's avatar
 
gauthier committed
638 639 640

  LOG_TRACE(WARNING, "EMM-PROC  - "
            "Abnormal case, authentication counters c/d/e = %d/%d/%d",
641 642
            authentication_data->mac_count, authentication_data->umts_count,
            authentication_data->sync_count);
gauthier's avatar
 
gauthier committed
643 644 645 646 647 648 649

  /*
   * Notify EMM-AS SAP that Authentication Failure message has to be sent
   * to the network
   */
  emm_sap_t emm_sap;
  emm_sap.primitive = EMMAS_SECURITY_RES;
650
  emm_sap.u.emm_as.u.security.guti = user->emm_data->guti;
Frédéric Leroy's avatar
Frédéric Leroy committed
651
  emm_sap.u.emm_as.u.security.ueid = user->ueid;
gauthier's avatar
 
gauthier committed
652 653 654 655 656
  emm_sap.u.emm_as.u.security.msgType = EMM_AS_MSG_TYPE_AUTH;
  emm_sap.u.emm_as.u.security.emm_cause = emm_cause;
  emm_sap.u.emm_as.u.security.auts = auts;
  /* Setup EPS NAS security data */
  emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx,
657
                           user->emm_data->security, FALSE, TRUE);
658
  rc = emm_sap_send(user, &emm_sap);
gauthier's avatar
 
gauthier committed
659 660 661 662 663 664 665 666 667

  if (rc != RETURNerror) {
    /*
     * Update the authentication failure counters
     */
    switch (emm_cause) {
    case EMM_CAUSE_MAC_FAILURE:
      /* 3GPP TS 24.301, section 5.4.2.6, case c
       * Update the MAC failure counter */
668
      authentication_data->mac_count += 1;
gauthier's avatar
 
gauthier committed
669
      /* Start timer T3418 */
670
      emm_timers->T3418.id = nas_timer_start(emm_timers->T3418.sec,
671
                                 _authentication_t3418_handler, user);
gauthier's avatar
 
gauthier committed
672
      LOG_TRACE(INFO,"EMM-PROC  - Timer T3418 (%d) expires in "
673
                "%ld seconds", emm_timers->T3418.id, emm_timers->T3418.sec);
gauthier's avatar
 
gauthier committed
674 675 676 677 678
      break;

    case EMM_CAUSE_NON_EPS_AUTH_UNACCEPTABLE:
      /* 3GPP TS 24.301, section 5.4.2.6, case d
       * Update the UMTS challenge failure counter */
679
      authentication_data->umts_count += 1;
gauthier's avatar
 
gauthier committed
680
      /* Start timer T3418 */
681
      emm_timers->T3418.id = nas_timer_start(emm_timers->T3418.sec,
682
                                 _authentication_t3418_handler, user);
gauthier's avatar
 
gauthier committed
683
      LOG_TRACE(INFO,"EMM-PROC  - Timer T3418 (%d) expires in "
684
                "%ld seconds", emm_timers->T3418.id, emm_timers->T3418.sec);
gauthier's avatar
 
gauthier committed
685 686 687 688 689
      break;

    case EMM_CAUSE_SYNCH_FAILURE:
      /* 3GPP TS 24.301, section 5.4.2.6, case e
       * Update the synch failure counter */
690
      authentication_data->sync_count += 1;
gauthier's avatar
 
gauthier committed
691
      /* Start timer T3420 */
692
      emm_timers->T3420.id = nas_timer_start(emm_timers->T3420.sec,
693
                                 _authentication_t3420_handler, user);
gauthier's avatar
 
gauthier committed
694
      LOG_TRACE(INFO,"EMM-PROC  - Timer T3420 (%d) expires in "
695
                "%ld seconds", emm_timers->T3420.id, emm_timers->T3420.sec);
gauthier's avatar
 
gauthier committed
696 697 698 699 700 701 702 703 704 705 706
      break;

    default:
      LOG_TRACE(WARNING, "EMM cause code is not valid (%d)",
                emm_cause);
      LOG_FUNC_RETURN (RETURNerror);
    }

    /*
     * Stop any retransmission timers that are running
     */
707
    rc = _authentication_stop_timers(user);
gauthier's avatar
 
gauthier committed
708 709 710 711 712 713 714 715 716 717 718 719 720

    if (rc != RETURNok) {
      LOG_TRACE(WARNING, "EMM-PROC  - "
                "Failed to stop retransmission timers");
      LOG_FUNC_RETURN (RETURNerror);
    }

    /*
     * Check whether the network has failed the authentication check
     */
    int failure_counter = 0;

    if (emm_cause == EMM_CAUSE_MAC_FAILURE) {
721 722
      failure_counter = authentication_data->mac_count
                        + authentication_data->sync_count;
gauthier's avatar
 
gauthier committed
723
    } else if (emm_cause == EMM_CAUSE_SYNCH_FAILURE) {
724 725 726
      failure_counter = authentication_data->mac_count
                        + authentication_data->umts_count
                        + authentication_data->sync_count;
gauthier's avatar
 
gauthier committed
727 728 729 730
    }

    if (failure_counter >= AUTHENTICATION_COUNTER_MAX) {
      /* 3GPP TS 24.301, section 5.4.2.6, case f */
731
      rc = _authentication_abnormal_case_f(user);
gauthier's avatar
 
gauthier committed
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758

      if (rc != RETURNok) {
        LOG_TRACE(WARNING, "EMM-PROC  - "
                  "Failed to proceed abnormal case f");
      }
    }
  }

  LOG_FUNC_RETURN (rc);
}

/****************************************************************************
 **                                                                        **
 ** Name:    _authentication_abnormal_case_f()                         **
 **                                                                        **
 ** Description: Performs the abnormal case authentication procedure.      **
 **                                                                        **
 **      3GPP TS 24.301, section 5.4.2.7, case f                   **
 **                                                                        **
 ** Inputs:  None                                                      **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
 **                                                                        **
 ***************************************************************************/
759
static int _authentication_abnormal_case_f(nas_user_t *user)
gauthier's avatar
 
gauthier committed
760 761 762 763 764 765 766 767 768 769 770 771 772
{
  LOG_FUNC_IN;

  int rc;

  LOG_TRACE(WARNING, "EMM-PROC  - Authentication abnormal case f");

  /*
   * Request RRC to locally release the RRC connection and treat
   * the active cell as barred
   */
  emm_sap_t emm_sap;
  emm_sap.primitive = EMMAS_RELEASE_REQ;
773
  emm_sap.u.emm_as.u.release.guti = user->emm_data->guti;
gauthier's avatar
 
gauthier committed
774
  emm_sap.u.emm_as.u.release.cause = EMM_AS_CAUSE_AUTHENTICATION;
775
  rc = emm_sap_send(user, &emm_sap);
gauthier's avatar
 
gauthier committed
776 777 778 779 780 781

  if (rc != RETURNerror) {
    /* Start any retransmission timers (e.g. T3410, T3417, T3421 or
     * T3430), if they were running and stopped when the UE received
     * the first AUTHENTICATION REQUEST message containing an invalid
     * MAC or SQN */
782
    rc = _authentication_start_timers(user);
gauthier's avatar
 
gauthier committed
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808
  }

  LOG_FUNC_RETURN (rc);
}

/*
 * --------------------------------------------------------------------------
 *              UE specific local functions
 * --------------------------------------------------------------------------
 */

/****************************************************************************
 **                                                                        **
 ** Name:    _authentication_stop_timers()                             **
 **                                                                        **
 ** Description: Stops any retransmission timers (e.g. T3410, T3417, T3421 **
 **      or T3430) that are running                                **
 **                                                                        **
 ** Inputs:  None                                                      **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **             T3430                                      **
 **                                                                        **
 ***************************************************************************/
809
static int _authentication_stop_timers(nas_user_t *user)
gauthier's avatar
 
gauthier committed
810 811
{
  LOG_FUNC_IN;
812
  authentication_data_t *authentication_data = user->authentication_data;
813
  emm_timers_t *emm_timers = user->emm_data->emm_timers;
gauthier's avatar
 
gauthier committed
814 815

  /* Stop attach timer */
816 817 818
  if (emm_timers->T3410.id != NAS_TIMER_INACTIVE_ID) {
    LOG_TRACE(INFO, "EMM-PROC  - Stop timer T3410 (%d)", emm_timers->T3410.id);
    emm_timers->T3410.id = nas_timer_stop(emm_timers->T3410.id);
819
    authentication_data->timers |= AUTHENTICATION_T3410;
gauthier's avatar
 
gauthier committed
820 821 822
  }

  /* Stop service request timer */
823 824 825
  if (emm_timers->T3417.id != NAS_TIMER_INACTIVE_ID) {
    LOG_TRACE(INFO, "EMM-PROC  - Stop timer T3417 (%d)", emm_timers->T3417.id);
    emm_timers->T3417.id = nas_timer_stop(emm_timers->T3417.id);
826
    authentication_data->timers |= AUTHENTICATION_T3417;
gauthier's avatar
 
gauthier committed
827 828 829
  }

  /* Stop detach timer */
830 831 832
  if (emm_timers->T3421.id != NAS_TIMER_INACTIVE_ID) {
    LOG_TRACE(INFO, "EMM-PROC  - Stop timer T3421 (%d)", emm_timers->T3421.id);
    emm_timers->T3421.id = nas_timer_stop(emm_timers->T3421.id);
833
    authentication_data->timers |= AUTHENTICATION_T3421;
gauthier's avatar
 
gauthier committed
834 835 836
  }

  /* Stop tracking area update timer */
837 838 839
  if (emm_timers->T3430.id != NAS_TIMER_INACTIVE_ID) {
    LOG_TRACE(INFO, "EMM-PROC  - Stop timer T3430 (%d)", emm_timers->T3430.id);
    emm_timers->T3430.id = nas_timer_stop(emm_timers->T3430.id);
840
    authentication_data->timers |= AUTHENTICATION_T3430;
gauthier's avatar
 
gauthier committed
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863
  }

  LOG_FUNC_RETURN (RETURNok);
}

/****************************************************************************
 **                                                                        **
 ** Name:    _authentication_start_timers()                            **
 **                                                                        **
 ** Description: Starts any retransmission timers (e.g. T3410, T3417,      **
 **      T3421 or T3430), if they were running and stopped when    **
 **      the UE received the first AUTHENTICATION REQUEST message  **
 **      containing an invalid MAC or SQN                          **
 **                                                                        **
 **      3GPP TS 24.301, section 5.4.2.7, case f                   **
 **                                                                        **
 ** Inputs:  None                                                      **
 **                                                                        **
 ** Outputs:     None                                                      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    T3410, T3417, T3421, T3430                 **
 **                                                                        **
 ***************************************************************************/
864
static int _authentication_start_timers(nas_user_t *user)
gauthier's avatar
 
gauthier committed
865 866
{
  LOG_FUNC_IN;
867
  authentication_data_t *authentication_data = user->authentication_data;
868
  emm_timers_t *emm_timers = user->emm_data->emm_timers;
gauthier's avatar
 
gauthier committed
869

870
  if (authentication_data->timers & AUTHENTICATION_T3410) {
gauthier's avatar
 
gauthier committed
871
    /* Start attach timer */
872
    emm_timers->T3410.id = nas_timer_start(emm_timers->T3410.sec, emm_attach_t3410_handler, NULL);
gauthier's avatar
 
gauthier committed
873
    LOG_TRACE(INFO,"EMM-PROC  - Timer T3410 (%d) expires in "
874
              "%ld seconds", emm_timers->T3410.id, emm_timers->T3410.sec);
gauthier's avatar
 
gauthier committed
875 876
  }

877
  if (authentication_data->timers & AUTHENTICATION_T3417) {
gauthier's avatar
 
gauthier committed
878
    /* Start service request timer */
879
    emm_timers->T3417.id = nas_timer_start(emm_timers->T3417.sec, emm_service_t3417_handler, NULL);
gauthier's avatar
 
gauthier committed
880
    LOG_TRACE(INFO,"EMM-PROC  - Timer T3417 (%d) expires in "
881
              "%ld seconds", emm_timers->T3417.id, emm_timers->T3417.sec);
gauthier's avatar
 
gauthier committed
882 883
  }

884
  if (authentication_data->timers & AUTHENTICATION_T3421) {
gauthier's avatar
 
gauthier committed
885
    /* Start detach timer */
886
    emm_timers->T3421.id = nas_timer_start(emm_timers->T3421.sec, emm_detach_t3421_handler, NULL);
gauthier's avatar
 
gauthier committed
887
    LOG_TRACE(INFO,"EMM-PROC  - Timer T3421 (%d) expires in "
888
              "%ld seconds", emm_timers->T3421.id, emm_timers->T3421.sec);
gauthier's avatar
 
gauthier committed
889 890
  }

891
  if (authentication_data->timers & AUTHENTICATION_T3430) {
gauthier's avatar
 
gauthier committed
892
    /* Start tracking area update timer */
893
    emm_timers->T3430.id = nas_timer_start(emm_timers->T3430.sec, emm_tau_t3430_handler, NULL);
gauthier's avatar
 
gauthier committed
894
    LOG_TRACE(INFO,"EMM-PROC  - Timer T3430 (%d) expires in "
895
              "%ld seconds", emm_timers->T3430.id, emm_timers->T3430.sec);
gauthier's avatar
 
gauthier committed
896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936
  }

  LOG_FUNC_RETURN (RETURNok);
}

/****************************************************************************
 **                                                                        **
 ** Name:    _authentication_kasme()                                   **
 **                                                                        **
 ** Description: Computes the Key Access Security Management Entity Kasme  **
 **      from the provided authentication challenge data.          **
 **                                                                        **
 **              3GPP TS 33.401, Annex A.2                                 **
 **                                                                        **
 ** Inputs:  autn:      Authentication token                       **
 **      ck:        Cipherig key                               **
 **      ik:        Integrity key                              **
 **      plmn:      Identifier of the currently selected PLMN  **
 **      Others:    None                                       **
 **                                                                        **
 ** Outputs:     kasme:     Key Access Security Management Entity      **
 **      Return:    RETURNok, RETURNerror                      **
 **      Others:    None                                       **
 **                                                                        **
 ***************************************************************************/
static int _authentication_kasme(const OctetString *autn,
                                 const OctetString *ck, const OctetString *ik,
                                 const plmn_t *plmn, OctetString *kasme)
{
  LOG_FUNC_IN;

  LOG_TRACE(INFO,"EMM-PROC  _authentication_kasme INPUT CK %s",
            dump_octet_string(ck));
  LOG_TRACE(INFO,"EMM-PROC  _authentication_kasme INPUT IK %s",
            dump_octet_string(ik));
  LOG_TRACE(INFO,"EMM-PROC  _authentication_kasme INPUT AUTN %s",
            dump_octet_string(autn));
  LOG_TRACE(INFO,"EMM-PROC  _authentication_kasme INPUT KASME LENGTH %u",
            kasme->length);

  /* Compute the derivation key KEY = CK || IK */
937
  uint8_t key[ck->length + ik->length];
gauthier's avatar
 
gauthier committed
938 939 940 941 942 943
  memcpy(key, ck->value, ck->length);
  memcpy(key + ck->length, ik->value, ik->length);

  /* Compute the KDF input_s parameter
   * S = FC(0x10) || SNid(MCC, MNC) || 0x00 0x03 || SQN ⊕ AK || 0x00 0x06
   */
944 945 946
  uint8_t  input_s[16]; // less than 16
  uint8_t  sn_id[AUTH_SNID_SIZE]; // less than 16
  uint16_t length;
gauthier's avatar
 
gauthier committed
947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001
  int      offset         = 0;
  int      size_of_length = sizeof(length);

  // FC
  input_s[offset] = 0x10;
  offset       += 1;

  // P0=SN id
  length        = AUTH_SNID_SIZE;
  sn_id[0] = (plmn->MCCdigit2 << 4) | plmn->MCCdigit1;
  sn_id[1] = (plmn->MNCdigit3 << 4) | plmn->MCCdigit3;
  sn_id[2] = (plmn->MNCdigit2 << 4) | plmn->MNCdigit1;

  memcpy(input_s + offset, sn_id, length);
  LOG_TRACE(INFO,"EMM-PROC  _authentication_kasme P0 MCC,MNC %02X %02X %02X",
            input_s[offset],
            input_s[offset+1],
            input_s[offset+2]);
  offset += length;
  // L0=SN id length
  length = htons(length);
  memcpy(input_s + offset, &length, size_of_length);
  offset += size_of_length;

  // P1=Authentication token
  length = AUTH_SQN_SIZE;
  memcpy(input_s + offset, autn->value, length);
  offset += length;
  // L1
  length = htons(length);
  memcpy(input_s + offset, &length, size_of_length);
  offset += size_of_length;

  LOG_TRACE(INFO,
            "EMM-PROC  _authentication_kasme input S to KFD (length %u)%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
            offset,
            input_s[0],input_s[1],input_s[2],input_s[3],
            input_s[4],input_s[5],input_s[6],input_s[7],
            input_s[8],input_s[9],input_s[10],input_s[11],
            input_s[12],input_s[13]);
  /* TODO !!! Compute the Kasme key */
  // todo_hmac_256(key, input_s, kasme->value);
  kdf(key,
      ck->length + ik->length , /*key_length*/
      input_s,
      offset,
      kasme->value,
      kasme->length);

  LOG_TRACE(INFO,"EMM-PROC  KASME (l=%d)%s",
            kasme->length,
            dump_octet_string(kasme));

  LOG_FUNC_RETURN (RETURNok);
}