Ledger: implement authorized-path APDU
This commit is contained in:
parent
92715a005b
commit
4bb28cd285
@ -43,8 +43,47 @@ let description =
|
|||||||
all connected devices."
|
all connected devices."
|
||||||
|
|
||||||
let hard = Int32.logor 0x8000_0000l
|
let hard = Int32.logor 0x8000_0000l
|
||||||
|
let unhard = Int32.logand 0x7fff_ffffl
|
||||||
|
let is_hard n = Int32.logand 0x8000_0000l n <> 0l
|
||||||
let tezos_root = [hard 44l ; hard 1729l]
|
let tezos_root = [hard 44l ; hard 1729l]
|
||||||
|
|
||||||
|
module Bip32_path = struct
|
||||||
|
let node_of_string str =
|
||||||
|
match Int32.of_string_opt str with
|
||||||
|
| Some node -> Some node
|
||||||
|
| None ->
|
||||||
|
match Int32.of_string_opt String.(sub str 0 ((length str) - 1)) with
|
||||||
|
| None -> None
|
||||||
|
| Some node -> Some (hard node)
|
||||||
|
|
||||||
|
let node_of_string_exn str =
|
||||||
|
match node_of_string str with
|
||||||
|
| None ->
|
||||||
|
invalid_arg (Printf.sprintf "node_of_string_exn: got %S" str)
|
||||||
|
| Some str -> str
|
||||||
|
|
||||||
|
let pp_node ppf node =
|
||||||
|
match is_hard node with
|
||||||
|
| true -> Fmt.pf ppf "%ld'" (unhard node)
|
||||||
|
| false -> Fmt.pf ppf "%ld" node
|
||||||
|
|
||||||
|
let string_of_node = Fmt.to_to_string pp_node
|
||||||
|
|
||||||
|
let path_of_string_exn s =
|
||||||
|
match String.split_on_char '/' s with
|
||||||
|
| [""] -> []
|
||||||
|
| nodes ->
|
||||||
|
List.map node_of_string_exn nodes
|
||||||
|
|
||||||
|
let path_of_string s =
|
||||||
|
try Some (path_of_string_exn s) with _ -> None
|
||||||
|
|
||||||
|
let pp_path =
|
||||||
|
Fmt.(list ~sep:(const char '/') pp_node)
|
||||||
|
|
||||||
|
let string_of_path = Fmt.to_to_string pp_path
|
||||||
|
end
|
||||||
|
|
||||||
(* Those are always valid on Ledger Nano S with latest firmware. *)
|
(* Those are always valid on Ledger Nano S with latest firmware. *)
|
||||||
let vendor_id = 0x2c97
|
let vendor_id = 0x2c97
|
||||||
let product_id = 0x0001
|
let product_id = 0x0001
|
||||||
@ -454,6 +493,30 @@ let commands =
|
|||||||
return_unit
|
return_unit
|
||||||
) ;
|
) ;
|
||||||
|
|
||||||
|
Clic.command ~group
|
||||||
|
~desc: "Query the path of the authorized key"
|
||||||
|
no_options
|
||||||
|
(prefixes [ "get" ; "ledger" ; "authorized" ; "path" ; "for" ]
|
||||||
|
@@ Public_key.alias_param
|
||||||
|
@@ stop)
|
||||||
|
(fun () (name, (pk_uri, _)) (cctxt : Client_context.io_wallet) ->
|
||||||
|
pkh_of_pk_uri pk_uri >>=? fun root_pkh ->
|
||||||
|
with_ledger root_pkh begin fun h _version _of_curve _to_curve ->
|
||||||
|
wrap_ledger_cmd begin fun pp ->
|
||||||
|
Ledgerwallet_tezos.get_authorized_key ~pp h
|
||||||
|
end >>=? function
|
||||||
|
| [] ->
|
||||||
|
cctxt#message
|
||||||
|
"@[<v 0>No baking key authorized for %s@]" name
|
||||||
|
>>= fun () ->
|
||||||
|
return_unit
|
||||||
|
| path ->
|
||||||
|
cctxt#message
|
||||||
|
"@[<v 0>Authorized baking path: %a@]"
|
||||||
|
Bip32_path.pp_path path >>= fun () ->
|
||||||
|
return_unit
|
||||||
|
end) ;
|
||||||
|
|
||||||
Clic.command ~group
|
Clic.command ~group
|
||||||
~desc: "Authorize a Ledger to bake for a key"
|
~desc: "Authorize a Ledger to bake for a key"
|
||||||
no_options
|
no_options
|
||||||
|
@ -23,6 +23,18 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(*****************************************************************************)
|
(*****************************************************************************)
|
||||||
|
|
||||||
|
module Bip32_path : sig
|
||||||
|
val node_of_string : string -> int32 option
|
||||||
|
val node_of_string_exn : string -> int32
|
||||||
|
val pp_node : int32 Fmt.t
|
||||||
|
val string_of_node : int32 -> string
|
||||||
|
|
||||||
|
val path_of_string : string -> int32 list option
|
||||||
|
val path_of_string_exn : string -> int32 list
|
||||||
|
val pp_path : int32 list Fmt.t
|
||||||
|
val string_of_path : int32 list -> string
|
||||||
|
end
|
||||||
|
|
||||||
include Client_keys.SIGNER
|
include Client_keys.SIGNER
|
||||||
|
|
||||||
val commands : unit -> Client_context.io_wallet Clic.command list
|
val commands : unit -> Client_context.io_wallet Clic.command list
|
||||||
|
@ -63,6 +63,7 @@ type ins =
|
|||||||
| Sign_unsafe
|
| Sign_unsafe
|
||||||
| Reset_high_watermark
|
| Reset_high_watermark
|
||||||
| Query_high_watermark
|
| Query_high_watermark
|
||||||
|
| Get_authorized_key
|
||||||
|
|
||||||
let int_of_ins = function
|
let int_of_ins = function
|
||||||
| Version -> 0x00
|
| Version -> 0x00
|
||||||
@ -74,6 +75,7 @@ let int_of_ins = function
|
|||||||
| Reset_high_watermark -> 0x06
|
| Reset_high_watermark -> 0x06
|
||||||
| Query_high_watermark -> 0x08
|
| Query_high_watermark -> 0x08
|
||||||
| Git_commit -> 0x09
|
| Git_commit -> 0x09
|
||||||
|
| Get_authorized_key -> 0x07
|
||||||
|
|
||||||
type curve =
|
type curve =
|
||||||
| Ed25519
|
| Ed25519
|
||||||
@ -98,6 +100,16 @@ let get_git_commit ?pp ?buf h =
|
|||||||
Transport.apdu ~msg:"get_git_commit" ?pp ?buf h apdu >>|
|
Transport.apdu ~msg:"get_git_commit" ?pp ?buf h apdu >>|
|
||||||
Cstruct.to_string
|
Cstruct.to_string
|
||||||
|
|
||||||
|
let get_authorized_key ?pp ?buf h =
|
||||||
|
let apdu = Apdu.create (wrap_ins Get_authorized_key) in
|
||||||
|
Transport.apdu ~msg:"get_authorized_key" ?pp ?buf h apdu >>| fun path ->
|
||||||
|
let rec read_numbers acc path =
|
||||||
|
if Cstruct.len path = 0 then List.rev acc
|
||||||
|
else
|
||||||
|
read_numbers (Cstruct.BE.get_uint32 path 0 :: acc)
|
||||||
|
(Cstruct.shift path 4) in
|
||||||
|
read_numbers [] (Cstruct.shift path 1)
|
||||||
|
|
||||||
let write_path cs path =
|
let write_path cs path =
|
||||||
ListLabels.fold_left path ~init:cs ~f:begin fun cs i ->
|
ListLabels.fold_left path ~init:cs ~f:begin fun cs i ->
|
||||||
Cstruct.BE.set_uint32 cs 0 i ;
|
Cstruct.BE.set_uint32 cs 0 i ;
|
||||||
|
@ -36,7 +36,13 @@ val get_git_commit :
|
|||||||
?pp:Format.formatter -> ?buf:Cstruct.t ->
|
?pp:Format.formatter -> ?buf:Cstruct.t ->
|
||||||
Hidapi.t -> (string, Transport.error) result
|
Hidapi.t -> (string, Transport.error) result
|
||||||
(** [get_git_commit ?pp ?buf ledger] is the git commit information of
|
(** [get_git_commit ?pp ?buf ledger] is the git commit information of
|
||||||
the Ledger app running at [ledger]. *)
|
the Ledger app running at [ledger]. *)
|
||||||
|
|
||||||
|
val get_authorized_key :
|
||||||
|
?pp:Format.formatter -> ?buf:Cstruct.t ->
|
||||||
|
Hidapi.t -> (int32 list, Transport.error) result
|
||||||
|
(** [get_authorized_key ?pp ?buf ledger] is the BIP32 path of the key
|
||||||
|
authorized to bake on the Ledger app running at [ledger]. *)
|
||||||
|
|
||||||
val get_public_key :
|
val get_public_key :
|
||||||
?prompt:bool ->
|
?prompt:bool ->
|
||||||
|
Loading…
Reference in New Issue
Block a user