Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(209)

Side by Side Diff: chrome/browser/resources/cryptotoken/multiplesigner.js

Issue 249913002: FIDO U2F component extension (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Merge with HEAD Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6 * @fileoverview A multiple gnubby signer wraps the process of opening a number
7 * of gnubbies, signing each challenge in an array of challenges until a
8 * success condition is satisfied, and yielding each succeeding gnubby.
9 *
10 * @author juanlang@google.com (Juan Lang)
11 */
12 'use strict';
13
14 /**
15 * Creates a new sign handler with an array of gnubby indexes.
16 * @param {!GnubbyFactory} factory Used to create and open the gnubbies.
17 * @param {Array.<llGnubbyDeviceId>} gnubbyIndexes Which gnubbies to open.
18 * @param {boolean} forEnroll Whether this signer is signing for an attempted
19 * enroll operation.
20 * @param {function(boolean, (number|undefined))} completedCb Called when this
21 * signer completes sign attempts, i.e. no further results should be
22 * expected.
23 * @param {function(number, MultipleSignerResult)} gnubbyFoundCb Called with
24 * each gnubby/challenge that yields a successful result.
25 * @param {Countdown=} opt_timer An advisory timer, beyond whose expiration the
26 * signer will not attempt any new operations, assuming the caller is no
27 * longer interested in the outcome.
28 * @param {string=} opt_logMsgUrl A URL to post log messages to.
29 * @constructor
30 */
31 function MultipleGnubbySigner(factory, gnubbyIndexes, forEnroll, completedCb,
32 gnubbyFoundCb, opt_timer, opt_logMsgUrl) {
33 /** @private {!GnubbyFactory} */
34 this.factory_ = factory;
35 /** @private {Array.<llGnubbyDeviceId>} */
36 this.gnubbyIndexes_ = gnubbyIndexes;
37 /** @private {boolean} */
38 this.forEnroll_ = forEnroll;
39 /** @private {function(boolean, (number|undefined))} */
40 this.completedCb_ = completedCb;
41 /** @private {function(number, MultipleSignerResult)} */
42 this.gnubbyFoundCb_ = gnubbyFoundCb;
43 /** @private {Countdown|undefined} */
44 this.timer_ = opt_timer;
45 /** @private {string|undefined} */
46 this.logMsgUrl_ = opt_logMsgUrl;
47
48 /** @private {Array.<SignHelperChallenge>} */
49 this.challenges_ = [];
50 /** @private {boolean} */
51 this.challengesFinal_ = false;
52
53 // Create a signer for each gnubby.
54 /** @private {boolean} */
55 this.anySucceeded_ = false;
56 /** @private {number} */
57 this.numComplete_ = 0;
58 /** @private {Array.<SingleGnubbySigner>} */
59 this.signers_ = [];
60 /** @private {Array.<boolean>} */
61 this.stillGoing_ = [];
62 /** @private {Array.<number>} */
63 this.errorStatus_ = [];
64 for (var i = 0; i < gnubbyIndexes.length; i++) {
65 this.addGnubby(gnubbyIndexes[i]);
66 }
67 }
68
69 /**
70 * Attempts to open this signer's gnubbies, if they're not already open.
71 * (This is implicitly done by addChallenges.)
72 */
73 MultipleGnubbySigner.prototype.open = function() {
74 for (var i = 0; i < this.signers_.length; i++) {
75 this.signers_[i].open();
76 }
77 };
78
79 /**
80 * Closes this signer's gnubbies, if any are open.
81 */
82 MultipleGnubbySigner.prototype.close = function() {
83 for (var i = 0; i < this.signers_.length; i++) {
84 this.signers_[i].close();
85 }
86 };
87
88 /**
89 * Adds challenges to the set of challenges being tried by this signer.
90 * The challenges are an array of challenge objects, where each challenge
91 * object's values are base64-encoded.
92 * If the signer is currently idle, begins signing the new challenges.
93 *
94 * @param {Array} challenges
95 * @param {boolean} finalChallenges
96 * @return {boolean} whether the challenges were successfully added.
97 * @public
98 */
99 MultipleGnubbySigner.prototype.addEncodedChallenges =
100 function(challenges, finalChallenges) {
101 var decodedChallenges = [];
102 if (challenges) {
103 for (var i = 0; i < challenges.length; i++) {
104 var decodedChallenge = {};
105 var challenge = challenges[i];
106 decodedChallenge['challengeHash'] =
107 B64_decode(challenge['challengeHash']);
108 decodedChallenge['appIdHash'] = B64_decode(challenge['appIdHash']);
109 decodedChallenge['keyHandle'] = B64_decode(challenge['keyHandle']);
110 if (challenge['version']) {
111 decodedChallenge['version'] = challenge['version'];
112 }
113 decodedChallenges.push(decodedChallenge);
114 }
115 }
116 return this.addChallenges(decodedChallenges, finalChallenges);
117 };
118
119 /**
120 * Adds challenges to the set of challenges being tried by this signer.
121 * If the signer is currently idle, begins signing the new challenges.
122 *
123 * @param {Array.<SignHelperChallenge>} challenges
124 * @param {boolean} finalChallenges
125 * @return {boolean} whether the challenges were successfully added.
126 * @public
127 */
128 MultipleGnubbySigner.prototype.addChallenges =
129 function(challenges, finalChallenges) {
130 if (this.challengesFinal_) {
131 // Can't add new challenges once they're finalized.
132 return false;
133 }
134
135 if (challenges) {
136 for (var i = 0; i < challenges.length; i++) {
137 this.challenges_.push(challenges[i]);
138 }
139 }
140 this.challengesFinal_ = finalChallenges;
141
142 for (var i = 0; i < this.signers_.length; i++) {
143 this.stillGoing_[i] =
144 this.signers_[i].addChallenges(challenges, finalChallenges);
145 this.errorStatus_[i] = 0;
146 }
147 return true;
148 };
149
150 /**
151 * Adds a new gnubby to this signer's list of gnubbies. (Only possible while
152 * this signer is still signing: without this restriction, the morePossible
153 * indication in the callbacks could become violated.) If this signer has
154 * challenges to sign, begins signing on the new gnubby with them.
155 * @param {llGnubbyDeviceId} gnubbyIndex The index of the gnubby to add.
156 * @return {boolean} Whether the gnubby was added successfully.
157 * @public
158 */
159 MultipleGnubbySigner.prototype.addGnubby = function(gnubbyIndex) {
160 if (this.numComplete_ && this.numComplete_ == this.signers_.length)
161 return false;
162
163 var index = this.signers_.length;
164 this.signers_.push(
165 new SingleGnubbySigner(
166 this.factory_,
167 gnubbyIndex,
168 this.forEnroll_,
169 this.signFailedCallback_.bind(this, index),
170 this.signSucceededCallback_.bind(this, index),
171 this.timer_ ? this.timer_.clone() : null,
172 this.logMsgUrl_));
173 this.stillGoing_.push(false);
174
175 if (this.challenges_.length) {
176 this.stillGoing_[index] =
177 this.signers_[index].addChallenges(this.challenges_,
178 this.challengesFinal_);
179 }
180 return true;
181 };
182
183 /**
184 * Called by a SingleGnubbySigner upon failure, i.e. unsuccessful completion of
185 * all its sign operations.
186 * @param {number} index the index of the gnubby whose result this is
187 * @param {number} code the result code of the sign operation
188 * @private
189 */
190 MultipleGnubbySigner.prototype.signFailedCallback_ = function(index, code) {
191 console.log(
192 UTIL_fmt('failure. gnubby ' + index + ' got code ' + code.toString(16)));
193 if (!this.stillGoing_[index]) {
194 console.log(UTIL_fmt('gnubby ' + index + ' no longer running!'));
195 // Shouldn't ever happen? Disregard.
196 return;
197 }
198 this.stillGoing_[index] = false;
199 this.errorStatus_[index] = code;
200 this.numComplete_++;
201 var morePossible = this.numComplete_ < this.signers_.length;
202 if (!morePossible)
203 this.notifyComplete_();
204 };
205
206 /**
207 * Called by a SingleGnubbySigner upon success.
208 * @param {number} index the index of the gnubby whose result this is
209 * @param {usbGnubby} gnubby the underlying gnubby that succeded.
210 * @param {number} code the result code of the sign operation
211 * @param {SingleSignerResult=} signResult
212 * @private
213 */
214 MultipleGnubbySigner.prototype.signSucceededCallback_ =
215 function(index, gnubby, code, signResult) {
216 console.log(UTIL_fmt('success! gnubby ' + index + ' got code ' +
217 code.toString(16)));
218 if (!this.stillGoing_[index]) {
219 console.log(UTIL_fmt('gnubby ' + index + ' no longer running!'));
220 // Shouldn't ever happen? Disregard.
221 return;
222 }
223 this.anySucceeded_ = true;
224 this.stillGoing_[index] = false;
225 this.notifySuccess_(code, gnubby, index, signResult);
226 this.numComplete_++;
227 var morePossible = this.numComplete_ < this.signers_.length;
228 if (!morePossible)
229 this.notifyComplete_();
230 };
231
232 /**
233 * @private
234 */
235 MultipleGnubbySigner.prototype.notifyComplete_ = function() {
236 // See if any of the signers failed with a strange error. If so, report a
237 // single error to the caller, partly as a diagnostic aid and partly to
238 // distinguish real failures from wrong data.
239 var funnyBusiness;
240 for (var i = 0; i < this.errorStatus_.length; i++) {
241 if (this.errorStatus_[i] &&
242 this.errorStatus_[i] != DeviceStatusCodes.WRONG_DATA_STATUS &&
243 this.errorStatus_[i] != DeviceStatusCodes.WAIT_TOUCH_STATUS) {
244 funnyBusiness = this.errorStatus_[i];
245 break;
246 }
247 }
248 if (funnyBusiness) {
249 console.warn(UTIL_fmt('all done (success: ' + this.anySucceeded_ + ', ' +
250 'funny error = ' + funnyBusiness + ')'));
251 } else {
252 console.log(UTIL_fmt('all done (success: ' + this.anySucceeded_ + ')'));
253 }
254 this.completedCb_(this.anySucceeded_, funnyBusiness);
255 };
256
257 /**
258 * @param {number} code
259 * @param {usbGnubby} gnubby
260 * @param {number} gnubbyIndex
261 * @param {SingleSignerResult=} singleSignerResult
262 * @private
263 */
264 MultipleGnubbySigner.prototype.notifySuccess_ =
265 function(code, gnubby, gnubbyIndex, singleSignerResult) {
266 console.log(UTIL_fmt('success (' + code.toString(16) + ')'));
267 var signResult = {
268 'gnubby': gnubby,
269 'gnubbyIndex': gnubbyIndex
270 };
271 if (singleSignerResult && singleSignerResult['challenge'])
272 signResult['challenge'] = singleSignerResult['challenge'];
273 if (singleSignerResult && singleSignerResult['info'])
274 signResult['info'] = singleSignerResult['info'];
275 this.gnubbyFoundCb_(code, signResult);
276 };
OLDNEW
« no previous file with comments | « chrome/browser/resources/cryptotoken/manifest.json ('k') | chrome/browser/resources/cryptotoken/requestqueue.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698