From 7f072e33d4a3c0db252f67e6f08cca48e4cbd1c1 Mon Sep 17 00:00:00 2001 From: Michele Balistreri Date: Fri, 29 Oct 2021 13:33:26 +0300 Subject: [PATCH] export flow interface --- examples/example-shared/main.go | 21 +- keycard_context.go | 2 +- main.go | 358 -------------------------------- shared/main.go | 64 +++++- types.go | 58 ------ utils.go | 19 -- 6 files changed, 78 insertions(+), 444 deletions(-) delete mode 100644 main.go diff --git a/examples/example-shared/main.go b/examples/example-shared/main.go index c820f90..476e7a2 100644 --- a/examples/example-shared/main.go +++ b/examples/example-shared/main.go @@ -3,15 +3,32 @@ package main /* #cgo LDFLAGS: -L ../../build/libkeycard -lkeycard #include "../../build/libkeycard/libkeycard.h" -extern char* HelloWorld(); */ import "C" import ( "fmt" + "os" + "path/filepath" ) func main() { - res := C.HelloWorld() + dir, err := os.MkdirTemp("", "status-keycard-go") + if err != nil { + fmt.Printf("error: %+v\n", err) + return + } + + defer os.RemoveAll(dir) + + pairingsFile := filepath.Join(dir, "keycard-pairings.json") + + res := C.KeycardInitFlow(C.CString(pairingsFile)) fmt.Printf("result: %+v\n", C.GoString(res)) + + if err != nil { + fmt.Printf("error: %+v\n", err) + return + } + } diff --git a/keycard_context.go b/keycard_context.go index 9ac687f..ca37509 100644 --- a/keycard_context.go +++ b/keycard_context.go @@ -29,7 +29,7 @@ type keycardContext struct { } func startKeycardContext() (*keycardContext, error) { - kctx = &keycardContext{ + kctx := &keycardContext{ connected: make(chan (struct{})), } err := kctx.start() diff --git a/main.go b/main.go deleted file mode 100644 index 5d185cf..0000000 --- a/main.go +++ /dev/null @@ -1,358 +0,0 @@ -package statuskeycardgo - -var kctx *keycardContext - -func HelloWorld() string { - return "Hello World" -} - -////export Start -//func Start() *C.char { -// var err error -// kctx, err = startKeycardContext() -// if err != nil { -// return retValue("err", err.Error()) -// } -// return retValue("ok", true) -//} - -////export Select -//func Select() *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// info, err := kctx.selectApplet() -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true, "applicationInfo", ApplicationInfo{ -// Installed: info.Installed, -// Initialized: info.Initialized, -// InstanceUID: info.InstanceUID, -// SecureChannelPublicKey: info.SecureChannelPublicKey, -// Version: bytesToInt(info.Version), -// AvailableSlots: bytesToInt(info.AvailableSlots), -// KeyUID: info.KeyUID, -// Capabilities: Capability(info.Capabilities), -// }) -//} - -////export Stop -//func Stop() *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// if err := kctx.stop(); err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true) -//} - -////export Pair -//func Pair(jsonParams *C.char) *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// var params pairParams -// if err := json.Unmarshal([]byte(C.GoString(jsonParams)), ¶ms); err != nil { -// return retValue("error", err.Error()) -// } - -// pairingInfo, err := kctx.pair(params.PairingPassword) -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true, "pairingInfo", PairingInfo{ -// Key: pairingInfo.Key, -// Index: pairingInfo.Index, -// }) -//} - -////export OpenSecureChannel -//func OpenSecureChannel(jsonParams *C.char) *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// var params openSecureChannelParams -// if err := json.Unmarshal([]byte(C.GoString(jsonParams)), ¶ms); err != nil { -// return retValue("error", err.Error()) -// } - -// err := kctx.openSecureChannel(params.Index, params.Key) -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true) -//} - -////export VerifyPin -//func VerifyPin(jsonParams *C.char) *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// var params verifyPinParams -// if err := json.Unmarshal([]byte(C.GoString(jsonParams)), ¶ms); err != nil { -// return retValue("error", err.Error()) -// } - -// err := kctx.verifyPin(params.Pin) - -// if wrongPing, ok := err.(*keycard.WrongPINError); ok { -// return retValue("error", err.Error(), "remainingAttempts", wrongPing.RemainingAttempts) -// } - -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true) -//} - -////export GenerateKey -//func GenerateKey() *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// keyUID, err := kctx.generateKey() -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true, "keyUID", hexString(keyUID)) -//} - -////export DeriveKey -//func DeriveKey(jsonParams *C.char) *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// var params deriveKeyParams -// if err := json.Unmarshal([]byte(C.GoString(jsonParams)), ¶ms); err != nil { -// return retValue("error", err.Error()) -// } - -// err := kctx.deriveKey(params.Path) -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true) -//} - -////export SignWithPath -//func SignWithPath(jsonParams *C.char) *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// var params signWithPathParams -// if err := json.Unmarshal([]byte(C.GoString(jsonParams)), ¶ms); err != nil { -// return retValue("error", err.Error()) -// } - -// sig, err := kctx.signWithPath(params.Data, params.Path) -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true, "signature", Signature{ -// PublicKey: hexString(sig.PubKey()), -// R: hexString(sig.R()), -// S: hexString(sig.S()), -// V: sig.V(), -// }) -//} - -////export ExportKey -//func ExportKey(jsonParams *C.char) *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// var params exportKeyParams -// if err := json.Unmarshal([]byte(C.GoString(jsonParams)), ¶ms); err != nil { -// return retValue("error", err.Error()) -// } - -// privKey, pubKey, address, err := kctx.exportKey(params.Derive, params.MakeCurrent, params.OnlyPublic, params.Path) -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true, "privateKey", hexString(privKey), "publicKey", hexString(pubKey), "address", address) -//} - -////export LoadSeed -//func LoadSeed(jsonParams *C.char) *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// var params loadSeedParams -// if err := json.Unmarshal([]byte(C.GoString(jsonParams)), ¶ms); err != nil { -// return retValue("error", err.Error()) -// } - -// pubKey, err := kctx.loadSeed(params.Seed) -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true, "publicKey", hexString(pubKey)) -//} - -////export Init -//func Init(jsonParams *C.char) *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// var params initSeedParams -// if err := json.Unmarshal([]byte(C.GoString(jsonParams)), ¶ms); err != nil { -// return retValue("error", err.Error()) -// } - -// err := kctx.init(params.Pin, params.Puk, params.PairingPassword) -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true) -//} - -////export Unpair -//func Unpair(jsonParams *C.char) *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// var params unpairParams -// if err := json.Unmarshal([]byte(C.GoString(jsonParams)), ¶ms); err != nil { -// return retValue("error", err.Error()) -// } - -// err := kctx.unpair(params.Index) -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true) -//} - -////export GetStatusApplication -//func GetStatusApplication() *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// status, err := kctx.getStatusApplication() -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true, "status", ApplicationStatus{ -// PinRetryCount: status.PinRetryCount, -// PUKRetryCount: status.PUKRetryCount, -// KeyInitialized: status.KeyInitialized, -// Path: status.Path, -// }) -//} - -////export ChangePin -//func ChangePin(jsonParams *C.char) *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// var params changeSecretsParams -// if err := json.Unmarshal([]byte(C.GoString(jsonParams)), ¶ms); err != nil { -// return retValue("error", err.Error()) -// } - -// err := kctx.changePin(params.Pin) -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true) -//} - -////export ChangePuk -//func ChangePuk(jsonParams *C.char) *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// var params changeSecretsParams -// if err := json.Unmarshal([]byte(C.GoString(jsonParams)), ¶ms); err != nil { -// return retValue("error", err.Error()) -// } - -// err := kctx.changePuk(params.Puk) -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true) -//} - -////export ChangePairingPassword -//func ChangePairingPassword(jsonParams *C.char) *C.char { -// if kctx == nil { -// l("select: not started") -// return retValue("error", "not started") -// } - -// var params changeSecretsParams -// if err := json.Unmarshal([]byte(C.GoString(jsonParams)), ¶ms); err != nil { -// return retValue("error", err.Error()) -// } - -// err := kctx.changePairingPassword(params.PairingPassword) -// if err != nil { -// return retValue("error", err.Error()) -// } - -// return retValue("ok", true) -//} - -////export KeycardSetSignalEventCallback -//func KeycardSetSignalEventCallback(cb unsafe.Pointer) { -// signal.KeycardSetSignalEventCallback(cb) -//} - -//func bytesToInt(s []byte) int { -// if len(s) > 4 { -// return 0 -// } - -// var b [4]byte -// copy(b[4-len(s):], s) -// return int(binary.BigEndian.Uint32(b[:])) -//} diff --git a/shared/main.go b/shared/main.go index c45e171..b028557 100644 --- a/shared/main.go +++ b/shared/main.go @@ -3,15 +3,67 @@ package main // #cgo LDFLAGS: -shared import "C" import ( - "fmt" + "encoding/json" - statuskeycardgo "github.com/status-im/status-keycard-go" + skg "github.com/status-im/status-keycard-go" ) func main() {} -//export HelloWorld -func HelloWorld() *C.char { - res := statuskeycardgo.HelloWorld() - return C.CString(fmt.Sprintf("shared lib: %s", res)) +var globalFlow *skg.KeycardFlow + +func retErr(err error) *C.char { + if err == nil { + return C.CString("ok") + } else { + return C.CString(err.Error()) + } +} + +func jsonToParams(jsonParams *C.char) (skg.FlowParams, error) { + var params skg.FlowParams + + if err := json.Unmarshal([]byte(C.GoString(jsonParams)), ¶ms); err != nil { + return nil, err + } + + return params, nil +} + +//export KeycardInitFlow +func KeycardInitFlow(storageDir *C.char) *C.char { + var err error + globalFlow, err = skg.NewFlow(C.GoString(storageDir)) + + return retErr(err) +} + +//export KeycardStartFlow +func KeycardStartFlow(flowType C.int, jsonParams *C.char) *C.char { + params, err := jsonToParams(jsonParams) + + if err != nil { + return retErr(err) + } + + err = globalFlow.Start(skg.FlowType(flowType), params) + return retErr(err) +} + +//export KeycardResumeFlow +func KeycardResumeFlow(jsonParams *C.char) *C.char { + params, err := jsonToParams(jsonParams) + + if err != nil { + return retErr(err) + } + + err = globalFlow.Resume(params) + return retErr(err) +} + +//export KeycardCancelFlow +func KeycardCancelFlow() *C.char { + err := globalFlow.Cancel() + return retErr(err) } diff --git a/types.go b/types.go index e7823d1..2d92672 100644 --- a/types.go +++ b/types.go @@ -28,63 +28,12 @@ func (s *hexString) UnmarshalJSON(data []byte) error { return nil } -type openSecureChannelParams struct { - Index int `json:"index"` - Key hexString `json:"key"` -} - -type verifyPinParams struct { - Pin string `json:"pin"` -} - -type deriveKeyParams struct { - Path string `json:"path"` -} - -type signWithPathParams struct { - Data hexString `json:"data"` - Path string `json:"path"` -} - -type exportKeyParams struct { - Derive bool `json:"derive"` - MakeCurrent bool `json:"makeCurrent"` - OnlyPublic bool `json:"onlyPublic"` - Path string `json:"path"` -} - -type loadSeedParams struct { - Seed hexString `json:"seed"` -} - -type pairParams struct { - PairingPassword string `json:"pairingPassword"` -} - -type initSeedParams struct { - Pin string `json:"pin"` - Puk string `json:"puk"` - PairingPassword string `json:"pairingPassword"` -} - -type changeSecretsParams struct { - Pin string `json:"pin"` - Puk string `json:"puk"` - PairingPassword string `json:"pairingPassword"` -} - -type unpairParams struct { - Index uint8 `json:"index"` -} - type Signature struct { R hexString `json:"r"` S hexString `json:"s"` V byte `json:"v"` } -type Capability uint8 - type ApplicationInfo struct { Initialized bool `json:"initialized"` InstanceUID hexString `json:"instanceUID"` @@ -100,13 +49,6 @@ type PairingInfo struct { Index int `json:"index"` } -type ApplicationStatus struct { - PinRetryCount int `json:"pinRetryCount"` - PUKRetryCount int `json:"pukRetryCount"` - KeyInitialized bool `json:"keyInitialized"` - Path string `json:"path"` -} - type KeyPair struct { Address string `json:"address"` PublicKey hexString `json:"publicKey"` diff --git a/utils.go b/utils.go index ac1bdff..c95d0b4 100644 --- a/utils.go +++ b/utils.go @@ -1,33 +1,14 @@ package statuskeycardgo -import "C" - import ( "encoding/binary" "encoding/hex" - "encoding/json" "github.com/ebfe/scard" keycard "github.com/status-im/keycard-go" ktypes "github.com/status-im/keycard-go/types" ) -func retValue(pairs ...interface{}) *C.char { - obj := make(map[string]interface{}) - for i := 0; i < len(pairs)/2; i++ { - key := pairs[i*2] - value := pairs[(i*2)+1] - obj[key.(string)] = value - } - - b, err := json.Marshal(obj) - if err != nil { - return C.CString(err.Error()) - } - - return C.CString(string(b)) -} - func isSCardError(err error) bool { _, ok := err.(scard.Error) return ok