@@ -176,7 +176,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("megolm-keys backup (%s)", (backe
176
176
expect ( event . getContent ( ) ) . toEqual ( "testytest" ) ;
177
177
} ) ;
178
178
179
- oldBackendOnly ( "getActiveSessionBackupVersion() should give correct result" , async function ( ) {
179
+ it ( "getActiveSessionBackupVersion() should give correct result" , async function ( ) {
180
180
// 404 means that there is no active backup
181
181
fetchMock . get ( "express:/_matrix/client/v3/room_keys/version" , 404 ) ;
182
182
@@ -187,7 +187,7 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("megolm-keys backup (%s)", (backe
187
187
// tell Alice to trust the dummy device that signed the backup
188
188
await waitForDeviceList ( ) ;
189
189
await aliceCrypto . setDeviceVerified ( testData . TEST_USER_ID , testData . TEST_DEVICE_ID ) ;
190
- await aliceClient . checkKeyBackup ( ) ;
190
+ await aliceCrypto . checkKeyBackupAndEnable ( ) ;
191
191
192
192
// At this point there is no backup
193
193
let backupStatus : string | null ;
@@ -201,9 +201,9 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("megolm-keys backup (%s)", (backe
201
201
overwriteRoutes : true ,
202
202
} ) ;
203
203
204
- const checked = await aliceClient . checkKeyBackup ( ) ;
204
+ const checked = await aliceCrypto . checkKeyBackupAndEnable ( ) ;
205
205
expect ( checked ?. backupInfo ?. version ) . toStrictEqual ( unsignedBackup . version ) ;
206
- expect ( checked ?. trustInfo ?. usable ) . toBeFalsy ( ) ;
206
+ expect ( checked ?. trustInfo ?. trusted ) . toBeFalsy ( ) ;
207
207
208
208
backupStatus = await aliceCrypto . getActiveSessionBackupVersion ( ) ;
209
209
expect ( backupStatus ) . toBeNull ( ) ;
@@ -222,8 +222,8 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("megolm-keys backup (%s)", (backe
222
222
} ) ;
223
223
} ) ;
224
224
225
- const validCheck = await aliceClient . checkKeyBackup ( ) ;
226
- expect ( validCheck ?. trustInfo ?. usable ) . toStrictEqual ( true ) ;
225
+ const validCheck = await aliceCrypto . checkKeyBackupAndEnable ( ) ;
226
+ expect ( validCheck ?. trustInfo ?. trusted ) . toStrictEqual ( true ) ;
227
227
228
228
await backupPromise ;
229
229
@@ -286,6 +286,128 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("megolm-keys backup (%s)", (backe
286
286
} ) ;
287
287
} ) ;
288
288
289
+ describe ( "checkKeyBackupAndEnable" , ( ) => {
290
+ it ( "enables a backup signed by a trusted device" , async ( ) => {
291
+ aliceClient = await initTestClient ( ) ;
292
+ const aliceCrypto = aliceClient . getCrypto ( ) ! ;
293
+
294
+ // tell Alice to trust the dummy device that signed the backup
295
+ await aliceClient . startClient ( ) ;
296
+ await waitForDeviceList ( ) ;
297
+ await aliceCrypto . setDeviceVerified ( testData . TEST_USER_ID , testData . TEST_DEVICE_ID ) ;
298
+
299
+ fetchMock . get ( "path:/_matrix/client/v3/room_keys/version" , testData . SIGNED_BACKUP_DATA ) ;
300
+
301
+ const result = await aliceCrypto . checkKeyBackupAndEnable ( ) ;
302
+ expect ( result ) . toBeTruthy ( ) ;
303
+ expect ( result ! . trustInfo ) . toEqual ( { trusted : true , matchesDecryptionKey : false } ) ;
304
+ expect ( await aliceCrypto . getActiveSessionBackupVersion ( ) ) . toEqual ( testData . SIGNED_BACKUP_DATA . version ) ;
305
+ } ) ;
306
+
307
+ it ( "does not enable a backup signed by an untrusted device" , async ( ) => {
308
+ aliceClient = await initTestClient ( ) ;
309
+ const aliceCrypto = aliceClient . getCrypto ( ) ! ;
310
+
311
+ // download the device list, to match the trusted case
312
+ await aliceClient . startClient ( ) ;
313
+ await waitForDeviceList ( ) ;
314
+
315
+ fetchMock . get ( "path:/_matrix/client/v3/room_keys/version" , testData . SIGNED_BACKUP_DATA ) ;
316
+
317
+ const result = await aliceCrypto . checkKeyBackupAndEnable ( ) ;
318
+ expect ( result ) . toBeTruthy ( ) ;
319
+ expect ( result ! . trustInfo ) . toEqual ( { trusted : false , matchesDecryptionKey : false } ) ;
320
+ expect ( await aliceCrypto . getActiveSessionBackupVersion ( ) ) . toBeNull ( ) ;
321
+ } ) ;
322
+
323
+ it ( "disables backup when a new untrusted backup is available" , async ( ) => {
324
+ aliceClient = await initTestClient ( ) ;
325
+ const aliceCrypto = aliceClient . getCrypto ( ) ! ;
326
+
327
+ // tell Alice to trust the dummy device that signed the backup
328
+ await aliceClient . startClient ( ) ;
329
+ await waitForDeviceList ( ) ;
330
+ await aliceCrypto . setDeviceVerified ( testData . TEST_USER_ID , testData . TEST_DEVICE_ID ) ;
331
+
332
+ fetchMock . get ( "path:/_matrix/client/v3/room_keys/version" , testData . SIGNED_BACKUP_DATA ) ;
333
+
334
+ const result = await aliceCrypto . checkKeyBackupAndEnable ( ) ;
335
+ expect ( result ) . toBeTruthy ( ) ;
336
+ expect ( await aliceCrypto . getActiveSessionBackupVersion ( ) ) . toEqual ( testData . SIGNED_BACKUP_DATA . version ) ;
337
+
338
+ const unsignedBackup = JSON . parse ( JSON . stringify ( testData . SIGNED_BACKUP_DATA ) ) ;
339
+ delete unsignedBackup . auth_data . signatures ;
340
+ unsignedBackup . version = "2" ;
341
+
342
+ fetchMock . get ( "path:/_matrix/client/v3/room_keys/version" , unsignedBackup , {
343
+ overwriteRoutes : true ,
344
+ } ) ;
345
+
346
+ await aliceCrypto . checkKeyBackupAndEnable ( ) ;
347
+ expect ( await aliceCrypto . getActiveSessionBackupVersion ( ) ) . toBeNull ( ) ;
348
+ } ) ;
349
+
350
+ it ( "switches backup when a new trusted backup is available" , async ( ) => {
351
+ aliceClient = await initTestClient ( ) ;
352
+ const aliceCrypto = aliceClient . getCrypto ( ) ! ;
353
+
354
+ // tell Alice to trust the dummy device that signed the backup
355
+ await aliceClient . startClient ( ) ;
356
+ await waitForDeviceList ( ) ;
357
+ await aliceCrypto . setDeviceVerified ( testData . TEST_USER_ID , testData . TEST_DEVICE_ID ) ;
358
+
359
+ fetchMock . get ( "path:/_matrix/client/v3/room_keys/version" , testData . SIGNED_BACKUP_DATA ) ;
360
+
361
+ const result = await aliceCrypto . checkKeyBackupAndEnable ( ) ;
362
+ expect ( result ) . toBeTruthy ( ) ;
363
+ expect ( await aliceCrypto . getActiveSessionBackupVersion ( ) ) . toEqual ( testData . SIGNED_BACKUP_DATA . version ) ;
364
+
365
+ const newBackupVersion = "2" ;
366
+ const unsignedBackup = JSON . parse ( JSON . stringify ( testData . SIGNED_BACKUP_DATA ) ) ;
367
+ unsignedBackup . version = newBackupVersion ;
368
+
369
+ fetchMock . get ( "path:/_matrix/client/v3/room_keys/version" , unsignedBackup , {
370
+ overwriteRoutes : true ,
371
+ } ) ;
372
+
373
+ await aliceCrypto . checkKeyBackupAndEnable ( ) ;
374
+ expect ( await aliceCrypto . getActiveSessionBackupVersion ( ) ) . toEqual ( newBackupVersion ) ;
375
+ } ) ;
376
+
377
+ it ( "Disables when backup is deleted" , async ( ) => {
378
+ aliceClient = await initTestClient ( ) ;
379
+ const aliceCrypto = aliceClient . getCrypto ( ) ! ;
380
+
381
+ // tell Alice to trust the dummy device that signed the backup
382
+ await aliceClient . startClient ( ) ;
383
+ await waitForDeviceList ( ) ;
384
+ await aliceCrypto . setDeviceVerified ( testData . TEST_USER_ID , testData . TEST_DEVICE_ID ) ;
385
+
386
+ fetchMock . get ( "path:/_matrix/client/v3/room_keys/version" , testData . SIGNED_BACKUP_DATA ) ;
387
+
388
+ const result = await aliceCrypto . checkKeyBackupAndEnable ( ) ;
389
+ expect ( result ) . toBeTruthy ( ) ;
390
+ expect ( await aliceCrypto . getActiveSessionBackupVersion ( ) ) . toEqual ( testData . SIGNED_BACKUP_DATA . version ) ;
391
+
392
+ fetchMock . get (
393
+ "path:/_matrix/client/v3/room_keys/version" ,
394
+ {
395
+ status : 404 ,
396
+ body : {
397
+ errcode : "M_NOT_FOUND" ,
398
+ error : "No backup found" ,
399
+ } ,
400
+ } ,
401
+ {
402
+ overwriteRoutes : true ,
403
+ } ,
404
+ ) ;
405
+ const noResult = await aliceCrypto . checkKeyBackupAndEnable ( ) ;
406
+ expect ( noResult ) . toBeNull ( ) ;
407
+ expect ( await aliceCrypto . getActiveSessionBackupVersion ( ) ) . toBeNull ( ) ;
408
+ } ) ;
409
+ } ) ;
410
+
289
411
/** make sure that the client knows about the dummy device */
290
412
async function waitForDeviceList ( ) : Promise < void > {
291
413
// Completing the initial sync will make the device list download outdated device lists (of which our own
0 commit comments