pySim.ota.OtaDialectSms: Implement command decoding

So far we only implemented command encoding and response decoding.
Let's also add command decoding, which is useful for example when
decoding protocol traces.

Change-Id: Id666cea8a91a854209f3c19c1f09b512bb493c85
This commit is contained in:
Harald Welte
2024-06-09 16:18:51 +02:00
committed by laforge
parent 8bd551af32
commit 32401a54e6
2 changed files with 66 additions and 7 deletions

View File

@@ -18,7 +18,7 @@
import zlib
import abc
import struct
from typing import Optional
from typing import Optional, Tuple
from construct import Enum, Int8ub, Int16ub, Struct, Bytes, GreedyBytes, BitsInteger, BitStruct
from construct import Flag, Padding, Switch, this
@@ -388,6 +388,49 @@ class OtaDialectSms(OtaDialect):
return envelope_data
def decode_cmd(self, otak: OtaKeyset, encoded: bytes) -> Tuple[bytes, dict, bytes]:
"""Decode an encoded (encrypted, signed) OTA SMS Command-APDU."""
if True: # TODO: how to decide?
cpl = int.from_bytes(encoded[:2], 'big')
part_head = encoded[2:2+8]
ciph = encoded[2+8:]
envelope_data = otak.crypt.decrypt(ciph)
else:
part_head = encoded[:8]
envelope_data = encoded[8:]
hdr_dec = self.hdr_construct.parse(part_head)
# strip counter part from front of envelope_data
part_cnt = envelope_data[:6]
cntr = int.from_bytes(part_cnt[:5], 'big')
pad_cnt = int.from_bytes(part_cnt[5:], 'big')
envelope_data = envelope_data[6:]
spi = hdr_dec['spi']
if spi['rc_cc_ds'] == 'cc':
# split cc from front of APDU
cc = envelope_data[:8]
apdu = envelope_data[8:]
# verify CC
temp_data = cpl.to_bytes(2, 'big') + part_head + part_cnt + apdu
otak.auth.check_sig(temp_data, cc)
elif spi['rc_cc_ds'] == 'rc':
# CRC32
crc32_rx = int.from_bytes(envelope_data[:4], 'big')
# FIXME: crc32_computed = zlip.crc32(
# FIXME: verify RC
raise NotImplementedError
apdu = envelope_data[4:]
elif spi['rc_cc_ds'] == 'no_rc_cc_ds':
apdu = envelope_data
else:
raise ValueError("Invalid rc_cc_ds: %s" % spi['rc_cc_ds'])
apdu = apdu[:len(apdu)-pad_cnt]
return hdr_dec['tar'], spi, apdu
def decode_resp(self, otak: OtaKeyset, spi: dict, data: bytes) -> ("OtaDialectSms.SmsResponsePacket", Optional["CompactRemoteResp"]):
if isinstance(data, str):
data = h2b(data)