Proper handling of passphrase for Trezor T

This commit is contained in:
nicolas.dorier 2019-12-10 18:16:52 +09:00
parent d9cd916440
commit 12055a000b
No known key found for this signature in database
GPG Key ID: 6618763EF09186FE
2 changed files with 24 additions and 62 deletions

View File

@ -64,7 +64,6 @@ namespace BTCPayServer.Controllers
HwiEnumerateEntry deviceEntry = null;
HDFingerprint? fingerprint = null;
string password = null;
bool pinProvided = false;
var websocketHelper = new WebSocketHelper(websocket);
async Task<bool> RequireDeviceUnlocking()
@ -79,39 +78,19 @@ namespace BTCPayServer.Controllers
await websocketHelper.Send("{ \"error\": \"need-initialized\"}", cancellationToken);
return true;
}
if ((deviceEntry.Code is HwiErrorCode.DeviceNotReady || deviceEntry.NeedsPinSent is true)
&& !pinProvided)
if (deviceEntry.Code is HwiErrorCode.DeviceNotReady && IsTrezorT(deviceEntry))
{
if (!IsTrezorT(deviceEntry))
{
await websocketHelper.Send("{ \"error\": \"need-pin\"}", cancellationToken);
return true;
}
else
{
try
{
// On trezor T this will prompt the password! (https://github.com/bitcoin-core/HWI/issues/283)
await device.GetXPubAsync(new KeyPath("44'"), cancellationToken);
}
catch (HwiException ex) when (ex.ErrorCode == HwiErrorCode.DeviceAlreadyUnlocked)
{
pinProvided = true;
}
await websocketHelper.Send("{ \"error\": \"need-passphrase-on-device\"}", cancellationToken);
return true;
}
await websocketHelper.Send("{ \"error\": \"need-passphrase-on-device\"}", cancellationToken);
return true;
}
if (deviceEntry.Code is HwiErrorCode.DeviceNotReady || deviceEntry.NeedsPinSent is true)
{
await websocketHelper.Send("{ \"error\": \"need-pin\"}", cancellationToken);
return true;
}
if ((deviceEntry.Code is HwiErrorCode.DeviceNotReady || deviceEntry.NeedsPassphraseSent is true) && password == null)
{
if (IsTrezorT(deviceEntry))
{
await websocketHelper.Send("{ \"error\": \"need-passphrase-on-device\"}", cancellationToken);
}
else
{
await websocketHelper.Send("{ \"error\": \"need-passphrase\"}", cancellationToken);
}
await websocketHelper.Send("{ \"error\": \"need-passphrase\"}", cancellationToken);
return true;
}
return false;
@ -198,7 +177,6 @@ namespace BTCPayServer.Controllers
}
catch (HwiException ex) when (ex.ErrorCode == HwiErrorCode.DeviceAlreadyUnlocked)
{
pinProvided = true;
await websocketHelper.Send("{ \"error\": \"device-already-unlocked\"}", cancellationToken);
continue;
}
@ -206,7 +184,6 @@ namespace BTCPayServer.Controllers
var pin = int.Parse(await websocketHelper.NextMessageAsync(cancellationToken), CultureInfo.InvariantCulture);
if (await device.SendPinAsync(pin, cancellationToken))
{
pinProvided = true;
await websocketHelper.Send("{ \"info\": \"the pin is correct\"}", cancellationToken);
}
else
@ -279,15 +256,23 @@ namespace BTCPayServer.Controllers
result.Add(new JProperty("keyPath", keyPath.ToString()));
await websocketHelper.Send(result.ToString(), cancellationToken);
break;
case "refresh-device":
case "ask-passphrase":
case "ask-device":
DeviceSelector deviceSelector = (command == "refresh-device" && deviceEntry != null ? deviceEntry.DeviceSelector : null);
if (command == "ask-passphrase")
{
if (deviceEntry == null)
{
await websocketHelper.Send("{ \"error\": \"need-device\"}", cancellationToken);
continue;
}
// The make the trezor T ask for password
await device.GetXPubAsync(new KeyPath("44'"), cancellationToken);
}
password = null;
pinProvided = false;
deviceEntry = null;
device = null;
var entries = (await hwi.EnumerateEntriesAsync(cancellationToken)).ToList();
deviceEntry = entries.Where(h => deviceSelector == null || SameSelector(deviceSelector, h.DeviceSelector)).FirstOrDefault();
deviceEntry = entries.FirstOrDefault();
if (deviceEntry == null)
{
await websocketHelper.Send("{ \"error\": \"no-device\"}", cancellationToken);

View File

@ -42,7 +42,6 @@ var vaultui = (function () {
unexpectedError: new VaultFeedback("failed", "An unexpected error happened. ({{0}})", "vault-feedback3", "unknown-error"),
invalidNetwork: new VaultFeedback("failed", "The device is targetting a different chain.", "vault-feedback3", "invalid-network"),
needPin: new VaultFeedback("?", "Enter the pin.", "vault-feedback3", "need-pin"),
needPinOnDevice: new VaultFeedback("?", "Please, enter the pin on the device.", "vault-feedback3", "need-pin-on-device"),
incorrectPin: new VaultFeedback("failed", "Incorrect pin code.", "vault-feedback3", "incorrect-pin"),
invalidPasswordConfirmation: new VaultFeedback("failed", "Invalid password confirmation.", "vault-feedback3", "invalid-password-confirm"),
wrongWallet: new VaultFeedback("failed", "This device can't sign the transaction. (Wrong device, wrong passphrase or wrong device fingerprint in your wallet settings)", "vault-feedback3", "wrong-wallet"),
@ -130,15 +129,10 @@ var vaultui = (function () {
if (await self.askForPassphrase())
return true;
}
if (json.error === "need-pin-on-device" || json.error === "need-passphrase-on-device") {
if (json.error === "need-passphrase-on-device") {
handled = true;
if (json.error === "need-pin-on-device") {
show(VaultFeedbacks.needPinOnDevice);
} else {
show(VaultFeedbacks.needPassphraseOnDevice);
}
await self.waitClickContinue();
self.bridge.socket.send("refresh-device");
show(VaultFeedbacks.needPassphraseOnDevice);
self.bridge.socket.send("ask-passphrase");
var json = await self.bridge.waitBackendMessage();
if (json.hasOwnProperty("error")) {
showError(json);
@ -240,23 +234,6 @@ var vaultui = (function () {
});
};
/**
* @returns {Promise}
*/
this.waitClickContinue = function () {
$("#vault-confirm").css("display", "block");
$("#vault-confirm").text("Continue");
return new Promise(function (resolve, reject) {
$("#vault-confirm").click(async function (e) {
e.preventDefault();
$("#vault-confirm").css("display", "none");
$(this).unbind();
resolve("");
});
});
};
/**
* @returns {Promise<string>}
*/