Add AlphaRne key decoder

See https://www.eevblog.com/forum/testgear/hacking-the-hdo1khdo4k-rigol-12-bit-scope/msg4499302/#msg4499302

Signed-off-by: Olliver Schinagl <oliver@schinagl.nl>
This commit is contained in:
Olliver Schinagl 2022-11-10 16:11:39 +01:00
parent 4c0beb9d88
commit 70db47cbbc
No known key found for this signature in database
GPG Key ID: 96E1A3A6C9044763

199
kd2.go Normal file
View File

@ -0,0 +1,199 @@
package main
import (
"bytes"
"encoding/binary"
"errors"
"flag"
"fmt"
"hash/crc32"
"io/ioutil"
"os/user"
"path/filepath"
"strconv"
"strings"
)
var dataFile string
var xxKey string
func initCmdline() {
flag.StringVar(&dataFile, "f", "Key.data", "file to decode")
flag.StringVar(&xxKey, "key", "", "key data")
flag.Parse()
}
func Expand(path string) string {
if len(path) == 0 || path[0] != '~' {
return path
}
usr, err := user.Current()
if err != nil {
return path
}
return filepath.Join(usr.HomeDir, path[1:])
}
func HexString(data []byte) string {
var buf bytes.Buffer
for i := 0; i < len(data)-1; i++ {
buf.WriteString(fmt.Sprintf("%02X ", data[i]))
}
buf.WriteString(fmt.Sprintf("%02X", data[len(data)-1]))
return buf.String()
}
const delta = 0x9E3779B9
func mx(sum uint32, y uint32, z uint32, p uint32, e uint32, k []uint32) uint32 {
return ((z>>5 ^ y<<2) + (y>>3 ^ z<<4)) ^ ((sum ^ y) + (k[p&3^e] ^ z))
}
func fixk(k []uint32) []uint32 {
if len(k) < 4 {
key := make([]uint32, 4)
copy(key, k)
return key
}
return k
}
func XXTeaDecrypt(v []uint32, k []uint32) []uint32 {
length := uint32(len(v))
n := length - 1
k = fixk(k)
var y, z, sum, e, p, q uint32
y = v[0]
q = 6 + 52/length
for sum = q * delta; sum != 0; sum -= delta {
e = sum >> 2 & 3
for p = n; p > 0; p-- {
z = v[p-1]
v[p] -= mx(sum, y, z, p, e, k)
y = v[p]
}
z = v[n]
v[0] -= mx(sum, y, z, p, e, k)
y = v[0]
}
return v
}
var fileKey = []uint32{0xAB12CD34, 0xAB12CD34, 0xAB12CD34, 0xAB12CD34}
var defaultKey = []uint32{0x03920001, 0x08410841, 0x18C32104, 0x318639C7}
func decodeXXTEA(data []byte, key []uint32) []byte {
N := len(data)
u32 := make([]uint32, N>>2)
for i, _ := range u32 {
u32[i] = binary.LittleEndian.Uint32(data[i*4:])
}
u32d := XXTeaDecrypt(u32, key)
res := make([]uint8, N)
for i, v := range u32d {
binary.LittleEndian.PutUint32(res[i*4:], v)
}
return res
}
func parseKey(k string) ([]uint32, error) {
parts := strings.Split(k, ",")
if len(parts) == 0 {
return nil, errors.New("invalid key data")
}
res := make([]uint32, len(parts))
for i, s := range parts {
if strings.HasPrefix(s, "0x") {
s = s[2:]
}
x, err := strconv.ParseUint(s, 16, 64)
if nil != err {
return nil, err
}
res[i] = uint32(x)
}
return res, nil
}
func DecryptFile(name string, key []uint32) ([]uint8, error) {
data, err := ioutil.ReadFile(Expand(name))
if nil != err {
return nil, err
}
dd := decodeXXTEA(data, key)
if bytes.Index(dd, []uint8{0}) < 0x10 {
fmt.Printf("raw data:\n%v\n", HexString(dd))
} else {
fmt.Printf("string data:%v\n", string(dd))
}
return dd, nil
}
func parseVendorData(data []uint8) error {
crc1 := binary.LittleEndian.Uint32(data)
size := binary.LittleEndian.Uint32(data[4:])
crc2 := crc32.ChecksumIEEE(data[8 : 8+size])
if crc1 != crc2 {
return errors.New("vendor crc mismatch")
}
fmt.Printf("vendor crc ok %x\n", crc1)
ofs := 8
for ofs < len(data) {
l1 := binary.LittleEndian.Uint32(data[ofs:])
ofs += 4
id := binary.LittleEndian.Uint32(data[ofs:])
ofs += int(l1)
l2 := binary.LittleEndian.Uint32(data[ofs:])
ofs += 4
item := data[ofs : ofs+int(l2)]
crc1 = binary.LittleEndian.Uint32(item)
size = binary.LittleEndian.Uint32(item[4:])
strSize := binary.LittleEndian.Uint32(item[8:])
crc2 := crc32.ChecksumIEEE(item[8 : 12+size])
if crc1 != crc2 {
fmt.Printf("crc mismatch id:%x crc:%x,%x\n", id, crc1, crc2)
continue
}
dd := decodeXXTEA(item[12:], defaultKey)
ofs += int(l2)
//n := bytes.Index(dd,[]uint8{0})
n := int(strSize)
name := string(dd[:n])
n = (n + 3) & (^0x3)
edata := make([]uint32, (int(size)-n)>>2)
for i := 0; i < len(edata); i++ {
edata[i] = binary.LittleEndian.Uint32(dd[n+4*i:])
}
fmt.Printf("id:%x | str:%v | data:%x\n", id, name, edata)
}
return nil
}
func main() {
initCmdline()
k, _ := parseKey(xxKey)
if nil != k {
N := len(k)
if N < 4 {
for i := N; i < 4; i++ {
k = append(k, k[N-1])
}
}
} else {
if strings.HasSuffix(dataFile, "vendor.bin") {
k = fileKey
} else {
k = defaultKey
}
}
fmt.Printf("using key %x\n", k)
data, err := DecryptFile(dataFile, k)
if nil != err {
fmt.Printf("error %v\n", err)
return
}
if strings.HasSuffix(dataFile, "vendor.bin") {
parseVendorData(data)
}
}