Skip to content

Commit a2e1cc7

Browse files
xaionarorfjakob
authored andcommitted
Implemented the support of Trezor devices.
1 parent bec5047 commit a2e1cc7

File tree

1 file changed

+75
-9
lines changed

1 file changed

+75
-9
lines changed

internal/readpassword/trezor.go

+75-9
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,97 @@ import (
55

66
"github.com/rfjakob/gocryptfs/internal/exitcodes"
77
"github.com/rfjakob/gocryptfs/internal/tlog"
8+
9+
"github.com/xaionaro-go/cryptoWallet"
10+
"github.com/xaionaro-go/cryptoWallet/vendors"
811
)
912

1013
const (
1114
// TrezorPayloadLen is the length of the payload data passed to Trezor's
1215
// CipherKeyValue function.
13-
TrezorPayloadLen = 32
16+
TrezorPayloadLen = 32
17+
trezorNonce = "" // the "nonce" is optional and has no use in here
18+
trezorKeyName = "gocryptfs"
19+
trezorKeyDerivationPath = `m/10019'/0'`
1420
)
1521

16-
// Trezor reads 16 deterministically derived bytes from a
22+
func trezorGetPin(title, description, ok, cancel string) ([]byte, error) {
23+
return Once("", title), nil
24+
}
25+
func trezorGetConfirm(title, description, ok, cancel string) (bool, error) {
26+
return false, nil // do not retry on connection failure
27+
}
28+
29+
// Trezor reads 32 deterministically derived bytes from a
1730
// SatoshiLabs Trezor USB security module.
1831
// The bytes are pseudorandom binary data and may contain null bytes.
19-
// This function either succeeds and returns 16 bytes or calls os.Exit to end
32+
// This function either succeeds and returns 32 bytes or calls os.Exit to end
2033
// the application.
2134
func Trezor(payload []byte) []byte {
2235
if len(payload) != TrezorPayloadLen {
2336
tlog.Fatal.Printf("Invalid TrezorPayload length: wanted %d, got %d bytes\n", TrezorPayloadLen, len(payload))
2437
os.Exit(exitcodes.LoadConf)
2538
}
26-
var err error
27-
// TODO try to read bytes here....
28-
// Handle errors
39+
40+
// Find all trezor devices
41+
trezors := cryptoWallet.Find(cryptoWallet.Filter{
42+
VendorID: &[]uint16{vendors.GetVendorID("satoshilabs")}[0],
43+
ProductIDs: []uint16{1 /* Trezor One */},
44+
})
45+
46+
// ATM, we require to one and only one trezor device to be connected.
47+
// The support of multiple trezor devices is not implemented, yet.
48+
if len(trezors) == 0 {
49+
tlog.Fatal.Printf("Trezor device is not found. Check the connection.")
50+
os.Exit(exitcodes.TrezorError)
51+
}
52+
if len(trezors) > 1 {
53+
tlog.Fatal.Printf("It's more than one Trezor device connected. This case is not implemented, yet. The number of currently connected devices: %v.", len(trezors))
54+
os.Exit(exitcodes.TrezorError)
55+
}
56+
57+
// Using the first found device
58+
trezor := trezors[0]
59+
60+
// Trezor may ask for PIN or Passphrase. Setting the handler for this case.
61+
trezor.SetGetPinFunc(trezorGetPin)
62+
63+
// In some cases (like lost connection to the Trezor device and cannot
64+
// reconnect) it's required to get a confirmation from the user to
65+
// retry to reconnect. Setting the handler for this case.
66+
trezor.SetGetConfirmFunc(trezorGetConfirm)
67+
68+
// To reset the state of the device and check if it's initialized.
69+
// If device is not initialized then trezor.Reset() will return an
70+
// error.
71+
err := trezor.Reset()
2972
if err != nil {
30-
tlog.Fatal.Printf("xxx some error was encountered...")
73+
tlog.Fatal.Printf("Cannot reset the Trezor device. Error: %v", err.Error())
3174
os.Exit(exitcodes.TrezorError)
3275
}
33-
tlog.Warn.Println("XXX readpassword.Trezor(): not implemented yet - returning hardcoded dummy bytes XXX")
34-
return []byte("1234567890123456")
76+
77+
// To generate a deterministic key we trying to decrypt our
78+
// predefined constant key using the Trezor device. The resulting key
79+
// will depend on next variables:
80+
// * the Trezor master key;
81+
// * the passphrase (passed to the Trezor).
82+
//
83+
// The right key will be received only if both values (mentioned
84+
// above) are correct.
85+
//
86+
// Note:
87+
// Also the resulting key depends on this values (that we defined as
88+
// constants above):
89+
// * the key derivation path;
90+
// * the "encrypted" payload;
91+
// * the nonce;
92+
// * the key name.
93+
key, err := trezor.DecryptKey(trezorKeyDerivationPath, payload, []byte(trezorNonce), trezorKeyName)
94+
if err != nil {
95+
tlog.Fatal.Printf("Cannot get the key from the Trezor device. Error description:\n\t%v", err.Error())
96+
os.Exit(exitcodes.TrezorError)
97+
}
98+
99+
// Everything ok
100+
return key
35101
}

0 commit comments

Comments
 (0)