From c81f11df0afd4d0da3b088892745ae2f8ba1c4a7 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Wed, 27 May 2020 19:34:28 -0400 Subject: [PATCH] encrypt/decrypt cached private keys with pickle key --- src/crypto/CrossSigning.js | 19 +++++++++++++++---- src/crypto/index.js | 17 ++++++++++++++--- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/crypto/CrossSigning.js b/src/crypto/CrossSigning.js index 6d86d1bd9..ff5bc7080 100644 --- a/src/crypto/CrossSigning.js +++ b/src/crypto/CrossSigning.js @@ -24,6 +24,7 @@ import {decodeBase64, encodeBase64, pkSign, pkVerify} from './olmlib'; import {EventEmitter} from 'events'; import {logger} from '../logger'; import {IndexedDBCryptoStore} from '../crypto/store/indexeddb-crypto-store'; +import {decryptAES, encryptAES} from './aes'; function publicKeyFromKeyInfo(keyInfo) { // `keys` is an object with { [`ed25519:${pubKey}`]: pubKey } @@ -637,10 +638,10 @@ export class DeviceTrustLevel { } } -export function createCryptoStoreCacheCallbacks(store) { +export function createCryptoStoreCacheCallbacks(store, olmdevice) { return { - getCrossSigningKeyCache: function(type, _expectedPublicKey) { - return new Promise((resolve) => { + getCrossSigningKeyCache: async function(type, _expectedPublicKey) { + const key = await new Promise((resolve) => { return store.doTxn( 'readonly', [IndexedDBCryptoStore.STORE_ACCOUNT], @@ -649,13 +650,23 @@ export function createCryptoStoreCacheCallbacks(store) { }, ); }); + + if (key && key.ciphertext) { + const pickleKey = Buffer.from(olmdevice._pickleKey); + const decrypted = await decryptAES(key, pickleKey, type); + return decodeBase64(decrypted); + } else { + return key; + } }, - storeCrossSigningKeyCache: function(type, key) { + storeCrossSigningKeyCache: async function(type, key) { if (!(key instanceof Uint8Array)) { throw new Error( `storeCrossSigningKeyCache expects Uint8Array, got ${key}`, ); } + const pickleKey = Buffer.from(olmdevice._pickleKey); + key = await encryptAES(encodeBase64(key), pickleKey, type); return store.doTxn( 'readwrite', [IndexedDBCryptoStore.STORE_ACCOUNT], diff --git a/src/crypto/index.js b/src/crypto/index.js index aa74cae97..06cc2add2 100644 --- a/src/crypto/index.js +++ b/src/crypto/index.js @@ -56,6 +56,7 @@ import {ToDeviceChannel, ToDeviceRequests} from "./verification/request/ToDevice import * as httpApi from "../http-api"; import {IllegalMethod} from "./verification/IllegalMethod"; import {KeySignatureUploadError} from "../errors"; +import {decryptAES, encryptAES} from './aes'; const DeviceVerification = DeviceInfo.DeviceVerification; @@ -231,7 +232,7 @@ export function Crypto(baseApis, sessionStore, userId, deviceId, this._sendKeyRequestsImmediately = false; const cryptoCallbacks = this._baseApis._cryptoCallbacks || {}; - const cacheCallbacks = createCryptoStoreCacheCallbacks(cryptoStore); + const cacheCallbacks = createCryptoStoreCacheCallbacks(cryptoStore, this._olmDevice); this._crossSigningInfo = new CrossSigningInfo( userId, @@ -798,8 +799,8 @@ Crypto.prototype.checkSecretStoragePrivateKey = function(privateKey, expectedPub * Fetches the backup private key, if cached * @returns {Promise} the key, if any, or null */ -Crypto.prototype.getSessionBackupPrivateKey = function() { - return new Promise((resolve) => { +Crypto.prototype.getSessionBackupPrivateKey = async function() { + const key = await new Promise((resolve) => { this._cryptoStore.doTxn( 'readonly', [IndexedDBCryptoStore.STORE_ACCOUNT], @@ -812,6 +813,14 @@ Crypto.prototype.getSessionBackupPrivateKey = function() { }, ); }); + + if (key && key.ciphertext) { + const pickleKey = Buffer.from(this._olmDevice._pickleKey); + const decrypted = await decryptAES(key, pickleKey, "m.megolm_backup.v1"); + return olmlib.decodeBase64(decrypted); + } else { + return key; + } }; /** @@ -823,6 +832,8 @@ Crypto.prototype.storeSessionBackupPrivateKey = async function(key) { if (!(key instanceof Uint8Array)) { throw new Error(`storeSessionBackupPrivateKey expects Uint8Array, got ${key}`); } + const pickleKey = Buffer.from(this._olmDevice._pickleKey); + key = await encryptAES(olmlib.encodeBase64(key), pickleKey, "m.megolm_backup.v1"); return this._cryptoStore.doTxn( 'readwrite', [IndexedDBCryptoStore.STORE_ACCOUNT],