2023-12-17 15:54:35 +02:00
|
|
|
// mautrix-signal - A Matrix-signal puppeting bridge.
|
|
|
|
|
// Copyright (C) 2023 Scott Weber
|
2025-01-17 17:49:37 +02:00
|
|
|
// Copyright (C) 2025 Tulir Asokan
|
2023-12-17 15:54:35 +02:00
|
|
|
//
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// GNU Affero General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
|
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
2023-03-22 10:31:22 -06:00
|
|
|
package libsignalgo
|
|
|
|
|
|
|
|
|
|
/*
|
2023-03-22 10:55:34 -06:00
|
|
|
#include "./libsignal-ffi.h"
|
2023-03-22 10:31:22 -06:00
|
|
|
*/
|
|
|
|
|
import "C"
|
|
|
|
|
import (
|
2024-01-04 01:06:45 +02:00
|
|
|
"context"
|
2025-12-08 16:45:42 +02:00
|
|
|
"fmt"
|
2023-03-22 10:31:22 -06:00
|
|
|
"runtime"
|
2025-11-27 16:53:59 +02:00
|
|
|
"unsafe"
|
2023-03-22 10:31:22 -06:00
|
|
|
|
|
|
|
|
"github.com/google/uuid"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type SealedSenderAddress struct {
|
|
|
|
|
E164 string
|
|
|
|
|
UUID uuid.UUID
|
|
|
|
|
DeviceID uint32
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-31 16:39:09 -04:00
|
|
|
func NewSealedSenderAddress(e164 string, uuid uuid.UUID, deviceID uint32) *SealedSenderAddress {
|
|
|
|
|
return &SealedSenderAddress{
|
|
|
|
|
E164: e164,
|
|
|
|
|
UUID: uuid,
|
|
|
|
|
DeviceID: deviceID,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-08 23:11:45 +02:00
|
|
|
func SealedSenderEncryptPlaintext(ctx context.Context, message []byte, contentHint UnidentifiedSenderMessageContentHint, forAddress *Address, fromSenderCert *SenderCertificate, sessionStore SessionStore, identityStore IdentityKeyStore, groupID *GroupIdentifier) ([]byte, error) {
|
2024-01-04 01:06:45 +02:00
|
|
|
ciphertextMessage, err := Encrypt(ctx, message, forAddress, sessionStore, identityStore)
|
2023-05-31 16:39:09 -04:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usmc, err := NewUnidentifiedSenderMessageContent(
|
|
|
|
|
ciphertextMessage,
|
|
|
|
|
fromSenderCert,
|
2024-09-24 17:22:43 +03:00
|
|
|
contentHint,
|
2025-12-08 23:11:45 +02:00
|
|
|
groupID,
|
2023-05-31 16:39:09 -04:00
|
|
|
)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
2024-01-04 01:06:45 +02:00
|
|
|
return SealedSenderEncrypt(ctx, usmc, forAddress, identityStore)
|
2023-05-31 16:39:09 -04:00
|
|
|
}
|
|
|
|
|
|
2024-01-04 01:06:45 +02:00
|
|
|
func SealedSenderEncrypt(ctx context.Context, usmc *UnidentifiedSenderMessageContent, forRecipient *Address, identityStore IdentityKeyStore) ([]byte, error) {
|
2023-06-20 15:55:54 -04:00
|
|
|
var encrypted C.SignalOwnedBuffer = C.SignalOwnedBuffer{}
|
2024-01-04 01:06:45 +02:00
|
|
|
callbackCtx := NewCallbackContext(ctx)
|
|
|
|
|
defer callbackCtx.Unref()
|
2023-05-31 16:39:09 -04:00
|
|
|
signalFfiError := C.signal_sealed_session_cipher_encrypt(
|
|
|
|
|
&encrypted,
|
2025-01-17 17:49:37 +02:00
|
|
|
forRecipient.constPtr(),
|
|
|
|
|
usmc.constPtr(),
|
2024-01-04 01:06:45 +02:00
|
|
|
callbackCtx.wrapIdentityKeyStore(identityStore),
|
2023-05-31 16:39:09 -04:00
|
|
|
)
|
2024-01-03 20:31:27 +02:00
|
|
|
runtime.KeepAlive(usmc)
|
|
|
|
|
runtime.KeepAlive(forRecipient)
|
2023-05-31 16:39:09 -04:00
|
|
|
if signalFfiError != nil {
|
2024-01-04 01:06:45 +02:00
|
|
|
return nil, callbackCtx.wrapError(signalFfiError)
|
2023-05-31 16:39:09 -04:00
|
|
|
}
|
2023-06-20 15:55:54 -04:00
|
|
|
return CopySignalOwnedBufferToBytes(encrypted), nil
|
2023-05-31 16:39:09 -04:00
|
|
|
}
|
|
|
|
|
|
2025-11-27 16:53:59 +02:00
|
|
|
type SessionAddressTuple struct {
|
|
|
|
|
ServiceID ServiceID
|
|
|
|
|
DeviceID int
|
|
|
|
|
Address *Address
|
|
|
|
|
Record *SessionRecord
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func SealedSenderMultiRecipientEncrypt(
|
|
|
|
|
ctx context.Context,
|
|
|
|
|
usmc *UnidentifiedSenderMessageContent,
|
|
|
|
|
recipients []SessionAddressTuple,
|
|
|
|
|
identityStore IdentityKeyStore,
|
|
|
|
|
) ([]byte, error) {
|
|
|
|
|
var encrypted C.SignalOwnedBuffer = C.SignalOwnedBuffer{}
|
|
|
|
|
callbackCtx := NewCallbackContext(ctx)
|
|
|
|
|
defer callbackCtx.Unref()
|
|
|
|
|
recipientAddresses := make([]C.SignalConstPointerProtocolAddress, len(recipients))
|
|
|
|
|
recipientSessions := make([]C.SignalConstPointerSessionRecord, len(recipients))
|
2025-12-08 23:34:32 +02:00
|
|
|
|
2025-11-27 16:53:59 +02:00
|
|
|
for i, recipient := range recipients {
|
|
|
|
|
recipientAddresses[i] = recipient.Address.constPtr()
|
|
|
|
|
recipientSessions[i] = recipient.Record.constPtr()
|
|
|
|
|
}
|
|
|
|
|
signalFfiError := C.signal_sealed_sender_multi_recipient_encrypt(
|
|
|
|
|
&encrypted,
|
|
|
|
|
C.SignalBorrowedSliceOfConstPointerProtocolAddress{
|
|
|
|
|
base: unsafe.SliceData(recipientAddresses),
|
|
|
|
|
length: C.size_t(len(recipientAddresses)),
|
|
|
|
|
},
|
|
|
|
|
C.SignalBorrowedSliceOfConstPointerSessionRecord{
|
|
|
|
|
base: unsafe.SliceData(recipientSessions),
|
|
|
|
|
length: C.size_t(len(recipientSessions)),
|
|
|
|
|
},
|
|
|
|
|
BytesToBuffer(nil),
|
|
|
|
|
usmc.constPtr(),
|
|
|
|
|
callbackCtx.wrapIdentityKeyStore(identityStore),
|
|
|
|
|
)
|
|
|
|
|
runtime.KeepAlive(usmc)
|
|
|
|
|
runtime.KeepAlive(recipients)
|
|
|
|
|
runtime.KeepAlive(recipientAddresses)
|
|
|
|
|
runtime.KeepAlive(recipientSessions)
|
|
|
|
|
if signalFfiError != nil {
|
|
|
|
|
return nil, callbackCtx.wrapError(signalFfiError)
|
|
|
|
|
}
|
|
|
|
|
return CopySignalOwnedBufferToBytes(encrypted), nil
|
2023-05-31 16:39:09 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type SealedSenderResult struct {
|
|
|
|
|
Message []byte
|
|
|
|
|
Sender SealedSenderAddress
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-09 09:39:45 -04:00
|
|
|
func SealedSenderDecryptToUSMC(
|
2024-01-04 01:06:45 +02:00
|
|
|
ctx context.Context,
|
2023-07-09 09:39:45 -04:00
|
|
|
ciphertext []byte,
|
|
|
|
|
identityStore IdentityKeyStore,
|
|
|
|
|
) (*UnidentifiedSenderMessageContent, error) {
|
2024-01-04 01:06:45 +02:00
|
|
|
callbackCtx := NewCallbackContext(ctx)
|
|
|
|
|
defer callbackCtx.Unref()
|
2025-01-17 17:49:37 +02:00
|
|
|
var usmc C.SignalMutPointerUnidentifiedSenderMessageContent
|
2023-07-09 09:39:45 -04:00
|
|
|
signalFfiError := C.signal_sealed_session_cipher_decrypt_to_usmc(
|
|
|
|
|
&usmc,
|
2023-07-26 10:03:28 -04:00
|
|
|
BytesToBuffer(ciphertext),
|
2024-01-04 01:06:45 +02:00
|
|
|
callbackCtx.wrapIdentityKeyStore(identityStore),
|
2023-07-09 09:39:45 -04:00
|
|
|
)
|
2024-01-03 20:31:27 +02:00
|
|
|
runtime.KeepAlive(ciphertext)
|
2023-07-09 09:39:45 -04:00
|
|
|
if signalFfiError != nil {
|
2024-01-04 01:06:45 +02:00
|
|
|
return nil, callbackCtx.wrapError(signalFfiError)
|
2023-07-09 09:39:45 -04:00
|
|
|
}
|
2025-01-17 17:49:37 +02:00
|
|
|
return wrapUnidentifiedSenderMessageContent(usmc.raw), nil
|
2023-07-09 09:39:45 -04:00
|
|
|
}
|
|
|
|
|
|
2023-03-22 10:31:22 -06:00
|
|
|
type UnidentifiedSenderMessageContentHint uint32
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
UnidentifiedSenderMessageContentHintDefault UnidentifiedSenderMessageContentHint = 0
|
|
|
|
|
UnidentifiedSenderMessageContentHintResendable UnidentifiedSenderMessageContentHint = 1
|
|
|
|
|
UnidentifiedSenderMessageContentHintImplicit UnidentifiedSenderMessageContentHint = 2
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type UnidentifiedSenderMessageContent struct {
|
2024-01-02 23:47:18 +02:00
|
|
|
nc noCopy
|
2023-03-22 10:31:22 -06:00
|
|
|
ptr *C.SignalUnidentifiedSenderMessageContent
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func wrapUnidentifiedSenderMessageContent(ptr *C.SignalUnidentifiedSenderMessageContent) *UnidentifiedSenderMessageContent {
|
|
|
|
|
messageContent := &UnidentifiedSenderMessageContent{ptr: ptr}
|
|
|
|
|
runtime.SetFinalizer(messageContent, (*UnidentifiedSenderMessageContent).Destroy)
|
|
|
|
|
return messageContent
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-08 23:11:45 +02:00
|
|
|
func NewUnidentifiedSenderMessageContent(message *CiphertextMessage, senderCertificate *SenderCertificate, contentHint UnidentifiedSenderMessageContentHint, groupID *GroupIdentifier) (*UnidentifiedSenderMessageContent, error) {
|
2025-01-17 17:49:37 +02:00
|
|
|
var usmc C.SignalMutPointerUnidentifiedSenderMessageContent
|
2025-12-08 23:11:45 +02:00
|
|
|
var groupIDBytes []byte
|
|
|
|
|
if groupID != nil {
|
|
|
|
|
groupIDBytes = groupID[:]
|
|
|
|
|
}
|
2025-01-17 17:49:37 +02:00
|
|
|
signalFfiError := C.signal_unidentified_sender_message_content_new(
|
|
|
|
|
&usmc,
|
|
|
|
|
message.constPtr(),
|
|
|
|
|
senderCertificate.constPtr(),
|
|
|
|
|
C.uint32_t(contentHint),
|
2025-12-08 23:11:45 +02:00
|
|
|
BytesToBuffer(groupIDBytes),
|
2025-01-17 17:49:37 +02:00
|
|
|
)
|
2024-01-03 20:31:27 +02:00
|
|
|
runtime.KeepAlive(message)
|
|
|
|
|
runtime.KeepAlive(senderCertificate)
|
2025-12-08 23:11:45 +02:00
|
|
|
runtime.KeepAlive(groupIDBytes)
|
2023-03-22 10:31:22 -06:00
|
|
|
if signalFfiError != nil {
|
|
|
|
|
return nil, wrapError(signalFfiError)
|
|
|
|
|
}
|
2025-01-17 17:49:37 +02:00
|
|
|
return wrapUnidentifiedSenderMessageContent(usmc.raw), nil
|
2023-03-22 10:31:22 -06:00
|
|
|
}
|
|
|
|
|
|
2023-05-31 16:39:09 -04:00
|
|
|
//func NewUnidentifiedSenderMessageContentFromMessage(sealedSenderMessage []byte, identityStore IdentityKeyStore, ctx *CallbackContext) (*UnidentifiedSenderMessageContent, error) {
|
|
|
|
|
// contextPtr := gopointer.Save(ctx)
|
|
|
|
|
// defer gopointer.Unref(contextPtr)
|
|
|
|
|
//
|
|
|
|
|
// var usmc *C.SignalUnidentifiedSenderMessageContent
|
|
|
|
|
//
|
|
|
|
|
// signalFfiError := C.signal_sealed_session_cipher_decrypt_to_usmc(
|
|
|
|
|
// &usmc,
|
|
|
|
|
// BytesToBuffer(sealedSenderMessage),
|
|
|
|
|
// wrapIdentityKeyStore(identityStore),
|
|
|
|
|
// contextPtr,
|
|
|
|
|
// )
|
|
|
|
|
// if signalFfiError != nil {
|
|
|
|
|
// return nil, wrapError(signalFfiError)
|
|
|
|
|
// }
|
|
|
|
|
// return wrapUnidentifiedSenderMessageContent(usmc), nil
|
|
|
|
|
//}
|
|
|
|
|
|
2023-03-22 10:31:22 -06:00
|
|
|
func DeserializeUnidentifiedSenderMessageContent(serialized []byte) (*UnidentifiedSenderMessageContent, error) {
|
2025-01-17 17:49:37 +02:00
|
|
|
var usmc C.SignalMutPointerUnidentifiedSenderMessageContent
|
2023-03-22 10:31:22 -06:00
|
|
|
signalFfiError := C.signal_unidentified_sender_message_content_deserialize(&usmc, BytesToBuffer(serialized))
|
2024-01-03 20:31:27 +02:00
|
|
|
runtime.KeepAlive(serialized)
|
2023-03-22 10:31:22 -06:00
|
|
|
if signalFfiError != nil {
|
|
|
|
|
return nil, wrapError(signalFfiError)
|
|
|
|
|
}
|
2025-01-17 17:49:37 +02:00
|
|
|
return wrapUnidentifiedSenderMessageContent(usmc.raw), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (usmc *UnidentifiedSenderMessageContent) mutPtr() C.SignalMutPointerUnidentifiedSenderMessageContent {
|
|
|
|
|
return C.SignalMutPointerUnidentifiedSenderMessageContent{usmc.ptr}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (usmc *UnidentifiedSenderMessageContent) constPtr() C.SignalConstPointerUnidentifiedSenderMessageContent {
|
|
|
|
|
return C.SignalConstPointerUnidentifiedSenderMessageContent{usmc.ptr}
|
2023-03-22 10:31:22 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (usmc *UnidentifiedSenderMessageContent) Destroy() error {
|
2024-01-02 23:49:44 +02:00
|
|
|
usmc.CancelFinalizer()
|
2025-01-17 17:49:37 +02:00
|
|
|
return wrapError(C.signal_unidentified_sender_message_content_destroy(usmc.mutPtr()))
|
2023-03-22 10:31:22 -06:00
|
|
|
}
|
|
|
|
|
|
2024-01-02 23:49:44 +02:00
|
|
|
func (usmc *UnidentifiedSenderMessageContent) CancelFinalizer() {
|
|
|
|
|
runtime.SetFinalizer(usmc, nil)
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-22 10:31:22 -06:00
|
|
|
func (usmc *UnidentifiedSenderMessageContent) Serialize() ([]byte, error) {
|
2023-06-20 15:55:54 -04:00
|
|
|
var serialized C.SignalOwnedBuffer = C.SignalOwnedBuffer{}
|
2025-01-17 17:49:37 +02:00
|
|
|
signalFfiError := C.signal_unidentified_sender_message_content_serialize(&serialized, usmc.constPtr())
|
2024-01-03 20:31:27 +02:00
|
|
|
runtime.KeepAlive(usmc)
|
2023-03-22 10:31:22 -06:00
|
|
|
if signalFfiError != nil {
|
|
|
|
|
return nil, wrapError(signalFfiError)
|
|
|
|
|
}
|
2023-06-20 15:55:54 -04:00
|
|
|
return CopySignalOwnedBufferToBytes(serialized), nil
|
2023-03-22 10:31:22 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (usmc *UnidentifiedSenderMessageContent) GetContents() ([]byte, error) {
|
2023-06-20 15:55:54 -04:00
|
|
|
var contents C.SignalOwnedBuffer = C.SignalOwnedBuffer{}
|
2025-01-17 17:49:37 +02:00
|
|
|
signalFfiError := C.signal_unidentified_sender_message_content_get_contents(&contents, usmc.constPtr())
|
2024-01-03 20:31:27 +02:00
|
|
|
runtime.KeepAlive(usmc)
|
2023-03-22 10:31:22 -06:00
|
|
|
if signalFfiError != nil {
|
|
|
|
|
return nil, wrapError(signalFfiError)
|
|
|
|
|
}
|
2023-06-20 15:55:54 -04:00
|
|
|
return CopySignalOwnedBufferToBytes(contents), nil
|
2023-03-22 10:31:22 -06:00
|
|
|
}
|
|
|
|
|
|
2025-12-08 16:45:42 +02:00
|
|
|
func (usmc *UnidentifiedSenderMessageContent) GetGroupID() (*GroupIdentifier, error) {
|
|
|
|
|
var contents C.SignalOwnedBuffer = C.SignalOwnedBuffer{}
|
|
|
|
|
signalFfiError := C.signal_unidentified_sender_message_content_get_group_id_or_empty(&contents, usmc.constPtr())
|
|
|
|
|
runtime.KeepAlive(usmc)
|
|
|
|
|
if signalFfiError != nil {
|
|
|
|
|
return nil, wrapError(signalFfiError)
|
|
|
|
|
}
|
|
|
|
|
bytes := CopySignalOwnedBufferToBytes(contents)
|
|
|
|
|
if len(bytes) == 0 {
|
|
|
|
|
return nil, nil
|
|
|
|
|
} else if len(bytes) != GroupIdentifierLength {
|
|
|
|
|
return nil, fmt.Errorf("unexpected group ID length: %d", len(bytes))
|
|
|
|
|
}
|
|
|
|
|
return (*GroupIdentifier)(bytes), nil
|
|
|
|
|
}
|
2023-03-22 10:31:22 -06:00
|
|
|
|
|
|
|
|
func (usmc *UnidentifiedSenderMessageContent) GetSenderCertificate() (*SenderCertificate, error) {
|
2025-01-17 17:49:37 +02:00
|
|
|
var senderCertificate C.SignalMutPointerSenderCertificate
|
|
|
|
|
signalFfiError := C.signal_unidentified_sender_message_content_get_sender_cert(&senderCertificate, usmc.constPtr())
|
2024-01-03 20:31:27 +02:00
|
|
|
runtime.KeepAlive(usmc)
|
2023-03-22 10:31:22 -06:00
|
|
|
if signalFfiError != nil {
|
|
|
|
|
return nil, wrapError(signalFfiError)
|
|
|
|
|
}
|
2025-01-17 17:49:37 +02:00
|
|
|
return wrapSenderCertificate(senderCertificate.raw), nil
|
2023-03-22 10:31:22 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (usmc *UnidentifiedSenderMessageContent) GetMessageType() (CiphertextMessageType, error) {
|
|
|
|
|
var messageType C.uint8_t
|
2025-01-17 17:49:37 +02:00
|
|
|
signalFfiError := C.signal_unidentified_sender_message_content_get_msg_type(&messageType, usmc.constPtr())
|
2024-01-03 20:31:27 +02:00
|
|
|
runtime.KeepAlive(usmc)
|
2023-03-22 10:31:22 -06:00
|
|
|
if signalFfiError != nil {
|
|
|
|
|
return 0, wrapError(signalFfiError)
|
|
|
|
|
}
|
|
|
|
|
return CiphertextMessageType(messageType), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (usmc *UnidentifiedSenderMessageContent) GetContentHint() (UnidentifiedSenderMessageContentHint, error) {
|
|
|
|
|
var contentHint C.uint32_t
|
2025-01-17 17:49:37 +02:00
|
|
|
signalFfiError := C.signal_unidentified_sender_message_content_get_content_hint(&contentHint, usmc.constPtr())
|
2024-01-03 20:31:27 +02:00
|
|
|
runtime.KeepAlive(usmc)
|
2023-03-22 10:31:22 -06:00
|
|
|
if signalFfiError != nil {
|
|
|
|
|
return 0, wrapError(signalFfiError)
|
|
|
|
|
}
|
|
|
|
|
return UnidentifiedSenderMessageContentHint(contentHint), nil
|
|
|
|
|
}
|