So as stated before, the eNB emulator has to implement S1AP and S1-U interfaces, and in case we are using a real HSS/AuC, we need also to handle the authentication and key derivation.
root@ubuntu:/home/fabricio/Documents# lsusb | grep ZTE
Bus 002 Device 000: ID 19d2:2000 ZTE WCDMA Technologies MSM MF627/MF628/MF628+/MF636+ HSDPA/HSUPA
root@ubuntu:/home/fabricio/Documents# more /lib/systemd/system/ModemManager.service
[Unit]
Description=Modem Manager
After=polkit.service
Requires=polkit.service
[Service]
Type=dbus
BusName=org.freedesktop.ModemManager1
ExecStart=/usr/sbin/ModemManager --filter-policy=default
StandardError=null
Restart=on-abort
CapabilityBoundingSet=CAP_SYS_ADMIN
ProtectSystem=true
ProtectHome=true
PrivateTmp=true
RestrictAddressFamilies=AF_NETLINK AF_UNIX
NoNewPrivileges=true
User=root
[Install]
WantedBy=multi-user.target
Alias=dbus-org.freedesktop.ModemManager1.service
root@ubuntu:/home/fabricio/Documents# more /etc/udev/rules.d/99zte.rules
ATTRS{idVendor}=="19d2" ATTRS{idProduct}=="0001", ENV{ID_MM_DEVICE_IGNORE}="1"
ATTRS{idVendor}=="19d2" ATTRS{idProduct}=="2000", ENV{ID_MM_DEVICE_IGNORE}="1"
root@ubuntu:/home/fabricio/Documents# udevadm control --reload-rules
from pycrate_asn1dir import S1AP
from pycrate_asn1rt.utils import *
from CryptoMobile.CM import *
from Crypto.Hash import HMAC
from Crypto.Hash import SHA256
import serial
- SCTP (IETF RFC 4960 [5]) shall be supported as the transport layer of S1-MME signalling bearer. The Payload Protocol Identifier assigned by IANA to be used by SCTP for the application layer protocol S1AP is 18.
-
There shall be only one SCTP association established between one MME and eNB pair.
The eNB shall establish the SCTP association. The SCTP Destination Port number value assigned by IANA to be used for S1AP is 36412.
Within the SCTP association established between one MME and eNB pair:
- a single pair of stream identifiers shall be reserved for the sole use of S1AP elementary procedures that utilize non UE-associated signalling.
- At least one pair of stream identifiers shall be reserved for the sole use of S1AP elementary procedures that utilize UE-associated signallings. However a few pairs (i.e. more than one) should be reserved.
- A single UE-associated signalling shall use one SCTP stream and the stream should not be changed during the communication of the UE-associated signalling.
import socket def main(): server_address = ('1.1.1.1', 36412) client = socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.IPPROTO_SCTP) client.bind(('2.2.2.2', 0)) sctp_default_send_param = bytearray(client.getsockopt(132,10,32)) sctp_default_send_param[11]= 18 client.setsockopt(132, 10, sctp_default_send_param) client.connect(server_address)
PDU = S1AP.S1AP_PDU_Descriptions.S1AP_PDU
def set_stream(client, stream): sctp_default_send_param = bytearray(client.getsockopt(132,10,32)) sctp_default_send_param[0]= stream client.setsockopt(132, 10, sctp_default_send_param) return client
def session_dict_initialization(session_dict):
session_dict['STATE'] = 0
session_dict['ENB-UE-S1AP-ID'] = 1000
session_dict['ENB-NAME'] = 'Fabricio-eNB'
session_dict['ENB-PLMN'] = return_plmn(PLMN)
session_dict['XRES'] = b'xresxres'
session_dict['KASME'] = b'kasme kasme kasme kasme '
# hex: 6b61736d652020206b61736d652020206b61736d652020206b61736d65202020
session_dict['ENB-GTP-ADDRESS-INT'] = ''
session_dict['RAB-ID'] = []
session_dict['SGW-GTP-ADDRESS'] = []
session_dict['SGW-TEID'] = []
session_dict['EPS-BEARER-IDENTITY'] = []
session_dict['EPS-BEARER-TYPE'] = [] # default 0, dedicated 1
session_dict['EPS-BEARER-STATE'] = [] # active 1, inactive 0
session_dict['EPS-BEARER-APN'] = []
session_dict['PDN-ADDRESS'] = []
session_dict['PDN-ADDRESS-IPV4'] = None
session_dict['PDN-ADDRESS-IPV6'] = None
session_dict['ENB-TAC'] = b'\x00\x01'
session_dict['ENB-TAC-NBIOT'] = b'\x00\x02'
session_dict['ENB-ID'] = 1
session_dict['ENB-CELLID'] = 1000000
session_dict['NAS-KEY-EEA1'] = return_key(session_dict['KASME'],1,'NAS-ENC')
session_dict['NAS-KEY-EEA2'] = return_key(session_dict['KASME'],2,'NAS-ENC')
session_dict['NAS-KEY-EEA3'] = return_key(session_dict['KASME'],3,'NAS-ENC')
session_dict['NAS-KEY-EIA1'] = return_key(session_dict['KASME'],1,'NAS-INT')
session_dict['NAS-KEY-EIA2'] = return_key(session_dict['KASME'],2,'NAS-INT')
session_dict['NAS-KEY-EIA3'] = return_key(session_dict['KASME'],3,'NAS-INT')
session_dict['UP-COUNT'] = -1
session_dict['DOWN-COUNT'] = -1
session_dict['ENC-ALG'] = 0
session_dict['INT-ALG'] = 0
session_dict['ENC-KEY'] = None
session_dict['INT-KEY'] = None
session_dict['APN'] = APN
session_dict['NAS-SMS-MT'] = None
if session_dict['LOCAL_KEYS'] == True:
if session_dict['IMSI'] == None:
session_dict['IMSI'] = IMSI
else:
if session_dict['IMSI'] == None:
try:
session_dict['IMSI'] = get_imsi(session_dict['SERIAL-INTERFACE'])
except:
session_dict['LOCAL_KEYS'] = True
session_dict['IMSI'] = IMSI
if session_dict['IMEISV'] == None:
session_dict['IMEISV'] = IMEISV
session_dict['ENCODED-IMSI'] = eNAS.encode_imsi(session_dict['IMSI'])
session_dict['ENCODED-IMEI'] = eNAS.encode_imei(IMEISV)
session_dict['ENCODED-GUTI'] = eNAS.encode_guti(12345,32769,1,12345678)
session_dict['S-TMSI'] = None
session_dict['TMSI'] = None
session_dict['LAI'] = None
session_dict['CPSR-TYPE'] = 0
session_dict['S1-TYPE'] = "4G"
session_dict['MOBILE-IDENTITY'] = session_dict['ENCODED-IMSI']
session_dict['MOBILE-IDENTITY-TYPE'] = "IMSI"
session_dict['SESSION-SESSION-TYPE'] = None
session_dict['SESSION-TYPE'] = "4G"
session_dict['SESSION-TYPE-TUN'] = 1
session_dict['PDP-TYPE'] = 1
session_dict['ATTACH-PDN'] = None
session_dict['ATTACH-TYPE'] = 1
session_dict['TAU-TYPE'] = 0
session_dict['SMS-UPDATE-TYPE'] = False
session_dict['NBIOT-SESSION-TYPE'] = "NONE"
session_dict['CPSR-TYPE'] = 0
session_dict['UECONTEXTRELEASE-CSFB'] = False
session_dict['PROCESS-PAGING'] = True
session_dict['LOG'] = []
return session_dict
def S1SetupRequest(dic):
IEs = []
IEs.append({'id': 59, 'value': ('Global-ENB-ID', {'pLMNidentity': dic['ENB-PLMN'], 'eNB-ID' : ('macroENB-ID', (dic['ENB-ID'], 20))}), 'criticality': 'reject'})
IEs.append({'id': 60, 'value': ('ENBname', dic['ENB-NAME']), 'criticality': 'ignore'})
if dic['S1-TYPE'] == "4G" :
IEs.append({'id': 64, 'value': ('SupportedTAs', [{'tAC': dic['ENB-TAC'], 'broadcastPLMNs': [dic['ENB-PLMN']]}]), 'criticality': 'reject'})
elif dic['S1-TYPE'] == "NBIOT":
IEs.append({'id': 64, 'value': ('SupportedTAs', [{'tAC': dic['ENB-TAC-NBIOT'], 'broadcastPLMNs': [dic['ENB-PLMN']], 'iE-Extensions': [{'id':232, 'criticality': 'reject', 'extensionValue':('RAT-Type','nbiot')}]}]), 'criticality': 'reject'})
elif dic['S1-TYPE'] == "BOTH":
IEs.append({'id': 64, 'value': ('SupportedTAs', [{'tAC': dic['ENB-TAC'], 'broadcastPLMNs': [dic['ENB-PLMN']]}, {'tAC': dic['ENB-TAC-NBIOT'], 'broadcastPLMNs': [dic['ENB-PLMN']], 'iE-Extensions': [{'id':232, 'criticality': 'reject', 'extensionValue':('RAT-Type','nbiot')}]}]), 'criticality': 'reject'})
IEs.append({'id': 137, 'value': ('PagingDRX', 'v128'), 'criticality': 'ignore'})
if dic['S1-TYPE'] == "NBIOT" or dic['S1-TYPE'] == "BOTH":
IEs.append({'id': 234, 'value': ('NB-IoT-DefaultPagingDRX', 'v256'), 'criticality': 'ignore'})
val = ('initiatingMessage', {'procedureCode': 17, 'value': ('S1SetupRequest', {'protocolIEs': IEs}), 'criticality': 'ignore'})
dic = eMENU.print_log(dic, "S1AP: sending S1SetupRequest")
return val
PDU.set_val(S1SetupRequest(session_dict)) message = PDU.to_aper() client = set_stream(client, 0) bytes_sent = client.send(message)