Ledger: implement authorized-path APDU
This commit is contained in:
parent
92715a005b
commit
4bb28cd285
@ -43,8 +43,47 @@ let description =
|
||||
all connected devices."
|
||||
|
||||
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]
|
||||
|
||||
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. *)
|
||||
let vendor_id = 0x2c97
|
||||
let product_id = 0x0001
|
||||
@ -454,6 +493,30 @@ let commands =
|
||||
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
|
||||
~desc: "Authorize a Ledger to bake for a key"
|
||||
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
|
||||
|
||||
val commands : unit -> Client_context.io_wallet Clic.command list
|
||||
|
@ -63,6 +63,7 @@ type ins =
|
||||
| Sign_unsafe
|
||||
| Reset_high_watermark
|
||||
| Query_high_watermark
|
||||
| Get_authorized_key
|
||||
|
||||
let int_of_ins = function
|
||||
| Version -> 0x00
|
||||
@ -74,6 +75,7 @@ let int_of_ins = function
|
||||
| Reset_high_watermark -> 0x06
|
||||
| Query_high_watermark -> 0x08
|
||||
| Git_commit -> 0x09
|
||||
| Get_authorized_key -> 0x07
|
||||
|
||||
type curve =
|
||||
| Ed25519
|
||||
@ -98,6 +100,16 @@ let get_git_commit ?pp ?buf h =
|
||||
Transport.apdu ~msg:"get_git_commit" ?pp ?buf h apdu >>|
|
||||
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 =
|
||||
ListLabels.fold_left path ~init:cs ~f:begin fun cs i ->
|
||||
Cstruct.BE.set_uint32 cs 0 i ;
|
||||
|
@ -38,6 +38,12 @@ val get_git_commit :
|
||||
(** [get_git_commit ?pp ?buf ledger] is the git commit information of
|
||||
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 :
|
||||
?prompt:bool ->
|
||||
?pp:Format.formatter ->
|
||||
|
Loading…
Reference in New Issue
Block a user