pycrate/pycrate_mobile/TS24301_EMM.py

1059 lines
40 KiB
Python

# -*- coding: UTF-8 -*-
#/**
# * Software Name : pycrate
# * Version : 0.4
# *
# * Copyright 2017. Benoit Michau. ANSSI.
# * Copyright 2019. Benoit Michau. P1Sec.
# *
# * This library is free software; you can redistribute it and/or
# * modify it under the terms of the GNU Lesser General Public
# * License as published by the Free Software Foundation; either
# * version 2.1 of the License, or (at your option) any later version.
# *
# * This library is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# * Lesser General Public License for more details.
# *
# * You should have received a copy of the GNU Lesser General Public
# * License along with this library; if not, write to the Free Software
# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# * MA 02110-1301 USA
# *
# *--------------------------------------------------------
# * File Name : pycrate_mobile/TS24301_EMM.py
# * Created : 2017-10-27
# * Authors : Benoit Michau
# *--------------------------------------------------------
#*/
__all__ = [
'EMMAttachAccept',
'EMMAttachComplete',
'EMMAttachReject',
'EMMAttachRequest',
'EMMAuthenticationFailure',
'EMMAuthenticationReject',
'EMMAuthenticationRequest',
'EMMAuthenticationResponse',
'EMMCPServiceRequest',
'EMMCSServiceNotification',
'EMMDetachAccept',
'EMMDetachRequestMO',
'EMMDetachRequestMT',
'EMMDLGenericNASTransport',
'EMMDLNASTransport',
'EMMExtServiceRequest',
'EMMGUTIReallocCommand',
'EMMGUTIReallocComplete',
'EMMIdentityRequest',
'EMMIdentityResponse',
'EMMInformation',
'EMMSecurityModeCommand',
'EMMSecurityModeComplete',
'EMMSecurityModeReject',
'EMMServiceAccept',
'EMMServiceReject',
'EMMStatus',
'EMMTrackingAreaUpdateAccept',
'EMMTrackingAreaUpdateComplete',
'EMMTrackingAreaUpdateReject',
'EMMTrackingAreaUpdateRequest',
'EMMULGenericNASTransport',
'EMMULNASTransport',
#
'EMMTypeMOClasses',
'EMMTypeMTClasses',
'get_emm_msg_mo_instances',
'get_emm_msg_mt_instances',
]
#------------------------------------------------------------------------------#
# 3GPP TS 24.301: NAS protocol for EPS
# release 13 (g51)
#------------------------------------------------------------------------------#
from pycrate_core.utils import *
from pycrate_core.elt import *
from pycrate_core.base import *
from .TS24007 import *
from .TS24008_IE import *
from .TS24301_IE import *
from .TS24501_IE import (
UERadioCapID, UERadioCapIDDelInd, UEStatus,
)
from .TS24301_ESM import ESMTypeClasses
try:
from CryptoMobile import CM
except:
_with_cm = False
log('warning: CryptoMobile Python module not found, unable to handle LTE NAS security')
else:
_with_cm = True
if hasattr(CM, 'EEA2'):
_EIA = {
1 : CM.EIA1,
2 : CM.EIA2,
3 : CM.EIA3
}
_EEA = {
1 : CM.EEA1,
2 : CM.EEA2,
3 : CM.EEA3
}
else:
_EIA = {
1 : CM.EIA1,
3 : CM.EIA3
}
_EEA = {
1 : CM.EEA1,
3 : CM.EEA3
}
#------------------------------------------------------------------------------#
# EPS Mobility Management header
# TS 24.301, section 9
#------------------------------------------------------------------------------#
# section 9.8
_EMM_dict = {
# attach / detach
65 : "Attach request",
66 : "Attach accept",
67 : "Attach complete",
68 : "Attach reject",
69 : "Detach request",
70 : "Detach accept",
# TAU
72 : "Tracking area update request",
73 : "Tracking area update accept",
74 : "Tracking area update complete",
75 : "Tracking area update reject",
# serv request
76 : "Extended service request",
77 : "Control plane service request",
78 : "Service reject",
79 : "Service accept",
# identification / authentication
80 : "GUTI reallocation command",
81 : "GUTI reallocation complete",
82 : "Authentication request",
83 : "Authentication response",
84 : "Authentication reject",
92 : "Authentication failure",
85 : "Identity request",
86 : "Identity response",
93 : "Security mode command",
94 : "Security mode complete",
95 : "Security mode reject",
# misc
96 : "EMM status",
97 : "EMM information",
98 : "Downlink NAS transport",
99 : "Uplink NAS transport",
100 : "CS Service notification",
104 : "Downlink generic NAS transport",
105 : "Uplink generic NAS transport"
}
class EMMHeader(Envelope):
_GEN = (
Uint('SecHdr', bl=4, dic=SecHdrType_dict),
Uint('ProtDisc', val=7, bl=4, dic=ProtDisc_dict),
Uint8('Type', val=96, dic=_EMM_dict)
)
class EMMHeaderSec(Envelope):
_GEN = (
Uint('SecHdr', val=1, bl=4, dic=SecHdrType_dict),
Uint('ProtDisc', val=7, bl=4, dic=ProtDisc_dict),
)
class EMMHeaderServ(Envelope):
_GEN = (
Uint('SecHdr', val=1, bl=4, dic=SecHdrType_dict),
Uint('ProtDisc', val=7, bl=4, dic=ProtDisc_dict),
Uint8('Type', val=0, trans=True)
)
#------------------------------------------------------------------------------#
# Attach accept
# TS 24.301, section 8.2.1
#------------------------------------------------------------------------------#
class EMMAttachAccept(Layer3E):
_GEN = (
EMMHeader(val={'Type':66}),
Uint('spare', bl=4),
Type1V('EPSAttachResult', dic=EPSAttRes_dict),
Type3V('T3412', val={'V':b'\0'}, bl={'V':8}, IE=GPRSTimer()),
Type4LV('TAIList', val={'V':6*b'\0'}, IE=TAIList()),
Type6LVE('ESMContainer', val={'V':b'\0\0\0'}),
Type4TLV('GUTI', val={'T':0x50, 'V':b'\xf6'+10*b'\0'}, IE=EPSID()),
Type3TV('LAI', val={'T':0x13, 'V':5*b'\0'}, bl={'V':40}, IE=LAI()),
Type4TLV('ID', val={'T':0x23, 'V':b'\xf4\0\0\0\0'}, IE=ID()),
Type3TV('EMMCause', val={'T':0x53, 'V':b'\0'}, bl={'V':8}, IE=EMMCause()),
Type3TV('T3402', val={'T':0x17, 'V':b'\0'}, bl={'V':8}, IE=GPRSTimer()),
Type3TV('T3423', val={'T':0x59, 'V':b'\0'}, bl={'V':8}, IE=GPRSTimer()),
Type4TLV('EquivPLMNList', val={'T':0x4A, 'V':3*b'\0'}, IE=PLMNList()),
Type4TLV('EmergNumList', val={'T':0x34, 'V':b'\x02\x01\0'}, IE=EmergNumList()),
Type4TLV('EPSNetFeat', val={'T':0x64, 'V':b'\0\0'}, IE=EPSNetFeat()),
Type1TV('AddUpdateRes', val={'T':0xF, 'V':0}, IE=AddUpdateRes()),
Type4TLV('T3412Ext', val={'T':0x5E, 'V':b'\0'}, IE=GPRSTimer3()),
Type4TLV('T3324', val={'T':0x6A, 'V':b'\0'}, IE=GPRSTimer()),
Type4TLV('ExtDRXParam', val={'T':0x6E, 'V':b'\0'}, IE=ExtDRXParam()),
Type1TV('SMSServStat', val={'T':0xE, 'V':0}, IE=SMSServStat()),
Type1TV('Non3GPPNWProvPol', val={'T':0xD, 'V':0}, IE=Non3GPPNWProvPol()),
Type4TLV('T3448', val={'T':0x6B, 'V':b'\0'}, IE=GPRSTimer()),
Type1TV('NetworkPol', val={'T':0xC, 'V':0}, IE=NetworkPol()),
Type4TLV('T3447', val={'T':0x6C, 'V':b'\0'}, IE=GPRSTimer3()),
Type6TLVE('ExtEmergNumList', val={'T':0x7A, 'V':b'\0\0\0\0'}, IE=ExtEmergNumList()),
Type6TLVE('CipherKeyData', val={'T':0x7C, 'V':32*b'\0'}, IE=CipherKeyData()),
Type4TLV('UERadioCapID', val={'T':0x66, 'V':b'\0'}, IE=UERadioCapID()),
Type1TV('UERadioCapIDDelInd', val={'T':0xB, 'V':0}, IE=UERadioCapIDDelInd()),
)
#------------------------------------------------------------------------------#
# Attach complete
# TS 24.301, section 8.2.2
#------------------------------------------------------------------------------#
class EMMAttachComplete(Layer3E):
_GEN = (
EMMHeader(val={'Type':67}),
Type6LVE('ESMContainer', val={'V':b'\0\0\0'}),
)
#------------------------------------------------------------------------------#
# Attach reject
# TS 24.301, section 8.2.3
#------------------------------------------------------------------------------#
class EMMAttachReject(Layer3E):
_GEN = (
EMMHeader(val={'Type':68}),
Type3V('EMMCause', val={'V':b'\x11'}, bl={'V':8}, IE=EMMCause()),
Type6TLVE('ESMContainer', val={'T':0x78, 'V':b'\0\0\0'}),
Type4TLV('T3346', val={'T':0x5F, 'V':b'\0'}, IE=GPRSTimer()),
Type4TLV('T3402', val={'T':0x16, 'V':b'\0'}, IE=GPRSTimer()),
Type1TV('ExtEMMCause', val={'T':0xA, 'V':0}, IE=ExtEMMCause())
)
#------------------------------------------------------------------------------#
# Attach request
# TS 24.301, section 8.2.4
#------------------------------------------------------------------------------#
class EMMAttachRequest(Layer3E):
_GEN = (
EMMHeader(val={'Type':65}),
Type1V('NAS_KSI', val={'V':7}, IE=NAS_KSI()),
Type1V('EPSAttachType', dic=EPSAttType_dict),
Type4LV('EPSID', val={'V':b'\xf6'+10*b'\0'}, IE=EPSID()),
Type4LV('UENetCap', val={'V':b'\0\0'}, IE=UENetCap()),
Type6LVE('ESMContainer', val={'V':b'\0\0\0'}),
Type3TV('OldPTMSISign', val={'T':0x19, 'V':b'\0\0\0'}, bl={'V':24}),
Type4TLV('AddGUTI', val={'T':0x50, 'V':b'\xf6'+10*b'\0'}, IE=EPSID()),
Type3TV('OldTAI', val={'T':0x52, 'V':5*b'\0'}, bl={'V':40}, IE=TAI()),
Type3TV('DRXParam', val={'T':0x5C, 'V':b'\0\0'}, bl={'V':16}, IE=DRXParam()),
Type4TLV('MSNetCap', val={'T':0x31, 'V':b'\0\0'}, IE=ms_network_capability_value_part),
Type3TV('OldLAI', val={'T':0x13, 'V':5*b'\0'}, bl={'V':40}, IE=LAI()),
Type1TV('TMSIStatus', val={'T':0x9, 'V':0}, IE=TMSIStatus()),
Type4TLV('MSCm2', val={'T':0x11, 'V':b'@\0\0'}, IE=MSCm2()),
Type4TLV('MSCm3', val={'T':0x20, 'V':b''}, IE=classmark_3_value_part),
Type4TLV('SuppCodecs', val={'T':0x40, 'V':b'\0\x01\0'}, IE=SuppCodecList()),
Type1TV('AddUpdateType', val={'T':0xF, 'V':0}, IE=AddUpdateType()),
Type4TLV('VoiceDomPref', val={'T':0x5D, 'V':b'\0'}, IE=VoiceDomPref()),
Type1TV('DeviceProp', val={'T':0xD, 'V':0}, IE=DeviceProp()),
Type1TV('OldGUTIType', val={'T':0xE, 'V':0}, IE=GUTIType()),
Type1TV('MSNetFeatSupp', val={'T':0xC, 'V':0}, IE=MSNetFeatSupp()),
Type4TLV('TMSIBasedNRICont', val={'T':0x10, 'V':b'\0\0'}, IE=NRICont()),
Type4TLV('T3324', val={'T':0x6A, 'V':b'\0'}, IE=GPRSTimer()),
Type4TLV('T3412Ext', val={'T':0x5E, 'V':b'\0'}, IE=GPRSTimer3()),
Type4TLV('ExtDRXParam', val={'T':0x6E, 'V':b'\0'}, IE=ExtDRXParam()),
Type4TLV('UEAddSecCap', val={'T':0x6F, 'V':b'\0\0\0\0'}, IE=UEAddSecCap()),
Type4TLV('UEStatus', val={'T':0x6D, 'V':b'\0'}, IE=UEStatus()),
Type3TV('AddInfoReq', val={'T':0x17, 'V':b'\0'}, IE=AddInfoReq()),
Type4TLV('N1UENetCap', val={'T':0x32, 'V':b'\0'}, IE=N1UENetCap()),
Type1TV('UERadioCapIDAvail', val={'T':0xB, 'V':0}, IE=UERadioCapIDAvail()) # WNG: tag is undefined in current TS
)
#------------------------------------------------------------------------------#
# Authentication failure
# TS 24.301, section 8.2.5
#------------------------------------------------------------------------------#
class EMMAuthenticationFailure(Layer3E):
_GEN = (
EMMHeader(val={'Type':92}),
Type3V('EMMCause', val={'V':b'\x11'}, bl={'V':8}, IE=EMMCause()),
Type4TLV('AUTS', val={'T':0x30, 'V':14*b'\0'})
)
#------------------------------------------------------------------------------#
# Authentication reject
# TS 24.301, section 8.2.6
#------------------------------------------------------------------------------#
class EMMAuthenticationReject(Layer3E):
_GEN = (
EMMHeader(val={'Type':84}),
)
#------------------------------------------------------------------------------#
# Authentication request
# TS 24.301, section 8.2.7
#------------------------------------------------------------------------------#
class EMMAuthenticationRequest(Layer3E):
_GEN = (
EMMHeader(val={'Type':82}),
Uint('spare', bl=4),
Type1V('NAS_KSI', val={'V':7}, IE=NAS_KSI()),
Type3V('RAND', val={'V':16*b'\0'}, bl={'V':128}),
Type4LV('AUTN', val={'V':16*b'\0'}, IE=AUTN())
)
#------------------------------------------------------------------------------#
# Authentication response
# TS 24.301, section 8.2.8
#------------------------------------------------------------------------------#
class EMMAuthenticationResponse(Layer3E):
_GEN = (
EMMHeader(val={'Type':83}),
Type4LV('RES', val={'V':8*b'\0'})
)
#------------------------------------------------------------------------------#
# CS service notification
# TS 24.301, section 8.2.9
#------------------------------------------------------------------------------#
class EMMCSServiceNotification(Layer3E):
_GEN = (
EMMHeader(val={'Type':100}),
Type3V('PagingIdentity', val={'V':b'\x01'}, bl={'V':8}, IE=PagingIdentity()),
Type4TLV('CLI', val={'T':0x60, 'V':b'\x91'}, IE=CallingPartyBCDNumber()),
Type3TV('SSCode', val={'T':0x61, 'V':b'\0'}, bl={'V':8}, IE=SSCode()),
Type3TV('LCSInd', val={'T':0x62, 'V':b'\x01'}, bl={'V':8}, IE=LCSInd()),
Type4TLV('LCSClientId', val={'T':0x63, 'V':b''}, IE=LCSClientId())
)
#------------------------------------------------------------------------------#
# Detach accept
# TS 24.301, 8.2.10
#------------------------------------------------------------------------------#
class EMMDetachAccept(Layer3E):
_GEN = (
EMMHeader(val={'Type':70}),
)
#------------------------------------------------------------------------------#
# Detach request (UE originating detach)
# TS 24.301, section 8.2.11.1
#------------------------------------------------------------------------------#
class EMMDetachRequestMO(Layer3E):
_GEN = (
EMMHeader(val={'Type':69}),
Type1V('NAS_KSI', val={'V':7}, IE=NAS_KSI()),
Type1V('EPSDetachType', IE=EPSDetachTypeMO()),
Type4LV('EPSID', val={'V':b'\xf6'+10*b'\0'}, IE=EPSID())
)
#------------------------------------------------------------------------------#
# Detach request (UE terminated detach)
# TS 24.301, section 8.2.11.2
#------------------------------------------------------------------------------#
class EMMDetachRequestMT(Layer3E):
_GEN = (
EMMHeader(val={'Type':69}),
Uint('spare', bl=4),
Type1V('EPSDetachType', IE=EPSDetachTypeMT()),
Type3TV('EMMCause', val={'T':0x53, 'V':b'\0'}, bl={'V':8}, IE=EMMCause())
)
#------------------------------------------------------------------------------#
# Downlink NAS Transport
# TS 24.301, section 8.2.12
#------------------------------------------------------------------------------#
class EMMDLNASTransport(Layer3E):
_GEN = (
EMMHeader(val={'Type':98}),
Type4LV('NASContainer', val={'V':b'\0\0'})
)
#------------------------------------------------------------------------------#
# EMM information
# TS 24.301, section 8.2.13
#------------------------------------------------------------------------------#
class EMMInformation(Layer3E):
_GEN = (
EMMHeader(val={'Type':97}),
Type4TLV('NetFullName', val={'T':0x43, 'V':b'\0'}, IE=NetworkName()),
Type4TLV('NetShortName', val={'T':0x45, 'V':b'\0'}, IE=NetworkName()),
Type3TV('LocalTimeZone', val={'T':0x46, 'V':b'\0'}, bl={'V':8}, IE=TimeZone()),
Type3TV('UnivTimeAndTimeZone', val={'T':0x47, 'V':7*b'\0'}, bl={'V':56},
IE=TimeZoneTime()),
Type4TLV('DLSavingTime', val={'T':0x49, 'V':b'\0'}, IE=DLSavingTime())
)
#------------------------------------------------------------------------------#
# EMM status
# TS 24.301, section 8.2.14
#------------------------------------------------------------------------------#
class EMMStatus(Layer3E):
_GEN = (
EMMHeader(val={'Type':96}),
Type3V('EMMCause', val={'V':b'\x11'}, bl={'V':8}, IE=EMMCause())
)
#------------------------------------------------------------------------------#
# Extended service request
# TS 24.301, section 8.2.15
#------------------------------------------------------------------------------#
class EMMExtServiceRequest(Layer3E):
_GEN = (
EMMHeader(val={'Type':76}),
Type1V('NAS_KSI', val={'V':7}, IE=NAS_KSI()),
Type1V('ServiceType', dic=EMMServType_dict),
Type4LV('MTMSI', val={'V':b'\xf4\0\0\0\0'}, IE=ID()),
Type1TV('CSFBResponse', val={'T':0xB, 'V':0}, IE=CSFBResponse()),
Type4TLV('EPSBearerCtxtStat', val={'T':0x57, 'V':b'\0\0'}, IE=EPSBearerCtxtStat()),
Type1TV('DeviceProp', val={'T':0xD, 'V':0}, IE=DeviceProp())
)
#------------------------------------------------------------------------------#
# GUTI reallocation command
# TS 24.301, section 8.2.16
#------------------------------------------------------------------------------#
class EMMGUTIReallocCommand(Layer3E):
_GEN = (
EMMHeader(val={'Type':80}),
Type4LV('GUTI', val={'V':b'\xf6'+10*b'\0'}, IE=EPSID()),
Type4TLV('TAIList', val={'T':0x54, 'V':6*b'\0'}, IE=TAIList()),
Type4TLV('DCNID', val={'T':0x65, 'V':b'\0\0'}, IE=DCNID()),
Type4TLV('UERadioCapID', val={'T':0x66, 'V':b'\0'}, IE=UERadioCapID()),
Type1TV('UERadioCapIDDelInd', val={'T':0xB, 'V':0}, IE=UERadioCapIDDelInd()),
)
#------------------------------------------------------------------------------#
# GUTI reallocation complete
# TS 24.301, section 8.2.17
#------------------------------------------------------------------------------#
class EMMGUTIReallocComplete(Layer3E):
_GEN = (
EMMHeader(val={'Type':81}),
)
#------------------------------------------------------------------------------#
# Identity request
# TS 24.301, section 8.2.18
#------------------------------------------------------------------------------#
class EMMIdentityRequest(Layer3E):
_GEN = (
EMMHeader(val={'Type':85}),
Uint('spare', bl=4),
Type1V('IDType', val={'V':IDTYPE_IMSI}, dic=IDType_dict)
)
#------------------------------------------------------------------------------#
# Identity response
# TS 24.301, section 8.2.19
#------------------------------------------------------------------------------#
class EMMIdentityResponse(Layer3E):
_GEN = (
EMMHeader(val={'Type':86}),
Type4LV('ID', val={'V':b'\xf4\0\0\0\0'}, IE=ID())
)
#------------------------------------------------------------------------------#
# Security mode command
# TS 24.301, section 8.2.20
#------------------------------------------------------------------------------#
class EMMSecurityModeCommand(Layer3E):
_GEN = (
EMMHeader(val={'Type':93}),
Type3V('NASSecAlgo', val={'V':b'\x11'}, bl={'V':8}, IE=NASSecAlgo()),
Uint('spare', bl=4),
Type1V('NAS_KSI', val={'V':0}, IE=NAS_KSI()),
Type4LV('UESecCap', val={'V':b'\0\0'}, IE=UESecCap()),
Type1TV('IMEISVReq', val={'T':0xC, 'V':0}, IE=IMEISVReq()),
Type3TV('NonceUE', val={'T':0x55, 'V':b'\0\0\0\0'}, bl={'V':32}),
Type3TV('NonceMME', val={'T':0x56, 'V':b'\0\0\0\0'}, bl={'V':32}),
Type4TLV('HashMME', val={'T':0x4F, 'V':8*b'\0'}),
Type4TLV('UEAddSecCap', val={'T':0x6F, 'V':b'\0\0\0\0'}, IE=UEAddSecCap()),
Type1TV('UERadioCapIDReq', val={'T':0xD, 'V':0}, IE=UERadioCapIDReq())
)
#------------------------------------------------------------------------------#
# Security mode complete
# TS 24.301, section 8.2.21
#------------------------------------------------------------------------------#
class EMMSecurityModeComplete(Layer3E):
_GEN = (
EMMHeader(val={'Type':94}),
Type4TLV('IMEISV', val={'T':0x23, 'V':b'\x03\0\0\0\0\0\0\0\xf0'}, IE=ID()),
Type6TLVE('NASMessage', val={'T':0x79, 'V':b'\x07\0'}),
Type4TLV('UERadioCapID', val={'T':0x66, 'V':b'\0'}, IE=UERadioCapID())
)
#------------------------------------------------------------------------------#
# Security mode reject
# TS 24.301, section 8.2.22
#------------------------------------------------------------------------------#
class EMMSecurityModeReject(Layer3E):
_GEN = (
EMMHeader(val={'Type':95}),
Type3V('EMMCause', val={'V':b'\x11'}, bl={'V':8}, IE=EMMCause())
)
#------------------------------------------------------------------------------#
# Security protected NAS message
# TS 24.301, section 8.2.23
#------------------------------------------------------------------------------#
if _with_cm:
class EMMSecProtNASMessage(Layer3E):
_GEN = (
EMMHeaderSec(),
Buf('MAC', val=b'\0\0\0\0', bl=32, rep=REPR_HEX),
Uint8('Seqn'),
Buf('NASMessage')
)
def mac_verify(self, key=16*b'\0', dir=0, eia=0, seqnoff=0):
"""compute the MAC of the NASMessage using Seqn plus seqnoff, key,
direction and eia, and verify against the embedded MAC value
Args:
key: 16 bytes buffer, K_nas_int
dir: 0 for uplink, 1 for downlink
eia: 0 to 3, reference to EIA algorithm
seqnoff: 0 to 2^32 - 2^8, NAS count offset to add to Seqn
Returns:
True if embedded MAC is correct, False otherwise
"""
if eia == 0:
return True
shdr = self[0][0].get_val()
if shdr == 0:
return True
elif shdr in (1, 2, 3, 4):
try:
EIA = _EIA[eia]
except KeyError:
raise(PycrateErr('EMMSecProtNASMessage.mac_verify(): invalid EIA identifier, {0}'\
.format(eia)))
mac = EIA(key, seqnoff + self[2].get_val(), 0, dir, self[2].to_bytes() + self[3].get_val())
return mac == self[1].get_val()
else:
raise(PycrateErr('EMMSecProtNASMessage.mac_verify(): invalid sec hdr value, {0}'\
.format(shdr)))
def mac_compute(self, key=16*b'\0', dir=0, eia=0, seqnoff=0):
"""compute the MAC of the NASMessage using Seqn plus seqnoff, key,
direction and eia, and set the embedded MAC value with it
Args:
key: 16 bytes buffer, K_nas_int
dir: 0 for uplink, 1 for downlink
eia: 0 to 3, reference to EIA algorithm
seqnoff: 0 to 2^32 - 2^8, NAS count offset to add to Seqn
Returns:
None
"""
if eia == 0:
self[1].set_val(b'\0\0\0\0')
return
shdr = self[0][0].get_val()
if shdr == 0:
self[1].set_val(b'\0\0\0\0')
elif shdr in (1, 2, 3, 4):
try:
EIA = _EIA[eia]
except KeyError:
raise(PycrateErr('EMMSecProtNASMessage.mac_compute(): invalid EIA identifier, {0}'\
.format(eia)))
mac = EIA(key, seqnoff + self[2].get_val(), 0, dir, self[2].to_bytes() + self[3].get_val())
self[1].set_val(mac)
else:
raise(PycrateErr('EMMSecProtNASMessage.mac_compute(): invalid sec hdr value, {0}'\
.format(shdr)))
def encrypt(self, key=16*b'\0', dir=0, eea=0, seqnoff=0):
"""encrypt the NASMessage in place using Seqn plus seqnoff, key,
direction and eea,
Args:
key: 16 bytes buffer, K_nas_enc
dir: 0 for uplink, 1 for downlink
eea: 0 to 3, reference to EEA algorithm
seqnoff: 0 to 2^24 by step of 0x100
Returns:
None
"""
if eea == 0:
return
shdr = self[0][0].get_val()
if shdr in (0, 1, 3):
return
elif shdr in (2, 4):
try:
EEA = _EEA[eea]
except KeyError:
raise(PycrateErr('EMMSecProtNASMessage.encrypt(): invalid EEA identifier, {0}'\
.format(eea)))
self._dec_msg = self[3].to_bytes()
self._enc_msg = EEA(key, seqnoff + self[2].get_val(), 0, dir, self._dec_msg)
self[3].set_val(self._enc_msg)
else:
raise(PycrateErr('EMMSecProtNASMessage.encrypt(): invalid sec hdr value, {0}'\
.format(shdr)))
def decrypt(self, key=16*b'\0', dir=0, eea=0, seqnoff=0):
"""decrypt the NASMessage in place using Seqn plus seqnoff, key,
direction and eea, and decode the NASMessage content
Args:
key: 16 bytes buffer, K_nas_enc
dir: 0 for uplink, 1 for downlink
eea: 0 to 3, reference to EEA algorithm
seqnoff: 0 to 2^24 by step of 0x100
Returns:
None
"""
if eea == 0:
return
shdr = self[0][0].get_val()
if shdr in (0, 1, 3):
return
elif shdr in (2, 4):
try:
EEA = _EEA[eea]
except KeyError:
raise(PycrateErr('EMMSecProtNASMessage.decrypt(): invalid EEA identifier, {0}'\
.format(eea)))
self._enc_msg = self[3].to_bytes()
self._dec_msg = EEA(key, seqnoff + self[2].get_val(), 0, dir, self._enc_msg)
self[3].set_val(self._dec_msg)
else:
raise(PycrateErr('EMMSecProtNASMessage.decrypt(): invalid sec hdr value, {0}'\
.format(shdr)))
else:
class EMMSecProtNASMessage(Layer3E):
_GEN = (
EMMHeaderSec(),
Buf('MAC', val=b'\0\0\0\0', bl=32, rep=REPR_HEX),
Uint8('Seqn'),
Buf('NASMessage')
)
#------------------------------------------------------------------------------#
# Service reject
# TS 24.301, section 8.2.24
#------------------------------------------------------------------------------#
class EMMServiceReject(Layer3E):
_GEN = (
EMMHeader(val={'Type':78}),
Type3V('EMMCause', val={'V':b'\x11'}, bl={'V':8}, IE=EMMCause()),
Type3TV('T3442', val={'T':0x5B, 'V':b'\0'}, bl={'V':8}, IE=GPRSTimer()),
Type4TLV('T3346', val={'T':0x5C, 'V':b'\0'}, IE=GPRSTimer()),
Type4TLV('T3448', val={'T':0x6B, 'V':b'\0'}, IE=GPRSTimer()),
)
#------------------------------------------------------------------------------#
# Service request
# TS 24.301, section 8.2.25
#------------------------------------------------------------------------------#
if _with_cm:
class EMMServiceRequest(Layer3E):
_GEN = (
EMMHeaderServ(val={'SecHdr': 12}),
Uint('KSI', bl=3, dic={7:'no key available'}),
Uint('SeqnShort', bl=5),
Buf('MACShort', val=b'\0\0', bl=16, rep=REPR_HEX)
)
def mac_verify(self, key=16*b'\0', dir=0, eia=0, seqnoff=0):
"""compute the MAC of the EMMServiceRequest using SeqnShort plus seqnoff,
key, direction and eia, and verify against the embedded MACShort value
Args:
key: 16 bytes buffer, K_nas_int
dir: 0 for uplink, 1 for downlink
eia: 0 to 3, reference to EIA algorithm
seqnoff: 0 to 2^32 - 2^5, NAS count offset to add to SeqnShort
Returns:
True if embedded MACShort is correct, False otherwise
"""
if eia == 0:
return True
else:
try:
EIA = _EIA[eia]
except KeyError:
raise(PycrateErr('EMMServiceRequest.mac_verify(): invalid EIA identifier, {0}'\
.format(eia)))
msg = self.to_bytes()
mac = EIA(key, seqnoff + self[2].get_val(), 0, dir, msg[:2])
if mac[2:4] != msg[2:4]:
return False
else:
return True
def mac_compute(self, key=16*b'\0', dir=0, eia=0, seqnoff=0):
"""compute the MAC of the EMMServiceRequest using SeqnShort plus seqnoff,
key, direction and eia, and set the embedded MACShort value with it
Args:
key: 16 bytes buffer, K_nas_int
dir: 0 for uplink, 1 for downlink
eia: 0 to 3, reference to EIA algorithm
seqnoff: 0 to 2^32 - 2^5, NAS count offset to add to SeqnShort
Returns:
None
"""
if eia == 0:
self[4].set_val(b'\0\0')
else:
try:
EIA = _EIA[eia]
except KeyError:
raise(PycrateErr('EMMServiceRequest.mac_compute(): invalid EIA identifier, {0}'\
.format(eia)))
msg = self.to_bytes()
mac = EIA(key, seqnoff + self[2].get_val(), 0, dir, msg[:2])
self[4].set_val(mac[2:4])
else:
class EMMServiceRequest(Layer3E):
_GEN = (
EMMHeaderServ(val={'SecHdr': 12}),
Uint('KSI', bl=3, dic={7:'no key available'}),
Uint('SeqnShort', bl=5),
Buf('MACShort', val=b'\0\0', bl=16, rep=REPR_HEX)
)
#------------------------------------------------------------------------------#
# Tracking area update accept
# TS 24.301, section 8.2.26
#------------------------------------------------------------------------------#
class EMMTrackingAreaUpdateAccept(Layer3E):
_GEN = (
EMMHeader(val={'Type':73}),
Uint('spare', bl=4),
Type1V('EPSUpdateResult', dic=EPSUpdRes_dict),
Type3TV('T3412', val={'T':0x5A, 'V':b'\0'}, bl={'V':8}, IE=GPRSTimer()),
Type4TLV('GUTI', val={'T':0x50, 'V':b'\xf6'+10*b'\0'}, IE=EPSID()),
Type4TLV('TAIList', val={'T':0x54, 'V':6*b'\0'}, IE=TAIList()),
Type4TLV('EPSBearerCtxtStat', val={'T':0x57, 'V':b'\0\0'}, IE=EPSBearerCtxtStat()),
Type3TV('LAI', val={'T':0x13, 'V':5*b'\0'}, bl={'V':40}, IE=LAI()),
Type4TLV('ID', val={'T':0x23, 'V':b'\xf4\0\0\0\0'}, IE=ID()),
Type3TV('EMMCause', val={'T':0x53, 'V':b'\0'}, bl={'V':8}, IE=EMMCause()),
Type3TV('T3402', val={'T':0x17, 'V':b'\0'}, bl={'V':8}, IE=GPRSTimer()),
Type3TV('T3423', val={'T':0x59, 'V':b'\0'}, bl={'V':8}, IE=GPRSTimer()),
Type4TLV('EquivPLMNList', val={'T':0x4A, 'V':3*b'\0'}, IE=PLMNList()),
Type4TLV('EmergNumList', val={'T':0x34, 'V':b'\x02\x01\0'}, IE=EmergNumList()),
Type4TLV('EPSNetFeat', val={'T':0x64, 'V':b'\0\0'}, IE=EPSNetFeat()),
Type1TV('AddUpdateRes', val={'T':0xF, 'V':0}, IE=AddUpdateRes()),
Type4TLV('T3412Ext', val={'T':0x5E, 'V':b'\0'}, IE=GPRSTimer3()),
Type4TLV('T3324', val={'T':0x6A, 'V':b'\0'}, IE=GPRSTimer()),
Type4TLV('ExtDRXParam', val={'T':0x6E, 'V':b'\0'}, IE=ExtDRXParam()),
Type4TLV('HdrCompConfigStat', val={'T':0x68, 'V':b'\0\0'}, IE=HdrCompConfigStat()),
Type4TLV('DCNID', val={'T':0x65, 'V':b'\0\0'}, IE=DCNID()),
Type1TV('SMSServStat', val={'T':0xE, 'V':0}, IE=SMSServStat()),
Type1TV('Non3GPPNWProvPol', val={'T':0xD, 'V':0}, IE=Non3GPPNWProvPol()),
Type4TLV('T3448', val={'T':0x6B, 'V':b'\0'}, IE=GPRSTimer()),
Type1TV('NetworkPol', val={'T':0xC, 'V':0}, IE=NetworkPol()),
Type4TLV('T3447', val={'T':0x6C, 'V':b'\0'}, IE=GPRSTimer3()),
Type6TLVE('ExtEmergNumList', val={'T':0x7A, 'V':b'\0\0\0\0'}, IE=ExtEmergNumList()),
Type6TLVE('CipherKeyData', val={'T':0x7C, 'V':32*b'\0'}, IE=CipherKeyData()),
Type4TLV('UERadioCapID', val={'T':0x66, 'V':b'\0'}, IE=UERadioCapID()),
Type1TV('UERadioCapIDDelInd', val={'T':0xB, 'V':0}, IE=UERadioCapIDDelInd())
)
#------------------------------------------------------------------------------#
# Tracking area update complete
# TS 24.301, section 8.2.27
#------------------------------------------------------------------------------#
class EMMTrackingAreaUpdateComplete(Layer3E):
_GEN = (
EMMHeader(val={'Type':74}),
)
#------------------------------------------------------------------------------#
# Tracking area update reject
# TS 24.301, section 8.2.28
#------------------------------------------------------------------------------#
class EMMTrackingAreaUpdateReject(Layer3E):
_GEN = (
EMMHeader(val={'Type':75}),
Type3V('EMMCause', val={'V':b'\x11'}, bl={'V':8}, IE=EMMCause()),
Type4TLV('T3346', val={'T':0x5F, 'V':b'\0'}, IE=GPRSTimer()),
Type1TV('ExtEMMCause', val={'T':0xA, 'V':0}, IE=ExtEMMCause())
)
#------------------------------------------------------------------------------#
# Tracking area update request
# TS 24.301, section 8.2.29
#------------------------------------------------------------------------------#
class EMMTrackingAreaUpdateRequest(Layer3E):
_GEN = (
EMMHeader(val={'Type':72}),
Type1V('NAS_KSI', val={'V':7}, IE=NAS_KSI()),
Type1V('EPSUpdateType', IE=EPSUpdateType()),
Type4LV('OldGUTI', val={'V':b'\xf6'+10*b'\0'}, IE=EPSID()),
Type1TV('Native_NAS_KSI', val={'T':0xB, 'V':0}, IE=NAS_KSI()),
Type1TV('GPRS_CKSN', val={'T':0x8, 'V':0}, dic=CKSN_dict),
Type3TV('OldPTMSISign', val={'T':0x19, 'V':b'\0\0\0'}, bl={'V':24}),
Type4TLV('AddGUTI', val={'T':0x50, 'V':b'\xf6'+10*b'\0'}, IE=EPSID()),
Type3TV('NonceUE', val={'T':0x55, 'V':4*b'\0'}, bl={'V':32}),
Type4TLV('UENetCap', val={'T':0x58, 'V':b'\0\0'}, IE=UENetCap()),
Type3TV('OldTAI', val={'T':0x52, 'V':5*b'\0'}, bl={'V':40}, IE=TAI()),
Type3TV('DRXParam', val={'T':0x5C, 'V':b'\0\0'}, bl={'V':16}, IE=DRXParam()),
Type1TV('UERACapUpdateNeed', val={'T':0xA, 'V':0}),
Type4TLV('EPSBearerCtxtStat', val={'T':0x57, 'V':b'\0\0'}, IE=EPSBearerCtxtStat()),
Type4TLV('MSNetCap', val={'T':0x31, 'V':b'\0\0'}, IE=ms_network_capability_value_part),
Type3TV('OldLAI', val={'T':0x13, 'V':5*b'\0'}, bl={'V':40}, IE=LAI()),
Type1TV('TMSIStatus', val={'T':0x9, 'V':0}, IE=TMSIStatus()),
Type4TLV('MSCm2', val={'T':0x11, 'V':b'@\0\0'}, IE=MSCm2()),
Type4TLV('MSCm3', val={'T':0x20, 'V':b''}, IE=classmark_3_value_part),
Type4TLV('SuppCodecs', val={'T':0x40, 'V':b'\0\x01\0'}, IE=SuppCodecList()),
Type1TV('AddUpdateType', val={'T':0xF, 'V':0}, IE=AddUpdateType()),
Type4TLV('VoiceDomPref', val={'T':0x5D, 'V':b'\0'}, IE=VoiceDomPref()),
Type1TV('OldGUTIType', val={'T':0xE, 'V':0}, IE=GUTIType()),
Type1TV('DeviceProp', val={'T':0xD, 'V':0}, IE=DeviceProp()),
Type1TV('MSNetFeatSupp', val={'T':0xC, 'V':0}, IE=MSNetFeatSupp()),
Type4TLV('TMSIBasedNRICont', val={'T':0x10, 'V':b'\0\0'}, IE=NRICont()),
Type4TLV('T3324', val={'T':0x6A, 'V':b'\0'}, IE=GPRSTimer()),
Type4TLV('T3412Ext', val={'T':0x5E, 'V':b'\0'}, IE=GPRSTimer3()),
Type4TLV('ExtDRXParam', val={'T':0x6E, 'V':b'\0'}, IE=ExtDRXParam()),
Type4TLV('UEAddSecCap', val={'T':0x6F, 'V':b'\0\0\0\0'}, IE=UEAddSecCap()),
Type4TLV('UEStatus', val={'T':0x6D, 'V':b'\0'}, IE=UEStatus()),
Type3TV('AddInfoReq', val={'T':0x17, 'V':b'\0'}, IE=AddInfoReq()),
Type4TLV('N1UENetCap', val={'T':0x32, 'V':b'\0'}, IE=N1UENetCap()),
#Type1TV('UERadioCapIDAvail', val={'T':0xB, 'V':0}, IE=UERadioCapIDAvail()) # WNG: tag is undefined in current TS
)
#------------------------------------------------------------------------------#
# Uplink NAS transport
# TS 24.301, section 8.2.30
#------------------------------------------------------------------------------#
class EMMULNASTransport(Layer3E):
_GEN = (
EMMHeader(val={'Type':99}),
Type4LV('NASContainer', val={'V':b'\0\0'})
)
#------------------------------------------------------------------------------#
# Downlink generic NAS transport
# TS 24.301, section 8.2.31
#------------------------------------------------------------------------------#
class EMMDLGenericNASTransport(Layer3E):
_GEN = (
EMMHeader(val={'Type':104}),
Type3V('GenericContType', val={'V':b'\0'}, bl={'V':8}, IE=GenericContType()),
Type6LVE('GenericContainer', val={'V':b'\0\0'}),
Type4TLV('AddInfo', val={'T':0x65, 'V':b'\0'})
)
#------------------------------------------------------------------------------#
# Uplink generic NAS transport
# TS 24.301, section 8.2.32
#------------------------------------------------------------------------------#
class EMMULGenericNASTransport(Layer3E):
_GEN = (
EMMHeader(val={'Type':105}),
Type3V('GenericContType', val={'V':b'\0'}, bl={'V':8}, IE=GenericContType()),
Type6LVE('GenericContainer', val={'V':b'\0\0'}),
Type4TLV('AddInfo', val={'T':0x65, 'V':b'\0'})
)
#------------------------------------------------------------------------------#
# Control plane service request
# TS 24.301, section 8.2.33
#------------------------------------------------------------------------------#
class EMMCPServiceRequest(Layer3E):
_GEN = (
EMMHeader(val={'Type':77}),
Type1V('NAS_KSI', val={'V':7}, IE=NAS_KSI()),
Type1V('CPServiceType', IE=CPServiceType()),
Type6TLVE('ESMContainer', val={'T':0x78, 'V':b'\0'}),
Type4TLV('NASContainer', val={'T':0x67, 'V':b'\0\0'}),
Type4TLV('EPSBearerCtxtStat', val={'T':0x57, 'V':b'\0\0'}, IE=EPSBearerCtxtStat()),
Type1TV('DeviceProp', val={'T':0xD, 'V':0}, IE=DeviceProp())
)
#------------------------------------------------------------------------------#
# Service accept
# TS 24.301, section 8.2.34
#------------------------------------------------------------------------------#
class EMMServiceAccept(Layer3E):
_GEN = (
EMMHeader(val={'Type':79}),
Type4TLV('EPSBearerCtxtStat', val={'T':0x57, 'V':b'\0\0'}, IE=EPSBearerCtxtStat()),
Type4TLV('T3448', val={'T':0x6B, 'V':b'\0'}, IE=GPRSTimer())
)
#------------------------------------------------------------------------------#
# EMM dispatcher
#------------------------------------------------------------------------------#
# special EMM messages: EMMSecProtNASMessage, EMMServiceRequest
EMMTypeMOClasses = {
65 : EMMAttachRequest,
66 : EMMAttachAccept,
67 : EMMAttachComplete,
68 : EMMAttachReject,
69 : EMMDetachRequestMO,
70 : EMMDetachAccept,
72 : EMMTrackingAreaUpdateRequest,
73 : EMMTrackingAreaUpdateAccept,
74 : EMMTrackingAreaUpdateComplete,
75 : EMMTrackingAreaUpdateReject,
76 : EMMExtServiceRequest,
77 : EMMCPServiceRequest,
78 : EMMServiceReject,
79 : EMMServiceAccept,
80 : EMMGUTIReallocCommand,
81 : EMMGUTIReallocComplete,
82 : EMMAuthenticationRequest,
83 : EMMAuthenticationResponse,
84 : EMMAuthenticationReject,
92 : EMMAuthenticationFailure,
85 : EMMIdentityRequest,
86 : EMMIdentityResponse,
93 : EMMSecurityModeCommand,
94 : EMMSecurityModeComplete,
95 : EMMSecurityModeReject,
96 : EMMStatus,
97 : EMMInformation,
98 : EMMDLNASTransport,
99 : EMMULNASTransport,
100 : EMMCSServiceNotification,
104 : EMMDLGenericNASTransport,
105 : EMMULGenericNASTransport
}
EMMTypeMTClasses = {
65 : EMMAttachRequest,
66 : EMMAttachAccept,
67 : EMMAttachComplete,
68 : EMMAttachReject,
69 : EMMDetachRequestMT,
70 : EMMDetachAccept,
72 : EMMTrackingAreaUpdateRequest,
73 : EMMTrackingAreaUpdateAccept,
74 : EMMTrackingAreaUpdateComplete,
75 : EMMTrackingAreaUpdateReject,
76 : EMMExtServiceRequest,
77 : EMMCPServiceRequest,
78 : EMMServiceReject,
79 : EMMServiceAccept,
80 : EMMGUTIReallocCommand,
81 : EMMGUTIReallocComplete,
82 : EMMAuthenticationRequest,
83 : EMMAuthenticationResponse,
84 : EMMAuthenticationReject,
92 : EMMAuthenticationFailure,
85 : EMMIdentityRequest,
86 : EMMIdentityResponse,
93 : EMMSecurityModeCommand,
94 : EMMSecurityModeComplete,
95 : EMMSecurityModeReject,
96 : EMMStatus,
97 : EMMInformation,
98 : EMMDLNASTransport,
99 : EMMULNASTransport,
100 : EMMCSServiceNotification,
104 : EMMDLGenericNASTransport,
105 : EMMULGenericNASTransport
}
def get_emm_msg_mo_instances():
return {k: EMMTypeMOClasses[k]() for k in EMMTypeMOClasses}
def get_emm_msg_mt_instances():
return {k: EMMTypeMTClasses[k]() for k in EMMTypeMTClasses}