Skip to content

Commit

Permalink
Generate keys in a worker
Browse files Browse the repository at this point in the history
 * Part of #20

 * Next to use async notion for a better experience.
  • Loading branch information
arlolra committed Jun 25, 2015
1 parent bad6b9e commit ed1af6f
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 17 deletions.
22 changes: 13 additions & 9 deletions chrome/content/libotr.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,20 @@ switch(Services.appinfo.OS) {

// Open libotr. Determine the path to the chrome directory and look for it
// there first. If not, fallback to searching the standard locations.
let libotr;
let libotr, libotrPath;
try {
// try in chrome
let uri = "chrome://otr/content/" + ctypes.libraryName("otr");
let chromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry);
uri = chromeReg.convertChromeURL(Services.io.newURI(uri, null, null));
libotr = ctypes.open(uri.QueryInterface(Ci.nsIFileURL).file.path);
libotrPath = uri.QueryInterface(Ci.nsIFileURL).file.path;
libotr = ctypes.open(libotrPath);
} catch(e) {
// look in standard locations
libotr = ctypes.open(ctypes.libraryName("otr"));
libotrPath = ctypes.libraryName("otr");
libotr = ctypes.open(libotrPath);
}

// libotr API version
const otrl_version = [4, 1, 0];

// type defs

const time_t = ctypes.long;
Expand Down Expand Up @@ -336,9 +335,14 @@ const OTRL_POLICY_ERROR_START_AKE = 0x40;

let libOTR = {

path: libotrPath,

// libotr API version
otrl_version: [4, 1, 0],

init: function() {
// apply version array as arguments to the init function
if (this.otrl_init.apply(this, otrl_version))
if (this.otrl_init.apply(this, this.otrl_version))
throw new Error("Couldn't initialize libotr.");
},

Expand Down Expand Up @@ -532,15 +536,15 @@ let libOTR = {
// private key into the given file and store it in the OtrlUserState.
otrl_privkey_generate_finish: libotr.declare(
"otrl_privkey_generate_finish", abi, gcry_error_t,
ctypes.void_t.ptr, ctypes.char.ptr
OtrlUserState, ctypes.void_t.ptr, ctypes.char.ptr
),

// Call this from the main thread only, in the event that the background
// thread generating the key is cancelled. The newkey is deallocated,
// and must not be used further.
otrl_privkey_generate_cancelled: libotr.declare(
"otrl_privkey_generate_cancelled", abi, gcry_error_t,
ctypes.void_t.ptr
OtrlUserState, ctypes.void_t.ptr
),

// Read a sets of private DSA keys from a file on disk into the given
Expand Down
27 changes: 23 additions & 4 deletions chrome/content/otr.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { interfaces: Ci, utils: Cu, classes: Cc } = Components;

Cu.import("resource:///modules/imServices.jsm");
Cu.import("resource:///modules/imXPCOMUtils.jsm");
Cu.import("resource://gre/modules/PromiseWorker.jsm");
Cu.import("resource://gre/modules/ctypes.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
Cu.import("chrome://otr/content/libotr.js");
Expand Down Expand Up @@ -178,11 +179,29 @@ let otr = {
this.commands.forEach(cmd => Services.cmd.unregisterCommand(cmd.name));
},

// generate a private key
// generate a private key in a worker
generatePrivateKey: function(account, protocol) {
if (libOTR.otrl_privkey_generate(
this.userstate, this.privateKeyPath, account, protocol
)) throw new Error("Failed to generate private key.");
let newkey = new ctypes.void_t.ptr();
let err = libOTR.otrl_privkey_generate_start(
otr.userstate, account, protocol, newkey.address()
);
if (err || newkey.isNull())
return Promise.resolve(false);
let worker = new BasePromiseWorker("chrome://otr/content/worker.js");
let handleErr = function(err) {
if (!newkey.isNull())
libOTR.otrl_privkey_generate_cancelled(otr.userstate, newkey);
return false;
};
return worker.post("generateKey", [
libOTR.path, libOTR.otrl_version, newkey.toSource()
]).then(function(err) {
if (!err)
libOTR.otrl_privkey_generate_finish(
otr.userstate, newkey, otr.privateKeyPath
);
return err ? handleErr(err) : true;
}).catch(handleErr);
},

// write fingerprints to file synchronously
Expand Down
9 changes: 5 additions & 4 deletions chrome/content/priv.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ let otrPriv = {
let args = window.arguments[0].wrappedJSObject;
let priv = document.getElementById("priv");
priv.textContent = _("priv.account", args.account, args.protocol);
setTimeout(function() {
otr.generatePrivateKey(args.account, args.protocol);
otr.generatePrivateKey(args.account, args.protocol).then(function(success) {
if (!success)
throw new Error("Generating key failed!")
// document.documentElement.acceptDialog();
document.documentElement.getButton("accept").disabled = false;
}, 1000);
}
});
},

};
49 changes: 49 additions & 0 deletions chrome/content/worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
importScripts("resource://gre/modules/workers/require.js");

let PromiseWorker = require("resource://gre/modules/workers/PromiseWorker.js");

let Funcs = {};

// Only what we need from libotr.js
Funcs.generateKey = function(path, otrl_version, newkeySource) {
let newkey = eval(newkeySource);
let libotr = ctypes.open(path);

let abi = ctypes.default_abi;
let gcry_error_t = ctypes.unsigned_int;

// Initialize the OTR library. Pass the version of the API you are using.
let otrl_init = libotr.declare(
"otrl_init", abi, gcry_error_t,
ctypes.unsigned_int, ctypes.unsigned_int, ctypes.unsigned_int
);

// Do the private key generation calculation. You may call this from a
// background thread. When it completes, call
// otrl_privkey_generate_finish from the _main_ thread.
let otrl_privkey_generate_calculate = libotr.declare(
"otrl_privkey_generate_calculate", abi, gcry_error_t,
ctypes.void_t.ptr
);

otrl_init.apply(libotr, otrl_version);
let err = otrl_privkey_generate_calculate(newkey);
libotr.close();
return err;
};

let worker = new PromiseWorker.AbstractWorker();

worker.dispatch = function(method, args = []) {
return Funcs[method](...args);
};

worker.postMessage = function(res, ...args) {
self.postMessage(res, ...args);
};

worker.close = function() {
self.close();
};

self.addEventListener("message", msg => worker.handleMessage(msg));

1 comment on commit ed1af6f

@arlolra
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aleth In case you missed this. They don't appear to be shared nothing.

Please sign in to comment.