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:
masayuki.harada
2020-11-16 13:59:33 +09:00
101 changed files with 6634 additions and 2623 deletions
+391
View File
@@ -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
+355
View File
@@ -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
+66
View File
@@ -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;
}
+178
View File
@@ -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;
}
+214
View File
@@ -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;
}
+34
View File
@@ -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;
}
+92
View File
@@ -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:");
}
+71
View File
@@ -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