// @dart=2.9 /* * Famedly Matrix SDK * Copyright (C) 2019, 2020, 2021 Famedly GmbH * * 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 . */ import 'package:matrix/encryption/utils/stored_inbound_group_session.dart'; import 'package:olm/olm.dart' as olm; import '../../matrix.dart'; class SessionKey { /// The raw json content of the key Map content; /// Map of stringified-index to event id, so that we can detect replay attacks Map indexes; /// Map of userId to map of deviceId to index, that we know that device receivied, e.g. sending it ourself. /// Used for automatically answering key requests Map> allowedAtIndex; /// Underlying olm [InboundGroupSession] object olm.InboundGroupSession inboundGroupSession; /// Key for libolm pickle / unpickle final String key; /// Forwarding keychain List get forwardingCurve25519KeyChain => (content['forwarding_curve25519_key_chain'] != null ? List.from(content['forwarding_curve25519_key_chain']) : null) ?? []; /// Claimed keys of the original sender Map senderClaimedKeys; /// Sender curve25519 key String senderKey; /// Is this session valid? bool get isValid => inboundGroupSession != null; /// roomId for this session String roomId; /// Id of this session String sessionId; SessionKey( {this.content, this.inboundGroupSession, this.key, this.indexes, this.allowedAtIndex, this.roomId, this.sessionId, String senderKey, Map senderClaimedKeys}) { _setSenderKey(senderKey); _setSenderClaimedKeys(senderClaimedKeys); indexes ??= {}; allowedAtIndex ??= >{}; } SessionKey.fromDb(StoredInboundGroupSession dbEntry, String key) : key = key { final parsedContent = Event.getMapFromPayload(dbEntry.content); final parsedIndexes = Event.getMapFromPayload(dbEntry.indexes); final parsedAllowedAtIndex = Event.getMapFromPayload(dbEntry.allowedAtIndex); final parsedSenderClaimedKeys = Event.getMapFromPayload(dbEntry.senderClaimedKeys); content = parsedContent; // we need to try...catch as the map used to be and that will throw an error. try { indexes = parsedIndexes != null ? Map.from(parsedIndexes) : {}; } catch (e) { indexes = {}; } try { allowedAtIndex = parsedAllowedAtIndex != null ? Map>.from(parsedAllowedAtIndex .map((k, v) => MapEntry(k, Map.from(v)))) : >{}; } catch (e) { allowedAtIndex = >{}; } roomId = dbEntry.roomId; sessionId = dbEntry.sessionId; _setSenderKey(dbEntry.senderKey); _setSenderClaimedKeys(Map.from(parsedSenderClaimedKeys)); inboundGroupSession = olm.InboundGroupSession(); try { inboundGroupSession.unpickle(key, dbEntry.pickle); } catch (e, s) { dispose(); Logs().e('[LibOlm] Unable to unpickle inboundGroupSession', e, s); } } void _setSenderKey(String key) { senderKey = key ?? content['sender_key'] ?? ''; } void _setSenderClaimedKeys(Map keys) { senderClaimedKeys = (keys != null && keys.isNotEmpty) ? keys : (content['sender_claimed_keys'] is Map ? Map.from(content['sender_claimed_keys']) : (content['sender_claimed_ed25519_key'] is String ? { 'ed25519': content['sender_claimed_ed25519_key'] } : {})); } void dispose() { inboundGroupSession?.free(); inboundGroupSession = null; } }