178 lines, 95 LOC, 85 covered (89%)
12 | 1 | /* ***** BEGIN LICENSE BLOCK ***** |
2 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
|
3 | * |
|
4 | * The contents of this file are subject to the Mozilla Public License Version |
|
5 | * 1.1 (the "License"); you may not use this file except in compliance with |
|
6 | * the License. You may obtain a copy of the License at |
|
7 | * http://www.mozilla.org/MPL/ |
|
8 | * |
|
9 | * Software distributed under the License is distributed on an "AS IS" basis, |
|
10 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
|
11 | * for the specific language governing rights and limitations under the |
|
12 | * License. |
|
13 | * |
|
14 | * The Original Code is Weave. |
|
15 | * |
|
16 | * The Initial Developer of the Original Code is Mozilla. |
|
17 | * Portions created by the Initial Developer are Copyright (C) 2008 |
|
18 | * the Initial Developer. All Rights Reserved. |
|
19 | * |
|
20 | * Contributor(s): |
|
21 | * Dan Mills <thunder@mozilla.com> |
|
22 | * |
|
23 | * Alternatively, the contents of this file may be used under the terms of |
|
24 | * either the GNU General Public License Version 2 or later (the "GPL"), or |
|
25 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
|
26 | * in which case the provisions of the GPL or the LGPL are applicable instead |
|
27 | * of those above. If you wish to allow use of your version of this file only |
|
28 | * under the terms of either the GPL or the LGPL, and not to allow others to |
|
29 | * use your version of this file under the terms of the MPL, indicate your |
|
30 | * decision by deleting the provisions above and replace them with the notice |
|
31 | * and other provisions required by the GPL or the LGPL. If you do not delete |
|
32 | * the provisions above, a recipient may use your version of this file under |
|
33 | * the terms of any one of the MPL, the GPL or the LGPL. |
|
34 | * |
|
35 | * ***** END LICENSE BLOCK ***** */ |
|
36 | ||
108 | 37 | const EXPORTED_SYMBOLS = ['PubKey', 'PrivKey', |
84 | 38 | 'PubKeys', 'PrivKeys']; |
39 | ||
48 | 40 | const Cc = Components.classes; |
48 | 41 | const Ci = Components.interfaces; |
48 | 42 | const Cr = Components.results; |
48 | 43 | const Cu = Components.utils; |
44 | ||
60 | 45 | Cu.import("resource://weave/log4moz.js"); |
60 | 46 | Cu.import("resource://weave/constants.js"); |
60 | 47 | Cu.import("resource://weave/util.js"); |
60 | 48 | Cu.import("resource://weave/resource.js"); |
60 | 49 | Cu.import("resource://weave/base_records/wbo.js"); |
50 | ||
39 | 51 | function PubKey(uri) { |
90 | 52 | WBORecord.call(this, uri); |
45 | 53 | this.type = "pubkey"; |
45 | 54 | this.keyData = null; |
60 | 55 | this.privateKeyUri = null; |
56 | } |
|
24 | 57 | PubKey.prototype = { |
36 | 58 | __proto__: WBORecord.prototype, |
24 | 59 | _logName: "Record.PubKey", |
60 | ||
3633 | 61 | get privateKeyUri() { |
10827 | 62 | if (!this.data) |
63 | return null; |
|
64 | ||
65 | // Use the uri if it resolves, otherwise return raw (uri type unresolvable) |
|
14436 | 66 | let key = this.payload.privateKeyUri; |
36090 | 67 | return Utils.makeURI(this.uri.resolve(key) || key); |
68 | }, |
|
69 | ||
60 | 70 | get publicKeyUri() { |
71 | throw "attempted to get public key url from a public key!"; |
|
72 | } |
|
73 | }; |
|
74 | ||
204 | 75 | Utils.deferGetSet(PubKey, "payload", ["keyData", "privateKeyUri", "type"]); |
76 | ||
39 | 77 | function PrivKey(uri) { |
90 | 78 | WBORecord.call(this, uri); |
45 | 79 | this.type = "privkey"; |
45 | 80 | this.salt = null; |
45 | 81 | this.iv = null; |
45 | 82 | this.keyData = null; |
60 | 83 | this.publicKeyUri = null; |
84 | } |
|
24 | 85 | PrivKey.prototype = { |
36 | 86 | __proto__: WBORecord.prototype, |
24 | 87 | _logName: "Record.PrivKey", |
88 | ||
35 | 89 | get publicKeyUri() { |
33 | 90 | if (!this.data) |
91 | return null; |
|
92 | ||
93 | // Use the uri if it resolves, otherwise return raw (uri type unresolvable) |
|
44 | 94 | let key = this.payload.publicKeyUri; |
110 | 95 | return Utils.makeURI(this.uri.resolve(key) || key); |
96 | }, |
|
97 | ||
60 | 98 | get privateKeyUri() { |
99 | throw "attempted to get private key url from a private key!"; |
|
100 | } |
|
101 | }; |
|
102 | ||
276 | 103 | Utils.deferGetSet(PrivKey, "payload", ["salt", "iv", "keyData", "publicKeyUri", "type"]); |
104 | ||
105 | // XXX unused/unfinished |
|
24 | 106 | function SymKey(keyData, wrapped) { |
107 | this._data = keyData; |
|
108 | this._wrapped = wrapped; |
|
109 | } |
|
24 | 110 | SymKey.prototype = { |
24 | 111 | get wrapped() { |
112 | return this._wrapped; |
|
113 | }, |
|
114 | ||
60 | 115 | unwrap: function SymKey_unwrap(privkey, passphrase, meta_record) { |
116 | this._data = |
|
117 | Svc.Crypto.unwrapSymmetricKey(this._data, privkey.keyData, passphrase, |
|
118 | privkey.salt, privkey.iv); |
|
119 | } |
|
120 | }; |
|
121 | ||
84 | 122 | Utils.lazy(this, 'PubKeys', PubKeyManager); |
123 | ||
48 | 124 | function PubKeyManager() { |
144 | 125 | RecordManager.call(this); |
126 | } |
|
24 | 127 | PubKeyManager.prototype = { |
36 | 128 | __proto__: RecordManager.prototype, |
24 | 129 | _recordType: PubKey, |
24 | 130 | _logName: "PubKeyManager", |
131 | ||
10926 | 132 | get defaultKeyUri() this._defaultKeyUri, |
124 | 133 | set defaultKeyUri(value) { this._defaultKeyUri = value; }, |
134 | ||
3640 | 135 | getDefaultKey: function PubKeyManager_getDefaultKey() { |
18080 | 136 | return this.get(this.defaultKeyUri); |
137 | }, |
|
138 | ||
36 | 139 | createKeypair: function KeyMgr_createKeypair(passphrase, pubkeyUri, privkeyUri) { |
72 | 140 | this._log.debug("Generating RSA keypair"); |
36 | 141 | let pubkey = new PubKey(); |
36 | 142 | let privkey = new PrivKey(); |
84 | 143 | privkey.salt = Svc.Crypto.generateRandomBytes(16); |
72 | 144 | privkey.iv = Svc.Crypto.generateRandomIV(); |
145 | ||
72 | 146 | let pub = {}, priv = {}; |
120 | 147 | Svc.Crypto.generateKeypair(passphrase.password, privkey.salt, privkey.iv, pub, priv); |
132 | 148 | [pubkey.keyData, privkey.keyData] = [pub.value, priv.value]; |
149 | ||
24 | 150 | if (pubkeyUri) { |
36 | 151 | pubkey.uri = pubkeyUri; |
36 | 152 | privkey.publicKeyUri = pubkeyUri; |
153 | } |
|
24 | 154 | if (privkeyUri) { |
36 | 155 | privkey.uri = privkeyUri; |
36 | 156 | pubkey.privateKeyUri = privkeyUri; |
157 | } |
|
158 | ||
72 | 159 | this._log.debug("Generating RSA keypair... done"); |
84 | 160 | return {pubkey: pubkey, privkey: privkey}; |
161 | }, |
|
162 | ||
69 | 163 | uploadKeypair: function PubKeyManager_uploadKeypair(keys) { |
72 | 164 | for each (let key in keys) |
207 | 165 | new Resource(key.uri).put(key); |
166 | } |
|
167 | }; |
|
168 | ||
84 | 169 | Utils.lazy(this, 'PrivKeys', PrivKeyManager); |
170 | ||
36 | 171 | function PrivKeyManager() { |
72 | 172 | PubKeyManager.call(this); |
173 | } |
|
24 | 174 | PrivKeyManager.prototype = { |
36 | 175 | __proto__: PubKeyManager.prototype, |
24 | 176 | _recordType: PrivKey, |
60 | 177 | _logName: "PrivKeyManager" |
12 | 178 | }; |