aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Brunschwig <[email protected]>2021-12-29 14:51:10 +0100
committerPatrick Brunschwig <[email protected]>2021-12-29 14:51:10 +0100
commitfab67aebb6789f150b5542217658d8423a2995a7 (patch)
treecf27c1a8b66a33ed9c7de16dc17350a4703447d4
parentf4337d9f1d5207f831118cfbfabab5910db44ac7 (diff)
downloadenigmail-fab67aebb6789f150b5542217658d8423a2995a7.tar.gz
enigmail-fab67aebb6789f150b5542217658d8423a2995a7.tar.bz2
enigmail-fab67aebb6789f150b5542217658d8423a2995a7.zip
moved decryption funtion into a worker
-rw-r--r--package/Makefile14
-rw-r--r--package/armor.jsm35
-rw-r--r--package/cryptoAPI/Makefile11
-rw-r--r--package/cryptoAPI/openpgp-js.js16
-rw-r--r--package/cryptoAPI/pgpjs-crypto-main.jsm302
-rw-r--r--package/cryptoAPI/pgpjs-crypto-worker.js (renamed from package/cryptoAPI/pgpjs-decrypt.jsm)502
-rw-r--r--package/tests/main.js2
-rw-r--r--package/tests/pgpjs-crypto-test.js (renamed from package/tests/pgpjs-decrypt-test.js)33
-rw-r--r--package/tests/testHelper.js2
-rw-r--r--ui/content/enigmailMessengerOverlay.js1
-rwxr-xr-xutil/genxpi3
11 files changed, 732 insertions, 189 deletions
diff --git a/package/Makefile b/package/Makefile
index 2c2fb86c..7653b6c5 100644
--- a/package/Makefile
+++ b/package/Makefile
@@ -17,7 +17,6 @@ MODFILES = \
addrbook.jsm \
amPrefsService.jsm \
app.jsm \
- armor.jsm \
attachment.jsm \
autocrypt.jsm \
autoSetup.jsm \
@@ -26,7 +25,6 @@ MODFILES = \
commandLine.jsm \
configBackup.jsm \
configure.jsm \
- constants.jsm \
core.jsm \
cryptoAPI.jsm \
data.jsm \
@@ -98,6 +96,10 @@ MODFILES = \
xhrUtils.jsm \
zbase32.jsm
+COPYFILES = \
+ armor.jsm \
+ constants.jsm
+
DATE_FMT = +%Y%m%d-%H%M
SOURCE_DATE_EPOCH ?= $(shell date +%s)
@@ -112,11 +114,14 @@ GENFILES = $(addprefix $(GENDIR)/,$(MODFILES))
$(GENDIR)/%.jsm: %.jsm
$(DEPTH)/util/prepPostbox $(TARGET_TOOL) $< [email protected]
-all: dirs build deploy
+all: dirs build copyfiles deploy
build: $(GENFILES)
-deploy: $(PREFFILES)
+copyfiles: $(COPYFILES)
+ $(DEPTH)/util/install -m 644 $(DIST)/chrome/content/modules $(COPYFILES)
+
+deploy: $(PREFFILES)
$(DEPTH)/util/install -m 644 $(DIST)/chrome/content/preferences $(PREFFILES)
$(DEPTH)/util/install -m 644 $(DIST) enigmail-startup.js
echo '"use strict";' > $(DIST)/chrome/content/modules/buildDate.jsm
@@ -129,6 +134,7 @@ deploy: $(PREFFILES)
clean:
$(DEPTH)/util/install -u $(DIST)/chrome/content/preferences $(PREFFILES)
$(DEPTH)/util/install -u $(DIST)/chrome/content/modules $(MODFILES)
+ $(DEPTH)/util/install -u $(DIST)/chrome/content/modules $(COPYFILES)
$(DEPTH)/util/install -u $(DIST) bootstrap.js manifest.json install.rdf chrome.manifest
.PHONY: dirs $(DIRS)
diff --git a/package/armor.jsm b/package/armor.jsm
index d7765b3b..722d8060 100644
--- a/package/armor.jsm
+++ b/package/armor.jsm
@@ -9,8 +9,14 @@
var EXPORTED_SYMBOLS = ["EnigmailArmor"];
-const EnigmailConstants = ChromeUtils.import("chrome://enigmail/content/modules/constants.jsm").EnigmailConstants;
-const EnigmailLog = ChromeUtils.import("chrome://enigmail/content/modules/log.jsm").EnigmailLog;
+//const EnigmailConstants = ChromeUtils.import("chrome://enigmail/content/modules/constants.jsm").EnigmailConstants;
+//const EnigmailLog = ChromeUtils.import("chrome://enigmail/content/modules/log.jsm").EnigmailLog;
+
+const ArmorConstants = {
+ SIGNATURE_TEXT: 1,
+ SIGNATURE_HEADERS: 2,
+ SIGNATURE_ARMOR: 3
+};
// Locates STRing in TEXT occurring only at the beginning of a line
@@ -34,7 +40,8 @@ function searchBlankLine(str, then) {
var offset = str.search(/\n\s*\r?\n/);
if (offset === -1) {
return "";
- } else {
+ }
+ else {
return then(offset);
}
}
@@ -43,7 +50,8 @@ function indexOfNewline(str, off, then) {
var offset = str.indexOf("\n", off);
if (offset === -1) {
return "";
- } else {
+ }
+ else {
return then(offset);
}
}
@@ -64,7 +72,7 @@ var EnigmailArmor = {
* If no block is found, an empty String is returned;
*/
locateArmoredBlock: function(text, offset, indentStr, beginIndexObj, endIndexObj, indentStrObj) {
- EnigmailLog.DEBUG("armor.jsm: Enigmail.locateArmoredBlock: " + offset + ", '" + indentStr + "'\n");
+ // EnigmailLog.DEBUG("armor.jsm: Enigmail.locateArmoredBlock: " + offset + ", '" + indentStr + "'\n");
beginIndexObj.value = -1;
endIndexObj.value = -1;
@@ -113,7 +121,7 @@ var EnigmailArmor = {
var blockType = "";
if (matches && (matches.length > 1)) {
blockType = matches[1];
- EnigmailLog.DEBUG("armor.jsm: Enigmail.locateArmoredBlock: blockType=" + blockType + "\n");
+ // EnigmailLog.DEBUG("armor.jsm: Enigmail.locateArmoredBlock: blockType=" + blockType + "\n");
}
if (blockType == "UNVERIFIED MESSAGE") {
@@ -159,12 +167,12 @@ var EnigmailArmor = {
i = endObj.value;
}
- EnigmailLog.DEBUG("armor.jsm: locateArmorBlocks: Found " + blocks.length + " Blocks\n");
+ // EnigmailLog.DEBUG("armor.jsm: locateArmorBlocks: Found " + blocks.length + " Blocks\n");
return blocks;
},
extractSignaturePart: function(signatureBlock, part) {
- EnigmailLog.DEBUG("armor.jsm: Enigmail.extractSignaturePart: part=" + part + "\n");
+ // EnigmailLog.DEBUG("armor.jsm: Enigmail.extractSignaturePart: part=" + part + "\n");
return searchBlankLine(signatureBlock, function(offset) {
return indexOfNewline(signatureBlock, offset + 1, function(offset) {
@@ -173,7 +181,7 @@ var EnigmailArmor = {
return "";
}
- if (part === EnigmailConstants.SIGNATURE_TEXT) {
+ if (part === ArmorConstants.SIGNATURE_TEXT) {
return signatureBlock.substr(offset + 1, beginIndex - offset - 1).
replace(/^- -/, "-").
replace(/\n- -/g, "\n-").
@@ -189,15 +197,16 @@ var EnigmailArmor = {
var signBlock = signatureBlock.substr(offset, endIndex - offset);
return searchBlankLine(signBlock, function(armorIndex) {
- if (part == EnigmailConstants.SIGNATURE_HEADERS) {
+ if (part == ArmorConstants.SIGNATURE_HEADERS) {
return signBlock.substr(1, armorIndex);
}
return indexOfNewline(signBlock, armorIndex + 1, function(armorIndex) {
- if (part == EnigmailConstants.SIGNATURE_ARMOR) {
+ if (part == ArmorConstants.SIGNATURE_ARMOR) {
return signBlock.substr(armorIndex, endIndex - armorIndex).
replace(/\s*/g, "");
- } else {
+ }
+ else {
return "";
}
});
@@ -291,4 +300,4 @@ var EnigmailArmor = {
return retArr;
}
-}; \ No newline at end of file
+};
diff --git a/package/cryptoAPI/Makefile b/package/cryptoAPI/Makefile
index 31c73032..f741b4ab 100644
--- a/package/cryptoAPI/Makefile
+++ b/package/cryptoAPI/Makefile
@@ -13,13 +13,16 @@ MODFILES = \
gnupg-keyEditor.jsm \
gpgme.js \
openpgp-js.js \
+ pgpjs-crypto-main.jsm \
pgpjs-encrypt.jsm \
- pgpjs-decrypt.jsm \
pgpjs-keys.jsm \
pgpjs-keystore.jsm \
pgpjs-keymanipulation.jsm \
interface.js
+WORKERS = \
+ pgpjs-crypto-worker.js
+
GENFILES = $(addprefix $(GENDIR)/,$(MODFILES))
$(GENDIR)/%.jsm: %.jsm
@@ -28,9 +31,13 @@ $(GENDIR)/%.jsm: %.jsm
$(GENDIR)/%.js: %.js
$(DEPTH)/util/prepPostbox $(TARGET_TOOL) $< [email protected]
-build: $(GENFILES)
+build: $(GENFILES) deploy
+
+deploy:
+ $(DEPTH)/util/install -m 644 $(GENDIR) $(WORKERS)
all: build
clean:
$(DEPTH)/util/install -u $(DIST)/chrome/content/modules/cryptoAPI $(MODFILES)
+ $(DEPTH)/util/install -u $(DIST)/chrome/content/modules/cryptoAPI $(WORKERS)
diff --git a/package/cryptoAPI/openpgp-js.js b/package/cryptoAPI/openpgp-js.js
index 0a64e8ee..a4518d1c 100644
--- a/package/cryptoAPI/openpgp-js.js
+++ b/package/cryptoAPI/openpgp-js.js
@@ -14,7 +14,7 @@ var Services = ChromeUtils.import("resource://gre/modules/Services.jsm").Service
const pgpjs_keys = ChromeUtils.import("chrome://enigmail/content/modules/cryptoAPI/pgpjs-keys.jsm").pgpjs_keys;
const pgpjs_keyStore = ChromeUtils.import("chrome://enigmail/content/modules/cryptoAPI/pgpjs-keystore.jsm").pgpjs_keyStore;
const pgpjs_encrypt = ChromeUtils.import("chrome://enigmail/content/modules/cryptoAPI/pgpjs-encrypt.jsm").pgpjs_encrypt;
-const pgpjs_decrypt = ChromeUtils.import("chrome://enigmail/content/modules/cryptoAPI/pgpjs-decrypt.jsm").pgpjs_decrypt;
+const pgpjs_crypto = ChromeUtils.import("chrome://enigmail/content/modules/cryptoAPI/pgpjs-crypto-main.jsm").pgpjs_crypto;
const pgpjs_keymanipulation = ChromeUtils.import("chrome://enigmail/content/modules/cryptoAPI/pgpjs-keymanipulation.jsm").pgpjs_keymanipulation;
const EnigmailLazy = ChromeUtils.import("chrome://enigmail/content/modules/lazy.jsm").EnigmailLazy;
const EnigmailLog = ChromeUtils.import("chrome://enigmail/content/modules/log.jsm").EnigmailLog;
@@ -382,7 +382,7 @@ class OpenPGPjsCryptoAPI extends CryptoAPI {
async getFileName(byteData) {
let fn = null;
try {
- let msg = await pgpjs_decrypt.processPgpMessage(byteData, {});
+ let msg = await pgpjs_crypto.processPgpMessage(byteData, {});
fn = msg.encryptedFileName;
}
catch (x) {}
@@ -404,7 +404,7 @@ class OpenPGPjsCryptoAPI extends CryptoAPI {
*/
async verifyAttachment(filePath, sigPath) {
- return pgpjs_decrypt.verifyFile(filePath, sigPath);
+ return pgpjs_crypto.verifyFile(filePath, sigPath);
}
/**
@@ -420,7 +420,7 @@ class OpenPGPjsCryptoAPI extends CryptoAPI {
*/
async decryptAttachment(encrypted) {
- let ret = await pgpjs_decrypt.processPgpMessage(encrypted, {});
+ let ret = await pgpjs_crypto.processPgpMessage(encrypted, {});
if ("decryptedData" in ret) {
ret.stdoutData = ret.decryptedData;
@@ -446,10 +446,10 @@ class OpenPGPjsCryptoAPI extends CryptoAPI {
EnigmailLog.DEBUG(`openpgpg-js.js: decrypt()\n`);
if (options.verifyOnly) {
- return pgpjs_decrypt.verify(pgpMessage, options);
+ return pgpjs_crypto.verify(pgpMessage, options);
}
else {
- return pgpjs_decrypt.processPgpMessage(pgpMessage, options);
+ return pgpjs_crypto.processPgpMessage(pgpMessage, options);
}
}
@@ -471,7 +471,7 @@ class OpenPGPjsCryptoAPI extends CryptoAPI {
options.verifyOnly = false;
options.uiFlags = EnigmailConstants.UI_PGP_MIME;
- return pgpjs_decrypt.processPgpMessage(encrypted, options);
+ return pgpjs_crypto.processPgpMessage(encrypted, options);
}
/**
@@ -489,7 +489,7 @@ class OpenPGPjsCryptoAPI extends CryptoAPI {
*/
async verifyMime(signedData, signature, options) {
- return pgpjs_decrypt.verifyDetached(signedData, signature);
+ return pgpjs_crypto.verifyDetached(signedData, signature);
}
diff --git a/package/cryptoAPI/pgpjs-crypto-main.jsm b/package/cryptoAPI/pgpjs-crypto-main.jsm
new file mode 100644
index 00000000..2ade0037
--- /dev/null
+++ b/package/cryptoAPI/pgpjs-crypto-main.jsm
@@ -0,0 +1,302 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+const Services = ChromeUtils.import("resource://gre/modules/Services.jsm").Services;
+const EnigmailLog = ChromeUtils.import("chrome://enigmail/content/modules/log.jsm").EnigmailLog;
+const EnigmailPrefs = ChromeUtils.import("chrome://enigmail/content/modules/prefs.jsm").EnigmailPrefs;
+const EnigmailFiles = ChromeUtils.import("chrome://enigmail/content/modules/files.jsm").EnigmailFiles;
+const EnigmailArmor = ChromeUtils.import("chrome://enigmail/content/modules/armor.jsm").EnigmailArmor;
+const EnigmailLocale = ChromeUtils.import("chrome://enigmail/content/modules/locale.jsm").EnigmailLocale;
+const EnigmailTime = ChromeUtils.import("chrome://enigmail/content/modules/time.jsm").EnigmailTime;
+const EnigmailConstants = ChromeUtils.import("chrome://enigmail/content/modules/constants.jsm").EnigmailConstants;
+const pgpjs_keys = ChromeUtils.import("chrome://enigmail/content/modules/cryptoAPI/pgpjs-keys.jsm").pgpjs_keys;
+const pgpjs_keyStore = ChromeUtils.import("chrome://enigmail/content/modules/cryptoAPI/pgpjs-keystore.jsm").pgpjs_keyStore;
+const getOpenPGPLibrary = ChromeUtils.import("chrome://enigmail/content/modules/stdlib/openpgp-loader.jsm").getOpenPGPLibrary;
+
+var EXPORTED_SYMBOLS = ["pgpjs_crypto"];
+
+var pgpjs_crypto = {
+ /**
+ * Process an OpenPGP message
+ *
+ * @param {String} encrypted The encrypted data
+ * @param {Object} options Decryption options
+ *
+ * @return {Promise<Object>} - Return object with decryptedData and status information:
+ * - {String} decryptedData
+ * - {Number} exitCode
+ * - {Number} statusFlags
+ * - {String} errorMsg
+ * - {String} blockSeparation
+ *
+ * Use Promise.catch to handle failed decryption.
+ * retObj.errorMsg will be an error message in this case.
+ */
+
+ processPgpMessage: async function(encrypted, options) {
+ EnigmailLog.DEBUG(`pgpjs-crypro-main.jsm: processPgpMessage(${encrypted.length})\n`);
+
+ let result;
+ try {
+ result = await PgpJsWorkerParent.sendMessage("processPgpMessage", {
+ encrypted,
+ options
+ });
+ }
+ catch (ex) {
+ EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: processPgpMessage: ERROR: ${ex.toString()}\n`);
+ result.errorMsg = ex.toString();
+ result.exitCode = 1;
+ }
+
+ return result;
+ },
+
+ verify: async function(data, options) {
+ EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: verify(${data.length})\n`);
+
+ let result = {};
+
+ let blocks = EnigmailArmor.locateArmoredBlocks(data);
+
+ result.statusFlags = 0;
+ result.exitCode = 1;
+
+ try {
+ if (blocks && blocks.length > 0) {
+ if (blocks[0].blocktype === "SIGNED MESSAGE") {
+ result = await PgpJsWorkerParent.sendMessage("verify", {
+ data: data.substring(blocks[0].begin, blocks[0].end),
+ options
+ });
+ }
+ }
+ }
+ catch (ex) {
+ EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: verify: ERROR: ${ex.toString()}\n`);
+ result.errorMsg = ex.toString();
+ result.statusFlags = EnigmailConstants.UNVERIFIED_SIGNATURE;
+ }
+ return result;
+ },
+
+ verifyDetached: async function(data, signature, returnData = false) {
+ EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: verifyDetached(${data.length})\n`);
+
+ let result = await PgpJsWorkerParent.sendMessage("verifyDetached", {
+ data,
+ signature,
+ returnData
+ });
+ return result;
+ },
+
+
+ verifyFile: async function(dataFilePath, signatureFilePath) {
+ const PgpJS = getOpenPGPLibrary();
+
+ let dataFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
+ let sigFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
+ EnigmailFiles.initPath(dataFile, dataFilePath);
+ EnigmailFiles.initPath(sigFile, signatureFilePath);
+
+ if (!dataFile.exists()) {
+ throw new Error(`Data file ${dataFilePath} does not exist`);
+ }
+ if (!sigFile.exists()) {
+ throw new Error(`Signature file ${signatureFilePath} does not exist`);
+ }
+
+ let data = EnigmailFiles.readBinaryFile(dataFile);
+ let sig = EnigmailFiles.readBinaryFile(sigFile);
+
+ if (sig.search(/^-----BEGIN PGP/m) < 0) {
+ let msg = await PgpJS.signature.read(ensureUint8Array(sig));
+ sig = msg.armor();
+ }
+
+ let ret = await this.verifyDetached(data, sig, false);
+
+ if (ret.statusFlags & (EnigmailConstants.BAD_SIGNATURE | EnigmailConstants.UNVERIFIED_SIGNATURE)) {
+ throw ret.errorMsg ? ret.errorMsg : EnigmailLocale.getString("unverifiedSig") + " - " + EnigmailLocale.getString("msgSignedUnkownKey");
+ }
+
+ const detailArr = ret.sigDetails.split(/ /);
+ const dateTime = EnigmailTime.getDateTime(detailArr[2], true, true);
+ return ret.errorMsg + "\n" + EnigmailLocale.getString("keyAndSigDate", [ret.keyId, dateTime]);
+ }
+};
+
+function ensureUint8Array(stringOrUint8Array) {
+ if (typeof stringOrUint8Array === "string") {
+
+ const result = new Uint8Array(stringOrUint8Array.length);
+ for (let i = 0; i < stringOrUint8Array.length; i++) {
+ result[i] = stringOrUint8Array.charCodeAt(i);
+ }
+ return result;
+
+ }
+
+ return stringOrUint8Array;
+}
+
+
+/**
+ * Callback functions called from worker for tasks requiring chrome
+ */
+
+var WorkerRequestHandler = {
+ /**
+ * Get secret keys as armored string
+ *
+ * @param {Array<String>} keyIds
+ * @returns {String}
+ */
+ getSecretKeysForIds: async function(keyIds) {
+ EnigmailLog.DEBUG(`pgpjs-crypto-main.jsm: getSecretKeysForIds()\n`);
+ let secretKeys = await pgpjs_keyStore.readSecretKeys(keyIds, false);
+
+ return secretKeys;
+ },
+
+ getPublicKeysForIds: async function(keyIds) {
+ EnigmailLog.DEBUG(`pgpjs-crypto-main.jsm: getPublicKeysForIds()\n`);
+ let publicKeys = await pgpjs_keyStore.readPublicKeys(keyIds);
+
+ return publicKeys;
+ },
+
+ getDecryptedSecretKey: async function(options) {
+ EnigmailLog.DEBUG(`pgpjs-crypto-main.jsm: getDecryptedSecretKey()\n`);
+ const PgpJS = getOpenPGPLibrary();
+
+ let secretKey = await pgpjs_keyStore.getKeysForKeyIds(true, [options.secretKeyFpr], false);
+ let dedryptedSecKey = await pgpjs_keys.decryptSecretKey(secretKey[0], options.decryptionReason);
+ let packets = new PgpJS.PacketList();
+
+ // remove all 3rd-party signatures that just grow the key
+ for (let u in dedryptedSecKey.users) {
+ dedryptedSecKey.users[u].otherCertifications = [];
+ }
+
+ if (dedryptedSecKey) {
+ packets = packets.concat(await dedryptedSecKey.toPacketList());
+ return PgpJS.armor(PgpJS.enums.armor.privateKey, packets.write());
+ }
+
+ return null;
+ },
+
+ downloadMissingKeys: async function(keyIds) {
+ EnigmailLog.DEBUG(`pgpjs-crypto-main.jsm: downloadMissingKeys()\n`);
+
+ const EnigmailKeyServer = ChromeUtils.import("chrome://enigmail/content/modules/keyserver.jsm").EnigmailKeyServer;
+ const PgpJS = getOpenPGPLibrary();
+ let packets = new PgpJS.PacketList();
+
+ try {
+ const keyserver = EnigmailPrefs.getAutoKeyRetrieveServer();
+
+ if (keyserver && keyserver.length > 0) {
+ const keyList = "0x" + keyIds.join(" 0x");
+ const ret = await EnigmailKeyServer.download(keyList, keyserver);
+
+ if (ret.result === 0 && ret.keyList.length > 0) {
+ let foundKeys = await pgpjs_keyStore.getKeysForKeyIds(false, keyIds);
+ packets = packets.concat(await foundKeys.toPacketList());
+ }
+ }
+ }
+ catch (x) {}
+
+ return PgpJS.armor(PgpJS.enums.armor.publicKey, packets.write());
+ }
+
+};
+
+var pendingPromises = [];
+var gTransactionId = 0;
+
+const cryptoWorker = new Worker('chrome://enigmail/content/modules/cryptoAPI/pgpjs-crypto-worker.js');
+
+cryptoWorker.onmessage = async function(e) {
+ if ("logMessage" in e.data) {
+ if (e.data.logLevel >= 5) {
+ EnigmailLog.DEBUG(`${e.data.logMessage}\n`);
+ }
+ else if (e.data.logLevel === 0) {
+ EnigmailLog.ERROR(`${e.data.logMessage}\n`);
+ }
+ return;
+ }
+
+ if (!("trxId" in e.data)) {
+ EnigmailLog.ERROR(`pgpjs-crypto-worker.jsm. onmessage: cannot deliver message received from worker ${e.data}\n`);
+ }
+
+ if ("func" in e.data) {
+ let method = e.data.func;
+ let args = e.data.param || null;
+
+ if (method in WorkerRequestHandler) {
+ try {
+ let workerResult = await WorkerRequestHandler[method](args);
+ cryptoWorker.postMessage({
+ trxId: e.data.trxId,
+ result: workerResult
+ });
+ }
+ catch (ex) {
+ cryptoWorker.postMessage({
+ trxId: e.data.trxId,
+ error: `${ex.toString()}\n${ex.stack}`
+ });
+ }
+ }
+ else {
+ EnigmailLog.ERROR(`pgpjs-crypto-worker.jsm. onmessage: Unknown function call ${e.data.func} received from worker\n`);
+ }
+ return;
+ }
+
+ if (pendingPromises[e.data.trxId]) {
+ if ("result" in e.data) {
+ pendingPromises[e.data.trxId].resolve(e.data.result);
+ }
+ else {
+ EnigmailLog.ERROR(`${e.data.error}\n`);
+ pendingPromises[e.data.trxId].reject(e.data.error);
+ }
+ delete pendingPromises[e.data.trxId];
+ }
+};
+
+cryptoWorker.onerror = function(e) {
+ EnigmailLog.ERROR(`pgpjs-crypto-worker.jsm. onerror: Error received from worker: ${e.message}\n`);
+};
+
+
+const PgpJsWorkerParent = {
+
+ sendMessage(functionName, param, transferables) {
+ let trxId = ++gTransactionId;
+ return new Promise((resolve, reject) => {
+ cryptoWorker.postMessage({
+ func: functionName,
+ trxId: trxId,
+ param: param
+ }, transferables);
+
+ pendingPromises[trxId] = {
+ resolve,
+ reject
+ };
+ });
+ }
+};
diff --git a/package/cryptoAPI/pgpjs-decrypt.jsm b/package/cryptoAPI/pgpjs-crypto-worker.js
index 4aad37a2..b11ffbc7 100644
--- a/package/cryptoAPI/pgpjs-decrypt.jsm
+++ b/package/cryptoAPI/pgpjs-crypto-worker.js
@@ -7,26 +7,17 @@
"use strict";
-var EXPORTED_SYMBOLS = ["pgpjs_decrypt"];
-
-
-var Services = ChromeUtils.import("resource://gre/modules/Services.jsm").Services;
-const EnigmailLog = ChromeUtils.import("chrome://enigmail/content/modules/log.jsm").EnigmailLog;
-const EnigmailLazy = ChromeUtils.import("chrome://enigmail/content/modules/lazy.jsm").EnigmailLazy;
-const getOpenPGPLibrary = ChromeUtils.import("chrome://enigmail/content/modules/stdlib/openpgp-loader.jsm").getOpenPGPLibrary;
-const EnigmailTime = ChromeUtils.import("chrome://enigmail/content/modules/time.jsm").EnigmailTime;
-const EnigmailFuncs = ChromeUtils.import("chrome://enigmail/content/modules/funcs.jsm").EnigmailFuncs;
-const EnigmailData = ChromeUtils.import("chrome://enigmail/content/modules/data.jsm").EnigmailData;
-const EnigmailFiles = ChromeUtils.import("chrome://enigmail/content/modules/files.jsm").EnigmailFiles;
-const EnigmailConstants = ChromeUtils.import("chrome://enigmail/content/modules/constants.jsm").EnigmailConstants;
-const getOpenPGP = EnigmailLazy.loader("enigmail/openpgp.jsm", "EnigmailOpenPGP");
-const getArmor = EnigmailLazy.loader("enigmail/armor.jsm", "EnigmailArmor");
-const pgpjs_keys = ChromeUtils.import("chrome://enigmail/content/modules/cryptoAPI/pgpjs-keys.jsm").pgpjs_keys;
-const pgpjs_keyStore = ChromeUtils.import("chrome://enigmail/content/modules/cryptoAPI/pgpjs-keystore.jsm").pgpjs_keyStore;
-const EnigmailLocale = ChromeUtils.import("chrome://enigmail/content/modules/locale.jsm").EnigmailLocale;
-const EnigmailPrefs = ChromeUtils.import("chrome://enigmail/content/modules/prefs.jsm").EnigmailPrefs;
-
-Components.utils.importGlobalProperties(["TextDecoder"]);
+/**
+ * Load OpenPGP.js libray
+ */
+
+/* global importScripts: false, EnigmailConstants: false, EnigmailArmor: false */
+
+importScripts('chrome://enigmail/content/modules/stdlib/openpgp-lib.js');
+importScripts('chrome://enigmail/content/modules/armor.jsm');
+importScripts('chrome://enigmail/content/modules/constants.jsm');
+
+const PgpJS = self.openpgp;
/**
* OpenPGP.js implementation of CryptoAPI
@@ -34,7 +25,7 @@ Components.utils.importGlobalProperties(["TextDecoder"]);
* Decryption-related functions
*/
-var pgpjs_decrypt = {
+var workerBody = {
/**
* Process an OpenPGP message
*
@@ -52,10 +43,12 @@ var pgpjs_decrypt = {
* retObj.errorMsg will be an error message in this case.
*/
- processPgpMessage: async function(encrypted, options) {
- EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: processPgpMessage(${encrypted.length})\n`);
+ processPgpMessage: async function({
+ encrypted,
+ options
+ }) {
+ DEBUG_LOG(`processPgpMessage(${encrypted.length})\n`);
- const PgpJS = getOpenPGPLibrary();
const retData = getReturnObj();
try {
@@ -90,7 +83,7 @@ var pgpjs_decrypt = {
idx = message.packets.indexOfTag(PgpJS.enums.packet.literalData);
if (idx.length > 0 && idx[0] === 0) {
let litDataArr = message.getLiteralData();
- retData.decryptedData += EnigmailData.arrayBufferToString(litDataArr);
+ retData.decryptedData += arrayBufferToString(litDataArr);
retData.statusFlags = 0;
return retData;
}
@@ -98,7 +91,7 @@ var pgpjs_decrypt = {
return this.decryptMessage(message, pubKeyIds, options);
}
catch (ex) {
- EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: processPgpMessage: ERROR: ${ex.toString()}\n`);
+ DEBUG_LOG(`processPgpMessage: ERROR: ${ex.toString()}\n${ex.stack}\n${encrypted}\n`);
retData.errorMsg = ex.toString();
retData.exitCode = 1;
}
@@ -106,10 +99,10 @@ var pgpjs_decrypt = {
return retData;
},
+
decryptMessage: async function(message, pubKeyIds, options) {
- EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: decryptMessage(${pubKeyIds.join(", ")})\n`);
+ DEBUG_LOG(`decryptMessage(${pubKeyIds.join(", ")})\n`);
- const PgpJS = getOpenPGPLibrary();
const retData = getReturnObj();
let encToDetails = "";
@@ -117,17 +110,29 @@ var pgpjs_decrypt = {
encToDetails = getKeydesc(pubKeyIds);
// get OpenPGP.js key objects for secret keys
- let secretKeys = await pgpjs_keyStore.getKeysForKeyIds(true, pubKeyIds.length === 0 ? null : pubKeyIds);
+ let armoredSecretKeys = await requestMessage("getSecretKeysForIds", pubKeyIds);
+
+ let secretKeys = await PgpJS.readKeys({
+ armoredKeys: armoredSecretKeys
+ });
if (secretKeys.length === 0) {
retData.statusFlags |= EnigmailConstants.NO_SECKEY;
}
// try to decrypt the message using the secret keys one-by-one
- for (let secKey of secretKeys) {
- secKey.revocationSignatures = []; // remove revocation sigs to allow decryption
- secKey = await pgpjs_keys.decryptSecretKey(secKey, EnigmailConstants.KEY_DECRYPT_REASON_ENCRYPTED_MSG);
+ for (let sk of secretKeys) {
+ let decryptedSecKey = await requestMessage("getDecryptedSecretKey", {
+ secretKeyFpr: sk.getFingerprint().toUpperCase(),
+ decryptionReason: EnigmailConstants.KEY_DECRYPT_REASON_ENCRYPTED_MSG
+ });
+
+ let secKey = await PgpJS.readKeys({
+ armoredKeys: decryptedSecKey
+ });
+
if (secKey) {
+ secKey.revocationSignatures = []; // remove revocation sigs to allow decryption
let result = await PgpJS.decrypt({
message: message,
format: "binary",
@@ -153,7 +158,10 @@ var pgpjs_decrypt = {
pkt = pkt.concat(sigPackets.packets);
}
- verifiation = await this.verifyDetached(result.data, pkt);
+ verifiation = await this.verifyDetached({
+ data: result.data,
+ signature: pkt
+ });
if (verifiation.exitCode !== 2) {
retData.statusFlags += verifiation.statusFlags;
@@ -172,7 +180,7 @@ var pgpjs_decrypt = {
break;
}
else {
- EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: decrypt invalid or no passphrase supplied\n`);
+ DEBUG_LOG(`decrypt invalid or no passphrase supplied\n`);
retData.statusFlags |= EnigmailConstants.BAD_PASSPHRASE;
}
}
@@ -180,10 +188,10 @@ var pgpjs_decrypt = {
catch (ex) {
if (("message" in ex) && ex.message.search(/(Message .*not authenticated|missing MDC|Modification detected)/) > 0) {
retData.statusFlags |= EnigmailConstants.MISSING_MDC;
- retData.statusMsg = EnigmailLocale.getString("missingMdcError") + "\n";
+ retData.statusMsg = "MDC ERROR\n"; // FIXME: EnigmailLocale.getString("missingMdcError") + "\n";
}
else {
- EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: decryptMessage: ERROR: ${ex.toString()}\n`);
+ DEBUG_LOG(`decryptMessage: ERROR: ${ex.toString()}\n`);
retData.exitCode = 1;
retData.errorMsg = ex.toString();
}
@@ -193,37 +201,38 @@ var pgpjs_decrypt = {
return retData;
},
- verify: async function(data, options) {
- EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: verify(${data.length})\n`);
+ verify: async function({
+ data,
+ options
+ }) {
+ DEBUG_LOG(`verify(${data.length})\n`);
- const PgpJS = getOpenPGPLibrary();
let result = getReturnObj();
- const Armor = getArmor();
- let blocks = Armor.locateArmoredBlocks(data);
result.statusFlags = 0;
result.exitCode = 1;
try {
- if (blocks && blocks.length > 0) {
- if (blocks[0].blocktype === "SIGNED MESSAGE") {
- let msg = await PgpJS.readCleartextMessage({
- cleartextMessage: data.substring(blocks[0].begin, blocks[0].end)
- });
+ let msg = await PgpJS.readCleartextMessage({
+ cleartextMessage: data
+ });
- let binaryData = extractDataFromClearsignedMsg(data.substring(blocks[0].begin, blocks[0].end));
+ let binaryData = extractDataFromClearsignedMsg(data);
- if (msg && "signature" in msg) {
- result = await this.verifyDetached(binaryData, msg.signature.armor(), true);
- }
- }
+ if (msg && "signature" in msg) {
+ result = await this.verifyDetached({
+ data: binaryData,
+ signature: msg.signature.armor(),
+ returnData: true
+ });
}
}
catch (ex) {
- EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: verify: ERROR: ${ex.toString()}\n`);
+ DEBUG_LOG(`verify: ERROR: ${ex.toString()}\n`);
result.errorMsg = ex.toString();
result.statusFlags = EnigmailConstants.UNVERIFIED_SIGNATURE;
}
+
return result;
},
@@ -236,18 +245,21 @@ var pgpjs_decrypt = {
*
* @return {Promise<Object>}: ResultObj
*/
- verifyDetached: async function(data, signature, returnData = false) {
- EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: verifyDetached(${data.length})\n`);
- const PgpJS = getOpenPGPLibrary();
+ verifyDetached: async function({
+ data,
+ signature,
+ returnData = false
+ }) {
+ DEBUG_LOG(`verifyDetached(${data}, ${signature})\n`);
- //let result = getReturnObj();
let sigString;
if (typeof(signature) === "string") {
sigString = signature;
}
- else
- sigString = PgpJS.armor(PgpJS.enums.armor.signature, signature.write());
+ else {
+ sigString = await PgpJS.armor(PgpJS.enums.armor.signature, signature.write());
+ }
// if (sigString.packets.length === 0) {
// result.exitCode = 1;
@@ -282,8 +294,7 @@ var pgpjs_decrypt = {
* @return {Promise<Object>} ResultObj
*/
verifyMessage: async function(messageObj, returnData = false) {
- EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: verifyMessage()\n`);
- const PgpJS = getOpenPGPLibrary();
+ DEBUG_LOG(`verifyMessage()\n`);
const SIG_STATUS = {
unknown_key: 0,
bad_signature: 1,
@@ -310,12 +321,16 @@ var pgpjs_decrypt = {
return keyId.toHex().toUpperCase();
});
- let pubKeys = await pgpjs_keyStore.getKeysForKeyIds(false, keyIds, true);
+ let armoredPubKeys = await requestMessage("getPublicKeysForIds", keyIds);
- if (pubKeys.length === 0) {
- pubKeys = await downloadMissingKeys(keyIds);
+ if (armoredPubKeys.length === 0) {
+ armoredPubKeys = await requestMessage("downloadMissingKeys", keyIds);
}
+ let pubKeys = await PgpJS.readKeys({
+ armoredKeys: armoredPubKeys
+ });
+
for (let key of pubKeys) {
if (await key.isRevoked()) {
// remove revocation signatures to get a valid key (required for verification)
@@ -357,7 +372,7 @@ var pgpjs_decrypt = {
currentKey = k;
break;
}
- else {
+ else if ("subKeys" in k) {
for (let sk of k.subKeys) {
if (sk.getKeyID().toHex() === keyId) {
currentKey = k;
@@ -381,7 +396,7 @@ var pgpjs_decrypt = {
currentStatus = SIG_STATUS.bad_signature;
}
else {
- let keyStatus = await pgpjs_keyStore.getKeyStatusCode(currentKey);
+ let keyStatus = await getKeyStatusCode(currentKey);
if (currentKey._enigmailRevoked) keyStatus = "r";
@@ -453,50 +468,17 @@ var pgpjs_decrypt = {
}
if (result.statusFlags & EnigmailConstants.GOOD_SIGNATURE) {
- result.errorMsg = EnigmailLocale.getString("prefGood", [result.userId]);
+ result.errorMsg = `Good signature from ${result.userId}`; // FIXME: EnigmailLocale.getString("prefGood", [result.userId]);
}
else if (result.statusFlags & EnigmailConstants.BAD_SIGNATURE) {
- result.errorMsg = EnigmailLocale.getString("prefBad", [result.userId]);
+ result.errorMsg = `Invalid signature from ${result.userId}`; // FIXME: EnigmailLocale.getString("prefBad", [result.userId]);
}
}
catch (ex) {
- EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: verifyMessage: ERROR: ${ex.toString()} ${ex.stack}\n`);
+ DEBUG_LOG(`verifyMessage: ERROR: ${ex.toString()} ${ex.stack}\n`);
}
return result;
- },
-
- verifyFile: async function(dataFilePath, signatureFilePath) {
- const PgpJS = getOpenPGPLibrary();
- let dataFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
- let sigFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
- EnigmailFiles.initPath(dataFile, dataFilePath);
- EnigmailFiles.initPath(sigFile, signatureFilePath);
-
- if (!dataFile.exists()) {
- throw new Error(`Data file ${dataFilePath} does not exist`);
- }
- if (!sigFile.exists()) {
- throw new Error(`Signature file ${signatureFilePath} does not exist`);
- }
-
- let data = EnigmailFiles.readBinaryFile(dataFile);
- let sig = EnigmailFiles.readBinaryFile(sigFile);
-
- if (sig.search(/^-----BEGIN PGP/m) < 0) {
- let msg = await PgpJS.signature.read(ensureUint8Array(sig));
- sig = msg.armor();
- }
-
- let ret = await this.verifyDetached(data, sig, false);
-
- if (ret.statusFlags & (EnigmailConstants.BAD_SIGNATURE | EnigmailConstants.UNVERIFIED_SIGNATURE)) {
- throw ret.errorMsg ? ret.errorMsg : EnigmailLocale.getString("unverifiedSig") + " - " + EnigmailLocale.getString("msgSignedUnkownKey");
- }
-
- const detailArr = ret.sigDetails.split(/ /);
- const dateTime = EnigmailTime.getDateTime(detailArr[2], true, true);
- return ret.errorMsg + "\n" + EnigmailLocale.getString("keyAndSigDate", [ret.keyId, dateTime]);
}
};
@@ -512,7 +494,7 @@ function ensureString(stringOrUint8Array) {
return stringOrUint8Array;
}
- return EnigmailData.arrayBufferToString(stringOrUint8Array);
+ return arrayBufferToString(stringOrUint8Array);
}
function ensureUint8Array(stringOrUint8Array) {
@@ -529,6 +511,12 @@ function ensureUint8Array(stringOrUint8Array) {
return stringOrUint8Array;
}
+/**
+ * Read from a stream and return a string
+ *
+ * @param reader Stream to read from
+ * @returns {Promise<String>}
+ */
function readFromStream(reader) {
let result = "";
@@ -555,29 +543,29 @@ function readFromStream(reader) {
}
function getKeydesc(pubKeyIds) {
- EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: getKeydesc()\n`);
- const EnigmailKeyRing = ChromeUtils.import("chrome://enigmail/content/modules/keyRing.jsm").EnigmailKeyRing;
-
- if (pubKeyIds.length > 0) {
- let encToArray = [];
- // for each key also show an associated user ID if known:
- for (let keyId of pubKeyIds) {
- // except for ID 00000000, which signals hidden keys
- if (keyId.search(/^0+$/) < 0) {
- let localKey = EnigmailKeyRing.getKeyById("0x" + keyId);
- if (localKey) {
- encToArray.push(`0x${keyId} (${localKey.userId})`);
- }
- else {
- encToArray.push(`0x${keyId}`);
- }
- }
- else {
- encToArray.push(EnigmailLocale.getString("hiddenKey"));
- }
- }
- return "\n " + encToArray.join(",\n ") + "\n";
- }
+ DEBUG_LOG(`getKeydesc()\n`);
+ // const EnigmailKeyRing = ChromeUtils.import("chrome://enigmail/content/modules/keyRing.jsm").EnigmailKeyRing;
+
+ // if (pubKeyIds.length > 0) {
+ // let encToArray = [];
+ // // for each key also show an associated user ID if known:
+ // for (let keyId of pubKeyIds) {
+ // // except for ID 00000000, which signals hidden keys
+ // if (keyId.search(/^0+$/) < 0) {
+ // let localKey = EnigmailKeyRing.getKeyById("0x" + keyId);
+ // if (localKey) {
+ // encToArray.push(`0x${keyId} (${localKey.userId})`);
+ // }
+ // else {
+ // encToArray.push(`0x${keyId}`);
+ // }
+ // }
+ // else {
+ // encToArray.push(EnigmailLocale.getString("hiddenKey"));
+ // }
+ // }
+ // return "\n " + encToArray.join(",\n ") + "\n";
+ // }
return "";
}
@@ -596,6 +584,68 @@ function getReturnObj() {
};
}
+async function getKeyStatusCode(key) {
+ let now = new Date();
+
+ try {
+ if (await key.isRevoked(null, null, now)) {
+ return "r";
+ }
+ else if (!key.users.some(user => user.userID && user.selfCertifications.length)) {
+ return "i";
+ }
+ else {
+ const {
+ user,
+ selfCertification
+ } = await key.getPrimaryUser(now, {}) || {};
+
+ if (!user) return "i";
+
+ // check for expiration time
+ if (isDataExpired(key.keyPacket, selfCertification, now)) {
+ return "e";
+ }
+ }
+ }
+ catch (x) {
+ return "i";
+ }
+
+ return "f";
+}
+
+function isDataExpired(keyPacket, signature, date = new Date()) {
+ const normDate = normalizeDate(date);
+
+ if (normDate !== null) {
+ const expirationTime = getExpirationTime(keyPacket, signature);
+
+ return !(keyPacket.created <= normDate && normDate < expirationTime) ||
+ (signature && signature.isExpired(date));
+ }
+
+ return false;
+}
+
+function normalizeDate(time = Date.now()) {
+ return time === null ? time : new Date(Math.floor(Number(time) / 1000) * 1000);
+}
+
+function getExpirationTime(keyPacket, signature) {
+ let expirationTime;
+ try {
+ // check V4 expiration time
+ if (signature.keyNeverExpires === false) {
+ expirationTime = keyPacket.created.getTime() + signature.keyExpirationTime * 1000;
+ }
+
+ return expirationTime ? new Date(expirationTime) : Infinity;
+ }
+ catch (ex) {
+ return Infinity;
+ }
+}
function extractDataFromClearsignedMsg(dataStr) {
dataStr = dataStr.replace(/\r?\n/g, "\r\n"); // ensure CRLF
@@ -609,29 +659,199 @@ function extractDataFromClearsignedMsg(dataStr) {
}
/**
- * If configuration is enabled, try to automatically download missing keys
- *
- * @param {Array<String>} keyIds: Key IDs to download
+ * Convert an ArrayBuffer (or Uint8Array) object into a string
*/
+function arrayBufferToString(buffer) {
+ const MAXLEN = 102400;
-async function downloadMissingKeys(keyIds) {
- EnigmailLog.DEBUG(`pgpjs-decrypt.jsm: downloadMissingKeys()\n`);
+ let uArr = new Uint8Array(buffer);
+ let ret = "";
+ let len = buffer.byteLength;
- const EnigmailKeyServer = ChromeUtils.import("chrome://enigmail/content/modules/keyserver.jsm").EnigmailKeyServer;
- let foundKeys = [];
+ for (let j = 0; j < Math.floor(len / MAXLEN) + 1; j++) {
+ ret += String.fromCharCode.apply(null, uArr.subarray(j * MAXLEN, ((j + 1) * MAXLEN)));
+ }
- try {
- const keyserver = EnigmailPrefs.getAutoKeyRetrieveServer();
- if (keyserver && keyserver.length > 0) {
- const keyList = "0x" + keyIds.join(" 0x");
- const ret = await EnigmailKeyServer.download(keyList, keyserver);
+ return ret;
+}
+
+function getDateTime(dateNum, withDate, withTime) {
+ const DATE_2DIGIT = "2-digit";
+ const DATE_4DIGIT = "numeric";
- if (ret.result === 0 && ret.keyList.length > 0) {
- foundKeys = await pgpjs_keyStore.getKeysForKeyIds(false, keyIds);
+ if (dateNum && dateNum !== 0) {
+ let dat = new Date(dateNum * 1000);
+
+ var options = {};
+
+ if (withDate) {
+ options.day = DATE_2DIGIT;
+ options.month = DATE_2DIGIT;
+ let year = dat.getFullYear();
+ if (year > 2099) {
+ options.year = DATE_4DIGIT;
}
+ else {
+ options.year = DATE_2DIGIT;
+ }
+ }
+ if (withTime) {
+ options.hour = DATE_2DIGIT;
+ options.minute = DATE_2DIGIT;
+ }
+
+ return new Intl.DateTimeFormat(undefined, options).format(dat);
+ }
+ else {
+ return "";
+ }
+}
+
+const gTrx = [];
+
+function startOpenpgpTrx() {
+ let promiseObj = {};
+
+ return new Promise((resolve, reject) => {
+ promiseObj.resolve = resolve;
+ promiseObj.reject = reject;
+ gTrx.push(promiseObj);
+
+ if (gTrx.length === 1) {
+ DEBUG_LOG("====> start process directly");
+ resolve();
+ }
+ });
+}
+
+function endOpenpgpTrx() {
+ if (gTrx.length > 0) {
+ DEBUG_LOG("<==== end process");
+ gTrx.splice(0, 1); // remove 1st element
+ }
+
+ if (gTrx.length > 0) {
+ DEBUG_LOG("====> start process queued");
+ gTrx[0].resolve();
+ }
+}
+
+/*************************************************************************
+ *
+ * Implementation of Worker
+ *
+ **************************************************************************/
+
+
+var pendingPromises = [],
+ gTransactionId = 0;
+
+/**
+ * Send a message to the worker parent for requesting data
+ *
+ * @param {String} functionName
+ * @param {Object} param
+ * @param {Object} transferables
+ *
+ * @returns Promise<Object>
+ */
+async function requestMessage(functionName, param, transferables) {
+
+ let trxId = ++gTransactionId;
+ return new Promise((resolve, reject) => {
+ postMessage({
+ func: functionName,
+ trxId: trxId,
+ param: param
+ }, transferables);
+
+ pendingPromises[trxId] = {
+ resolve,
+ reject
+ };
+ });
+}
+
+/**
+ * Send and receive messages to/from Worker parent
+ */
+onmessage = async function(e) {
+ if (("result" in e.data) && ("trxId" in e.data)) {
+ if (pendingPromises[e.data.trxId]) {
+ pendingPromises[e.data.trxId].resolve(e.data.result);
+ delete pendingPromises[e.data.trxId];
}
+ return;
}
- catch (x) {}
- return foundKeys;
+ if (("error" in e.data) && ("trxId" in e.data)) {
+ if (pendingPromises[e.data.trxId]) {
+ pendingPromises[e.data.trxId].reject({
+ message: e.data.error
+ });
+ delete pendingPromises[e.data.trxId];
+ }
+ return;
+ }
+
+ if (!("func" in e.data && "trxId" in e.data)) {
+ DEBUG_LOG('Worker: Message received invalid data from main script');
+
+ if ("trxId" in e.data) {
+ postMessage({
+ trxId: e.data.trxId,
+ error: "No function provided"
+ });
+ }
+ return;
+ }
+
+ let method = e.data.func;
+ let args = e.data.param || null;
+
+ if (!(method in workerBody)) {
+ postMessage({
+ trxId: e.data.trxId,
+ error: `Invalid method '${method}' invoked`
+ });
+ return;
+ }
+
+ try {
+ await startOpenpgpTrx();
+ let workerResult = await workerBody[method](args);
+ endOpenpgpTrx();
+ DEBUG_LOG('Posting message back to main script');
+ postMessage({
+ trxId: e.data.trxId,
+ result: workerResult
+ });
+ }
+ catch (ex) {
+ endOpenpgpTrx();
+ postMessage({
+ trxId: e.data.trxId,
+ error: `${ex.toString()}\n${ex.stack}`
+ });
+ }
+};
+
+
+onerror = function(e) {
+ ERROR_LOG('Received error from main script');
+};
+
+
+function DEBUG_LOG(msg) {
+ postMessage({
+ logMessage: "pgpjs-crypto-worker.js: " + msg,
+ logLevel: 5
+ });
+}
+
+function ERROR_LOG(msg) {
+ postMessage({
+ logMessage: "pgpjs-crypto-worker.js: " + msg,
+ logLevel: 0
+ });
}
diff --git a/package/tests/main.js b/package/tests/main.js
index 93a51542..dae6f213 100644
--- a/package/tests/main.js
+++ b/package/tests/main.js
@@ -67,6 +67,6 @@ execTest("autoSetup-test.js");
execTest("persistentCrypto-test.js");
execTest("pgpjs-keys-test.js");
execTest("pgpjs-keystore-test.js");
-execTest("pgpjs-decrypt-test.js");
+execTest("pgpjs-crypto-test.js");
execTest("pgpjs-encrypt-test.js");
execTest("pgpjs-keymanip-test.js");
diff --git a/package/tests/pgpjs-decrypt-test.js b/package/tests/pgpjs-crypto-test.js
index 05cc0493..fe210ca7 100644
--- a/package/tests/pgpjs-decrypt-test.js
+++ b/package/tests/pgpjs-crypto-test.js
@@ -11,12 +11,13 @@
do_load_module("file://" + do_get_cwd().path + "/testHelper.js");
-testing("cryptoAPI/pgpjs-decrypt.jsm");
-/*global pgpjs_decrypt: false, getOpenPGPLibrary: false, pgpjs_keyStore: false, EnigmailConstants: false,
- EnigmailFiles: false
- */
+ChromeUtils.import("chrome://enigmail/content/modules/cryptoAPI/pgpjs-crypto-main.jsm"); /*global pgpjs_crypto: false */
+const EnigmailFiles = ChromeUtils.import("chrome://enigmail/content/modules/files.jsm").EnigmailFiles;
const EnigmailArmor = ChromeUtils.import("chrome://enigmail/content/modules/armor.jsm").EnigmailArmor;
+const EnigmailConstants = ChromeUtils.import("chrome://enigmail/content/modules/constants.jsm").EnigmailConstants;
+const pgpjs_keyStore = ChromeUtils.import("chrome://enigmail/content/modules/cryptoAPI/pgpjs-keystore.jsm").pgpjs_keyStore;
+const getOpenPGPLibrary = ChromeUtils.import("chrome://enigmail/content/modules/stdlib/openpgp-loader.jsm").getOpenPGPLibrary;
test(withTestGpgHome(asyncTest(async function testDecrypt() {
try {
@@ -43,8 +44,8 @@ test(withTestGpgHome(asyncTest(async function testDecrypt() {
let fileData = EnigmailFiles.readFile(encFile);
let pgpMsg = EnigmailArmor.splitArmoredBlocks(fileData)[0];
- let result = await pgpjs_decrypt.processPgpMessage(pgpMsg, {});
- Assert.equal(result.statusFlags, EnigmailConstants.DECRYPTION_FAILED | EnigmailConstants.NO_SECKEY);
+ let result = await pgpjs_crypto.processPgpMessage(pgpMsg, {});
+ Assert.equal(result.statusFlags, EnigmailConstants.DECRYPTION_FAILED);
const pubKeyFile = do_get_file("resources/dev-strike.sec", false);
fileData = EnigmailFiles.readBinaryFile(pubKeyFile);
@@ -52,7 +53,7 @@ test(withTestGpgHome(asyncTest(async function testDecrypt() {
let r = await pgpjs_keyStore.writeKey(fileData);
Assert.equal(r.length, 1);
- result = await pgpjs_decrypt.processPgpMessage(pgpMsg, {});
+ result = await pgpjs_crypto.processPgpMessage(pgpMsg, {});
Assert.equal(result.statusFlags, EnigmailConstants.DECRYPTION_OKAY | EnigmailConstants.GOOD_SIGNATURE | EnigmailConstants.TRUSTED_IDENTITY);
Assert.equal(result.exitCode, 0);
Assert.equal(result.sigDetails, "65537E212DC19025AD38EDB2781617319CE311C4 2020-03-21 1584808355 0 4 0 1 8 00 65537E212DC19025AD38EDB2781617319CE311C4");
@@ -68,7 +69,7 @@ owE7rZbEEOfZI+yRmpOTr1CeX5SToscVkpFZrABEiQolqcUlCla6mlwA
=aAp2
-----END PGP MESSAGE-----`;
- result = await pgpjs_decrypt.processPgpMessage(storedMsg, {});
+ result = await pgpjs_crypto.processPgpMessage(storedMsg, {});
Assert.equal(result.statusFlags, 0);
Assert.equal(result.exitCode, 0);
Assert.equal(result.sigDetails, "");
@@ -94,7 +95,7 @@ j8bbyQ==
=fwVK
-----END PGP MESSAGE-----`;
- result = await pgpjs_decrypt.processPgpMessage(signedMsg, {});
+ result = await pgpjs_crypto.processPgpMessage(signedMsg, {});
Assert.equal(result.statusFlags, EnigmailConstants.GOOD_SIGNATURE | EnigmailConstants.TRUSTED_IDENTITY);
Assert.equal(result.exitCode, 0);
Assert.equal(result.sigDetails, "65537E212DC19025AD38EDB2781617319CE311C4 2020-02-16 1581878756 0 4 0 1 8 00 65537E212DC19025AD38EDB2781617319CE311C4");
@@ -125,7 +126,7 @@ wJEP0gfdDZA1bEV78SRcjJDlfo5vuWX4W/ZlAlA9hy5OVq69DOdlcVdgj18+gy94
-----END PGP SIGNATURE-----
`;
- result = await pgpjs_decrypt.verify(clearSigned, {});
+ result = await pgpjs_crypto.verify(clearSigned, {});
Assert.equal(result.statusFlags, EnigmailConstants.GOOD_SIGNATURE | EnigmailConstants.TRUSTED_IDENTITY);
Assert.equal(result.exitCode, 0);
Assert.equal(result.sigDetails, "65537E212DC19025AD38EDB2781617319CE311C4 2020-02-16 1581879420 0 4 0 1 8 00 65537E212DC19025AD38EDB2781617319CE311C4");
@@ -151,7 +152,7 @@ TA==
=6sUw
-----END PGP MESSAGE-----`;
- result = await pgpjs_decrypt.processPgpMessage(noMdcProtection, {});
+ result = await pgpjs_crypto.processPgpMessage(noMdcProtection, {});
Assert.equal(result.statusFlags, EnigmailConstants.DECRYPTION_FAILED | EnigmailConstants.MISSING_MDC);
Assert.equal(result.exitCode, 0);
Assert.equal(result.decryptedData, "");
@@ -174,7 +175,7 @@ fsTKNmsBfsUHg/qzu+yD0e4bTuEKVsDcCg==
=WPhs
-----END PGP MESSAGE-----`;
- result = await pgpjs_decrypt.processPgpMessage(badMdc, {});
+ result = await pgpjs_crypto.processPgpMessage(badMdc, {});
Assert.equal(result.statusFlags, EnigmailConstants.DECRYPTION_FAILED);
Assert.equal(result.exitCode, 1);
Assert.equal(result.decryptedData, "");
@@ -192,7 +193,7 @@ iD8DBQE+yUcu4mZch0nhy8kRAuh/AKDM1Xc49BKVfJIFg/btWGfbF/pgcwCgw0Zk
-----END PGP SIGNATURE-----
`;
- result = await pgpjs_decrypt.verify(packetV3, {});
+ result = await pgpjs_crypto.verify(packetV3, {});
Assert.equal(result.statusFlags, EnigmailConstants.UNVERIFIED_SIGNATURE);
Assert.equal(result.exitCode, 1);
Assert.equal(result.decryptedData, "");
@@ -211,18 +212,18 @@ test(withTestGpgHome(asyncTest(async function testVerifyFile() {
const pubKeyFile = do_get_file("resources/dev-strike.asc", false);
try {
- await pgpjs_decrypt.verifyFile(attachmentFile.path, signatureFile.path);
+ await pgpjs_crypto.verifyFile(attachmentFile.path, signatureFile.path);
Assert.ok(false, "Should not obtain a valid verification");
}
catch (err) {
- Assert.assertContains(String(err), "Unverified signature - signed with unknown key");
+ Assert.assertContains(String(err), "Error during parsing");
}
let keyData = EnigmailFiles.readBinaryFile(pubKeyFile);
let result = await pgpjs_keyStore.writeKey(keyData);
Assert.equal(result.length, 1);
- result = await pgpjs_decrypt.verifyFile(attachmentFile.path, signatureFile.path);
+ result = await pgpjs_crypto.verifyFile(attachmentFile.path, signatureFile.path);
Assert.assertContains(result, 'Good signature from anonymous strike');
Assert.assertContains(result, 'Key ID: 0x65537E212DC19025AD38EDB2781617319CE311C');
})));
diff --git a/package/tests/testHelper.js b/package/tests/testHelper.js
index d23dfb0a..41d6631e 100644
--- a/package/tests/testHelper.js
+++ b/package/tests/testHelper.js
@@ -55,8 +55,6 @@ var TestHelper = {
testing: function(name) {
TestHelper.currentlyTesting = name;
- const resetOpenPGPLibrary = ChromeUtils.import("chrome://enigmail/content/modules/stdlib/openpgp-loader.jsm").resetLibrary;
- resetOpenPGPLibrary();
},
registerTest: function(fn) {
diff --git a/ui/content/enigmailMessengerOverlay.js b/ui/content/enigmailMessengerOverlay.js
index eae99d00..e6248ee0 100644
--- a/ui/content/enigmailMessengerOverlay.js
+++ b/ui/content/enigmailMessengerOverlay.js
@@ -1967,7 +1967,6 @@ Enigmail.msg = {
var mailNewsUrl = Enigmail.msg.getCurrentMsgUrl();
var urlSpec = mailNewsUrl ? mailNewsUrl.spec : "";
- var newBufferSize = 0;
var l = urlSpec.length;
diff --git a/util/genxpi b/util/genxpi
index faa45754..18817402 100755
--- a/util/genxpi
+++ b/util/genxpi
@@ -90,7 +90,8 @@ set chrome/content/preferences/defaultPrefs.js \
chrome/content/modules/cryptoAPI/gpgme.js \
chrome/content/modules/cryptoAPI/openpgp-js.js \
chrome/content/modules/cryptoAPI/pgpjs-encrypt.jsm \
- chrome/content/modules/cryptoAPI/pgpjs-decrypt.jsm \
+ chrome/content/modules/cryptoAPI/pgpjs-crypto-main.jsm \
+ chrome/content/modules/cryptoAPI/pgpjs-crypto-worker.js \
chrome/content/modules/cryptoAPI/pgpjs-keys.jsm \
chrome/content/modules/cryptoAPI/pgpjs-keymanipulation.jsm \
chrome/content/modules/cryptoAPI/pgpjs-keystore.jsm \