LCOV - code coverage report
Current view: top level - lib/encryption/utils - session_key.dart (source / functions) Coverage Total Hit
Test: merged.info Lines: 71.4 % 35 25
Test Date: 2025-10-13 02:23:18 Functions: - 0 0

            Line data    Source code
       1              : /*
       2              :  *   Famedly Matrix SDK
       3              :  *   Copyright (C) 2019, 2020, 2021 Famedly GmbH
       4              :  *
       5              :  *   This program is free software: you can redistribute it and/or modify
       6              :  *   it under the terms of the GNU Affero General Public License as
       7              :  *   published by the Free Software Foundation, either version 3 of the
       8              :  *   License, or (at your option) any later version.
       9              :  *
      10              :  *   This program is distributed in the hope that it will be useful,
      11              :  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              :  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      13              :  *   GNU Affero General Public License for more details.
      14              :  *
      15              :  *   You should have received a copy of the GNU Affero General Public License
      16              :  *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
      17              :  */
      18              : 
      19              : import 'dart:convert';
      20              : 
      21              : import 'package:vodozemac/vodozemac.dart' as vod;
      22              : 
      23              : import 'package:matrix/encryption/utils/pickle_key.dart';
      24              : import 'package:matrix/encryption/utils/stored_inbound_group_session.dart';
      25              : import 'package:matrix/matrix.dart';
      26              : 
      27              : class SessionKey {
      28              :   /// The raw json content of the key
      29              :   Map<String, dynamic> content = <String, dynamic>{};
      30              : 
      31              :   /// Map of stringified-index to event id, so that we can detect replay attacks
      32              :   Map<String, String> indexes;
      33              : 
      34              :   /// Map of userId to map of deviceId to index, that we know that device receivied, e.g. sending it ourself.
      35              :   /// Used for automatically answering key requests
      36              :   Map<String, Map<String, int>> allowedAtIndex;
      37              : 
      38              :   /// Underlying olm [InboundGroupSession] object
      39              :   vod.InboundGroupSession? inboundGroupSession;
      40              : 
      41              :   /// Key for libolm pickle / unpickle
      42              :   final String key;
      43              : 
      44              :   /// Forwarding keychain
      45            6 :   List<String> get forwardingCurve25519KeyChain =>
      46           12 :       (content['forwarding_curve25519_key_chain'] != null
      47            6 :           ? List<String>.from(content['forwarding_curve25519_key_chain'])
      48              :           : null) ??
      49            4 :       <String>[];
      50              : 
      51              :   /// Claimed keys of the original sender
      52              :   late Map<String, String> senderClaimedKeys;
      53              : 
      54              :   /// Sender curve25519 key
      55              :   String senderKey;
      56              : 
      57              :   /// Is this session valid?
      58           14 :   bool get isValid => inboundGroupSession != null;
      59              : 
      60              :   /// roomId for this session
      61              :   String roomId;
      62              : 
      63              :   /// Id of this session
      64              :   String sessionId;
      65              : 
      66           27 :   SessionKey({
      67              :     required this.content,
      68              :     required this.inboundGroupSession,
      69              :     required this.key,
      70              :     Map<String, String>? indexes,
      71              :     Map<String, Map<String, int>>? allowedAtIndex,
      72              :     required this.roomId,
      73              :     required this.sessionId,
      74              :     required this.senderKey,
      75              :     required this.senderClaimedKeys,
      76            0 :   })  : indexes = indexes ?? <String, String>{},
      77            0 :         allowedAtIndex = allowedAtIndex ?? <String, Map<String, int>>{};
      78              : 
      79            6 :   SessionKey.fromDb(StoredInboundGroupSession dbEntry, this.key)
      80           12 :       : content = Event.getMapFromPayload(dbEntry.content),
      81           12 :         indexes = Event.getMapFromPayload(dbEntry.indexes)
      82            8 :             .catchMap((k, v) => MapEntry<String, String>(k, v)),
      83           12 :         allowedAtIndex = Event.getMapFromPayload(dbEntry.allowedAtIndex)
      84            9 :             .catchMap((k, v) => MapEntry(k, Map<String, int>.from(v))),
      85            6 :         roomId = dbEntry.roomId,
      86            6 :         sessionId = dbEntry.sessionId,
      87            6 :         senderKey = dbEntry.senderKey {
      88              :     final parsedSenderClaimedKeys =
      89           12 :         Event.getMapFromPayload(dbEntry.senderClaimedKeys)
      90           12 :             .catchMap((k, v) => MapEntry<String, String>(k, v));
      91              :     // we need to try...catch as the map used to be <String, int> and that will throw an error.
      92           12 :     senderClaimedKeys = (parsedSenderClaimedKeys.isNotEmpty)
      93              :         ? parsedSenderClaimedKeys
      94            3 :         : (content
      95            3 :                 .tryGetMap<String, dynamic>('sender_claimed_keys')
      96            0 :                 ?.catchMap((k, v) => MapEntry<String, String>(k, v)) ??
      97            9 :             (content['sender_claimed_ed25519_key'] is String
      98            0 :                 ? <String, String>{
      99            0 :                     'ed25519': content['sender_claimed_ed25519_key'],
     100              :                   }
     101            3 :                 : <String, String>{}));
     102              : 
     103              :     try {
     104           12 :       inboundGroupSession = vod.InboundGroupSession.fromPickleEncrypted(
     105            6 :         pickle: dbEntry.pickle,
     106           12 :         pickleKey: key.toPickleKey(),
     107              :       );
     108              :     } catch (e, s) {
     109              :       try {
     110            0 :         Logs().d('Unable to unpickle inboundGroupSession. Try LibOlm format.');
     111            0 :         inboundGroupSession = vod.InboundGroupSession.fromOlmPickleEncrypted(
     112            0 :           pickle: dbEntry.pickle,
     113            0 :           pickleKey: utf8.encode(key),
     114              :         );
     115              :       } catch (_) {
     116            0 :         Logs().e('[Vodozemac] Unable to unpickle inboundGroupSession', e, s);
     117              :         rethrow;
     118              :       }
     119              :     }
     120              :   }
     121              : }
        

Generated by: LCOV version 2.0-1