Skip to content

Commit

Permalink
Add memory cleanup to web5c.go
Browse files Browse the repository at this point in the history
  • Loading branch information
KendallWeihe committed Sep 17, 2024
1 parent b0bb8d5 commit f2bdf51
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 35 deletions.
18 changes: 18 additions & 0 deletions bindings/web5_c/src/crypto/dsa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,24 @@ pub struct CSigner {
) -> *mut u8,
}

#[no_mangle]
pub extern "C" fn alloc_csigner() -> *mut CSigner {
let signer = CSigner {
signer_id: 0,
sign: rust_signer_sign,
};
Box::into_raw(Box::new(signer))
}

#[no_mangle]
pub extern "C" fn free_csigner(signer: *mut CSigner) {
if !signer.is_null() {
unsafe {
let _ = Box::from_raw(signer);
}
}
}

pub extern "C" fn rust_signer_sign(
signer_id: i32,
payload: *const u8,
Expand Down
40 changes: 40 additions & 0 deletions bindings/web5_c/src/crypto/jwk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,46 @@ pub struct CJwk {
pub y: *const c_char,
}

#[no_mangle]
pub extern "C" fn alloc_cjwk() -> *mut CJwk {
let jwk = CJwk {
alg: ptr::null(),
kty: ptr::null(),
crv: ptr::null(),
d: ptr::null(),
x: ptr::null(),
y: ptr::null(),
};
Box::into_raw(Box::new(jwk))
}

#[no_mangle]
pub extern "C" fn free_cjwk(jwk: *mut CJwk) {
if !jwk.is_null() {
unsafe {
if !(*jwk).alg.is_null() {
let _ = CString::from_raw((*jwk).alg as *mut c_char);
}
if !(*jwk).kty.is_null() {
let _ = CString::from_raw((*jwk).kty as *mut c_char);
}
if !(*jwk).crv.is_null() {
let _ = CString::from_raw((*jwk).crv as *mut c_char);
}
if !(*jwk).d.is_null() {
let _ = CString::from_raw((*jwk).d as *mut c_char);
}
if !(*jwk).x.is_null() {
let _ = CString::from_raw((*jwk).x as *mut c_char);
}
if !(*jwk).y.is_null() {
let _ = CString::from_raw((*jwk).y as *mut c_char);
}
let _ = Box::from_raw(jwk);
}
}
}

impl From<&CJwk> for Jwk {
fn from(jwk_c: &CJwk) -> Self {
Jwk {
Expand Down
19 changes: 19 additions & 0 deletions bindings/web5_c/src/crypto/key_managers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,25 @@ pub struct CKeyManager {
pub get_signer: extern "C" fn(manager_id: i32, public_jwk: *const CJwk) -> *mut CSigner,
}

#[no_mangle]
pub extern "C" fn alloc_ckeymanager() -> *mut CKeyManager {
let manager = CKeyManager {
manager_id: 0,
import_private_jwk: rust_key_manager_import_private_jwk,
get_signer: rust_key_manager_get_signer,
};
Box::into_raw(Box::new(manager))
}

#[no_mangle]
pub extern "C" fn free_ckeymanager(manager: *mut CKeyManager) {
if !manager.is_null() {
unsafe {
let _ = Box::from_raw(manager);
}
}
}

pub extern "C" fn rust_key_manager_import_private_jwk(
manager_id: i32,
private_jwk: *const CJwk,
Expand Down
6 changes: 6 additions & 0 deletions bindings/web5_c/web5_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ typedef struct
const char *x;
const char *y;
} CJwk;
CJwk *alloc_cjwk();
void free_cjwk(CJwk *jwk);
char *jwk_compute_thumbprint(const CJwk *jwk);
/** --- */

Expand All @@ -25,6 +27,8 @@ typedef struct
int signer_id;
signFunc sign;
} CSigner;
CSigner *alloc_csigner();
void free_csigner(CSigner *signer);
unsigned char *call_sign(CSigner *signer, const unsigned char *payload, size_t payload_len, size_t *out_len);
void poc_signer_from_foreign(const CSigner *signer);

Expand All @@ -40,6 +44,8 @@ typedef struct
importFunc import_private_jwk;
getSignerFunc get_signer;
} CKeyManager;
CKeyManager *alloc_ckeymanager();
void free_ckeymanager(CKeyManager *manager);
CJwk *call_import_private_jwk(CKeyManager *manager, const CJwk *private_jwk);
CSigner *call_get_signer(CKeyManager *manager, const CJwk *public_jwk);
void poc_key_manager_from_foreign(const CKeyManager *manager);
Expand Down
2 changes: 1 addition & 1 deletion bound/golang/crypto/keymanagers/in_memory_key_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type InMemoryKeyManager struct {
}

func NewInMemoryKeyManager() (*InMemoryKeyManager, error) {
cManager, err := web5c.NewCInMemoryKeyManager_2()
cManager, err := web5c.NewCInMemoryKeyManager()
if err != nil {
return nil, err
}
Expand Down
81 changes: 47 additions & 34 deletions bound/golang/web5c/web5c.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,19 @@ package web5c
#include <stdlib.h>
#include "../../../bindings/web5_c/web5_c.h"
// functions in export.go
extern unsigned char *foreign_signer_sign(int signer_id, const unsigned char *payload, size_t payload_len, size_t *out_len);
extern CJwk* foreign_key_manager_import_private_jwk(int manager_id, const CJwk *private_jwk);
extern CSigner* foreign_key_manager_get_signer(int manager_id, const CJwk *public_jwk);
CJwk *alloc_cjwk()
{
return (CJwk *)malloc(sizeof(CJwk));
}
CSigner *alloc_csigner()
{
return (CSigner *)malloc(sizeof(CSigner));
}
CKeyManager *alloc_ckeymanager()
{
return (CKeyManager *)malloc(sizeof(CKeyManager));
}
*/
import "C"
import (
"fmt"
"runtime"
"sync"
"unsafe"
)

// TODO we need to free the memory from the alloc calls in the preamble
// TODO perhaps just manage the memory in rust

type CJWK struct {
ALG string
KTY string
Expand Down Expand Up @@ -67,25 +53,27 @@ func NewCJWKFromCGo(cJWK *C.CJwk) *CJWK {

func (j CJWK) ComputeThumbprint() string {
cgoJWK := j.toCGo()
defer C.free(unsafe.Pointer(cgoJWK.alg))
defer C.free(unsafe.Pointer(cgoJWK.kty))
defer C.free(unsafe.Pointer(cgoJWK.crv))
defer C.free(unsafe.Pointer(cgoJWK.d))
defer C.free(unsafe.Pointer(cgoJWK.x))
defer C.free(unsafe.Pointer(cgoJWK.y))
defer C.free(unsafe.Pointer(cgoJWK))
defer C.free_cjwk(cgoJWK)

cThumbprint := C.jwk_compute_thumbprint(cgoJWK)
defer C.free_string(cThumbprint)

return C.GoString(cThumbprint)
}

/** --- */

func NewCEd25519Signer(cJWK *CJWK) (*CSigner, error) {
cgoJWK := cJWK.toCGo()
defer C.free_cjwk(cgoJWK)

cgoSigner := C.new_ed25519_signer(cgoJWK)

cSigner := NewCSignerFromCGo(cgoSigner)
runtime.SetFinalizer(cSigner, func(signer *CSigner) {
C.free_csigner(cgoSigner)
})

return cSigner, nil
}

Expand Down Expand Up @@ -155,15 +143,22 @@ func FreeSigner(id int) {

func POCSignerFromForeign(cSigner *CSigner) {
cgoSigner := cSigner.toCGo()
defer C.free_csigner(cgoSigner)

C.poc_signer_from_foreign(cgoSigner)
}

/** --- */

func NewCInMemoryKeyManager_2() (*CKeyManager, error) {
func NewCInMemoryKeyManager() (*CKeyManager, error) {
cgoManager := C.new_in_memory_key_manager()
cManager := NewCKeyManagerFromCGo(cgoManager)
return cManager, nil

cKeyManager := NewCKeyManagerFromCGo(cgoManager)
runtime.SetFinalizer(cKeyManager, func(manager *CKeyManager) {
C.free_ckeymanager(cgoManager)
})

return cKeyManager, nil
}

/** --- */
Expand Down Expand Up @@ -191,20 +186,36 @@ func NewCKeyManagerFromCGo(cManager *C.CKeyManager) *CKeyManager {
return &CKeyManager{
ID: int(cManager.manager_id),
ImportPrivateJWK: func(privateJWK *CJWK) (*CJWK, error) {
cPrivateJWK := privateJWK.toCGo()
cPublicJWK := C.call_import_private_jwk(cManager, cPrivateJWK)
if cPublicJWK == nil {
cgoPrivateJWK := privateJWK.toCGo()
defer C.free_cjwk(cgoPrivateJWK)

cgoPublicJWK := C.call_import_private_jwk(cManager, cgoPrivateJWK)
if cgoPublicJWK == nil {
return nil, fmt.Errorf("failed to import private JWK")
}
return NewCJWKFromCGo(cPublicJWK), nil

cPublicJWK := NewCJWKFromCGo(cgoPublicJWK)
runtime.SetFinalizer(cPublicJWK, func(jwk *CJWK) {
C.free_cjwk(cgoPublicJWK)
})

return cPublicJWK, nil
},
GetSigner: func(publicJWK *CJWK) (*CSigner, error) {
cPublicJWK := publicJWK.toCGo()
cSigner := C.call_get_signer(cManager, cPublicJWK)
if cSigner == nil {
cgoPublicJWK := publicJWK.toCGo()
defer C.free_cjwk(cgoPublicJWK)

cgoSigner := C.call_get_signer(cManager, cgoPublicJWK)
if cgoSigner == nil {
return nil, fmt.Errorf("failed to get signer")
}
return NewCSignerFromCGo(cSigner), nil

cSigner := NewCSignerFromCGo(cgoSigner)
runtime.SetFinalizer(cSigner, func(signer *CSigner) {
C.free_csigner(cgoSigner)
})

return cSigner, nil
},
}
}
Expand Down Expand Up @@ -241,5 +252,7 @@ func FreeKeyManager(id int) {

func POCKeyManagerFromForeign(cManager *CKeyManager) {
cgoKeyManager := cManager.toCGo()
defer C.free_ckeymanager(cgoKeyManager)

C.poc_key_manager_from_foreign(cgoKeyManager)
}

0 comments on commit f2bdf51

Please sign in to comment.