| Index: chrome/browser/resources/cryptotoken/gnubby-u2f.js
|
| diff --git a/chrome/browser/resources/cryptotoken/gnubby-u2f.js b/chrome/browser/resources/cryptotoken/gnubby-u2f.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8e6ef1d032bb9569a76d0f4b8c7764e679ec05ed
|
| --- /dev/null
|
| +++ b/chrome/browser/resources/cryptotoken/gnubby-u2f.js
|
| @@ -0,0 +1,88 @@
|
| +// Copyright (c) 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +/**
|
| + * @fileoverview usbGnubby methods related to U2F support.
|
| + */
|
| +'use strict';
|
| +
|
| +// Commands and flags of the Gnubby applet at
|
| +// //depot/google3/security/tools/gnubby/applet/gnubby/src/pkgGnubby/Gnubby.java
|
| +usbGnubby.U2F_ENROLL = 0x01;
|
| +usbGnubby.U2F_SIGN = 0x02;
|
| +usbGnubby.U2F_VERSION = 0x03;
|
| +
|
| +usbGnubby.APPLET_VERSION = 0x11; // First 3 bytes are applet version.
|
| +
|
| +// APDU.P1 flags
|
| +usbGnubby.P1_TUP_REQUIRED = 0x01;
|
| +usbGnubby.P1_TUP_CONSUME = 0x02;
|
| +usbGnubby.P1_TUP_TESTONLY = 0x04;
|
| +usbGnubby.P1_INDIVIDUAL_KEY = 0x80;
|
| +
|
| +usbGnubby.prototype.enroll = function(challenge, appIdHash, cb) {
|
| + var apdu = new Uint8Array(
|
| + [0x00,
|
| + usbGnubby.U2F_ENROLL,
|
| + usbGnubby.P1_TUP_REQUIRED | usbGnubby.P1_TUP_CONSUME |
|
| + usbGnubby.P1_INDIVIDUAL_KEY,
|
| + 0x00, 0x00, 0x00,
|
| + challenge.length + appIdHash.length]);
|
| + // TODO(mschilder): only use P1_INDIVIDUAL_KEY for corp appIdHashes.
|
| + var u8 = new Uint8Array(apdu.length + challenge.length +
|
| + appIdHash.length + 2);
|
| + for (var i = 0; i < apdu.length; ++i) u8[i] = apdu[i];
|
| + for (var i = 0; i < challenge.length; ++i) u8[i + apdu.length] =
|
| + challenge[i];
|
| + for (var i = 0; i < appIdHash.length; ++i) {
|
| + u8[i + apdu.length + challenge.length] = appIdHash[i];
|
| + }
|
| + this.apduReply_(u8.buffer, cb);
|
| +};
|
| +
|
| +usbGnubby.prototype.sign = function(challengeHash, appIdHash, keyHandle, cb,
|
| + opt_nowink) {
|
| + var apdu = new Uint8Array(
|
| + [0x00,
|
| + usbGnubby.U2F_SIGN,
|
| + usbGnubby.P1_TUP_REQUIRED | usbGnubby.P1_TUP_CONSUME,
|
| + 0x00, 0x00, 0x00,
|
| + challengeHash.length + appIdHash.length + keyHandle.length]);
|
| + if (opt_nowink) {
|
| + // A signature request that does not want winking.
|
| + // These are used during enroll to figure out whether a gnubby was already
|
| + // enrolled.
|
| + // Tell applet to not actually produce a signature, even
|
| + // if already touched.
|
| + apdu[2] |= usbGnubby.P1_TUP_TESTONLY;
|
| + }
|
| + var u8 = new Uint8Array(apdu.length + challengeHash.length +
|
| + appIdHash.length + keyHandle.length + 2);
|
| + for (var i = 0; i < apdu.length; ++i) u8[i] = apdu[i];
|
| + for (var i = 0; i < challengeHash.length; ++i) u8[i + apdu.length] =
|
| + challengeHash[i];
|
| + for (var i = 0; i < appIdHash.length; ++i) {
|
| + u8[i + apdu.length + challengeHash.length] = appIdHash[i];
|
| + }
|
| + for (var i = 0; i < keyHandle.length; ++i) {
|
| + u8[i + apdu.length + challengeHash.length + appIdHash.length] =
|
| + keyHandle[i];
|
| + }
|
| + this.apduReply_(u8.buffer, cb, opt_nowink);
|
| +};
|
| +
|
| +usbGnubby.prototype.version = function(cb) {
|
| + if (!cb) cb = usbGnubby.defaultCallback;
|
| + var apdu = new Uint8Array([0x00, usbGnubby.U2F_VERSION, 0x00, 0x00, 0x00,
|
| + 0x00, 0x00, 0x00, 0x00]);
|
| + this.apduReply_(apdu.buffer, function(rc, data) {
|
| + if (rc == 0x6d00) {
|
| + // Command not implemented. Pretend this is v1.
|
| + var v1 = new Uint8Array(UTIL_StringToBytes('U2F_V1'));
|
| + cb(-llGnubby.OK, v1.buffer);
|
| + } else {
|
| + cb(rc, data);
|
| + }
|
| + });
|
| +};
|
|
|