From 086dcae907344108f04f71011b41c23350249797 Mon Sep 17 00:00:00 2001 From: Sorunome Date: Fri, 5 Jun 2020 10:51:11 +0200 Subject: [PATCH] add key manager tests --- lib/encryption/key_manager.dart | 5 + test/encryption/key_manager_test.dart | 162 ++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 test/encryption/key_manager_test.dart diff --git a/lib/encryption/key_manager.dart b/lib/encryption/key_manager.dart index 243d5a5..8a8ff42 100644 --- a/lib/encryption/key_manager.dart +++ b/lib/encryption/key_manager.dart @@ -147,6 +147,11 @@ class KeyManager { return sess; } + /// clear all cached inbound group sessions. useful for testing + void clearOutboundGroupSessions() { + _outboundGroupSessions.clear(); + } + /// Clears the existing outboundGroupSession but first checks if the participating /// devices have been changed. Returns false if the session has not been cleared because /// it wasn't necessary. diff --git a/test/encryption/key_manager_test.dart b/test/encryption/key_manager_test.dart new file mode 100644 index 0000000..3094332 --- /dev/null +++ b/test/encryption/key_manager_test.dart @@ -0,0 +1,162 @@ +/* + * Ansible inventory script used at Famedly GmbH for managing many hosts + * Copyright (C) 2020 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 'dart:convert'; +import 'package:famedlysdk/famedlysdk.dart'; +import 'package:test/test.dart'; +import 'package:olm/olm.dart' as olm; + +import '../fake_client.dart'; +import '../fake_matrix_api.dart'; + +void main() { + group('Key Manager', () { + var olmEnabled = true; + try { + olm.init(); + olm.Account(); + } catch (_) { + olmEnabled = false; + print('[LibOlm] Failed to load LibOlm: ' + _.toString()); + } + print('[LibOlm] Enabled: $olmEnabled'); + + if (!olmEnabled) return; + + Client client; + + test('setupClient', () async { + client = await getClient(); + }); + + test('handle new m.room_key', () async { + final validSessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; + final validSenderKey = 'JBG7ZaPn54OBC7TuIEiylW3BZ+7WcGQhFBPB9pogbAg'; + final sessionKey = 'AgAAAAAQcQ6XrFJk6Prm8FikZDqfry/NbDz8Xw7T6e+/9Yf/q3YHIPEQlzv7IZMNcYb51ifkRzFejVvtphS7wwG2FaXIp4XS2obla14iKISR0X74ugB2vyb1AydIHE/zbBQ1ic5s3kgjMFlWpu/S3FQCnCrv+DPFGEt3ERGWxIl3Bl5X53IjPyVkz65oljz2TZESwz0GH/QFvyOOm8ci0q/gceaF3S7Dmafg3dwTKYwcA5xkcc+BLyrLRzB6Hn+oMAqSNSscnm4mTeT5zYibIhrzqyUTMWr32spFtI9dNR/RFSzfCw'; + + + client.encryption.keyManager.clearInboundGroupSessions(); + var event = ToDeviceEvent( + sender: '@alice:example.com', + type: 'm.room_key', + content: { + 'algorithm': 'm.megolm.v1.aes-sha2', + 'room_id': '!726s6s6q:example.com', + 'session_id': validSessionId, + 'session_key': sessionKey, + }, + encryptedContent: { + 'sender_key': validSessionId, + }); + await client.encryption.keyManager.handleToDeviceEvent(event); + expect( + client.encryption.keyManager.getInboundGroupSession( + '!726s6s6q:example.com', validSessionId, validSenderKey) != + null, + true); + + // now test a few invalid scenarios + + // not encrypted + client.encryption.keyManager.clearInboundGroupSessions(); + event = ToDeviceEvent( + sender: '@alice:example.com', + type: 'm.room_key', + content: { + 'algorithm': 'm.megolm.v1.aes-sha2', + 'room_id': '!726s6s6q:example.com', + 'session_id': validSessionId, + 'session_key': sessionKey, + }); + await client.encryption.keyManager.handleToDeviceEvent(event); + expect( + client.encryption.keyManager.getInboundGroupSession( + '!726s6s6q:example.com', validSessionId, validSenderKey) != + null, + false); + }); + + test('outbound group session', () async { + final roomId = '!726s6s6q:example.com'; + expect(client.encryption.keyManager.getOutboundGroupSession(roomId) != null, false); + var sess = await client.encryption.keyManager.createOutboundGroupSession(roomId); + expect(client.encryption.keyManager.getOutboundGroupSession(roomId) != null, true); + await client.encryption.keyManager.clearOutboundGroupSession(roomId); + expect(client.encryption.keyManager.getOutboundGroupSession(roomId) != null, true); + expect(client.encryption.keyManager.getInboundGroupSession(roomId, sess.outboundGroupSession.session_id(), client.identityKey) != null, true); + + // rotate after too many messages + sess.sentMessages = 300; + await client.encryption.keyManager.clearOutboundGroupSession(roomId); + expect(client.encryption.keyManager.getOutboundGroupSession(roomId) != null, false); + + // rotate if devices in room change + sess = await client.encryption.keyManager.createOutboundGroupSession(roomId); + client.userDeviceKeys['@alice:example.com'].deviceKeys['JLAFKJWSCS'].blocked = true; + await client.encryption.keyManager.clearOutboundGroupSession(roomId); + expect(client.encryption.keyManager.getOutboundGroupSession(roomId) != null, false); + client.userDeviceKeys['@alice:example.com'].deviceKeys['JLAFKJWSCS'].blocked = false; + + // rotate if too far in the past + sess = await client.encryption.keyManager.createOutboundGroupSession(roomId); + sess.creationTime = DateTime.now().subtract(Duration(days: 30)); + await client.encryption.keyManager.clearOutboundGroupSession(roomId); + expect(client.encryption.keyManager.getOutboundGroupSession(roomId) != null, false); + + // force wipe + sess = await client.encryption.keyManager.createOutboundGroupSession(roomId); + await client.encryption.keyManager.clearOutboundGroupSession(roomId, wipe: true); + expect(client.encryption.keyManager.getOutboundGroupSession(roomId) != null, false); + + // load from database + sess = await client.encryption.keyManager.createOutboundGroupSession(roomId); + client.encryption.keyManager.clearOutboundGroupSessions(); + expect(client.encryption.keyManager.getOutboundGroupSession(roomId) != null, false); + await client.encryption.keyManager.loadOutboundGroupSession(roomId); + expect(client.encryption.keyManager.getOutboundGroupSession(roomId) != null, true); + }); + + test('inbound group session', () async { + final roomId = '!726s6s6q:example.com'; + final sessionId = 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'; + final senderKey = 'JBG7ZaPn54OBC7TuIEiylW3BZ+7WcGQhFBPB9pogbAg'; + final sessionContent = { + 'algorithm': 'm.megolm.v1.aes-sha2', + 'room_id': '!726s6s6q:example.com', + 'session_id': 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU', + 'session_key': + 'AgAAAAAQcQ6XrFJk6Prm8FikZDqfry/NbDz8Xw7T6e+/9Yf/q3YHIPEQlzv7IZMNcYb51ifkRzFejVvtphS7wwG2FaXIp4XS2obla14iKISR0X74ugB2vyb1AydIHE/zbBQ1ic5s3kgjMFlWpu/S3FQCnCrv+DPFGEt3ERGWxIl3Bl5X53IjPyVkz65oljz2TZESwz0GH/QFvyOOm8ci0q/gceaF3S7Dmafg3dwTKYwcA5xkcc+BLyrLRzB6Hn+oMAqSNSscnm4mTeT5zYibIhrzqyUTMWr32spFtI9dNR/RFSzfCw' + }; + client.encryption.keyManager.clearInboundGroupSessions(); + expect(client.encryption.keyManager.getInboundGroupSession(roomId, sessionId, senderKey) != null, false); + client.encryption.keyManager.setInboundGroupSession(roomId, sessionId, senderKey, sessionContent); + await Future.delayed(Duration(milliseconds: 10)); + expect(client.encryption.keyManager.getInboundGroupSession(roomId, sessionId, senderKey) != null, true); + + expect(client.encryption.keyManager.getInboundGroupSession(roomId, sessionId, senderKey) != null, true); + expect(client.encryption.keyManager.getInboundGroupSession('otherroom', sessionId, senderKey) != null, true); + expect(client.encryption.keyManager.getInboundGroupSession('otherroom', 'invalid', senderKey) != null, false); + + client.encryption.keyManager.clearInboundGroupSessions(); + expect(client.encryption.keyManager.getInboundGroupSession(roomId, sessionId, senderKey) != null, false); + await client.encryption.keyManager.loadInboundGroupSession(roomId, sessionId, senderKey); + expect(client.encryption.keyManager.getInboundGroupSession(roomId, sessionId, senderKey) != null, true); + + }); + }); +}