427 lines
10 KiB
Go
Raw Normal View History

2021-09-13 13:09:23 +02:00
package main
// #cgo LDFLAGS: -shared
import "C"
import (
2021-10-04 10:48:02 +02:00
"encoding/binary"
2021-09-13 13:09:23 +02:00
"encoding/json"
"fmt"
"time"
2021-09-29 11:32:34 +02:00
"unsafe"
2021-10-07 10:27:40 +02:00
keycard "github.com/status-im/keycard-go"
2021-09-29 11:32:34 +02:00
"github.com/status-im/nim-keycard-go/go/keycard/signal"
2021-09-13 13:09:23 +02:00
)
var kctx *keycardContext
func main() {
2021-09-13 13:23:33 +02:00
// example()
2021-09-13 13:09:23 +02:00
}
func example() {
2021-09-13 13:23:33 +02:00
fmt.Printf("RUNNING EXAMPLE \n")
2021-09-13 13:09:23 +02:00
res := Start()
fmt.Printf("*** start %+v\n", C.GoString(res))
time.Sleep(2)
res = Select()
fmt.Printf("*** select %+v\n", C.GoString(res))
2021-09-14 18:31:02 +02:00
// res = Init(C.CString(`{"pin": "123456", "puk": "123456789012", "pairingPassword": "KeycardTest"}`))
// fmt.Printf("*** OpenSecureChannel %+v\n", C.GoString(res))
2021-09-13 13:09:23 +02:00
2021-09-14 18:31:02 +02:00
// res = Pair(C.CString(`{"pairingPassword": "KeycardTest"}`))
// fmt.Printf("*** Pair %+v\n", C.GoString(res))
res = OpenSecureChannel(C.CString(`{"index":1, "key": "33b0b458d19df44b009ea8142b64e041837667355250d13f3b84f389f6350cc8"}`))
2021-09-13 13:09:23 +02:00
fmt.Printf("*** OpenSecureChannel %+v\n", C.GoString(res))
res = VerifyPin(C.CString(`{"pin": "123456"}`))
fmt.Printf("*** VerifyPin %+v\n", C.GoString(res))
2021-09-14 18:31:02 +02:00
res = ChangePin(C.CString(`{"pin": "123456"}`))
fmt.Printf("*** ChangePin %+v\n", C.GoString(res))
res = ChangePuk(C.CString(`{"puk": "123456789012"}`))
fmt.Printf("*** ChangePuk %+v\n", C.GoString(res))
res = ChangePairingPassword(C.CString(`{"pairingPassword": "KeycardTest"}`))
fmt.Printf("*** ChangePairingPassword %+v\n", C.GoString(res))
res = GetStatusApplication()
fmt.Printf("*** GetStatusApplication %+v\n", C.GoString(res))
// res = Unpair(C.CString(`{"index": 1}`))
// fmt.Printf("*** Unpair %+v\n", C.GoString(res))
// res = GenerateKey()
// fmt.Printf("*** GenerateKey %+v\n", C.GoString(res))
res = DeriveKey(C.CString(`{"path":"m/1/2/3/4/5"}`))
fmt.Printf("*** DeriveKey %+v\n", C.GoString(res))
res = SignWithPath(C.CString(`{"data": "0000000000000000000000000000000000000000000000000000000000000000", "path":"m/1/2/3/4/5"}`))
fmt.Printf("*** SignWithPath %+v\n", C.GoString(res))
res = ExportKey(C.CString(`{"derive": true, "makeCurrent": false, "onlyPublic": false, "path": "m/43'/60'/1581'/0'/0"}`))
fmt.Printf("*** ExportKey %+v\n", C.GoString(res))
res = LoadSeed(C.CString(`{"seed": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}`))
fmt.Printf("*** LoadSeed %+v\n", C.GoString(res))
2021-09-13 13:09:23 +02:00
res = Stop()
fmt.Printf("*** stop %+v\n", C.GoString(res))
time.Sleep(10 * time.Second)
}
//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())
}
2021-09-28 11:26:45 +02:00
return retValue("ok", true, "applicationInfo", ApplicationInfo{
Installed: info.Installed,
Initialized: info.Initialized,
InstanceUID: info.InstanceUID,
SecureChannelPublicKey: info.SecureChannelPublicKey,
2021-10-04 10:48:02 +02:00
Version: bytesToInt(info.Version),
AvailableSlots: bytesToInt(info.AvailableSlots),
2021-09-28 11:26:45 +02:00
KeyUID: info.KeyUID,
Capabilities: Capability(info.Capabilities),
})
2021-09-13 13:09:23 +02:00
}
//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
2021-09-14 18:31:02 +02:00
func Pair(jsonParams *C.char) *C.char {
2021-09-13 13:09:23 +02:00
if kctx == nil {
l("select: not started")
return retValue("error", "not started")
}
2021-09-14 18:31:02 +02:00
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)
2021-09-13 13:09:23 +02:00
if err != nil {
return retValue("error", err.Error())
}
2021-09-14 18:31:02 +02:00
return retValue("ok", true, "pairingInfo", PairingInfo{
Key: pairingInfo.Key,
Index: pairingInfo.Index,
})
2021-09-13 13:09:23 +02:00
}
//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)
2021-10-07 10:27:40 +02:00
if wrongPing, ok := err.(*keycard.WrongPINError); ok {
return retValue("error", err.Error(), "remainingAttempts", wrongPing.RemainingAttempts)
}
2021-09-13 13:09:23 +02:00
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())
}
2021-10-06 09:47:14 +02:00
return retValue("ok", true, "keyUID", hexString(keyUID))
2021-09-13 13:09:23 +02:00
}
2021-09-14 18:31:02 +02:00
//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())
}
2021-10-08 11:06:46 +02:00
privKey, pubKey, address, err := kctx.exportKey(params.Derive, params.MakeCurrent, params.OnlyPublic, params.Path)
2021-09-14 18:31:02 +02:00
if err != nil {
return retValue("error", err.Error())
}
2021-10-08 11:06:46 +02:00
return retValue("ok", true, "privateKey", hexString(privKey), "publicKey", hexString(pubKey), "address", address)
2021-09-14 18:31:02 +02:00
}
//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)
}
2021-09-29 11:32:34 +02:00
2021-10-07 11:50:53 +02:00
//export KeycardSetSignalEventCallback
func KeycardSetSignalEventCallback(cb unsafe.Pointer) {
signal.KeycardSetSignalEventCallback(cb)
2021-09-29 11:32:34 +02:00
}
2021-10-04 10:48:02 +02:00
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[:]))
}