OLD | NEW |
(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 usbGnubby methods related to U2F support. |
| 7 */ |
| 8 'use strict'; |
| 9 |
| 10 // Commands and flags of the Gnubby applet at |
| 11 // //depot/google3/security/tools/gnubby/applet/gnubby/src/pkgGnubby/Gnubby.java |
| 12 usbGnubby.U2F_ENROLL = 0x01; |
| 13 usbGnubby.U2F_SIGN = 0x02; |
| 14 usbGnubby.U2F_VERSION = 0x03; |
| 15 |
| 16 usbGnubby.APPLET_VERSION = 0x11; // First 3 bytes are applet version. |
| 17 |
| 18 // APDU.P1 flags |
| 19 usbGnubby.P1_TUP_REQUIRED = 0x01; |
| 20 usbGnubby.P1_TUP_CONSUME = 0x02; |
| 21 usbGnubby.P1_TUP_TESTONLY = 0x04; |
| 22 usbGnubby.P1_INDIVIDUAL_KEY = 0x80; |
| 23 |
| 24 usbGnubby.prototype.enroll = function(challenge, appIdHash, cb) { |
| 25 var apdu = new Uint8Array( |
| 26 [0x00, |
| 27 usbGnubby.U2F_ENROLL, |
| 28 usbGnubby.P1_TUP_REQUIRED | usbGnubby.P1_TUP_CONSUME | |
| 29 usbGnubby.P1_INDIVIDUAL_KEY, |
| 30 0x00, 0x00, 0x00, |
| 31 challenge.length + appIdHash.length]); |
| 32 // TODO(mschilder): only use P1_INDIVIDUAL_KEY for corp appIdHashes. |
| 33 var u8 = new Uint8Array(apdu.length + challenge.length + |
| 34 appIdHash.length + 2); |
| 35 for (var i = 0; i < apdu.length; ++i) u8[i] = apdu[i]; |
| 36 for (var i = 0; i < challenge.length; ++i) u8[i + apdu.length] = |
| 37 challenge[i]; |
| 38 for (var i = 0; i < appIdHash.length; ++i) { |
| 39 u8[i + apdu.length + challenge.length] = appIdHash[i]; |
| 40 } |
| 41 this.apduReply_(u8.buffer, cb); |
| 42 }; |
| 43 |
| 44 usbGnubby.prototype.sign = function(challengeHash, appIdHash, keyHandle, cb, |
| 45 opt_nowink) { |
| 46 var apdu = new Uint8Array( |
| 47 [0x00, |
| 48 usbGnubby.U2F_SIGN, |
| 49 usbGnubby.P1_TUP_REQUIRED | usbGnubby.P1_TUP_CONSUME, |
| 50 0x00, 0x00, 0x00, |
| 51 challengeHash.length + appIdHash.length + keyHandle.length]); |
| 52 if (opt_nowink) { |
| 53 // A signature request that does not want winking. |
| 54 // These are used during enroll to figure out whether a gnubby was already |
| 55 // enrolled. |
| 56 // Tell applet to not actually produce a signature, even |
| 57 // if already touched. |
| 58 apdu[2] |= usbGnubby.P1_TUP_TESTONLY; |
| 59 } |
| 60 var u8 = new Uint8Array(apdu.length + challengeHash.length + |
| 61 appIdHash.length + keyHandle.length + 2); |
| 62 for (var i = 0; i < apdu.length; ++i) u8[i] = apdu[i]; |
| 63 for (var i = 0; i < challengeHash.length; ++i) u8[i + apdu.length] = |
| 64 challengeHash[i]; |
| 65 for (var i = 0; i < appIdHash.length; ++i) { |
| 66 u8[i + apdu.length + challengeHash.length] = appIdHash[i]; |
| 67 } |
| 68 for (var i = 0; i < keyHandle.length; ++i) { |
| 69 u8[i + apdu.length + challengeHash.length + appIdHash.length] = |
| 70 keyHandle[i]; |
| 71 } |
| 72 this.apduReply_(u8.buffer, cb, opt_nowink); |
| 73 }; |
| 74 |
| 75 usbGnubby.prototype.version = function(cb) { |
| 76 if (!cb) cb = usbGnubby.defaultCallback; |
| 77 var apdu = new Uint8Array([0x00, usbGnubby.U2F_VERSION, 0x00, 0x00, 0x00, |
| 78 0x00, 0x00, 0x00, 0x00]); |
| 79 this.apduReply_(apdu.buffer, function(rc, data) { |
| 80 if (rc == 0x6d00) { |
| 81 // Command not implemented. Pretend this is v1. |
| 82 var v1 = new Uint8Array(UTIL_StringToBytes('U2F_V1')); |
| 83 cb(-llGnubby.OK, v1.buffer); |
| 84 } else { |
| 85 cb(rc, data); |
| 86 } |
| 87 }); |
| 88 }; |
OLD | NEW |