Skip to content

Commit

Permalink
🔒 [FIX] Trustchain switch device while logged in case (#7603)
Browse files Browse the repository at this point in the history
* Fix the remove member with wrong seed test

* Detect wrong seed device error

* Re-record "remove member with wrong seed"

* Update changeset

---------

Co-authored-by: Theophile Sandoz <Theophile Sandoz>
  • Loading branch information
thesan authored Aug 19, 2024
1 parent acc5226 commit 5c738cb
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 131 deletions.
6 changes: 6 additions & 0 deletions .changeset/blue-ads-smell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@ledgerhq/errors": minor
"@ledgerhq/trustchain": minor
---

Fix Trustchain error when switching device while logged in
3 changes: 3 additions & 0 deletions libs/ledgerjs/packages/errors/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,9 @@ export const StatusCodes = {
INVALID_RESTORE_STATE: 0x6643,
INVALID_CHUNK_LENGTH: 0x6734,
INVALID_BACKUP_HEADER: 0x684a,

// Not documented:
TRUSTCHAIN_WRONG_SEED: 0xb007,
};

export function getAltStatusMessage(code: number): string | undefined | null {
Expand Down
186 changes: 67 additions & 119 deletions libs/trustchain/mocks/scenarios/removeMemberWithTheWrongSeed.json

Large diffs are not rendered by default.

25 changes: 16 additions & 9 deletions libs/trustchain/src/HWDeviceProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { crypto, device } from "@ledgerhq/hw-trustchain";
import getApi from "./api";
import { genericWithJWT } from "./auth";
import { AuthCachePolicy, JWT, TrustchainDeviceCallbacks, WithDevice } from "./types";
import { TrustchainNotAllowed } from "./errors";

export class HWDeviceProvider {
/**
Expand Down Expand Up @@ -56,22 +57,28 @@ export class HWDeviceProvider {
try {
return await lastValueFrom(runWithDevice(transport => from(job(device.apdu(transport)))));
} catch (error) {
if (
error instanceof TransportStatusError &&
[StatusCodes.USER_REFUSED_ON_DEVICE, StatusCodes.CONDITIONS_OF_USE_NOT_SATISFIED].includes(
error.statusCode,
)
) {
throw new UserRefusedOnDevice();
if (!(error instanceof TransportStatusError)) {
throw error;
}
switch (error.statusCode) {
case StatusCodes.USER_REFUSED_ON_DEVICE:
case StatusCodes.CONDITIONS_OF_USE_NOT_SATISFIED:
throw new UserRefusedOnDevice();

case StatusCodes.TRUSTCHAIN_WRONG_SEED:
this.clearJwt();
throw new TrustchainNotAllowed();

default:
throw error;
}
throw error;
} finally {
callbacks?.onEndRequestUserInteraction();
}
}

public async refreshJwt(deviceId: string, callbacks?: TrustchainDeviceCallbacks): Promise<void> {
this.jwt = await this.withJwt(deviceId, this.api.refreshAuth, undefined, callbacks);
this.jwt = await this.withJwt(deviceId, this.api.refreshAuth, "cache", callbacks);
}

public clearJwt() {
Expand Down
4 changes: 2 additions & 2 deletions libs/trustchain/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export class SDK implements TrustchainSDK {
let type = TrustchainResultType.restored;

const withJwt: WithJwt = job =>
this.hwDeviceProvider.withJwt(deviceId, job, undefined, callbacks);
this.hwDeviceProvider.withJwt(deviceId, job, "cache", callbacks);
const withHw: WithDevice = job => this.hwDeviceProvider.withHw(deviceId, job, callbacks);

let trustchains = await withJwt(this.api.getTrustchains);
Expand Down Expand Up @@ -212,7 +212,7 @@ export class SDK implements TrustchainSDK {
callbacks?: TrustchainDeviceCallbacks,
): Promise<Trustchain> {
const withJwt: WithJwt = job =>
this.hwDeviceProvider.withJwt(deviceId, job, undefined, callbacks);
this.hwDeviceProvider.withJwt(deviceId, job, "cache", callbacks);
const withHw: WithDevice = job => this.hwDeviceProvider.withHw(deviceId, job, callbacks);

// invariant because the sdk does not support this case, and the UI should not allows it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export async function scenario(

const device = await switchDeviceSeed();

await expect(sdk2.removeMember(device.id, trustchain, member2creds, member1)).rejects.toThrow(
await expect(sdk1.removeMember(device.id, trustchain, member2creds, member1)).rejects.toThrow(
TrustchainNotAllowed,
);

Expand Down

0 comments on commit 5c738cb

Please sign in to comment.