From b1b6ad394c2e8cdcdee6fcf1d8678bdd22533422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Renaudeau?= Date: Thu, 21 Feb 2019 15:57:37 +0100 Subject: [PATCH 1/6] Add more events in genuineCheck --- src/api/Manager.js | 48 +++++++++++++++++++++++++++++++++++------- src/hw/genuineCheck.js | 4 ++-- src/types/manager.js | 12 +++++++++++ 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/api/Manager.js b/src/api/Manager.js index c315017cca..b60cd55c5d 100644 --- a/src/api/Manager.js +++ b/src/api/Manager.js @@ -13,8 +13,8 @@ import { DeviceOnDashboardExpected } from "@ledgerhq/errors"; import type Transport from "@ledgerhq/hw-transport"; -import { throwError } from "rxjs"; -import { catchError, filter, last, map } from "rxjs/operators"; +import { throwError, Observable } from "rxjs"; +import { catchError } from "rxjs/operators"; import { version as livecommonversion } from "../../package.json"; import { createDeviceSocket } from "./socket"; import network from "../network"; @@ -27,10 +27,13 @@ import type { Application, Category, Id, - McuVersion + McuVersion, + GenuineCheckEvent } from "../types/manager"; import { makeLRUCache } from "../cache"; +const ALLOW_MANAGER_APDU_DEBOUNCE = 500; + const remapSocketError = (context?: string) => catchError((e: Error) => { if (!e || !e.message) return throwError(e); @@ -273,16 +276,45 @@ const API = { genuineCheck: ( transport: Transport<*>, { targetId, perso }: { targetId: *, perso: * } - ) => + ): Observable => createDeviceSocket(transport, { url: URL.format({ pathname: `${getEnv("BASE_SOCKET_URL")}/genuine`, query: { targetId, perso, livecommonversion } }) - }).pipe( - last(), - filter(o => o.type === "result"), - map(o => o.payload || "") + }).pipe(input => + Observable.create(o => { + let timeout; + let requested; + input.subscribe({ + complete: () => { + o.complete(); + }, + error: e => { + o.error(e); + }, + next: e => { + if (timeout) { + clearTimeout(timeout); + timeout = null; + } + if (e.type === "result") { + o.next(e); + } else if (e.nonce === 3) { + if (e.type === "exchange-before") { + timeout = setTimeout(() => { + o.next({ type: "allow-manager-requested" }); + requested = true; + }, ALLOW_MANAGER_APDU_DEBOUNCE); + } else if (e.type === "exchange") { + if (requested) { + o.next({ type: "allow-manager-accepted" }); + } + } + } + } + }); + }) ), installMcu: ( diff --git a/src/hw/genuineCheck.js b/src/hw/genuineCheck.js index f9a958d65d..72650c4d9a 100644 --- a/src/hw/genuineCheck.js +++ b/src/hw/genuineCheck.js @@ -4,13 +4,13 @@ import Transport from "@ledgerhq/hw-transport"; import { Observable, from } from "rxjs"; import { switchMap } from "rxjs/operators"; -import type { DeviceInfo } from "../types/manager"; +import type { DeviceInfo, GenuineCheckEvent } from "../types/manager"; import ManagerAPI from "../api/Manager"; export default ( transport: Transport<*>, deviceInfo: DeviceInfo -): Observable => +): Observable => from( ManagerAPI.getDeviceVersion(deviceInfo.targetId, deviceInfo.providerId) ).pipe( diff --git a/src/types/manager.js b/src/types/manager.js index 62dd5ac9d5..5422ee0299 100644 --- a/src/types/manager.js +++ b/src/types/manager.js @@ -139,3 +139,15 @@ export type Category = { date_creation: string, date_last_modified: string }; + +export type GenuineCheckEvent = + | { + type: "result", + payload: string + } + | { + type: "allow-manager-requested" + } + | { + type: "allow-manager-accepted" + }; From 7946bac08ff51551848f29862977e8d4a6b94c45 Mon Sep 17 00:00:00 2001 From: "Valentin D. Pinkman" Date: Thu, 21 Feb 2019 18:23:20 +0100 Subject: [PATCH 2/6] add demo example for genuine check --- demo/src/demos/transports/index.js | 97 ++++++++++++++++++------------ 1 file changed, 60 insertions(+), 37 deletions(-) diff --git a/demo/src/demos/transports/index.js b/demo/src/demos/transports/index.js index 23c974ce09..69ba95b039 100644 --- a/demo/src/demos/transports/index.js +++ b/demo/src/demos/transports/index.js @@ -18,7 +18,7 @@ class SelectTransport extends Component<*> { render() { return (