package libsignal /* #include #include // 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")