aboutsummaryrefslogtreecommitdiff
path: root/internal/readpassword
diff options
context:
space:
mode:
authorDmitry Yu Okunev2018-06-25 23:52:55 +0200
committerJakob Unterwurzacher2018-07-01 20:56:22 +0200
commit978f1f3f6d44d1e71c85b5ea2ac13e80cde773bb (patch)
treebbbdb1d7e16c83300d8c8a2de9a67d2a112d04cd /internal/readpassword
parent3f9a4bbcaa7c3c78b2c709373172503a67084611 (diff)
Implemented the support of Trezor devices.
Diffstat (limited to 'internal/readpassword')
-rw-r--r--internal/readpassword/trezor.go84
1 files changed, 75 insertions, 9 deletions
diff --git a/internal/readpassword/trezor.go b/internal/readpassword/trezor.go
index 45edfd8..be9c22a 100644
--- a/internal/readpassword/trezor.go
+++ b/internal/readpassword/trezor.go
@@ -5,31 +5,97 @@ import (
"github.com/rfjakob/gocryptfs/internal/exitcodes"
"github.com/rfjakob/gocryptfs/internal/tlog"
+
+ "github.com/xaionaro-go/cryptoWallet"
+ "github.com/xaionaro-go/cryptoWallet/vendors"
)
const (
// TrezorPayloadLen is the length of the payload data passed to Trezor's
// CipherKeyValue function.
- TrezorPayloadLen = 32
+ TrezorPayloadLen = 32
+ trezorNonce = "" // the "nonce" is optional and has no use in here
+ trezorKeyName = "gocryptfs"
+ trezorKeyDerivationPath = `m/10019'/0'`
)
-// Trezor reads 16 deterministically derived bytes from a
+func trezorGetPin(title, description, ok, cancel string) ([]byte, error) {
+ return Once("", title), nil
+}
+func trezorGetConfirm(title, description, ok, cancel string) (bool, error) {
+ return false, nil // do not retry on connection failure
+}
+
+// Trezor reads 32 deterministically derived bytes from a
// SatoshiLabs Trezor USB security module.
// The bytes are pseudorandom binary data and may contain null bytes.
-// This function either succeeds and returns 16 bytes or calls os.Exit to end
+// This function either succeeds and returns 32 bytes or calls os.Exit to end
// the application.
func Trezor(payload []byte) []byte {
if len(payload) != TrezorPayloadLen {
tlog.Fatal.Printf("Invalid TrezorPayload length: wanted %d, got %d bytes\n", TrezorPayloadLen, len(payload))
os.Exit(exitcodes.LoadConf)
}
- var err error
- // TODO try to read bytes here....
- // Handle errors
+
+ // Find all trezor devices
+ trezors := cryptoWallet.Find(cryptoWallet.Filter{
+ VendorID: &[]uint16{vendors.GetVendorID("satoshilabs")}[0],
+ ProductIDs: []uint16{1 /* Trezor One */},
+ })
+
+ // ATM, we require to one and only one trezor device to be connected.
+ // The support of multiple trezor devices is not implemented, yet.
+ if len(trezors) == 0 {
+ tlog.Fatal.Printf("Trezor device is not found. Check the connection.")
+ os.Exit(exitcodes.TrezorError)
+ }
+ if len(trezors) > 1 {
+ 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))
+ os.Exit(exitcodes.TrezorError)
+ }
+
+ // Using the first found device
+ trezor := trezors[0]
+
+ // Trezor may ask for PIN or Passphrase. Setting the handler for this case.
+ trezor.SetGetPinFunc(trezorGetPin)
+
+ // In some cases (like lost connection to the Trezor device and cannot
+ // reconnect) it's required to get a confirmation from the user to
+ // retry to reconnect. Setting the handler for this case.
+ trezor.SetGetConfirmFunc(trezorGetConfirm)
+
+ // To reset the state of the device and check if it's initialized.
+ // If device is not initialized then trezor.Reset() will return an
+ // error.
+ err := trezor.Reset()
if err != nil {
- tlog.Fatal.Printf("xxx some error was encountered...")
+ tlog.Fatal.Printf("Cannot reset the Trezor device. Error: %v", err.Error())
os.Exit(exitcodes.TrezorError)
}
- tlog.Warn.Println("XXX readpassword.Trezor(): not implemented yet - returning hardcoded dummy bytes XXX")
- return []byte("1234567890123456")
+
+ // To generate a deterministic key we trying to decrypt our
+ // predefined constant key using the Trezor device. The resulting key
+ // will depend on next variables:
+ // * the Trezor master key;
+ // * the passphrase (passed to the Trezor).
+ //
+ // The right key will be received only if both values (mentioned
+ // above) are correct.
+ //
+ // Note:
+ // Also the resulting key depends on this values (that we defined as
+ // constants above):
+ // * the key derivation path;
+ // * the "encrypted" payload;
+ // * the nonce;
+ // * the key name.
+ key, err := trezor.DecryptKey(trezorKeyDerivationPath, payload, []byte(trezorNonce), trezorKeyName)
+ if err != nil {
+ tlog.Fatal.Printf("Cannot get the key from the Trezor device. Error description:\n\t%v", err.Error())
+ os.Exit(exitcodes.TrezorError)
+ }
+
+ // Everything ok
+ return key
}