Skip to content

Commit

Permalink
NAS: add explicit support for null-cipher in 4G and 5G NAS parsers
Browse files Browse the repository at this point in the history
  • Loading branch information
mitshell committed Apr 13, 2024
1 parent 4166239 commit 18aefa0
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 14 deletions.
8 changes: 4 additions & 4 deletions pycrate_mobile/NAS.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ def parse_NAS_MO(buf, inner=True):
if pd in (3, 5, 11):
type &= 0x3f
elif pd in (2, 7):
return parse_NASLTE_MO(buf, inner=inner, sec_hdr=True)
return parse_NASLTE_MO(buf, inner=inner, sec_hdr=True, null_cipher=False)
elif pd in (46, 126):
return parse_NAS5G(buf, inner=inner, sec_hdr=True)
return parse_NAS5G(buf, inner=inner, sec_hdr=True, null_cipher=False)
#
try:
Msg = NASMODispatcher[pd][type]()
Expand Down Expand Up @@ -160,9 +160,9 @@ def parse_NAS_MT(buf, inner=True, wl2=False):
if pd in (3, 5, 11):
type &= 0x3f
elif pd in (2, 7):
return parse_NASLTE_MT(buf, inner=inner, sec_hdr=True)
return parse_NASLTE_MT(buf, inner=inner, sec_hdr=True, null_cipher=False)
elif pd in (46, 126):
return parse_NAS5G(buf, inner=inner, sec_hdr=True)
return parse_NAS5G(buf, inner=inner, sec_hdr=True, null_cipher=False)
#
try:
Msg = NASMTDispatcher[pd][type]()
Expand Down
11 changes: 6 additions & 5 deletions pycrate_mobile/NAS5G.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: UTF-8 -*-
#/**
# * Software Name : pycrate
# * Version : 0.4
# * Version : 0.7
# *
# * Copyright 2019. Benoit Michau. P1Sec.
# *
Expand Down Expand Up @@ -40,17 +40,18 @@
# TODO: migrate TS24519_TSNAF to the new TS24539 spec


def parse_NAS5G(buf, inner=True, sec_hdr=True):
def parse_NAS5G(buf, inner=True, sec_hdr=True, null_cipher=False):
"""Parses a 5G NAS message bytes' buffer
Args:
buf: 5G NAS message bytes' buffer
inner: if True, decode NASMessage within the security header, PayloadContainer
and PortMgmtInfoContainer if possible
otherwise, keep those field as plain bytes buffer (e.g. for later decoding)
sec_hdr: if True, consider the 5GMM security header with potential encryption
otherwise, just consider the NAS message is in plain text
null_cipher: if True, try to decode the 1st level inner payload, even if security header
indicates encryption is applied, but suppose null-cipher is used
Returns:
element, err: 2-tuple
Expand All @@ -74,7 +75,7 @@ def parse_NAS5G(buf, inner=True, sec_hdr=True):
except Exception:
# error 96, invalid mandatory info
return None, 96
if inner and shdr in (1, 3):
if inner and (shdr in (1, 3) or null_cipher):
# parse clear-text NAS message container
cont, err = parse_NAS5G(Msg[3].get_val(), inner=inner)
if cont is not None:
Expand All @@ -92,7 +93,7 @@ def parse_NAS5G(buf, inner=True, sec_hdr=True):
return None, 97
#
elif pd == 46:
# 5GSM
# 5GSM
try:
typ = buf[3]
except:
Expand Down
14 changes: 9 additions & 5 deletions pycrate_mobile/NASLTE.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: UTF-8 -*-
#/**
# * Software Name : pycrate
# * Version : 0.4
# * Version : 0.7
# *
# * Copyright 2017. Benoit Michau. ANSSI.
# *
Expand Down Expand Up @@ -35,7 +35,7 @@
from .TS24011_PPSMS import PPSMSCPTypeClasses


def parse_NASLTE_MO(buf, inner=True, sec_hdr=True):
def parse_NASLTE_MO(buf, inner=True, sec_hdr=True, null_cipher=False):
"""Parses a Mobile Originated LTE NAS message bytes' buffer
Args:
Expand All @@ -45,6 +45,8 @@ def parse_NASLTE_MO(buf, inner=True, sec_hdr=True):
decode NASContainer within EMM NAS Transport message if possible
sec_hdr: if True, handle the NAS EMM security header
otherwise, just consider the NAS message is in plain text
null_cipher: if True, try to decode the 1st level inner payload, even if security header
indicates encryption is applied, but suppose null-cipher is used
Returns:
element, err: 2-tuple
Expand All @@ -67,7 +69,7 @@ def parse_NASLTE_MO(buf, inner=True, sec_hdr=True):
# error 96, invalid mandatory info
return None, 96
#
if inner and shdr in {1, 3}:
if inner and (shdr in {1, 3} or null_cipher):
# parse clear-text NAS message container
cont, err = parse_NASLTE_MO(Msg[3].get_val(), inner=inner)
if cont is not None:
Expand Down Expand Up @@ -149,7 +151,7 @@ def parse_NASLTE_MO(buf, inner=True, sec_hdr=True):
return Msg, err


def parse_NASLTE_MT(buf, inner=True, sec_hdr=True):
def parse_NASLTE_MT(buf, inner=True, sec_hdr=True, null_cipher=False):
"""Parses a Mobile Terminated LTE NAS message bytes' buffer
Args:
Expand All @@ -159,6 +161,8 @@ def parse_NASLTE_MT(buf, inner=True, sec_hdr=True):
decode NASContainer within EMM NAS Transport message if possible
sec_hdr: if True, handle the NAS EMM security header
otherwise, just consider the NAS message is in plain text
null_cipher: if True, try to decode the 1st level inner payload, even if security header
indicates encryption is applied, but suppose null-cipher is used
Returns:
element, err: 2-tuple
Expand All @@ -181,7 +185,7 @@ def parse_NASLTE_MT(buf, inner=True, sec_hdr=True):
# error 96, invalid mandatory info
return None, 96
#
if inner and shdr in {1, 3}:
if inner and (shdr in {1, 3} or null_cipher):
# parse clear-text NAS message container
cont, err = parse_NASLTE_MT(Msg[3].get_val(), inner=inner)
if cont is not None:
Expand Down

0 comments on commit 18aefa0

Please sign in to comment.