Jimmy's blog

TCL, DOCSIS 測試筆記

DOCSIS BPI 解密 - 解開 PDU

| Comments

簡介

DOCSIS BPI 解密 - 取得 TEK中已經把 TEK 解出來,接下來只要使用對的的演算法就能解開加密的封包了。 延續之前的範例,用 Key Reply 裡的參數來解密

加解密參數

Key Reply 的內容為 其中用來加解密的 key 為 TEK 以及 IV,此範例中 TEK=0xe6600fd8852ef5ab IV=0x810e528e1c5fda1a 其他參數用來指示這組 key 能用多久以及提供一個序號,在 DOCSIS 封包的 header 裡會帶有這個序號標示使用的是那一組 key。 真正被加密的部份只有 Packet PDU (Layer 2 Ethernet frame) 中 DA (destination MAC) SA (source MAC) 之後的內容。以下只探討 Packet PDU 的部份。

加密演算法

加密 PDU 使用的是 DES,這是一種 Block cipher 有多種工作模式,DES 使用的 block size 為 8 bytes,DOCSIS BPI 用了 CBC 和 CFB 這兩種工作模式。 由於封包長度不固定,但是使用這種加密方式輸入必須要是 8 bytes 的整數倍,所以會用 2 種工作模式來處理。

CBC only

若要加密的內容正好是 8 bytes 的整數倍,直接使用 DES-CBC 加密 若輸入為

DA 01 02 03 04 05 06
SA f1 f2 f3 f4 f5 f6
Type/Len 00 01
User Data 02 03 04 05 06 07 08 09 0a 0b
CRC 88 41 65 06


則加密後會變成

DA 01 02 03 04 05 06
SA f1 f2 f3 f4 f5 f6
Type/Len 0d da
User Data 5a cb d0 5e 55 67 9f 04 d1 b6
CRC 41 3d 4e ed


使用 tcl 解密

1
2
3
4
5
6
7
package require tclDES
set iv  [binary format H* 810e528e1c5fda1a]
set keyset [::des::keyset create [binary format H* e6600fd8852ef5ab]]
set cipher [binary format H* 0dda5acbd05e55679f04d1b6413d4eed ]
set plain [::des::decrypt $keyset $cipher cbc iv]
binary scan $plain H* plain
puts plaintext=$plain

plaintext=000102030405060708090a0b88416506

CBC + CFB

若要加密的內容大於 8 bytes 但不是 8 bytes 的整數倍要分成兩段加密,第一部份是 8 bytes 的整數倍使用 CBC,剩餘的部份使用 CFB。 若輸入為

DA 01 02 03 04 05 06
SA f1 f2 f3 f4 f5 f6
Type/Len 00 01
User Data 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e
CRC 91 d2 d1 9f


則加密後會變成

DA 01 02 03 04 05 06
SA f1 f2 f3 f4 f5 f6
Type/Len 0d 0a
User Data 5a cb d0 5e 55 67 51 47 46 86 8a 71 e5
CRC 77 ef ac 88

首先是 CBC 的部份,和之前作法相同,要加密的資料是 0x0001…0e91 這 16 bytes,剩下的 3 bytes 0xd2d19f 要特別處理,因為 DES 要輸入 8 bytes 整數倍,所以先補 0x00 補到 8 bytes, 接著再用 DES-CFB 加密 (此時使用的 key 不變,IV 換成 CBC 密文區塊中的最後 8 bytes),加密完後載取出前 3 bytes 即可,透過照種方式就能讓加密前後的資料長度維持不變。

同樣使用 tcl 解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package require tclDES
# CBC 區塊
set iv  [binary format H* 810e528e1c5fda1a]
set keyset [::des::keyset create [binary format H* e6600fd8852ef5ab]]
set cipher [binary format H* 0dda5acbd05e5567514746868a71e577]
set plain [::des::decrypt $keyset $cipher cbc iv]
binary scan $plain H* plain
puts plaintext=$plain

# CFB 區塊
set iv  [binary format H* 514746868a71e577] ; # IV 要換掉
set keyset [::des::keyset create [binary format H* e6600fd8852ef5ab]]
# CFB 工作模式的特性,解密時後面亂填不影響真正要的部份,這邊補0x00
set cipher [binary format H* efac880000000000]
set plain [string range [::des::decrypt $keyset $cipher cfb iv] 0 2]
binary scan $plain H* plain
puts plaintext=$plain

plaintext=000102030405060708090a0b0c0d0e91
plaintext=d2d19f

CFB only

若要加密的內容小於 8 bytes,就使用 DES-CFB,key 和 IV 使用 key reply 取得的資訊, 若輸入為

DA 01 02 03 04 05 06
SA f1 f2 f3 f4 f5 f6
Type/Len 00 01
User Data 02
CRC 88 ee 59 7e


加密後會變成

DA 01 02 03 04 05 06
SA f1 f2 f3 f4 f5 f6
Type/Len 17 86
User Data a8
CRC 03 a0 85 75
1
2
3
4
5
6
7
8
package require tclDES
set iv  [binary format H* 810e528e1c5fda1a]
set keyset [::des::keyset create [binary format H* e6600fd8852ef5ab]]
# 資料只有 7 bytes, 補一個 00
set cipher [binary format H* 1786a803a0857500]
set plain  [string range [::des::decrypt $keyset $cipher cfb iv] 0 6]
binary scan $plain H* plain
puts plaintext=$plain

plaintext=00010288ee597e

CRC

解密完後可以算一下 CRC 來驗證有沒有算錯,CRC 計算範圍是 Ethernet frame 扣除 CRC 4 bytes,以最後這個 CFB only 的範例來看

inputt = 0x010203040506f1f2f3f4f5f6000102

1
2
3
4
package require crc32
set crc [crc::crc32 [binary format H* 010203040506f1f2f3f4f5f6000102]]
binary scan [binary format i $crc] H* CRC
puts CRC=$CRC

CRC=88ee597e

Comments