Merge branch 'NR_SA_NGAP_RRC_wk42' of https://gitlab.eurecom.fr/oai/openairinterface5g into NR_SA_NGAP_RRC_wk42
This commit is contained in:
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
* 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.1 (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
|
||||
*
|
||||
* Author and copyright: Laurent Thomas, open-cells.com
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#ifndef NR_NAS_DEFS_H
|
||||
#define NR_NAS_DEFS_H
|
||||
|
||||
#include <common/utils/LOG/log.h>
|
||||
#include <openair3/UICC/usim_interface.h>
|
||||
#include <openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h>
|
||||
|
||||
/* TS 24.007 possible L3 formats:
|
||||
Table 11.1: Formats of information elements
|
||||
Format Meaning IEI present LI present Value part present
|
||||
T Type only yes no no
|
||||
V Value only no no yes
|
||||
TV Type and Value yes no yes
|
||||
LV Length and Value no yes yes
|
||||
TLV Type, Length and Value yes yes yes
|
||||
LV-E Length and Value no yes yes
|
||||
TLV-E Type, Length and Value yes yes yes
|
||||
*/
|
||||
|
||||
/* Map task id to printable name. */
|
||||
typedef struct {
|
||||
int id;
|
||||
char text[256];
|
||||
} text_info_t;
|
||||
|
||||
static inline const char * idToText(const text_info_t* table, int size, int id) {
|
||||
for(int i=0; i<size; i++)
|
||||
if (table[i].id==id)
|
||||
return table[i].text;
|
||||
LOG_E(NAS,"impossible id %x\n", id);
|
||||
return "IMPOSSIBLE";
|
||||
}
|
||||
#define idStr(TaBle, iD) idToText(TaBle, sizeof(TaBle)/sizeof(text_info_t), iD)
|
||||
|
||||
#define TO_TEXT(LabEl, nUmID) {nUmID, #LabEl},
|
||||
#define TO_ENUM(LabEl, nUmID ) LabEl = nUmID,
|
||||
|
||||
//TS 24.501, chap 9.2 => TS 24.007
|
||||
typedef enum {
|
||||
SGSsessionmanagementmessages=0x2e, //LTEbox: 0xC0 ???
|
||||
SGSmobilitymanagementmessages=0x7e,
|
||||
} Extendedprotocoldiscriminator_t;
|
||||
|
||||
#define FOREACH_TYPE(TYPE_DEF) \
|
||||
TYPE_DEF( Registrationrequest,0x41 )\
|
||||
TYPE_DEF( Registrationaccept,0x42 )\
|
||||
TYPE_DEF( Registrationcomplete,0x43 )\
|
||||
TYPE_DEF( Registrationreject,0x44 )\
|
||||
TYPE_DEF( DeregistrationrequestUEoriginating,0x45 )\
|
||||
TYPE_DEF( DeregistrationacceptUEoriginating,0x46 )\
|
||||
TYPE_DEF( DeregistrationrequestUEterminated,0x47 )\
|
||||
TYPE_DEF( DeregistrationacceptUEterminated,0x48 )\
|
||||
TYPE_DEF( Servicerequest,0x4c )\
|
||||
TYPE_DEF( Servicereject,0x4d )\
|
||||
TYPE_DEF( Serviceaccept,0x4e )\
|
||||
TYPE_DEF( Controlplaneservicerequest,0x4f )\
|
||||
TYPE_DEF( Networkslicespecificauthenticationcommand,0x50 )\
|
||||
TYPE_DEF( Networkslicespecificauthenticationcomplete,0x51 )\
|
||||
TYPE_DEF( Networkslicespecificauthenticationresult,0x52 )\
|
||||
TYPE_DEF( Configurationupdatecommand,0x54 )\
|
||||
TYPE_DEF( Configurationupdatecomplete,0x55 )\
|
||||
TYPE_DEF( Authenticationrequest,0x56 )\
|
||||
TYPE_DEF( Authenticationresponse,0x57 )\
|
||||
TYPE_DEF( Authenticationreject,0x58 )\
|
||||
TYPE_DEF( Authenticationfailure,0x59 )\
|
||||
TYPE_DEF( Authenticationresult,0x5a )\
|
||||
TYPE_DEF( Identityrequest,0x5b )\
|
||||
TYPE_DEF( Identityresponse,0x5c )\
|
||||
TYPE_DEF( Securitymodecommand,0x5d )\
|
||||
TYPE_DEF( Securitymodecomplete,0x5e )\
|
||||
TYPE_DEF( Securitymodereject,0x5f )\
|
||||
TYPE_DEF( SGMMstatus,0x64 )\
|
||||
TYPE_DEF( Notification,0x65 )\
|
||||
TYPE_DEF( Notificationresponse,0x66 )\
|
||||
TYPE_DEF( ULNAStransport,0x67 )\
|
||||
TYPE_DEF( DLNAStransport,0x68 )\
|
||||
TYPE_DEF( PDUsessionestablishmentrequest,0xc1 )\
|
||||
TYPE_DEF( PDUsessionestablishmentaccept,0xc2 )\
|
||||
TYPE_DEF( PDUsessionestablishmentreject,0xc3 )\
|
||||
TYPE_DEF( PDUsessionauthenticationcommand,0xc5 )\
|
||||
TYPE_DEF( PDUsessionauthenticationcomplete,0xc6 )\
|
||||
TYPE_DEF( PDUsessionauthenticationresult,0xc7 )\
|
||||
TYPE_DEF( PDUsessionmodificationrequest,0xc9 )\
|
||||
TYPE_DEF( PDUsessionmodificationreject,0xca )\
|
||||
TYPE_DEF( PDUsessionmodificationcommand,0xcb )\
|
||||
TYPE_DEF( PDUsessionmodificationcomplete,0xcc )\
|
||||
TYPE_DEF( PDUsessionmodificationcommandreject,0xcd )\
|
||||
TYPE_DEF( PDUsessionreleaserequest,0xd1 )\
|
||||
TYPE_DEF( PDUsessionreleasereject,0xd2 )\
|
||||
TYPE_DEF( PDUsessionreleasecommand,0xd3 )\
|
||||
TYPE_DEF( PDUsessionreleasecomplete,0xd4 )\
|
||||
TYPE_DEF( SGSMstatus,0xd6 )\
|
||||
|
||||
static const text_info_t message_text_info[] = {
|
||||
FOREACH_TYPE(TO_TEXT)
|
||||
};
|
||||
|
||||
//! Tasks id of each task
|
||||
typedef enum {
|
||||
FOREACH_TYPE(TO_ENUM)
|
||||
} SGSmobilitymanagementmessages_t;
|
||||
|
||||
// TS 24.501
|
||||
typedef enum {
|
||||
notsecurityprotected=0,
|
||||
Integrityprotected=1,
|
||||
Integrityprotectedandciphered=2,
|
||||
Integrityprotectedwithnew5GNASsecuritycontext=3,
|
||||
Integrityprotectedandcipheredwithnew5GNASsecuritycontext=4,
|
||||
} Security_header_t;
|
||||
|
||||
typedef enum {
|
||||
SUCI=1,
|
||||
SGGUTI,
|
||||
IMEI,
|
||||
SGSTMSI,
|
||||
IMEISV,
|
||||
MACaddress,
|
||||
EUI64,
|
||||
} identitytype_t;
|
||||
|
||||
|
||||
// table 9.11.3.2.1
|
||||
#define FOREACH_CAUSE(CAUSE_DEF) \
|
||||
CAUSE_DEF(Illegal_UE,0x3 )\
|
||||
CAUSE_DEF(PEI_not_accepted,0x5 )\
|
||||
CAUSE_DEF(Illegal_ME,0x6 )\
|
||||
CAUSE_DEF(SGS_services_not_allowed,0x7 )\
|
||||
CAUSE_DEF(UE_identity_cannot_be_derived_by_the_network,0x9 )\
|
||||
CAUSE_DEF(Implicitly_de_registered,0x0a )\
|
||||
CAUSE_DEF(PLMN_not_allowed,0x0b )\
|
||||
CAUSE_DEF(Tracking_area_not_allowed,0x0c )\
|
||||
CAUSE_DEF(Roaming_not_allowed_in_this_tracking_area,0x0d )\
|
||||
CAUSE_DEF(No_suitable_cells_in_tracking_area,0x0f )\
|
||||
CAUSE_DEF(MAC_failure,0x14 )\
|
||||
CAUSE_DEF(Synch_failure,0x15 )\
|
||||
CAUSE_DEF(Congestion,0x16 )\
|
||||
CAUSE_DEF(UE_security_capabilities_mismatch,0x17 )\
|
||||
CAUSE_DEF(Security_mode_rejected_unspecified,0x18 )\
|
||||
CAUSE_DEF(Non_5G_authentication_unacceptable,0x1a )\
|
||||
CAUSE_DEF(N1_mode_not_allowed,0x1b )\
|
||||
CAUSE_DEF(Restricted_service_area,0x1c )\
|
||||
CAUSE_DEF(Redirection_to_EPC_required,0x1f )\
|
||||
CAUSE_DEF(LADN_not_available,0x2b )\
|
||||
CAUSE_DEF(No_network_slices_available,0x3e )\
|
||||
CAUSE_DEF(Maximum_number_of_PDU_sessions_reached,0x41 )\
|
||||
CAUSE_DEF(Insufficient_resources_for_specific_slice_and_DNN,0x43 )\
|
||||
CAUSE_DEF(Insufficient_resources_for_specific_slice,0x45 )\
|
||||
CAUSE_DEF(ngKSI_already_in_use,0x47 )\
|
||||
CAUSE_DEF(Non_3GPP_access_to_5GCN_not_allowed,0x48 )\
|
||||
CAUSE_DEF(Serving_network_not_authorized,0x49 )\
|
||||
CAUSE_DEF(Temporarily_not_authorized_for_this_SNPN,0x4A )\
|
||||
CAUSE_DEF(Permanently_not_authorized_for_this_SNPN,0x4b )\
|
||||
CAUSE_DEF(Not_authorized_for_this_CAG_or_authorized_for_CAG_cells_only,0x4c )\
|
||||
CAUSE_DEF(Wireline_access_area_not_allowed,0x4d )\
|
||||
CAUSE_DEF(Payload_was_not_forwarded,0x5a )\
|
||||
CAUSE_DEF(DNN_not_supported_or_not_subscribed_in_the_slice,0x5b )\
|
||||
CAUSE_DEF(Insufficient_user_plane_resources_for_the_PDU_session,0x5c )\
|
||||
CAUSE_DEF(Semantically_incorrect_message,0x5f )\
|
||||
CAUSE_DEF(Invalid_mandatory_information,0x60 )\
|
||||
CAUSE_DEF(Message_type_non_existent_or_not_implemented,0x61 )\
|
||||
CAUSE_DEF(Message_type_not_compatible_with_the_protocol_state,0x62 )\
|
||||
CAUSE_DEF(Information_element_non_existent_or_not_implemented,0x63 )\
|
||||
CAUSE_DEF(Conditional_IE_error,0x64 )\
|
||||
CAUSE_DEF(Message_not_compatible_with_the_protocol_state,0x65 )\
|
||||
CAUSE_DEF(Protocol_error_unspecified,0x67 )
|
||||
|
||||
/* Map task id to printable name. */
|
||||
|
||||
#define CAUSE_TEXT(LabEl, nUmID) {nUmID, #LabEl},
|
||||
|
||||
static const text_info_t cause_text_info[] = {
|
||||
FOREACH_CAUSE(TO_TEXT)
|
||||
};
|
||||
|
||||
#define CAUSE_ENUM(LabEl, nUmID ) LabEl = nUmID,
|
||||
//! Tasks id of each task
|
||||
typedef enum {
|
||||
FOREACH_CAUSE(TO_ENUM)
|
||||
} cause_id_t;
|
||||
|
||||
//_table_9.11.4.2.1:_5GSM_cause_information_element
|
||||
#define FOREACH_CAUSE_SECU(CAUSE_SECU_DEF) \
|
||||
CAUSE_SECU_DEF(Security_Operator_determined_barring,0x08 )\
|
||||
CAUSE_SECU_DEF(Security_Insufficient_resources,0x1a )\
|
||||
CAUSE_SECU_DEF(Security_Missing_or_unknown_DNN,0x1b )\
|
||||
CAUSE_SECU_DEF(Security_Unknown_PDU_session_type,0x1c )\
|
||||
CAUSE_SECU_DEF(Security_User_authentication_or_authorization_failed,0x1d )\
|
||||
CAUSE_SECU_DEF(Security_Request_rejected_unspecified,0x1f )\
|
||||
CAUSE_SECU_DEF(Security_Service_option_not_supported,0x20 )\
|
||||
CAUSE_SECU_DEF(Security_Requested_service_option_not_subscribed,0x21 )\
|
||||
CAUSE_SECU_DEF(Security_Service_option_temporarily_out_of_order,0x22 )\
|
||||
CAUSE_SECU_DEF(Security_PTI_already_in_use,0x23 )\
|
||||
CAUSE_SECU_DEF(Security_Regular_deactivation,0x24 )\
|
||||
CAUSE_SECU_DEF(Security_Network_failure,0x26 )\
|
||||
CAUSE_SECU_DEF(Security_Reactivation_requested,0x27 )\
|
||||
CAUSE_SECU_DEF(Security_Semantic_error_in_the_TFT_operation,0x29 )\
|
||||
CAUSE_SECU_DEF(Security_Syntactical_error_in_the_TFT_operation,0x2a )\
|
||||
CAUSE_SECU_DEF(Security_Invalid_PDU_session_identity,0x2b )\
|
||||
CAUSE_SECU_DEF(Security_Semantic_errors_in_packet_filter,0x2c )\
|
||||
CAUSE_SECU_DEF(Security_Syntactical_error_in_packet_filter,0x2d )\
|
||||
CAUSE_SECU_DEF(Security_Out_of_LADN_service_area,0x2e )\
|
||||
CAUSE_SECU_DEF(Security_PTI_mismatch,0x2f )\
|
||||
CAUSE_SECU_DEF(Security_PDU_session_type_IPv4_only_allowed,0x32 )\
|
||||
CAUSE_SECU_DEF(Security_PDU_session_type_IPv6_only_allowed,0x33 )\
|
||||
CAUSE_SECU_DEF(Security_PDU_session_does_not_exist,0x36 )\
|
||||
CAUSE_SECU_DEF(Security_PDU_session_type_IPv4v6_only_allowed,0x39 )\
|
||||
CAUSE_SECU_DEF(Security_PDU_session_type_Unstructured_only_allowed,0x3a )\
|
||||
CAUSE_SECU_DEF(Security_PDU_session_type_Ethernet_only_allowed,0x3d )\
|
||||
CAUSE_SECU_DEF(Security_Insufficient_resources_for_specific_slice_and_DNN,0x43 )\
|
||||
CAUSE_SECU_DEF(Security_Not_supported_SSC_mode,0x44 )\
|
||||
CAUSE_SECU_DEF(Security_Insufficient_resources_for_specific_slice,0x45 )\
|
||||
CAUSE_SECU_DEF(Security_Missing_or_unknown_DNN_in_a_slice,0x46 )\
|
||||
CAUSE_SECU_DEF(Security_Invalid_PTI_value,0x51 )\
|
||||
CAUSE_SECU_DEF(Security_Maximum_data_rate_per_UE_for_user_plane_integrity_protection_is_too_low,0x52 )\
|
||||
CAUSE_SECU_DEF(Security_Semantic_error_in_the_QoS_operation,0x53 )\
|
||||
CAUSE_SECU_DEF(Security_Syntactical_error_in_the_QoS_operation,0x54 )\
|
||||
CAUSE_SECU_DEF(Security_Invalid_mapped_EPS_bearer_identity,0x55 )\
|
||||
CAUSE_SECU_DEF(Security_Semantically_incorrect_message,0x5f )\
|
||||
CAUSE_SECU_DEF(Security_Invalid_mandatory_information,0x60 )\
|
||||
CAUSE_SECU_DEF(Security_Message_type_non_existent_or_not_implemented,0x61 )\
|
||||
CAUSE_SECU_DEF(Security_Message_type_not_compatible_with_the_protocol_state,0x62 )\
|
||||
CAUSE_SECU_DEF(Security_Information_element_non_existent_or_not_implemented,0x63 )\
|
||||
CAUSE_SECU_DEF(Security_Conditional_IE_error,0x64 )\
|
||||
CAUSE_SECU_DEF(Security_Message_not_compatible_with_the_protocol_state,0x65 )\
|
||||
CAUSE_SECU_DEF(Security_Protocol_error_unspecified,0x6f )
|
||||
|
||||
static const text_info_t cause_secu_text_info[] = {
|
||||
FOREACH_CAUSE_SECU(TO_TEXT)
|
||||
};
|
||||
|
||||
//! Tasks id of each task
|
||||
typedef enum {
|
||||
FOREACH_CAUSE_SECU(TO_ENUM)
|
||||
} cause_secu_id_t;
|
||||
|
||||
// IEI (information element identifier) are spread in each message definition
|
||||
#define IEI_RAND 0x21
|
||||
#define IEI_AUTN 0x20
|
||||
#define IEI_EAP 0x78
|
||||
#define IEI_AuthenticationResponse 0x2d
|
||||
|
||||
//TS 24.501 sub layer states for UE
|
||||
// for network side, only 5GMMderegistered, 5GMMderegistered_initiated, 5GMMregistered, 5GMMservice_request_initiated are valid
|
||||
typedef enum {
|
||||
SGMMnull,
|
||||
SGMMderegistered,
|
||||
SGMMderegistered_initiated,
|
||||
SGMMregistered,
|
||||
SGMMregistered_initiated,
|
||||
SGMMservice_request_initiated,
|
||||
} SGMM_UE_states;
|
||||
|
||||
typedef struct {
|
||||
Extendedprotocoldiscriminator_t epd:8;
|
||||
Security_header_t sh:8;
|
||||
SGSmobilitymanagementmessages_t mt:8;
|
||||
} SGScommonHeader_t;
|
||||
|
||||
typedef struct {
|
||||
Extendedprotocoldiscriminator_t epd:8;
|
||||
Security_header_t sh:8;
|
||||
SGSmobilitymanagementmessages_t mt:8;
|
||||
identitytype_t it:8;
|
||||
} Identityrequest_t;
|
||||
|
||||
// the message continues with the identity value, depending on identity type, see TS 14.501, 9.11.3.4
|
||||
typedef struct __attribute__((packed)) {
|
||||
Extendedprotocoldiscriminator_t epd:8;
|
||||
Security_header_t sh:8;
|
||||
SGSmobilitymanagementmessages_t mt:8;
|
||||
uint16_t len;
|
||||
}
|
||||
Identityresponse_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
Identityresponse_t common;
|
||||
identitytype_t mi:8;
|
||||
unsigned int supiFormat:4;
|
||||
unsigned int identityType:4;
|
||||
unsigned int mcc1:4;
|
||||
unsigned int mcc2:4;
|
||||
unsigned int mcc3:4;
|
||||
unsigned int mnc3:4;
|
||||
unsigned int mnc1:4;
|
||||
unsigned int mnc2:4;
|
||||
unsigned int routing1:4;
|
||||
unsigned int routing2:4;
|
||||
unsigned int routing3:4;
|
||||
unsigned int routing4:4;
|
||||
unsigned int protectScheme:4;
|
||||
unsigned int spare:4;
|
||||
uint8_t hplmnId;
|
||||
}
|
||||
IdentityresponseIMSI_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
Extendedprotocoldiscriminator_t epd:8;
|
||||
Security_header_t sh:8;
|
||||
SGSmobilitymanagementmessages_t mt:8;
|
||||
unsigned int ngKSI:4;
|
||||
unsigned int spare:4;
|
||||
unsigned int ABBALen:8;
|
||||
unsigned int ABBA:16;
|
||||
uint8_t ieiRAND;
|
||||
uint8_t RAND[16];
|
||||
uint8_t ieiAUTN;
|
||||
uint8_t AUTNlen;
|
||||
uint8_t AUTN[16];
|
||||
}
|
||||
authenticationrequestHeader_t;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
Extendedprotocoldiscriminator_t epd:8;
|
||||
Security_header_t sh:8;
|
||||
SGSmobilitymanagementmessages_t mt:8;
|
||||
uint8_t iei;
|
||||
uint8_t RESlen;
|
||||
uint8_t RES[16];
|
||||
} authenticationresponse_t;
|
||||
|
||||
//AUTHENTICATION RESULT
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
Extendedprotocoldiscriminator_t epd:8;
|
||||
Security_header_t sh:8;
|
||||
SGSmobilitymanagementmessages_t mt:8;
|
||||
|
||||
unsigned int selectedNASsecurityalgorithms;
|
||||
unsigned int ngKSI:4; //ngKSI NAS key set identifier 9.11.3.32
|
||||
unsigned int spare:4;
|
||||
// LV 3-9 bytes Replayed UE security capabilities UE security capability 9.11.3.54
|
||||
|
||||
/* optional
|
||||
TV (E-, 1 byte) Oprional IMEISV request IMEISV request 9.11.3.28
|
||||
TV (57, 2 bytes ) Selected EPS NAS security algorithms EPS NAS security algorithms 9.11.3.25
|
||||
TLV (36, 3 bytes) Additional 5G security information Additional 5G security information 9.11.3.12
|
||||
TLV-E (78,, 7-1503 bytes) EAP message EAP message 9.11.2.2
|
||||
TLV (38, 4-n)ABBA ABBA 9.11.3.10
|
||||
TLV (19, 4-7) Replayed S1 UE security capabilities S1 UE security capability 9.11.3.48A
|
||||
*/
|
||||
|
||||
} securityModeCommand_t;
|
||||
|
||||
typedef struct {
|
||||
uicc_t *uicc;
|
||||
} nr_user_nas_t;
|
||||
|
||||
#define STATIC_ASSERT(test_for_true) _Static_assert((test_for_true), "(" #test_for_true ") failed")
|
||||
#define myCalloc(var, type) type * var=(type*)calloc(sizeof(type),1);
|
||||
#define arrayCpy(tO, FroM) STATIC_ASSERT(sizeof(tO) == sizeof(FroM)) ; memcpy(tO, FroM, sizeof(tO))
|
||||
int resToresStar(uint8_t *msg, uicc_t* uicc);
|
||||
|
||||
int identityResponse(void **msg, nr_user_nas_t *UE);
|
||||
int authenticationResponse(void **msg, nr_user_nas_t *UE);
|
||||
void UEprocessNAS(void *msg,nr_user_nas_t *UE);
|
||||
void SGSabortUE(void *msg, NRUEcontext_t *UE) ;
|
||||
void SGSregistrationReq(void *msg, NRUEcontext_t *UE);
|
||||
void SGSderegistrationUEReq(void *msg, NRUEcontext_t *UE);
|
||||
void SGSauthenticationResp(void *msg, NRUEcontext_t *UE);
|
||||
void SGSidentityResp(void *msg, NRUEcontext_t *UE);
|
||||
void SGSsecurityModeComplete(void *msg, NRUEcontext_t *UE);
|
||||
void SGSregistrationComplete(void *msg, NRUEcontext_t *UE);
|
||||
void processNAS(void *msg, NRUEcontext_t *UE);
|
||||
int identityRequest(void **msg, NRUEcontext_t *UE);
|
||||
int authenticationRequest(void **msg, NRUEcontext_t *UE);
|
||||
int securityModeCommand(void **msg, NRUEcontext_t *UE);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
Adaptatipn of SW from hereafter license
|
||||
Author: laurent.thomas@open-cells.com
|
||||
The OpenAirInterface project uses this copy under the terms of BSD
|
||||
license.
|
||||
*/
|
||||
/*
|
||||
3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208)
|
||||
Copyright (c) 2006-2007 <j@w1.fi>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
Alternatively, this software may be distributed under the terms of BSD
|
||||
license.
|
||||
|
||||
See README and COPYING for more details.
|
||||
|
||||
This file implements an example authentication algorithm defined for 3GPP
|
||||
AKA. This can be used to implement a simple HLR/AuC into hlr_auc_gw to allow
|
||||
EAP-AKA to be tested properly with real USIM cards.
|
||||
|
||||
This implementations assumes that the r1..r5 and c1..c5 constants defined in
|
||||
TS 35.206 are used, i.e., r1=64, r2=0, r3=32, r4=64, r5=96, c1=00..00,
|
||||
c2=00..01, c3=00..02, c4=00..04, c5=00..08. The block cipher is assumed to
|
||||
be AES (Rijndael).
|
||||
*/
|
||||
|
||||
#ifndef MILENAGE_H
|
||||
#define MILENAGE_H
|
||||
#include <openssl/aes.h>
|
||||
|
||||
|
||||
#define u8 uint8_t
|
||||
/**
|
||||
milenage_f1 - Milenage f1 and f1* algorithms
|
||||
@opc: OPc = 128-bit value derived from OP and K
|
||||
@k: K = 128-bit subscriber key
|
||||
@_rand: RAND = 128-bit random challenge
|
||||
@sqn: SQN = 48-bit sequence number
|
||||
@amf: AMF = 16-bit authentication management field
|
||||
@mac_a: Buffer for MAC-A = 64-bit network authentication code, or %NULL
|
||||
@mac_s: Buffer for MAC-S = 64-bit resync authentication code, or %NULL
|
||||
Returns: true on success, false on failure
|
||||
*/
|
||||
|
||||
void aes_128_encrypt_block(const u8* key, const u8* in, u8* out) {
|
||||
AES_KEY k;
|
||||
u8 tmp[16];
|
||||
AES_set_encrypt_key(key, 128, &k);
|
||||
AES_encrypt(in, tmp, &k);
|
||||
memcpy(out, tmp, sizeof(tmp));
|
||||
}
|
||||
static bool milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
|
||||
const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s) {
|
||||
u8 tmp1[16], tmp2[16], tmp3[16];
|
||||
int i;
|
||||
|
||||
/* tmp1 = TEMP = E_K(RAND XOR OP_C) */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp1[i] = _rand[i] ^ opc[i];
|
||||
|
||||
aes_128_encrypt_block(k, tmp1, tmp1);
|
||||
AES_KEY kTab;
|
||||
uint8_t cyphered[16];
|
||||
AES_set_encrypt_key(k, 128, &kTab);
|
||||
AES_encrypt(tmp1, cyphered, &kTab);
|
||||
/* tmp2 = IN1 = SQN || AMF || SQN || AMF */
|
||||
memcpy(tmp2, sqn, 6);
|
||||
memcpy(tmp2 + 6, amf, 2);
|
||||
memcpy(tmp2 + 8, tmp2, 8);
|
||||
|
||||
/* OUT1 = E_K(TEMP XOR rot(IN1 XOR OP_C, r1) XOR c1) XOR OP_C */
|
||||
|
||||
/* rotate (tmp2 XOR OP_C) by r1 (= 0x40 = 8 bytes) */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp3[(i + 8) % 16] = tmp2[i] ^ opc[i];
|
||||
|
||||
/* XOR with TEMP = E_K(RAND XOR OP_C) */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp3[i] ^= tmp1[i];
|
||||
|
||||
/* XOR with c1 (= ..00, i.e., NOP) */
|
||||
/* f1 || f1* = E_K(tmp3) XOR OP_c */
|
||||
aes_128_encrypt_block(k, tmp3, tmp1);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp1[i] ^= opc[i];
|
||||
|
||||
if (mac_a)
|
||||
memcpy(mac_a, tmp1, 8); /* f1 */
|
||||
|
||||
if (mac_s)
|
||||
memcpy(mac_s, tmp1 + 8, 8); /* f1* */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms
|
||||
@opc: OPc = 128-bit value derived from OP and K
|
||||
@k: K = 128-bit subscriber key
|
||||
@_rand: RAND = 128-bit random challenge
|
||||
@res: Buffer for RES = 64-bit signed response (f2), or %NULL
|
||||
@ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
|
||||
@ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
|
||||
@ak: Buffer for AK = 48-bit anonymity key (f5), or %NULL
|
||||
@akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL
|
||||
Returns: true on success, false on failure
|
||||
*/
|
||||
static bool milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
|
||||
u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar) {
|
||||
u8 tmp1[16], tmp2[16], tmp3[16];
|
||||
int i;
|
||||
|
||||
/* tmp2 = TEMP = E_K(RAND XOR OP_C) */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp1[i] = _rand[i] ^ opc[i];
|
||||
|
||||
aes_128_encrypt_block(k, tmp1, tmp2);
|
||||
|
||||
/* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */
|
||||
/* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */
|
||||
/* OUT4 = E_K(rot(TEMP XOR OP_C, r4) XOR c4) XOR OP_C */
|
||||
/* OUT5 = E_K(rot(TEMP XOR OP_C, r5) XOR c5) XOR OP_C */
|
||||
|
||||
/* f2 and f5 */
|
||||
/* rotate by r2 (= 0, i.e., NOP) */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp1[i] = tmp2[i] ^ opc[i];
|
||||
|
||||
tmp1[15] ^= 1; /* XOR c2 (= ..01) */
|
||||
/* f5 || f2 = E_K(tmp1) XOR OP_c */
|
||||
aes_128_encrypt_block(k, tmp1, tmp3);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp3[i] ^= opc[i];
|
||||
|
||||
if (res)
|
||||
memcpy(res, tmp3 + 8, 8); /* f2 */
|
||||
|
||||
if (ak)
|
||||
memcpy(ak, tmp3, 6); /* f5 */
|
||||
|
||||
/* f3 */
|
||||
if (ck) {
|
||||
/* rotate by r3 = 0x20 = 4 bytes */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i];
|
||||
|
||||
tmp1[15] ^= 2; /* XOR c3 (= ..02) */
|
||||
aes_128_encrypt_block(k, tmp1, ck);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
ck[i] ^= opc[i];
|
||||
}
|
||||
|
||||
/* f4 */
|
||||
if (ik) {
|
||||
/* rotate by r4 = 0x40 = 8 bytes */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i];
|
||||
|
||||
tmp1[15] ^= 4; /* XOR c4 (= ..04) */
|
||||
aes_128_encrypt_block(k, tmp1, ik);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
ik[i] ^= opc[i];
|
||||
}
|
||||
|
||||
/* f5* */
|
||||
if (akstar) {
|
||||
/* rotate by r5 = 0x60 = 12 bytes */
|
||||
for (i = 0; i < 16; i++)
|
||||
tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i];
|
||||
|
||||
tmp1[15] ^= 8; /* XOR c5 (= ..08) */
|
||||
aes_128_encrypt_block(k, tmp1, tmp1);
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
akstar[i] = tmp1[i] ^ opc[i];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
milenage_generate - Generate AKA AUTN,IK,CK,RES
|
||||
@opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
|
||||
@amf: AMF = 16-bit authentication management field
|
||||
@k: K = 128-bit subscriber key
|
||||
@sqn: SQN = 48-bit sequence number
|
||||
@_rand: RAND = 128-bit random challenge
|
||||
@autn: Buffer for AUTN = 128-bit authentication token
|
||||
@ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
|
||||
@ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
|
||||
@res: Buffer for RES = 64-bit signed response (f2), or %NULL
|
||||
@res_len: Max length for res; set to used length or 0 on failure
|
||||
*/
|
||||
static bool milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
|
||||
const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik,
|
||||
u8 *ck, u8 *res) {
|
||||
int i;
|
||||
u8 mac_a[8], ak[6];
|
||||
|
||||
if (!milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) ||
|
||||
!milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
|
||||
return false;
|
||||
|
||||
/* AUTN = (SQN ^ AK) || AMF || MAC */
|
||||
for (i = 0; i < 6; i++)
|
||||
autn[i] = sqn[i] ^ ak[i];
|
||||
|
||||
memcpy(autn + 6, amf, 2);
|
||||
memcpy(autn + 8, mac_a, 8);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
milenage_auts - Milenage AUTS validation
|
||||
@opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
|
||||
@k: K = 128-bit subscriber key
|
||||
@_rand: RAND = 128-bit random challenge
|
||||
@auts: AUTS = 112-bit authentication token from client
|
||||
@sqn: Buffer for SQN = 48-bit sequence number
|
||||
Returns: 0 = success (sqn filled), -1 on failure
|
||||
*/
|
||||
#define p(a) printf("%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", (int)((a)[0]), (int)((a)[1]), (int)((a)[2]), (int)((a)[3]),(int)((a)[4]), (int)((a)[5]));
|
||||
// valid code but put in comment as it is not used right now
|
||||
#if 0
|
||||
static bool milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts,
|
||||
u8 *sqn) {
|
||||
u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
|
||||
u8 ak[6], mac_s[8];
|
||||
int i;
|
||||
|
||||
if (!milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
sqn[i] = auts[i] ^ ak[i];
|
||||
|
||||
//p(sqn);
|
||||
if (!milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) ||
|
||||
memcmp(mac_s, auts + 6, 8) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
gsm_milenage - Generate GSM-Milenage (3GPP TS 55.205) authentication triplet
|
||||
@opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
|
||||
@k: K = 128-bit subscriber key
|
||||
@_rand: RAND = 128-bit random challenge
|
||||
@sres: Buffer for SRES = 32-bit SRES
|
||||
@kc: Buffer for Kc = 64-bit Kc
|
||||
Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
static bool gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc) {
|
||||
u8 res[8], ck[16], ik[16];
|
||||
int i;
|
||||
|
||||
if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8];
|
||||
|
||||
#ifdef GSM_MILENAGE_ALT_SRES
|
||||
memcpy(sres, res, 4);
|
||||
#else /* GSM_MILENAGE_ALT_SRES */
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
sres[i] = res[i] ^ res[i + 4];
|
||||
|
||||
#endif /* GSM_MILENAGE_ALT_SRES */
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
milenage_generate - Generate AKA AUTN,IK,CK,RES
|
||||
@opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
|
||||
@k: K = 128-bit subscriber key
|
||||
@sqn: SQN = 48-bit sequence number
|
||||
@_rand: RAND = 128-bit random challenge
|
||||
@autn: AUTN = 128-bit authentication token
|
||||
@ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
|
||||
@ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
|
||||
@res: Buffer for RES = 64-bit signed response (f2), or %NULL
|
||||
@res_len: Variable that will be set to RES length
|
||||
@auts: 112-bit buffer for AUTS
|
||||
Returns: 0 on success, -1 on failure, or -2 on synchronization failure
|
||||
*/
|
||||
static int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
|
||||
const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len,
|
||||
u8 *auts) {
|
||||
int i;
|
||||
u8 mac_a[8], ak[6], rx_sqn[6];
|
||||
const u8 *amf;
|
||||
|
||||
if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
|
||||
return -1;
|
||||
|
||||
*res_len = 8;
|
||||
|
||||
/* AUTN = (SQN ^ AK) || AMF || MAC */
|
||||
for (i = 0; i < 6; i++)
|
||||
rx_sqn[i] = autn[i] ^ ak[i];
|
||||
|
||||
if (memcmp(rx_sqn, sqn, 6) <= 0) {
|
||||
u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
|
||||
|
||||
if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
auts[i] = sqn[i] ^ ak[i];
|
||||
|
||||
if (milenage_f1(opc, k, _rand, sqn, auts_amf, NULL, auts + 6))
|
||||
return -1;
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
amf = autn + 6;
|
||||
|
||||
if (milenage_f1(opc, k, _rand, rx_sqn, amf, mac_a, NULL))
|
||||
return -1;
|
||||
|
||||
if (memcmp(mac_a, autn + 8, 8) != 0) {
|
||||
printf( "Milenage: MAC mismatch\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void milenage_opc_gen(const u8 *k, const u8 *op, u8 *opc) {
|
||||
int i;
|
||||
/* Encrypt OP using K */
|
||||
aes_128_encrypt_block(k, op, opc);
|
||||
|
||||
/* XOR the resulting Ek(OP) with OP */
|
||||
for (i = 0; i < 16; i++)
|
||||
opc[i] = opc[i] ^ op[i];
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.1 (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
|
||||
*
|
||||
* Author and copyright: Laurent Thomas, open-cells.com
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <openair3/NAS/COMMON/NR_NAS_defs.h>
|
||||
#include <openair3/SECU/secu_defs.h>
|
||||
|
||||
void servingNetworkName(uint8_t *msg, char * imsiStr, int nmc_size) {
|
||||
//SNN-network-identifier in TS 24.501
|
||||
// TS 24.501: If the MNC of the serving PLMN has two digits, then a zero is added at the beginning.
|
||||
const char *format="5G:mnc000.mcc000.3gppnetwork.org";
|
||||
memcpy(msg,format, strlen(format));
|
||||
|
||||
if (nmc_size == 2)
|
||||
memcpy(msg+7, imsiStr+3, 2);
|
||||
else
|
||||
memcpy(msg+6, imsiStr+3, 3);
|
||||
|
||||
memcpy(msg+13, imsiStr, 3);
|
||||
}
|
||||
|
||||
int resToresStar(uint8_t *msg, uicc_t* uicc) {
|
||||
// TS 33.220 annex B.2 => FC=0x6B in TS 33.501 annex A.4
|
||||
//input S to KDF
|
||||
uint8_t S[128]= {0};
|
||||
S[0]=0x6B;
|
||||
uint8_t *ptr=S+1;
|
||||
servingNetworkName(ptr, uicc->imsiStr, uicc->nmc_size);
|
||||
*(uint16_t *)(ptr+strlen((char *)ptr))=htons(strlen((char *)ptr));
|
||||
ptr+=strlen((char *)ptr)+sizeof(uint16_t);
|
||||
// add rand
|
||||
memcpy(ptr, uicc->rand, sizeof(uicc->rand) ) ;
|
||||
*(uint16_t *)(ptr+sizeof(uicc->rand))=htons(sizeof(uicc->rand));
|
||||
ptr+=sizeof(uicc->rand)+sizeof(uint16_t);
|
||||
// add res
|
||||
memcpy(ptr, uicc->milenage_res, sizeof(uicc->milenage_res) ) ;
|
||||
*(uint16_t *)(ptr+sizeof(uicc->milenage_res))=htons(sizeof(uicc->milenage_res));
|
||||
ptr+=sizeof(uicc->milenage_res)+sizeof(uint16_t);
|
||||
// S is done
|
||||
uint8_t ckik[sizeof(uicc->ck) +sizeof(uicc->ik)];
|
||||
memcpy(ckik, uicc->ck, sizeof(uicc->ck));
|
||||
memcpy(ckik+sizeof(uicc->ck),uicc->ik, sizeof(uicc->ik));
|
||||
uint8_t out[32];
|
||||
kdf(S, ptr-S, ckik, 32, out, sizeof(out));
|
||||
memcpy(msg, out+16, 16);
|
||||
return 16;
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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.1 (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
|
||||
*
|
||||
* Author and copyright: Laurent Thomas, open-cells.com
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#include <openair3/NAS/COMMON/NR_NAS_defs.h>
|
||||
#include <openair3/SECU/secu_defs.h>
|
||||
|
||||
|
||||
void SGSabortNet(void *msg, nr_user_nas_t *UE) {
|
||||
}
|
||||
|
||||
void ue_nas_schedule(void) {
|
||||
}
|
||||
|
||||
/*
|
||||
*Message reception
|
||||
*/
|
||||
|
||||
void SGSauthenticationReq(void *msg, nr_user_nas_t *UE) {
|
||||
authenticationrequestHeader_t *amsg=(authenticationrequestHeader_t *) msg;
|
||||
arrayCpy(UE->uicc->rand,amsg->RAND);
|
||||
arrayCpy(UE->uicc->autn,amsg->AUTN);
|
||||
// AUTHENTICATION REQUEST message that contains a valid ngKSI, SQN and MAC is received
|
||||
// TBD verify ngKSI (we set it as '2', see gNB code)
|
||||
// SQN and MAC are tested in auth resp processing
|
||||
ue_nas_schedule();
|
||||
}
|
||||
|
||||
void SGSidentityReq(void *msg, nr_user_nas_t *UE) {
|
||||
Identityrequest_t *idmsg=(Identityrequest_t *) msg;
|
||||
|
||||
if (idmsg->it == SUCI ) {
|
||||
LOG_I(NAS,"Received Identity request, scheduling answer\n");
|
||||
ue_nas_schedule();
|
||||
} else
|
||||
LOG_E(NAS,"Not developped: identity request for %d\n", idmsg->it);
|
||||
}
|
||||
|
||||
void SGSsecurityModeCommand(void *msg, nr_user_nas_t *UE) {
|
||||
}
|
||||
|
||||
|
||||
void UEprocessNAS(void *msg,nr_user_nas_t *UE) {
|
||||
SGScommonHeader_t *header=(SGScommonHeader_t *) msg;
|
||||
|
||||
if ( header->sh > 4 )
|
||||
SGSabortNet(msg, UE);
|
||||
else {
|
||||
switch (header->epd) {
|
||||
case SGSmobilitymanagementmessages:
|
||||
LOG_I(NAS,"Received message: %s\n", idStr(message_text_info, header->mt));
|
||||
|
||||
switch (header->mt) {
|
||||
case Authenticationrequest:
|
||||
SGSauthenticationReq(msg, UE);
|
||||
break;
|
||||
|
||||
case Identityrequest:
|
||||
SGSidentityReq(msg, UE);
|
||||
break;
|
||||
|
||||
case Securitymodecommand:
|
||||
SGSsecurityModeCommand(msg, UE);
|
||||
break;
|
||||
|
||||
default:
|
||||
SGSabortNet(msg, UE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SGSsessionmanagementmessages:
|
||||
SGSabortNet(msg, UE);
|
||||
break;
|
||||
|
||||
default:
|
||||
SGSabortNet(msg, UE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Messages emission
|
||||
*/
|
||||
|
||||
int identityResponse(void **msg, nr_user_nas_t *UE) {
|
||||
if (UE->uicc == NULL)
|
||||
// config file section hardcoded as "uicc", nevertheless it opens to manage several UEs or a multi SIM UE
|
||||
UE->uicc=init_uicc("uicc");
|
||||
|
||||
// TS 24.501 9.11.3.4
|
||||
int imsiL=strlen(UE->uicc->imsiStr);
|
||||
int msinL=imsiL-3-UE->uicc->nmc_size;
|
||||
int respSize=sizeof(IdentityresponseIMSI_t) + (msinL+1)/2;
|
||||
IdentityresponseIMSI_t *resp=(IdentityresponseIMSI_t *) calloc(respSize,1);
|
||||
resp->common.epd=SGSmobilitymanagementmessages;
|
||||
resp->common.sh=0;
|
||||
resp->common.mt=Identityresponse;
|
||||
resp->common.len=htons(respSize-sizeof(Identityresponse_t));
|
||||
resp->mi=SUCI;
|
||||
resp->mcc1=UE->uicc->imsiStr[0]-'0';
|
||||
resp->mcc2=UE->uicc->imsiStr[1]-'0';
|
||||
resp->mcc3=UE->uicc->imsiStr[2]-'0';
|
||||
resp->mnc1=UE->uicc->imsiStr[3]-'0';
|
||||
resp->mnc2=UE->uicc->imsiStr[4]-'0';
|
||||
resp->mnc3=UE->uicc->nmc_size==2? 0xF : UE->uicc->imsiStr[3]-'0';
|
||||
// TBD: routing to fill (FF ?)
|
||||
char *out=(char *)(resp+1);
|
||||
char *ptr=UE->uicc->imsiStr + 3 + UE->uicc->nmc_size;
|
||||
|
||||
while ( ptr < UE->uicc->imsiStr+strlen(UE->uicc->imsiStr) ) {
|
||||
*out=((*(ptr+1)-'0')<<4) | (*(ptr) -'0');
|
||||
out++;
|
||||
ptr+=2;
|
||||
}
|
||||
|
||||
if (msinL%2 == 1)
|
||||
*out=((*(ptr-1)-'0')) | 0xF0;
|
||||
|
||||
*msg=resp;
|
||||
return respSize;
|
||||
}
|
||||
|
||||
int authenticationResponse(void **msg,nr_user_nas_t *UE) {
|
||||
if (UE->uicc == NULL)
|
||||
// config file section hardcoded as "uicc", nevertheless it opens to manage several UEs or a multi SIM UE
|
||||
UE->uicc=init_uicc("uicc");
|
||||
|
||||
myCalloc(resp, authenticationresponse_t);
|
||||
resp->epd=SGSmobilitymanagementmessages;
|
||||
resp->sh=0;
|
||||
resp->mt=Authenticationresponse;
|
||||
resp->iei=IEI_AuthenticationResponse;
|
||||
resp->RESlen=sizeof(resp->RES); // always 16 see TS 24.501 Table 8.2.2.1.1
|
||||
// Verify the AUTN
|
||||
// a full implementation need to test several SQN
|
||||
// as the last 5bits can be any value
|
||||
// and the value can also be greater and accepted (if it is in the accepted window)
|
||||
uint8_t AUTN[16];
|
||||
uicc_milenage_generate(AUTN, UE->uicc);
|
||||
|
||||
if ( memcmp(UE->uicc->autn, AUTN, sizeof(AUTN)) == 0 ) {
|
||||
// prepare and send good answer
|
||||
resToresStar(resp->RES,UE->uicc);
|
||||
} else {
|
||||
// prepare and send autn is not compatible with our data
|
||||
abort();
|
||||
}
|
||||
|
||||
*msg=resp;
|
||||
return sizeof(authenticationresponse_t);
|
||||
}
|
||||
|
||||
int securityModeComplete(void **msg, nr_user_nas_t *UE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int registrationComplete(void **msg, nr_user_nas_t *UE) {
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* 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.1 (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
|
||||
*
|
||||
* Author and copyright: Laurent Thomas, open-cells.com
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#include <openair3/NAS/COMMON/NR_NAS_defs.h>
|
||||
|
||||
void SGSabortUE(void *msg, NRUEcontext_t *UE) {
|
||||
}
|
||||
void nas_schedule(void) {
|
||||
}
|
||||
/*
|
||||
*Message reception
|
||||
*/
|
||||
|
||||
void SGSregistrationReq(void *msg, NRUEcontext_t *UE) {
|
||||
}
|
||||
|
||||
void SGSderegistrationUEReq(void *msg, NRUEcontext_t *UE) {
|
||||
}
|
||||
|
||||
void SGSidentityResp(void *msg, NRUEcontext_t *UE) {
|
||||
// use the UE SUPI to load the USIM
|
||||
IdentityresponseIMSI_t *resp=(IdentityresponseIMSI_t *)msg;
|
||||
char configName[100]={0};
|
||||
char * ptr= stpcpy(configName,"uicc");
|
||||
*ptr++=resp->mcc1+'0';
|
||||
*ptr++=resp->mcc2+'0';
|
||||
*ptr++=resp->mcc3+'0';
|
||||
*ptr++=resp->mnc1+'0';
|
||||
*ptr++=resp->mnc2+'0';
|
||||
if ( resp->mnc3 != 0xF )
|
||||
*ptr++=resp->mnc3 +'0';
|
||||
int respSize=ntohs(resp->common.len);
|
||||
int msinByteSize=respSize-sizeof(IdentityresponseIMSI_t);
|
||||
uint8_t * msin=(uint8_t *) (resp+1);
|
||||
for(int i=3 ; i<msinByteSize; i++) {
|
||||
char digit1=(msin[i] >> 4) ;
|
||||
*ptr++=(msin[i] & 0xf) +'0';
|
||||
if (digit1 != 0xf)
|
||||
*ptr++=digit1 +'0';
|
||||
}
|
||||
*ptr=0;
|
||||
if (UE->uicc == NULL)
|
||||
// config file section hardcoded as "uicc", nevertheless it opens to manage several UEs or a multi SIM UE
|
||||
UE->uicc=init_uicc(configName);
|
||||
//We schedule Authentication request
|
||||
nas_schedule();
|
||||
}
|
||||
|
||||
void SGSauthenticationResp(void *msg, NRUEcontext_t *UE) {
|
||||
// Let's check the answer
|
||||
authenticationresponse_t* resp=(authenticationresponse_t*) msg;
|
||||
uint8_t resStarLocal[16];
|
||||
resToresStar(resStarLocal,UE->uicc);
|
||||
if ( memcmp(resStarLocal, resp->RES, sizeof(resStarLocal)) == 0 ) {
|
||||
LOG_I(NAS,"UE answer to authentication resquest is correct\n");
|
||||
// we will send securityModeCommand
|
||||
nas_schedule();
|
||||
} else {
|
||||
LOG_E(NAS,"UE authentication response not good\n");
|
||||
// To be implemented ?
|
||||
}
|
||||
}
|
||||
|
||||
void SGSsecurityModeComplete(void *msg, NRUEcontext_t *UE) {
|
||||
|
||||
}
|
||||
|
||||
void SGSregistrationComplete(void *msg, NRUEcontext_t *UE) {
|
||||
}
|
||||
|
||||
void processNAS(void *msg, NRUEcontext_t *UE) {
|
||||
SGScommonHeader_t *header=(SGScommonHeader_t *) msg;
|
||||
|
||||
if ( header->sh > 4 )
|
||||
SGSabortUE(msg, UE);
|
||||
else {
|
||||
switch (header->epd) {
|
||||
case SGSmobilitymanagementmessages:
|
||||
LOG_I(NAS,"Received message: %s\n", idStr(message_text_info, header->mt));
|
||||
|
||||
switch (header->mt) {
|
||||
case Registrationrequest:
|
||||
SGSregistrationReq(msg, UE);
|
||||
break;
|
||||
|
||||
case DeregistrationrequestUEoriginating:
|
||||
SGSderegistrationUEReq(msg, UE);
|
||||
break;
|
||||
|
||||
case Authenticationresponse:
|
||||
SGSauthenticationResp(msg, UE);
|
||||
break;
|
||||
|
||||
case Identityresponse:
|
||||
SGSidentityResp(msg, UE);
|
||||
break;
|
||||
|
||||
case Securitymodecomplete:
|
||||
SGSsecurityModeComplete(msg, UE);
|
||||
break;
|
||||
|
||||
case Registrationcomplete:
|
||||
SGSregistrationComplete(msg, UE);
|
||||
break;
|
||||
|
||||
default:
|
||||
SGSabortUE(msg, UE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SGSsessionmanagementmessages:
|
||||
SGSabortUE(msg, UE);
|
||||
break;
|
||||
|
||||
default:
|
||||
SGSabortUE(msg, UE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Messages emission
|
||||
*/
|
||||
|
||||
int identityRequest(void **msg, NRUEcontext_t *UE) {
|
||||
myCalloc(req, Identityrequest_t);
|
||||
req->epd=SGSmobilitymanagementmessages;
|
||||
req->sh=0;
|
||||
req->mt=Identityrequest;
|
||||
req->it=SUCI;
|
||||
*msg=req;
|
||||
return sizeof(Identityrequest_t);
|
||||
}
|
||||
|
||||
int authenticationRequest(void **msg, NRUEcontext_t *UE) {
|
||||
|
||||
myCalloc(req, authenticationrequestHeader_t);
|
||||
req->epd=SGSmobilitymanagementmessages;
|
||||
req->sh=0;
|
||||
req->mt=Authenticationrequest;
|
||||
// native security context => bit 4 to 0
|
||||
// probably from TS 33.501, table A-8.1
|
||||
// N-NAS-int-alg (Native NAS integrity)
|
||||
/*
|
||||
N-NAS-enc-alg 0x01
|
||||
N-NAS-int-alg 0x02
|
||||
N-RRC-enc-alg 0x03
|
||||
N-RRC-int-alg 0x04
|
||||
N-UP-enc-alg 0x05
|
||||
N-UP-int-alg 0x06
|
||||
*/
|
||||
req->ngKSI=2;
|
||||
// TS 33.501, Annex A.7.1: Initial set of security features defined for 5GS.
|
||||
req->ABBALen=2;
|
||||
req->ABBA=0;
|
||||
//rand (TV)
|
||||
req->ieiRAND=IEI_RAND;
|
||||
FILE *h=fopen("/dev/random","r");
|
||||
|
||||
if ( sizeof(req->RAND) != fread(req->RAND,1,sizeof(req->RAND),h) )
|
||||
LOG_E(NAS, "can't read /dev/random\n");
|
||||
|
||||
fclose(h);
|
||||
memcpy(UE->uicc->rand, req->RAND, sizeof(UE->uicc->rand));
|
||||
// challenge/AUTN (TLV)
|
||||
req->ieiAUTN=IEI_AUTN;
|
||||
req->AUTNlen=sizeof(req->AUTN);
|
||||
uicc_milenage_generate( req->AUTN, UE->uicc);
|
||||
// EAP message (TLV-E)
|
||||
// not developped
|
||||
*msg=req;
|
||||
return sizeof(authenticationrequestHeader_t);
|
||||
}
|
||||
|
||||
int securityModeCommand(void **msg, NRUEcontext_t *UE) {
|
||||
*msg=NULL;
|
||||
myCalloc(req, securityModeCommand_t);
|
||||
req->epd=SGSmobilitymanagementmessages;
|
||||
req->sh=0;
|
||||
req->mt=Securitymodecommand;
|
||||
|
||||
// integrity algo from 5G-IA0 (null algo) to 5G-IA7 in first 4 bits
|
||||
unsigned int ia=0;
|
||||
// cyphering algo from 5G-EA0 (null algo) to 5G-IA7 in MSB 4 bits
|
||||
unsigned int ea=0;
|
||||
// trace from commercial: 5G-IA0 (0) 128-5G-IA2 (2)
|
||||
req->selectedNASsecurityalgorithms= ea<<4 | ia;
|
||||
|
||||
// KSI: N-NAS-int-alg 0x02
|
||||
req->ngKSI=2;
|
||||
|
||||
*msg=req;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#include <common/config/config_userapi.h>
|
||||
#include <openair3/NAS/COMMON/NR_NAS_defs.h>
|
||||
|
||||
volatile int oai_exit;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == NULL) {
|
||||
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
|
||||
}
|
||||
|
||||
logInit();
|
||||
char *resp;
|
||||
nr_user_nas_t UErrc= {0};
|
||||
NRUEcontext_t UEnas= {0};
|
||||
// Network generate identity request after a sucessfull radio attach
|
||||
int size=identityRequest((void **)&resp, &UEnas);
|
||||
log_dump(NAS, resp, size, LOG_DUMP_CHAR," identity Request:\n" );
|
||||
// UE process the message that it has received from phy layer in a "DL transfer" message
|
||||
UEprocessNAS(resp, &UErrc);
|
||||
// UE Scheduler should later call the response
|
||||
size=identityResponse((void **)&resp, &UErrc);
|
||||
log_dump(NAS, resp, size, LOG_DUMP_CHAR," identity Response:\n" );
|
||||
// Now the gNB process the identity response
|
||||
processNAS(resp, &UEnas);
|
||||
// gNB scheduler should call the next query
|
||||
size=authenticationRequest((void **)&resp, &UEnas);
|
||||
log_dump(NAS, resp, size, LOG_DUMP_CHAR," authentication request:\n" );
|
||||
// as above
|
||||
UEprocessNAS(resp, &UErrc);
|
||||
size=authenticationResponse((void **)&resp, &UErrc);
|
||||
log_dump(NAS, resp, size, LOG_DUMP_CHAR," authentication response:\n" );
|
||||
processNAS(resp, &UEnas);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.1 (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
|
||||
*
|
||||
* Author and copyright: Laurent Thomas, open-cells.com
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <openair3/UICC/usim_interface.h>
|
||||
#include <openair3/NAS/COMMON/milenage.h>
|
||||
|
||||
#define UICC_SECTION "uicc"
|
||||
#define UICC_CONFIG_HELP_OPTIONS " list of comma separated options to interface a simulated (real UICC to be developped). Available options: \n"\
|
||||
" imsi: user imsi\n"\
|
||||
" key: cyphering key\n"\
|
||||
" opc: cyphering OPc\n"
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* configuration parameters for the rfsimulator device */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define UICC_PARAMS_DESC {\
|
||||
{"imsi", "USIM IMSI\n", 0, strptr:&(uicc->imsiStr), defstrval:"", TYPE_STRING, 0 },\
|
||||
{"nmc_size" "number of digits in NMC", 0, iptr:&(uicc->nmc_size), defintval:2, TYPE_INT, 0 },\
|
||||
{"key", "USIM Ki\n", 0, strptr:&(uicc->keyStr), defstrval:"", TYPE_STRING, 0 },\
|
||||
{"opc", "USIM OPc\n", 0, strptr:&(uicc->opcStr), defstrval:"", TYPE_STRING, 0 },\
|
||||
{"amf", "USIM amf\n", 0, strptr:&(uicc->amfStr), defstrval:"8000", TYPE_STRING, 0 },\
|
||||
{"sqn", "USIM sqn\n", 0, strptr:&(uicc->sqnStr), defstrval:"000000", TYPE_STRING, 0 },\
|
||||
};
|
||||
|
||||
const char *hexTable="0123456789abcdef";
|
||||
static inline uint8_t mkDigit(unsigned char in) {
|
||||
for (int i=0; i<16; i++)
|
||||
if (in==hexTable[i])
|
||||
return i;
|
||||
LOG_E(SIM,"Impossible hexa input: %c\n",in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void to_hex(char *in, uint8_t *out, int size) {
|
||||
for (size_t i=0; in[i]!=0 && i < size*2 ; i+=2) {
|
||||
*out++=(mkDigit(in[i]) << 4) | mkDigit(in[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
uicc_t *init_uicc(char *sectionName) {
|
||||
uicc_t *uicc=(uicc_t *)calloc(sizeof(uicc_t),1);
|
||||
paramdef_t uicc_params[] = UICC_PARAMS_DESC;
|
||||
// here we call usim simulation, but calling actual usim is quite simple
|
||||
// the code is in open-cells.com => program_uicc open source
|
||||
// we can read the IMSI from the USIM
|
||||
// key, OPc, sqn, amf don't need to be read from the true USIM
|
||||
int ret = config_get( uicc_params,sizeof(uicc_params)/sizeof(paramdef_t),sectionName);
|
||||
AssertFatal(ret >= 0, "configuration couldn't be performed");
|
||||
LOG_I(SIM, "UICC simulation: IMSI=%s, Ki=%s, OPc=%s\n", uicc->imsiStr, uicc->keyStr, uicc->opcStr);
|
||||
to_hex(uicc->keyStr,uicc->key, sizeof(uicc->key) );
|
||||
to_hex(uicc->opcStr,uicc->opc, sizeof(uicc->opc) );
|
||||
to_hex(uicc->sqnStr,uicc->sqn, sizeof(uicc->sqn) );
|
||||
to_hex(uicc->amfStr,uicc->amf, sizeof(uicc->amf) );
|
||||
return uicc;
|
||||
}
|
||||
|
||||
void uicc_milenage_generate(uint8_t *autn, uicc_t *uicc) {
|
||||
// here we call usim simulation, but calling actual usim is quite simple
|
||||
// the code is in open-cells.com => program_uicc open source
|
||||
milenage_generate(uicc->opc, uicc->amf, uicc->key,
|
||||
uicc->sqn, uicc->rand, autn, uicc->ik, uicc->ck, uicc->milenage_res);
|
||||
log_dump(SIM,uicc->opc,sizeof(uicc->opc), LOG_DUMP_CHAR,"opc:");
|
||||
log_dump(SIM,uicc->amf,sizeof(uicc->amf), LOG_DUMP_CHAR,"amf:");
|
||||
log_dump(SIM,uicc->key,sizeof(uicc->key), LOG_DUMP_CHAR,"key:");
|
||||
log_dump(SIM,uicc->sqn,sizeof(uicc->sqn), LOG_DUMP_CHAR,"sqn:");
|
||||
log_dump(SIM,uicc->rand,sizeof(uicc->rand), LOG_DUMP_CHAR,"rand:");
|
||||
log_dump(SIM,uicc->ik,sizeof(uicc->ik), LOG_DUMP_CHAR,"milenage output ik:");
|
||||
log_dump(SIM,uicc->ck,sizeof(uicc->ck), LOG_DUMP_CHAR,"milenage output ck:");
|
||||
log_dump(SIM,uicc->milenage_res,sizeof(uicc->milenage_res), LOG_DUMP_CHAR,"milenage output res:");
|
||||
log_dump(SIM,autn,sizeof(autn), LOG_DUMP_CHAR,"milenage output autn:");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.1 (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
|
||||
*
|
||||
* Author and copyright: Laurent Thomas, open-cells.comopenair3/UICC/usim_interface.h
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#ifndef USIM_INTERFACE_H
|
||||
#define USIM_INTERFACE_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <common/utils/assertions.h>
|
||||
#include <common/utils/LOG/log.h>
|
||||
#include <common/utils/load_module_shlib.h>
|
||||
#include <common/config/config_userapi.h>
|
||||
#include "common_lib.h"
|
||||
|
||||
/* 3GPP glossary
|
||||
RES RESponse
|
||||
XRES eXpected RESponse
|
||||
HRES Hash RESponse
|
||||
HXRES Hash eXpected RESponse
|
||||
So, RES can be either milenage res, or received response, so hash of milenage res
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char *imsiStr;
|
||||
char *keyStr;
|
||||
char *opcStr;
|
||||
char *amfStr;
|
||||
char *sqnStr;
|
||||
uint8_t key[16];
|
||||
uint8_t opc[16];
|
||||
uint8_t amf[2];
|
||||
uint8_t sqn[6];
|
||||
int nmc_size;
|
||||
uint8_t rand[16];
|
||||
uint8_t autn[16];
|
||||
uint8_t ak[6];
|
||||
uint8_t akstar[6];
|
||||
uint8_t ck[16];
|
||||
uint8_t ik[16];
|
||||
uint8_t milenage_res[8];
|
||||
} uicc_t;
|
||||
|
||||
/*
|
||||
* Read the configuration file, section name variable to be able to manage several UICC
|
||||
*/
|
||||
uicc_t *init_uicc(char *sectionName);
|
||||
void uicc_milenage_generate(uint8_t * autn, uicc_t *uicc);
|
||||
#endif
|
||||
Reference in New Issue
Block a user