Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/connector/e2ee_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func (lc *LineClient) fetchAndUnwrapGroupKey(ctx context.Context, chatMid string
Int("group_key_id", sharedKey.GroupKeyID).
Int("creator_key_id", sharedKey.CreatorKeyID).
Int("receiver_key_id", sharedKey.ReceiverKeyID).
Int("spec_version", sharedKey.SpecVersion).
Msg("Fetched group shared key")

if _, _, err := lc.ensurePeerKey(ctx, sharedKey.Creator); err != nil {
Expand Down
3 changes: 3 additions & 0 deletions pkg/connector/send_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,7 @@ func (lc *LineClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2.Mat
lineMsg.Text = plainTextBody
} else {
lineMsg.Chunks = chunks
contentMetadata["e2eeVersion"] = strconv.Itoa(e2ee.ChunksVersion(chunks))
}

var relatedMsg *database.Message
Expand Down Expand Up @@ -776,6 +777,7 @@ func (lc *LineClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2.Mat
return nil, wrapConvertError(fmt.Errorf("failed to encrypt zipped file message: %w", err))
}
lineMsg.Chunks = chunks
contentMetadata["e2eeVersion"] = strconv.Itoa(e2ee.ChunksVersion(chunks))
}

retryReqSeq := int(time.Now().UnixMilli() % 1_000_000_000)
Expand All @@ -801,6 +803,7 @@ func (lc *LineClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2.Mat
}
if err == nil {
lineMsg.Chunks = chunks
contentMetadata["e2eeVersion"] = strconv.Itoa(e2ee.ChunksVersion(chunks))
lineMsg.Text = ""
}
}
Expand Down
23 changes: 23 additions & 0 deletions pkg/e2ee/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ type Manager struct {
groupSessionChannels map[string]map[int]map[int]int

latestGroupKey map[string]int // chatMid -> latest groupKeyId
// groupSpecVersion maps chatMid -> specVersion of the latest group key
groupSpecVersion map[string]int

groupKeyLRU []groupKeyRef
groupNativeObjects int
Expand Down Expand Up @@ -83,6 +85,7 @@ func NewManagerWithRunner(r *gen.Runner) *Manager {
groupKeys: make(map[string]map[int]int),
groupSessionChannels: make(map[string]map[int]map[int]int),
latestGroupKey: make(map[string]int),
groupSpecVersion: make(map[string]int),
}
}

Expand All @@ -104,6 +107,7 @@ func (m *Manager) Close() {
m.groupKeys = nil
m.groupSessionChannels = nil
m.latestGroupKey = nil
m.groupSpecVersion = nil
m.groupKeyLRU = nil
m.groupNativeObjects = 0
}
Expand Down Expand Up @@ -540,6 +544,18 @@ func assembleCipherV1(chunks []string) ([]byte, error) {
return append(append(b0, b1...), b2...), nil
}

// ChunksVersion returns the Letter Sealing version (1 or 2) of encrypted message chunks.
func ChunksVersion(chunks []string) int {
if len(chunks) == 0 {
return 2
}
ver, err := cipherVersion(chunks)
if err != nil {
return 2
}
return ver
}

func cipherVersion(chunks []string) (int, error) {
first, err := base64.StdEncoding.DecodeString(strings.TrimSpace(chunks[0]))
if err != nil {
Expand All @@ -561,6 +577,7 @@ func (m *Manager) UnwrapGroupSharedKey(chatMid string, sharedKey *line.E2EEGroup
ref := groupKeyRef{chatMid, sharedKey.GroupKeyID}
if id := m.groupKeys[chatMid][sharedKey.GroupKeyID]; id != 0 {
m.latestGroupKey[chatMid] = sharedKey.GroupKeyID
m.groupSpecVersion[chatMid] = sharedKey.SpecVersion
m.touchGroupKeyLocked(ref)
return id, nil
}
Expand Down Expand Up @@ -599,6 +616,7 @@ func (m *Manager) UnwrapGroupSharedKey(chatMid string, sharedKey *line.E2EEGroup
m.groupKeys[chatMid][sharedKey.GroupKeyID] = unwrappedKeyID

m.latestGroupKey[chatMid] = sharedKey.GroupKeyID
m.groupSpecVersion[chatMid] = sharedKey.SpecVersion
m.groupNativeObjects++
m.touchGroupKeyLocked(ref)

Expand Down Expand Up @@ -631,6 +649,7 @@ func (m *Manager) evictGroupKeysLocked() error {
}
if m.latestGroupKey[ref.chatMid] == ref.groupKeyID {
delete(m.latestGroupKey, ref.chatMid)
delete(m.groupSpecVersion, ref.chatMid)
}
if err := m.runner.KeyDestroy(keyID); err != nil && isFatalLTSMError(err) {
return err
Expand Down Expand Up @@ -860,6 +879,10 @@ func (m *Manager) EncryptGroupMessageRaw(chatMid, fromMid string, contentType in
return nil, err
}

if m.groupSpecVersion[chatMid] == 1 {
return m.encryptV1Chunks(chanID, myKeyID, groupKeyID, payload)
}

ctB64, err := m.runner.ChannelEncryptV2(chanID, chatMid, fromMid, myKeyID, groupKeyID, contentType, seq, string(payload))
if err != nil {
if isFatalLTSMError(err) {
Expand Down
Loading