forked from andlabs/reallymine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
initio.go
107 lines (90 loc) · 2.27 KB
/
initio.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// 23 october 2015
package bridge
import (
"bytes"
"crypto/aes"
"encoding/binary"
"github.com/andlabs/reallymine/byteops"
"github.com/andlabs/reallymine/decryptloop"
)
type Initio struct{}
func (Initio) Name() string {
return "Initio"
}
func (Initio) Is(keySector []byte) bool {
return keySector[0] == 'W' &&
keySector[1] == 'D' &&
keySector[2] == 0x01 &&
keySector[3] == 0x14
}
func (Initio) NeedsKEK() bool {
return true
}
type InitioKeySector struct {
raw []byte
d struct { // d for "DEK block"
Magic [4]byte // 27 5D BA 35
Unknown [8]byte
Key [32]byte // stored as little-endian longs
}
}
func (Initio) DecryptKeySector(keySector []byte, kek []byte) (KeySector, error) {
// copy to avoid clobbering
keySector = byteops.DupBytes(keySector)
kek = byteops.DupBytes(kek)
byteops.SwapHalves(kek)
byteops.Reverse(kek)
kekcipher, err := aes.NewCipher(kek)
if err != nil {
return nil, err
}
for i := 0; i < len(keySector); i += 16 {
block := keySector[i : i+16]
byteops.SwapLongs(block)
kekcipher.Decrypt(block, block)
// Don't swap back; it'll be correct as-is.
}
return &InitioKeySector{
raw: keySector,
}, nil
}
func (ks *InitioKeySector) Raw() []byte {
return ks.raw
}
func (ks *InitioKeySector) valid() bool {
return ks.d.Magic[0] == 0x27 &&
ks.d.Magic[1] == 0x5D &&
ks.d.Magic[2] == 0xBA &&
ks.d.Magic[3] == 0x35
}
// Unlike the JMicron one, the Initio DEK block is at a fixed offset
// into the key sector.
const initioDEKOffset = 0x190
func (ks *InitioKeySector) DEK() (dek []byte, err error) {
r := bytes.NewReader(ks.raw[initioDEKOffset:])
// The endianness is most likely right, but unimportant since every field is [...]byte.
err = binary.Read(r, binary.LittleEndian, &(ks.d))
if err != nil {
return nil, err
}
if !ks.valid() {
return nil, ErrWrongKEK
}
// make a copy to avoid altering ks.d
dek = byteops.DupBytes(ks.d.Key[:])
byteops.SwapLongs(dek) // undo the little-endian-ness
byteops.SwapHalves(dek)
byteops.Reverse(dek)
return dek, nil
}
func (Initio) DecryptLoopSteps() decryptloop.StepList {
return decryptloop.StepList{
decryptloop.StepSwapLongs,
decryptloop.StepDecrypt,
// We DO need to swap again after this, though!
decryptloop.StepSwapLongs,
}
}
func init() {
Bridges = append(Bridges, Initio{})
}