Skip to content
LIVE FEED

BlogQuy tắc đọc & cắt khúc một gói OTA từ chuỗi hex

Quy tắc đọc & cắt khúc một gói OTA từ chuỗi hex

Hướng dẫn cách tự bổ một chuỗi hex OTA thành các trường mà không cần đoán — vì mỗi trường đều tự khai độ dài của nó, hoặc có độ dài cố định theo chuẩn.


0. Nền tảng: 1 byte = 2 chữ số hex

  • 1 byte = 8 bit.
  • 1 chữ số hex biểu diễn 4 bit (16 giá trị 0–F, vì 16 = 2⁴).
  • Vậy cần 2 chữ số hex mới đủ 1 byte.
  • “Nửa byte” (4 bit = 1 chữ số hex) gọi là nibble. 1 byte = 2 nibble.
Byte (hex)Nibble caoNibble thấpThập phân
00000 (nhỏ nhất)
0D0D13
1F1F31
A0A0160
FFFF255 (lớn nhất)

Hệ quả thực tế:

  • TAR dài 3 byte → chiếm 6 ký tự hex (A1B2C3).
  • short_message = 36 byte → viết ra 72 ký tự hex.
  • Số ký tự hex luôn chẵn. Nếu lẻ → chuỗi lỗi (thiếu/thừa 1 nibble).

Cách đọc nhanh: gom 2 ký tự một lần từ trái sang.

02 70 00 00 1F 0D …   ✔ mỗi cặp = 1 byte
0270 0000 1F0D …      -> SAI: đây là gom 2 byte, dễ nhầm

⚠️ Đừng lẫn “cặp chữ số hex” với “cặp chữ số thập phân của số điện thoại”. Số điện thoại BCD nhét 2 chữ số 0–9 vào 1 byte rồi đảo nibble (“84”→48) — đó là mã hoá riêng của trường địa chỉ SMS. Quy ước “1 byte = 2 ký tự hex” thì luôn đúng ở mọi nơi.


1. Ba loại “manh mối” để biết chỗ cắt

Bạn không đoán vị trí dấu |. Mỗi trường thuộc một trong ba loại sau:

LoạiCách biết độ dàiVí dụ
Độ dài cố địnhHọc thuộc bảng theo chuẩnCPL 2, CHL 1, TAR 3, CNTR 5…
Có byte khai độ dài đứng ngay trướcĐọc byte đó, lấy đúng bấy nhiêuUDHL, Lc của APDU
Suy ra từ trường tổngLấy tổng trừ các phần đã biếtSecured Data = CPL − 14; CC = CHL − 13

Nói cách khác: UDHL, CPL, CHL, Lc là những “cây thước” nhúng sẵn trong gói. Đọc thước → cắt → thước tiếp theo chỉ cho bạn đoạn kế.


2. Bảng độ dài CỐ ĐỊNH của OTA Command Packet (TS 23.048)

Học thuộc thứ tự và độ dài này là cắt được phần header:

Thứ tựTrườngĐộ dài (byte)
1CPL2
2CHL1
3SPI2
4KIc1
5KID1
6TAR3
7CNTR5
8PCNTR1
9CC (nếu có)= CHL − 13
10Secured Data= CPL − 1 − CHL

Mẹo nhớ dãy header: 2 · 1 · 2 · 1 · 1 · 3 · 5 · 1.


3. Quy trình cắt — 4 bước

Bước 1: UDH        — đọc byte đầu (UDHL), lấy đúng bấy nhiêu byte
Bước 2: OTA header — cắt theo bảng cố định 2·1·2·1·1·3·5·1
Bước 3: kiểm chéo  — dùng CHL và CPL để xác nhận + tính Secured Data
Bước 4: APDU       — mỗi APDU đọc Lc để biết dài bao nhiêu

Bước 1 — UDH: byte đầu tự khai độ dài

02 70 00
│  └──┴─ 2 byte (vì byte đầu = 02)
└─ UDHL = 2

Đọc 02 → UDH gồm 2 byte kế (70 00). Cắt xong UDH. (70 = Command Packet; chiều SIM trả về dùng 71 = Response Packet.)

Bước 2 — OTA header: cắt theo bảng cố định

00 1F | 0D | 00 00 | 00 | 00 | A1 B2 C3 | 00 00 00 00 01 | 00
  2     1     2      1    1       3            5            1   ← byte
 CPL   CHL   SPI   KIc  KID     TAR         CNTR         PCNTR

Bước 3 — kiểm tra chéo bằng CHL và CPL

CHL = 0D = 13 khai “header dài 13 byte” = SPI..PCNTR. Đếm lại: 2+1+1+3+5+1 = 13 ✔ → Nếu có CC, CHL > 13, phần dôi ra = độ dài CC.

CPL = 00 1F = 31 khai “toàn bộ phần sau CPL dài 31 byte”. → Secured Data = CPL − (1 byte CHL + CHL) = 31 − (1 + 13) = 17 byte.

CPL (31)  −  [ 1 byte CHL  +  CHL=13 ]  =  Secured Data (17)

Bước 4 — Secured Data: mỗi APDU tự khai Lc

APDU có cấu trúc 4 byte header + 1 byte Lc + đúng Lc byte data:

A0 A4 00 00 02 6F46          Lc=02 → lấy 2 byte → APDU 1 = 7 byte
A0 D6 00 00 05 0056494554    Lc=05 → lấy 5 byte → APDU 2 = 10 byte

Kiểm tra: 7 + 10 = 17 byte = đúng Secured Data ở bước 3 ✔

Vòng lặp đọc từng APDU:

đọc 4 byte (CLA INS P1 P2) → đọc byte thứ 5 (Lc)
→ lấy đúng Lc byte data → xong 1 APDU → còn byte thì lặp lại

4. Ví dụ HOÀN CHỈNH đã cắt

Chuỗi gốc:

027000001F0D00000000A1B2C3000000000100A0A40000026F46A0D60000050056494554

Cắt ra:

02 70 00 | 00 1F | 0D | 00 00 | 00 | 00 | A1 B2 C3 | 00 00 00 00 01 | 00 | A0A40000026F46 | A0D60000050056494554
Lát cắtTrườngÝ nghĩa
02 70 00UDHUDHL=2, IEI=70 (Command Packet)
00 1FCPL31 byte còn lại
0DCHL13 byte header
00 00SPIkhông mã hoá, không ký
00KIcchỉ số khoá mã hoá
00KIDchỉ số khoá chữ ký
A1 B2 C3TARapplet đích
00 00 00 00 01CNTRbộ đếm = 1
00PCNTR0 byte đệm
A0A40000026F46APDUSELECT EF_SPN (6F46)
A0D60000050056494554APDUUPDATE BINARY, ghi 00 “VIET”

Tổng: 3 + 2 + 1 + 13 + 17 = 36 byte = sm_length ✔


5. Tự luyện

Thử tự cắt chuỗi Warehouse này theo đúng 4 bước:

027000002E0D00000000B00010000000000100 0B 3834393832323232323232 48652054686F6E672042696E68205468756F6E67

Gợi ý: UDH 3 byte → CPL=002E=46 → CHL=13 → Secured Data = 46 − 14 = 32 byte. Trong Secured Data lần này KHÔNG phải APDU mà là dữ liệu applet: 0B = độ dài số (11) → 11 byte ASCII số UE B → phần còn lại là text.


6. Bảng công thức nhanh (tra khi cần)

Muốn tínhCông thức
Số byte của chuỗi hex(số ký tự hex) ÷ 2
Độ dài UDHđọc byte UDHL (byte đầu)
Vị trí bắt đầu OTAsau UDH = 1 + UDHL
Độ dài CCCHL − 13
Độ dài Secured DataCPL − 1 − CHL
Độ dài 1 APDU5 + Lc (với case 3s có data)
Kiểm tra tổng1 + UDHL + 2 + CPL == sm_length

7. Ba dấu hiệu chuỗi bị LỖI (cắt không khớp)

  1. Số ký tự hex lẻ → thiếu/thừa 1 nibble.
  2. CPL ≠ số byte thật đứng sau CPL → sai độ dài (lỗi hay gặp nhất).
  3. CHL < 13 hoặc CHL > cả gói → header vô lý.
  4. (dấu hiệu phụ) Secured Data đọc ra chữ người-đọc-được trong khi lẽ ra là APDU/nhị phân đã mã hoá → dựng sai hoặc quên bật bảo mật.

Tài liệu học tập. Áp dụng cho OTA Command Packet theo 3GPP TS 23.048 / TS 31.115.

Contact
Facebook
TOP