| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview Handles web page requests for gnubby enrollment. | 6 * @fileoverview Handles web page requests for gnubby enrollment. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 'use strict'; | 9 'use strict'; |
| 10 | 10 |
| 11 /** | 11 /** |
| 12 * Handles a U2F enroll request. | 12 * Handles a U2F enroll request. |
| 13 * @param {MessageSender} messageSender The message sender. | 13 * @param {MessageSender} messageSender The message sender. |
| 14 * @param {Object} request The web page's enroll request. | 14 * @param {Object} request The web page's enroll request. |
| 15 * @param {Function} sendResponse Called back with the result of the enroll. | 15 * @param {Function} sendResponse Called back with the result of the enroll. |
| 16 * @return {Closeable} A handler object to be closed when the browser channel | 16 * @return {Closeable} A handler object to be closed when the browser channel |
| 17 * closes. | 17 * closes. |
| 18 */ | 18 */ |
| 19 function handleU2fEnrollRequest(messageSender, request, sendResponse) { | 19 function handleU2fEnrollRequest(messageSender, request, sendResponse) { |
| 20 var sentResponse = false; | 20 var sentResponse = false; |
| 21 var closeable = null; | 21 var closeable = null; |
| 22 | 22 |
| 23 function sendErrorResponse(error) { | 23 function sendErrorResponse(error) { |
| 24 var response = makeU2fErrorResponse(request, error.errorCode, | 24 var response = |
| 25 error.errorMessage); | 25 makeU2fErrorResponse(request, error.errorCode, error.errorMessage); |
| 26 sendResponseOnce(sentResponse, closeable, response, sendResponse); | 26 sendResponseOnce(sentResponse, closeable, response, sendResponse); |
| 27 } | 27 } |
| 28 | 28 |
| 29 function sendSuccessResponse(u2fVersion, info, clientData) { | 29 function sendSuccessResponse(u2fVersion, info, clientData) { |
| 30 var enrollChallenges = request['registerRequests']; | 30 var enrollChallenges = request['registerRequests']; |
| 31 var enrollChallenge = | 31 var enrollChallenge = |
| 32 findEnrollChallengeOfVersion(enrollChallenges, u2fVersion); | 32 findEnrollChallengeOfVersion(enrollChallenges, u2fVersion); |
| 33 if (!enrollChallenge) { | 33 if (!enrollChallenge) { |
| 34 sendErrorResponse({errorCode: ErrorCodes.OTHER_ERROR}); | 34 sendErrorResponse({errorCode: ErrorCodes.OTHER_ERROR}); |
| 35 return; | 35 return; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 58 sendErrorResponse({errorCode: ErrorCodes.BAD_REQUEST}); | 58 sendErrorResponse({errorCode: ErrorCodes.BAD_REQUEST}); |
| 59 return null; | 59 return null; |
| 60 } | 60 } |
| 61 | 61 |
| 62 var timeoutValueSeconds = getTimeoutValueFromRequest(request); | 62 var timeoutValueSeconds = getTimeoutValueFromRequest(request); |
| 63 // Attenuate watchdog timeout value less than the enroller's timeout, so the | 63 // Attenuate watchdog timeout value less than the enroller's timeout, so the |
| 64 // watchdog only fires after the enroller could reasonably have called back, | 64 // watchdog only fires after the enroller could reasonably have called back, |
| 65 // not before. | 65 // not before. |
| 66 var watchdogTimeoutValueSeconds = attenuateTimeoutInSeconds( | 66 var watchdogTimeoutValueSeconds = attenuateTimeoutInSeconds( |
| 67 timeoutValueSeconds, MINIMUM_TIMEOUT_ATTENUATION_SECONDS / 2); | 67 timeoutValueSeconds, MINIMUM_TIMEOUT_ATTENUATION_SECONDS / 2); |
| 68 var watchdog = new WatchdogRequestHandler(watchdogTimeoutValueSeconds, | 68 var watchdog = |
| 69 timeout); | 69 new WatchdogRequestHandler(watchdogTimeoutValueSeconds, timeout); |
| 70 var wrappedErrorCb = watchdog.wrapCallback(sendErrorResponse); | 70 var wrappedErrorCb = watchdog.wrapCallback(sendErrorResponse); |
| 71 var wrappedSuccessCb = watchdog.wrapCallback(sendSuccessResponse); | 71 var wrappedSuccessCb = watchdog.wrapCallback(sendSuccessResponse); |
| 72 | 72 |
| 73 var timer = createAttenuatedTimer( | 73 var timer = createAttenuatedTimer( |
| 74 FACTORY_REGISTRY.getCountdownFactory(), timeoutValueSeconds); | 74 FACTORY_REGISTRY.getCountdownFactory(), timeoutValueSeconds); |
| 75 var logMsgUrl = request['logMsgUrl']; | 75 var logMsgUrl = request['logMsgUrl']; |
| 76 var enroller = new Enroller(timer, sender, sendErrorResponse, | 76 var enroller = new Enroller( |
| 77 sendSuccessResponse, logMsgUrl); | 77 timer, sender, sendErrorResponse, sendSuccessResponse, logMsgUrl); |
| 78 watchdog.setCloseable(/** @type {!Closeable} */ (enroller)); | 78 watchdog.setCloseable(/** @type {!Closeable} */ (enroller)); |
| 79 closeable = watchdog; | 79 closeable = watchdog; |
| 80 | 80 |
| 81 var registerRequests = request['registerRequests']; | 81 var registerRequests = request['registerRequests']; |
| 82 var signRequests = getSignRequestsFromEnrollRequest(request); | 82 var signRequests = getSignRequestsFromEnrollRequest(request); |
| 83 enroller.doEnroll(registerRequests, signRequests, request['appId']); | 83 enroller.doEnroll(registerRequests, signRequests, request['appId']); |
| 84 | 84 |
| 85 return closeable; | 85 return closeable; |
| 86 } | 86 } |
| 87 | 87 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 | 175 |
| 176 /** | 176 /** |
| 177 * Makes a responseData object for the enroll request with the given parameters. | 177 * Makes a responseData object for the enroll request with the given parameters. |
| 178 * @param {EnrollChallenge} enrollChallenge The enroll challenge used to | 178 * @param {EnrollChallenge} enrollChallenge The enroll challenge used to |
| 179 * register. | 179 * register. |
| 180 * @param {string} u2fVersion Version of gnubby that enrolled. | 180 * @param {string} u2fVersion Version of gnubby that enrolled. |
| 181 * @param {string} registrationData The registration data. | 181 * @param {string} registrationData The registration data. |
| 182 * @param {string=} opt_clientData The client data, if available. | 182 * @param {string=} opt_clientData The client data, if available. |
| 183 * @return {Object} The responseData object. | 183 * @return {Object} The responseData object. |
| 184 */ | 184 */ |
| 185 function makeEnrollResponseData(enrollChallenge, u2fVersion, registrationData, | 185 function makeEnrollResponseData( |
| 186 opt_clientData) { | 186 enrollChallenge, u2fVersion, registrationData, opt_clientData) { |
| 187 var responseData = {}; | 187 var responseData = {}; |
| 188 responseData['registrationData'] = registrationData; | 188 responseData['registrationData'] = registrationData; |
| 189 // Echo the used challenge back in the reply. | 189 // Echo the used challenge back in the reply. |
| 190 for (var k in enrollChallenge) { | 190 for (var k in enrollChallenge) { |
| 191 responseData[k] = enrollChallenge[k]; | 191 responseData[k] = enrollChallenge[k]; |
| 192 } | 192 } |
| 193 if (u2fVersion == 'U2F_V2') { | 193 if (u2fVersion == 'U2F_V2') { |
| 194 // For U2F_V2, the challenge sent to the gnubby is modified to be the | 194 // For U2F_V2, the challenge sent to the gnubby is modified to be the |
| 195 // hash of the client data. Include the client data. | 195 // hash of the client data. Include the client data. |
| 196 responseData['clientData'] = opt_clientData; | 196 responseData['clientData'] = opt_clientData; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 */ | 271 */ |
| 272 Enroller.DEFAULT_TIMEOUT_MILLIS = 30 * 1000; | 272 Enroller.DEFAULT_TIMEOUT_MILLIS = 30 * 1000; |
| 273 | 273 |
| 274 /** | 274 /** |
| 275 * Performs an enroll request with the given enroll and sign challenges. | 275 * Performs an enroll request with the given enroll and sign challenges. |
| 276 * @param {Array<EnrollChallenge>} enrollChallenges A set of enroll challenges. | 276 * @param {Array<EnrollChallenge>} enrollChallenges A set of enroll challenges. |
| 277 * @param {Array<SignChallenge>} signChallenges A set of sign challenges for | 277 * @param {Array<SignChallenge>} signChallenges A set of sign challenges for |
| 278 * existing enrollments for this user and appId. | 278 * existing enrollments for this user and appId. |
| 279 * @param {string=} opt_appId The app id for the entire request. | 279 * @param {string=} opt_appId The app id for the entire request. |
| 280 */ | 280 */ |
| 281 Enroller.prototype.doEnroll = function(enrollChallenges, signChallenges, | 281 Enroller.prototype.doEnroll = function( |
| 282 opt_appId) { | 282 enrollChallenges, signChallenges, opt_appId) { |
| 283 /** @private {Array<EnrollChallenge>} */ | 283 /** @private {Array<EnrollChallenge>} */ |
| 284 this.enrollChallenges_ = enrollChallenges; | 284 this.enrollChallenges_ = enrollChallenges; |
| 285 /** @private {Array<SignChallenge>} */ | 285 /** @private {Array<SignChallenge>} */ |
| 286 this.signChallenges_ = signChallenges; | 286 this.signChallenges_ = signChallenges; |
| 287 /** @private {(string|undefined)} */ | 287 /** @private {(string|undefined)} */ |
| 288 this.appId_ = opt_appId; | 288 this.appId_ = opt_appId; |
| 289 var self = this; | 289 var self = this; |
| 290 getTabIdWhenPossible(this.sender_).then(function() { | 290 getTabIdWhenPossible(this.sender_) |
| 291 if (self.done_) return; | 291 .then( |
| 292 self.approveOrigin_(); | 292 function() { |
| 293 }, function() { | 293 if (self.done_) |
| 294 self.close(); | 294 return; |
| 295 self.notifyError_({errorCode: ErrorCodes.BAD_REQUEST}); | 295 self.approveOrigin_(); |
| 296 }); | 296 }, |
| 297 function() { |
| 298 self.close(); |
| 299 self.notifyError_({errorCode: ErrorCodes.BAD_REQUEST}); |
| 300 }); |
| 297 }; | 301 }; |
| 298 | 302 |
| 299 /** | 303 /** |
| 300 * Ensures the user has approved this origin to use security keys, sending | 304 * Ensures the user has approved this origin to use security keys, sending |
| 301 * to the request to the handler if/when the user has done so. | 305 * to the request to the handler if/when the user has done so. |
| 302 * @private | 306 * @private |
| 303 */ | 307 */ |
| 304 Enroller.prototype.approveOrigin_ = function() { | 308 Enroller.prototype.approveOrigin_ = function() { |
| 305 var self = this; | 309 var self = this; |
| 306 FACTORY_REGISTRY.getApprovedOrigins() | 310 FACTORY_REGISTRY.getApprovedOrigins() |
| 307 .isApprovedOrigin(this.sender_.origin, this.sender_.tabId) | 311 .isApprovedOrigin(this.sender_.origin, this.sender_.tabId) |
| 308 .then(function(result) { | 312 .then(function(result) { |
| 309 if (self.done_) return; | 313 if (self.done_) |
| 314 return; |
| 310 if (!result) { | 315 if (!result) { |
| 311 // Origin not approved: rather than give an explicit indication to | 316 // Origin not approved: rather than give an explicit indication to |
| 312 // the web page, let a timeout occur. | 317 // the web page, let a timeout occur. |
| 313 // NOTE: if you are looking at this in a debugger, this line will | 318 // NOTE: if you are looking at this in a debugger, this line will |
| 314 // always be false since the origin of the debugger is different | 319 // always be false since the origin of the debugger is different |
| 315 // than origin of requesting page | 320 // than origin of requesting page |
| 316 if (self.timer_.expired()) { | 321 if (self.timer_.expired()) { |
| 317 self.notifyTimeout_(); | 322 self.notifyTimeout_(); |
| 318 return; | 323 return; |
| 319 } | 324 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 339 * by encoding them into a helper request and passing the resulting request to | 344 * by encoding them into a helper request and passing the resulting request to |
| 340 * the factory registry's helper. | 345 * the factory registry's helper. |
| 341 * @private | 346 * @private |
| 342 */ | 347 */ |
| 343 Enroller.prototype.sendEnrollRequestToHelper_ = function() { | 348 Enroller.prototype.sendEnrollRequestToHelper_ = function() { |
| 344 var encodedEnrollChallenges = | 349 var encodedEnrollChallenges = |
| 345 this.encodeEnrollChallenges_(this.enrollChallenges_, this.appId_); | 350 this.encodeEnrollChallenges_(this.enrollChallenges_, this.appId_); |
| 346 // If the request didn't contain a sign challenge, provide one. The value | 351 // If the request didn't contain a sign challenge, provide one. The value |
| 347 // doesn't matter. | 352 // doesn't matter. |
| 348 var defaultSignChallenge = ''; | 353 var defaultSignChallenge = ''; |
| 349 var encodedSignChallenges = | 354 var encodedSignChallenges = encodeSignChallenges( |
| 350 encodeSignChallenges(this.signChallenges_, defaultSignChallenge, | 355 this.signChallenges_, defaultSignChallenge, this.appId_); |
| 351 this.appId_); | |
| 352 var request = { | 356 var request = { |
| 353 type: 'enroll_helper_request', | 357 type: 'enroll_helper_request', |
| 354 enrollChallenges: encodedEnrollChallenges, | 358 enrollChallenges: encodedEnrollChallenges, |
| 355 signData: encodedSignChallenges, | 359 signData: encodedSignChallenges, |
| 356 logMsgUrl: this.logMsgUrl_ | 360 logMsgUrl: this.logMsgUrl_ |
| 357 }; | 361 }; |
| 358 if (!this.timer_.expired()) { | 362 if (!this.timer_.expired()) { |
| 359 request.timeout = this.timer_.millisecondsUntilExpired() / 1000.0; | 363 request.timeout = this.timer_.millisecondsUntilExpired() / 1000.0; |
| 360 request.timeoutSeconds = this.timer_.millisecondsUntilExpired() / 1000.0; | 364 request.timeoutSeconds = this.timer_.millisecondsUntilExpired() / 1000.0; |
| 361 } | 365 } |
| 362 | 366 |
| 363 // Begin fetching/checking the app ids. | 367 // Begin fetching/checking the app ids. |
| 364 var enrollAppIds = []; | 368 var enrollAppIds = []; |
| 365 if (this.appId_) { | 369 if (this.appId_) { |
| 366 enrollAppIds.push(this.appId_); | 370 enrollAppIds.push(this.appId_); |
| 367 } | 371 } |
| 368 for (var i = 0; i < this.enrollChallenges_.length; i++) { | 372 for (var i = 0; i < this.enrollChallenges_.length; i++) { |
| 369 if (this.enrollChallenges_[i].hasOwnProperty('appId')) { | 373 if (this.enrollChallenges_[i].hasOwnProperty('appId')) { |
| 370 enrollAppIds.push(this.enrollChallenges_[i]['appId']); | 374 enrollAppIds.push(this.enrollChallenges_[i]['appId']); |
| 371 } | 375 } |
| 372 } | 376 } |
| 373 // Sanity check | 377 // Sanity check |
| 374 if (!enrollAppIds.length) { | 378 if (!enrollAppIds.length) { |
| 375 console.warn(UTIL_fmt('empty enroll app ids?')); | 379 console.warn(UTIL_fmt('empty enroll app ids?')); |
| 376 this.notifyError_({errorCode: ErrorCodes.BAD_REQUEST}); | 380 this.notifyError_({errorCode: ErrorCodes.BAD_REQUEST}); |
| 377 return; | 381 return; |
| 378 } | 382 } |
| 379 var self = this; | 383 var self = this; |
| 380 this.checkAppIds_(enrollAppIds, function(result) { | 384 this.checkAppIds_(enrollAppIds, function(result) { |
| 381 if (self.done_) return; | 385 if (self.done_) |
| 386 return; |
| 382 if (result) { | 387 if (result) { |
| 383 self.handler_ = FACTORY_REGISTRY.getRequestHelper().getHandler(request); | 388 self.handler_ = FACTORY_REGISTRY.getRequestHelper().getHandler(request); |
| 384 if (self.handler_) { | 389 if (self.handler_) { |
| 385 var helperComplete = | 390 var helperComplete = |
| 386 /** @type {function(HelperReply)} */ | 391 /** @type {function(HelperReply)} */ |
| 387 (self.helperComplete_.bind(self)); | 392 (self.helperComplete_.bind(self)); |
| 388 self.handler_.run(helperComplete); | 393 self.handler_.run(helperComplete); |
| 389 } else { | 394 } else { |
| 390 self.notifyError_({errorCode: ErrorCodes.OTHER_ERROR}); | 395 self.notifyError_({errorCode: ErrorCodes.OTHER_ERROR}); |
| 391 } | 396 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 return /** @type {EnrollHelperChallenge} */ (encodedChallenge); | 432 return /** @type {EnrollHelperChallenge} */ (encodedChallenge); |
| 428 }; | 433 }; |
| 429 | 434 |
| 430 /** | 435 /** |
| 431 * Encodes the given enroll challenges using this enroller's state. | 436 * Encodes the given enroll challenges using this enroller's state. |
| 432 * @param {Array<EnrollChallenge>} enrollChallenges The enroll challenges. | 437 * @param {Array<EnrollChallenge>} enrollChallenges The enroll challenges. |
| 433 * @param {string=} opt_appId The app id for the entire request. | 438 * @param {string=} opt_appId The app id for the entire request. |
| 434 * @return {!Array<EnrollHelperChallenge>} The encoded enroll challenges. | 439 * @return {!Array<EnrollHelperChallenge>} The encoded enroll challenges. |
| 435 * @private | 440 * @private |
| 436 */ | 441 */ |
| 437 Enroller.prototype.encodeEnrollChallenges_ = function(enrollChallenges, | 442 Enroller.prototype.encodeEnrollChallenges_ = function( |
| 438 opt_appId) { | 443 enrollChallenges, opt_appId) { |
| 439 var challenges = []; | 444 var challenges = []; |
| 440 for (var i = 0; i < enrollChallenges.length; i++) { | 445 for (var i = 0; i < enrollChallenges.length; i++) { |
| 441 var enrollChallenge = enrollChallenges[i]; | 446 var enrollChallenge = enrollChallenges[i]; |
| 442 var version = enrollChallenge.version; | 447 var version = enrollChallenge.version; |
| 443 if (!version) { | 448 if (!version) { |
| 444 // Version is implicitly V1 if not specified. | 449 // Version is implicitly V1 if not specified. |
| 445 version = 'U2F_V1'; | 450 version = 'U2F_V1'; |
| 446 } | 451 } |
| 447 | 452 |
| 448 if (version == 'U2F_V2') { | 453 if (version == 'U2F_V2') { |
| 449 var modifiedChallenge = {}; | 454 var modifiedChallenge = {}; |
| 450 for (var k in enrollChallenge) { | 455 for (var k in enrollChallenge) { |
| 451 modifiedChallenge[k] = enrollChallenge[k]; | 456 modifiedChallenge[k] = enrollChallenge[k]; |
| 452 } | 457 } |
| 453 // V2 enroll responses contain signatures over a browser data object, | 458 // V2 enroll responses contain signatures over a browser data object, |
| 454 // which we're constructing here. The browser data object contains, among | 459 // which we're constructing here. The browser data object contains, among |
| 455 // other things, the server challenge. | 460 // other things, the server challenge. |
| 456 var serverChallenge = enrollChallenge['challenge']; | 461 var serverChallenge = enrollChallenge['challenge']; |
| 457 var browserData = makeEnrollBrowserData( | 462 var browserData = makeEnrollBrowserData( |
| 458 serverChallenge, this.sender_.origin, this.sender_.tlsChannelId); | 463 serverChallenge, this.sender_.origin, this.sender_.tlsChannelId); |
| 459 // Replace the challenge with the hash of the browser data. | 464 // Replace the challenge with the hash of the browser data. |
| 460 modifiedChallenge['challenge'] = | 465 modifiedChallenge['challenge'] = |
| 461 B64_encode(sha256HashOfString(browserData)); | 466 B64_encode(sha256HashOfString(browserData)); |
| 462 this.browserData_[version] = | 467 this.browserData_[version] = B64_encode(UTIL_StringToBytes(browserData)); |
| 463 B64_encode(UTIL_StringToBytes(browserData)); | |
| 464 challenges.push(Enroller.encodeEnrollChallenge_( | 468 challenges.push(Enroller.encodeEnrollChallenge_( |
| 465 /** @type {EnrollChallenge} */ (modifiedChallenge), opt_appId)); | 469 /** @type {EnrollChallenge} */ (modifiedChallenge), opt_appId)); |
| 466 } else { | 470 } else { |
| 467 challenges.push( | 471 challenges.push( |
| 468 Enroller.encodeEnrollChallenge_(enrollChallenge, opt_appId)); | 472 Enroller.encodeEnrollChallenge_(enrollChallenge, opt_appId)); |
| 469 } | 473 } |
| 470 } | 474 } |
| 471 return challenges; | 475 return challenges; |
| 472 }; | 476 }; |
| 473 | 477 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 495 * @param {function(boolean)} cb Called with the result of the check. | 499 * @param {function(boolean)} cb Called with the result of the check. |
| 496 * @param {boolean} result Whether the origin could claim the app ids. | 500 * @param {boolean} result Whether the origin could claim the app ids. |
| 497 * @private | 501 * @private |
| 498 */ | 502 */ |
| 499 Enroller.prototype.originChecked_ = function(appIds, cb, result) { | 503 Enroller.prototype.originChecked_ = function(appIds, cb, result) { |
| 500 if (!result) { | 504 if (!result) { |
| 501 this.notifyError_({errorCode: ErrorCodes.BAD_REQUEST}); | 505 this.notifyError_({errorCode: ErrorCodes.BAD_REQUEST}); |
| 502 return; | 506 return; |
| 503 } | 507 } |
| 504 var appIdChecker = FACTORY_REGISTRY.getAppIdCheckerFactory().create(); | 508 var appIdChecker = FACTORY_REGISTRY.getAppIdCheckerFactory().create(); |
| 505 appIdChecker. | 509 appIdChecker |
| 506 checkAppIds( | 510 .checkAppIds( |
| 507 this.timer_.clone(), this.sender_.origin, appIds, this.allowHttp_, | 511 this.timer_.clone(), this.sender_.origin, appIds, this.allowHttp_, |
| 508 this.logMsgUrl_) | 512 this.logMsgUrl_) |
| 509 .then(cb); | 513 .then(cb); |
| 510 }; | 514 }; |
| 511 | 515 |
| 512 /** Closes this enroller. */ | 516 /** Closes this enroller. */ |
| 513 Enroller.prototype.close = function() { | 517 Enroller.prototype.close = function() { |
| 514 if (this.handler_) { | 518 if (this.handler_) { |
| 515 this.handler_.close(); | 519 this.handler_.close(); |
| 516 this.handler_ = null; | 520 this.handler_ = null; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 531 this.errorCb_(error); | 535 this.errorCb_(error); |
| 532 }; | 536 }; |
| 533 | 537 |
| 534 /** | 538 /** |
| 535 * Notifies the caller of success with the provided response data. | 539 * Notifies the caller of success with the provided response data. |
| 536 * @param {string} u2fVersion Protocol version | 540 * @param {string} u2fVersion Protocol version |
| 537 * @param {string} info Response data | 541 * @param {string} info Response data |
| 538 * @param {string|undefined} opt_browserData Browser data used | 542 * @param {string|undefined} opt_browserData Browser data used |
| 539 * @private | 543 * @private |
| 540 */ | 544 */ |
| 541 Enroller.prototype.notifySuccess_ = | 545 Enroller.prototype.notifySuccess_ = function( |
| 542 function(u2fVersion, info, opt_browserData) { | 546 u2fVersion, info, opt_browserData) { |
| 543 if (this.done_) | 547 if (this.done_) |
| 544 return; | 548 return; |
| 545 this.close(); | 549 this.close(); |
| 546 this.done_ = true; | 550 this.done_ = true; |
| 547 this.successCb_(u2fVersion, info, opt_browserData); | 551 this.successCb_(u2fVersion, info, opt_browserData); |
| 548 }; | 552 }; |
| 549 | 553 |
| 550 /** | 554 /** |
| 551 * Called by the helper upon completion. | 555 * Called by the helper upon completion. |
| 552 * @param {EnrollHelperReply} reply The result of the enroll request. | 556 * @param {EnrollHelperReply} reply The result of the enroll request. |
| 553 * @private | 557 * @private |
| 554 */ | 558 */ |
| 555 Enroller.prototype.helperComplete_ = function(reply) { | 559 Enroller.prototype.helperComplete_ = function(reply) { |
| 556 if (reply.code) { | 560 if (reply.code) { |
| 557 var reportedError = mapDeviceStatusCodeToU2fError(reply.code); | 561 var reportedError = mapDeviceStatusCodeToU2fError(reply.code); |
| 558 console.log(UTIL_fmt('helper reported ' + reply.code.toString(16) + | 562 console.log(UTIL_fmt( |
| 559 ', returning ' + reportedError.errorCode)); | 563 'helper reported ' + reply.code.toString(16) + ', returning ' + |
| 564 reportedError.errorCode)); |
| 560 this.notifyError_(reportedError); | 565 this.notifyError_(reportedError); |
| 561 } else { | 566 } else { |
| 562 console.log(UTIL_fmt('Gnubby enrollment succeeded!!!!!')); | 567 console.log(UTIL_fmt('Gnubby enrollment succeeded!!!!!')); |
| 563 var browserData; | 568 var browserData; |
| 564 | 569 |
| 565 if (reply.version == 'U2F_V2') { | 570 if (reply.version == 'U2F_V2') { |
| 566 // For U2F_V2, the challenge sent to the gnubby is modified to be the hash | 571 // For U2F_V2, the challenge sent to the gnubby is modified to be the hash |
| 567 // of the browser data. Include the browser data. | 572 // of the browser data. Include the browser data. |
| 568 browserData = this.browserData_[reply.version]; | 573 browserData = this.browserData_[reply.version]; |
| 569 } | 574 } |
| 570 | 575 |
| 571 this.notifySuccess_(/** @type {string} */ (reply.version), | 576 this.notifySuccess_( |
| 572 /** @type {string} */ (reply.enrollData), | 577 /** @type {string} */ (reply.version), |
| 573 browserData); | 578 /** @type {string} */ (reply.enrollData), browserData); |
| 574 } | 579 } |
| 575 }; | 580 }; |
| OLD | NEW |