export flow interface

This commit is contained in:
Michele Balistreri 2021-10-29 13:33:26 +03:00
parent 3727d89ae7
commit 7f072e33d4
No known key found for this signature in database
GPG Key ID: E9567DA33A4F791A
6 changed files with 78 additions and 444 deletions

View File

@ -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
}
}

View File

@ -29,7 +29,7 @@ type keycardContext struct {
}
func startKeycardContext() (*keycardContext, error) {
kctx = &keycardContext{
kctx := &keycardContext{
connected: make(chan (struct{})),
}
err := kctx.start()

358
main.go
View File

@ -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)), &params); 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)), &params); 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)), &params); 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)), &params); 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)), &params); 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)), &params); 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)), &params); 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)), &params); 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)), &params); 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)), &params); 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)), &params); 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)), &params); 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[:]))
//}

View File

@ -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)), &params); 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)
}

View File

@ -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"`

View File

@ -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