improve credential handling for e2e

Signed-off-by: Michele Balistreri <michele@bitgamma.com>
This commit is contained in:
Michele Balistreri 2021-06-04 11:40:34 +02:00
parent f917782fc1
commit 9ba0960d71
No known key found for this signature in database
GPG Key ID: E9567DA33A4F791A
1 changed files with 151 additions and 144 deletions

View File

@ -12,6 +12,11 @@
[taoensso.timbre :as log]
[status-im.multiaccounts.create.core :as multiaccounts.create]))
(def kk1-password "000000")
(def default-pin "111111")
(def default-puk "000000000000")
(def account-password (ethereum/sha3 "no password"))
(def initial-state
{:card-connected? false
:nfc-started? false
@ -27,7 +32,7 @@
(defn connect-selected-card []
(swap! state assoc :application-info
{:free-pairing-slots 5
:app-version "2.2"
:app-version "3.0"
:secure-channel-pub-key "04c3071768912a515c00aeab7ceb8a5bfda91d036f4a4e60b7944cee3ca7fb67b6d118e8df1e2480b87fd636c6615253245bbbc93a6a407f155f2c58f76c96ef0e",
:instance-uid "1b360b10a9a68b7d494e8f059059f118"
:paired? true
@ -36,6 +41,7 @@
:pin-retry-counter 3
:puk-retry-counter 5
:key-uid (get-in @re-frame.db/app-db [:multiaccounts/login :key-uid])})
(swap! state assoc :pin default-pin :puk default-puk :password kk1-password)
(connect-card))
(def initialization (atom false))
@ -44,7 +50,7 @@
(reset! initialization false)
(swap! state assoc :application-info
{:free-pairing-slots 5
:app-version "2.2"
:app-version "3.0"
:secure-channel-pub-key "04c3071768912a515c00aeab7ceb8a5bfda91d036f4a4e60b7944cee3ca7fb67b6d118e8df1e2480b87fd636c6615253245bbbc93a6a407f155f2c58f76c96ef0e",
:instance-uid "1b360b10a9a68b7d494e8f059059f118"
:paired? false
@ -53,6 +59,7 @@
:pin-retry-counter 3
:puk-retry-counter 5
:key-uid "0x16839e8b1b8a395acb18100c7e2b161701c225adf31eefa02114099b4d81a30b"})
(swap! state assoc :pin default-pin :puk default-puk :password kk1-password)
(connect-card))
(defn disconnect-card []
@ -67,6 +74,27 @@
(when f
(utils/set-timeout f 500)))
(defn pin-error []
#js {:code "EUNSPECIFIED"
:message (str "Unexpected error SW, 0x63C" (get-in @state [:application-info :pin-retry-counter]))})
(defn puk-error []
#js {:code "EUNSPECIFIED"
:message (str "Unexpected error SW, 0x63C" (get-in @state [:application-info :puk-retry-counter]))})
(defn with-pin [pin on-failure on-valid]
(if (= pin (get @state :pin))
(do
(swap! state update :application-info assoc
:pin-retry-counter 3
:puk-retry-counter 5)
(later on-valid))
(do
(swap! state update-in
[:application-info :pin-retry-counter]
(fnil dec 3))
(later #(on-failure (pin-error))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn start-nfc [{:keys [on-success]}]
@ -119,24 +147,28 @@
(log/debug "get-application-info")
(later #(on-success (get @state :application-info))))
(defn factory-reset [_])
(defn factory-reset [args]
(log/debug "factory-reset")
(reset-state)
(get-application-info args))
(defn install-applet [_])
(defn install-cash-applet [_])
(def kk1-password "000000")
(def default-puk "000000000000")
(defn init-card [{:keys [pin on-success]}]
(reset! initialization true)
(swap! state assoc :application-info
{:free-pairing-slots 5
:app-version "2.2"
:app-version "3.0"
:secure-channel-pub-key "04c3071768912a515c00aeab7ceb8a5bfda91d036f4a4e60b7944cee3ca7fb67b6d118e8df1e2480b87fd636c6615253245bbbc93a6a407f155f2c58f76c96ef0e",
:key-uid "",
:instance-uid "1b360b10a9a68b7d494e8f059059f118"
:paired? false
:has-master-key? false
:pin-retry-counter 3
:puk-retry-counter 5
:initialized? true})
(swap! state assoc :pin pin)
(swap! state assoc :pin pin :puk default-puk :password kk1-password)
(later
#(on-success {:password kk1-password
:puk default-puk
@ -144,11 +176,9 @@
(defn install-applet-and-init-card [_])
(def kk1-pair "ADEol+GCD67EO7zU6ko0DNK7XrNs9w2+h9GxcibNY4yf")
(def derived-acc (atom nil))
(defn multiaccount->keys [pin data]
(defn multiaccount->keys [data]
(let [{:keys [selected-id multiaccounts root-key derived]}
data
@ -161,7 +191,7 @@
whisper (get derived constants/path-whisper-keyword)
wallet (get derived constants/path-default-wallet-keyword)
wallet-root (get derived constants/path-wallet-root-keyword)
password (ethereum/sha3 pin)
password account-password
response {:key-uid key-uid
:encryption-public-key password
:address address
@ -206,7 +236,7 @@
(reset! derived-acc
{:root-key root-data
:derived derived-data-extended})))))))))))
(when (= password kk1-password)
(when (= password (get @state :password))
(do
(swap! state assoc-in [:application-info :paired?] true)
(later #(on-success (str (rand-int 10000000)))))))
@ -215,7 +245,6 @@
[{:keys [pin on-success]}]
(when (= pin (get @state :pin))
(let [[id response] (multiaccount->keys
pin
(:intro-wizard @re-frame.db/app-db))]
(log/debug "[simulated kk] generate-and-load-key response" response)
(swap! state assoc-in
@ -227,12 +256,12 @@
constants/path-eip1581
constants/path-whisper
constants/path-default-wallet]
(ethereum/sha3 pin)
account-password
#(on-success response)))))
(defn unblock-pin
[{:keys [puk on-success on-failure]}]
(if (= puk default-puk)
(if (= puk (get @state :puk))
(do
(swap! state update :application-info assoc
:pin-retry-counter 3
@ -243,27 +272,29 @@
[:application-info :puk-retry-counter]
(fnil dec 5))
(later
#(on-failure
#js {:code "EUNSPECIFIED"
:message "Unexpected error SW, 0x63C2"})))))
#(on-failure (puk-error))))))
(defn verify-pin [{:keys [pin on-success on-failure]}]
(if (= pin (get @state :pin))
(later #(on-success 3))
(do
(swap! state update-in
[:application-info :pin-retry-counter]
(fnil dec 3))
(later #(on-failure
#js {:code "EUNSPECIFIED"
:message "Unexpected error SW, 0x63C2"})))))
(with-pin pin on-failure #(on-success 3)))
(defn change-pin [{:keys [current-pin new-pin on-success on-failure]}]
(with-pin current-pin on-failure
(fn []
(swap! state assoc :pin new-pin)
(on-success))))
(defn change-puk [{:keys [pin puk on-success on-failure]}]
(with-pin pin on-failure
(fn []
(swap! state assoc :puk puk)
(on-success))))
(defn change-pairing [{:keys [pin pairing on-success on-failure]}]
(with-pin pin on-failure
(fn []
(swap! state assoc :password pairing)
(on-success))))
(defn change-pin [args]
(log/warn "change-pin not implemented" args))
(defn change-puk [args]
(log/warn "change-puk not implemented" args))
(defn change-pairing [args]
(log/warn "change-pairing not implemented" args))
(defn unpair [args]
(log/warn "unpair not implemented" args))
(defn delete [args]
@ -280,124 +311,100 @@
path))
(defn export-key [{:keys [pin on-success on-failure]}]
(let [{:keys [key-uid wallet-root-address]}
(get @re-frame.db/app-db :multiaccount)
accounts (get @re-frame.db/app-db :multiaccount/accounts)
hashed-password (ethereum/sha3 pin)
path-num (inc (get-in @re-frame.db/app-db [:multiaccount :latest-derived-path]))
path (str "m/" path-num)]
(status/multiaccount-load-account
wallet-root-address
hashed-password
(fn [value]
(let [{:keys [id error]} (types/json->clj value)]
(if error
(re-frame/dispatch [::new-account-error :password-error error])
(status/multiaccount-derive-addresses
id
[path]
(fn [derived]
(let [derived-address (get-in (types/json->clj derived) [(keyword path) :address])]
(if (some #(= derived-address (get % :address)) accounts)
(re-frame/dispatch [::new-account-error :account-error (i18n/label :t/account-exists-title)])
(status/multiaccount-store-derived
id
key-uid
[path]
hashed-password
(fn [result]
(let [{:keys [error] :as result} (types/json->clj result)
{:keys [publicKey]} (get result (keyword path))]
(if error
(on-failure error)
(on-success publicKey)))))))))))))))
(with-pin pin on-failure
#(let [{:keys [key-uid wallet-root-address]}
(get @re-frame.db/app-db :multiaccount)
accounts (get @re-frame.db/app-db :multiaccount/accounts)
hashed-password account-password
path-num (inc (get-in @re-frame.db/app-db [:multiaccount :latest-derived-path]))
path (str "m/" path-num)]
(status/multiaccount-load-account
wallet-root-address
hashed-password
(fn [value]
(let [{:keys [id error]} (types/json->clj value)]
(if error
(re-frame/dispatch [::new-account-error :password-error error])
(status/multiaccount-derive-addresses
id
[path]
(fn [derived]
(let [derived-address (get-in (types/json->clj derived) [(keyword path) :address])]
(if (some (fn [a] (= derived-address (get a :address))) accounts)
(re-frame/dispatch [::new-account-error :account-error (i18n/label :t/account-exists-title)])
(status/multiaccount-store-derived
id
key-uid
[path]
hashed-password
(fn [result]
(let [{:keys [error] :as result} (types/json->clj result)
{:keys [publicKey]} (get result (keyword path))]
(if error
(on-failure error)
(on-success publicKey))))))))))))))))
(defn unpair-and-delete [_])
;; It is a bit complicated to verify password before we have multiaccs main
;; wallet address, so we just define a set of "allowed" pins
(def allowed-pins
#{"121212" "111111" "222222" "123123"})
(defn get-keys [{:keys [on-success on-failure pin]}]
(if (contains? allowed-pins pin)
(do
(swap! state assoc :pin pin)
(later
(if @derived-acc
(let [[id keys] (multiaccount->keys pin @derived-acc)]
(swap! state assoc-in
[:application-info :key-uid] (:key-uid keys))
(status/multiaccount-store-derived
id
(:key-uid keys)
[constants/path-wallet-root
constants/path-eip1581
constants/path-whisper
constants/path-default-wallet]
(ethereum/sha3 pin)
#(on-success keys)))
#(on-success
{:key-uid (get-in @state [:application-info :key-uid])
:encryption-public-key (ethereum/sha3 pin)}))))
(do
(log/debug "Incorrect PIN" pin)
(swap! state update-in
[:application-info :pin-retry-counter]
(fnil dec 3))
(later
#(on-failure
#js {:code "EUNSPECIFIED"
:message "Unexpected error SW, 0x63C2"})))))
(with-pin pin on-failure
(if @derived-acc
(let [[id keys] (multiaccount->keys @derived-acc)]
(swap! state assoc-in
[:application-info :key-uid] (:key-uid keys))
(status/multiaccount-store-derived
id
(:key-uid keys)
[constants/path-wallet-root
constants/path-eip1581
constants/path-whisper
constants/path-default-wallet]
account-password
#(on-success keys)))
#(on-success
{:key-uid (get-in @state [:application-info :key-uid])
:instance-uid (get-in @state [:application-info :instance-uid])
:encryption-public-key account-password}))))
(def import-keys get-keys)
(defn sign [{:keys [pin hash data path typed? on-success on-failure]}]
(if (= pin (get @state :pin))
(later
#(let [address
(if path
(reduce
(fn [_ {:keys [address] :as acc}]
(when (= path (:path acc))
(reduced address)))
nil
(:multiaccount/accounts @re-frame.db/app-db))
(-> (:multiaccount/accounts @re-frame.db/app-db)
first
:address))
password (ethereum/sha3 pin)]
(if-not typed?
(let [params (types/clj->json
{:account address
:password password
:data (or data (str "0x" hash))})]
(status/sign-message
params
(fn [res]
(let [signature (-> res
types/json->clj
:result
ethereum/normalized-hex)]
(on-success signature)))))
(status/sign-typed-data
data
address
password
(fn [res]
(let [signature (-> res
types/json->clj
:result
ethereum/normalized-hex)]
(on-success signature)))))))
(do
(swap! state update-in
[:application-info :pin-retry-counter]
(fnil dec 3))
(later
#(on-failure
#js {:code "EUNSPECIFIED"
:message "Unexpected error SW, 0x63C2"})))))
(with-pin pin on-failure
#(let [address
(if path
(reduce
(fn [_ {:keys [address] :as acc}]
(when (= path (:path acc))
(reduced address)))
nil
(:multiaccount/accounts @re-frame.db/app-db))
(-> (:multiaccount/accounts @re-frame.db/app-db)
first
:address))
password account-password]
(if-not typed?
(let [params (types/clj->json
{:account address
:password password
:data (or data (str "0x" hash))})]
(status/sign-message
params
(fn [res]
(let [signature (-> res
types/json->clj
:result
ethereum/normalized-hex)]
(on-success signature)))))
(status/sign-typed-data
data
address
password
(fn [res]
(let [signature (-> res
types/json->clj
:result
ethereum/normalized-hex)]
(on-success signature))))))))
(defn sign-typed-data [args]
(log/warn "sign-typed-data not implemented" args))
@ -417,7 +424,7 @@
(defn send-transaction-with-signature
[{:keys [transaction on-completed]}]
(status/send-transaction transaction (ethereum/sha3 (:pin @state)) on-completed))
(status/send-transaction transaction account-password on-completed))
(defrecord SimulatedKeycard []
keycard/Keycard