From f2cd670d7e76f7daad83fc7dc4b5317c383f37a5 Mon Sep 17 00:00:00 2001 From: Konrad Rosenbaum Date: Wed, 19 Nov 2014 22:42:23 +0100 Subject: [PATCH] initial tests and drafts --- .gitignore | 4 + .gitmodules | 3 + COPYING.GPL | 676 +++++++++++++++++++++++++++++++++++++++++++ COPYING.MIT | 19 ++ README | 30 ++ daemon/hidtoken/u2f.h | 103 +++++++ daemon/hidtoken/u2f_hid.h | 129 +++++++++ doc/arch-diagram.odg | Bin 0 -> 15643 bytes doc/arch-diagram.png | Bin 0 -> 32043 bytes doc/gpl3.html | 694 +++++++++++++++++++++++++++++++++++++++++++++ doc/index.html | 42 +++ doc/mit.html | 26 ++ hidapi | 1 + libfido/libfido.h | 128 +++++++++ testapp/Makefile | 20 ++ testapp/fidodevice.c | 151 ++++++++++ testapp/fidodevice.h | 27 ++ testapp/hidapi_report.c | 155 ++++++++++ testapp/hidapi_report.h | 8 + testapp/hidapi_usage.c | 125 ++++++++ testapp/hidapi_usage.h | 5 + testapp/main.c | 35 +++ testapp/scanfordev.c | 135 +++++++++ testapp/scanfordev.h | 2 + testapp/u2f.h | 103 +++++++ testapp/u2f_hid.h | 129 +++++++++ 26 files changed, 2750 insertions(+), 0 deletions(-) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 COPYING.GPL create mode 100644 COPYING.MIT create mode 100644 README create mode 100644 daemon/hidtoken/u2f.h create mode 100644 daemon/hidtoken/u2f_hid.h create mode 100644 doc/arch-diagram.odg create mode 100644 doc/arch-diagram.png create mode 100644 doc/gpl3.html create mode 100644 doc/index.html create mode 100644 doc/mit.html create mode 160000 hidapi create mode 100644 libfido/libfido.h create mode 100644 testapp/Makefile create mode 100644 testapp/fidodevice.c create mode 100644 testapp/fidodevice.h create mode 100644 testapp/hidapi_report.c create mode 100644 testapp/hidapi_report.h create mode 100644 testapp/hidapi_usage.c create mode 100644 testapp/hidapi_usage.h create mode 100644 testapp/main.c create mode 100644 testapp/scanfordev.c create mode 100644 testapp/scanfordev.h create mode 100644 testapp/u2f.h create mode 100644 testapp/u2f_hid.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c6ce447 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +*.obj +moc_* +testapp/testapp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..340344d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "hidapi"] + path = hidapi + url = git://github.com/signal11/hidapi.git diff --git a/COPYING.GPL b/COPYING.GPL new file mode 100644 index 0000000..4432540 --- /dev/null +++ b/COPYING.GPL @@ -0,0 +1,676 @@ + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + diff --git a/COPYING.MIT b/COPYING.MIT new file mode 100644 index 0000000..bca296b --- /dev/null +++ b/COPYING.MIT @@ -0,0 +1,19 @@ +Copyright (c) 2014 Konrad Rosenbaum + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..d3cc507 --- /dev/null +++ b/README @@ -0,0 +1,30 @@ +README for FIDO Tools +====================== + +(c) Konrad Rosenbaum , 2014 +FIDO tools are protected under the GPL version 3 or at your option any newer, +see COPYING.GPL for details. +As an exception libfido is protected under the much more permissive MIT +license, see COPYING.MIT for details. + +FIDO Tools provide local facilities to interface with FIDO second factor +authentication tokens. + +WARNING +-------- + +THIS IS WORK IN PROGRESS IN ITS EARLIEST STAGES. +DO NOT EXPECT IT TO DO ANYTHING USEFUL OR EVEN HARMLESS! +IT MAY EVEN CRASH YOUR TOKEN OR EAT YOUR SYSTEM. + +Documentation +-------------- + +See doc/index.html for instructions on how to use and build FIDO tools. + + +Preliminary Tests +------------------ + +The testapp directory contains code for testing out features - it is not +very functional or supposed to be part of the final product. diff --git a/daemon/hidtoken/u2f.h b/daemon/hidtoken/u2f.h new file mode 100644 index 0000000..6d447c2 --- /dev/null +++ b/daemon/hidtoken/u2f.h @@ -0,0 +1,103 @@ +// Common U2F raw message format header - Review Draft +// 2014-10-08 +// Editor: Jakob Ehrensvard, Yubico, jakob@yubico.com + +#ifndef __U2F_H_INCLUDED__ +#define __U2F_H_INCLUDED__ + +#ifdef _MSC_VER // Windows +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long int uint64_t; +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// General constants +#define U2F_EC_KEY_SIZE 32 // EC key size in bytes +#define U2F_EC_POINT_SIZE ((U2F_EC_KEY_SIZE * 2) + 1) // Size of EC point +#define U2F_MAX_KH_SIZE 128 // Max size of key handle +#define U2F_MAX_ATT_CERT_SIZE 2048 // Max size of attestation certificate +#define U2F_MAX_EC_SIG_SIZE 72 // Max size of DER coded EC signature +#define U2F_CTR_SIZE 4 // Size of counter field +#define U2F_APPID_SIZE 32 // Size of application id +#define U2F_CHAL_SIZE 32 // Size of challenge + +#define ENC_SIZE(x) ((x + 7)& 0xfff8) + +// EC (uncompressed) point + +#define U2F_POINT_UNCOMPRESSED 0x04 // Uncompressed point format + +typedef struct { + uint8_t pointFormat; // Point type + uint8_t x[U2F_EC_KEY_SIZE]; // X-value + uint8_t y[U2F_EC_KEY_SIZE]; // Y-value +} U2F_EC_POINT; + +// U2F native commands +#define U2F_REGISTER 0x01 // Registration command +#define U2F_AUTHENTICATE 0x02 // Authenticate/sign command +#define U2F_VERSION 0x03 // Read version string command + +#define U2F_VENDOR_FIRST 0xc0 // First vendor defined command +#define U2F_VENDOR_LAST 0xff // Last vendor defined command + +// U2F_CMD_REGISTER command defines + +#define U2F_REGISTER_ID 0x05 // Version 2 registration identifier +#define U2F_REGISTER_HASH_ID 0x00 // Version 2 hash identintifier + +typedef struct { + uint8_t chal[U2F_CHAL_SIZE]; // Challenge + uint8_t appId[U2F_APPID_SIZE]; // Application id +} U2F_REGISTER_REQ; + +typedef struct { + uint8_t registerId; // Registration identifier (U2F_REGISTER_ID_V2) + U2F_EC_POINT pubKey; // Generated public key + uint8_t keyHandleLen; // Length of key handle + uint8_t keyHandleCertSig[ + U2F_MAX_KH_SIZE + // Key handle + U2F_MAX_ATT_CERT_SIZE + // Attestation certificate + U2F_MAX_EC_SIG_SIZE]; // Registration signature +} U2F_REGISTER_RESP; + +// U2F_CMD_AUTHENTICATE command defines + +// Authentication control byte + +#define U2F_AUTH_ENFORCE 0x03 // Enforce user presence and sign +#define U2F_AUTH_CHECK_ONLY 0x07 // Check only +#define U2F_AUTH_FLAG_TUP 0x01 // Test of user presence set + +typedef struct { + uint8_t chal[U2F_CHAL_SIZE]; // Challenge + uint8_t appId[U2F_APPID_SIZE]; // Application id + uint8_t keyHandleLen; // Length of key handle + uint8_t keyHandle[U2F_MAX_KH_SIZE]; // Key handle +} U2F_AUTHENTICATE_REQ; + +typedef struct { + uint8_t flags; // U2F_AUTH_FLAG_ values + uint8_t ctr[U2F_CTR_SIZE]; // Counter field (big-endian) + uint8_t sig[U2F_MAX_EC_SIG_SIZE]; // Signature +} U2F_AUTHENTICATE_RESP; + +// Command status responses +#define U2F_SW_NO_ERROR 0x9000 // SW_NO_ERROR +#define U2F_SW_WRONG_DATA 0x6984 // SW_WRONG_DATA +#define U2F_SW_CONDITIONS_NOT_SATISFIED 0x6985 // SW_CONDITIONS_NOT_SATISFIED +#define U2F_SW_INS_NOT_SUPPORTED 0x6d00 // SW_INS_NOT_SUPPORTED + + +#ifdef __cplusplus +} +#endif + +#endif // __U2F_H_INCLUDED__ diff --git a/daemon/hidtoken/u2f_hid.h b/daemon/hidtoken/u2f_hid.h new file mode 100644 index 0000000..ed7b63a --- /dev/null +++ b/daemon/hidtoken/u2f_hid.h @@ -0,0 +1,129 @@ +// Common U2F HID transport header - Review Draft +// 2014-10-08 +// Editor: Jakob Ehrensvard, Yubico, jakob@yubico.com + +#ifndef __U2FHID_H_INCLUDED__ +#define __U2FHID_H_INCLUDED__ + +#ifdef _MSC_VER // Windows +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long int uint64_t; +#else +#include +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +// Size of HID reports + +#define HID_RPT_SIZE 64 // Default size of raw HID report + +// Frame layout - command- and continuation frames + +#define CID_BROADCAST 0xffffffff // Broadcast channel id + +#define TYPE_MASK 0x80 // Frame type mask +#define TYPE_INIT 0x80 // Initial frame identifier +#define TYPE_CONT 0x00 // Continuation frame identifier + +typedef struct { + uint32_t cid; // Channel identifier + union { + uint8_t type; // Frame type - b7 defines type + struct { + uint8_t cmd; // Command - b7 set + uint8_t bcnth; // Message byte count - high part + uint8_t bcntl; // Message byte count - low part + uint8_t data[HID_RPT_SIZE - 7]; // Data payload + } init; + struct { + uint8_t seq; // Sequence number - b7 cleared + uint8_t data[HID_RPT_SIZE - 5]; // Data payload + }cont; + }; +} U2FHID_FRAME; + +#define FRAME_TYPE(f) ((f).type & TYPE_MASK) +#define FRAME_CMD(f) ((f).init.cmd & ~TYPE_MASK) +#define MSG_LEN(f) ((f).init.bcnth*256 + (f).init.bcntl) +#define FRAME_SEQ(f) ((f).cont.seq & ~TYPE_MASK) + +// HID usage- and usage-page definitions + +#define FIDO_USAGE_PAGE 0xf1d0 // FIDO alliance HID usage page +#define FIDO_USAGE_U2FHID 0x01 // U2FHID usage for top-level collection +#define FIDO_USAGE_DATA_IN 0x20 // Raw IN data report +#define FIDO_USAGE_DATA_OUT 0x21 // Raw OUT data report + +// General constants + +#define U2FHID_IF_VERSION 2 // Current interface implementation version +#define U2FHID_TRANS_TIMEOUT 3000 // Default message timeout in ms + +// U2FHID native commands + +#define U2FHID_PING (TYPE_INIT | 0x01) // Echo data through local processor only +#define U2FHID_MSG (TYPE_INIT | 0x03) // Send U2F message frame +#define U2FHID_LOCK (TYPE_INIT | 0x04) // Send lock channel command +#define U2FHID_INIT (TYPE_INIT | 0x06) // Channel initialization +#define U2FHID_WINK (TYPE_INIT | 0x08) // Send device identification wink +#define U2FHID_SYNC (TYPE_INIT | 0x3c) // Protocol resync command +#define U2FHID_ERROR (TYPE_INIT | 0x3f) // Error response + +#define U2FHID_VENDOR_FIRST (TYPE_INIT | 0x40) // First vendor defined command +#define U2FHID_VENDOR_LAST (TYPE_INIT | 0x7f) // Last vendor defined command + + +// U2FHID_INIT command defines + +#define INIT_NONCE_SIZE 8 // Size of channel initialization challenge +#define CAPFLAG_WINK 0x01 // Device supports WINK command + + +typedef struct { + uint8_t nonce[INIT_NONCE_SIZE]; // Client application nonce +} U2FHID_INIT_REQ; + +typedef struct { + uint8_t nonce[INIT_NONCE_SIZE]; // Client application nonce + uint32_t cid; // Channel identifier + uint8_t versionInterface; // Interface version + uint8_t versionMajor; // Major version number + uint8_t versionMinor; // Minor version number + uint8_t versionBuild; // Build version number + uint8_t capFlags; // Capabilities flags +} U2FHID_INIT_RESP; + +// U2FHID_SYNC command defines + +typedef struct { + uint8_t nonce; // Client application nonce +} U2FHID_SYNC_REQ; + +typedef struct { + uint8_t nonce; // Client application nonce +} U2FHID_SYNC_RESP; + +// Low-level error codes. Return as negatives. + +#define ERR_NONE 0x00 // No error +#define ERR_INVALID_CMD 0x01 // Invalid command +#define ERR_INVALID_PAR 0x02 // Invalid parameter +#define ERR_INVALID_LEN 0x03 // Invalid message length +#define ERR_INVALID_SEQ 0x04 // Invalid message sequencing +#define ERR_MSG_TIMEOUT 0x05 // Message has timed out +#define ERR_CHANNEL_BUSY 0x06 // Channel busy +#define ERR_LOCK_REQUIRED 0x0a // Command requires channel lock +#define ERR_SYNC_FAIL 0x0b // SYNC command failed +#define ERR_OTHER 0x7f // Other unspecified error + +#ifdef __cplusplus +} +#endif + +#endif // __U2FHID_H_INCLUDED__ diff --git a/doc/arch-diagram.odg b/doc/arch-diagram.odg new file mode 100644 index 0000000000000000000000000000000000000000..a26c0be2ad0832b90e13071e8f9af68504182a7d GIT binary patch literal 15643 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 literal 0 HcmV?d00001 diff --git a/doc/gpl3.html b/doc/gpl3.html new file mode 100644 index 0000000..d64890f --- /dev/null +++ b/doc/gpl3.html @@ -0,0 +1,694 @@ + + + + + GNU General Public License - GNU Project - Free Software Foundation (FSF) + + + +

GNU GENERAL PUBLIC LICENSE

+

Version 3, 29 June 2007

+ +

Copyright © 2007 Free Software Foundation, Inc. + <http://fsf.org/>

+ Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed.

+ +

Preamble

+ +

The GNU General Public License is a free, copyleft license for +software and other kinds of works.

+ +

The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too.

+ +

When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things.

+ +

To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others.

+ +

For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights.

+ +

Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it.

+ +

For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions.

+ +

Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users.

+ +

Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free.

+ +

The precise terms and conditions for copying, distribution and +modification follow.

+ +

TERMS AND CONDITIONS

+ +

0. Definitions.

+ +

“This License” refers to version 3 of the GNU General Public License.

+ +

“Copyright” also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks.

+ +

“The Program” refers to any copyrightable work licensed under this +License. Each licensee is addressed as “you”. “Licensees” and +“recipients” may be individuals or organizations.

+ +

To “modify” a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a “modified version” of the +earlier work or a work “based on” the earlier work.

+ +

A “covered work” means either the unmodified Program or a work based +on the Program.

+ +

To “propagate” a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well.

+ +

To “convey” a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying.

+ +

An interactive user interface displays “Appropriate Legal Notices” +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion.

+ +

1. Source Code.

+ +

The “source code” for a work means the preferred form of the work +for making modifications to it. “Object code” means any non-source +form of a work.

+ +

A “Standard Interface” means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language.

+ +

The “System Libraries” of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +“Major Component”, in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it.

+ +

The “Corresponding Source” for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work.

+ +

The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source.

+ +

The Corresponding Source for a work in source code form is that +same work.

+ +

2. Basic Permissions.

+ +

All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law.

+ +

You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you.

+ +

Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary.

+ +

3. Protecting Users' Legal Rights From Anti-Circumvention Law.

+ +

No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures.

+ +

When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures.

+ +

4. Conveying Verbatim Copies.

+ +

You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program.

+ +

You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee.

+ +

5. Conveying Modified Source Versions.

+ +

You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions:

+ +
    +
  • a) The work must carry prominent notices stating that you modified + it, and giving a relevant date.
  • + +
  • b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + “keep intact all notices”.
  • + +
  • c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it.
  • + +
  • d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so.
  • +
+ +

A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +“aggregate” if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate.

+ +

6. Conveying Non-Source Forms.

+ +

You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways:

+ +
    +
  • a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange.
  • + +
  • b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge.
  • + +
  • c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b.
  • + +
  • d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements.
  • + +
  • e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d.
  • +
+ +

A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work.

+ +

A “User Product” is either (1) a “consumer product”, which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, “normally used” refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product.

+ +

“Installation Information” for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made.

+ +

If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM).

+ +

The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network.

+ +

Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying.

+ +

7. Additional Terms.

+ +

“Additional permissions” are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions.

+ +

When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission.

+ +

Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms:

+ +
    +
  • a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or
  • + +
  • b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or
  • + +
  • c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or
  • + +
  • d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or
  • + +
  • e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or
  • + +
  • f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors.
  • +
+ +

All other non-permissive additional terms are considered “further +restrictions” within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying.

+ +

If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms.

+ +

Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way.

+ +

8. Termination.

+ +

You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11).

+ +

However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation.

+ +

Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice.

+ +

Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10.

+ +

9. Acceptance Not Required for Having Copies.

+ +

You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so.

+ +

10. Automatic Licensing of Downstream Recipients.

+ +

Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License.

+ +

An “entity transaction” is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts.

+ +

You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it.

+ +

11. Patents.

+ +

A “contributor” is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's “contributor version”.

+ +

A contributor's “essential patent claims” are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, “control” includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License.

+ +

Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version.

+ +

In the following three paragraphs, a “patent license” is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To “grant” such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party.

+ +

If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. “Knowingly relying” means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid.

+ +

If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it.

+ +

A patent license is “discriminatory” if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007.

+ +

Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law.

+ +

12. No Surrender of Others' Freedom.

+ +

If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program.

+ +

13. Use with the GNU Affero General Public License.

+ +

Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such.

+ +

14. Revised Versions of this License.

+ +

The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns.

+ +

Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License “or any later version” applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation.

+ +

If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program.

+ +

Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version.

+ +

15. Disclaimer of Warranty.

+ +

THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

+ +

16. Limitation of Liability.

+ +

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES.

+ +

17. Interpretation of Sections 15 and 16.

+ +

If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee.

+ +

END OF TERMS AND CONDITIONS

+ +

How to Apply These Terms to Your New Programs

+ +

If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms.

+ +

To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the “copyright” line and a pointer to where the full notice is found.

+ +
    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+ +

Also add information on how to contact you by electronic and paper mail.

+ +

If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode:

+ +
    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+ +

The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an “about box”.

+ +

You should also get your employer (if you work as a programmer) or school, +if any, to sign a “copyright disclaimer” for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>.

+ +

The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>.

+ + diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..b60df14 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,42 @@ + +FIDO Tools + +

FIDO Tools

+ +

© Konrad Rosenbaum <konrad@silmor.de>, 2014
+FIDO tools are protected under the GPL version 3, or at your option any newer.
+As an exception libfido is protected under the much more permissive MIT license.

+ +

FIDO Tools provide local facilities to interface with FIDO second factor +authentication tokens as specified by the FIDO Alliance.

+ +

Parts of FIDO Tools

+ +

+ +

FIDO Daemon - a program working in the background accessing the FIDO tokens, generating, enrolling, and verifying keys and services. It acts as the actual backend for all other utilities.

+ +

LibFIDO - a thin library layer that is linked into client programs, which accesses the FIDO daemon for the actual work.

+ +

libQtFido - the Qt5 based version of the library.

+ +

PAM-FIDO - a PAM module that enables systems to authenticate users against FIDO tokens.

+ +

FidoCtl - a utility to access all FIDO Daemon functions from scripts. For example to enroll keys for PAM.

+ +

FidoUi - a GUI to access FIDO functions (based on Qt5 and libQtFido).

+ +

Building and Development

+ +
    +
  • Building FIDO Tools
  • +
  • Source Docu:
      +
    • libFIDO - how to use FIDO Tools in your own programs
    • +
    • FIDO Daemon - architecture of the main program
    • +
    • PAM-FIDO - the FIDO based PAM module
    • +
    • libQtFido - the Qt5 module for FIDO
    • +
  • +
+ + + \ No newline at end of file diff --git a/doc/mit.html b/doc/mit.html new file mode 100644 index 0000000..e30e02e --- /dev/null +++ b/doc/mit.html @@ -0,0 +1,26 @@ + +MIT License + +
+Copyright (c) 2014 Konrad Rosenbaum <konrad@silmor.de>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+ + \ No newline at end of file diff --git a/hidapi b/hidapi new file mode 160000 index 0000000..d17db57 --- /dev/null +++ b/hidapi @@ -0,0 +1 @@ +Subproject commit d17db57b9d4354752e0af42f5f33007a42ef2906 diff --git a/libfido/libfido.h b/libfido/libfido.h new file mode 100644 index 0000000..391b845 --- /dev/null +++ b/libfido/libfido.h @@ -0,0 +1,128 @@ +/* +LibFIDO header file + +Copyright (c) 2014 Konrad Rosenbaum + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#ifndef LIBFIDO_H_ +#define LIBFIDO_H_ + + +/// successful request +#define FIDO_SUCCESS 0 +/// there was no connection or the connection was lost, call libfido_init() +#define FIDO_NOCONN -1 +/// there was an I/O error, unable to send/receive data +#define FIDO_IOERR -2 +/// the request was rejected by the daemon +#define FIDO_REJECTED -3 + +/// Initialize the library: establishes a connection to the FIDO daemon. +/// \returns 0 on success +int libfido_init(); + +/// Close the connection to the daemon, free all resources. +void libfido_done(); + +enum libfido_client_request_type +{ + ///checks that the token is still plugged in + libfido_TokenPresent=1, + ///actually sends a ping packet to the token and veries it still reacts + libfido_PingToken=2, + ///enrolls an application with the token, generates a new key + libfido_EnrollToken=10, + ///verify that a key is present on one of the attached tokens, does not verify user presence + libfido_CheckKeyExists=20, + ///verifies that a key is present and valid as well as that the user is present + libfido_VerifyKeyAndPresence=21, +}; + +enum libfido_result_type +{ + ///the verification failed completely + libfido_Failed=0, + ///the key was verified as valid, but no user presence has been checked or the user was not present + libfido_VerifiedAbsent=1, + ///the key was verified as valid and the user was present + libfido_VerifiedPresent=2 +}; + +struct libfido_client_request +{ + //request data + libfido_client_request_type type; + + //generic data + unsigned char keyhandle[128],nonce[8],appid[32],challenge[32]; + unsigned char token_uuid[16]; + + //response data + libfido_result_type result; +}; + +void libfido_init_client_request(struct libfido_client_request*request,libfido_request_type type); +void libfido_free_client_request(struct libfido_client_request*request); + +void libfido_client_request_set_appid(struct libfido_client_request*request,const char*appid); + +int libfido_exec_client_request(struct libfido_client_request*request); + + +struct libfido_token +{ + unsigned char token_uuid[16]; + /** Serial Number */ + char *serial_number; + /** Manufacturer String */ + char *manufacturer_string; + /** Product string */ + char *product_string; +}; + +void libfido_enumerate_tokens(struct libfido_token**tokens,int*numtokens); +void libfido_free_tokens(struct libfido_token*tokens); + + +enum libfido_server_request_type +{ + ///enrolls a key at the server side + libfido_EnrollKey, + ///creates random data as a challenge parameter + libfido_CreateChallenge, + ///authenticates the response received from a client + libfido_Authenticate +}; + +struct libfido_server_request +{ + libfido_server_request_type type; + + ///the server domain/context in which the key is used + char domain[1024]; +}; + +void libfido_init_server_request(struct libfido_server_request*request,libfido_server_request_type type,const char*domain); +void libfido_free_server_request(struct libfido_server_request*request); + +int libfido_exec_server_request(struct libfido_server_request*request); + +#endif diff --git a/testapp/Makefile b/testapp/Makefile new file mode 100644 index 0000000..3e20259 --- /dev/null +++ b/testapp/Makefile @@ -0,0 +1,20 @@ + +SOURCES = $(shell ls *.c) +OBJECTS = $(SOURCES:.c=.o) + +USBCFLAGS = $(shell pkg-config libusb-1.0 --cflags) +USBLIBS = $(shell pkg-config libusb-1.0 --libs) + +CFLAGS = -g -Wall $(USBCFLAGS) +LDFLAGS = $(USBLIBS) +CC = gcc + +testapp: $(OBJECTS) + $(CC) -o $@ $^ $(LDFLAGS) + +%.o: %.c + $(CC) $(CFLAGS) -c $< + +.PHONY: clean +clean: + -rm -rf testapp *.o diff --git a/testapp/fidodevice.c b/testapp/fidodevice.c new file mode 100644 index 0000000..c46cf75 --- /dev/null +++ b/testapp/fidodevice.c @@ -0,0 +1,151 @@ +#include +#include +#include +#include +#include +#include + +#include "fidodevice.h" + +#include "hidapi_report.h" + +#include "u2f.h" +#include "u2f_hid.h" + +struct fido_device_s*fido_devicelist=NULL; + +int fido_numdevices() +{ + int num=0; + struct fido_device_s *dev; + for(dev=fido_devicelist;dev!=NULL;dev=dev->next)num++; + return num; +} + +void fido_freedevice() +{ + struct fido_device_s*dev,*tmp; + for(dev=fido_devicelist;dev!=NULL;dev=tmp){ + tmp=dev->next; + libusb_unref_device(dev->device); + free(dev); + } + fido_devicelist=NULL; +} + +libusb_device_handle*fido_open(struct fido_device_s*dev) +{ + libusb_device_handle*hdl; + int r; + if((r=libusb_open(dev->device,&hdl))!=0){ + fprintf(stderr,"Unable to open Device %04x:%04x - %s (%i)\n",dev->idVendor,dev->idProduct,libusb_strerror(r),r); + return NULL; + } + libusb_set_auto_detach_kernel_driver(hdl,1); + if((r=libusb_claim_interface(hdl,dev->interfaceidx))!=0){ + fprintf(stderr,"Unable to claim Device %04x:%04x Interface %i - %s (%i)\n",dev->idVendor,dev->idProduct,dev->interface,libusb_strerror(r),r); + libusb_close(hdl); + return NULL; + } + if((r=libusb_set_interface_alt_setting(hdl,dev->interfaceidx,dev->altsettingidx))!=0){ + fprintf(stderr,"Unable to set alt-setting correctly %04x:%04x Interface %i AltSetting %i - %s (%i)\n", dev->idVendor, dev->idProduct, dev->interface, dev->altsetting, libusb_strerror(r),r); + libusb_release_interface(hdl,dev->interfaceidx); + libusb_close(hdl); + return NULL; + } + return hdl; +} + +void fido_close(libusb_device_handle*hdl,struct fido_device_s*dev) +{ + libusb_release_interface(hdl,dev->interfaceidx); + libusb_close(hdl); +} + +static int fido_getrandom(unsigned char*data,int length) +{ + if(data==NULL)return 0; + if(length<=0)return 0; + int fd=open("/dev/random",O_RDONLY); + if(fd<0)return 0; + int rd=read(fd,data,length); + close(fd); + if(rd>4]; + buf[i*2+1]=hex[data[i]&0xf]; + } + return buf; +} + +static void fido_info_one(struct fido_device_s*dev) +{ + //open device + libusb_device_handle*hdl=fido_open(dev); + if(hdl==NULL) + return; + //send command + unsigned char data[1024]; + memset(data,0,sizeof(data)); + data[0]=FIDO_USAGE_DATA_OUT; + data[1]=U2FHID_INIT; + data[2]=8; + fido_getrandom(data+3,8); + int ret=hid_write(hdl,dev->interfaceidx,dev->endpointout,data,11); + if(ret>=0){ + memset(data,0,sizeof(data)); + data[0]=FIDO_USAGE_DATA_IN; + ret=hid_read(hdl,dev->interfaceidx,dev->endpointin,data,sizeof(data)); + if(ret>=0){ + printf(" Report Length: %i\n Report Type: %i (%s)\n",ret,data[0],data[0]==FIDO_USAGE_DATA_IN?"FIDO IN":"?"); + printf(" Nonce: %s\n",bytes2hex(data+2,8)); + printf(" Channel: %s\n",bytes2hex(data+10,4)); + printf(" Protocol Version: %i\n Major Device Version: %i\n Minor Device Version: %i\n Build Device Version: %i\n Capabilities: %02x\n",data[14],data[15],data[16],data[17],data[18]); + }else + fprintf(stderr,"Failed to receive response to INIT request: %s\n",libusb_strerror(ret)); + }else + fprintf(stderr,"Unable to transmit INIT request: %s\n",libusb_strerror(ret)); + //free device + fido_close(hdl,dev); +} + +void fido_info() +{ + struct fido_device_s*dev; + for(dev=fido_devicelist;dev!=NULL;dev=dev->next){ + printf("Device %04x:%04x\n",dev->idVendor,dev->idProduct); + fido_info_one(dev); + } +} + + +int fido_send(struct fido_device_s*dev,unsigned int channel,unsigned char cmd,unsigned char *data,int length) +{ + if(cmd<0x80)return 0;//not a valid command + if(dev->packetsize<7 || dev->packetsize>1024)return -100; //ooops! + if(length<0 || length > (dev->packetsize-7 + 128*(dev->packetsize-5)))return -1;//too much data + unsigned char frame[1024]; + //construct command frame + frame[0]=FIDO_USAGE_DATA_OUT; + frame[1]=cmd; + frame[2]=channel>>24; + frame[3]=(channel>>16)&0xff; + frame[4]=(channel>>8)&0xff; + frame[5]=channel&0xff; + frame[6]=(length>>8)&0xff; + frame[7]=length&0xff; + int plen=length; + if(plen>(dev->packetsize-7))plen=dev->packetsize-7; + memcpy(frame+8,data,plen); + if(hid_write() + //construct remaining frames +} diff --git a/testapp/fidodevice.h b/testapp/fidodevice.h new file mode 100644 index 0000000..d1b0da2 --- /dev/null +++ b/testapp/fidodevice.h @@ -0,0 +1,27 @@ + +struct libusb_device; + +struct fido_device_s { + struct libusb_device*device; + unsigned short idVendor,idProduct; + unsigned char interface,interfaceidx,altsetting,altsettingidx,config; + unsigned char endpointin,endpointout; + int packetsize; + struct fido_device_s*next; +}; + +extern struct fido_device_s*fido_devicelist; + +///returns the number of detected devices +int fido_numdevices(); +///frees all devices +void fido_freedevice(); + +///prints info about all devices +void fido_info(); + +///send a message to the fido device, returns 1 on success, <=0 on failure +int fido_send(struct fido_device_s*dev,unsigned int channel,unsigned char cmd,unsigned char *data,int length); + +//default protocol timeout in ms +#define FIDO_TIMEOUT 30000 diff --git a/testapp/hidapi_report.c b/testapp/hidapi_report.c new file mode 100644 index 0000000..47d64a7 --- /dev/null +++ b/testapp/hidapi_report.c @@ -0,0 +1,155 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + 8/22/2009 + Linux Version - 6/2/2010 + Libusb Version - 8/13/2010 + FreeBSD Version - 11/1/2011 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . +********************************************************/ + +//Slightly modified by Konrad Rosenbaum, 2014 + +#include +#include +#include +#include + +#include "fidodevice.h" + +int hid_send_feature_report(libusb_device_handle *dev, unsigned char interface, const unsigned char *data, size_t length) +{ + int res = -1; + int skipped_report_id = 0; + int report_number = data[0]; + + if (report_number == 0x0) { + data++; + length--; + skipped_report_id = 1; + } + + res = libusb_control_transfer(dev, + LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, + 0x09/*HID set_report*/, + (3/*HID feature*/ << 8) | report_number, + interface, + (unsigned char *)data, length, + FIDO_TIMEOUT/*timeout millis*/); + + if (res < 0) + return res; + + /* Account for the report ID */ + if (skipped_report_id) + length++; + + return length; +} + +int hid_get_feature_report(libusb_device_handle *dev, unsigned char interface, unsigned char *data, size_t length) +{ + int res = -1; + int skipped_report_id = 0; + int report_number = data[0]; + + if (report_number == 0x0) { + /* Offset the return buffer by 1, so that the report ID + will remain in byte 0. */ + data++; + length--; + skipped_report_id = 1; + } + res = libusb_control_transfer(dev, + LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN, + 0x01/*HID get_report*/, + (3/*HID feature*/ << 8) | report_number, + interface, + (unsigned char *)data, length, + FIDO_TIMEOUT/*timeout millis*/); + + if (res < 0) + return res; + + if (skipped_report_id) + res++; + + return res; +} + + + +int hid_write(libusb_device_handle *dev, unsigned char interface, unsigned char endpoint, const unsigned char *data, size_t length) +{ + int res; + int report_number = data[0]; + int skipped_report_id = 0; + + if (report_number == 0x0) { + data++; + length--; + skipped_report_id = 1; + } + + + if (endpoint <= 0) { + /* No interrput out endpoint. Use the Control Endpoint */ + res = libusb_control_transfer(dev, + LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, + 0x09/*HID Set_Report*/, + (2/*HID output*/ << 8) | report_number, + interface, + (unsigned char *)data, length, + FIDO_TIMEOUT/*timeout millis*/); + + if (res < 0) + return res; + + if (skipped_report_id) + length++; + + return length; + } + else { + /* Use the interrupt out endpoint */ + int actual_length; + res = libusb_interrupt_transfer(dev, + endpoint, + (unsigned char*)data, + length, + &actual_length, FIDO_TIMEOUT); + + if (res < 0) + return res; + + if (skipped_report_id) + actual_length++; + + return actual_length; + } +} + + +//actually completely re-implemented synchronously +int hid_read(libusb_device_handle *dev, unsigned char interface, unsigned char endpoint, unsigned char *data, size_t length) +{ + int reallength; + int res= libusb_interrupt_transfer(dev,endpoint,data,length,&reallength,FIDO_TIMEOUT); + if(res==0)return reallength; + else return res; +} diff --git a/testapp/hidapi_report.h b/testapp/hidapi_report.h new file mode 100644 index 0000000..84c632e --- /dev/null +++ b/testapp/hidapi_report.h @@ -0,0 +1,8 @@ +#include + +struct libusb_device_handle; + +int hid_send_feature_report(libusb_device_handle *dev, unsigned char interface, const unsigned char *data, size_t length); +int hid_get_feature_report(libusb_device_handle *dev, unsigned char interface, unsigned char *data, size_t length); +int hid_write(libusb_device_handle *dev, unsigned char interface, unsigned char endpoint, const unsigned char *data, size_t length); +int hid_read(libusb_device_handle *dev, unsigned char interface, unsigned char endpoint, unsigned char *data, size_t length); diff --git a/testapp/hidapi_usage.c b/testapp/hidapi_usage.c new file mode 100644 index 0000000..c566391 --- /dev/null +++ b/testapp/hidapi_usage.c @@ -0,0 +1,125 @@ +/******************************************************************** + * These functions were copied from the LibUSB based implementation + * of HIDAPI: + * + Alan Ott + Signal 11 Software + + 8/22/2009 + Linux Version - 6/2/2010 + Libusb Version - 8/13/2010 + FreeBSD Version - 11/1/2011 + + Copyright 2009, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + http://github.com/signal11/hidapi . + ********************************************************************/ + +#include "hidapi_usage.h" + +/* Get bytes from a HID Report Descriptor. + Only call with a num_bytes of 0, 1, 2, or 4. */ +static uint32_t get_bytes(uint8_t *rpt, size_t len, size_t num_bytes, size_t cur) +{ + /* Return if there aren't enough bytes. */ + if (cur + num_bytes >= len) + return 0; + + if (num_bytes == 0) + return 0; + else if (num_bytes == 1) { + return rpt[cur+1]; + } + else if (num_bytes == 2) { + return (rpt[cur+2] * 256 + rpt[cur+1]); + } + else if (num_bytes == 4) { + return (rpt[cur+4] * 0x01000000 + + rpt[cur+3] * 0x00010000 + + rpt[cur+2] * 0x00000100 + + rpt[cur+1] * 0x00000001); + } + else + return 0; +} + +/* Retrieves the device's Usage Page and Usage from the report + descriptor. The algorithm is simple, as it just returns the first + Usage and Usage Page that it finds in the descriptor. + The return value is 0 on success and -1 on failure. */ +int hidapi_usage_get_usage(uint8_t* report_descriptor, size_t size, short unsigned int* usage_page, short unsigned int* usage) +{ + unsigned int i = 0; + int size_code; + int data_len, key_size; + int usage_found = 0, usage_page_found = 0; + + while (i < size) { + int key = report_descriptor[i]; + int key_cmd = key & 0xfc; + + //printf("key: %02hhx\n", key); + + if ((key & 0xf0) == 0xf0) { + /* This is a Long Item. The next byte contains the + length of the data section (value) for this key. + See the HID specification, version 1.11, section + 6.2.2.3, titled "Long Items." */ + if (i+1 < size) + data_len = report_descriptor[i+1]; + else + data_len = 0; /* malformed report */ + key_size = 3; + } + else { + /* This is a Short Item. The bottom two bits of the + key contain the size code for the data section + (value) for this key. Refer to the HID + specification, version 1.11, section 6.2.2.2, + titled "Short Items." */ + size_code = key & 0x3; + switch (size_code) { + case 0: + case 1: + case 2: + data_len = size_code; + break; + case 3: + data_len = 4; + break; + default: + /* Can't ever happen since size_code is & 0x3 */ + data_len = 0; + break; + }; + key_size = 1; + } + + if (key_cmd == 0x4) { + *usage_page = get_bytes(report_descriptor, size, data_len, i); + usage_page_found = 1; + //printf("Usage Page: %x\n", (uint32_t)*usage_page); + } + if (key_cmd == 0x8) { + *usage = get_bytes(report_descriptor, size, data_len, i); + usage_found = 1; + //printf("Usage: %x\n", (uint32_t)*usage); + } + + if (usage_page_found && usage_found) + return 0; /* success */ + + /* Skip over this key and it's associated data */ + i += data_len + key_size; + } + + return -1; /* failure */ +} diff --git a/testapp/hidapi_usage.h b/testapp/hidapi_usage.h new file mode 100644 index 0000000..1e881cb --- /dev/null +++ b/testapp/hidapi_usage.h @@ -0,0 +1,5 @@ +#include +#include + +int hidapi_usage_get_usage(uint8_t *report_descriptor, size_t size, + unsigned short *usage_page, unsigned short *usage); diff --git a/testapp/main.c b/testapp/main.c new file mode 100644 index 0000000..1879573 --- /dev/null +++ b/testapp/main.c @@ -0,0 +1,35 @@ +#include +#include +#include + +#include "fidodevice.h" +#include "scanfordev.h" + +static void printhelp(char*app) +{ + fprintf(stderr, + "Usage: %s \n\n" + " help\n\tshow help text\n\n" + " info\n\tquery information about the token\n\n" + " register appid [challenge]\n\tregister the key for the given appid, if no challenge is\n\tgiven, one is generated.\n\n" + " auth keyid [challenge]\n\tauthenticates the key, if no challenge is given, one is generated\n\n", + app); +} + +int main(int ac,char**av) +{ + if(ac<2 || strcmp(av[1],"help")==0 || strcmp(av[1],"--help")==0){ + printhelp(av[0]); + return 0; + } + libusb_init(NULL); + scanfordevices(); + if(strcmp(av[1],"info")==0){ + fido_info(); + return 0; + }else{ + fprintf(stderr,"Unknown sub-command %s.\n",av[1]); + printhelp(av[0]); + return 1; + } +} diff --git a/testapp/scanfordev.c b/testapp/scanfordev.c new file mode 100644 index 0000000..85b6fe6 --- /dev/null +++ b/testapp/scanfordev.c @@ -0,0 +1,135 @@ +#include +#include +#include +#include + +#include "hidapi_usage.h" +#include "fidodevice.h" + +void scaninterface(libusb_device*dev,int iface,int altset,struct libusb_config_descriptor *config,struct libusb_device_descriptor*desc) +{ + unsigned char buf[64]; + int len,i,j; + unsigned short usagepage,usage; + //sequence for opening and claiming the interface + libusb_device_handle*hdl; + if(libusb_open(dev,&hdl)!=0){ + fprintf(stderr," Unable to open Device.\n"); + return; + } + libusb_set_auto_detach_kernel_driver(hdl,1); + if(libusb_claim_interface(hdl,iface)!=0){ + fprintf(stderr," Unable to claim Device.\n"); + libusb_close(hdl); + return; + } + if(libusb_set_interface_alt_setting(hdl,iface,altset)!=0){ + fprintf(stderr," Unable to set alt-setting correctly.\n"); + libusb_release_interface(hdl,iface); + libusb_close(hdl); + return; + } + //get descriptor + if((len=libusb_get_descriptor(hdl,LIBUSB_DT_HID,0,buf,sizeof(buf)))<2){ + fprintf(stderr," Unable to retrieve HID descriptor.\n"); + libusb_release_interface(hdl,iface); + libusb_close(hdl); + return; + } + printf(" Descriptor"); + for(i=0;ialtsetting=config->interface[iface].altsetting[altset].bAlternateSetting; + devd->altsettingidx=altset; + devd->config=config->bConfigurationValue; + devd->interface=config->interface[iface].altsetting[altset].iInterface; + devd->interfaceidx=iface; + devd->idProduct=desc->idProduct; + devd->idVendor=desc->idVendor; + devd->packetsize=desc->bMaxPacketSize0; + devd->device=libusb_ref_device(dev); + for(j=0;jinterface[iface].altsetting[altset].bNumEndpoints;j++){ + unsigned char ep=config->interface[iface].altsetting[altset].endpoint[j].bEndpointAddress; + int ps=config->interface[iface].altsetting[altset].endpoint[j].wMaxPacketSize; + if(ep&LIBUSB_ENDPOINT_IN) + devd->endpointin=ep; + else + devd->endpointout=ep; + if(pspacketsize)devd->packetsize=ps; + } + devd->next=fido_devicelist; + fido_devicelist=devd; + }else printf("Sorry, no match.\n"); + } + libusb_release_interface(hdl,iface); + libusb_close(hdl); +} + +void scandevice(libusb_device*dev) +{ + struct libusb_device_descriptor dd; + struct libusb_config_descriptor *config; + int i,j,k; + if(libusb_get_device_descriptor(dev,&dd)!=0){ + fprintf(stderr,"Unable to scan one device.\n"); + return; + } + printf("Device ID %04x:%04x type %i subtype %i\n",dd.idVendor,dd.idProduct,dd.bDeviceClass,dd.bDeviceSubClass); + if(dd.bDeviceClass!=LIBUSB_CLASS_PER_INTERFACE && dd.bDeviceClass!=LIBUSB_CLASS_HID)return;//not direct HID or per-Iface + if(dd.bDeviceClass==LIBUSB_CLASS_HID && dd.bDeviceSubClass!=0)return;//direct HID, but not "unspecific" + printf("Device Type ok, ID %04x:%04x\n",dd.idVendor,dd.idProduct); + //scan interfaces + if(libusb_get_active_config_descriptor(dev,&config)!=0){ + fprintf(stderr,"Unable to get active Configuration of Device %04x:%04x\n",dd.idVendor,dd.idProduct); + return; + } + for(i=0;ibNumInterfaces;i++){ + for(j=0;jinterface[i].num_altsetting;j++){ + printf(" Scanning Config %i Iface %i Altsetting %i... ",config->bConfigurationValue, config->interface[i].altsetting[j].bInterfaceNumber, config->interface[i].altsetting[j].bAlternateSetting); + if(config->interface[i].altsetting[j].bInterfaceClass==LIBUSB_CLASS_HID && config->interface[i].altsetting[j].bInterfaceSubClass==0){ + printf("potential match!\n"); + printf(" desctype %i exlen %i\n", + config->interface[i].altsetting[j].bDescriptorType, + config->interface[i].altsetting[j].extra_length + ); + for(k=0;kinterface[i].altsetting[j].bNumEndpoints;k++) + printf(" endpoint %02x packet size %i\n", + config->interface[i].altsetting[j].endpoint[k].bEndpointAddress, + config->interface[i].altsetting[j].endpoint[k].wMaxPacketSize); + printf(" extra"); + for(k=0;kinterface[i].altsetting[j].extra_length;k++) + printf(" %02x",config->interface[i].altsetting[j].extra[k]); + printf(".\n"); + scaninterface(dev,i,j,config,&dd); + }else + printf("no match.\n"); + } + } + libusb_free_config_descriptor(config); +} + +void scanfordevices() +{ + struct libusb_device**devlist; + ssize_t numdevs; + int i; + numdevs=libusb_get_device_list(NULL,&devlist); + if(numdevs<=0){ + fprintf(stderr,"No USB devices found.\n"); + return; + } + for(i=0;i +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// General constants +#define U2F_EC_KEY_SIZE 32 // EC key size in bytes +#define U2F_EC_POINT_SIZE ((U2F_EC_KEY_SIZE * 2) + 1) // Size of EC point +#define U2F_MAX_KH_SIZE 128 // Max size of key handle +#define U2F_MAX_ATT_CERT_SIZE 2048 // Max size of attestation certificate +#define U2F_MAX_EC_SIG_SIZE 72 // Max size of DER coded EC signature +#define U2F_CTR_SIZE 4 // Size of counter field +#define U2F_APPID_SIZE 32 // Size of application id +#define U2F_CHAL_SIZE 32 // Size of challenge + +#define ENC_SIZE(x) ((x + 7)& 0xfff8) + +// EC (uncompressed) point + +#define U2F_POINT_UNCOMPRESSED 0x04 // Uncompressed point format + +typedef struct { + uint8_t pointFormat; // Point type + uint8_t x[U2F_EC_KEY_SIZE]; // X-value + uint8_t y[U2F_EC_KEY_SIZE]; // Y-value +} U2F_EC_POINT; + +// U2F native commands +#define U2F_REGISTER 0x01 // Registration command +#define U2F_AUTHENTICATE 0x02 // Authenticate/sign command +#define U2F_VERSION 0x03 // Read version string command + +#define U2F_VENDOR_FIRST 0xc0 // First vendor defined command +#define U2F_VENDOR_LAST 0xff // Last vendor defined command + +// U2F_CMD_REGISTER command defines + +#define U2F_REGISTER_ID 0x05 // Version 2 registration identifier +#define U2F_REGISTER_HASH_ID 0x00 // Version 2 hash identintifier + +typedef struct { + uint8_t chal[U2F_CHAL_SIZE]; // Challenge + uint8_t appId[U2F_APPID_SIZE]; // Application id +} U2F_REGISTER_REQ; + +typedef struct { + uint8_t registerId; // Registration identifier (U2F_REGISTER_ID_V2) + U2F_EC_POINT pubKey; // Generated public key + uint8_t keyHandleLen; // Length of key handle + uint8_t keyHandleCertSig[ + U2F_MAX_KH_SIZE + // Key handle + U2F_MAX_ATT_CERT_SIZE + // Attestation certificate + U2F_MAX_EC_SIG_SIZE]; // Registration signature +} U2F_REGISTER_RESP; + +// U2F_CMD_AUTHENTICATE command defines + +// Authentication control byte + +#define U2F_AUTH_ENFORCE 0x03 // Enforce user presence and sign +#define U2F_AUTH_CHECK_ONLY 0x07 // Check only +#define U2F_AUTH_FLAG_TUP 0x01 // Test of user presence set + +typedef struct { + uint8_t chal[U2F_CHAL_SIZE]; // Challenge + uint8_t appId[U2F_APPID_SIZE]; // Application id + uint8_t keyHandleLen; // Length of key handle + uint8_t keyHandle[U2F_MAX_KH_SIZE]; // Key handle +} U2F_AUTHENTICATE_REQ; + +typedef struct { + uint8_t flags; // U2F_AUTH_FLAG_ values + uint8_t ctr[U2F_CTR_SIZE]; // Counter field (big-endian) + uint8_t sig[U2F_MAX_EC_SIG_SIZE]; // Signature +} U2F_AUTHENTICATE_RESP; + +// Command status responses +#define U2F_SW_NO_ERROR 0x9000 // SW_NO_ERROR +#define U2F_SW_WRONG_DATA 0x6984 // SW_WRONG_DATA +#define U2F_SW_CONDITIONS_NOT_SATISFIED 0x6985 // SW_CONDITIONS_NOT_SATISFIED +#define U2F_SW_INS_NOT_SUPPORTED 0x6d00 // SW_INS_NOT_SUPPORTED + + +#ifdef __cplusplus +} +#endif + +#endif // __U2F_H_INCLUDED__ diff --git a/testapp/u2f_hid.h b/testapp/u2f_hid.h new file mode 100644 index 0000000..ed7b63a --- /dev/null +++ b/testapp/u2f_hid.h @@ -0,0 +1,129 @@ +// Common U2F HID transport header - Review Draft +// 2014-10-08 +// Editor: Jakob Ehrensvard, Yubico, jakob@yubico.com + +#ifndef __U2FHID_H_INCLUDED__ +#define __U2FHID_H_INCLUDED__ + +#ifdef _MSC_VER // Windows +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long int uint64_t; +#else +#include +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +// Size of HID reports + +#define HID_RPT_SIZE 64 // Default size of raw HID report + +// Frame layout - command- and continuation frames + +#define CID_BROADCAST 0xffffffff // Broadcast channel id + +#define TYPE_MASK 0x80 // Frame type mask +#define TYPE_INIT 0x80 // Initial frame identifier +#define TYPE_CONT 0x00 // Continuation frame identifier + +typedef struct { + uint32_t cid; // Channel identifier + union { + uint8_t type; // Frame type - b7 defines type + struct { + uint8_t cmd; // Command - b7 set + uint8_t bcnth; // Message byte count - high part + uint8_t bcntl; // Message byte count - low part + uint8_t data[HID_RPT_SIZE - 7]; // Data payload + } init; + struct { + uint8_t seq; // Sequence number - b7 cleared + uint8_t data[HID_RPT_SIZE - 5]; // Data payload + }cont; + }; +} U2FHID_FRAME; + +#define FRAME_TYPE(f) ((f).type & TYPE_MASK) +#define FRAME_CMD(f) ((f).init.cmd & ~TYPE_MASK) +#define MSG_LEN(f) ((f).init.bcnth*256 + (f).init.bcntl) +#define FRAME_SEQ(f) ((f).cont.seq & ~TYPE_MASK) + +// HID usage- and usage-page definitions + +#define FIDO_USAGE_PAGE 0xf1d0 // FIDO alliance HID usage page +#define FIDO_USAGE_U2FHID 0x01 // U2FHID usage for top-level collection +#define FIDO_USAGE_DATA_IN 0x20 // Raw IN data report +#define FIDO_USAGE_DATA_OUT 0x21 // Raw OUT data report + +// General constants + +#define U2FHID_IF_VERSION 2 // Current interface implementation version +#define U2FHID_TRANS_TIMEOUT 3000 // Default message timeout in ms + +// U2FHID native commands + +#define U2FHID_PING (TYPE_INIT | 0x01) // Echo data through local processor only +#define U2FHID_MSG (TYPE_INIT | 0x03) // Send U2F message frame +#define U2FHID_LOCK (TYPE_INIT | 0x04) // Send lock channel command +#define U2FHID_INIT (TYPE_INIT | 0x06) // Channel initialization +#define U2FHID_WINK (TYPE_INIT | 0x08) // Send device identification wink +#define U2FHID_SYNC (TYPE_INIT | 0x3c) // Protocol resync command +#define U2FHID_ERROR (TYPE_INIT | 0x3f) // Error response + +#define U2FHID_VENDOR_FIRST (TYPE_INIT | 0x40) // First vendor defined command +#define U2FHID_VENDOR_LAST (TYPE_INIT | 0x7f) // Last vendor defined command + + +// U2FHID_INIT command defines + +#define INIT_NONCE_SIZE 8 // Size of channel initialization challenge +#define CAPFLAG_WINK 0x01 // Device supports WINK command + + +typedef struct { + uint8_t nonce[INIT_NONCE_SIZE]; // Client application nonce +} U2FHID_INIT_REQ; + +typedef struct { + uint8_t nonce[INIT_NONCE_SIZE]; // Client application nonce + uint32_t cid; // Channel identifier + uint8_t versionInterface; // Interface version + uint8_t versionMajor; // Major version number + uint8_t versionMinor; // Minor version number + uint8_t versionBuild; // Build version number + uint8_t capFlags; // Capabilities flags +} U2FHID_INIT_RESP; + +// U2FHID_SYNC command defines + +typedef struct { + uint8_t nonce; // Client application nonce +} U2FHID_SYNC_REQ; + +typedef struct { + uint8_t nonce; // Client application nonce +} U2FHID_SYNC_RESP; + +// Low-level error codes. Return as negatives. + +#define ERR_NONE 0x00 // No error +#define ERR_INVALID_CMD 0x01 // Invalid command +#define ERR_INVALID_PAR 0x02 // Invalid parameter +#define ERR_INVALID_LEN 0x03 // Invalid message length +#define ERR_INVALID_SEQ 0x04 // Invalid message sequencing +#define ERR_MSG_TIMEOUT 0x05 // Message has timed out +#define ERR_CHANNEL_BUSY 0x06 // Channel busy +#define ERR_LOCK_REQUIRED 0x0a // Command requires channel lock +#define ERR_SYNC_FAIL 0x0b // SYNC command failed +#define ERR_OTHER 0x7f // Other unspecified error + +#ifdef __cplusplus +} +#endif + +#endif // __U2FHID_H_INCLUDED__ -- 1.7.2.5