From 70db47cbbc8dae6f2b9903abcb72c05a5455ff53 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Thu, 10 Nov 2022 16:11:39 +0100 Subject: [PATCH] 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 --- kd2.go | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 kd2.go diff --git a/kd2.go b/kd2.go new file mode 100644 index 0000000..a4b1dc5 --- /dev/null +++ b/kd2.go @@ -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) + } +}