mirror of
https://dev.narayana.im/narayana/telegabber.git
synced 2026-08-05 04:07:07 +00:00
89 lines
4.1 KiB
Go
89 lines
4.1 KiB
Go
package libsignal
|
|
|
|
/*
|
|
#include <signal_protocol.h>
|
|
#include <stdint.h>
|
|
|
|
// Forward declarations of the Go-exported crypto callbacks implemented in
|
|
// crypto.go. Declared here (rather than relying on a generated
|
|
// _cgo_export.h) with signatures matching signal_protocol.h's
|
|
// signal_crypto_provider field types exactly, so the struct-literal
|
|
// assignment below type-checks; the actual symbols are resolved at link
|
|
// time regardless of the const-qualifier differences cgo's own generated
|
|
// prototypes would have (const has no effect on calling convention).
|
|
extern int go_crypto_random(uint8_t *data, size_t len, void *user_data);
|
|
extern int go_crypto_hmac_sha256_init(void **hmac_context, const uint8_t *key, size_t key_len, void *user_data);
|
|
extern int go_crypto_hmac_sha256_update(void *hmac_context, const uint8_t *data, size_t data_len, void *user_data);
|
|
extern int go_crypto_hmac_sha256_final(void *hmac_context, signal_buffer **output, void *user_data);
|
|
extern void go_crypto_hmac_sha256_cleanup(void *hmac_context, void *user_data);
|
|
extern int go_crypto_sha512_init(void **digest_context, void *user_data);
|
|
extern int go_crypto_sha512_update(void *digest_context, const uint8_t *data, size_t data_len, void *user_data);
|
|
extern int go_crypto_sha512_final(void *digest_context, signal_buffer **output, void *user_data);
|
|
extern void go_crypto_sha512_cleanup(void *digest_context, void *user_data);
|
|
extern int go_crypto_encrypt(signal_buffer **output, int cipher,
|
|
const uint8_t *key, size_t key_len,
|
|
const uint8_t *iv, size_t iv_len,
|
|
const uint8_t *plaintext, size_t plaintext_len, void *user_data);
|
|
extern int go_crypto_decrypt(signal_buffer **output, int cipher,
|
|
const uint8_t *key, size_t key_len,
|
|
const uint8_t *iv, size_t iv_len,
|
|
const uint8_t *ciphertext, size_t ciphertext_len, void *user_data);
|
|
|
|
static int telegabber_setup_crypto_provider(signal_context *ctx) {
|
|
signal_crypto_provider provider;
|
|
provider.random_func = go_crypto_random;
|
|
provider.hmac_sha256_init_func = go_crypto_hmac_sha256_init;
|
|
provider.hmac_sha256_update_func = go_crypto_hmac_sha256_update;
|
|
provider.hmac_sha256_final_func = go_crypto_hmac_sha256_final;
|
|
provider.hmac_sha256_cleanup_func = go_crypto_hmac_sha256_cleanup;
|
|
provider.sha512_digest_init_func = go_crypto_sha512_init;
|
|
provider.sha512_digest_update_func = go_crypto_sha512_update;
|
|
provider.sha512_digest_final_func = go_crypto_sha512_final;
|
|
provider.sha512_digest_cleanup_func = go_crypto_sha512_cleanup;
|
|
provider.encrypt_func = go_crypto_encrypt;
|
|
provider.decrypt_func = go_crypto_decrypt;
|
|
provider.user_data = 0;
|
|
return signal_context_set_crypto_provider(ctx, &provider);
|
|
}
|
|
*/
|
|
import "C"
|
|
|
|
import "errors"
|
|
|
|
// Context wraps the global signal_context, wiring up a crypto provider
|
|
// backed by Go's standard library (libomemo-c ships no default one).
|
|
//
|
|
// This binding does not register locking functions with the library (see
|
|
// signal_context_set_locking_functions), because the C API requires them to
|
|
// support recursive locking, which a plain sync.Mutex cannot safely
|
|
// provide. Instead, callers MUST serialize all operations against a given
|
|
// Context - and anything built from it (StoreContext, SessionBuilder,
|
|
// SessionCipher) - themselves; libomemo-c does not spawn threads of its
|
|
// own, so a single mutex held by the caller around each call is sufficient.
|
|
type Context struct {
|
|
raw *C.signal_context
|
|
}
|
|
|
|
// NewContext creates and configures a new global library context.
|
|
func NewContext() (*Context, error) {
|
|
ctx := &Context{}
|
|
if code := C.signal_context_create(&ctx.raw, nil); code != C.SG_SUCCESS {
|
|
return nil, newError("signal_context_create", int(code))
|
|
}
|
|
if code := C.telegabber_setup_crypto_provider(ctx.raw); code != C.SG_SUCCESS {
|
|
C.signal_context_destroy(ctx.raw)
|
|
return nil, newError("signal_context_set_crypto_provider", int(code))
|
|
}
|
|
return ctx, nil
|
|
}
|
|
|
|
// Close destroys the underlying signal_context. Do not use the Context (or
|
|
// anything built from it) afterward.
|
|
func (c *Context) Close() {
|
|
if c.raw != nil {
|
|
C.signal_context_destroy(c.raw)
|
|
c.raw = nil
|
|
}
|
|
}
|
|
|
|
var errContextClosed = errors.New("libsignal: context is closed")
|