1
0
Fork 0
mirror of https://github.com/mautrix/signal.git synced 2026-05-15 05:36:53 -04:00
mautrix-signal/pkg/libsignalgo/sealedsender.go

305 lines
10 KiB
Go
Raw Permalink Normal View History

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/>.
package libsignalgo
/*
#include "./libsignal-ffi.h"
*/
import "C"
import (
2024-01-04 01:06:45 +02:00
"context"
"fmt"
"runtime"
"unsafe"
"github.com/google/uuid"
)
type SealedSenderAddress struct {
E164 string
UUID uuid.UUID
DeviceID uint32
}
func NewSealedSenderAddress(e164 string, uuid uuid.UUID, deviceID uint32) *SealedSenderAddress {
return &SealedSenderAddress{
E164: e164,
UUID: uuid,
DeviceID: deviceID,
}
}
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)
if err != nil {
return nil, err
}
usmc, err := NewUnidentifiedSenderMessageContent(
ciphertextMessage,
fromSenderCert,
contentHint,
groupID,
)
if err != nil {
return nil, err
}
2024-01-04 01:06:45 +02:00
return SealedSenderEncrypt(ctx, usmc, forAddress, identityStore)
}
2024-01-04 01:06:45 +02:00
func SealedSenderEncrypt(ctx context.Context, usmc *UnidentifiedSenderMessageContent, forRecipient *Address, identityStore IdentityKeyStore) ([]byte, error) {
var encrypted C.SignalOwnedBuffer = C.SignalOwnedBuffer{}
2024-01-04 01:06:45 +02:00
callbackCtx := NewCallbackContext(ctx)
defer callbackCtx.Unref()
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),
)
2024-01-03 20:31:27 +02:00
runtime.KeepAlive(usmc)
runtime.KeepAlive(forRecipient)
if signalFfiError != nil {
2024-01-04 01:06:45 +02:00
return nil, callbackCtx.wrapError(signalFfiError)
}
return CopySignalOwnedBufferToBytes(encrypted), nil
}
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))
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
}
type SealedSenderResult struct {
Message []byte
Sender SealedSenderAddress
}
func SealedSenderDecryptToUSMC(
2024-01-04 01:06:45 +02:00
ctx context.Context,
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
signalFfiError := C.signal_sealed_session_cipher_decrypt_to_usmc(
&usmc,
BytesToBuffer(ciphertext),
2024-01-04 01:06:45 +02:00
callbackCtx.wrapIdentityKeyStore(identityStore),
)
2024-01-03 20:31:27 +02:00
runtime.KeepAlive(ciphertext)
if signalFfiError != nil {
2024-01-04 01:06:45 +02:00
return nil, callbackCtx.wrapError(signalFfiError)
}
2025-01-17 17:49:37 +02:00
return wrapUnidentifiedSenderMessageContent(usmc.raw), nil
}
type UnidentifiedSenderMessageContentHint uint32
const (
UnidentifiedSenderMessageContentHintDefault UnidentifiedSenderMessageContentHint = 0
UnidentifiedSenderMessageContentHintResendable UnidentifiedSenderMessageContentHint = 1
UnidentifiedSenderMessageContentHintImplicit UnidentifiedSenderMessageContentHint = 2
)
type UnidentifiedSenderMessageContent struct {
nc noCopy
ptr *C.SignalUnidentifiedSenderMessageContent
}
func wrapUnidentifiedSenderMessageContent(ptr *C.SignalUnidentifiedSenderMessageContent) *UnidentifiedSenderMessageContent {
messageContent := &UnidentifiedSenderMessageContent{ptr: ptr}
runtime.SetFinalizer(messageContent, (*UnidentifiedSenderMessageContent).Destroy)
return messageContent
}
func NewUnidentifiedSenderMessageContent(message *CiphertextMessage, senderCertificate *SenderCertificate, contentHint UnidentifiedSenderMessageContentHint, groupID *GroupIdentifier) (*UnidentifiedSenderMessageContent, error) {
2025-01-17 17:49:37 +02:00
var usmc C.SignalMutPointerUnidentifiedSenderMessageContent
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),
BytesToBuffer(groupIDBytes),
2025-01-17 17:49:37 +02:00
)
2024-01-03 20:31:27 +02:00
runtime.KeepAlive(message)
runtime.KeepAlive(senderCertificate)
runtime.KeepAlive(groupIDBytes)
if signalFfiError != nil {
return nil, wrapError(signalFfiError)
}
2025-01-17 17:49:37 +02:00
return wrapUnidentifiedSenderMessageContent(usmc.raw), nil
}
//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
//}
func DeserializeUnidentifiedSenderMessageContent(serialized []byte) (*UnidentifiedSenderMessageContent, error) {
2025-01-17 17:49:37 +02:00
var usmc C.SignalMutPointerUnidentifiedSenderMessageContent
signalFfiError := C.signal_unidentified_sender_message_content_deserialize(&usmc, BytesToBuffer(serialized))
2024-01-03 20:31:27 +02:00
runtime.KeepAlive(serialized)
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}
}
func (usmc *UnidentifiedSenderMessageContent) Destroy() error {
usmc.CancelFinalizer()
2025-01-17 17:49:37 +02:00
return wrapError(C.signal_unidentified_sender_message_content_destroy(usmc.mutPtr()))
}
func (usmc *UnidentifiedSenderMessageContent) CancelFinalizer() {
runtime.SetFinalizer(usmc, nil)
}
func (usmc *UnidentifiedSenderMessageContent) Serialize() ([]byte, error) {
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)
if signalFfiError != nil {
return nil, wrapError(signalFfiError)
}
return CopySignalOwnedBufferToBytes(serialized), nil
}
func (usmc *UnidentifiedSenderMessageContent) GetContents() ([]byte, error) {
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)
if signalFfiError != nil {
return nil, wrapError(signalFfiError)
}
return CopySignalOwnedBufferToBytes(contents), nil
}
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
}
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)
if signalFfiError != nil {
return nil, wrapError(signalFfiError)
}
2025-01-17 17:49:37 +02:00
return wrapSenderCertificate(senderCertificate.raw), nil
}
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)
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)
if signalFfiError != nil {
return 0, wrapError(signalFfiError)
}
return UnidentifiedSenderMessageContentHint(contentHint), nil
}