From ae56e5c788e3ed6c60d98d445574d3042aaae24f Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Tue, 9 Dec 2008 20:59:55 +0000 Subject: Move into module folder --- COPYING | 458 -------------- make-dist.sh | 9 - module/COPYING | 458 ++++++++++++++ module/make-dist.sh | 9 + module/p11-capi-builtin.c | 245 ++++++++ module/p11-capi-builtin.h | 30 + module/p11-capi-cert.c | 775 +++++++++++++++++++++++ module/p11-capi-cert.h | 37 ++ module/p11-capi-der.c | 177 ++++++ module/p11-capi-der.h | 35 ++ module/p11-capi-key.c | 1083 ++++++++++++++++++++++++++++++++ module/p11-capi-key.h | 34 + module/p11-capi-object.c | 290 +++++++++ module/p11-capi-object.h | 100 +++ module/p11-capi-rsa.c | 415 +++++++++++++ module/p11-capi-rsa.h | 44 ++ module/p11-capi-session.c | 983 +++++++++++++++++++++++++++++ module/p11-capi-session.h | 169 +++++ module/p11-capi-token.c | 354 +++++++++++ module/p11-capi-token.h | 60 ++ module/p11-capi-trust.c | 569 +++++++++++++++++ module/p11-capi-trust.h | 30 + module/p11-capi-util.c | 547 ++++++++++++++++ module/p11-capi-util.h | 92 +++ module/p11-capi.c | 1515 +++++++++++++++++++++++++++++++++++++++++++++ module/p11-capi.dep | 69 +++ module/p11-capi.h | 126 ++++ module/p11-capi.vcproj | 428 +++++++++++++ module/pkcs11/Makefile.am | 9 + module/pkcs11/pkcs11.h | 1357 ++++++++++++++++++++++++++++++++++++++++ module/pkcs11/pkcs11n.h | 221 +++++++ module/x509-usages.h | 58 ++ p11-capi-builtin.c | 245 -------- p11-capi-builtin.h | 30 - p11-capi-cert.c | 775 ----------------------- p11-capi-cert.h | 37 -- p11-capi-der.c | 177 ------ p11-capi-der.h | 35 -- p11-capi-key.c | 1083 -------------------------------- p11-capi-key.h | 34 - p11-capi-object.c | 290 --------- p11-capi-object.h | 100 --- p11-capi-rsa.c | 415 ------------- p11-capi-rsa.h | 44 -- p11-capi-session.c | 983 ----------------------------- p11-capi-session.h | 169 ----- p11-capi-token.c | 354 ----------- p11-capi-token.h | 60 -- p11-capi-trust.c | 569 ----------------- p11-capi-trust.h | 30 - p11-capi-util.c | 547 ---------------- p11-capi-util.h | 92 --- p11-capi.c | 1515 --------------------------------------------- p11-capi.dep | 69 --- p11-capi.h | 126 ---- p11-capi.vcproj | 428 ------------- pkcs11/Makefile.am | 9 - pkcs11/pkcs11.h | 1357 ---------------------------------------- pkcs11/pkcs11n.h | 221 ------- x509-usages.h | 58 -- 60 files changed, 10319 insertions(+), 10319 deletions(-) delete mode 100644 COPYING delete mode 100644 make-dist.sh create mode 100644 module/COPYING create mode 100644 module/make-dist.sh create mode 100644 module/p11-capi-builtin.c create mode 100644 module/p11-capi-builtin.h create mode 100644 module/p11-capi-cert.c create mode 100644 module/p11-capi-cert.h create mode 100644 module/p11-capi-der.c create mode 100644 module/p11-capi-der.h create mode 100644 module/p11-capi-key.c create mode 100644 module/p11-capi-key.h create mode 100644 module/p11-capi-object.c create mode 100644 module/p11-capi-object.h create mode 100644 module/p11-capi-rsa.c create mode 100644 module/p11-capi-rsa.h create mode 100644 module/p11-capi-session.c create mode 100644 module/p11-capi-session.h create mode 100644 module/p11-capi-token.c create mode 100644 module/p11-capi-token.h create mode 100644 module/p11-capi-trust.c create mode 100644 module/p11-capi-trust.h create mode 100644 module/p11-capi-util.c create mode 100644 module/p11-capi-util.h create mode 100644 module/p11-capi.c create mode 100644 module/p11-capi.dep create mode 100644 module/p11-capi.h create mode 100644 module/p11-capi.vcproj create mode 100644 module/pkcs11/Makefile.am create mode 100644 module/pkcs11/pkcs11.h create mode 100644 module/pkcs11/pkcs11n.h create mode 100644 module/x509-usages.h delete mode 100644 p11-capi-builtin.c delete mode 100644 p11-capi-builtin.h delete mode 100644 p11-capi-cert.c delete mode 100644 p11-capi-cert.h delete mode 100644 p11-capi-der.c delete mode 100644 p11-capi-der.h delete mode 100644 p11-capi-key.c delete mode 100644 p11-capi-key.h delete mode 100644 p11-capi-object.c delete mode 100644 p11-capi-object.h delete mode 100644 p11-capi-rsa.c delete mode 100644 p11-capi-rsa.h delete mode 100644 p11-capi-session.c delete mode 100644 p11-capi-session.h delete mode 100644 p11-capi-token.c delete mode 100644 p11-capi-token.h delete mode 100644 p11-capi-trust.c delete mode 100644 p11-capi-trust.h delete mode 100644 p11-capi-util.c delete mode 100644 p11-capi-util.h delete mode 100644 p11-capi.c delete mode 100644 p11-capi.dep delete mode 100644 p11-capi.h delete mode 100644 p11-capi.vcproj delete mode 100644 pkcs11/Makefile.am delete mode 100644 pkcs11/pkcs11.h delete mode 100644 pkcs11/pkcs11n.h delete mode 100644 x509-usages.h diff --git a/COPYING b/COPYING deleted file mode 100644 index 27950e8..0000000 --- a/COPYING +++ /dev/null @@ -1,458 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -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 this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -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 -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser 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 Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "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 -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY 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 -LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS diff --git a/make-dist.sh b/make-dist.sh deleted file mode 100644 index 3c19301..0000000 --- a/make-dist.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -VERSION=0.1 - -tar -zcvf cryptoki-capi-$VERSION.tar.gz \ - --exclude=*.tar.gz --exclude=.svn --exclude=sandbox \ - --exclude=Debug --exclude=Release \ - --exclude=*.plg --exclude=*.ncb --exclude=*.opt \ - * diff --git a/module/COPYING b/module/COPYING new file mode 100644 index 0000000..27950e8 --- /dev/null +++ b/module/COPYING @@ -0,0 +1,458 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/module/make-dist.sh b/module/make-dist.sh new file mode 100644 index 0000000..3c19301 --- /dev/null +++ b/module/make-dist.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +VERSION=0.1 + +tar -zcvf cryptoki-capi-$VERSION.tar.gz \ + --exclude=*.tar.gz --exclude=.svn --exclude=sandbox \ + --exclude=Debug --exclude=Release \ + --exclude=*.plg --exclude=*.ncb --exclude=*.opt \ + * diff --git a/module/p11-capi-builtin.c b/module/p11-capi-builtin.c new file mode 100644 index 0000000..95fd476 --- /dev/null +++ b/module/p11-capi-builtin.c @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "p11-capi.h" +#include "p11-capi-object.h" +#include "p11-capi-session.h" +#include "p11-capi-token.h" + +#include "pkcs11/pkcs11n.h" + +/* -------------------------------------------------------------------------- + * BUILT IN VALUES + */ + +static const CK_BBOOL ck_true = CK_TRUE; +static const CK_BBOOL ck_false = CK_FALSE; + +static const CK_OBJECT_CLASS cko_netscape_builtin_root_list = CKO_NETSCAPE_BUILTIN_ROOT_LIST; + +static const char ck_root_label[] = "Windows Certificate Roots"; + +/* -------------------------------------------------------------------------- + * BUILT IN OBJECTS + */ + +#define CK_END_LIST (CK_ULONG)-1 + +static const CK_ATTRIBUTE builtin_root[] = { + { CKA_TOKEN, (void*)&ck_true, sizeof(CK_BBOOL) }, + { CKA_CLASS, (void*)&cko_netscape_builtin_root_list, sizeof(CK_OBJECT_CLASS) }, + { CKA_PRIVATE, (void*)&ck_false, sizeof(CK_BBOOL) }, + { CKA_MODIFIABLE, (void*)&ck_false, sizeof(CK_BBOOL) }, + { CKA_LABEL, (void*)ck_root_label, sizeof(ck_root_label) }, + { CK_END_LIST, NULL, 0 } +}; + +typedef struct _BuiltinMatch +{ + CK_ATTRIBUTE_PTR attr; + CK_ULONG slot_flags; +} +BuiltinMatch; + +static const BuiltinMatch all_builtins[] = { + { (CK_ATTRIBUTE_PTR)&builtin_root, P11C_SLOT_TRUSTED | P11C_SLOT_CA | P11C_SLOT_CERTS }, + { NULL, 0 } +}; + +/* This is filled in later */ +static CK_ULONG num_builtins = 0; + +/* -------------------------------------------------------------------------- + * IMPLEMENTATION + */ + +/* Represents a loaded builtin object */ +typedef struct _BuiltinObject +{ + P11cObject obj; + CK_ATTRIBUTE_PTR attr; +} +BuiltinObject; + +typedef struct _BuiltinObjectData +{ + P11cObjectData base; + CK_ATTRIBUTE_PTR attr; +} +BuiltinObjectData; + +static CK_RV +builtin_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) +{ + BuiltinObjectData* bdata = (BuiltinObjectData*)objdata; + CK_ATTRIBUTE_PTR builtin = bdata->attr; + + ASSERT(attr); + ASSERT(bdata); + + while(builtin->type != CK_END_LIST) + { + if(builtin->type == attr->type) + { + if(builtin->ulValueLen == 0) + return CKR_ATTRIBUTE_TYPE_INVALID; + return p11c_return_data(attr, builtin->pValue, builtin->ulValueLen); + } + + builtin++; + } + + return CKR_ATTRIBUTE_TYPE_INVALID; +} + +static void +builtin_data_release(void* data) +{ + BuiltinObjectData* bdata = (BuiltinObjectData*)data; + ASSERT(bdata); + free(bdata); +} + +static const P11cObjectDataVtable builtin_objdata_vtable = { + builtin_attribute, + builtin_attribute, + builtin_attribute, + builtin_data_release, +}; + +static CK_RV +builtin_load_data(P11cSession* sess, P11cObject* obj, P11cObjectData** objdata) +{ + BuiltinObject* bobj = (BuiltinObject*)obj; + BuiltinObjectData* bdata; + + ASSERT(bobj); + ASSERT(objdata); + ASSERT(num_builtins > 0); + + bdata = (BuiltinObjectData*)calloc(1, sizeof(BuiltinObjectData)); + if(!bdata) + return CKR_HOST_MEMORY; + + /* Simple, just use same data */ + bdata->attr = bobj->attr; + + bdata->base.object = obj->id; + bdata->base.data_funcs = &builtin_objdata_vtable; + + *objdata = &(bdata->base); + return CKR_OK; +} + +static unsigned int +builtin_hash_func(P11cObject* obj) +{ + return p11c_hash_pointer(((BuiltinObject*)obj)->attr); +} + +static int +builtin_equal_func(P11cObject* one, P11cObject* two) +{ + return ((BuiltinObject*)one)->attr == ((BuiltinObject*)two)->attr; +} + +static void +builtin_object_release(void* data) +{ + BuiltinObject* bobj = (BuiltinObject*)data; + ASSERT(bobj); + free(bobj); +} + +static const P11cObjectVtable builtin_object_vtable = { + builtin_load_data, + builtin_hash_func, + builtin_equal_func, + builtin_object_release, +}; + +static CK_RV +register_builtin_object(P11cSession* sess, CK_ATTRIBUTE_PTR attr, P11cObject** obj) +{ + BuiltinObject* bobj; + CK_RV ret; + + bobj = calloc(1, sizeof(BuiltinObject)); + if(!bobj) + return CKR_HOST_MEMORY; + + bobj->attr = attr; + + bobj->obj.id = 0; + bobj->obj.obj_funcs = &builtin_object_vtable; + + ret = p11c_token_register_object(sess->slot, &(bobj->obj)); + if(ret != CKR_OK) + { + free(bobj); + return ret; + } + + ASSERT(bobj->obj.id != 0); + *obj = &(bobj->obj); + return CKR_OK; +} + +CK_RV +p11c_builtin_find(P11cSession* sess, CK_OBJECT_CLASS cls, CK_ATTRIBUTE_PTR match, + CK_ULONG count, P11cArray* arr) +{ + P11cObject* obj; + BuiltinObjectData bdata; + CK_RV ret = CKR_OK; + CK_ULONG i, fl; + + /* First time around count total number */ + if(!num_builtins) + { + while(all_builtins[num_builtins].attr) + ++num_builtins; + ASSERT(num_builtins > 0); + } + + /* Match each certificate */ + for(i = 0; i < num_builtins; ++i) + { + /* Only apply built in objects to appropriate slots */ + fl = p11c_token_get_flags(sess->slot) & all_builtins[i].slot_flags; + if(fl != all_builtins[i].slot_flags) + continue; + + bdata.attr = all_builtins[i].attr; + bdata.base.object = 0; + bdata.base.data_funcs = &builtin_objdata_vtable; + + if(p11c_object_data_match(&bdata.base, match, count)) + { + ret = register_builtin_object(sess, all_builtins[i].attr, &obj); + if(ret != CKR_OK) + break; + + p11c_array_append(arr, obj->id); + } + } + + return ret; +} + diff --git a/module/p11-capi-builtin.h b/module/p11-capi-builtin.h new file mode 100644 index 0000000..b398509 --- /dev/null +++ b/module/p11-capi-builtin.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef P11C_BUILTIN_H +#define P11C_BUILTIN_H + +#include "p11-capi.h" + +/* Find builtin objects matching criteria */ +CK_RV p11c_builtin_find (P11cSession* sess, CK_OBJECT_CLASS cls, + CK_ATTRIBUTE_PTR match, CK_ULONG count, + P11cArray* arr); + +#endif /* P11C_BUILTIN_H */ diff --git a/module/p11-capi-cert.c b/module/p11-capi-cert.c new file mode 100644 index 0000000..53e198f --- /dev/null +++ b/module/p11-capi-cert.c @@ -0,0 +1,775 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "p11-capi.h" +#include "p11-capi-cert.h" +#include "p11-capi-object.h" +#include "p11-capi-session.h" +#include "p11-capi-token.h" + +#include + +#ifndef CERT_FIND_KEY_IDENTIFIER +#define CERT_FIND_KEY_IDENTIFIER 983040 +#endif + +#ifndef CERT_KEY_IDENTIFIER_PROP_ID +#define CERT_KEY_IDENTIFIER_PROP_ID 20 +#endif + +typedef struct _CertObject +{ + P11cObject obj; + + /* Together these can uniquely identify a certificate */ + CRYPT_INTEGER_BLOB serial; + CERT_NAME_BLOB issuer; +} +CertObject; + +typedef struct _CertObjectData +{ + P11cObjectData base; + PCCERT_CONTEXT cert; + BOOL is_in_root; +} +CertObjectData; + +static CK_RV +parse_basic_constraints(CertObjectData* cdata, CK_ULONG* category) +{ + CERT_BASIC_CONSTRAINTS_INFO* basic; + CERT_EXTENSION* ext; + DWORD size; + BYTE bits; + CK_RV ret; + + ASSERT(cdata); + ASSERT(cdata->cert); + + *category = 0; + + ext = CertFindExtension(szOID_BASIC_CONSTRAINTS, + cdata->cert->pCertInfo->cExtension, + cdata->cert->pCertInfo->rgExtension); + + /* No key usage, don't care */ + if(!ext) + return CKR_OK; + + /* Find the size of the decoded structure */ + if(!CryptDecodeObject(P11c_ENCODINGS, X509_BASIC_CONSTRAINTS, + ext->Value.pbData, ext->Value.cbData, 0, NULL, &size)) + return p11c_winerr_to_ckr(GetLastError()); + + /* Allocate enough memory */ + basic = (CERT_BASIC_CONSTRAINTS_INFO*)calloc(1, size); + if(!basic) + return CKR_HOST_MEMORY; + + /* And get the decoded structure */ + if(CryptDecodeObject(P11c_ENCODINGS, X509_BASIC_CONSTRAINTS, + ext->Value.pbData, ext->Value.cbData, 0, basic, &size)) + { + if(basic->SubjectType.cbData != 1) + { + DBG(("basic constraints bits are of invalid size")); + ret = CKR_GENERAL_ERROR; + } + else + { + /* All of the above was for 2 bits. Lovely */ + bits = basic->SubjectType.pbData[0] & ~(0xff >> (8 - basic->SubjectType.cUnusedBits)); + if((bits & CERT_CA_SUBJECT_FLAG) == CERT_CA_SUBJECT_FLAG) + *category = 2; + else if((bits & CERT_END_ENTITY_SUBJECT_FLAG) == CERT_END_ENTITY_SUBJECT_FLAG) + *category = 3; + else + *category = 0; + ret = CKR_OK; + } + } + else + { + ret = p11c_winerr_to_ckr(GetLastError()); + } + + free(basic); + + return ret; +} + + +static CK_RV +cert_bool_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) +{ + CertObjectData* cdata = (CertObjectData*)objdata; + CK_BBOOL val; + + ASSERT(cdata); + + switch(attr->type) + { + /* + * Resides on the token + * - Always true for CAPI objects. + */ + case CKA_TOKEN: + val = CK_TRUE; + break; + + /* + * Private vs. Public object. + * - Always false for certificates. + */ + case CKA_PRIVATE: + val = CK_FALSE; + break; + + /* + * If object can be modified. + * - Currently always false. In the future with additional + * functionality this may change. + */ + case CKA_MODIFIABLE: + val = CK_FALSE; + break; + + /* + * Whether the certificate can be trusted for the application + * in which it was created. + * - We just report on whether the certificate is a trusted root. + */ + case CKA_TRUSTED: + val = cdata->is_in_root ? CK_TRUE : CK_FALSE; + break; + + default: + return CKR_ATTRIBUTE_TYPE_INVALID; + }; + + return p11c_return_data(attr, &val, sizeof(CK_BBOOL)); +} + +static CK_RV +cert_ulong_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) +{ + CertObjectData* cdata = (CertObjectData*)objdata; + CK_ULONG val; + CK_RV ret; + + ASSERT(objdata); + + switch(attr->type) + { + + /* + * Object class. + * - Always CKO_CERTIFICATE for certificates. + */ + case CKA_CLASS: + val = CKO_CERTIFICATE; + break; + + /* + * Type of certificate. + * - Always X509. + */ + case CKA_CERTIFICATE_TYPE: + val = CKC_X_509; + break; + + /* + * Whether a CA, user certificate, other. + * - Get certificate szOID_ENHANCED_KEY_USAGE + * extension or CERT_CTL_PROP_ID and look into CTL_USAGE structure. + */ + case CKA_CERTIFICATE_CATEGORY: + ret = parse_basic_constraints(cdata, &val); + if(ret != CKR_OK) + return ret; + break; + + /* + * Java MIDP security domain. + * - Have no idea what this is. Spec says default to zero. + */ + case CKA_JAVA_MIDP_SECURITY_DOMAIN: + val = 0; + break; + + default: + return CKR_ATTRIBUTE_TYPE_INVALID; + }; + + return p11c_return_data(attr, &val, sizeof(CK_ULONG)); +} + +static CK_RV +cert_bytes_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) +{ + CertObjectData* cdata = (CertObjectData*)objdata; + PCCERT_CONTEXT cert = cdata->cert; + + ASSERT(sizeof(CK_ULONG) == sizeof(DWORD)); + ASSERT(cdata); + + return p11c_cert_certificate_get_bytes(cdata->cert, attr); +} + +static void +cert_data_release(void* data) +{ + CertObjectData* cdata = (CertObjectData*)data; + ASSERT(cdata && cdata->cert); + CertFreeCertificateContext(cdata->cert); + free(cdata); +} + +static const P11cObjectDataVtable cert_objdata_vtable = { + cert_bool_attribute, + cert_ulong_attribute, + cert_bytes_attribute, + cert_data_release, +}; + +static P11cObjectData* +cert_alloc_data(P11cSession* sess, P11cObject* obj, PCCERT_CONTEXT cert) +{ + CertObjectData* cdata; + + cdata = (CertObjectData*)calloc(1, sizeof(CertObjectData)); + if(!cdata) + return NULL; + + cdata->cert = cert; + cdata->is_in_root = (p11c_token_get_flags(sess->slot) & P11C_SLOT_CA) ? TRUE : FALSE; + + cdata->base.object = obj->id; + cdata->base.data_funcs = &cert_objdata_vtable; + + return &(cdata->base); +} + +static CK_RV +cert_load_data(P11cSession* sess, P11cObject* obj, P11cObjectData** objdata) +{ + CertObject* cobj = (CertObject*)obj; + CERT_INFO info; + PCCERT_CONTEXT cert; + + ASSERT(cobj); + ASSERT(objdata); + + ASSERT(cobj->issuer.pbData); + ASSERT(cobj->issuer.cbData); + ASSERT(cobj->serial.pbData); + ASSERT(cobj->serial.cbData); + + /* No store should mean no objects were loaded */ + ASSERT(sess->store); + + /* Setup our search */ + memset(&info, 0, sizeof(info)); + memcpy(&info.SerialNumber, &cobj->serial, sizeof(info.SerialNumber)); + memcpy(&info.Issuer, &cobj->issuer, sizeof(info.Issuer)); + + cert = CertGetSubjectCertificateFromStore(sess->store, P11c_ENCODINGS, &info); + + if(!cert) + { + DWORD err = GetLastError(); + + /* TODO: Is this right for a deleted certificate? */ + ASSERT(err != E_INVALIDARG); + if(err == CRYPT_E_NOT_FOUND) + return CKR_OBJECT_HANDLE_INVALID; + else + return p11c_winerr_to_ckr(GetLastError()); + } + + *objdata = cert_alloc_data(sess, obj, cert); + if(!(*objdata)) + { + CertFreeCertificateContext(cert); + return CKR_HOST_MEMORY; + } + + return CKR_OK; +} + +static unsigned int +cert_hash_func(P11cObject* obj) +{ + CertObject* cobj = (CertObject*)obj; + return p11c_hash_data(cobj->issuer.pbData, cobj->issuer.cbData) ^ + p11c_hash_data(cobj->serial.pbData, cobj->serial.cbData); +} + +static int +cert_equal_func(P11cObject* a, P11cObject* b) +{ + CertObject* ca = (CertObject*)a; + CertObject* cb = (CertObject*)b; + return ca->issuer.cbData == cb->issuer.cbData && + memcmp(ca->issuer.pbData, cb->issuer.pbData, ca->issuer.cbData) == 0 && + ca->serial.cbData == cb->serial.cbData && + memcmp(ca->serial.pbData, cb->serial.pbData, ca->serial.cbData) == 0; +} + +static void +cert_object_release(void* data) +{ + CertObject* cobj = (CertObject*)data; + ASSERT(cobj); + free(cobj); +} + +static const P11cObjectVtable cert_object_vtable = { + cert_load_data, + cert_hash_func, + cert_equal_func, + cert_object_release, +}; + +static CK_RV +calculate_check_value(PCCERT_CONTEXT cert, CK_ATTRIBUTE_PTR attr) +{ + BYTE* buffer; + DWORD length; + CK_RV ret; + + ASSERT(cert); + ASSERT(attr); + + /* Short cut for the measuring case */ + if(!attr->pValue) + { + attr->ulValueLen = 3; + return CKR_OK; + } + + length = 0; + if(!CryptHashCertificate(0, CALG_SHA1, 0, cert->pbCertEncoded, + cert->cbCertEncoded, NULL, &length)) + return p11c_winerr_to_ckr(GetLastError()); + + if(length < 3) + { + DBG(("SHA1 hash length too short: %d", length)); + return CKR_DEVICE_ERROR; + } + + buffer = malloc(length); + if(!buffer) + return CKR_HOST_MEMORY; + + if(!CryptHashCertificate(0, CALG_SHA1, 0, cert->pbCertEncoded, + cert->cbCertEncoded, buffer, &length)) + { + free(buffer); + return p11c_winerr_to_ckr(GetLastError()); + } + + ret = p11c_return_data(attr, buffer, 3); + free(buffer); + return ret; +} + + +CK_RV +p11c_cert_certificate_get_bytes(PCCERT_CONTEXT cert, CK_ATTRIBUTE_PTR attr) +{ + DWORD err; + + ASSERT(cert); + ASSERT(attr); + + switch(attr->type) + { + + /* + * Description of the object. + * - We use CAPI's CERT_FRIENDLY_NAME_PROP_ID property, + * converted into UTF8. + * - Yes this is slow, but this is not really a property + * that's searched on or retrieved intensively. + */ + case CKA_LABEL: + { + WCHAR* utf16 = NULL; + DWORD size; + + if(!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &size)) + { + err = GetLastError(); + if(err == CRYPT_E_NOT_FOUND) + utf16 = L"Unnamed Certificate"; + else + return p11c_winerr_to_ckr(err); + } + + if(!utf16) + { + utf16 = _alloca(size); + if(!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, utf16, &size)) + return p11c_winerr_to_ckr(GetLastError()); + } + + return p11c_return_string(attr, utf16); + } + break; + + /* + * A byte array unique to this certificate. The CKA_ID of + * matching certificates and private keys should match. + * Should match the key identifier in an X.509v3 certificate. + * + * We use CAPI's CERT_KEY_IDENTIFIER_PROP_ID property directly. + */ + case CKA_ID: + if(!CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, + attr->pValue, (DWORD*)&attr->ulValueLen)) + { + err = GetLastError(); + if(err == CRYPT_E_NOT_FOUND) + return CKR_ATTRIBUTE_TYPE_INVALID; + return p11c_winerr_to_ckr(err); + } + return CKR_OK; + + + /* + * DER-encoding of the certificate subject name. + * + * We use CAPI's CERT_CONTEXT pCertInfo->Subject field + * directly. + */ + case CKA_SUBJECT: + return p11c_return_data(attr, cert->pCertInfo->Subject.pbData, + cert->pCertInfo->Subject.cbData); + + /* + * DER-encoding of the certificate issuer name. + * + * We use CAPI's CERT_CONTEXT pCertInfo->Issuer field + * directly. + */ + case CKA_ISSUER: + return p11c_return_data(attr, cert->pCertInfo->Issuer.pbData, + cert->pCertInfo->Issuer.cbData); + + /* + * DER-encoding of the certificate serial number. + */ + case CKA_SERIAL_NUMBER: + if(!CryptEncodeObject(X509_ASN_ENCODING, X509_MULTI_BYTE_INTEGER, + &cert->pCertInfo->SerialNumber, + attr->pValue, (DWORD*)&attr->ulValueLen)) + { + err = GetLastError(); + if(err == ERROR_FILE_NOT_FOUND) + return CKR_GENERAL_ERROR; + return p11c_winerr_to_ckr(err); + } + return CKR_OK; + + /* + * BER-encoding of the full certificate. + * + * We use CAPI's CERT_CONTEXT pbCertEncoded field directly. + */ + case CKA_VALUE: + return p11c_return_data(attr, cert->pbCertEncoded, + cert->cbCertEncoded); + + /* + * If CKA_VALUE not specified, this is where the full + * certificate can be found. + * + * We don't support this. All our certificates are present + * in full. + * + * - Spec says default to empty. + */ + case CKA_URL: + return p11c_return_data(attr, "", 0); + + /* + * Checksum + * - This is the first 3 bytes of the SHA hash of the DER. + */ + case CKA_CHECK_VALUE: + return calculate_check_value(cert, attr); + + /* + * Various hashes for remote retrieval. + * - Spec says default to empty. + */ + case CKA_HASH_OF_SUBJECT_PUBLIC_KEY: + case CKA_HASH_OF_ISSUER_PUBLIC_KEY: + return p11c_return_data(attr, "", 0); + + /* + * Start date for the certificate. + */ + case CKA_START_DATE: + return p11c_return_filetime(attr, &cert->pCertInfo->NotBefore); + + /* + * End date for the certificate. + */ + case CKA_END_DATE: + return p11c_return_filetime(attr, &cert->pCertInfo->NotAfter); + + default: + return CKR_ATTRIBUTE_TYPE_INVALID; + }; +} + +PCCERT_CONTEXT +p11c_cert_object_data_get_certificate(P11cObjectData* objdata) +{ + CertObjectData* cdata; + + ASSERT(objdata); + ASSERT(objdata->data_funcs == &cert_objdata_vtable); + + cdata = (CertObjectData*)objdata; + return cdata->cert; +} + +static CK_RV +register_cert_object(P11cSession* sess, PCCERT_CONTEXT cert, P11cObject** obj) +{ + CertObject* cobj; + CK_RV ret; + size_t len; + + /* We save the Issuer and SerialNumber for identification later */ + len = cert->pCertInfo->SerialNumber.cbData + + cert->pCertInfo->Issuer.cbData; + + cobj = calloc(1, sizeof(CertObject) + len); + if(!cobj) + return CKR_HOST_MEMORY; + + cobj->obj.id = 0; + cobj->obj.obj_funcs = &cert_object_vtable; + + /* Copy Issuer data in */ + cobj->issuer.cbData = cert->pCertInfo->Issuer.cbData; + cobj->issuer.pbData = (BYTE*)(cobj + 1); + memcpy(cobj->issuer.pbData, cert->pCertInfo->Issuer.pbData, + cobj->issuer.cbData); + + /* Copy Serial Number data in */ + cobj->serial.cbData = cert->pCertInfo->SerialNumber.cbData; + cobj->serial.pbData = cobj->issuer.pbData + cobj->issuer.cbData; + memcpy(cobj->serial.pbData, cert->pCertInfo->SerialNumber.pbData, + cobj->serial.cbData); + + ret = p11c_token_register_object(sess->slot, &(cobj->obj)); + if(ret != CKR_OK) + { + free(cobj); + return ret; + } + + ASSERT(cobj->obj.id != 0); + *obj = &cobj->obj; + return CKR_OK; +} + +static CK_RV +find_in_store(P11cSession* sess, DWORD find_type, const void *find_criteria, + CK_ATTRIBUTE_PTR match, CK_ULONG count, P11cArray* arr) +{ + PCCERT_CONTEXT cert = NULL; + P11cObject* obj; + P11cObjectData* objdata; + CertObjectData cdata; + DWORD err; + CK_RV ret = CKR_OK; + + /* No store, no objects */ + if(!sess->store) + return CKR_OK; + + for(;;) + { + cert = CertFindCertificateInStore(sess->store, P11c_ENCODINGS, 0, + find_type, find_criteria, cert); + if(cert == NULL) + { + err = GetLastError(); + + /* Certificate not found, we don't care */ + if(err == CRYPT_E_NOT_FOUND) + return CKR_OK; + else + return p11c_winerr_to_ckr(err); + } + + /* Match the certificate */ + cdata.cert = cert; + cdata.base.object = 0; + cdata.base.data_funcs = &cert_objdata_vtable; + + if(p11c_object_data_match(&cdata.base, match, count)) + { + ret = register_cert_object(sess, cert, &obj); + if(ret == CKR_OK) + { + ASSERT(obj); + + /* Store away the object data for performance reasons */ + objdata = cert_alloc_data(sess, obj, cert); + if(objdata) + { + p11c_session_take_object_data(sess, obj, objdata); + + /* For continuing the enumeration */ + cert = CertDuplicateCertificateContext(cert); + } + + p11c_array_append(arr, obj->id); + } + } + } + + if(ret != CKR_OK && cert) + CertFreeCertificateContext(cert); + + return ret; +} + +CK_RV +p11c_cert_find(P11cSession* sess, CK_OBJECT_CLASS cls, CK_ATTRIBUTE_PTR match, + CK_ULONG count, P11cArray* arr) +{ + CRYPT_INTEGER_BLOB* serial = NULL; + CK_RV ret; + CK_ULONG i; + DWORD size; + + CERT_INFO find_info; /* For searching by issuer and serial */ + CRYPT_HASH_BLOB find_key; /* For searching by ID */ + + /* We only have certificates here */ + if(cls != CKO_CERTIFICATE && cls != CKO_ANY) + return CKR_OK; + + /* Only work with slots that have certificates */ + if(!(p11c_token_get_flags (sess->slot) & P11C_SLOT_CERTS)) + return CKR_OK; + + /* + * There are some better searches we can do rather than + * listing everything. + * + * CKA_ISSUER + CKA_SERIAL_NUMBER + * See if we have a issuer and serial number for a + * specific certificate to find. + * + * CKA_ID + * Search by key identifier + * + * TODO: could search by hash (use CertFindCertificateInStore + * with CERT_FIND_HASH or CERT_FIND_SHA1_HASH or CERT_FIND_MD5_HASH) + * + * TODO: could search by issuer (use CertFindCertificateInStore + * with CERT_FIND_ISSUER_NAME) + * + * TODO: could search by subject (use CertFindCertificateInStore + * with CERT_FIND_SUBJECT_NAME) + * + * TODO: could search by CKA_VALUE (use CertFindCertificateInStore + * with CERT_FIND_EXISTING) + */ + memset(&find_info, 0, sizeof(find_info)); + memset(&find_key, 0, sizeof(find_key)); + + for(i = 0; i < count; ++i) + { + if(!match[i].pValue || !match[i].ulValueLen) + continue; + + if(match[i].type == CKA_ISSUER) + { + find_info.Issuer.cbData = match[i].ulValueLen; + find_info.Issuer.pbData = match[i].pValue; + } + + else if(match[i].type == CKA_SERIAL_NUMBER && !serial) + { + if(!CryptDecodeObject(P11c_ENCODINGS, X509_MULTI_BYTE_INTEGER, + match[i].pValue, match[i].ulValueLen, 0, NULL, &size)) + { + continue; + } + + serial = calloc(1, size); + if(!serial) + continue; + + if(!CryptDecodeObject(P11c_ENCODINGS, X509_MULTI_BYTE_INTEGER, + match[i].pValue, match[i].ulValueLen, 0, serial, &size)) + continue; + + ASSERT(serial->cbData); + ASSERT(serial->pbData); + + find_info.SerialNumber.cbData = serial->cbData; + find_info.SerialNumber.pbData = serial->pbData; + } + + else if(match[i].type == CKA_ID) + { + find_key.cbData = match[i].ulValueLen; + find_key.pbData = match[i].pValue; + } + } + + /* Match a specific certificate */ + if(find_info.SerialNumber.cbData && find_info.Issuer.cbData) + { + ret = find_in_store(sess, CERT_FIND_SUBJECT_CERT, &find_info, + match, count, arr); + } + + /* Find all certificates with key identifier */ + else if(find_key.cbData) + { + ret = find_in_store(sess, CERT_FIND_KEY_IDENTIFIER, &find_key, + match, count, arr); + } + + /* Match any ol certificate */ + else + { + ret = find_in_store(sess, CERT_FIND_ANY, NULL, + match, count, arr); + } + + if(serial) + free(serial); + + return ret; +} diff --git a/module/p11-capi-cert.h b/module/p11-capi-cert.h new file mode 100644 index 0000000..f85d7b3 --- /dev/null +++ b/module/p11-capi-cert.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef P11C_CERT_H +#define P11C_CERT_H + +#include "p11-capi.h" +#include "p11-capi-util.h" + +/* Find certificates matching criteria */ +CK_RV p11c_cert_find (P11cSession* sess, CK_OBJECT_CLASS cls, + CK_ATTRIBUTE_PTR match, CK_ULONG count, + P11cArray* arr); + +/* Called by trust and key stuff */ +CK_RV p11c_cert_certificate_get_bytes (PCCERT_CONTEXT cert, + CK_ATTRIBUTE_PTR attr); + +PCCERT_CONTEXT p11c_cert_object_data_get_certificate (P11cObjectData* objdata); + +#endif /* P11C_CERT_H */ diff --git a/module/p11-capi-der.c b/module/p11-capi-der.c new file mode 100644 index 0000000..5698dff --- /dev/null +++ b/module/p11-capi-der.c @@ -0,0 +1,177 @@ +/* + * Portions derived from NSS source files: + * lib/ckfw/capi/cobject.c + * lib/ckfw/capi/crsa.c + * + * Portions of this file: + * Copyright (C) Stef Walter 2008 + * + */ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * Portions created by Red Hat, Inc, are Copyright (C) 2005 + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "p11-capi.h" +#include "p11-capi-der.h" + +/* + * unwrap a single DER value + */ +BYTE* +p11c_der_unwrap(BYTE* src, DWORD n_src, + DWORD* n_result, BYTE** next) +{ + BYTE* start = src; + BYTE* end = src + n_src; + DWORD len = 0; + + /* initialize error condition return values */ + *n_result = 0; + if(next) + *next = src; + + if(n_src < 2) + return start; + + src++ ; /* skip the tag -- should check it against an expected value! */ + len = (DWORD)*src++; + if(len & 0x80) + { + DWORD count = len & 0x7f; + len = 0; + + if(count + 2 > n_src) + return start; + + while(count-- > 0) + len = (len << 8) | (DWORD)*src++; + } + + if(len + (src - start) > (DWORD)n_src) + return start; + + if(next) + *next = src + len; + + *n_result = len; + return src; +} + +/* + * write a Decimal value to a string + */ + +static char* +put_decimal_string(char* cstr, DWORD value) +{ + DWORD tenpower; + BOOL first = TRUE; + + for(tenpower = 10000000; tenpower; tenpower /= 10) + { + BYTE digit = (BYTE)(value / tenpower); + value = value % tenpower; + + /* drop leading zeros */ + if(first && (0 == digit)) + continue; + + first = FALSE; + *cstr++ = digit + '0'; + } + + /* if value was zero, put one of them out */ + if(first) + *cstr++ = '0'; + + return cstr; +} + +/* + * Create a Capi OID string value from a DER OID + */ +char* +p11c_der_read_oid(BYTE* oid_tag, DWORD n_oid_tag) +{ + BYTE* oid; + char *oid_str; + char *cstr; + DWORD value; + DWORD n_oid; + + /* wasn't an oid */ + if(P11C_DER_OBJECT_ID != *oid_tag) + return NULL; + + oid = p11c_der_unwrap(oid_tag, n_oid_tag, &n_oid, NULL);; + if(n_oid < 2) + return NULL; + + oid_str = malloc(n_oid * 4); + if(!oid_str) + return NULL; + + cstr = oid_str; + cstr = put_decimal_string(cstr, (*oid) / 40); + *cstr++ = '.'; + cstr = put_decimal_string(cstr, (*oid) % 40); + n_oid--; + + value = 0; + while(n_oid--) + { + oid++; + value = (value << 7) + (*oid & 0x7f); + if(0 == (*oid & 0x80)) + { + *cstr++ = '.'; + cstr = put_decimal_string(cstr, value); + value = 0; + } + } + + *cstr = 0; /* NULL terminate */ + + if(value != 0) + { + free(oid_str); + return NULL; + } + + return oid_str; +} diff --git a/module/p11-capi-der.h b/module/p11-capi-der.h new file mode 100644 index 0000000..0807fcd --- /dev/null +++ b/module/p11-capi-der.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2008 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef P11C_DER_H +#define P11C_DER_H + +#include "p11-capi.h" + +#define P11C_DER_OCTET_STRING 0x04 +#define P11C_DER_OBJECT_ID 0x06 +#define P11C_DER_SEQUENCE 0x10 +#define P11C_DER_CONSTRUCTED 0x20 + +BYTE* p11c_der_unwrap (BYTE* src, DWORD n_src, + DWORD* n_result, BYTE** next); + +char* p11c_der_read_oid (BYTE* oid_tag, DWORD n_oid_tag); + +#endif /* P11C_DER_H */ diff --git a/module/p11-capi-key.c b/module/p11-capi-key.c new file mode 100644 index 0000000..ed306d4 --- /dev/null +++ b/module/p11-capi-key.c @@ -0,0 +1,1083 @@ +/* + * Copyright (C) 2008 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "p11-capi.h" +#include "p11-capi-cert.h" +#include "p11-capi-key.h" +#include "p11-capi-object.h" +#include "p11-capi-session.h" +#include "p11-capi-token.h" +#include "x509-usages.h" + +typedef struct _KeyObject +{ + P11cObject obj; + + /* The raw key identifier */ + CRYPT_HASH_BLOB key_identifier; + CK_OBJECT_CLASS object_class; +} +KeyObject; + +typedef struct _KeyObjectData +{ + P11cObjectData base; + CK_OBJECT_CLASS object_class; + CRYPT_INTEGER_BLOB key_identifier; + CRYPT_DATA_BLOB raw_public_key; + CRYPT_KEY_PROV_INFO* prov_info; +} +KeyObjectData; + +static CK_RV +load_key_handle(P11cObjectData* objdata, HCRYPTPROV* ret_prov, + HCRYPTKEY* ret_key) +{ + KeyObjectData* kdata = (KeyObjectData*)objdata; + HCRYPTPROV prov; + HCRYPTKEY key; + DWORD error; + + ASSERT(kdata); + ASSERT(ret_key); + ASSERT(ret_prov); + + if(!CryptAcquireContextW(&prov, kdata->prov_info->pwszContainerName, + kdata->prov_info->pwszProvName, + kdata->prov_info->dwProvType, 0)) + { + return p11c_winerr_to_ckr(GetLastError()); + } + + if(!CryptGetUserKey(prov, kdata->prov_info->dwKeySpec, &key)) + { + error = GetLastError(); + CryptReleaseContext(prov, 0); + return p11c_winerr_to_ckr(error); + } + + *ret_key = key; + *ret_prov = prov; + + return CKR_OK; +} + + +static CK_RV +load_raw_public_key(KeyObjectData* kdata) +{ + BOOL success = FALSE; + HCRYPTPROV prov; + HCRYPTKEY key; + CK_RV ret; + DWORD error; + + ASSERT(kdata); + ASSERT(!kdata->raw_public_key.pbData); + + ret = load_key_handle(&kdata->base, &prov, &key); + if(ret != CKR_OK) + return ret; + + if(CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &kdata->raw_public_key.cbData)) + { + kdata->raw_public_key.pbData = malloc(kdata->raw_public_key.cbData); + if(!kdata->raw_public_key.pbData) + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + else + { + if(CryptExportKey(key, 0, PUBLICKEYBLOB, 0, kdata->raw_public_key.pbData, + &kdata->raw_public_key.cbData)) + { + success = TRUE; + } + } + } + + CryptReleaseContext(prov, 0); + CryptDestroyKey(key); + + if(success) + { + return CKR_OK; + } + else + { + error = GetLastError(); + if(error == NTE_BAD_KEY_STATE) + return CKR_ATTRIBUTE_SENSITIVE; + return p11c_winerr_to_ckr(error); + } +} + +static CK_RV +lookup_rsa_attribute(KeyObjectData* kdata, CK_ATTRIBUTE_PTR attr) +{ + PUBLICKEYSTRUC* header; + RSAPUBKEY* pubkey; + CK_ULONG number; + CK_RV ret; + + ASSERT(kdata); + ASSERT(attr); + + if(!kdata->raw_public_key.pbData) + { + ret = load_raw_public_key(kdata); + if(ret != CKR_OK) + return ret; + } + + header = (PUBLICKEYSTRUC*)kdata->raw_public_key.pbData; + if(!header->bType == PUBLICKEYBLOB) + return CKR_GENERAL_ERROR; + + pubkey = (RSAPUBKEY*)(header + 1); + if(!pubkey->magic == 0x31415352) + return CKR_GENERAL_ERROR; + + switch(attr->type) + { + case CKA_MODULUS_BITS: + number = pubkey->bitlen; + return p11c_return_data(attr, &number, sizeof(CK_ULONG)); + + case CKA_PUBLIC_EXPONENT: + return p11c_return_dword_as_bytes(attr, pubkey->pubexp); + + case CKA_MODULUS: + return p11c_return_reversed_data(attr, (pubkey + 1), + pubkey->bitlen / 8); + + case CKA_PRIVATE_EXPONENT: + case CKA_PRIME_1: + case CKA_PRIME_2: + case CKA_EXPONENT_1: + case CKA_EXPONENT_2: + case CKA_COEFFICIENT: + if(kdata->object_class == CKO_PRIVATE_KEY) + return CKR_ATTRIBUTE_SENSITIVE; + else + return CKR_ATTRIBUTE_TYPE_INVALID; + + default: + ASSERT(FALSE); + return CKR_ATTRIBUTE_TYPE_INVALID; + } +} + +static CK_RV +key_bool_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) +{ + KeyObjectData* kdata = (KeyObjectData*)objdata; + CK_BBOOL val; + CK_BBOOL is_private, is_rsa; + + ASSERT(objdata); + ASSERT(attr); + + is_private = (kdata->object_class == CKO_PRIVATE_KEY); + is_rsa = kdata->prov_info->dwProvType == PROV_RSA_FULL; + + switch(attr->type) + { + + /* + * Whether to authenticate before every use. + * - CAPI does all authentication + */ + case CKA_ALWAYS_AUTHENTICATE: + val = CK_FALSE; + break; + + /* + * Whether this key has always been sensitive. + * TODO: Can we detect this? + */ + case CKA_ALWAYS_SENSITIVE: + val = CK_FALSE; + break; + + /* + * Whether this key can be used to decrypt. + * - CKK_RSA but not CKK_DSA. + */ + case CKA_DECRYPT: + val = is_private && is_rsa; + break; + + /* + * Whether this key can be used to derive a session or + * other key. + * - Not true for CKK_RSA or CKK_DSA. + */ + case CKA_DERIVE: + val = CK_FALSE; + break; + + /* + * Whether or not this key can be used to encrypt?. + * TODO: Support for RSA public keys. + */ + case CKA_ENCRYPT: + val = CK_FALSE; + break; + + /* + * Whether this key can be exported or not. + * TODO: We may want to support this for public keys. + */ + case CKA_EXTRACTABLE: + val = CK_FALSE; + break; + + /* + * Whether this key was created on token. + * TODO: Can we implement this properly? + */ + case CKA_LOCAL: + val = CK_FALSE; + break; + + /* + * Whether this object is modifiable. + * - Keys are generally. never modifiable. + */ + case CKA_MODIFIABLE: + val = CK_FALSE; + break; + + /* + * Whether this key was ever extractable. + * TODO: Can we determine this? + */ + case CKA_NEVER_EXTRACTABLE: + val = CK_FALSE; + break; + + /* + * Whether this is a private object or not. + * - This 'private' means login before use. But maps + * well to private key use, since we're always logged in. + */ + case CKA_PRIVATE: + val = is_private; + break; + + /* + * Whether this is a sensitive object or not. + * - Private keys are sensitive, some attributes not + * readable. + */ + case CKA_SENSITIVE: + val = is_private; + break; + + /* + * Can this key sign stuff? + * - Private keys can sign. + */ + case CKA_SIGN: + val = is_private; + break; + + /* + * Can this key sign recoverable. + * TODO: Private RSA keys can sign recoverable. + */ + case CKA_SIGN_RECOVER: + val = CK_FALSE; + break; + + /* + * Is this stored on the token? + * - All CAPI objects are. + */ + case CKA_TOKEN: + val = CK_TRUE; + break; + + /* + * Is this key trusted? + * - A nebulous question. + */ + case CKA_TRUSTED: + val = CK_FALSE; + break; + + /* + * Key wrapping with public keys. + */ + case CKA_WRAP: + if(is_private) + return CKR_ATTRIBUTE_TYPE_INVALID; + val = CK_FALSE; + break; + + /* + * Key wrapping on private keys. + */ + case CKA_WRAP_WITH_TRUSTED: + if(!is_private) + return CKR_ATTRIBUTE_TYPE_INVALID; + val = CK_FALSE; + break; + + /* + * Can do a unwrap operation? + * - We don't implement this. + */ + case CKA_UNWRAP: + val = CK_FALSE; + break; + + /* + * Wrap, and unwrap stuff. + * - We don't implement this. + */ + case CKA_UNWRAP_TEMPLATE: + return CKR_ATTRIBUTE_TYPE_INVALID; + + /* + * Whether this key can be used to verify? + * TODO: Support for public keys. + */ + case CKA_VERIFY: + val = CK_FALSE; + break; + + /* + * Whether this key can be used to verify? + * TODO: Support for public keys. + */ + case CKA_VERIFY_RECOVER: + val = CK_FALSE; + break; + + default: + return CKR_ATTRIBUTE_TYPE_INVALID; + }; + + return p11c_return_data(attr, &val, sizeof(CK_BBOOL)); +} + +static CK_RV +key_ulong_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) +{ + KeyObjectData* kdata = (KeyObjectData*)objdata; + CK_ULONG val; + + ASSERT(kdata); + ASSERT(attr); + + switch(attr->type) + { + + /* + * Object class. + */ + case CKA_CLASS: + val = kdata->object_class; + break; + + /* + * The key type. + * - Right now we only support (and load) RSA. + */ + case CKA_KEY_TYPE: + if(kdata->prov_info->dwProvType == PROV_RSA_FULL) + val = CKK_RSA; + else + val = CK_UNAVAILABLE_INFORMATION; + break; + + /* + * The key generation mechanism. + * TODO: We don't yet support key generation. + */ + case CKA_KEY_GEN_MECHANISM: + val = CK_UNAVAILABLE_INFORMATION; + break; + + /* + * The RSA modulus bits. + */ + case CKA_MODULUS_BITS: + if(kdata->prov_info->dwProvType == PROV_RSA_FULL) + return lookup_rsa_attribute(kdata, attr); + else + return CKR_ATTRIBUTE_TYPE_INVALID; + + default: + return CKR_ATTRIBUTE_TYPE_INVALID; + }; + + return p11c_return_data(attr, &val, sizeof(CK_ULONG)); +} + +static CK_RV +key_bytes_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) +{ + KeyObjectData* kdata = (KeyObjectData*)objdata; + CK_MECHANISM_TYPE allowed_mechanisms[] = { CKM_RSA_PKCS }; + WCHAR* label; + + ASSERT(kdata); + ASSERT(attr); + + switch(attr->type) + { + /* + * The ID of the key. This should match the ID we + * return for any matching certificates. + */ + case CKA_ID: + return p11c_return_data(attr, kdata->key_identifier.pbData, + kdata->key_identifier.cbData); + + /* + * The key label. + * - We use the container name. + */ + case CKA_LABEL: + label = kdata->prov_info->pwszContainerName; + if(!label) + label = L"Unnamed Key"; + return p11c_return_string(attr, label); + + /* + * The subject of the related certificate. + * TODO: Implement this lookup. + */ + case CKA_SUBJECT: + return p11c_return_data(attr, "", 0); + + /* + * Allowed mechanisms with this key. + * - RSA used with CKM_RSA + * TODO: Needs updating when DSA implemented. + */ + case CKA_ALLOWED_MECHANISMS: + return p11c_return_data(attr, &allowed_mechanisms, + sizeof(allowed_mechanisms)); + + /* + * Various RSA public attributes. + */ + case CKA_MODULUS: + case CKA_PUBLIC_EXPONENT: + case CKA_PRIVATE_EXPONENT: + case CKA_PRIME_1: + case CKA_PRIME_2: + case CKA_EXPONENT_1: + case CKA_EXPONENT_2: + case CKA_COEFFICIENT: + if(kdata->prov_info->dwProvType == PROV_RSA_FULL) + return lookup_rsa_attribute(kdata, attr); + else + return CKR_ATTRIBUTE_TYPE_INVALID; + + /* + * Last date this key can be used. + * TODO: Does CAPI support this ability? + */ + case CKA_END_DATE: + case CKA_START_DATE: + return p11c_return_data(attr, "", 0); + + default: + return CKR_ATTRIBUTE_TYPE_INVALID; + }; +} + +static void +key_release(void* data) +{ + KeyObjectData* kdata = (KeyObjectData*)data; + ASSERT(kdata); + + ASSERT(kdata->key_identifier.pbData); + ASSERT(kdata->prov_info); + + free(kdata->key_identifier.pbData); + free(kdata->prov_info); + + free(kdata); +} + +static const P11cObjectDataVtable key_objdata_vtable = { + key_bool_attribute, + key_ulong_attribute, + key_bytes_attribute, + key_release, +}; + +static CRYPT_KEY_PROV_INFO* +duplicate_prov_info(CRYPT_KEY_PROV_INFO* original) +{ + DWORD container_length, prov_length; + CRYPT_KEY_PROV_INFO* result; + DWORD length, i; + BYTE* at; + BYTE* end; + + if(!original) + return NULL; + + /* Go through and calculate the length */ + length = sizeof(CRYPT_KEY_PROV_INFO); + if(original->pwszContainerName) + { + container_length = (wcslen(original->pwszContainerName) + 1) * sizeof(WCHAR); + length += container_length; + } + + if(original->pwszProvName) + { + prov_length = (wcslen(original->pwszProvName) + 1) * sizeof(WCHAR); + length += prov_length; + } + + length += sizeof(CRYPT_KEY_PROV_PARAM) * original->cProvParam; + for(i = 0; i < original->cProvParam; ++i) + length += original->rgProvParam[i].cbData; + + /* Allocate a single block of memory for everything */ + at = (BYTE*)malloc(length); + if(!at) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + + /* Copy in very carefully */ + end = at + length; + + memcpy(at, original, sizeof(CRYPT_KEY_PROV_INFO)); + result = (CRYPT_KEY_PROV_INFO*)at; + at += sizeof(CRYPT_KEY_PROV_INFO); + + if(result->pwszContainerName) + { + memcpy(at, result->pwszContainerName, container_length); + result->pwszContainerName = (LPWSTR)at; + at += container_length; + } + + if(result->pwszProvName) + { + memcpy(at, result->pwszProvName, prov_length); + result->pwszProvName = (LPWSTR)at; + at += prov_length; + } + + if(original->cProvParam) + { + memcpy(at, result->rgProvParam, sizeof(CRYPT_KEY_PROV_PARAM) * result->cProvParam); + result->rgProvParam = (CRYPT_KEY_PROV_PARAM*)at; + at += sizeof(CRYPT_KEY_PROV_PARAM) * result->cProvParam; + + for(i = 0; i < result->cProvParam; ++i) + { + memcpy(at, result->rgProvParam[i].pbData, result->rgProvParam[i].cbData); + result->rgProvParam[i].pbData = (BYTE*)at; + at += result->rgProvParam[i].cbData; + } + } + + ASSERT(at == end); + return result; +} + +static P11cObjectData* +key_alloc_data(P11cSession* sess, P11cObject* obj, CRYPT_KEY_PROV_INFO* prov_info) +{ + KeyObject* kobj = (KeyObject*)obj; + KeyObjectData* kdata; + + kdata = (KeyObjectData*)calloc(1, sizeof(KeyObjectData)); + if(!kdata) + return NULL; + + /* Allocate memory for key identifier */ + kdata->key_identifier.pbData = malloc(kobj->key_identifier.cbData); + if(!kdata->key_identifier.pbData) + { + free(kdata); + return NULL; + } + + /* Setup the object data */ + kdata->object_class = kobj->object_class; + kdata->prov_info = prov_info; + kdata->key_identifier.cbData = kobj->key_identifier.cbData; + memcpy(kdata->key_identifier.pbData, kobj->key_identifier.pbData, + kdata->key_identifier.cbData); + kdata->raw_public_key.pbData = NULL; + kdata->raw_public_key.cbData = 0; + + kdata->base.object = obj->id; + kdata->base.data_funcs = &key_objdata_vtable; + + return &(kdata->base); +} + +static BOOL WINAPI +load_key_property_info(PCRYPT_HASH_BLOB key_identifier, DWORD flags, + void* reserved, void* arg, DWORD n_props, DWORD* props, + void** datas, DWORD* n_datas) +{ + CRYPT_KEY_PROV_INFO** prov_info = (CRYPT_KEY_PROV_INFO**)arg; + DWORD i; + + /* + * Already got a provider info. This shouldn't happen + * but can occur if the same key is present twice. + */ + if(*prov_info) + return TRUE; + + /* Find the key provider info property */ + for(i = 0; i < n_props; ++i) + { + if(props[i] == CERT_KEY_PROV_INFO_PROP_ID) + { + *prov_info = duplicate_prov_info((CRYPT_KEY_PROV_INFO*)datas[i]); + break; + } + } + + return TRUE; +} + +static CK_RV +key_load_data(P11cSession* sess, P11cObject* obj, P11cObjectData** objdata) +{ + KeyObject* kobj = (KeyObject*)obj; + CRYPT_KEY_PROV_INFO* prov_info = NULL; + + ASSERT(kobj); + ASSERT(objdata); + + /* Load the provider info */ + if(!CryptEnumKeyIdentifierProperties((CRYPT_HASH_BLOB*)&kobj->key_identifier, + CERT_KEY_PROV_INFO_PROP_ID, 0, NULL, NULL, + &prov_info, load_key_property_info)) + return p11c_winerr_to_ckr(GetLastError()); + + /* No provider info, bad news */ + if(!prov_info) + return CKR_GENERAL_ERROR; + + *objdata = key_alloc_data(sess, obj, prov_info); + if(!(*objdata)) + { + free(prov_info); + return CKR_HOST_MEMORY; + } + + return CKR_OK; +} + +static unsigned int +key_hash_func(P11cObject* obj) +{ + KeyObject* kobj = (KeyObject*)obj; + return p11c_hash_data(kobj->key_identifier.pbData, kobj->key_identifier.cbData) ^ + p11c_hash_integer((int)kobj->object_class); +} + +static int +key_equal_func(P11cObject* a, P11cObject* b) +{ + KeyObject* ka = (KeyObject*)a; + KeyObject* kb = (KeyObject*)b; + return ka->object_class == kb->object_class && + ka->key_identifier.cbData == kb->key_identifier.cbData && + memcmp(ka->key_identifier.pbData, kb->key_identifier.pbData, ka->key_identifier.cbData) == 0; +} + +static void +key_object_release(void* data) +{ + KeyObject* kobj = (KeyObject*)data; + ASSERT(kobj); + free(kobj); +} + +static const P11cObjectVtable key_object_vtable = { + key_load_data, + key_hash_func, + key_equal_func, + key_object_release, +}; + +static CK_RV +register_key_object(P11cSession* sess, CK_OBJECT_CLASS cls, + CRYPT_HASH_BLOB* key_identifier, P11cObject** obj) +{ + KeyObject* kobj; + CK_RV ret; + + ASSERT(obj); + ASSERT(key_identifier); + ASSERT(cls == CKO_PRIVATE_KEY || cls == CKO_PUBLIC_KEY); + + kobj = calloc(1, sizeof(KeyObject) + key_identifier->cbData); + if(!kobj) + return CKR_HOST_MEMORY; + + kobj->obj.id = 0; + kobj->obj.obj_funcs = &key_object_vtable; + + kobj->object_class = cls; + kobj->key_identifier.pbData = (BYTE*)(kobj + 1); + kobj->key_identifier.cbData = key_identifier->cbData; + memcpy(kobj->key_identifier.pbData, key_identifier->pbData, + kobj->key_identifier.cbData); + + ret = p11c_token_register_object(sess->slot, &(kobj->obj)); + if(ret != CKR_OK) + { + free(kobj); + return ret; + } + + ASSERT(kobj->obj.id != 0); + *obj = &(kobj->obj); + + return CKR_OK; +} + +typedef struct _EnumArguments +{ + P11cSession* sess; + CK_OBJECT_CLASS object_class; + CK_ATTRIBUTE_PTR match; + CK_ULONG count; + P11cArray* results; + CK_RV ret; +} +EnumArguments; + +static BOOL WINAPI +enum_key_property_info(PCRYPT_HASH_BLOB key_identifier, DWORD flags, + void* reserved, void* arg, DWORD n_props, DWORD* props, + void** datas, DWORD* n_datas) +{ + EnumArguments* args = (EnumArguments*)arg; + CRYPT_KEY_PROV_INFO* prov_info = NULL; + P11cObject *obj = NULL; + KeyObjectData kdata; + DWORD i; + + /* Find the key provider info property */ + for(i = 0; i < n_props; ++i) + { + if(props[i] == CERT_KEY_PROV_INFO_PROP_ID) + { + prov_info = (CRYPT_KEY_PROV_INFO*)datas[i]; + break; + } + } + + /* Strange key, skip */ + if(!prov_info) + return TRUE; + + /* Match the public key */ + kdata.prov_info = prov_info; + kdata.object_class = args->object_class; + kdata.base.object = 0; + kdata.base.data_funcs = &key_objdata_vtable; + + if(p11c_object_data_match(&kdata.base, args->match, args->count)) + { + args->ret = register_key_object(args->sess, args->object_class, key_identifier, &obj); + if(args->ret == CKR_OK) + { + ASSERT(obj); + p11c_array_append(args->results, obj->id); + } + } + + return TRUE; + +} + +static CK_RV +find_any_keys(P11cSession* sess, CK_OBJECT_CLASS cls, + CK_ATTRIBUTE_PTR match, CK_ULONG count, P11cArray* arr) +{ + CRYPT_HASH_BLOB find_id; + EnumArguments enum_args; + CK_ULONG i; + + /* Try to setup for an efficient search based on key id */ + memset(&find_id, 0, sizeof(find_id)); + for(i = 0; i < count; ++i) + { + if(!match[i].pValue || !match[i].ulValueLen) + continue; + if(match[i].type == CKA_ID) + { + find_id.cbData = match[i].ulValueLen; + find_id.pbData = match[i].pValue; + } + } + + enum_args.sess = sess; + enum_args.match = match; + enum_args.count = count; + enum_args.results = arr; + enum_args.object_class = cls; + enum_args.ret = CKR_OK; + + if(!CryptEnumKeyIdentifierProperties(find_id.cbData != 0 ? &find_id : NULL, + CERT_KEY_PROV_INFO_PROP_ID, 0, NULL, NULL, + &enum_args, enum_key_property_info)) + return p11c_winerr_to_ckr(GetLastError()); + + return enum_args.ret; +} + +static CK_RV +list_matching_certificates(P11cSession* sess, CK_ATTRIBUTE_PTR match, + CK_ULONG count, P11cArray* arr) +{ + CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; + CK_ATTRIBUTE search[3]; + CK_ULONG n_search = 0; + CK_ULONG i; + + /* The class */ + search[0].type = CKA_CLASS; + search[0].pValue = &cert_class; + search[0].ulValueLen = sizeof(CK_OBJECT_CLASS); + ++n_search; + + for(i = 0; i < count && n_search < 3; ++i) + { + /* + * This is the attributes that tie a certificate + * to key object, so try match certs with these + */ + if(match[i].type == CKA_ID) + { + search[n_search].type = match[i].type; + search[n_search].pValue = match[i].pValue; + search[n_search].ulValueLen = match[i].ulValueLen; + ++n_search; + } + } + + /* Do the certificate search */ + return p11c_cert_find(sess, CKO_CERTIFICATE, search, n_search, arr); +} + +static CK_RV +find_certificate_key(P11cSession* session, CK_OBJECT_CLASS cls, + CK_ATTRIBUTE_PTR match, CK_ULONG count, + PCCERT_CONTEXT cert, P11cArray* arr) +{ + CRYPT_KEY_PROV_INFO* prov_info; + CRYPT_HASH_BLOB key_identifier; + P11cObjectData* objdata; + KeyObjectData kdata; + P11cObject* obj; + DWORD prov_length; + DWORD error; + CK_RV ret = CKR_OK; + + /* Look up the key provider info and identifier */ + if(!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &prov_length) || + !CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &key_identifier.cbData)) + { + error = GetLastError(); + if(error == CRYPT_E_NOT_FOUND) + return CKR_OK; + return p11c_winerr_to_ckr(error); + } + + /* We own the info memory */ + prov_info = malloc(prov_length); + if(!prov_info) + return CKR_HOST_MEMORY; + key_identifier.pbData = malloc(key_identifier.cbData); + if(!key_identifier.pbData) + { + free(prov_info); + return CKR_HOST_MEMORY; + } + + /* Lookup the key provider info and identifier */ + if(CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, prov_info, &prov_length) && + CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, key_identifier.pbData, &key_identifier.cbData)) + { + kdata.object_class = cls; + kdata.prov_info = prov_info; + kdata.key_identifier = key_identifier; + kdata.base.object = 0; + kdata.base.data_funcs = &key_objdata_vtable; + + if(p11c_object_data_match(&kdata.base, match, count)) + { + ret = register_key_object(session, cls, &key_identifier, &obj); + if(ret == CKR_OK) + { + ASSERT(obj); + + /* Store away the object data for performance reasons */ + objdata = key_alloc_data(session, obj, prov_info); + if(objdata) + { + p11c_session_take_object_data(session, obj, objdata); + + /* Note these are used, and not to be freed */ + key_identifier.pbData = NULL; + key_identifier.cbData = 0; + prov_info = NULL; + } + + p11c_array_append(arr, obj->id); + } + } + } + else + { + ret = p11c_winerr_to_ckr(GetLastError()); + } + + if(key_identifier.pbData) + free(key_identifier.pbData); + if(prov_info) + free(prov_info); + + return ret; +} + +static CK_RV +find_certificate_keys(P11cSession* session, CK_OBJECT_CLASS cls, + CK_ATTRIBUTE_PTR match, CK_ULONG count, P11cArray* arr) +{ + CK_OBJECT_HANDLE id; + P11cObjectData* certdata; + P11cArray* certarr; + PCCERT_CONTEXT cert; + CK_RV ret = CKR_OK; + CK_ULONG i; + + /* Get a list of all certificates */ + certarr = p11c_array_new(0, 1, sizeof(CK_OBJECT_HANDLE)); + if(!certarr) + return CKR_HOST_MEMORY; + ret = list_matching_certificates(session, match, count, certarr); + + /* Now match each of them against our criteria */ + if(ret == CKR_OK) + { + for(i = 0; i < certarr->len; ++i) + { + id = p11c_array_index(certarr, CK_OBJECT_HANDLE, i); + ASSERT(id); + + /* Get the certificate data for this certificate object */ + if(p11c_session_get_object_data_for(session, id, &certdata) != CKR_OK) + continue; + + /* Get the certificate context */ + cert = p11c_cert_object_data_get_certificate(certdata); + if(!cert) + continue; + + /* Remember we can have either or both keys for each certificate */ + ret = find_certificate_key(session, cls, match, count, cert, arr); + } + } + + p11c_array_free(certarr, TRUE); + return ret; +} + +CK_RV +p11c_key_find(P11cSession* sess, CK_OBJECT_CLASS cls, + CK_ATTRIBUTE_PTR match, CK_ULONG count, P11cArray* arr) +{ + CK_RV ret = CKR_OK; + + /* Is this somewhere we have all keys present? */ + if(p11c_token_get_flags(sess->slot) & P11C_SLOT_ANYKEY) + { + if((cls == CKO_PRIVATE_KEY || cls == CKO_ANY) && ret == CKR_OK) + ret = find_any_keys(sess, CKO_PRIVATE_KEY, match, count, arr); + if((cls == CKO_PUBLIC_KEY || cls == CKO_ANY) && ret == CKR_OK) + ret = find_any_keys(sess, CKO_PUBLIC_KEY, match, count, arr); + } + + /* Otherwise we can only list the keys that have certificates */ + else + { + if((cls == CKO_PRIVATE_KEY || cls == CKO_ANY) && ret == CKR_OK) + ret = find_certificate_keys(sess, CKO_PRIVATE_KEY, match, count, arr); + if((cls == CKO_PUBLIC_KEY || cls == CKO_ANY) && ret == CKR_OK) + ret = find_certificate_keys(sess, CKO_PUBLIC_KEY, match, count, arr); + } + + return ret; +} + +DWORD +p11c_key_object_data_get_bits(P11cObjectData* objdata) +{ + KeyObjectData* kdata; + PUBLICKEYSTRUC* header; + RSAPUBKEY* pubkey; + CK_RV ret; + + ASSERT(objdata); + + kdata = (KeyObjectData*)objdata; + + if(!kdata->raw_public_key.pbData) + { + ret = load_raw_public_key(kdata); + if(ret != CKR_OK) + return ret; + } + + header = (PUBLICKEYSTRUC*)kdata->raw_public_key.pbData; + if(!header->bType == PUBLICKEYBLOB) + return 0; + + pubkey = (RSAPUBKEY*)(header + 1); + if(!pubkey->magic == 0x31415352) + return 0; + + return pubkey->bitlen; +} + +CRYPT_KEY_PROV_INFO* +p11c_key_object_data_get_prov_info(P11cObjectData* objdata) +{ + KeyObjectData* kdata; + + ASSERT(objdata); + kdata = (KeyObjectData*)objdata; + return kdata->prov_info; +} diff --git a/module/p11-capi-key.h b/module/p11-capi-key.h new file mode 100644 index 0000000..b57a2d3 --- /dev/null +++ b/module/p11-capi-key.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2008 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef P11C_KEY_H +#define P11C_KEY_H + +#include "p11-capi.h" + +/* Find key objects matching criteria */ +CK_RV p11c_key_find (P11cSession* sess, CK_OBJECT_CLASS cls, + CK_ATTRIBUTE_PTR match, CK_ULONG count, + P11cArray* arr); + +DWORD p11c_key_object_data_get_bits (P11cObjectData* objdata); + +CRYPT_KEY_PROV_INFO* p11c_key_object_data_get_prov_info (P11cObjectData* objdata); + +#endif /* P11C_KEY_H */ diff --git a/module/p11-capi-object.c b/module/p11-capi-object.c new file mode 100644 index 0000000..6c2330e --- /dev/null +++ b/module/p11-capi-object.c @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "p11-capi.h" +#include "p11-capi-object.h" + +#include "pkcs11/pkcs11n.h" + +#include + +enum +{ + DATA_UNKNOWN = 0, + DATA_BOOL, + DATA_ULONG, + DATA_BYTES +}; + +int +attribute_data_type(CK_ATTRIBUTE_TYPE type) +{ + switch(type) + { + // CK_ULONG attribute types + case CKA_CLASS: + case CKA_CERTIFICATE_TYPE: + case CKA_CERTIFICATE_CATEGORY: + case CKA_KEY_TYPE: + case CKA_MODULUS_BITS: + case CKA_PRIME_BITS: + /* case CKA_SUBPRIME_BITS: */ + case CKA_SUB_PRIME_BITS: + case CKA_VALUE_BITS: + case CKA_VALUE_LEN: + case CKA_KEY_GEN_MECHANISM: + case CKA_HW_FEATURE_TYPE: + case CKA_PIXEL_X: + case CKA_PIXEL_Y: + case CKA_RESOLUTION: + case CKA_CHAR_ROWS: + case CKA_CHAR_COLUMNS: + case CKA_BITS_PER_PIXEL: + case CKA_MECHANISM_TYPE: + case CKA_JAVA_MIDP_SECURITY_DOMAIN: + case CKA_TRUST_SERVER_AUTH: + case CKA_TRUST_CLIENT_AUTH: + case CKA_TRUST_CODE_SIGNING: + case CKA_TRUST_EMAIL_PROTECTION: + case CKA_TRUST_IPSEC_END_SYSTEM: + case CKA_TRUST_IPSEC_TUNNEL: + case CKA_TRUST_IPSEC_USER: + case CKA_TRUST_TIME_STAMPING: + return DATA_ULONG; + + // CK_BBOOL attribute types + case CKA_TOKEN: + case CKA_PRIVATE: + case CKA_MODIFIABLE: + case CKA_TRUSTED: + case CKA_SENSITIVE: + case CKA_DECRYPT: + case CKA_SIGN: + case CKA_SIGN_RECOVER: + case CKA_UNWRAP: + case CKA_EXTRACTABLE: + case CKA_NEVER_EXTRACTABLE: + case CKA_ALWAYS_SENSITIVE: + case CKA_WRAP_WITH_TRUSTED: + case CKA_ALWAYS_AUTHENTICATE: + case CKA_ENCRYPT: + case CKA_WRAP: + case CKA_VERIFY: + case CKA_VERIFY_RECOVER: + case CKA_DERIVE: + case CKA_LOCAL: + case CKA_RESET_ON_INIT: + case CKA_HAS_RESET: + case CKA_COLOR: + case CKA_TRUST_STEP_UP_APPROVED: + return DATA_BOOL; + + // Raw or string data + case CKA_LABEL: + case CKA_APPLICATION: + case CKA_VALUE: + case CKA_OBJECT_ID: + case CKA_CHECK_VALUE: + case CKA_ISSUER: + case CKA_SERIAL_NUMBER: + case CKA_SUBJECT: + case CKA_ID: + case CKA_URL: + case CKA_HASH_OF_SUBJECT_PUBLIC_KEY: + case CKA_HASH_OF_ISSUER_PUBLIC_KEY: + case CKA_AC_ISSUER: + case CKA_OWNER: + case CKA_ATTR_TYPES: + case CKA_MODULUS: + case CKA_PUBLIC_EXPONENT: + case CKA_PRIVATE_EXPONENT: + case CKA_PRIME_1: + case CKA_PRIME_2: + case CKA_EXPONENT_1: + case CKA_EXPONENT_2: + case CKA_COEFFICIENT: + case CKA_PRIME: + case CKA_SUBPRIME: + case CKA_BASE: + case CKA_ECDSA_PARAMS: + /* case CKA_EC_PARAMS: */ + case CKA_EC_POINT: + case CKA_CHAR_SETS: + case CKA_ENCODING_METHODS: + case CKA_MIME_TYPES: + case CKA_REQUIRED_CMS_ATTRIBUTES: + case CKA_DEFAULT_CMS_ATTRIBUTES: + case CKA_SUPPORTED_CMS_ATTRIBUTES: + case CKA_CERT_SHA1_HASH: + case CKA_CERT_MD5_HASH: + case CKA_ALLOWED_MECHANISMS: + case CKA_START_DATE: + case CKA_END_DATE: + return DATA_BYTES; + + // Arrays are nasty + case CKA_WRAP_TEMPLATE: + case CKA_UNWRAP_TEMPLATE: + default: + DBG(("unknown attribute type: %x", type)); + return DATA_UNKNOWN; + }; +} + +CK_BBOOL +p11c_object_data_match_attr(P11cObjectData* objdata, CK_ATTRIBUTE_PTR match) +{ + CK_ATTRIBUTE attr; + CK_RV rv; + int dtype; + + ASSERT(match); + ASSERT(objdata); + ASSERT(objdata->data_funcs); + + /* Get the data type of the attribute */ + dtype = attribute_data_type(match->type); + if(dtype == DATA_UNKNOWN) + return CK_FALSE; + + /* We only do byte matching */ + if(match->pValue == NULL) + return CK_FALSE; + + /* Only load as much data as is needed */ + attr.type = match->type; + attr.pValue = _alloca(match->ulValueLen > 4 ? match->ulValueLen : 4); + attr.ulValueLen = match->ulValueLen; + + switch(dtype) + { + case DATA_BOOL: + rv = (objdata->data_funcs->get_bool)(objdata, &attr); + break; + case DATA_ULONG: + rv = (objdata->data_funcs->get_ulong)(objdata, &attr); + break; + case DATA_BYTES: + rv = (objdata->data_funcs->get_bytes)(objdata, &attr); + break; + default: + ASSERT(0 && "unrecognized type"); + break; + }; + + /* Unrecognized attribute */ + if(rv == CKR_ATTRIBUTE_TYPE_INVALID) + return CK_FALSE; + + /* Value is longer than this one */ + if(rv == CKR_BUFFER_TOO_SMALL) + return CK_FALSE; + + /* All other errors */ + if(rv != CKR_OK) + return CK_FALSE; + + return (match->ulValueLen == attr.ulValueLen && + memcmp(match->pValue, attr.pValue, attr.ulValueLen) == 0); +} + +CK_BBOOL +p11c_object_data_match(P11cObjectData* objdata, CK_ATTRIBUTE_PTR matches, + CK_ULONG count) +{ + CK_ULONG i; + + for(i = 0; i < count; ++i) + { + if(!p11c_object_data_match_attr(objdata, &matches[i])) + return CK_FALSE; + } + + return CK_TRUE; +} + +CK_RV +p11c_object_data_get_attrs(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attrs, + CK_ULONG count) +{ + CK_ULONG i; + CK_RV rv, ret = CKR_OK; + + ASSERT(objdata); + ASSERT(!count || attrs); + + for(i = 0; i < count; ++i) + { + /* Get the data type of the attribute */ + switch(attribute_data_type(attrs[i].type)) + { + case DATA_BOOL: + rv = (objdata->data_funcs->get_bool)(objdata, &attrs[i]); + break; + case DATA_ULONG: + rv = (objdata->data_funcs->get_ulong)(objdata, &attrs[i]); + break; + case DATA_BYTES: + rv = (objdata->data_funcs->get_bytes)(objdata, &attrs[i]); + break; + case DATA_UNKNOWN: + rv = CKR_ATTRIBUTE_TYPE_INVALID; + break; + default: + ASSERT(0 && "unrecognized type"); + break; + }; + + /* Not an error if they were just requesting the size */ + if(rv != CKR_OK) + { + if(rv == CKR_BUFFER_TOO_SMALL) + { + if(!attrs[i].pValue) + rv = CKR_OK; + } + + /* Attribute is sensitive */ + else if(rv == CKR_ATTRIBUTE_SENSITIVE) + { + attrs[i].ulValueLen = (CK_ULONG)-1; + } + + /* Attribute doesn't exist */ + else if(rv == CKR_ATTRIBUTE_TYPE_INVALID) + { + DBG(("O%d: attribute not found: 0x%08x", objdata->object, attrs[i].type)); + attrs[i].ulValueLen = (CK_ULONG)-1; + } + + /* A fatal error? */ + else + { + ret = rv; + break; + } + + /* Transfer any non-fatal errors outward */ + if(rv != CKR_OK && ret == CKR_OK) + ret = rv; + } + } + + return ret; +} diff --git a/module/p11-capi-object.h b/module/p11-capi-object.h new file mode 100644 index 0000000..e884ee1 --- /dev/null +++ b/module/p11-capi-object.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef P11C_OBJECT_H +#define P11C_OBJECT_H + +#include "p11-capi.h" + +/* Debug print something about an object */ +#define DBGO(obj, msg) \ + p11c_debug("O%d: %s", (obj) ? (obj)->id : 0, (msg)) + +/* A function to load data for an object */ +typedef CK_RV (*P11cLoadData)(P11cSession* sess, struct _P11cObject* obj, + P11cObjectData** objdata); + +/* Produce a hash code for an object */ +typedef CK_RV (*P11cHashObject)(struct _P11cObject* obj); + +/* Produce a hash code for an object */ +typedef CK_RV (*P11cEqualObject)(struct _P11cObject* one, struct _P11cObject* two); + +/* A function to free some data */ +typedef void (*P11cRelease)(void* data); + +/* Object functions */ +typedef struct _P11cObjectVtable +{ + P11cLoadData load_data; + P11cHashObject hash_object; + P11cEqualObject equal_object; + P11cRelease release; +} +P11cObjectVtable; + +/* Represents a object we've seen */ +struct _P11cObject +{ + CK_OBJECT_HANDLE id; + CK_SLOT_ID slot; + CK_SESSION_HANDLE session; + const P11cObjectVtable* obj_funcs; +}; + +/* A function to get an attribute from ObjectData */ +typedef CK_RV (*P11cGetAttribute)(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr); + +/* Object data functions */ +typedef struct _P11cObjectDataVtable +{ + P11cGetAttribute get_bool; + P11cGetAttribute get_ulong; + P11cGetAttribute get_bytes; + P11cRelease release; +} +P11cObjectDataVtable; + +/* + * Base class for object data. Different types of + * objects extend this with more detailed data + */ +struct _P11cObjectData +{ + CK_OBJECT_HANDLE object; + const P11cObjectDataVtable* data_funcs; +}; + +/* Match object data against all the given match attributes */ +CK_BBOOL p11c_object_data_match (P11cObjectData* objdata, + CK_ATTRIBUTE_PTR matches, CK_ULONG count); + +/* Match a single attribute against object data */ +CK_BBOOL p11c_object_data_match_attr (P11cObjectData* objdata, + CK_ATTRIBUTE_PTR match); + +/* Get a bunch of attributes from object data */ +CK_RV p11c_object_data_get_attrs (P11cObjectData* objdata, CK_ATTRIBUTE_PTR attrs, + CK_ULONG count); + +/* Debug print something about an object data */ +#define DBGOD(objdata, msg) \ + p11c_debug("O%d: %s", (objdata) ? (objdata)->obj : 0, (msg)) + +#endif /* P11C_OBJECT_H */ diff --git a/module/p11-capi-rsa.c b/module/p11-capi-rsa.c new file mode 100644 index 0000000..18fc4eb --- /dev/null +++ b/module/p11-capi-rsa.c @@ -0,0 +1,415 @@ +/* + * Copyright (C) 2008 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "p11-capi.h" +#include "p11-capi-der.h" +#include "p11-capi-key.h" +#include "p11-capi-object.h" + +/* + * Portions derived from NSS source files: + * lib/ckfw/capi/crsa.c + */ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Red Hat, Inc. + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#define SSL3_SHAMD5_HASH_SIZE 36 /* LEN_MD5 (16) + LEN_SHA1 (20) */ + +/* + * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value, + * which includes the hash OID. CAPI expects to take a Hash Context. While + * CAPI does have the capability of setting a raw hash value, it does not + * have the ability to sign an arbitrary value. This function tries to + * reduce the passed in data into something that CAPI could actually sign. + */ +static CK_BYTE_PTR +parse_rsa_pkcs_der_hash(CK_BYTE_PTR input, CK_ULONG n_input, + ALG_ID* algorithm, CK_ULONG_PTR n_hash) +{ + BYTE* algid; + BYTE* oid; + BYTE* hash_data; + BYTE* oid_str; + DWORD n_oid; + DWORD n_algid; + + /* + * there are 2 types of hashes NSS typically tries to sign, regular + * RSA signature format (with encoded DER_OIDS), and SSL3 Signed hashes. + * CAPI knows not to add any oids to SSL3_Signed hashes, so if we have any + * random hash that is exactly the same size as an SSL3 hash, then we can + * just pass the data through. CAPI has know way of knowing if the value + * is really a combined hash or some other arbitrary data, so it's safe to + * handle this case first. + */ + if(SSL3_SHAMD5_HASH_SIZE == n_input) + { + *n_hash = n_input; + *algorithm = CALG_SSL3_SHAMD5; + return input; + } + + /* make sure we have a sequence tag */ + if((P11C_DER_SEQUENCE | P11C_DER_CONSTRUCTED) != *input) + return NULL; + + /* + * parse the input block to get 1) the hash oid, and 2) the raw hash value. + * unfortunatly CAPI doesn't have a builtin function to do this work, so + * we go ahead and do it by hand here. + * + * format is: + * SEQUENCE { + * SECQUENCE { // algid + * OID {} // oid + * ANY {} // optional params + * } + * OCTECT {} // hash + */ + + /* unwrap */ + algid = p11c_der_unwrap(input, n_input, &n_algid, NULL); + if(!algid) + return NULL; + + /* make sure there is not extra data at the end */ + if(algid + n_algid != input + n_input) + return NULL; + + /* wasn't an algid */ + if((P11C_DER_SEQUENCE | P11C_DER_CONSTRUCTED) != *algid) + return NULL; + + oid = p11c_der_unwrap(algid, n_algid, &n_oid, &hash_data); + if(!oid || !hash_data) + return NULL; + + if(algorithm) + { + /* + * get the real oid as a string. Again, Microsoft does not + * export anything that does this for us + */ + oid_str = p11c_der_read_oid(oid, n_oid); + if(!oid_str) + return NULL; + + /* look up the hash alg from the oid (fortunately CAPI does to this) */ + *algorithm = CertOIDToAlgId(oid_str); + free(oid_str); + } + + /* wasn't a hash? */ + if(P11C_DER_OCTET_STRING != *hash_data) + return NULL; + + /* get the real raw hash */ + return p11c_der_unwrap(hash_data, n_algid - (hash_data - algid), + n_hash, NULL); +} + +CK_RV +p11c_rsa_pkcs_sign_init(P11cObjectData *keydata, void** operation) +{ + CRYPT_KEY_PROV_INFO* prov_info; + + ASSERT(keydata); + ASSERT(operation); + ASSERT(!*operation); + + prov_info = p11c_key_object_data_get_prov_info(keydata); + if(prov_info->dwProvType != PROV_RSA_FULL) + return CKR_KEY_TYPE_INCONSISTENT; + + *operation = keydata; + return CKR_OK; +} + +CK_RV +p11c_rsa_pkcs_sign_perform (CK_BYTE_PTR data, CK_ULONG n_data, + CK_BYTE_PTR signature, CK_ULONG_PTR n_signature, + void** operation) +{ + CRYPT_KEY_PROV_INFO* prov_info; + P11cObjectData* keydata; + ALG_ID algorithm; + BYTE* hash_data; + DWORD n_hash_data; + BOOL capifail; + DWORD len, check; + DWORD bits; + CK_RV ret; + + HCRYPTPROV prov = 0; + HCRYPTHASH hash = 0; + + + ASSERT(operation); + ASSERT(*operation); + + if(!data || !n_data) + return CKR_ARGUMENTS_BAD; + + keydata = (P11cObjectData*)*operation; + + prov_info = p11c_key_object_data_get_prov_info(keydata); + ASSERT(prov_info); + + /* Calculate the number of bits */ + bits = p11c_key_object_data_get_bits (keydata); + if(!bits) + return CKR_GENERAL_ERROR; + + /* Want to know the length */ + if(!signature) + { + *n_signature = bits / 8; + return CKR_OK; + } + + /* TODO: Support arbitrary input on Vista */ + + /* + * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value, + * which includes the hash OID. CAPI expects to take a Hash Context. While + * CAPI does have the capability of setting a raw hash value, it does not + * have the ability to sign an arbitrary value. This function tries to + * reduce the passed in data into something that CAPI could actually sign. + */ + hash_data = parse_rsa_pkcs_der_hash(data, n_data, &algorithm, &n_hash_data); + if(!hash_data) + return CKR_DATA_INVALID; + + capifail = TRUE; + if(CryptAcquireContextW(&prov, prov_info->pwszContainerName, prov_info->pwszProvName, + prov_info->dwProvType, 0)) + { + if(CryptCreateHash(prov, algorithm, 0, 0, &hash)) + { + /* make sure the hash lens match before we set it */ + len = sizeof(DWORD); + if(CryptGetHashParam(hash, HP_HASHSIZE, (BYTE*)&check, &len, 0)) + { + if(check != n_hash_data) + { + capifail = FALSE; + ret = CKR_DATA_INVALID; + } + + /* + * we have an explicit hash, set it, note that the length is + * implicit by the hashAlg used in create + */ + if(CryptSetHashParam(hash, HP_HASHVAL, hash_data, 0)) + { + /* OK, we have the data in a hash structure, sign it! */ + if(CryptSignHash(hash, prov_info->dwKeySpec, + NULL, 0, signature, n_signature)) + { + /* + * OK, Microsoft likes to do things completely + * differently than anyone else. We need to reverse + * the data we recieved here + */ + if(signature) + p11c_reverse_memory(signature, *n_signature); + + capifail = FALSE; + ret = CKR_OK; + } + } + } + } + } + + if(capifail) + ret = p11c_winerr_to_ckr(GetLastError()); + + if(hash) + CryptDestroyHash(hash); + if(prov) + CryptReleaseContext(prov, 0); + + return ret; +} + +void +p11c_rsa_pkcs_sign_cleanup (void* operation) +{ + /* Nothing to do */ +} + + +CK_RV +p11c_rsa_pkcs_decrypt_init(P11cObjectData* keydata, void** operation) +{ + CRYPT_KEY_PROV_INFO* prov_info; + + ASSERT(keydata); + ASSERT(operation); + ASSERT(!*operation); + + prov_info = p11c_key_object_data_get_prov_info(keydata); + if(prov_info->dwProvType != PROV_RSA_FULL) + return CKR_KEY_TYPE_INCONSISTENT; + + *operation = keydata; + return CKR_OK; +} + +CK_RV +p11c_rsa_pkcs_decrypt_perform(CK_BYTE_PTR encdata, CK_ULONG n_encdata, + CK_BYTE_PTR result, CK_ULONG_PTR n_result, + void** operation) +{ + CRYPT_KEY_PROV_INFO* prov_info; + P11cObjectData* keydata; + BOOL capifail; + DWORD bits, error; + CK_RV ret; + + HCRYPTPROV prov = 0; + HCRYPTKEY key = 0; + void* buffer = NULL; + + ASSERT(operation); + ASSERT(*operation); + ASSERT(encdata); + ASSERT(n_encdata); + + keydata = (P11cObjectData*)*operation; + + prov_info = p11c_key_object_data_get_prov_info(keydata); + ASSERT(prov_info); + + /* Calculate the number of bits */ + bits = p11c_key_object_data_get_bits (keydata); + if(!bits) + return CKR_GENERAL_ERROR; + + /* Want to know the length */ + if(!result) + { + *n_result = bits / 8; + return CKR_OK; + } + + /* + * Copy the input, since CAPI operates in place, and + * we must also reverse it properly. + */ + buffer = malloc(n_encdata); + if(!buffer) + return CKR_HOST_MEMORY; + + memcpy(buffer, encdata, n_encdata); + p11c_reverse_memory(buffer, n_encdata); + + capifail = TRUE; + if(CryptAcquireContextW(&prov, prov_info->pwszContainerName, prov_info->pwszProvName, + prov_info->dwProvType, 0)) + { + if(CryptGetUserKey(prov, prov_info->dwKeySpec, &key)) + { + *n_result = n_encdata; + if(CryptDecrypt(key, 0, TRUE, 0, buffer, n_result)) + { + capifail = FALSE; + ret = CKR_OK; + } + } + } + + if(capifail) + { + error = GetLastError(); + switch(error) + { + case NTE_BAD_DATA: + ret = CKR_ENCRYPTED_DATA_INVALID; + default: + ret = p11c_winerr_to_ckr(error); + }; + } + + /* Copy the memory out to the result buffer */ + if(ret == CKR_OK) + ret = p11c_return_data_raw(result, n_result, buffer, *n_result); + + if(key) + CryptDestroyKey(key); + if(prov) + CryptReleaseContext(prov, 0); + if(buffer) + free(buffer); + + return ret; +} + +void +p11c_rsa_pkcs_decrypt_cleanup(void* operation) +{ + /* Nothing to do */ +} + +void +p11c_rsa_pkcs_get_info(CK_MECHANISM_TYPE mech, CK_MECHANISM_INFO_PTR info) +{ + ASSERT(mech == CKM_RSA_PKCS); + ASSERT(info != NULL); + + info->ulMinKeySize = 384; + info->ulMaxKeySize = 16384; + info->flags = 0; +} diff --git a/module/p11-capi-rsa.h b/module/p11-capi-rsa.h new file mode 100644 index 0000000..0ce571e --- /dev/null +++ b/module/p11-capi-rsa.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef P11C_RSA_H +#define P11C_RSA_H + +#include "p11-capi.h" + +CK_RV p11c_rsa_pkcs_sign_init (P11cObjectData* keydata, void** operation); + +CK_RV p11c_rsa_pkcs_sign_perform (CK_BYTE_PTR data, CK_ULONG data_len, + CK_BYTE_PTR signature, CK_ULONG_PTR signature_len, + void** operation); + +void p11c_rsa_pkcs_sign_cleanup (void* operation); + +CK_RV p11c_rsa_pkcs_decrypt_init (P11cObjectData* keydata, void** operation); + +CK_RV p11c_rsa_pkcs_decrypt_perform (CK_BYTE_PTR encdata, CK_ULONG n_encdata, + CK_BYTE_PTR result, CK_ULONG_PTR n_result, + void** operation); + +void p11c_rsa_pkcs_decrypt_cleanup (void* operation); + +void p11c_rsa_pkcs_get_info (CK_MECHANISM_TYPE mech, + CK_MECHANISM_INFO_PTR info); + +#endif /* P11C_RSA_H */ diff --git a/module/p11-capi-session.c b/module/p11-capi-session.c new file mode 100644 index 0000000..e921875 --- /dev/null +++ b/module/p11-capi-session.c @@ -0,0 +1,983 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#include "p11-capi.h" +#include "p11-capi-builtin.h" +#include "p11-capi-cert.h" +#include "p11-capi-key.h" +#include "p11-capi-object.h" +#include "p11-capi-rsa.h" +#include "p11-capi-session.h" +#include "p11-capi-token.h" +#include "p11-capi-trust.h" + +/* For operation_type in P11cSession */ +enum +{ + OPERATION_NONE, + OPERATION_FIND, + OPERATION_SIGN, + OPERATION_DECRYPT +}; + +static P11cArray* all_sessions = NULL; + +static void +object_data_release(P11cObjectData* objdata) +{ + ASSERT(objdata->data_funcs); + ASSERT(objdata->data_funcs->release); + (objdata->data_funcs->release)(objdata); +} + +CK_RV +p11c_session_create(CK_SLOT_ID slot, P11cSession** ret) +{ + P11cSession* sess; + const char *store; + DWORD err; + + sess = calloc(1, sizeof(P11cSession)); + if(!sess) + return CKR_HOST_MEMORY; + + sess->object_data = p11c_hash_new(NULL, NULL); + if(!sess->object_data) { + free(sess); + return CKR_HOST_MEMORY; + } + + sess->mutex = CreateMutex(NULL, FALSE, NULL); + if(!sess->mutex) { + p11c_hash_free(sess->object_data, NULL); + free(sess); + return CKR_HOST_MEMORY; + } + + store = p11c_token_get_store_name(slot); + if(store) + { + sess->store = CertOpenSystemStore((HCRYPTPROV)NULL, store); + if(sess->store == NULL) + { + err = GetLastError(); + + /* Store not found, we don't care */ + if(err != ERROR_FILE_NOT_FOUND) + { + p11c_hash_free(sess->object_data, NULL); + CloseHandle(sess->mutex); + free(sess); + return p11c_winerr_to_ckr(err); + } + } + } + + sess->slot = slot; + + DBGS(sess, "created"); + + *ret = sess; + return CKR_OK; +} + +CK_RV +p11c_session_register(P11cSession* sess) +{ + P11cSession* blank = NULL; + CK_SESSION_HANDLE id = 0; + CK_RV ret = CKR_OK; + size_t i; + + ASSERT(sess); + ASSERT(sess->id == 0 && sess->refs == 0); + + DBGS(sess, "registering new session"); + + p11c_lock_global(); + + /* Find a nice session identifier */ + while(id == 0) { + + /* Allocate sessions properly */ + if(!all_sessions) + { + all_sessions = p11c_array_new(0, 1, sizeof(P11cSession*)); + if(!all_sessions) + { + ret = CKR_HOST_MEMORY; + break; + } + + /* A blank entry for '0' */ + p11c_array_append(all_sessions, blank); + + DBG(("allocated new session list")); + } + + /* + * PKCS#11 GRAY AREA: We're assuming we can reuse session + * handles. PKCS#11 spec says they're like file handles, + * and file handles get reused :) + */ + + /* Note we never put anything in array position '0' */ + for(i = 1; i < all_sessions->len; ++i) + { + /* Any empty position will do */ + if(!p11c_array_index(all_sessions, P11cSession*, i)) + { + id = i; + break; + } + } + + /* Couldn't find a handle, append a handle */ + if(id == 0) + { + id = all_sessions->len; + p11c_array_append(all_sessions, blank); + } + } + + if(ret == CKR_OK) + { + ASSERT(id > 0 && id < all_sessions->len); + ASSERT(!p11c_array_index(all_sessions, P11cSession*, id)); + + + /* And assign it to the session handle */ + p11c_array_index(all_sessions, P11cSession*, i) = sess; + sess->id = id; + + /* The session list reference */ + ASSERT(sess->refs == 0); + sess->refs++; + + DBGS(sess, "registered sesson id"); + } + + p11c_unlock_global(); + + return ret; +} + +void +p11c_session_destroy(P11cSession* sess) +{ + ASSERT(sess); + ASSERT(sess->refs == 0); + + /* Ask any pending operations to cleanup */ + if(sess->operation_type) + { + ASSERT(sess->operation_cancel); + (sess->operation_cancel)(sess); + } + + ASSERT(sess->operation_type == 0); + ASSERT(sess->operation_data == NULL); + ASSERT(sess->operation_cancel == NULL); + + if(sess->store) + CertCloseStore(sess->store, 0); + + /* Make all the object adat go away */ + ASSERT(sess->object_data != NULL); + p11c_hash_free(sess->object_data, object_data_release); + + /* And make the mutex go away */ + ASSERT(sess->mutex != NULL); + CloseHandle(sess->mutex); + + DBGS(sess, "destroyed"); + free(sess); +} + +void +p11c_session_get_info(P11cSession* sess, CK_SESSION_INFO_PTR info) +{ + ASSERT(sess); + ASSERT(info); + + info->slotID = sess->slot; + info->flags = CKF_SERIAL_SESSION; + if(sess->read_write) + info->flags |= CKF_RW_SESSION; + + if(p11c_token_is_logged_in(sess->slot)) + info->state = sess->read_write ? CKS_RW_USER_FUNCTIONS : CKS_RO_USER_FUNCTIONS; + else + info->state = sess->read_write ? CKS_RW_PUBLIC_SESSION : CKS_RO_PUBLIC_SESSION; + + /* TODO: We could implement some use of GetLastError() here */ + info->ulDeviceError = 0; +} + +static CK_RV +lock_ref_internal(P11cArray* sessions, CK_SESSION_HANDLE id, + BOOL remove, BOOL writable, P11cSession** sess_ret) +{ + P11cSession *sess; + DWORD r; + + ASSERT(sessions); + ASSERT(sess_ret); + + if(id >= sessions->len) + { + DBG(("invalid session id: %d", id)); + return CKR_SESSION_HANDLE_INVALID; + } + + /* A seemingly valid id */ + ASSERT(sessions); + sess = p11c_array_index(sessions, P11cSession*, id); + + if(!sess) + { + DBG(("session does not exist: %d", id)); + return CKR_SESSION_HANDLE_INVALID; + } + + /* Make sure it's the right kind of session */ + if(writable && !sess->read_write) + return CKR_SESSION_READ_ONLY; + + ASSERT(sess->id == id); + + /* Closing takes precedence over active operations */ + if(!remove) + { + /* + * An initial check is done to make sure this session is not active. + * This is done outside of the lock. The real check is done later + * inside a lock. This is so we can return quickly without blocking + * in most cases. + */ + + if(sess->in_call) + { + DBGS(sess, ("an operation is already active in this session")); + return CKR_OPERATION_ACTIVE; + } + } + + /* Lock the CallP11cSession */ + r = WaitForSingleObject(sess->mutex, INFINITE); + ASSERT(r == WAIT_OBJECT_0); + + /* Do the real check */ + if(!remove && sess->in_call) + { + ReleaseMutex(sess->mutex); + DBGS(sess, ("an operation is already active in this session")); + return CKR_OPERATION_ACTIVE; + } + + /* Make sure it doesn't go away */ + ASSERT(sess->refs > 0); + sess->refs++; + + DBGS(sess, "found and locked session"); + + /* And remove it if necessary */ + if(remove) + { + p11c_array_index(sessions, P11cSession*, id) = NULL; + + /* The session list reference */ + sess->refs--; + ASSERT(sess->refs > 0); + + DBGS(sess, "removed session from list"); + } + else + { + ASSERT(!sess->in_call); + sess->in_call = 1; + } + + *sess_ret = sess; + return CKR_OK; +} + +CK_RV +p11c_session_get_lock_ref(CK_ULONG id, BOOL writable, P11cSession **sess) +{ + /* This must be called without any locks held */ + + CK_RV ret = CKR_OK; + + ASSERT(sess); + + if(id <= 0) + { + DBG(("invalid session id passed: %d", id)); + return CKR_ARGUMENTS_BAD; + } + + p11c_lock_global(); + + ret = lock_ref_internal (all_sessions, id, FALSE, writable, sess); + + p11c_unlock_global(); + + return ret; +} + +CK_RV +p11c_session_remove_lock_ref(CK_ULONG id, P11cSession **sess) +{ + /* This must be called without any locks held */ + + CK_RV ret = CKR_OK; + + ASSERT(sess); + + if(id <= 0) + { + DBG(("invalid session id passed: %d", id)); + return CKR_ARGUMENTS_BAD; + } + + p11c_lock_global(); + + ret = lock_ref_internal (all_sessions, id, TRUE, FALSE, sess); + + p11c_unlock_global(); + + return ret; +} + +void +p11c_session_unref_unlock(P11cSession* sess) +{ + /* The CallP11cSession must be locked at this point */ + + int refs; + BOOL r; + + ASSERT(sess); + + ASSERT(sess->refs > 0); + sess->refs--; + refs = sess->refs; + + sess->in_call = 0; + + DBGS(sess, "unlocked session"); + + r = ReleaseMutex(sess->mutex); + ASSERT(r == TRUE); + + /* + * At this point if no references are held, then we can safely + * delete. No other thread should be involved. + */ + + if(refs == 0) + p11c_session_destroy(sess); +} + +CK_RV +p11c_session_close_all(CK_SLOT_ID slot) +{ + /* This must be called without any locks held */ + + P11cArray* sessions; + P11cSession *sess; + size_t i; + CK_RV ret = CKR_OK; + + /* + * PKCS#11 GRAY AREA: What happens when this gets called + * concurrently? We don't return an error on the second call, + * because by the time it returns, all sessions should be closed. + */ + + DBG(("closing all sessions for: %d", slot)); + + if(!all_sessions) + return CKR_OK; + + p11c_lock_global(); + + sessions = p11c_array_sized_new(0, 1, sizeof(P11cSession*), + all_sessions->len); + if(!sessions) + ret = CKR_HOST_MEMORY; + + /* Steal all the session data */ + if(ret == CKR_OK) + { + for(i = 0; i < all_sessions->len; ++i) + { + sess = p11c_array_index(all_sessions, P11cSession*, i); + if(sess && (slot == ((CK_SLOT_ID)-1) || sess->slot == slot)) + { + /* Steal this session */ + p11c_array_index(all_sessions, P11cSession*, i) = NULL; + } + else + { + /* Not a session we're interested in */ + sess = NULL; + } + + /* Both null and normal sessions are set to preserve indexes */ + p11c_array_append(sessions, sess); + } + + ASSERT(sessions->len == all_sessions->len); + } + + p11c_unlock_global(); + + if(ret != CKR_OK) + return ret; + + /* Close each session in turn */ + for(i = 0; i < sessions->len; ++i) + { + if(!p11c_array_index(sessions, P11cSession*, i)) + continue; + + /* We need any calls in other threads to finish, so wait here */ + if(lock_ref_internal(sessions, i, TRUE, FALSE, &sess) == CKR_OK) + p11c_session_unref_unlock(sess); + } + + /* We stole the memory above, free it now */ + p11c_array_free(sessions, 1); + return CKR_OK; +} + +void +p11c_session_cleanup_all() +{ + p11c_session_close_all((CK_SLOT_ID)-1); + + p11c_lock_global(); + + p11c_array_free(all_sessions, 1); + all_sessions = NULL; + + p11c_unlock_global(); +} + +/* ---------------------------------------------------------------------------- + * OBJECT DATA + */ + +CK_RV +p11c_session_get_object_data(P11cSession* sess, P11cObject* obj, + P11cObjectData** objdata) +{ + CK_OBJECT_HANDLE id; + P11cObjectData* newdata; + CK_RV ret; + + ASSERT(sess); + ASSERT(sess->object_data); + ASSERT(obj); + ASSERT(obj->obj_funcs); + ASSERT(obj->obj_funcs->load_data); + ASSERT(objdata); + + id = obj->id; + + *objdata = p11c_hash_get(sess->object_data, p11c_hash_key(id)); + if(*objdata) + return CKR_OK; + + ret = (obj->obj_funcs->load_data)(sess, obj, &newdata); + if(ret != CKR_OK) + return ret; + + newdata->object = id; + ASSERT(newdata->data_funcs); + + if(!p11c_hash_set(sess->object_data, p11c_hash_key(id), newdata)) + { + object_data_release(newdata); + return CKR_HOST_MEMORY; + } + + *objdata = newdata; + return CKR_OK; +} + +void +p11c_session_clear_object_data(P11cSession* sess, P11cObject* obj) +{ + P11cObjectData* objdata; + + ASSERT(sess); + ASSERT(sess->object_data); + ASSERT(obj); + + objdata = (P11cObjectData*)p11c_hash_rem(sess->object_data, p11c_hash_key(obj->id)); + if(objdata) + object_data_release(objdata); +} + +void +p11c_session_enum_object_data(P11cSession* sess, + P11cEnumObjectData enum_func, void* arg) +{ + CK_OBJECT_HANDLE i, max; + P11cObject* obj; + P11cObjectData* objdata; + + ASSERT(sess); + ASSERT(sess->object_data); + ASSERT(enum_func); + + max = p11c_token_get_max_handle(); + for(i = 0; i < max; ++i) + { + objdata = (P11cObjectData*)p11c_hash_get(sess->object_data, p11c_hash_key(i)); + if(!objdata) + continue; + + obj = p11c_token_lookup_object(sess->slot, i); + if(!obj) + continue; + + (enum_func)(sess, obj, objdata, arg); + } +} + +CK_RV +p11c_session_get_object_data_for(P11cSession* sess, CK_OBJECT_HANDLE hand, + P11cObjectData** objdata) +{ + P11cObject* obj; + + obj = p11c_token_lookup_object(sess->slot, hand); + if(!obj) + return CKR_OBJECT_HANDLE_INVALID; + + return p11c_session_get_object_data(sess, obj, objdata); +} + +void +p11c_session_take_object_data(P11cSession* sess, P11cObject* obj, + P11cObjectData* objdata) +{ + P11cObjectData* prev; + + ASSERT(obj); + ASSERT(sess); + ASSERT(sess->object_data); + + ASSERT(objdata); + objdata->object = obj->id; + + prev = p11c_hash_rem(sess->object_data, p11c_hash_key(obj->id)); + if(prev) + object_data_release(prev); + + if(!p11c_hash_set(sess->object_data, p11c_hash_key(obj->id), objdata)) + object_data_release(objdata); +} + + +/* ---------------------------------------------------------------------------- + * FIND OPERATION + */ + +static BOOL +get_ulong_attribute(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_PTR templ, + CK_ULONG count, CK_ULONG* val) +{ + CK_ULONG i; + + ASSERT(val); + ASSERT(!count || templ); + + for(i = 0; i < count; ++i) + { + if(templ[i].type == type) + { + *val = *((CK_ULONG*)templ[i].pValue); + return TRUE; + } + } + + return FALSE; +} + +static CK_RV +gather_objects(P11cSession* sess, CK_ATTRIBUTE_PTR match, + CK_ULONG count, P11cArray* arr) +{ + CK_OBJECT_CLASS ocls = CKO_ANY; + CK_RV ret = CKR_OK; + + get_ulong_attribute(CKA_CLASS, match, count, &ocls); + + /* Search for builtins */ + ret = p11c_builtin_find(sess, ocls, match, count, arr); + if(ret != CKR_OK) + return ret; + + /* + * Search through certificates. + * + * We always do this search first. In Windows a lots hangs off + * the certificates. For example private keys are not contained + * in the same stores that certificates are in. There are a different + * set of key containers many of which can be used together + * with a certificate stored in any store. + * + * The trust objects we expose also depend on the certificates + * loaded. + */ + ret = p11c_cert_find(sess, ocls, match, count, arr); + if(ret != CKR_OK) + return ret; + + /* Search through trust objects */ + ret = p11c_trust_find(sess, ocls, match, count, arr); + if(ret != CKR_OK) + return ret; + + /* Search through key objects */ + ret = p11c_key_find(sess, ocls, match, count, arr); + if(ret != CKR_OK) + return ret; + + return ret; +} + +void +cleanup_find_operation(P11cSession* sess) +{ + ASSERT(sess->operation_type == OPERATION_FIND); + if(sess->operation_data) + p11c_array_free((P11cArray*)sess->operation_data, TRUE); + sess->operation_type = OPERATION_NONE; + sess->operation_data = NULL; + sess->operation_cancel = NULL; +} + +void +purge_duplicate_objects(P11cArray* arr) +{ + P11cHash* checks; + CK_OBJECT_HANDLE v; + size_t i; + + checks = p11c_hash_new(NULL, NULL); + if(!checks) + return; + + for(i = 0; i < arr->len; ) + { + v = p11c_array_index(arr, CK_OBJECT_HANDLE, i); + if(p11c_hash_get(checks, p11c_hash_key(v))) + { + p11c_array_remove_index(arr, i); + /* Look at same i again */ + } + else + { + if(!p11c_hash_set(checks, p11c_hash_key(v), arr)) + break; + ++i; + } + } + + p11c_hash_free(checks, NULL); +} + +CK_RV +p11c_session_find_init(P11cSession* sess, CK_ATTRIBUTE_PTR match, + CK_ULONG count) +{ + P11cArray* arr; + CK_RV ret; + + ASSERT(sess); + ASSERT(!count || match); + + if(sess->operation_type != OPERATION_NONE) + return CKR_OPERATION_ACTIVE; + + arr = p11c_array_new(0, 1, sizeof(CK_OBJECT_HANDLE)); + if(!arr) + return CKR_HOST_MEMORY; + + ret = gather_objects(sess, match, count, arr); + if(ret != CKR_OK) + { + p11c_array_free(arr, TRUE); + return ret; + } + + /* Cleanup all duplicates in the array */ + purge_duplicate_objects(arr); + + sess->operation_type = OPERATION_FIND; + sess->operation_data = arr; + sess->operation_cancel = cleanup_find_operation; + + return CKR_OK; +} + +CK_RV +p11c_session_find(P11cSession* sess, CK_OBJECT_HANDLE_PTR objects, + CK_ULONG max_object_count, CK_ULONG_PTR object_count) +{ + P11cArray* arr; + size_t i; + + ASSERT(sess); + ASSERT(object_count); + ASSERT(!max_object_count || objects); + + if(sess->operation_type != OPERATION_FIND) + return CKR_OPERATION_NOT_INITIALIZED; + + if(!max_object_count) + { + *object_count = 0; + return CKR_OK; + } + + arr = (P11cArray*)sess->operation_data; + *object_count = (max_object_count > arr->len ? arr->len : max_object_count); + for(i = 0; i < *object_count; ++i) + objects[i] = p11c_array_index(arr, CK_OBJECT_HANDLE, i); + + p11c_array_remove_range(arr, 0, *object_count); + + return CKR_OK; +} + +CK_RV +p11c_session_find_final(P11cSession* sess) +{ + ASSERT(sess); + + if(sess->operation_type != OPERATION_FIND) + return CKR_OPERATION_NOT_INITIALIZED; + + cleanup_find_operation(sess); + return CKR_OK; +} + + +/* ---------------------------------------------------------------------------- + * CRYPTO OPERATIONS + */ + +typedef struct _CryptoContext +{ + CK_MECHANISM_TYPE mech_type; + P11cDestroyFunc mech_cleanup; + void* mech_data; +} +CryptoContext; + +void +cleanup_crypto_operation(P11cSession* sess) +{ + CryptoContext* ctx; + + if(sess->operation_data) + { + ctx = (CryptoContext*)sess->operation_data; + if(ctx->mech_cleanup) + (ctx->mech_cleanup)(ctx->mech_data); + free(ctx); + } + + sess->operation_type = OPERATION_NONE; + sess->operation_data = NULL; + sess->operation_cancel = NULL; +} + +CK_RV +p11c_session_sign_init(P11cSession* sess, CK_MECHANISM_PTR mech, + P11cObjectData *objdata) +{ + CryptoContext* ctx; + CK_RV ret; + + ASSERT(sess); + ASSERT(mech); + ASSERT(objdata); + + if(sess->operation_type != OPERATION_NONE) + return CKR_OPERATION_ACTIVE; + + ctx = calloc(1, sizeof(CryptoContext)); + if(!ctx) + return CKR_HOST_MEMORY; + + ctx->mech_type = mech->mechanism; + + switch(mech->mechanism) + { + case CKM_RSA_PKCS: + ret = p11c_rsa_pkcs_sign_init(objdata, &ctx->mech_data); + ctx->mech_cleanup = p11c_rsa_pkcs_sign_cleanup; + break; + default: + ret = CKR_MECHANISM_INVALID; + break; + }; + + if(ret != CKR_OK) + { + free(ctx); + ASSERT(!sess->operation_data); + return ret; + } + + sess->operation_type = OPERATION_SIGN; + sess->operation_data = ctx; + sess->operation_cancel = cleanup_crypto_operation; + return CKR_OK; +} + +CK_RV +p11c_session_sign(P11cSession* sess, CK_BYTE_PTR data, CK_ULONG n_data, + CK_BYTE_PTR signature, CK_ULONG_PTR n_signature) +{ + CryptoContext *ctx; + BOOL incomplete; + CK_RV ret; + + ASSERT(sess); + ASSERT(data); + ASSERT(n_data); + + if(sess->operation_type != OPERATION_SIGN) + return CKR_OPERATION_NOT_INITIALIZED; + + ctx = (CryptoContext*)sess->operation_data; + switch(ctx->mech_type) + { + case CKM_RSA_PKCS: + ret = p11c_rsa_pkcs_sign_perform(data, n_data, signature, n_signature, + &ctx->mech_data); + break; + + default: + ASSERT(FALSE); + ret = CKR_GENERAL_ERROR; + break; + } + + /* Buffer calculation, we don't end operation */ + incomplete = (ret == CKR_BUFFER_TOO_SMALL || (ret == CKR_OK && !signature)); + + if(!incomplete) + cleanup_crypto_operation(sess); + + return ret; +} + +CK_RV +p11c_session_decrypt_init(P11cSession* sess, CK_MECHANISM_PTR mech, + P11cObjectData *objdata) +{ + CryptoContext* ctx; + CK_RV ret; + + ASSERT(sess); + ASSERT(mech); + ASSERT(objdata); + + if(sess->operation_type != OPERATION_NONE) + return CKR_OPERATION_ACTIVE; + + ctx = calloc(1, sizeof(CryptoContext)); + if(!ctx) + return CKR_HOST_MEMORY; + + ctx->mech_type = mech->mechanism; + + switch(mech->mechanism) + { + case CKM_RSA_PKCS: + ret = p11c_rsa_pkcs_decrypt_init(objdata, &ctx->mech_data); + ctx->mech_cleanup = p11c_rsa_pkcs_decrypt_cleanup; + break; + default: + ret = CKR_MECHANISM_INVALID; + break; + }; + + if(ret != CKR_OK) + { + free(ctx); + ASSERT(!sess->operation_data); + return ret; + } + + sess->operation_type = OPERATION_DECRYPT; + sess->operation_data = ctx; + sess->operation_cancel = cleanup_crypto_operation; + return CKR_OK; +} + +CK_RV +p11c_session_decrypt(P11cSession* sess, CK_BYTE_PTR encdata, CK_ULONG n_encdata, + CK_BYTE_PTR result, CK_ULONG_PTR n_result) +{ + CryptoContext *ctx; + BOOL incomplete; + CK_RV ret; + + ASSERT(sess); + ASSERT(encdata); + ASSERT(n_encdata); + + if(sess->operation_type != OPERATION_DECRYPT) + return CKR_OPERATION_NOT_INITIALIZED; + + ctx = (CryptoContext*)sess->operation_data; + switch(ctx->mech_type) + { + case CKM_RSA_PKCS: + ret = p11c_rsa_pkcs_decrypt_perform(encdata, n_encdata, result, n_result, + &ctx->mech_data); + break; + + default: + ASSERT(FALSE); + ret = CKR_GENERAL_ERROR; + break; + } + + /* Buffer calculation, we don't end operation */ + incomplete = (ret == CKR_BUFFER_TOO_SMALL || (ret == CKR_OK && !result)); + + if(!incomplete) + cleanup_crypto_operation(sess); + + return ret; +} diff --git a/module/p11-capi-session.h b/module/p11-capi-session.h new file mode 100644 index 0000000..8f84026 --- /dev/null +++ b/module/p11-capi-session.h @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef P11C_SESSION_H +#define P11C_SESSION_H + +#include "p11-capi.h" + +/* -------------------------------------------------------------------- + * + * Session = P11cSession + * - A PKCS#11 Session + * + * Objects = P11cObject + * - There's a global list of objects in p11c-object.c indexed by + * object handle. + * - The object itself has no attributes or cached data, but knows how + * to load data when needed. + * - Each object has a unique key which guarantees we don't load the + * same object twice with two different object handles. + * + * Object Data = P11cObjectData + * - Object Data is owned by the Session + * - Loaded data and/or attributes for an object. + */ + +/* Callback to cleanup a current operation */ +typedef void (*P11cSessionCancel) (struct _P11cSession* sess); + +/* Represents an open session */ +typedef struct _P11cSession +{ + CK_SESSION_HANDLE id; /* Unique ID for this session */ + CK_SLOT_ID slot; + int in_call; /* Whether this session is use in PKCS#11 function */ + + HCERTSTORE store; /* Handle to an open certificate store */ + + BOOL read_write; /* A read-write session? */ + + int operation_type; /* Whether an operation is happening or not */ + void* operation_data; /* Data for this operation */ + P11cSessionCancel operation_cancel; /* Callback to cancel operation when necessary */ + + P11cHash* object_data; + + CK_NOTIFY notify_callback; /* Application specified callback */ + CK_VOID_PTR user_data; /* Argument for above */ + + int refs; /* Reference count */ + HANDLE mutex; /* Mutex for protecting this structure */ +} +P11cSession; + +/* Debug print something related to a session */ +#define DBGS(sess, msg) \ + p11c_debug("S%d: %s", (sess) ? (sess)->id : 0, (msg)) + +/* Create a session */ +CK_RV p11c_session_create (CK_SLOT_ID slot, P11cSession** ret); + +/* Destroy a session */ +void p11c_session_destroy (P11cSession* sess); + +/* Register a new session */ +CK_RV p11c_session_register (P11cSession* sess); + +/* Get information about a session */ +void p11c_session_get_info (P11cSession* sess, + CK_SESSION_INFO_PTR info); + +/* Get a session from a handle, and lock it */ +CK_RV p11c_session_get_lock_ref (CK_ULONG id, BOOL writable, + P11cSession **sess); + +/* Get a session from a handle, remove it from list, and lock it */ +CK_RV p11c_session_remove_lock_ref (CK_ULONG id, P11cSession **sess); + +/* Unlock and unreference a session */ +void p11c_session_unref_unlock (P11cSession* sess); + +/* Close all sessions on a certain slot/token */ +CK_RV p11c_session_close_all (CK_SLOT_ID slot); + + + +/* Start a find operation on a session */ +CK_RV p11c_session_find_init (P11cSession* sess, + CK_ATTRIBUTE_PTR templ, + CK_ULONG count); + +/* Return results from a find operation */ +CK_RV p11c_session_find (P11cSession* sess, + CK_OBJECT_HANDLE_PTR objects, + CK_ULONG max_object_count, + CK_ULONG_PTR object_count); + +/* End a find operation */ +CK_RV p11c_session_find_final (P11cSession* sess); + + +/* Start a sign operation on a session */ +CK_RV p11c_session_sign_init (P11cSession* sess, + CK_MECHANISM_PTR mech, + P11cObjectData *objdata); + +/* Perform sign operation */ +CK_RV p11c_session_sign (P11cSession* sess, + CK_BYTE_PTR data, CK_ULONG n_data, + CK_BYTE_PTR sig, CK_ULONG_PTR n_sig); + +/* Start a decrypt operation on a session */ +CK_RV p11c_session_decrypt_init (P11cSession* sess, + CK_MECHANISM_PTR mech, + P11cObjectData *objdata); + +/* Perform decrypt operation */ +CK_RV p11c_session_decrypt (P11cSession* sess, + CK_BYTE_PTR encdata, CK_ULONG n_encdata, + CK_BYTE_PTR result, CK_ULONG_PTR n_result); + +/* Get object data for an object */ +CK_RV p11c_session_get_object_data (P11cSession* sess, + P11cObject* obj, + P11cObjectData** objdata); + +/* Get object data for an object handle */ +CK_RV p11c_session_get_object_data_for (P11cSession* sess, + CK_OBJECT_HANDLE hand, + P11cObjectData** objdata); + +/* Set object data for an object */ +void p11c_session_take_object_data (P11cSession* sess, + P11cObject* obj, + P11cObjectData* objdata); + +/* Clear object data for an object */ +void p11c_session_clear_object_data (P11cSession* sess, + P11cObject* obj); + +/* Enumerate object data for all objects */ +typedef void (*P11cEnumObjectData) (P11cSession* sess, + P11cObject* obj, + P11cObjectData* data, + void* arg); + +void p11c_session_enum_object_data (P11cSession* sess, + P11cEnumObjectData enum_func, + void* arg); + +void p11c_session_cleanup_all (void); + +#endif /* P11C_SESSION_H */ diff --git a/module/p11-capi-token.c b/module/p11-capi-token.c new file mode 100644 index 0000000..f6ef2ca --- /dev/null +++ b/module/p11-capi-token.c @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "p11-capi.h" +#include "p11-capi-object.h" +#include "p11-capi-token.h" + +static P11cArray* object_array = NULL; +static P11cHash* object_hash = NULL; +static P11cArray* logged_in_slots = NULL; + +typedef struct _SlotInfo +{ + const char* capi_store; + const char* display_name; + CK_ULONG slot_flags; +} +SlotInfo; + +#define SLOT_OFFSET 0x00001000 + +static SlotInfo slot_info[] = { + { "My", "Personal Certificates", P11C_SLOT_TRUSTED | P11C_SLOT_CERTS }, + { "AddressBook", "Address Book Certificates", P11C_SLOT_CERTS }, + { "CA", "Certificate Authorities", P11C_SLOT_CA | P11C_SLOT_CERTS }, + { "Root", "Root Authorities", P11C_SLOT_TRUSTED | P11C_SLOT_CA | P11C_SLOT_CERTS }, + { "Trust", "Trust", P11C_SLOT_CERTS }, + { "TrustedPeople", "Trusted People", P11C_SLOT_TRUSTED | P11C_SLOT_CERTS }, + { "AuthRoot", "Auth Root", P11C_SLOT_CERTS }, + { NULL, "All User Keys", P11C_SLOT_ANYKEY } +}; + +#define SLOT_TO_OFFSET(slot) \ + ((slot) & ~(SLOT_OFFSET)) + +#define OFFSET_TO_SLOT(offset) \ + ((offset) | SLOT_OFFSET) + +unsigned int +p11c_token_get_count(void) +{ + return sizeof(slot_info) / sizeof(slot_info[0]); +} + +CK_SLOT_ID +p11c_token_get_slot_id(unsigned int offset) +{ + ASSERT(offset < p11c_token_get_count()); + return OFFSET_TO_SLOT(offset); +} + +CK_BBOOL +p11c_token_is_valid(CK_SLOT_ID slot) +{ + unsigned int offset = SLOT_TO_OFFSET(slot); + return offset >= 0 && offset < p11c_token_get_count(); +} + +const char* +p11c_token_get_display_name(CK_SLOT_ID slot) +{ + unsigned int offset = SLOT_TO_OFFSET(slot); + ASSERT(p11c_token_is_valid(slot)); + ASSERT(slot_info[offset].display_name); + return slot_info[offset].display_name; +} + +const char* +p11c_token_get_store_name(CK_SLOT_ID slot) +{ + unsigned int offset = SLOT_TO_OFFSET(slot); + ASSERT(p11c_token_is_valid(slot)); + return slot_info[offset].capi_store; +} + +CK_ULONG +p11c_token_get_flags(CK_SLOT_ID slot) +{ + unsigned int offset = SLOT_TO_OFFSET(slot); + ASSERT(p11c_token_is_valid(slot)); + return slot_info[offset].slot_flags; +} + +static void +object_free(P11cObject* obj) +{ + ASSERT(obj); + ASSERT(obj->obj_funcs); + ASSERT(obj->obj_funcs->release); + (obj->obj_funcs->release)(obj); +} + +void +p11c_token_cleanup_all(void) +{ + size_t i; + + p11c_lock_global(); + + if(object_hash) + { + p11c_hash_free(object_hash, NULL); + object_hash = NULL; + } + + if(object_array) + { + for(i = 1; i < object_array->len; ++i) + { + ASSERT(p11c_array_index(object_array, P11cObject*, i)); + object_free(p11c_array_index(object_array, P11cObject*, i)); + } + + p11c_array_free(object_array, TRUE); + object_array = NULL; + } + + if(logged_in_slots) + { + p11c_array_free(logged_in_slots, TRUE); + logged_in_slots = NULL; + } + + p11c_unlock_global(); +} + +CK_OBJECT_HANDLE +p11c_token_get_max_handle(void) +{ + if(!object_array) + return 0; + return object_array->len; +} + +P11cObject* +p11c_token_lookup_object(CK_SLOT_ID slot, CK_OBJECT_HANDLE obj) +{ + /* This must be called without any locks held */ + + P11cObject* ret = NULL; + + ASSERT(slot); + ASSERT(obj > 0); + + p11c_lock_global(); + + if(object_array && obj < object_array->len) + ret = p11c_array_index(object_array, P11cObject*, obj); + + p11c_unlock_global(); + + /* Must belong to the right slot */ + if(ret && ret->slot != slot) + ret = NULL; + + return ret; +} + +static unsigned int +object_hash_func(const void* a) +{ + P11cObject* obj = (P11cObject*)a; + unsigned int hash = p11c_hash_pointer(obj->obj_funcs); + hash ^= (obj->obj_funcs->hash_object)(obj); + return hash; +} + +static int +object_equal_func(const void* a, const void* b) +{ + P11cObject* ca = (P11cObject*)a; + P11cObject* cb = (P11cObject*)b; + if(ca == cb) + return 1; + if(ca->obj_funcs != cb->obj_funcs) + return 0; + return (ca->obj_funcs->equal_object)(ca, cb); +} + +CK_RV +p11c_token_register_object(CK_SLOT_ID slot, P11cObject* obj) +{ + P11cObject* prev; + CK_RV ret = CKR_OK; + + ASSERT(slot); + ASSERT(obj->id == 0); + + DBG(("registering object")); + + p11c_lock_global(); + + if(!object_array) + { + object_array = p11c_array_sized_new(0, 1, sizeof(P11cObject*), 16); + if(object_array) + { + /* A blank entry for '0' */ + P11cObject* blank = NULL; + p11c_array_append(object_array, blank); + } + + object_hash = p11c_hash_new(object_hash_func, object_equal_func); + + if(!object_array || !object_hash) + { + /* Allocation failed above */ + ret = CKR_HOST_MEMORY; + } + } + + if(ret == CKR_OK) + { + ASSERT(object_array); + ASSERT(object_hash); + + /* Look in the hash and find a previous object */ + prev = p11c_hash_get(object_hash, obj); + if(prev) + { + /* Register it in the previous object's place */ + obj->id = prev->id; + ASSERT(prev->id < object_array->len); + if(p11c_hash_set(object_hash, obj, obj)) + { + p11c_array_index(object_array, P11cObject*, obj->id) = obj; + object_free(prev); + DBGO(obj, "found old object id"); + } + else + { + ret = CKR_HOST_MEMORY; + } + } + else + { + /* Register it at the end of the array */ + obj->id = object_array->len; + ASSERT(obj->id > 0); + if(p11c_hash_set(object_hash, obj, obj)) + { + if(p11c_array_append(object_array, obj)) + { + DBGO(obj, "registered new object id"); + } + else + { + ret = CKR_HOST_MEMORY; + + /* Roll back our addition */ + p11c_hash_rem(object_hash, obj); + } + } + else + { + ret = CKR_HOST_MEMORY; + } + } + } + + if(ret == CKR_OK) + obj->slot = slot; + + p11c_unlock_global(); + + return ret; + +} + +CK_BBOOL +p11c_token_is_logged_in(CK_SLOT_ID slot) +{ + unsigned int count, offset; + + ASSERT(p11c_token_is_valid(slot)); + + if(!logged_in_slots) + return CK_FALSE; + + offset = SLOT_TO_OFFSET(slot); + count = p11c_token_get_count(); + + ASSERT(logged_in_slots->len == count && offset < count); + return p11c_array_index(logged_in_slots, CK_BBOOL, offset); +} + +CK_RV +p11c_token_login(CK_SLOT_ID slot) +{ + unsigned int i, count; + unsigned int offset; + CK_BBOOL value; + + ASSERT(p11c_token_is_valid(slot)); + + offset = SLOT_TO_OFFSET(slot); + count = p11c_token_get_count(); + + if(!logged_in_slots) + { + logged_in_slots = p11c_array_sized_new(0, 1, sizeof(CK_BBOOL), count); + if(!logged_in_slots) + return CKR_HOST_MEMORY; + + value = CK_FALSE; + for(i = 0; i < count; ++i) + p11c_array_append(logged_in_slots, value); + + } + + ASSERT(logged_in_slots->len == count && offset < count); + if(p11c_array_index(logged_in_slots, CK_BBOOL, offset)) + return CKR_USER_ALREADY_LOGGED_IN; + + p11c_array_index(logged_in_slots, CK_BBOOL, offset) = CK_TRUE; + return CKR_OK; +} + +CK_RV +p11c_token_logout(CK_SLOT_ID slot) +{ + unsigned int count, offset; + + ASSERT(p11c_token_is_valid(slot)); + + if(!logged_in_slots) + return CKR_USER_NOT_LOGGED_IN; + + offset = SLOT_TO_OFFSET(slot); + count = p11c_token_get_count(); + + ASSERT(logged_in_slots->len == count && offset < count); + if(!p11c_array_index(logged_in_slots, CK_BBOOL, offset)) + return CKR_USER_NOT_LOGGED_IN; + + p11c_array_index(logged_in_slots, CK_BBOOL, offset) = CK_FALSE; + return CKR_OK; +} diff --git a/module/p11-capi-token.h b/module/p11-capi-token.h new file mode 100644 index 0000000..e97f547 --- /dev/null +++ b/module/p11-capi-token.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef P11C_TOKEN_H +#define P11C_TOKEN_H + +#include "p11-capi.h" + +#define P11C_SLOT_CERTS 0x00000001 +#define P11C_SLOT_ANYKEY 0x00000002 +#define P11C_SLOT_CA 0x00000100 +#define P11C_SLOT_TRUSTED 0x00000200 + +/* Register a new object, a handle will be assigned to obj->id */ +CK_RV p11c_token_register_object (CK_SLOT_ID slot, P11cObject* obj); + +/* Lookup an object for a given object handle */ +P11cObject* p11c_token_lookup_object (CK_SLOT_ID slot, CK_OBJECT_HANDLE obj); + +/* Clear all objects for all tokens. Only done when finalizing */ +void p11c_token_cleanup_all (void); + +/* Get the number of the maximum object handle currently in memory */ +CK_OBJECT_HANDLE p11c_token_get_max_handle (void); + +unsigned int p11c_token_get_count (void); + +CK_SLOT_ID p11c_token_get_slot_id (unsigned int index); + +CK_BBOOL p11c_token_is_valid (CK_SLOT_ID slot); + +const char* p11c_token_get_display_name (CK_SLOT_ID slot); + +const char* p11c_token_get_store_name (CK_SLOT_ID slot); + +CK_ULONG p11c_token_get_flags (CK_SLOT_ID slot); + +CK_RV p11c_token_login (CK_SLOT_ID slot); + +CK_RV p11c_token_logout (CK_SLOT_ID slot); + +CK_BBOOL p11c_token_is_logged_in (CK_SLOT_ID slot); + +#endif /* P11C_TOKEN_H */ diff --git a/module/p11-capi-trust.c b/module/p11-capi-trust.c new file mode 100644 index 0000000..e45106a --- /dev/null +++ b/module/p11-capi-trust.c @@ -0,0 +1,569 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "p11-capi.h" +#include "p11-capi-cert.h" +#include "p11-capi-object.h" +#include "p11-capi-session.h" +#include "p11-capi-token.h" +#include "p11-capi-trust.h" +#include "x509-usages.h" + +#include "pkcs11/pkcs11n.h" + +/* + * These are the attributes expected by NSS on a trust object: + * + * CKA_CLASS + * CKA_TOKEN + * CKA_LABEL + * CKA_CERT_SHA1_HASH + * CKA_CERT_MD5_HASH + * CKA_ISSUER + * CKA_SUBJECT + * CKA_TRUST_SERVER_AUTH + * CKA_TRUST_CLIENT_AUTH + * CKA_TRUST_EMAIL_PROTECTION + * CKA_TRUST_CODE_SIGNING + * CKA_SERIAL_NUMBER + */ + +typedef struct _TrustObject +{ + P11cObject obj; + CK_OBJECT_HANDLE cert_obj; +} +TrustObject; + +typedef struct _TrustObjectData +{ + P11cObjectData base; + + PCCERT_CONTEXT cert; + CERT_ENHKEY_USAGE* enhanced_usage; + + BOOL has_usage; + BYTE usage; +} +TrustObjectData; + +static CK_TRUST +has_usage(TrustObjectData* tdata, BYTE restriction) +{ + if(!tdata->has_usage) + CKT_NETSCAPE_TRUST_UNKNOWN; + if((tdata->usage & restriction) == restriction) + return CKT_NETSCAPE_TRUSTED; + return CKT_NETSCAPE_UNTRUSTED; + +} + +static CK_TRUST +has_enhanced_usage(TrustObjectData* tdata, const char* oid) +{ + CERT_ENHKEY_USAGE* eusage = tdata->enhanced_usage; + DWORD i; + + /* No usages, means anything goes */ + if(eusage == NULL) + return CKT_NETSCAPE_TRUSTED_DELEGATOR; + + for(i = 0; i < eusage->cUsageIdentifier; ++i) + { + if(eusage->rgpszUsageIdentifier[i] && + strcmp(oid, eusage->rgpszUsageIdentifier[i]) == 0) + return CKT_NETSCAPE_TRUSTED_DELEGATOR; + } + + return CKT_NETSCAPE_TRUST_UNKNOWN; +} + +static CK_RV +trust_bool_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) +{ + CK_BBOOL val; + + ASSERT(objdata); + ASSERT(attr); + + switch(attr->type) + { + /* + * Resides on the token + * - Always true for CAPI objects. + */ + case CKA_TOKEN: + val = CK_TRUE; + break; + + /* + * Private vs. Public object. + * - Always false for certificates. + */ + case CKA_PRIVATE: + val = CK_FALSE; + break; + + /* + * If object can be modified. + */ + case CKA_MODIFIABLE: + val = CK_TRUE; + break; + + /* + * TODO: Figure out what this is. + */ + case CKA_TRUST_STEP_UP_APPROVED: + val = CK_FALSE; + break; + + default: + return CKR_ATTRIBUTE_TYPE_INVALID; + }; + + return p11c_return_data(attr, &val, sizeof(CK_BBOOL)); +} + +static CK_RV +trust_ulong_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) +{ + TrustObjectData* tdata = (TrustObjectData*)objdata; + CK_ULONG val; + + ASSERT(tdata); + ASSERT(attr); + + switch(attr->type) + { + + /* + * Object class. + * - Always CKO_NETSCAPE_TRUST for netscape trust + */ + case CKA_CLASS: + val = CKO_NETSCAPE_TRUST; + break; + + /* + * Key restrictions + */ + case CKA_TRUST_DIGITAL_SIGNATURE: + val = has_usage(tdata, CERT_DIGITAL_SIGNATURE_KEY_USAGE); + break; + case CKA_TRUST_NON_REPUDIATION: + val = has_usage(tdata, CERT_NON_REPUDIATION_KEY_USAGE); + break; + case CKA_TRUST_KEY_ENCIPHERMENT: + val = has_usage(tdata, CERT_KEY_ENCIPHERMENT_KEY_USAGE); + break; + case CKA_TRUST_DATA_ENCIPHERMENT: + val = has_usage(tdata, CERT_DATA_ENCIPHERMENT_KEY_USAGE); + break; + case CKA_TRUST_KEY_AGREEMENT: + val = has_usage(tdata, CERT_KEY_AGREEMENT_KEY_USAGE); + break; + case CKA_TRUST_KEY_CERT_SIGN: + val = has_usage(tdata, CERT_KEY_CERT_SIGN_KEY_USAGE); + break; + case CKA_TRUST_CRL_SIGN: + val = has_usage(tdata, CERT_CRL_SIGN_KEY_USAGE); + break; + + /* + * Various trust flags + */ + case CKA_TRUST_SERVER_AUTH: + val = has_enhanced_usage(tdata, X509_USAGE_SERVER_AUTH); + break; + case CKA_TRUST_CLIENT_AUTH: + val = has_enhanced_usage(tdata, X509_USAGE_CLIENT_AUTH); + break; + case CKA_TRUST_CODE_SIGNING: + val = has_enhanced_usage(tdata, X509_USAGE_CODE_SIGNING); + break; + case CKA_TRUST_EMAIL_PROTECTION: + val = has_enhanced_usage(tdata, X509_USAGE_EMAIL); + break; + case CKA_TRUST_IPSEC_END_SYSTEM: + val = has_enhanced_usage(tdata, X509_USAGE_IPSEC_ENDPOINT); + break; + case CKA_TRUST_IPSEC_TUNNEL: + val = has_enhanced_usage(tdata, X509_USAGE_IPSEC_TUNNEL); + break; + case CKA_TRUST_IPSEC_USER: + val = has_enhanced_usage(tdata, X509_USAGE_IPSEC_USER); + break; + case CKA_TRUST_TIME_STAMPING: + val = has_enhanced_usage(tdata, X509_USAGE_TIME_STAMPING); + break; + + default: + return CKR_ATTRIBUTE_TYPE_INVALID; + }; + + return p11c_return_data(attr, &val, sizeof(CK_ULONG)); +} + +static CK_RV +trust_bytes_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) +{ + TrustObjectData* tdata = (TrustObjectData*)objdata; + + ASSERT(tdata); + ASSERT(attr); + + switch(attr->type) + { + /* + * Forward these through to the certificate itself. + */ + case CKA_SUBJECT: + case CKA_ISSUER: + case CKA_SERIAL_NUMBER: + case CKA_LABEL: + ASSERT(tdata->cert); + return p11c_cert_certificate_get_bytes(tdata->cert, attr); + + /* + * The hash of the DER encoded certificate. + */ + case CKA_CERT_MD5_HASH: + case CKA_CERT_SHA1_HASH: + if(!CryptHashCertificate(0, attr->type == CKA_CERT_MD5_HASH ? CALG_MD5 : CALG_SHA1, + 0, tdata->cert->pbCertEncoded, + tdata->cert->cbCertEncoded, attr->pValue, + (DWORD*)(&attr->ulValueLen))) + return p11c_winerr_to_ckr(GetLastError()); + return CKR_OK; + }; + + return CKR_ATTRIBUTE_TYPE_INVALID; +} + +static unsigned int +trust_hash_func(P11cObject* obj) +{ + return p11c_hash_integer(((TrustObject*)obj)->cert_obj); +} + +static int +trust_equal_func(P11cObject* a, P11cObject* b) +{ + return ((TrustObject*)a)->cert_obj == ((TrustObject*)b)->cert_obj; +} + +static void +trust_release(void* data) +{ + TrustObjectData* tdata = (TrustObjectData*)data; + ASSERT(tdata); + + ASSERT(tdata->cert); + CertFreeCertificateContext(tdata->cert); + + if(tdata->enhanced_usage) + free(tdata->enhanced_usage); + + free(tdata); +} + +static const P11cObjectDataVtable trust_objdata_vtable = { + trust_bool_attribute, + trust_ulong_attribute, + trust_bytes_attribute, + trust_release, +}; + +static CK_RV +parse_usage(TrustObjectData* tdata, DWORD flags) +{ + DWORD size, err; + CERT_ENHKEY_USAGE* eusage; + + ASSERT(!tdata->enhanced_usage); + + /* Get the size of the enhanced_usage */ + if(!CertGetEnhancedKeyUsage(tdata->cert, flags, NULL, &size)) + { + err = GetLastError(); + + /* No enhanced_usage data is not an error */ + if(err == CRYPT_E_NOT_FOUND) + return CKR_OK; + return p11c_winerr_to_ckr(err); + } + + eusage = (CERT_ENHKEY_USAGE*)calloc(1, size); + if(!eusage) + return CKR_HOST_MEMORY; + + /* Now get the actual enhanced usage property */ + if(!CertGetEnhancedKeyUsage(tdata->cert, flags, eusage, &size)) + { + err = GetLastError(); + if(err == CRYPT_E_NOT_FOUND) + return CKR_OK; + return p11c_winerr_to_ckr(err); + } + + tdata->enhanced_usage = eusage; + return CKR_OK; +} + +static CK_RV +parse_restrictions(TrustObjectData* tdata) +{ + CRYPT_BIT_BLOB* rst; + CERT_EXTENSION* ext; + DWORD size; + + ASSERT(tdata); + ASSERT(tdata->cert); + + tdata->has_usage = CK_FALSE; + tdata->usage = 0x00; + + ext = CertFindExtension(szOID_KEY_USAGE, + tdata->cert->pCertInfo->cExtension, + tdata->cert->pCertInfo->rgExtension); + + /* No key usage, don't care */ + if(!ext) + return CKR_OK; + + /* Find the size of the decoded structure */ + if(!CryptDecodeObject(P11c_ENCODINGS, X509_KEY_USAGE, + ext->Value.pbData, ext->Value.cbData, 0, NULL, &size)) + return p11c_winerr_to_ckr(GetLastError()); + + /* Allocate enough memory */ + rst = (CRYPT_BIT_BLOB*)calloc(1, size); + if(!rst) + return CKR_HOST_MEMORY; + + /* And get the decoded structure */ + if(CryptDecodeObject(P11c_ENCODINGS, X509_KEY_USAGE, + ext->Value.pbData, ext->Value.cbData, 0, rst, &size)) + { + if(rst->cbData != 1 && + rst->cUnusedBits != 0) + { + DBG(("key usage are of invalid size")); + } + else + { + /* A valid byte of key restricted usage flags. Yes all that for one byte */ + tdata->usage = *((BYTE*)(rst->pbData)); + tdata->has_usage = TRUE; + } + } + + free(rst); + return CKR_OK; +} + +static CK_RV +trust_load_data(P11cSession* sess, P11cObject* obj, P11cObjectData** objdata) +{ + TrustObject* tobj = (TrustObject*)obj; + TrustObjectData* tdata; + P11cObjectData* certdata; + CK_RV ret; + + ASSERT(tobj); + ASSERT(objdata); + + /* Get the raw data for the certificate */ + ret = p11c_session_get_object_data_for(sess, tobj->cert_obj, &certdata); + if(ret != CKR_OK) + return ret; + + tdata = (TrustObjectData*)calloc(1, sizeof(TrustObjectData)); + if(!tdata) + return CKR_HOST_MEMORY; + + tdata->cert = p11c_cert_object_data_get_certificate (certdata); + ASSERT(tdata->cert); + + /* Dig up the restrictions data extension */ + ret = parse_restrictions(tdata); + if(ret != CKR_OK) + { + free(tdata); + return ret; + } + + /* Dig up the enhanced usage data property, and then try the extension */ + ret = parse_usage(tdata, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG); + if(ret == CKR_OK && !tdata->enhanced_usage) + ret = parse_usage(tdata, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG); + + if(ret != CKR_OK) + { + free(tdata); + return ret; + } + + /* And keep a reference to the certificate */ + tdata->cert = CertDuplicateCertificateContext(tdata->cert); + + tdata->base.object = obj->id; + tdata->base.data_funcs = &trust_objdata_vtable; + + *objdata = &(tdata->base); + return CKR_OK; +} + + +static void +trust_object_release(void* data) +{ + TrustObject* tobj = (TrustObject*)data; + ASSERT(tobj); + free(tobj); +} + +static const P11cObjectVtable trust_object_vtable = { + trust_load_data, + trust_hash_func, + trust_equal_func, + trust_object_release, +}; + +static CK_RV +register_trust_object(P11cSession* sess, P11cObject* cert, P11cObject** obj) +{ + TrustObject* tobj; + CK_RV ret; + + tobj = calloc(1, sizeof(TrustObject)); + if(!tobj) + return CKR_HOST_MEMORY; + + tobj->cert_obj = cert->id; + + tobj->obj.id = 0; + tobj->obj.obj_funcs = &trust_object_vtable; + + ret = p11c_token_register_object(sess->slot, &(tobj->obj)); + if(ret != CKR_OK) + { + free(tobj); + return ret; + } + + ASSERT(tobj->obj.id != 0); + *obj = &(tobj->obj); + + return CKR_OK; +} + +static CK_RV +list_matching_certificates(P11cSession* sess, CK_ATTRIBUTE_PTR match, + CK_ULONG count, P11cArray* arr) +{ + CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; + CK_ATTRIBUTE search[3]; + CK_ULONG n_search = 0; + CK_ULONG i; + + /* The class */ + search[0].type = CKA_CLASS; + search[0].pValue = &cert_class; + search[0].ulValueLen = sizeof(CK_OBJECT_CLASS); + ++n_search; + + for(i = 0; i < count && n_search < 3; ++i) + { + /* + * These are the attributes that tie a certificate + * to trust object, so try match certs with these + */ + if(match[i].type == CKA_ISSUER || + match[i].type == CKA_SERIAL_NUMBER) + { + search[n_search].type = match[i].type; + search[n_search].pValue = match[i].pValue; + search[n_search].ulValueLen = match[i].ulValueLen; + ++n_search; + } + } + + /* Do the certificate search */ + return p11c_cert_find(sess, CKO_CERTIFICATE, search, n_search, arr); +} + +CK_RV +p11c_trust_find(P11cSession* sess, CK_OBJECT_CLASS cls, + CK_ATTRIBUTE_PTR match, CK_ULONG count, P11cArray* arr) +{ + CK_OBJECT_HANDLE id; + P11cObject* obj; + P11cObject* certobj; + P11cObjectData* objdata; + P11cArray* certarr; + CK_RV ret = CKR_OK; + CK_ULONG i; + + /* We only have trust objects in here */ + if(cls != CKO_NETSCAPE_TRUST && cls != CKO_ANY) + return CKR_OK; + + /* Only work with slots that have certificates */ + if(!(p11c_token_get_flags (sess->slot) & P11C_SLOT_CERTS)) + return CKR_OK; + + /* Get a list of all certificates */ + certarr = p11c_array_new(0, 1, sizeof(CK_OBJECT_HANDLE)); + if(!certarr) + return CKR_HOST_MEMORY; + ret = list_matching_certificates(sess, match, count, certarr); + + /* Now match each of them against our criteria */ + if(ret == CKR_OK) + { + for(i = 0; i < certarr->len; ++i) + { + id = p11c_array_index(certarr, CK_OBJECT_HANDLE, i); + ASSERT(id); + + certobj = p11c_token_lookup_object(sess->slot, id); + ASSERT(certobj); + + /* We'll register a trust object for any loaded certificate */ + ret = register_trust_object(sess, certobj, &obj); + if(ret != CKR_OK) + break; + + ASSERT(obj); + + ret = p11c_session_get_object_data(sess, obj, &objdata); + if(ret != CKR_OK) + break; + + /* Only return new object if it matches */ + if(p11c_object_data_match(objdata, match, count)) + p11c_array_append(arr, obj->id); + } + } + + p11c_array_free(certarr, TRUE); + return ret; +} diff --git a/module/p11-capi-trust.h b/module/p11-capi-trust.h new file mode 100644 index 0000000..639f2eb --- /dev/null +++ b/module/p11-capi-trust.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef P11C_TRUST_H +#define P11C_TRUST_H + +#include "p11-capi.h" + +/* Find trust objects matching criteria */ +CK_RV p11c_trust_find (P11cSession* sess, CK_OBJECT_CLASS cls, + CK_ATTRIBUTE_PTR match, CK_ULONG count, + P11cArray* arr); + +#endif /* P11C_TRUST_H */ diff --git a/module/p11-capi-util.c b/module/p11-capi-util.c new file mode 100644 index 0000000..5ebb72b --- /dev/null +++ b/module/p11-capi-util.c @@ -0,0 +1,547 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "p11-capi-util.h" + +#include +#include +#include + + +void +p11c_reverse_memory (void* data, size_t length) +{ + size_t end = length - 1; + size_t middle = length / 2; + unsigned char* buf = data; + size_t i; + + for (i = 0; i < middle; i++) + { + unsigned char tmp = buf[i]; + buf[i] = buf[end - i]; + buf[end - i] = tmp; + } +} + +/* + * Array code originially from Glib. + * Modified extensively by Stef Walter + */ + +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#define MIN_ARRAY_SIZE 16 + +typedef struct _RealArray +{ + P11cArray pub; + size_t alloc; + size_t elt_size; + int zero_terminated : 1; + int clear : 1; +} +RealArray; + +#define array_elt_len(array, i) ((array)->elt_size * (i)) +#define array_elt_pos(array, i) (((char*)(array)->pub.data) + array_elt_len((array),(i))) +#define array_elt_zero(array, pos, len) \ + (memset(array_elt_pos((array), pos), 0, array_elt_len((array), len))) +#define array_zero_terminate(array) \ + { if ((array)->zero_terminated) \ + array_elt_zero((array), (array)->pub.len, 1); } + +static unsigned int +nearest_pow(unsigned int num) +{ + unsigned int n = 1; + while(n < num) + n <<= 1; + return n; +} + +static int +maybe_expand(RealArray *array, size_t len) +{ + void* mem; + size_t want_alloc = array_elt_len(array, array->pub.len + len + + array->zero_terminated); + + if(want_alloc > array->alloc) + { + want_alloc = nearest_pow(want_alloc); + want_alloc = want_alloc > MIN_ARRAY_SIZE ? want_alloc : MIN_ARRAY_SIZE; + + mem = realloc(array->pub.data, want_alloc); + if(!mem) + return 0; + array->pub.data = mem; + + memset((char*)array->pub.data + array->alloc, 0, want_alloc - array->alloc); + array->alloc = want_alloc; + } + + return 1; +} + +P11cArray* +p11c_array_new(int zero_terminated, int clear, size_t elt_size) +{ + return p11c_array_sized_new(zero_terminated, clear, elt_size, 0); +} + +P11cArray* +p11c_array_sized_new(int zero_terminated, int clear, size_t elt_size, + size_t reserved_size) +{ + RealArray *array = malloc(sizeof(RealArray)); + if(!array) + return NULL; + + array->pub.data = NULL; + array->pub.len = 0; + array->alloc = 0; + array->zero_terminated = (zero_terminated ? 1 : 0); + array->clear = (clear ? 1 : 0); + array->elt_size = elt_size; + + if(array->zero_terminated || reserved_size != 0) + { + maybe_expand(array, reserved_size); + array_zero_terminate(array); + } + + return (P11cArray*)array; +} + +void* +p11c_array_free(P11cArray* array, int free_segment) +{ + void* segment; + + if(array == NULL) + return NULL; + + if(free_segment) + { + if(array->data) + free(array->data); + segment = NULL; + } + else + segment = array->data; + + free(array); + return segment; +} + +int +p11c_array_append_vals(P11cArray* parray, const void* data, size_t len) +{ + RealArray* array = (RealArray*)parray; + if(!maybe_expand(array, len)) + return 0; + + memcpy(array_elt_pos(array, array->pub.len), data, + array_elt_len(array, len)); + + array->pub.len += len; + array_zero_terminate(array); + + return 1; +} + +void +p11c_array_remove_index(P11cArray* parray, unsigned int index) +{ + RealArray* array = (RealArray*)parray; + + if(index >= array->pub.len) + return; + + if(index != array->pub.len - 1) + memmove(array_elt_pos (array, index), + array_elt_pos (array, index + 1), + array_elt_len (array, array->pub.len - index - 1)); + + array->pub.len -= 1; + + array_elt_zero (array, array->pub.len, 1); +} + +void +p11c_array_remove_range(P11cArray* parray, unsigned int index, size_t length) +{ + RealArray *array = (RealArray*)parray; + + if(index >= array->pub.len) + return; + if(index + length > array->pub.len) + length = array->pub.len - index; + if(length == 0) + return; + + if(index + length != array->pub.len) + memmove(array_elt_pos (array, index), + array_elt_pos (array, index + length), + (array->pub.len - (index + length)) * array->elt_size); + + array->pub.len -= length; + array_elt_zero(array, array->pub.len, length); +} + + +/* + * Originally from apache 2.0 + * Extensive modifications by + */ + +/* Copyright 2000-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/* + * The internal form of a hash table. + * + * The table is an array indexed by the hash of the key; collisions + * are resolved by hanging a linked list of hash entries off each + * element of the array. Although this is a really simple design it + * isn't too bad given that pools have a low allocation overhead. + */ + +typedef struct _HashEntry +{ + struct _HashEntry* next; + unsigned int hash; + const void* key; + void* val; +} +HashEntry; + +/* + * The size of the array is always a power of two. We use the maximum + * index rather than the size so that we can use bitwise-AND for + * modular arithmetic. + * The count of hash entries may be greater depending on the chosen + * collision rate. + */ +struct _P11cHash +{ + HashEntry** array; + P11cHashFunc hash_func; + P11cHashEqual equal_func; + size_t count; + size_t max; +}; + + +#define INITIAL_MAX 15 /* tunable == 2^n - 1 */ + +static int +equal_default(const void* a, const void* b) +{ + return a == b; +} + +/* + * Hash creation functions. + */ + +static HashEntry** +alloc_array(P11cHash* ht, size_t max) +{ + return calloc(1, sizeof(*(ht->array)) * (max + 1)); +} + +P11cHash* +p11c_hash_new(P11cHashFunc hash_func, P11cHashEqual equal_func) +{ + P11cHash* ht = malloc(sizeof(P11cHash)); + if(ht) + { + ht->hash_func = hash_func ? hash_func : p11c_hash_pointer; + ht->equal_func = equal_func ? equal_func : equal_default; + ht->count = 0; + ht->max = INITIAL_MAX; + ht->array = alloc_array(ht, ht->max); + if(!ht->array) + { + free(ht); + ht = NULL; + } + } + return ht; +} + +void +p11c_hash_free(P11cHash* ht, P11cHashDestroy destroy_func) +{ + HashEntry* he; + HashEntry* next; + size_t i; + + for(i = 0; i <= ht->max; ++i) + { + for(he = ht->array[i]; he; ) + { + next = he->next; + if(destroy_func) + (destroy_func)((void*)he->val); + free(he); + he = next; + } + } + + if(ht->array) + free(ht->array); + free(ht); +} + +/* + * Expanding a hash table + */ +static int +expand_array(P11cHash* ht) +{ + HashEntry** new_array; + size_t new_max; + HashEntry* he; + HashEntry* next; + size_t i; + + new_max = ht->max * 2 + 1; + new_array = alloc_array(ht, new_max); + + if(!new_array) + return 0; + + for(i = 0; i <= ht->max; ++i) + { + for(he = ht->array[i], next = he ? he->next : NULL; + he != NULL; he = next, next = next ? next->next : NULL) + { + unsigned int j = he->hash & new_max; + he->next = new_array[j]; + new_array[j] = he; + } + } + + if(ht->array) + free(ht->array); + + ht->array = new_array; + ht->max = new_max; + return 1; +} + +/* + * This is where we keep the details of the hash function and control + * the maximum collision rate. + * + * If val is non-NULL it creates and initializes a new hash entry if + * there isn't already one there; it returns an updatable pointer so + * that hash entries can be removed. + */ + +static HashEntry** +find_entry(P11cHash* ht, const void* key, void* val) +{ + HashEntry** hep; + HashEntry* he; + unsigned int hash; + + hash = (ht->hash_func)(key); + + /* scan linked list */ + for(hep = &ht->array[hash & ht->max], he = *hep; + he; hep = &he->next, he = *hep) + { + if(he->hash == hash && (ht->equal_func)(he->key, key)) + break; + } + + if(he || !val) + return hep; + + /* add a new entry for non-NULL val */ + he = malloc(sizeof(*he)); + if(he) + { + /* Key points to external data */ + he->key = key; + he->next = NULL; + he->hash = hash; + he->val = val; + + *hep = he; + ht->count++; + } + + return hep; +} + +void* +p11c_hash_get(P11cHash* ht, const void *key) +{ + HashEntry** he = find_entry(ht, key, NULL); + if(he && *he) + return (void*)((*he)->val); + else + return NULL; +} + +int +p11c_hash_set(P11cHash* ht, const void* key, void* val) +{ + HashEntry** hep = find_entry(ht, key, val); + if(hep && *hep) + { + /* replace entry */ + (*hep)->key = key; + (*hep)->val = val; + + /* check that the collision rate isn't too high */ + if(ht->count > ht->max) + { + if(!expand_array(ht)) + return 0; + } + + return 1; + } + + return 0; +} + +void* +p11c_hash_rem(P11cHash* ht, const void* key) +{ + HashEntry** hep = find_entry(ht, key, NULL); + void* val = NULL; + + if(hep && *hep) + { + HashEntry* old = *hep; + *hep = (*hep)->next; + --ht->count; + val = (void*)old->val; + free(old); + } + + return val; +} + +size_t +p11c_hash_count(P11cHash* ht) +{ + return ht->count; +} + +unsigned int +p11c_hash_pointer(const void* ptr) +{ + return (unsigned int)ptr; +} + +unsigned int +p11c_hash_data(const void* data, size_t n_data) +{ + unsigned int hash = 0; + const unsigned char* end; + const unsigned char* p; + + /* + * This is the popular `times 33' hash algorithm which is used by + * perl and also appears in Berkeley DB. This is one of the best + * known hash functions for strings because it is both computed + * very fast and distributes very well. + * + * The originator may be Dan Bernstein but the code in Berkeley DB + * cites Chris Torek as the source. The best citation I have found + * is "Chris Torek, Hash function for text in C, Usenet message + * <27038@mimsy.umd.edu> in comp.lang.c , October, 1990." in Rich + * Salz's USENIX 1992 paper about INN which can be found at + * . + * + * The magic of number 33, i.e. why it works better than many other + * constants, prime or not, has never been adequately explained by + * anyone. So I try an explanation: if one experimentally tests all + * multipliers between 1 and 256 (as I did while writing a low-level + * data structure library some time ago) one detects that even + * numbers are not useable at all. The remaining 128 odd numbers + * (except for the number 1) work more or less all equally well. + * They all distribute in an acceptable way and this way fill a hash + * table with an average percent of approx. 86%. + * + * If one compares the chi^2 values of the variants (see + * Bob Jenkins ``Hashing Frequently Asked Questions'' at + * http://burtleburtle.net/bob/hash/hashfaq.html for a description + * of chi^2), the number 33 not even has the best value. But the + * number 33 and a few other equally good numbers like 17, 31, 63, + * 127 and 129 have nevertheless a great advantage to the remaining + * numbers in the large set of possible multipliers: their multiply + * operation can be replaced by a faster operation based on just one + * shift plus either a single addition or subtraction operation. And + * because a hash function has to both distribute good _and_ has to + * be very fast to compute, those few numbers should be preferred. + * + * -- Ralf S. Engelschall + */ + + for(p = data, end = p + n_data; p != end; ++p) + hash = hash * 33 + *p; + + return hash; +} + +unsigned int +p11c_hash_integer(int integer) +{ + return integer; +} diff --git a/module/p11-capi-util.h b/module/p11-capi-util.h new file mode 100644 index 0000000..ed3507d --- /dev/null +++ b/module/p11-capi-util.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __P11C_UTIL_H__ +#define __P11C_UTIL_H__ + +#include + + +void p11c_reverse_memory (void* data, size_t length); + +/* -------------------------------------------------------------------------------- + * ARRAYS + */ + +typedef struct _Array +{ + void* data; + size_t len; +} +P11cArray; + +#define p11c_array_append(a,v) p11c_array_append_vals(a, &(v), 1) +#define p11c_array_index(a,t,i) (((t*) (a)->data) [(i)]) + +P11cArray* p11c_array_new (int zero_terminated, int zero, + size_t element_size); + +P11cArray* p11c_array_sized_new (int zero_terminated, int zero, + size_t element_size, size_t reserved_size); + +void* p11c_array_free (P11cArray* array, int free_segment); + +int p11c_array_append_vals (P11cArray* array, const void* data, + size_t num); + +void p11c_array_remove_index (P11cArray* array, unsigned int index); + +void p11c_array_remove_range (P11cArray* array, unsigned int index, + size_t count); + + +/* -------------------------------------------------------------------------------- + * HASHTABLE + */ + +struct _P11cHash; +typedef struct _P11cHash P11cHash; + +typedef unsigned int (*P11cHashFunc)(const void* key); + +typedef int (*P11cHashEqual)(const void* a, const void* b); + +typedef void (*P11cHashDestroy)(void* val); + +P11cHash* p11c_hash_new (P11cHashFunc hash_func, P11cHashEqual equal_func); + +void p11c_hash_free (P11cHash* ht, P11cHashDestroy destroy_func); + +size_t p11c_hash_count (P11cHash* ht); + +void* p11c_hash_get (P11cHash* ht, const void* key); + +int p11c_hash_set (P11cHash* ht, const void* key, void* val); + +void* p11c_hash_rem (P11cHash* ht, const void* key); + +unsigned int p11c_hash_pointer (const void* ptr); + +unsigned int p11c_hash_data (const void* data, size_t n_data); + +unsigned int p11c_hash_integer (int integer); + +#define p11c_hash_key(num) (((char*)NULL) + (size_t)(num)) + +#endif /* __P11C_UTIL_H__ */ diff --git a/module/p11-capi.c b/module/p11-capi.c new file mode 100644 index 0000000..b5f7f62 --- /dev/null +++ b/module/p11-capi.c @@ -0,0 +1,1515 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include "p11-capi.h" +#include "p11-capi-object.h" +#include "p11-capi-session.h" +#include "p11-capi-rsa.h" +#include "p11-capi-token.h" + +/* Warns about all the raw string usage in this file */ +#pragma warning (disable : 4996) + +/* ------------------------------------------------------------------- + * GLOBALS / DEFINES + */ + +static int cryptoki_initialized = 0; +static HANDLE global_mutex = NULL; + +#define MANUFACTURER_ID "Cryptoki CAPI " +#define LIBRARY_DESCRIPTION "Cryptoki CAPI Provider " +#define LIBRARY_VERSION_MAJOR 1 +#define LIBRARY_VERSION_MINOR 1 +#define HARDWARE_VERSION_MAJOR 0 +#define HARDWARE_VERSION_MINOR 0 +#define FIRMWARE_VERSION_MAJOR 0 +#define FIRMWARE_VERSION_MINOR 0 +#define SLOT_TOKEN_SERIAL "1.0 " +#define SLOT_TOKEN_MODEL "1.0 " +#define MAX_PIN_LEN 256 +#define MIN_PIN_LEN 1 + +static CK_MECHANISM_TYPE all_mechanisms[] = { + CKM_RSA_PKCS +}; + +/* ------------------------------------------------------------------- + * MODULE GLOBAL FUNCTIONS + */ + +#define LINE 1024 + +void +p11c_debug(const char* msg, ...) +{ + char buf[LINE]; + va_list va; + size_t len; + + va_start(va, msg); + _vsnprintf(buf, 1024, msg, va); + va_end(va); + + buf[LINE - 1] = 0; + len = strlen (buf); + + strncpy(buf + len, "\n", 1024 - len); + buf[LINE - 1] = 0; + // OutputDebugStringA(buf); +} + +/* Bah humbug, MSVC doesn't have __func__ */ +#define ENTER(func) \ + char* _func = #func; \ + p11c_debug("%s: enter", _func) + +#define RETURN(ret) \ + return (p11c_debug("%s: %d", _func, ret), ret) + +#define PREREQ(cond, ret) \ + if (!(cond)) { p11c_debug("%s: %s failed: %d", _func, #cond, ret); return ret; } + +void +p11c_lock_global(void) +{ + DWORD r; + + ASSERT(global_mutex); + + r = WaitForSingleObject(global_mutex, INFINITE); + ASSERT(r == WAIT_OBJECT_0); +} + +void +p11c_unlock_global(void) +{ + BOOL r; + + ASSERT(global_mutex); + + r = ReleaseMutex(global_mutex); + ASSERT(r); +} + +CK_RV +p11c_winerr_to_ckr(DWORD werr) +{ + switch(werr) + { + case ERROR_NOT_ENOUGH_MEMORY: + case ERROR_OUTOFMEMORY: + return CKR_HOST_MEMORY; + break; + case NTE_NO_MEMORY: + return CKR_DEVICE_MEMORY; + break; + case ERROR_MORE_DATA: + return CKR_BUFFER_TOO_SMALL; + case ERROR_INVALID_PARAMETER: /* these params were derived from the */ + case ERROR_INVALID_HANDLE: /* inputs, so if they are bad, the input */ + case NTE_BAD_ALGID: /* data is bad */ + case NTE_BAD_HASH: + case NTE_BAD_TYPE: + case NTE_BAD_PUBLIC_KEY: + return CKR_DATA_INVALID; + case ERROR_BUSY: + case NTE_FAIL: + case NTE_BAD_UID: + return CKR_DEVICE_ERROR; + default: + return CKR_GENERAL_ERROR; + }; +} + +CK_RV +p11c_return_data_raw(CK_VOID_PTR output, CK_ULONG_PTR n_output, + CK_VOID_PTR input, CK_ULONG n_input) +{ + ASSERT(n_output); + ASSERT(input); + + /* Just asking for the length */ + if(!output) + { + *n_output = n_input; + return CKR_OK; + } + + /* Buffer is too short */ + if(n_input > *n_output) + { + *n_output = n_input; + return CKR_BUFFER_TOO_SMALL; + } + + *n_output = n_input; + memcpy(output, input, n_input); + return CKR_OK; +} + +CK_RV +p11c_return_data(CK_ATTRIBUTE_PTR attr, CK_VOID_PTR input, DWORD n_input) +{ + return p11c_return_data_raw(attr->pValue, &(attr->ulValueLen), + input, n_input); +} + +CK_RV +p11c_return_string(CK_ATTRIBUTE_PTR attr, WCHAR* string) +{ + CK_UTF8CHAR_PTR buffer; + int result; + + SetLastError(0); + + /* + * Sadly WideCharToMultiByte doesn't handle zero + * length strings properly. So we have to special + * case this part. + */ + if(!string[0]) + return p11c_return_data(attr, "", 0); + + /* The length of the string, including null termination */ + result = WideCharToMultiByte(CP_UTF8, 0, string, -1, + NULL, 0, NULL, NULL); + + if(result) + { + /* Did the caller just want the length? */ + if(!attr->pValue) + { + attr->ulValueLen = result - 1; + return CKR_OK; + } + + /* Is the callers buffer too short? */ + if((int)attr->ulValueLen < result - 1) + { + attr->ulValueLen = result - 1; + return CKR_BUFFER_TOO_SMALL; + } + + /* + * Allocate a buffer for the conversion. We have to + * do this because strings in PKCS#11 are not null + * terminated and strings returned from + * WideCharToMultiByte are always null terminated. + */ + buffer = malloc(result); + if(!buffer) + return CKR_HOST_MEMORY; + + /* Do the actual conversion */ + result = WideCharToMultiByte(CP_UTF8, 0, string, -1, + buffer, result, NULL, NULL); + + if(result) + { + attr->ulValueLen = result - 1; + memcpy(attr->pValue, buffer, attr->ulValueLen); + + free(buffer); + return CKR_OK; + } + + free(buffer); + } + + /* + * We should never have too little buffer, or + * get a zero length success code. It's a very + * strange error that arrives here. + */ + return CKR_GENERAL_ERROR; +} + +CK_RV +p11c_return_dword_as_bytes(CK_ATTRIBUTE_PTR attr, DWORD value) +{ + int i; + CK_ULONG count = 0; + BOOL first = TRUE; + BYTE* at = attr->pValue; + CK_RV ret = CKR_OK; + + for(i = 0; i < sizeof(DWORD); i++) + { + BYTE digit = (BYTE)((value >> (((sizeof(DWORD)-1)*8))) & 0xFF); + value = value << 8; + + /* No leading zero */ + if (first && digit == 0) + continue; + + first = FALSE; + if(at) + { + if(count > attr->ulValueLen) + ret = CKR_BUFFER_TOO_SMALL; + else + *(at++) = digit; + } + + count++; + } + + attr->ulValueLen = count; + return ret; +} + +CK_RV +p11c_return_reversed_data(CK_ATTRIBUTE_PTR attr, CK_VOID_PTR data, CK_ULONG length) +{ + CK_RV ret = p11c_return_data(attr, data, length); + if(ret != CKR_OK || !attr->pValue) + return ret; + + p11c_reverse_memory(attr->pValue, attr->ulValueLen); + return CKR_OK; +} + +static void +print_zero_decimal(CK_BYTE_PTR buffer, CK_ULONG length, WORD value) +{ + int i; + for(i = (int)length - 1; i >= 0; --i) + { + BYTE digit = value % 10; + buffer[i] = '0' + digit; + value /= 10; + } +} + +CK_RV +p11c_return_filetime(CK_ATTRIBUTE_PTR attr, FILETIME *ftime) +{ + SYSTEMTIME stime; + CK_DATE* date; + + ASSERT(attr); + ASSERT(ftime); + + if(!attr->pValue) + { + attr->ulValueLen = sizeof(CK_DATE); + return CKR_OK; + } + + if(attr->ulValueLen < sizeof(CK_DATE)) + { + attr->ulValueLen = sizeof(CK_DATE); + return CKR_BUFFER_TOO_SMALL; + } + + if(!FileTimeToSystemTime(ftime, &stime)) + { + DBG(("An invalid FILETIME was encountered")); + return CKR_GENERAL_ERROR; + } + + date = (CK_DATE*)attr->pValue; + attr->ulValueLen = sizeof(CK_DATE); + print_zero_decimal(date->year, sizeof(date->year), stime.wYear); + print_zero_decimal(date->month, sizeof(date->month), stime.wMonth); + print_zero_decimal(date->day, sizeof(date->day), stime.wDay); + + return CKR_OK; +} + +/* ---------------------------------------------------------------- */ + +static CK_RV +PC_C_Initialize(CK_VOID_PTR init_args) +{ + ENTER(C_Initialize); + PREREQ(!cryptoki_initialized, CKR_CRYPTOKI_ALREADY_INITIALIZED); + + if (init_args != NULL) { + CK_C_INITIALIZE_ARGS_PTR args; + int supplied_ok; + + /* pReserved must be NULL */ + args = init_args; + PREREQ(!args->pReserved, CKR_ARGUMENTS_BAD); + + /* ALL supplied function pointers need to have the value either NULL or non-NULL. */ + supplied_ok = (args->CreateMutex == NULL && args->DestroyMutex == NULL && + args->LockMutex == NULL && args->UnlockMutex == NULL) || + (args->CreateMutex != NULL && args->DestroyMutex != NULL && + args->LockMutex != NULL && args->UnlockMutex != NULL); + PREREQ(supplied_ok, CKR_ARGUMENTS_BAD); + + /* + * When the CKF_OS_LOCKING_OK flag isn't set and mutex function pointers are supplied + * by an application, return an error. We must be able to use our own locks. + */ + if(!(args->flags & CKF_OS_LOCKING_OK) && (args->CreateMutex != NULL)) + RETURN(CKR_CANT_LOCK); + } + + if(!global_mutex) + { + global_mutex = CreateMutex(NULL, FALSE, NULL); + if(!global_mutex) + RETURN(CKR_CANT_LOCK); + } + + cryptoki_initialized = 1; + + RETURN(CKR_OK); +} + +static CK_RV +PC_C_Finalize(CK_VOID_PTR pReserved) +{ + ENTER(C_Finalize); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(!pReserved, CKR_ARGUMENTS_BAD); + + cryptoki_initialized = 0; + + p11c_session_cleanup_all(); + p11c_token_cleanup_all(); + + RETURN(CKR_OK); +} + +static CK_RV +PC_C_GetInfo(CK_INFO_PTR info) +{ + ENTER(C_GetInfo); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(info, CKR_ARGUMENTS_BAD); + + ASSERT(strlen(MANUFACTURER_ID) == 32); + ASSERT(strlen(LIBRARY_DESCRIPTION) == 32); + + info->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR; + info->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR; + info->libraryVersion.major = LIBRARY_VERSION_MAJOR; + info->libraryVersion.minor = LIBRARY_VERSION_MINOR; + info->flags = 0; + strncpy((char*)info->manufacturerID, MANUFACTURER_ID, 32); + strncpy((char*)info->libraryDescription, LIBRARY_DESCRIPTION, 32); + + RETURN(CKR_OK); +} + +static CK_RV +PC_C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR list) +{ + /* This would be a strange call to receive */ + return C_GetFunctionList(list); +} + +static CK_RV +PC_C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR slot_list, CK_ULONG_PTR count) +{ + unsigned int n_tokens, i; + + ENTER(C_GetSlotList); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(count, CKR_ARGUMENTS_BAD); + + /* All tokens are always present */ + + n_tokens = p11c_token_get_count(); + + /* Application only wants to know the number of slots. */ + if(slot_list == NULL) + { + *count = n_tokens; + RETURN(CKR_OK); + } + + if(*count < n_tokens) + { + *count = n_tokens; + RETURN(CKR_BUFFER_TOO_SMALL); + } + + *count = n_tokens; + for(i = 0; i < n_tokens; ++i) + slot_list[i] = p11c_token_get_slot_id (i); + RETURN(CKR_OK); +} + +static CK_RV +PC_C_GetSlotInfo(CK_SLOT_ID id, CK_SLOT_INFO_PTR info) +{ + const char* name; + + ENTER(C_GetSlotInfo); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(info, CKR_ARGUMENTS_BAD); + + /* Make sure the slot ID is valid */ + if(!p11c_token_is_valid(id)) + RETURN(CKR_SLOT_ID_INVALID); + + ASSERT(strlen(MANUFACTURER_ID) == 32); + + /* Provide information about the slot in the provided buffer */ + strncpy((char*)info->manufacturerID, MANUFACTURER_ID, 32); + info->hardwareVersion.major = HARDWARE_VERSION_MAJOR; + info->hardwareVersion.minor = HARDWARE_VERSION_MINOR; + info->firmwareVersion.major = FIRMWARE_VERSION_MAJOR; + info->firmwareVersion.minor = FIRMWARE_VERSION_MINOR; + + /* Token is always present */ + info->flags = CKF_TOKEN_PRESENT; + + /* Slot name is blank padded, odd */ + name = p11c_token_get_display_name(id); + memset((char*)info->slotDescription, ' ', + sizeof(info->slotDescription)); + memcpy((char*)info->slotDescription, name, + min(strlen(name), sizeof(info->slotDescription))); + + RETURN(CKR_OK); +} + +static CK_RV +PC_C_GetTokenInfo(CK_SLOT_ID id, CK_TOKEN_INFO_PTR info) +{ + const char* name; + + ENTER(C_GetTokenInfo); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(info, CKR_ARGUMENTS_BAD); + + /* Make sure the slot ID is valid */ + if(!p11c_token_is_valid(id)) + RETURN(CKR_SLOT_ID_INVALID); + + ASSERT(strlen(MANUFACTURER_ID) == 32); + ASSERT(strlen(SLOT_TOKEN_MODEL) == 16); + ASSERT(strlen(SLOT_TOKEN_SERIAL) == 16); + + /* Provide information about a token in the provided buffer */ + strncpy((char*)info->manufacturerID, MANUFACTURER_ID, 32); + strncpy((char*)info->model, SLOT_TOKEN_MODEL, 16); + strncpy((char*)info->serialNumber, SLOT_TOKEN_SERIAL, 16); + + /* Protected authentication path: Windows prompts for it's own PINs */ + info->flags = CKF_TOKEN_INITIALIZED | CKF_PROTECTED_AUTHENTICATION_PATH; + info->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE; + info->ulSessionCount = CK_EFFECTIVELY_INFINITE; + info->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE; + info->ulRwSessionCount = CK_EFFECTIVELY_INFINITE; + info->ulMaxPinLen = MAX_PIN_LEN; + info->ulMinPinLen = MIN_PIN_LEN; + info->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION; + info->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION; + info->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION; + info->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION; + info->hardwareVersion.major = HARDWARE_VERSION_MAJOR; + info->hardwareVersion.minor = HARDWARE_VERSION_MINOR; + info->firmwareVersion.major = FIRMWARE_VERSION_MAJOR; + info->firmwareVersion.minor = FIRMWARE_VERSION_MINOR; + memset(info->utcTime, ' ', 16); + + /* Slot name is blank padded, odd */ + name = p11c_token_get_display_name(id); + memset((char*)info->label, ' ', sizeof(info->label)); + memcpy((char*)info->label, name, + min(strlen(name), sizeof(info->label))); + + RETURN(CKR_OK); +} + +static CK_RV +PC_C_GetMechanismList(CK_SLOT_ID id, CK_MECHANISM_TYPE_PTR mechanism_list, + CK_ULONG_PTR count) +{ + CK_ULONG n_mechs; + + ENTER(C_GetMechanismList); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(count, CKR_ARGUMENTS_BAD); + + if(!p11c_token_is_valid(id)) + RETURN(CKR_SLOT_ID_INVALID); + + n_mechs = sizeof(all_mechanisms) / sizeof(all_mechanisms[0]); + + if(mechanism_list == NULL) + { + *count = n_mechs; + RETURN(CKR_OK); + } + + if(*count < n_mechs) + { + *count = n_mechs; + RETURN(CKR_BUFFER_TOO_SMALL); + } + + memcpy(mechanism_list, all_mechanisms, + n_mechs * sizeof(CK_MECHANISM_TYPE)); + *count = n_mechs; + RETURN(CKR_OK); +} + +static CK_RV +PC_C_GetMechanismInfo(CK_SLOT_ID id, CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR info) +{ + ENTER(C_GetMechanismInfo); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(info, CKR_ARGUMENTS_BAD); + + if(!p11c_token_is_valid(id)) + RETURN(CKR_SLOT_ID_INVALID); + + if(type == CKM_RSA_PKCS) + { + p11c_rsa_pkcs_get_info(type, info); + RETURN(CKR_OK); + } + + RETURN(CKR_MECHANISM_INVALID); +} + +static CK_RV +PC_C_InitToken(CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len, + CK_UTF8CHAR_PTR label) +{ + ENTER(C_InitToken); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved) +{ + ENTER(C_WaitForSlotEvent); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* + * PKCS#11 GRAY AREA: What happens when we know we'll *never* + * have any slot events, and someone calls us without CKR_DONT_BLOCK? + * In case there's a thread dedicated to calling this function in a + * loop, we wait 1 seconds when called without CKR_DONT_BLOCK. + */ + + if(!(flags & CKF_DONT_BLOCK)) + Sleep(1000); + + RETURN(CKR_NO_EVENT); +} + +static CK_RV +PC_C_OpenSession(CK_SLOT_ID id, CK_FLAGS flags, CK_VOID_PTR application, + CK_NOTIFY notify, CK_SESSION_HANDLE_PTR session) +{ + P11cSession* sess; + CK_RV ret; + + ENTER(C_OpenSession); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(session, CKR_ARGUMENTS_BAD); + PREREQ(flags & CKF_SERIAL_SESSION, CKR_SESSION_PARALLEL_NOT_SUPPORTED); + + if(!p11c_token_is_valid(id)) + RETURN(CKR_SLOT_ID_INVALID); + + ret = p11c_session_create(id, &sess); + if(ret != CKR_OK) + RETURN(ret); + + sess->notify_callback = notify; + sess->user_data = application; + + if(flags & CKF_RW_SESSION) + sess->read_write = TRUE; + + ret = p11c_session_register(sess); + if(ret == CKR_OK) + { + /* ID should have been assigned when registering */ + ASSERT(sess->id > 0); + *session = sess->id; + } + else + { + p11c_session_destroy(sess); + } + + RETURN(ret); +} + +static CK_RV +PC_C_CloseSession(CK_SESSION_HANDLE session) +{ + P11cSession* sess; + CK_RV ret; + + ENTER(C_CloseSession); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + ret = p11c_session_remove_lock_ref(session, &sess); + if(ret == CKR_OK) + { + /* This will unref and possibly destroy the session */ + p11c_session_unref_unlock(sess); + } + + RETURN(ret); +} + +static CK_RV +PC_C_CloseAllSessions(CK_SLOT_ID id) +{ + ENTER(C_CloseAllSession); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + if(!p11c_token_is_valid(id)) + RETURN(CKR_SLOT_ID_INVALID); + + p11c_session_close_all(id); + RETURN(CKR_OK); +} + +static CK_RV +PC_C_GetFunctionStatus(CK_SESSION_HANDLE session) +{ + ENTER(C_GetFunctionStatus); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + RETURN(CKR_FUNCTION_NOT_PARALLEL); +} + +static CK_RV +PC_C_CancelFunction(CK_SESSION_HANDLE session) +{ + ENTER(C_CancelFunction); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + RETURN(CKR_FUNCTION_NOT_PARALLEL); +} + +static CK_RV +PC_C_GetSessionInfo(CK_SESSION_HANDLE session, CK_SESSION_INFO_PTR info) +{ + P11cSession* sess; + CK_RV ret; + + ENTER(C_GetSessionInfo); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(info, CKR_ARGUMENTS_BAD); + + ret = p11c_session_get_lock_ref(session, FALSE, &sess); + if(ret == CKR_OK) + { + p11c_session_get_info(sess, info); + p11c_session_unref_unlock(sess); + } + + RETURN(ret); +} + +static CK_RV +PC_C_InitPIN(CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR pin, + CK_ULONG pin_len) +{ + ENTER(C_InitPIN); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* We don't support this stuff. We don't support 'SO' logins. */ + RETURN(CKR_USER_NOT_LOGGED_IN); +} + +static CK_RV +PC_C_SetPIN(CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR old_pin, + CK_ULONG old_len, CK_UTF8CHAR_PTR new_pin, CK_ULONG new_len) +{ + ENTER(C_SetPIN); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* Not supported, Windows takes care of this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_GetOperationState(CK_SESSION_HANDLE session, CK_BYTE_PTR operation_state, + CK_ULONG_PTR operation_state_len) +{ + ENTER(C_GetOperationState); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* Nasty, no sirrr */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_SetOperationState(CK_SESSION_HANDLE session, CK_BYTE_PTR operation_state, + CK_ULONG operation_state_len, CK_OBJECT_HANDLE encryption_key, + CK_OBJECT_HANDLE authentication_key) +{ + ENTER(C_SetOperationState); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* Nasty, no sirrr */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_Login(CK_SESSION_HANDLE session, CK_USER_TYPE user_type, + CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) +{ + P11cSession* sess; + CK_RV ret; + + ENTER(C_Login); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + ret = p11c_session_get_lock_ref(session, FALSE, &sess); + if(ret == CKR_OK) + { + switch(user_type) + { + case CKU_USER: + ret = p11c_token_login(sess->slot); + break; + case CKU_SO: + ret = CKR_USER_TYPE_INVALID; + break; + default: + ret = CKR_USER_TYPE_INVALID; + break; + } + + p11c_session_unref_unlock(sess); + } + + RETURN(ret); +} + +static CK_RV +PC_C_Logout(CK_SESSION_HANDLE session) +{ + P11cSession* sess; + CK_RV ret; + + ENTER(C_Logout); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + ret = p11c_session_get_lock_ref(session, FALSE, &sess); + if(ret == CKR_OK) + { + ret = p11c_token_logout(sess->slot); + p11c_session_unref_unlock(sess); + } + + RETURN(ret); +} + +static CK_RV +PC_C_CreateObject(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR templ, + CK_ULONG count, CK_OBJECT_HANDLE_PTR object) +{ + ENTER(C_CreateObject); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: See if we need to support this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_CopyObject(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR templ, CK_ULONG count, + CK_OBJECT_HANDLE_PTR new_object) +{ + ENTER(C_CopyObject); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: See if we need to support this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + + +static CK_RV +PC_C_DestroyObject(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) +{ + ENTER(C_DestroyObject); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: See if we need to support this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_GetObjectSize(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, + CK_ULONG_PTR size) +{ + ENTER(C_GetObjectSize); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: Implement this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_GetAttributeValue(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR templ, CK_ULONG count) +{ + P11cSession* sess; + P11cObjectData* objdata; + CK_RV ret; + + ENTER(C_GetAttributeValue); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(object, CKR_OBJECT_HANDLE_INVALID); + PREREQ(!count || templ, CKR_ARGUMENTS_BAD); + + ret = p11c_session_get_lock_ref(session, FALSE, &sess); + if(ret == CKR_OK) + { + ret = p11c_session_get_object_data_for(sess, object, &objdata); + if(ret == CKR_OK) + ret = p11c_object_data_get_attrs(objdata, templ, count); + + p11c_session_unref_unlock(sess); + } + + RETURN(ret); +} + +static CK_RV +PC_C_SetAttributeValue(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR templ, CK_ULONG count) +{ + ENTER(C_SetAttributeValue); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: See if we need to implement this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_FindObjectsInit(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR templ, + CK_ULONG count) +{ + P11cSession* sess; + CK_RV ret; + + ENTER(C_FindObjectsInit); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(!count || templ, CKR_ARGUMENTS_BAD); + + ret = p11c_session_get_lock_ref(session, FALSE, &sess); + if(ret == CKR_OK) + { + ret = p11c_session_find_init(sess, templ, count); + p11c_session_unref_unlock(sess); + } + + RETURN(ret); +} + +static CK_RV +PC_C_FindObjects(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE_PTR objects, + CK_ULONG max_object_count, CK_ULONG_PTR object_count) +{ + P11cSession* sess; + CK_RV ret; + + ENTER(C_FindObjects); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(object_count, CKR_ARGUMENTS_BAD); + PREREQ(!max_object_count || objects, CKR_ARGUMENTS_BAD); + + ret = p11c_session_get_lock_ref(session, FALSE, &sess); + if(ret == CKR_OK) + { + ret = p11c_session_find(sess, objects, max_object_count, object_count); + p11c_session_unref_unlock(sess); + } + + RETURN(ret); +} + +static CK_RV +PC_C_FindObjectsFinal(CK_SESSION_HANDLE session) +{ + P11cSession* sess; + CK_RV ret; + + ENTER(C_FindObjectsFinal); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + ret = p11c_session_get_lock_ref(session, FALSE, &sess); + if(ret == CKR_OK) + { + ret = p11c_session_find_final(sess); + p11c_session_unref_unlock(sess); + } + + RETURN(ret); +} + +static CK_RV +PC_C_EncryptInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + ENTER(C_EncryptInit); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: See if we need to implement this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_Encrypt(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, + CK_BYTE_PTR encrypted_data, CK_ULONG_PTR encrypted_data_len) +{ + ENTER(C_Encrypt); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: See if we need to implement this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_EncryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, + CK_ULONG part_len, CK_BYTE_PTR encrypted_part, + CK_ULONG_PTR encrypted_part_len) +{ + ENTER(C_EncryptUpdate); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support incremental crypto operations. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_EncryptFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR last_encrypted_part, + CK_ULONG_PTR last_encrypted_part_len) +{ + ENTER(C_EncryptFinal); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support incremental crypto operations. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_DecryptInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + P11cObjectData* objdata; + P11cSession* sess; + CK_RV ret; + + ENTER(C_DecryptInit); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(mechanism, CKR_ARGUMENTS_BAD); + PREREQ(key, CKR_ARGUMENTS_BAD); + + ret = p11c_session_get_lock_ref(session, FALSE, &sess); + if(ret == CKR_OK) + { + ret = p11c_session_get_object_data_for(sess, key, &objdata); + if(ret == CKR_OK) + ret = p11c_session_decrypt_init(sess, mechanism, objdata); + + p11c_session_unref_unlock(sess); + } + + RETURN(ret); +} + +static CK_RV +PC_C_Decrypt(CK_SESSION_HANDLE session, CK_BYTE_PTR encrypted_data, + CK_ULONG encrypted_data_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len) +{ + P11cSession* sess; + CK_RV ret; + + ENTER(C_Decrypt); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(encrypted_data, CKR_ARGUMENTS_BAD); + PREREQ(encrypted_data_len, CKR_ARGUMENTS_BAD); + + ret = p11c_session_get_lock_ref(session, FALSE, &sess); + if(ret == CKR_OK) + { + ret = p11c_session_decrypt(sess, encrypted_data, encrypted_data_len, + data, data_len); + p11c_session_unref_unlock(sess); + } + + RETURN(ret); +} + +static CK_RV +PC_C_DecryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR encrypted_part, + CK_ULONG encrypted_part_len, CK_BYTE_PTR part, CK_ULONG_PTR part_len) +{ + ENTER(C_DecryptUpdate); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support incremental crypto operations. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_DecryptFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR pLastPart, + CK_ULONG_PTR last_part_len) +{ + ENTER(C_DecryptFinal); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support incremental crypto operations. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_DigestInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism) +{ + ENTER(C_DigestInit); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support digest. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_Digest(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, + CK_BYTE_PTR digest, CK_ULONG_PTR digest_len) +{ + ENTER(C_Digest); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support digest. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_DigestUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len) +{ + ENTER(C_DigestUpdate); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support digest. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_DigestKey(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) +{ + ENTER(C_DigestKey); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support digest. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_DigestFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR digest, + CK_ULONG_PTR digest_len) +{ + ENTER(C_DigestFinal); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support digest. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_SignInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + P11cObjectData* objdata; + P11cSession* sess; + CK_RV ret; + + ENTER(C_SignInit); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(mechanism, CKR_ARGUMENTS_BAD); + PREREQ(key, CKR_ARGUMENTS_BAD); + + ret = p11c_session_get_lock_ref(session, FALSE, &sess); + if(ret == CKR_OK) + { + ret = p11c_session_get_object_data_for(sess, key, &objdata); + if(ret == CKR_OK) + ret = p11c_session_sign_init(sess, mechanism, objdata); + + p11c_session_unref_unlock(sess); + } + + RETURN(ret); +} + +static CK_RV +PC_C_Sign(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, + CK_BYTE_PTR signature, CK_ULONG_PTR signature_len) +{ + P11cSession* sess; + CK_RV ret; + + ENTER(C_Sign); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + PREREQ(data, CKR_ARGUMENTS_BAD); + PREREQ(data_len, CKR_ARGUMENTS_BAD); + + ret = p11c_session_get_lock_ref(session, FALSE, &sess); + if(ret == CKR_OK) + { + ret = p11c_session_sign(sess, data, data_len, signature, signature_len); + p11c_session_unref_unlock(sess); + } + + RETURN(ret); +} + +static CK_RV +PC_C_SignUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len) +{ + ENTER(C_SignUpdate); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support incremental crypto operations. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_SignFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR signature, + CK_ULONG_PTR signature_len) +{ + ENTER(C_SignFinal); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support incremental crypto operations. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_SignRecoverInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + ENTER(C_SignRecoverInit); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: Implement this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_SignRecover(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, + CK_BYTE_PTR signature, CK_ULONG_PTR signature_len) +{ + ENTER(C_SignRecover); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: Implement this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_VerifyInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + ENTER(C_VerifyInit); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: See if we need to implement this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_Verify(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, + CK_BYTE_PTR signature, CK_ULONG signature_len) +{ + ENTER(C_Verify); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: See if we need to implement this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_VerifyUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len) +{ + ENTER(C_VerifyUpdate); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support incremental crypto operations. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_VerifyFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR signature, + CK_ULONG signature_len) +{ + ENTER(C_VerifyFinal); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support incremental crypto operations. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_VerifyRecoverInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + ENTER(C_VerifyRecoverInit); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: See if we need to implement this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_VerifyRecover(CK_SESSION_HANDLE session, CK_BYTE_PTR signature, + CK_ULONG signature_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len) +{ + ENTER(C_VerifyRecover); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: See if we need to implement this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_DigestEncryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, + CK_ULONG part_len, CK_BYTE_PTR encrypted_part, + CK_ULONG_PTR encrypted_part_len) +{ + ENTER(C_DigestEncryptUpdate); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support incremental crypto operations. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_DecryptDigestUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR encrypted_part, + CK_ULONG encrypted_part_len, CK_BYTE_PTR part, + CK_ULONG_PTR part_len) +{ + ENTER(C_DecryptDigestUpdate); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support incremental crypto operations. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_SignEncryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, + CK_ULONG part_len, CK_BYTE_PTR encrypted_part, + CK_ULONG_PTR encrypted_part_len) +{ + ENTER(C_SignEncryptUpdate); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support incremental crypto operations. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_DecryptVerifyUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR encrypted_part, + CK_ULONG encrypted_part_len, CK_BYTE_PTR part, + CK_ULONG_PTR part_len) +{ + ENTER(C_DecryptVerifyUpdate); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* RSA/DSA mechs don't support incremental crypto operations. */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_GenerateKey(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_ATTRIBUTE_PTR templ, CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + ENTER(C_GenerateKey); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* Let key generation happen via Windows interfaces */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_GenerateKeyPair(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_ATTRIBUTE_PTR public_key_template, CK_ULONG public_key_attribute_count, + CK_ATTRIBUTE_PTR private_key_template, CK_ULONG private_key_attribute_count, + CK_OBJECT_HANDLE_PTR public_key, CK_OBJECT_HANDLE_PTR private_key) +{ + ENTER(C_GenerateKeyPair); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* Let key generation happen via Windows interfaces */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_WrapKey(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, + CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len) +{ + ENTER(C_WrapKey); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: See if we need to implement this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_UnwrapKey(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key, + CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR templ, + CK_ULONG count, CK_OBJECT_HANDLE_PTR key) +{ + ENTER(C_UnwrapKey); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* TODO: See if we need to implement this */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_DeriveKey(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE_PTR templ, + CK_ULONG count, CK_OBJECT_HANDLE_PTR key) +{ + ENTER(C_DeriveKey); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* Can't do this with RSA */ + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_SeedRandom(CK_SESSION_HANDLE session, CK_BYTE_PTR seed, CK_ULONG seed_len) +{ + ENTER(C_SeedRandom); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* + * TODO: Perhaps at some point in the future we may want + * to see if we can hook into the Windows RNG + */ + + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_RV +PC_C_GenerateRandom(CK_SESSION_HANDLE session, CK_BYTE_PTR random_data, + CK_ULONG random_len) +{ + ENTER(C_GenerateRandom); + PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + + /* + * TODO: Perhaps at some point in the future we may want + * to see if we can hook into the Windows RNG + */ + + RETURN(CKR_FUNCTION_NOT_SUPPORTED); +} + +static CK_FUNCTION_LIST functionList = { + { 2, 11 }, /* version */ + PC_C_Initialize, + PC_C_Finalize, + PC_C_GetInfo, + PC_C_GetFunctionList, + PC_C_GetSlotList, + PC_C_GetSlotInfo, + PC_C_GetTokenInfo, + PC_C_GetMechanismList, + PC_C_GetMechanismInfo, + PC_C_InitToken, + PC_C_InitPIN, + PC_C_SetPIN, + PC_C_OpenSession, + PC_C_CloseSession, + PC_C_CloseAllSessions, + PC_C_GetSessionInfo, + PC_C_GetOperationState, + PC_C_SetOperationState, + PC_C_Login, + PC_C_Logout, + PC_C_CreateObject, + PC_C_CopyObject, + PC_C_DestroyObject, + PC_C_GetObjectSize, + PC_C_GetAttributeValue, + PC_C_SetAttributeValue, + PC_C_FindObjectsInit, + PC_C_FindObjects, + PC_C_FindObjectsFinal, + PC_C_EncryptInit, + PC_C_Encrypt, + PC_C_EncryptUpdate, + PC_C_EncryptFinal, + PC_C_DecryptInit, + PC_C_Decrypt, + PC_C_DecryptUpdate, + PC_C_DecryptFinal, + PC_C_DigestInit, + PC_C_Digest, + PC_C_DigestUpdate, + PC_C_DigestKey, + PC_C_DigestFinal, + PC_C_SignInit, + PC_C_Sign, + PC_C_SignUpdate, + PC_C_SignFinal, + PC_C_SignRecoverInit, + PC_C_SignRecover, + PC_C_VerifyInit, + PC_C_Verify, + PC_C_VerifyUpdate, + PC_C_VerifyFinal, + PC_C_VerifyRecoverInit, + PC_C_VerifyRecover, + PC_C_DigestEncryptUpdate, + PC_C_DecryptDigestUpdate, + PC_C_SignEncryptUpdate, + PC_C_DecryptVerifyUpdate, + PC_C_GenerateKey, + PC_C_GenerateKeyPair, + PC_C_WrapKey, + PC_C_UnwrapKey, + PC_C_DeriveKey, + PC_C_SeedRandom, + PC_C_GenerateRandom, + PC_C_GetFunctionStatus, + PC_C_CancelFunction, + PC_C_WaitForSlotEvent +}; + +__declspec(dllexport) CK_RV +C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR list) +{ + if(!list) + return CKR_ARGUMENTS_BAD; + + *list = &functionList; + return CKR_OK; +} diff --git a/module/p11-capi.dep b/module/p11-capi.dep new file mode 100644 index 0000000..c04832a --- /dev/null +++ b/module/p11-capi.dep @@ -0,0 +1,69 @@ +# Microsoft Developer Studio Generated Dependency File, included by p11c.mak + +".\p11-capi-builtin.c" : \ + "..\..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\p11-capi-util.h"\ + ".\p11-capi.h"\ + ".\pkcs11\cryptoki.h"\ + ".\pkcs11\pkcs11.h"\ + ".\pkcs11\pkcs11f.h"\ + ".\pkcs11\pkcs11n.h"\ + ".\pkcs11\pkcs11t.h"\ + + +".\p11-capi-cert.c" : \ + "..\..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\p11-capi-util.h"\ + ".\p11-capi.h"\ + ".\pkcs11\cryptoki.h"\ + ".\pkcs11\pkcs11.h"\ + ".\pkcs11\pkcs11f.h"\ + ".\pkcs11\pkcs11t.h"\ + + +".\p11-capi-object.c" : \ + "..\..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\p11-capi-util.h"\ + ".\p11-capi.h"\ + ".\pkcs11\cryptoki.h"\ + ".\pkcs11\pkcs11.h"\ + ".\pkcs11\pkcs11f.h"\ + ".\pkcs11\pkcs11n.h"\ + ".\pkcs11\pkcs11t.h"\ + + +".\p11-capi-session.c" : \ + "..\..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\p11-capi-util.h"\ + ".\p11-capi.h"\ + ".\pkcs11\cryptoki.h"\ + ".\pkcs11\pkcs11.h"\ + ".\pkcs11\pkcs11f.h"\ + ".\pkcs11\pkcs11t.h"\ + + +".\p11-capi-trust.c" : \ + "..\..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\p11-capi-util.h"\ + ".\p11-capi.h"\ + ".\pkcs11\cryptoki.h"\ + ".\pkcs11\pkcs11.h"\ + ".\pkcs11\pkcs11f.h"\ + ".\pkcs11\pkcs11n.h"\ + ".\pkcs11\pkcs11t.h"\ + ".\x509-usages.h"\ + + +".\p11-capi-util.c" : \ + ".\p11-capi-util.h"\ + + +.\p11-capi.c : \ + "..\..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\p11-capi-util.h"\ + ".\p11-capi.h"\ + ".\pkcs11\cryptoki.h"\ + ".\pkcs11\pkcs11.h"\ + ".\pkcs11\pkcs11f.h"\ + ".\pkcs11\pkcs11t.h"\ + diff --git a/module/p11-capi.h b/module/p11-capi.h new file mode 100644 index 0000000..e522bfa --- /dev/null +++ b/module/p11-capi.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2007 Stef Walter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef P11C_H +#define P11C_H + +/* -------------------------------------------------------------------- + * + * Session = P11cSession + * - A PKCS#11 Session + * + * Objects = P11cObject + * - There's a global list of objects in p11c-object.c indexed by + * object handle. + * - The object itself has no attributes or cached data, but knows how + * to load data when needed. + * - Each object has a unique key which guarantees we don't load the + * same object twice with two different object handles. + * + * Object Data = P11cObjectData + * - Object Data is owned by the Session + * - Loaded data and/or attributes for an object. + */ + +#define WIN32_LEAN_AND_MEAN +#define _WIN32_WINNT 0x400 +#include +#include + +#define P11c_ENCODINGS (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING) + +#define CRYPTOKI_EXPORTS +#include "pkcs11/pkcs11.h" + +#include "p11-capi-util.h" + +struct _P11cSlot; +struct _P11cObject; +struct _P11cObjectData; +struct _P11cSession; + +typedef struct _P11cSlot P11cSlot; +typedef struct _P11cObject P11cObject; +typedef struct _P11cObjectData P11cObjectData; +typedef struct _P11cSession P11cSession; + +/* ------------------------------------------------------------------ + * cryptoki-capi.c + * + * Module helper and logging functions. + */ + +#define DBG(args) p11c_debug args + +void p11c_debug (const char* msg, ...); + +/* + * Protect global data with these. + */ +void p11c_lock_global (void); +void p11c_unlock_global (void); + +/* + * Convert a GetLastError() windows error to a + * PKCS#11 return code. + */ +CK_RV p11c_winerr_to_ckr (DWORD werr); + +/* + * This stores data in the output buffer with appropriate + * PKCS#11 codes when the buffer is too short, or the caller + * just wants to know the length, etc. + */ +CK_RV p11c_return_data (CK_ATTRIBUTE_PTR attr, + CK_VOID_PTR src, DWORD slen); + +CK_RV p11c_return_data_raw (CK_VOID_PTR output, CK_ULONG_PTR n_output, + CK_VOID_PTR input, CK_ULONG n_input); + +/* + * This stores a string in the output buffer with appropriate + * PKCS#11 codes when the buffer is too short, or the caller + * just wants to know the length, etc. + */ +CK_RV p11c_return_string (CK_ATTRIBUTE_PTR attr, + WCHAR* string); + +CK_RV p11c_return_dword_as_bytes (CK_ATTRIBUTE_PTR attr, + DWORD value); + +CK_RV p11c_return_reversed_data (CK_ATTRIBUTE_PTR attr, + CK_VOID_PTR data, CK_ULONG length); + +CK_RV p11c_return_filetime (CK_ATTRIBUTE_PTR attr, + FILETIME* ftime); + +/* ------------------------------------------------------------------ */ + +typedef void (*P11cDestroyFunc)(void* data); + +#ifndef ASSERT +#include "assert.h" +#define ASSERT assert +#endif + +/* Represents 'any' class in searches */ +#define CKO_ANY CK_INVALID_HANDLE + + +#endif /* P11C_CAPI_H */ diff --git a/module/p11-capi.vcproj b/module/p11-capi.vcproj new file mode 100644 index 0000000..7c554d1 --- /dev/null +++ b/module/p11-capi.vcproj @@ -0,0 +1,428 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/module/pkcs11/Makefile.am b/module/pkcs11/Makefile.am new file mode 100644 index 0000000..b3598ba --- /dev/null +++ b/module/pkcs11/Makefile.am @@ -0,0 +1,9 @@ + +EXTRA_DIST = \ + cryptoki.h \ + pkcs11.h \ + pkcs11f.h \ + pkcs11t.h \ + pkcs-11v2-20a3.h + + diff --git a/module/pkcs11/pkcs11.h b/module/pkcs11/pkcs11.h new file mode 100644 index 0000000..2e6a1e3 --- /dev/null +++ b/module/pkcs11/pkcs11.h @@ -0,0 +1,1357 @@ +/* pkcs11.h + Copyright 2006, 2007 g10 Code GmbH + Copyright 2006 Andreas Jellinghaus + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. */ + +/* Please submit changes back to the Scute project at + http://www.scute.org/ (or send them to marcus@g10code.com), so that + they can be picked up by other projects from there as well. */ + +/* This file is a modified implementation of the PKCS #11 standard by + RSA Security Inc. It is mostly a drop-in replacement, with the + following change: + + This header file does not require any macro definitions by the user + (like CK_DEFINE_FUNCTION etc). In fact, it defines those macros + for you (if useful, some are missing, let me know if you need + more). + + There is an additional API available that does comply better to the + GNU coding standard. It can be switched on by defining + CRYPTOKI_GNU before including this header file. For this, the + following changes are made to the specification: + + All structure types are changed to a "struct ck_foo" where CK_FOO + is the type name in PKCS #11. + + All non-structure types are changed to ck_foo_t where CK_FOO is the + lowercase version of the type name in PKCS #11. The basic types + (CK_ULONG et al.) are removed without substitute. + + All members of structures are modified in the following way: Type + indication prefixes are removed, and underscore characters are + inserted before words. Then the result is lowercased. + + Note that function names are still in the original case, as they + need for ABI compatibility. + + CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute. Use + . + + If CRYPTOKI_COMPAT is defined before including this header file, + then none of the API changes above take place, and the API is the + one defined by the PKCS #11 standard. */ + +#ifndef PKCS11_H +#define PKCS11_H 1 + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* The version of cryptoki we implement. The revision is changed with + each modification of this file. If you do not use the "official" + version of this file, please consider deleting the revision macro + (you may use a macro with a different name to keep track of your + versions). */ +#define CRYPTOKI_VERSION_MAJOR 2 +#define CRYPTOKI_VERSION_MINOR 20 +#define CRYPTOKI_VERSION_REVISION 6 + + +/* Compatibility interface is default, unless CRYPTOKI_GNU is + given. */ +#ifndef CRYPTOKI_GNU +#ifndef CRYPTOKI_COMPAT +#define CRYPTOKI_COMPAT 1 +#endif +#endif + +/* System dependencies. */ + +#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) + +/* There is a matching pop below. */ +#pragma pack(push, cryptoki, 1) + +#ifdef CRYPTOKI_EXPORTS +#define CK_SPEC __declspec(dllexport) +#else +#define CK_SPEC __declspec(dllimport) +#endif + +#else + +#define CK_SPEC + +#endif + + +#ifdef CRYPTOKI_COMPAT + /* If we are in compatibility mode, switch all exposed names to the + PKCS #11 variant. There are corresponding #undefs below. */ + +#define ck_flags_t CK_FLAGS +#define ck_version _CK_VERSION + +#define ck_info _CK_INFO +#define cryptoki_version cryptokiVersion +#define manufacturer_id manufacturerID +#define library_description libraryDescription +#define library_version libraryVersion + +#define ck_notification_t CK_NOTIFICATION +#define ck_slot_id_t CK_SLOT_ID + +#define ck_slot_info _CK_SLOT_INFO +#define slot_description slotDescription +#define hardware_version hardwareVersion +#define firmware_version firmwareVersion + +#define ck_token_info _CK_TOKEN_INFO +#define serial_number serialNumber +#define max_session_count ulMaxSessionCount +#define session_count ulSessionCount +#define max_rw_session_count ulMaxRwSessionCount +#define rw_session_count ulRwSessionCount +#define max_pin_len ulMaxPinLen +#define min_pin_len ulMinPinLen +#define total_public_memory ulTotalPublicMemory +#define free_public_memory ulFreePublicMemory +#define total_private_memory ulTotalPrivateMemory +#define free_private_memory ulFreePrivateMemory +#define utc_time utcTime + +#define ck_session_handle_t CK_SESSION_HANDLE +#define ck_user_type_t CK_USER_TYPE +#define ck_state_t CK_STATE + +#define ck_session_info _CK_SESSION_INFO +#define slot_id slotID +#define device_error ulDeviceError + +#define ck_object_handle_t CK_OBJECT_HANDLE +#define ck_object_class_t CK_OBJECT_CLASS +#define ck_hw_feature_type_t CK_HW_FEATURE_TYPE +#define ck_key_type_t CK_KEY_TYPE +#define ck_certificate_type_t CK_CERTIFICATE_TYPE +#define ck_attribute_type_t CK_ATTRIBUTE_TYPE + +#define ck_attribute _CK_ATTRIBUTE +#define value pValue +#define value_len ulValueLen + +#define ck_date _CK_DATE + +#define ck_mechanism_type_t CK_MECHANISM_TYPE + +#define ck_mechanism _CK_MECHANISM +#define parameter pParameter +#define parameter_len ulParameterLen + +#define ck_mechanism_info _CK_MECHANISM_INFO +#define min_key_size ulMinKeySize +#define max_key_size ulMaxKeySize + +#define ck_rv_t CK_RV +#define ck_notify_t CK_NOTIFY + +#define ck_function_list _CK_FUNCTION_LIST + +#define ck_createmutex_t CK_CREATEMUTEX +#define ck_destroymutex_t CK_DESTROYMUTEX +#define ck_lockmutex_t CK_LOCKMUTEX +#define ck_unlockmutex_t CK_UNLOCKMUTEX + +#define ck_c_initialize_args _CK_C_INITIALIZE_ARGS +#define create_mutex CreateMutex +#define destroy_mutex DestroyMutex +#define lock_mutex LockMutex +#define unlock_mutex UnlockMutex +#define reserved pReserved + +#endif /* CRYPTOKI_COMPAT */ + + + +typedef unsigned long ck_flags_t; + +struct ck_version +{ + unsigned char major; + unsigned char minor; +}; + + +struct ck_info +{ + struct ck_version cryptoki_version; + unsigned char manufacturer_id[32]; + ck_flags_t flags; + unsigned char library_description[32]; + struct ck_version library_version; +}; + + +typedef unsigned long ck_notification_t; + +#define CKN_SURRENDER (0) + + +typedef unsigned long ck_slot_id_t; + + +struct ck_slot_info +{ + unsigned char slot_description[64]; + unsigned char manufacturer_id[32]; + ck_flags_t flags; + struct ck_version hardware_version; + struct ck_version firmware_version; +}; + + +#define CKF_TOKEN_PRESENT (1 << 0) +#define CKF_REMOVABLE_DEVICE (1 << 1) +#define CKF_HW_SLOT (1 << 2) +#define CKF_ARRAY_ATTRIBUTE (1 << 30) + + +struct ck_token_info +{ + unsigned char label[32]; + unsigned char manufacturer_id[32]; + unsigned char model[16]; + unsigned char serial_number[16]; + ck_flags_t flags; + unsigned long max_session_count; + unsigned long session_count; + unsigned long max_rw_session_count; + unsigned long rw_session_count; + unsigned long max_pin_len; + unsigned long min_pin_len; + unsigned long total_public_memory; + unsigned long free_public_memory; + unsigned long total_private_memory; + unsigned long free_private_memory; + struct ck_version hardware_version; + struct ck_version firmware_version; + unsigned char utc_time[16]; +}; + + +#define CKF_RNG (1 << 0) +#define CKF_WRITE_PROTECTED (1 << 1) +#define CKF_LOGIN_REQUIRED (1 << 2) +#define CKF_USER_PIN_INITIALIZED (1 << 3) +#define CKF_RESTORE_KEY_NOT_NEEDED (1 << 5) +#define CKF_CLOCK_ON_TOKEN (1 << 6) +#define CKF_PROTECTED_AUTHENTICATION_PATH (1 << 8) +#define CKF_DUAL_CRYPTO_OPERATIONS (1 << 9) +#define CKF_TOKEN_INITIALIZED (1 << 10) +#define CKF_SECONDARY_AUTHENTICATION (1 << 11) +#define CKF_USER_PIN_COUNT_LOW (1 << 16) +#define CKF_USER_PIN_FINAL_TRY (1 << 17) +#define CKF_USER_PIN_LOCKED (1 << 18) +#define CKF_USER_PIN_TO_BE_CHANGED (1 << 19) +#define CKF_SO_PIN_COUNT_LOW (1 << 20) +#define CKF_SO_PIN_FINAL_TRY (1 << 21) +#define CKF_SO_PIN_LOCKED (1 << 22) +#define CKF_SO_PIN_TO_BE_CHANGED (1 << 23) + +#define CK_UNAVAILABLE_INFORMATION ((unsigned long) -1) +#define CK_EFFECTIVELY_INFINITE (0) + + +typedef unsigned long ck_session_handle_t; + +#define CK_INVALID_HANDLE (0) + + +typedef unsigned long ck_user_type_t; + +#define CKU_SO (0) +#define CKU_USER (1) +#define CKU_CONTEXT_SPECIFIC (2) + + +typedef unsigned long ck_state_t; + +#define CKS_RO_PUBLIC_SESSION (0) +#define CKS_RO_USER_FUNCTIONS (1) +#define CKS_RW_PUBLIC_SESSION (2) +#define CKS_RW_USER_FUNCTIONS (3) +#define CKS_RW_SO_FUNCTIONS (4) + + +struct ck_session_info +{ + ck_slot_id_t slot_id; + ck_state_t state; + ck_flags_t flags; + unsigned long device_error; +}; + +#define CKF_RW_SESSION (1 << 1) +#define CKF_SERIAL_SESSION (1 << 2) + + +typedef unsigned long ck_object_handle_t; + + +typedef unsigned long ck_object_class_t; + +#define CKO_DATA (0) +#define CKO_CERTIFICATE (1) +#define CKO_PUBLIC_KEY (2) +#define CKO_PRIVATE_KEY (3) +#define CKO_SECRET_KEY (4) +#define CKO_HW_FEATURE (5) +#define CKO_DOMAIN_PARAMETERS (6) +#define CKO_MECHANISM (7) +#define CKO_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +typedef unsigned long ck_hw_feature_type_t; + +#define CKH_MONOTONIC_COUNTER (1) +#define CKH_CLOCK (2) +#define CKH_USER_INTERFACE (3) +#define CKH_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +typedef unsigned long ck_key_type_t; + +#define CKK_RSA (0) +#define CKK_DSA (1) +#define CKK_DH (2) +#define CKK_ECDSA (3) +#define CKK_EC (3) +#define CKK_X9_42_DH (4) +#define CKK_KEA (5) +#define CKK_GENERIC_SECRET (0x10) +#define CKK_RC2 (0x11) +#define CKK_RC4 (0x12) +#define CKK_DES (0x13) +#define CKK_DES2 (0x14) +#define CKK_DES3 (0x15) +#define CKK_CAST (0x16) +#define CKK_CAST3 (0x17) +#define CKK_CAST128 (0x18) +#define CKK_RC5 (0x19) +#define CKK_IDEA (0x1a) +#define CKK_SKIPJACK (0x1b) +#define CKK_BATON (0x1c) +#define CKK_JUNIPER (0x1d) +#define CKK_CDMF (0x1e) +#define CKK_AES (0x1f) +#define CKK_BLOWFISH (0x20) +#define CKK_TWOFISH (0x21) +#define CKK_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +typedef unsigned long ck_certificate_type_t; + +#define CKC_X_509 (0) +#define CKC_X_509_ATTR_CERT (1) +#define CKC_WTLS (2) +#define CKC_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +typedef unsigned long ck_attribute_type_t; + +#define CKA_CLASS (0) +#define CKA_TOKEN (1) +#define CKA_PRIVATE (2) +#define CKA_LABEL (3) +#define CKA_APPLICATION (0x10) +#define CKA_VALUE (0x11) +#define CKA_OBJECT_ID (0x12) +#define CKA_CERTIFICATE_TYPE (0x80) +#define CKA_ISSUER (0x81) +#define CKA_SERIAL_NUMBER (0x82) +#define CKA_AC_ISSUER (0x83) +#define CKA_OWNER (0x84) +#define CKA_ATTR_TYPES (0x85) +#define CKA_TRUSTED (0x86) +#define CKA_CERTIFICATE_CATEGORY (0x87) +#define CKA_JAVA_MIDP_SECURITY_DOMAIN (0x88) +#define CKA_URL (0x89) +#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY (0x8a) +#define CKA_HASH_OF_ISSUER_PUBLIC_KEY (0x8b) +#define CKA_CHECK_VALUE (0x90) +#define CKA_KEY_TYPE (0x100) +#define CKA_SUBJECT (0x101) +#define CKA_ID (0x102) +#define CKA_SENSITIVE (0x103) +#define CKA_ENCRYPT (0x104) +#define CKA_DECRYPT (0x105) +#define CKA_WRAP (0x106) +#define CKA_UNWRAP (0x107) +#define CKA_SIGN (0x108) +#define CKA_SIGN_RECOVER (0x109) +#define CKA_VERIFY (0x10a) +#define CKA_VERIFY_RECOVER (0x10b) +#define CKA_DERIVE (0x10c) +#define CKA_START_DATE (0x110) +#define CKA_END_DATE (0x111) +#define CKA_MODULUS (0x120) +#define CKA_MODULUS_BITS (0x121) +#define CKA_PUBLIC_EXPONENT (0x122) +#define CKA_PRIVATE_EXPONENT (0x123) +#define CKA_PRIME_1 (0x124) +#define CKA_PRIME_2 (0x125) +#define CKA_EXPONENT_1 (0x126) +#define CKA_EXPONENT_2 (0x127) +#define CKA_COEFFICIENT (0x128) +#define CKA_PRIME (0x130) +#define CKA_SUBPRIME (0x131) +#define CKA_BASE (0x132) +#define CKA_PRIME_BITS (0x133) +#define CKA_SUB_PRIME_BITS (0x134) +#define CKA_VALUE_BITS (0x160) +#define CKA_VALUE_LEN (0x161) +#define CKA_EXTRACTABLE (0x162) +#define CKA_LOCAL (0x163) +#define CKA_NEVER_EXTRACTABLE (0x164) +#define CKA_ALWAYS_SENSITIVE (0x165) +#define CKA_KEY_GEN_MECHANISM (0x166) +#define CKA_MODIFIABLE (0x170) +#define CKA_ECDSA_PARAMS (0x180) +#define CKA_EC_PARAMS (0x180) +#define CKA_EC_POINT (0x181) +#define CKA_SECONDARY_AUTH (0x200) +#define CKA_AUTH_PIN_FLAGS (0x201) +#define CKA_ALWAYS_AUTHENTICATE (0x202) +#define CKA_WRAP_WITH_TRUSTED (0x210) +#define CKA_HW_FEATURE_TYPE (0x300) +#define CKA_RESET_ON_INIT (0x301) +#define CKA_HAS_RESET (0x302) +#define CKA_PIXEL_X (0x400) +#define CKA_PIXEL_Y (0x401) +#define CKA_RESOLUTION (0x402) +#define CKA_CHAR_ROWS (0x403) +#define CKA_CHAR_COLUMNS (0x404) +#define CKA_COLOR (0x405) +#define CKA_BITS_PER_PIXEL (0x406) +#define CKA_CHAR_SETS (0x480) +#define CKA_ENCODING_METHODS (0x481) +#define CKA_MIME_TYPES (0x482) +#define CKA_MECHANISM_TYPE (0x500) +#define CKA_REQUIRED_CMS_ATTRIBUTES (0x501) +#define CKA_DEFAULT_CMS_ATTRIBUTES (0x502) +#define CKA_SUPPORTED_CMS_ATTRIBUTES (0x503) +#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x211) +#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x212) +#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600) +#define CKA_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +struct ck_attribute +{ + ck_attribute_type_t type; + void *value; + unsigned long value_len; +}; + + +struct ck_date +{ + unsigned char year[4]; + unsigned char month[2]; + unsigned char day[2]; +}; + + +typedef unsigned long ck_mechanism_type_t; + +#define CKM_RSA_PKCS_KEY_PAIR_GEN (0) +#define CKM_RSA_PKCS (1) +#define CKM_RSA_9796 (2) +#define CKM_RSA_X_509 (3) +#define CKM_MD2_RSA_PKCS (4) +#define CKM_MD5_RSA_PKCS (5) +#define CKM_SHA1_RSA_PKCS (6) +#define CKM_RIPEMD128_RSA_PKCS (7) +#define CKM_RIPEMD160_RSA_PKCS (8) +#define CKM_RSA_PKCS_OAEP (9) +#define CKM_RSA_X9_31_KEY_PAIR_GEN (0xa) +#define CKM_RSA_X9_31 (0xb) +#define CKM_SHA1_RSA_X9_31 (0xc) +#define CKM_RSA_PKCS_PSS (0xd) +#define CKM_SHA1_RSA_PKCS_PSS (0xe) +#define CKM_DSA_KEY_PAIR_GEN (0x10) +#define CKM_DSA (0x11) +#define CKM_DSA_SHA1 (0x12) +#define CKM_DH_PKCS_KEY_PAIR_GEN (0x20) +#define CKM_DH_PKCS_DERIVE (0x21) +#define CKM_X9_42_DH_KEY_PAIR_GEN (0x30) +#define CKM_X9_42_DH_DERIVE (0x31) +#define CKM_X9_42_DH_HYBRID_DERIVE (0x32) +#define CKM_X9_42_MQV_DERIVE (0x33) +#define CKM_SHA256_RSA_PKCS (0x40) +#define CKM_SHA384_RSA_PKCS (0x41) +#define CKM_SHA512_RSA_PKCS (0x42) +#define CKM_SHA256_RSA_PKCS_PSS (0x43) +#define CKM_SHA384_RSA_PKCS_PSS (0x44) +#define CKM_SHA512_RSA_PKCS_PSS (0x45) +#define CKM_RC2_KEY_GEN (0x100) +#define CKM_RC2_ECB (0x101) +#define CKM_RC2_CBC (0x102) +#define CKM_RC2_MAC (0x103) +#define CKM_RC2_MAC_GENERAL (0x104) +#define CKM_RC2_CBC_PAD (0x105) +#define CKM_RC4_KEY_GEN (0x110) +#define CKM_RC4 (0x111) +#define CKM_DES_KEY_GEN (0x120) +#define CKM_DES_ECB (0x121) +#define CKM_DES_CBC (0x122) +#define CKM_DES_MAC (0x123) +#define CKM_DES_MAC_GENERAL (0x124) +#define CKM_DES_CBC_PAD (0x125) +#define CKM_DES2_KEY_GEN (0x130) +#define CKM_DES3_KEY_GEN (0x131) +#define CKM_DES3_ECB (0x132) +#define CKM_DES3_CBC (0x133) +#define CKM_DES3_MAC (0x134) +#define CKM_DES3_MAC_GENERAL (0x135) +#define CKM_DES3_CBC_PAD (0x136) +#define CKM_CDMF_KEY_GEN (0x140) +#define CKM_CDMF_ECB (0x141) +#define CKM_CDMF_CBC (0x142) +#define CKM_CDMF_MAC (0x143) +#define CKM_CDMF_MAC_GENERAL (0x144) +#define CKM_CDMF_CBC_PAD (0x145) +#define CKM_MD2 (0x200) +#define CKM_MD2_HMAC (0x201) +#define CKM_MD2_HMAC_GENERAL (0x202) +#define CKM_MD5 (0x210) +#define CKM_MD5_HMAC (0x211) +#define CKM_MD5_HMAC_GENERAL (0x212) +#define CKM_SHA_1 (0x220) +#define CKM_SHA_1_HMAC (0x221) +#define CKM_SHA_1_HMAC_GENERAL (0x222) +#define CKM_RIPEMD128 (0x230) +#define CKM_RIPEMD128_HMAC (0x231) +#define CKM_RIPEMD128_HMAC_GENERAL (0x232) +#define CKM_RIPEMD160 (0x240) +#define CKM_RIPEMD160_HMAC (0x241) +#define CKM_RIPEMD160_HMAC_GENERAL (0x242) +#define CKM_SHA256 (0x250) +#define CKM_SHA256_HMAC (0x251) +#define CKM_SHA256_HMAC_GENERAL (0x252) +#define CKM_SHA384 (0x260) +#define CKM_SHA384_HMAC (0x261) +#define CKM_SHA384_HMAC_GENERAL (0x262) +#define CKM_SHA512 (0x270) +#define CKM_SHA512_HMAC (0x271) +#define CKM_SHA512_HMAC_GENERAL (0x272) +#define CKM_CAST_KEY_GEN (0x300) +#define CKM_CAST_ECB (0x301) +#define CKM_CAST_CBC (0x302) +#define CKM_CAST_MAC (0x303) +#define CKM_CAST_MAC_GENERAL (0x304) +#define CKM_CAST_CBC_PAD (0x305) +#define CKM_CAST3_KEY_GEN (0x310) +#define CKM_CAST3_ECB (0x311) +#define CKM_CAST3_CBC (0x312) +#define CKM_CAST3_MAC (0x313) +#define CKM_CAST3_MAC_GENERAL (0x314) +#define CKM_CAST3_CBC_PAD (0x315) +#define CKM_CAST5_KEY_GEN (0x320) +#define CKM_CAST128_KEY_GEN (0x320) +#define CKM_CAST5_ECB (0x321) +#define CKM_CAST128_ECB (0x321) +#define CKM_CAST5_CBC (0x322) +#define CKM_CAST128_CBC (0x322) +#define CKM_CAST5_MAC (0x323) +#define CKM_CAST128_MAC (0x323) +#define CKM_CAST5_MAC_GENERAL (0x324) +#define CKM_CAST128_MAC_GENERAL (0x324) +#define CKM_CAST5_CBC_PAD (0x325) +#define CKM_CAST128_CBC_PAD (0x325) +#define CKM_RC5_KEY_GEN (0x330) +#define CKM_RC5_ECB (0x331) +#define CKM_RC5_CBC (0x332) +#define CKM_RC5_MAC (0x333) +#define CKM_RC5_MAC_GENERAL (0x334) +#define CKM_RC5_CBC_PAD (0x335) +#define CKM_IDEA_KEY_GEN (0x340) +#define CKM_IDEA_ECB (0x341) +#define CKM_IDEA_CBC (0x342) +#define CKM_IDEA_MAC (0x343) +#define CKM_IDEA_MAC_GENERAL (0x344) +#define CKM_IDEA_CBC_PAD (0x345) +#define CKM_GENERIC_SECRET_KEY_GEN (0x350) +#define CKM_CONCATENATE_BASE_AND_KEY (0x360) +#define CKM_CONCATENATE_BASE_AND_DATA (0x362) +#define CKM_CONCATENATE_DATA_AND_BASE (0x363) +#define CKM_XOR_BASE_AND_DATA (0x364) +#define CKM_EXTRACT_KEY_FROM_KEY (0x365) +#define CKM_SSL3_PRE_MASTER_KEY_GEN (0x370) +#define CKM_SSL3_MASTER_KEY_DERIVE (0x371) +#define CKM_SSL3_KEY_AND_MAC_DERIVE (0x372) +#define CKM_SSL3_MASTER_KEY_DERIVE_DH (0x373) +#define CKM_TLS_PRE_MASTER_KEY_GEN (0x374) +#define CKM_TLS_MASTER_KEY_DERIVE (0x375) +#define CKM_TLS_KEY_AND_MAC_DERIVE (0x376) +#define CKM_TLS_MASTER_KEY_DERIVE_DH (0x377) +#define CKM_SSL3_MD5_MAC (0x380) +#define CKM_SSL3_SHA1_MAC (0x381) +#define CKM_MD5_KEY_DERIVATION (0x390) +#define CKM_MD2_KEY_DERIVATION (0x391) +#define CKM_SHA1_KEY_DERIVATION (0x392) +#define CKM_PBE_MD2_DES_CBC (0x3a0) +#define CKM_PBE_MD5_DES_CBC (0x3a1) +#define CKM_PBE_MD5_CAST_CBC (0x3a2) +#define CKM_PBE_MD5_CAST3_CBC (0x3a3) +#define CKM_PBE_MD5_CAST5_CBC (0x3a4) +#define CKM_PBE_MD5_CAST128_CBC (0x3a4) +#define CKM_PBE_SHA1_CAST5_CBC (0x3a5) +#define CKM_PBE_SHA1_CAST128_CBC (0x3a5) +#define CKM_PBE_SHA1_RC4_128 (0x3a6) +#define CKM_PBE_SHA1_RC4_40 (0x3a7) +#define CKM_PBE_SHA1_DES3_EDE_CBC (0x3a8) +#define CKM_PBE_SHA1_DES2_EDE_CBC (0x3a9) +#define CKM_PBE_SHA1_RC2_128_CBC (0x3aa) +#define CKM_PBE_SHA1_RC2_40_CBC (0x3ab) +#define CKM_PKCS5_PBKD2 (0x3b0) +#define CKM_PBA_SHA1_WITH_SHA1_HMAC (0x3c0) +#define CKM_KEY_WRAP_LYNKS (0x400) +#define CKM_KEY_WRAP_SET_OAEP (0x401) +#define CKM_SKIPJACK_KEY_GEN (0x1000) +#define CKM_SKIPJACK_ECB64 (0x1001) +#define CKM_SKIPJACK_CBC64 (0x1002) +#define CKM_SKIPJACK_OFB64 (0x1003) +#define CKM_SKIPJACK_CFB64 (0x1004) +#define CKM_SKIPJACK_CFB32 (0x1005) +#define CKM_SKIPJACK_CFB16 (0x1006) +#define CKM_SKIPJACK_CFB8 (0x1007) +#define CKM_SKIPJACK_WRAP (0x1008) +#define CKM_SKIPJACK_PRIVATE_WRAP (0x1009) +#define CKM_SKIPJACK_RELAYX (0x100a) +#define CKM_KEA_KEY_PAIR_GEN (0x1010) +#define CKM_KEA_KEY_DERIVE (0x1011) +#define CKM_FORTEZZA_TIMESTAMP (0x1020) +#define CKM_BATON_KEY_GEN (0x1030) +#define CKM_BATON_ECB128 (0x1031) +#define CKM_BATON_ECB96 (0x1032) +#define CKM_BATON_CBC128 (0x1033) +#define CKM_BATON_COUNTER (0x1034) +#define CKM_BATON_SHUFFLE (0x1035) +#define CKM_BATON_WRAP (0x1036) +#define CKM_ECDSA_KEY_PAIR_GEN (0x1040) +#define CKM_EC_KEY_PAIR_GEN (0x1040) +#define CKM_ECDSA (0x1041) +#define CKM_ECDSA_SHA1 (0x1042) +#define CKM_ECDH1_DERIVE (0x1050) +#define CKM_ECDH1_COFACTOR_DERIVE (0x1051) +#define CKM_ECMQV_DERIVE (0x1052) +#define CKM_JUNIPER_KEY_GEN (0x1060) +#define CKM_JUNIPER_ECB128 (0x1061) +#define CKM_JUNIPER_CBC128 (0x1062) +#define CKM_JUNIPER_COUNTER (0x1063) +#define CKM_JUNIPER_SHUFFLE (0x1064) +#define CKM_JUNIPER_WRAP (0x1065) +#define CKM_FASTHASH (0x1070) +#define CKM_AES_KEY_GEN (0x1080) +#define CKM_AES_ECB (0x1081) +#define CKM_AES_CBC (0x1082) +#define CKM_AES_MAC (0x1083) +#define CKM_AES_MAC_GENERAL (0x1084) +#define CKM_AES_CBC_PAD (0x1085) +#define CKM_DSA_PARAMETER_GEN (0x2000) +#define CKM_DH_PKCS_PARAMETER_GEN (0x2001) +#define CKM_X9_42_DH_PARAMETER_GEN (0x2002) +#define CKM_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +struct ck_mechanism +{ + ck_mechanism_type_t mechanism; + void *parameter; + unsigned long parameter_len; +}; + + +struct ck_mechanism_info +{ + unsigned long min_key_size; + unsigned long max_key_size; + ck_flags_t flags; +}; + +#define CKF_HW (1 << 0) +#define CKF_ENCRYPT (1 << 8) +#define CKF_DECRYPT (1 << 9) +#define CKF_DIGEST (1 << 10) +#define CKF_SIGN (1 << 11) +#define CKF_SIGN_RECOVER (1 << 12) +#define CKF_VERIFY (1 << 13) +#define CKF_VERIFY_RECOVER (1 << 14) +#define CKF_GENERATE (1 << 15) +#define CKF_GENERATE_KEY_PAIR (1 << 16) +#define CKF_WRAP (1 << 17) +#define CKF_UNWRAP (1 << 18) +#define CKF_DERIVE (1 << 19) +#define CKF_EXTENSION ((unsigned long) (1 << 31)) + + +/* Flags for C_WaitForSlotEvent. */ +#define CKF_DONT_BLOCK (1) + + +typedef unsigned long ck_rv_t; + + +typedef ck_rv_t (*ck_notify_t) (ck_session_handle_t session, + ck_notification_t event, void *application); + +/* Forward reference. */ +struct ck_function_list; + +#define _CK_DECLARE_FUNCTION(name, args) \ +typedef ck_rv_t (*CK_ ## name) args; \ +ck_rv_t CK_SPEC name args + +_CK_DECLARE_FUNCTION (C_Initialize, (void *init_args)); +_CK_DECLARE_FUNCTION (C_Finalize, (void *reserved)); +_CK_DECLARE_FUNCTION (C_GetInfo, (struct ck_info *info)); +_CK_DECLARE_FUNCTION (C_GetFunctionList, + (struct ck_function_list **function_list)); + +_CK_DECLARE_FUNCTION (C_GetSlotList, + (unsigned char token_present, ck_slot_id_t *slot_list, + unsigned long *count)); +_CK_DECLARE_FUNCTION (C_GetSlotInfo, + (ck_slot_id_t slot_id, struct ck_slot_info *info)); +_CK_DECLARE_FUNCTION (C_GetTokenInfo, + (ck_slot_id_t slot_id, struct ck_token_info *info)); +_CK_DECLARE_FUNCTION (C_WaitForSlotEvent, + (ck_flags_t flags, ck_slot_id_t *slot, void *reserved)); +_CK_DECLARE_FUNCTION (C_GetMechanismList, + (ck_slot_id_t slot_id, + ck_mechanism_type_t *mechanism_list, + unsigned long *count)); +_CK_DECLARE_FUNCTION (C_GetMechanismInfo, + (ck_slot_id_t slot_id, ck_mechanism_type_t type, + struct ck_mechanism_info *info)); +_CK_DECLARE_FUNCTION (C_InitToken, + (ck_slot_id_t slot_id, unsigned char *pin, + unsigned long pin_len, unsigned char *label)); +_CK_DECLARE_FUNCTION (C_InitPIN, + (ck_session_handle_t session, unsigned char *pin, + unsigned long pin_len)); +_CK_DECLARE_FUNCTION (C_SetPIN, + (ck_session_handle_t session, unsigned char *old_pin, + unsigned long old_len, unsigned char *new_pin, + unsigned long new_len)); + +_CK_DECLARE_FUNCTION (C_OpenSession, + (ck_slot_id_t slot_id, ck_flags_t flags, + void *application, ck_notify_t notify, + ck_session_handle_t *session)); +_CK_DECLARE_FUNCTION (C_CloseSession, (ck_session_handle_t session)); +_CK_DECLARE_FUNCTION (C_CloseAllSessions, (ck_slot_id_t slot_id)); +_CK_DECLARE_FUNCTION (C_GetSessionInfo, + (ck_session_handle_t session, + struct ck_session_info *info)); +_CK_DECLARE_FUNCTION (C_GetOperationState, + (ck_session_handle_t session, + unsigned char *operation_state, + unsigned long *operation_state_len)); +_CK_DECLARE_FUNCTION (C_SetOperationState, + (ck_session_handle_t session, + unsigned char *operation_state, + unsigned long operation_state_len, + ck_object_handle_t encryption_key, + ck_object_handle_t authentiation_key)); +_CK_DECLARE_FUNCTION (C_Login, + (ck_session_handle_t session, ck_user_type_t user_type, + unsigned char *pin, unsigned long pin_len)); +_CK_DECLARE_FUNCTION (C_Logout, (ck_session_handle_t session)); + +_CK_DECLARE_FUNCTION (C_CreateObject, + (ck_session_handle_t session, + struct ck_attribute *templ, + unsigned long count, ck_object_handle_t *object)); +_CK_DECLARE_FUNCTION (C_CopyObject, + (ck_session_handle_t session, ck_object_handle_t object, + struct ck_attribute *templ, unsigned long count, + ck_object_handle_t *new_object)); +_CK_DECLARE_FUNCTION (C_DestroyObject, + (ck_session_handle_t session, + ck_object_handle_t object)); +_CK_DECLARE_FUNCTION (C_GetObjectSize, + (ck_session_handle_t session, + ck_object_handle_t object, + unsigned long *size)); +_CK_DECLARE_FUNCTION (C_GetAttributeValue, + (ck_session_handle_t session, + ck_object_handle_t object, + struct ck_attribute *templ, + unsigned long count)); +_CK_DECLARE_FUNCTION (C_SetAttributeValue, + (ck_session_handle_t session, + ck_object_handle_t object, + struct ck_attribute *templ, + unsigned long count)); +_CK_DECLARE_FUNCTION (C_FindObjectsInit, + (ck_session_handle_t session, + struct ck_attribute *templ, + unsigned long count)); +_CK_DECLARE_FUNCTION (C_FindObjects, + (ck_session_handle_t session, + ck_object_handle_t *object, + unsigned long max_object_count, + unsigned long *object_count)); +_CK_DECLARE_FUNCTION (C_FindObjectsFinal, + (ck_session_handle_t session)); + +_CK_DECLARE_FUNCTION (C_EncryptInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Encrypt, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *encrypted_data, + unsigned long *encrypted_data_len)); +_CK_DECLARE_FUNCTION (C_EncryptUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len, + unsigned char *encrypted_part, + unsigned long *encrypted_part_len)); +_CK_DECLARE_FUNCTION (C_EncryptFinal, + (ck_session_handle_t session, + unsigned char *last_encrypted_part, + unsigned long *last_encrypted_part_len)); + +_CK_DECLARE_FUNCTION (C_DecryptInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Decrypt, + (ck_session_handle_t session, + unsigned char *encrypted_data, + unsigned long encrypted_data_len, + unsigned char *data, unsigned long *data_len)); +_CK_DECLARE_FUNCTION (C_DecryptUpdate, + (ck_session_handle_t session, + unsigned char *encrypted_part, + unsigned long encrypted_part_len, + unsigned char *part, unsigned long *part_len)); +_CK_DECLARE_FUNCTION (C_DecryptFinal, + (ck_session_handle_t session, + unsigned char *last_part, + unsigned long *last_part_len)); + +_CK_DECLARE_FUNCTION (C_DigestInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism)); +_CK_DECLARE_FUNCTION (C_Digest, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *digest, + unsigned long *digest_len)); +_CK_DECLARE_FUNCTION (C_DigestUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len)); +_CK_DECLARE_FUNCTION (C_DigestKey, + (ck_session_handle_t session, ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_DigestFinal, + (ck_session_handle_t session, + unsigned char *digest, + unsigned long *digest_len)); + +_CK_DECLARE_FUNCTION (C_SignInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Sign, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *signature, + unsigned long *signature_len)); +_CK_DECLARE_FUNCTION (C_SignUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len)); +_CK_DECLARE_FUNCTION (C_SignFinal, + (ck_session_handle_t session, + unsigned char *signature, + unsigned long *signature_len)); +_CK_DECLARE_FUNCTION (C_SignRecoverInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_SignRecover, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *signature, + unsigned long *signature_len)); + +_CK_DECLARE_FUNCTION (C_VerifyInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Verify, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *signature, + unsigned long signature_len)); +_CK_DECLARE_FUNCTION (C_VerifyUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len)); +_CK_DECLARE_FUNCTION (C_VerifyFinal, + (ck_session_handle_t session, + unsigned char *signature, + unsigned long signature_len)); +_CK_DECLARE_FUNCTION (C_VerifyRecoverInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_VerifyRecover, + (ck_session_handle_t session, + unsigned char *signature, + unsigned long signature_len, + unsigned char *data, + unsigned long *data_len)); + +_CK_DECLARE_FUNCTION (C_DigestEncryptUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len, + unsigned char *encrypted_part, + unsigned long *encrypted_part_len)); +_CK_DECLARE_FUNCTION (C_DecryptDigestUpdate, + (ck_session_handle_t session, + unsigned char *encrypted_part, + unsigned long encrypted_part_len, + unsigned char *part, + unsigned long *part_len)); +_CK_DECLARE_FUNCTION (C_SignEncryptUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len, + unsigned char *encrypted_part, + unsigned long *encrypted_part_len)); +_CK_DECLARE_FUNCTION (C_DecryptVerifyUpdate, + (ck_session_handle_t session, + unsigned char *encrypted_part, + unsigned long encrypted_part_len, + unsigned char *part, + unsigned long *part_len)); + +_CK_DECLARE_FUNCTION (C_GenerateKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + struct ck_attribute *templ, + unsigned long count, + ck_object_handle_t *key)); +_CK_DECLARE_FUNCTION (C_GenerateKeyPair, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + struct ck_attribute *public_key_template, + unsigned long public_key_attribute_count, + struct ck_attribute *private_key_template, + unsigned long private_key_attribute_count, + ck_object_handle_t *public_key, + ck_object_handle_t *private_key)); +_CK_DECLARE_FUNCTION (C_WrapKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t wrapping_key, + ck_object_handle_t key, + unsigned char *wrapped_key, + unsigned long *wrapped_key_len)); +_CK_DECLARE_FUNCTION (C_UnwrapKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t unwrapping_key, + unsigned char *wrapped_key, + unsigned long wrapped_key_len, + struct ck_attribute *templ, + unsigned long attribute_count, + ck_object_handle_t *key)); +_CK_DECLARE_FUNCTION (C_DeriveKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t base_key, + struct ck_attribute *templ, + unsigned long attribute_count, + ck_object_handle_t *key)); + +_CK_DECLARE_FUNCTION (C_SeedRandom, + (ck_session_handle_t session, unsigned char *seed, + unsigned long seed_len)); +_CK_DECLARE_FUNCTION (C_GenerateRandom, + (ck_session_handle_t session, + unsigned char *random_data, + unsigned long random_len)); + +_CK_DECLARE_FUNCTION (C_GetFunctionStatus, (ck_session_handle_t session)); +_CK_DECLARE_FUNCTION (C_CancelFunction, (ck_session_handle_t session)); + + +struct ck_function_list +{ + struct ck_version version; + CK_C_Initialize C_Initialize; + CK_C_Finalize C_Finalize; + CK_C_GetInfo C_GetInfo; + CK_C_GetFunctionList C_GetFunctionList; + CK_C_GetSlotList C_GetSlotList; + CK_C_GetSlotInfo C_GetSlotInfo; + CK_C_GetTokenInfo C_GetTokenInfo; + CK_C_GetMechanismList C_GetMechanismList; + CK_C_GetMechanismInfo C_GetMechanismInfo; + CK_C_InitToken C_InitToken; + CK_C_InitPIN C_InitPIN; + CK_C_SetPIN C_SetPIN; + CK_C_OpenSession C_OpenSession; + CK_C_CloseSession C_CloseSession; + CK_C_CloseAllSessions C_CloseAllSessions; + CK_C_GetSessionInfo C_GetSessionInfo; + CK_C_GetOperationState C_GetOperationState; + CK_C_SetOperationState C_SetOperationState; + CK_C_Login C_Login; + CK_C_Logout C_Logout; + CK_C_CreateObject C_CreateObject; + CK_C_CopyObject C_CopyObject; + CK_C_DestroyObject C_DestroyObject; + CK_C_GetObjectSize C_GetObjectSize; + CK_C_GetAttributeValue C_GetAttributeValue; + CK_C_SetAttributeValue C_SetAttributeValue; + CK_C_FindObjectsInit C_FindObjectsInit; + CK_C_FindObjects C_FindObjects; + CK_C_FindObjectsFinal C_FindObjectsFinal; + CK_C_EncryptInit C_EncryptInit; + CK_C_Encrypt C_Encrypt; + CK_C_EncryptUpdate C_EncryptUpdate; + CK_C_EncryptFinal C_EncryptFinal; + CK_C_DecryptInit C_DecryptInit; + CK_C_Decrypt C_Decrypt; + CK_C_DecryptUpdate C_DecryptUpdate; + CK_C_DecryptFinal C_DecryptFinal; + CK_C_DigestInit C_DigestInit; + CK_C_Digest C_Digest; + CK_C_DigestUpdate C_DigestUpdate; + CK_C_DigestKey C_DigestKey; + CK_C_DigestFinal C_DigestFinal; + CK_C_SignInit C_SignInit; + CK_C_Sign C_Sign; + CK_C_SignUpdate C_SignUpdate; + CK_C_SignFinal C_SignFinal; + CK_C_SignRecoverInit C_SignRecoverInit; + CK_C_SignRecover C_SignRecover; + CK_C_VerifyInit C_VerifyInit; + CK_C_Verify C_Verify; + CK_C_VerifyUpdate C_VerifyUpdate; + CK_C_VerifyFinal C_VerifyFinal; + CK_C_VerifyRecoverInit C_VerifyRecoverInit; + CK_C_VerifyRecover C_VerifyRecover; + CK_C_DigestEncryptUpdate C_DigestEncryptUpdate; + CK_C_DecryptDigestUpdate C_DecryptDigestUpdate; + CK_C_SignEncryptUpdate C_SignEncryptUpdate; + CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate; + CK_C_GenerateKey C_GenerateKey; + CK_C_GenerateKeyPair C_GenerateKeyPair; + CK_C_WrapKey C_WrapKey; + CK_C_UnwrapKey C_UnwrapKey; + CK_C_DeriveKey C_DeriveKey; + CK_C_SeedRandom C_SeedRandom; + CK_C_GenerateRandom C_GenerateRandom; + CK_C_GetFunctionStatus C_GetFunctionStatus; + CK_C_CancelFunction C_CancelFunction; + CK_C_WaitForSlotEvent C_WaitForSlotEvent; +}; + + +typedef ck_rv_t (*ck_createmutex_t) (void **mutex); +typedef ck_rv_t (*ck_destroymutex_t) (void *mutex); +typedef ck_rv_t (*ck_lockmutex_t) (void *mutex); +typedef ck_rv_t (*ck_unlockmutex_t) (void *mutex); + + +struct ck_c_initialize_args +{ + ck_createmutex_t create_mutex; + ck_destroymutex_t destroy_mutex; + ck_lockmutex_t lock_mutex; + ck_unlockmutex_t unlock_mutex; + ck_flags_t flags; + void *reserved; +}; + + +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1 << 0) +#define CKF_OS_LOCKING_OK (1 << 1) + +#define CKR_OK (0) +#define CKR_CANCEL (1) +#define CKR_HOST_MEMORY (2) +#define CKR_SLOT_ID_INVALID (3) +#define CKR_GENERAL_ERROR (5) +#define CKR_FUNCTION_FAILED (6) +#define CKR_ARGUMENTS_BAD (7) +#define CKR_NO_EVENT (8) +#define CKR_NEED_TO_CREATE_THREADS (9) +#define CKR_CANT_LOCK (0xa) +#define CKR_ATTRIBUTE_READ_ONLY (0x10) +#define CKR_ATTRIBUTE_SENSITIVE (0x11) +#define CKR_ATTRIBUTE_TYPE_INVALID (0x12) +#define CKR_ATTRIBUTE_VALUE_INVALID (0x13) +#define CKR_DATA_INVALID (0x20) +#define CKR_DATA_LEN_RANGE (0x21) +#define CKR_DEVICE_ERROR (0x30) +#define CKR_DEVICE_MEMORY (0x31) +#define CKR_DEVICE_REMOVED (0x32) +#define CKR_ENCRYPTED_DATA_INVALID (0x40) +#define CKR_ENCRYPTED_DATA_LEN_RANGE (0x41) +#define CKR_FUNCTION_CANCELED (0x50) +#define CKR_FUNCTION_NOT_PARALLEL (0x51) +#define CKR_FUNCTION_NOT_SUPPORTED (0x54) +#define CKR_KEY_HANDLE_INVALID (0x60) +#define CKR_KEY_SIZE_RANGE (0x62) +#define CKR_KEY_TYPE_INCONSISTENT (0x63) +#define CKR_KEY_NOT_NEEDED (0x64) +#define CKR_KEY_CHANGED (0x65) +#define CKR_KEY_NEEDED (0x66) +#define CKR_KEY_INDIGESTIBLE (0x67) +#define CKR_KEY_FUNCTION_NOT_PERMITTED (0x68) +#define CKR_KEY_NOT_WRAPPABLE (0x69) +#define CKR_KEY_UNEXTRACTABLE (0x6a) +#define CKR_MECHANISM_INVALID (0x70) +#define CKR_MECHANISM_PARAM_INVALID (0x71) +#define CKR_OBJECT_HANDLE_INVALID (0x82) +#define CKR_OPERATION_ACTIVE (0x90) +#define CKR_OPERATION_NOT_INITIALIZED (0x91) +#define CKR_PIN_INCORRECT (0xa0) +#define CKR_PIN_INVALID (0xa1) +#define CKR_PIN_LEN_RANGE (0xa2) +#define CKR_PIN_EXPIRED (0xa3) +#define CKR_PIN_LOCKED (0xa4) +#define CKR_SESSION_CLOSED (0xb0) +#define CKR_SESSION_COUNT (0xb1) +#define CKR_SESSION_HANDLE_INVALID (0xb3) +#define CKR_SESSION_PARALLEL_NOT_SUPPORTED (0xb4) +#define CKR_SESSION_READ_ONLY (0xb5) +#define CKR_SESSION_EXISTS (0xb6) +#define CKR_SESSION_READ_ONLY_EXISTS (0xb7) +#define CKR_SESSION_READ_WRITE_SO_EXISTS (0xb8) +#define CKR_SIGNATURE_INVALID (0xc0) +#define CKR_SIGNATURE_LEN_RANGE (0xc1) +#define CKR_TEMPLATE_INCOMPLETE (0xd0) +#define CKR_TEMPLATE_INCONSISTENT (0xd1) +#define CKR_TOKEN_NOT_PRESENT (0xe0) +#define CKR_TOKEN_NOT_RECOGNIZED (0xe1) +#define CKR_TOKEN_WRITE_PROTECTED (0xe2) +#define CKR_UNWRAPPING_KEY_HANDLE_INVALID (0xf0) +#define CKR_UNWRAPPING_KEY_SIZE_RANGE (0xf1) +#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT (0xf2) +#define CKR_USER_ALREADY_LOGGED_IN (0x100) +#define CKR_USER_NOT_LOGGED_IN (0x101) +#define CKR_USER_PIN_NOT_INITIALIZED (0x102) +#define CKR_USER_TYPE_INVALID (0x103) +#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN (0x104) +#define CKR_USER_TOO_MANY_TYPES (0x105) +#define CKR_WRAPPED_KEY_INVALID (0x110) +#define CKR_WRAPPED_KEY_LEN_RANGE (0x112) +#define CKR_WRAPPING_KEY_HANDLE_INVALID (0x113) +#define CKR_WRAPPING_KEY_SIZE_RANGE (0x114) +#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT (0x115) +#define CKR_RANDOM_SEED_NOT_SUPPORTED (0x120) +#define CKR_RANDOM_NO_RNG (0x121) +#define CKR_DOMAIN_PARAMS_INVALID (0x130) +#define CKR_BUFFER_TOO_SMALL (0x150) +#define CKR_SAVED_STATE_INVALID (0x160) +#define CKR_INFORMATION_SENSITIVE (0x170) +#define CKR_STATE_UNSAVEABLE (0x180) +#define CKR_CRYPTOKI_NOT_INITIALIZED (0x190) +#define CKR_CRYPTOKI_ALREADY_INITIALIZED (0x191) +#define CKR_MUTEX_BAD (0x1a0) +#define CKR_MUTEX_NOT_LOCKED (0x1a1) +#define CKR_FUNCTION_REJECTED (0x200) +#define CKR_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + + +/* Compatibility layer. */ + +#ifdef CRYPTOKI_COMPAT + +#undef CK_DEFINE_FUNCTION +#define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name + +/* For NULL. */ +#include + +typedef unsigned char CK_BYTE; +typedef unsigned char CK_CHAR; +typedef unsigned char CK_UTF8CHAR; +typedef unsigned char CK_BBOOL; +typedef unsigned long int CK_ULONG; +typedef long int CK_LONG; +typedef CK_BYTE *CK_BYTE_PTR; +typedef CK_CHAR *CK_CHAR_PTR; +typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR; +typedef CK_ULONG *CK_ULONG_PTR; +typedef void *CK_VOID_PTR; +typedef void **CK_VOID_PTR_PTR; +#define CK_FALSE 0 +#define CK_TRUE 1 +#ifndef CK_DISABLE_TRUE_FALSE +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#endif + +typedef struct ck_version CK_VERSION; +typedef struct ck_version *CK_VERSION_PTR; + +typedef struct ck_info CK_INFO; +typedef struct ck_info *CK_INFO_PTR; + +typedef ck_slot_id_t *CK_SLOT_ID_PTR; + +typedef struct ck_slot_info CK_SLOT_INFO; +typedef struct ck_slot_info *CK_SLOT_INFO_PTR; + +typedef struct ck_token_info CK_TOKEN_INFO; +typedef struct ck_token_info *CK_TOKEN_INFO_PTR; + +typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR; + +typedef struct ck_session_info CK_SESSION_INFO; +typedef struct ck_session_info *CK_SESSION_INFO_PTR; + +typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR; + +typedef ck_object_class_t *CK_OBJECT_CLASS_PTR; + +typedef struct ck_attribute CK_ATTRIBUTE; +typedef struct ck_attribute *CK_ATTRIBUTE_PTR; + +typedef struct ck_date CK_DATE; +typedef struct ck_date *CK_DATE_PTR; + +typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR; + +typedef struct ck_mechanism CK_MECHANISM; +typedef struct ck_mechanism *CK_MECHANISM_PTR; + +typedef struct ck_mechanism_info CK_MECHANISM_INFO; +typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR; + +typedef struct ck_function_list CK_FUNCTION_LIST; +typedef struct ck_function_list *CK_FUNCTION_LIST_PTR; +typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR; + +typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS; +typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; + +#define NULL_PTR NULL + +/* Delete the helper macros defined at the top of the file. */ +#undef ck_flags_t +#undef ck_version + +#undef ck_info +#undef cryptoki_version +#undef manufacturer_id +#undef library_description +#undef library_version + +#undef ck_notification_t +#undef ck_slot_id_t + +#undef ck_slot_info +#undef slot_description +#undef hardware_version +#undef firmware_version + +#undef ck_token_info +#undef serial_number +#undef max_session_count +#undef session_count +#undef max_rw_session_count +#undef rw_session_count +#undef max_pin_len +#undef min_pin_len +#undef total_public_memory +#undef free_public_memory +#undef total_private_memory +#undef free_private_memory +#undef utc_time + +#undef ck_session_handle_t +#undef ck_user_type_t +#undef ck_state_t + +#undef ck_session_info +#undef slot_id +#undef device_error + +#undef ck_object_handle_t +#undef ck_object_class_t +#undef ck_hw_feature_type_t +#undef ck_key_type_t +#undef ck_certificate_type_t +#undef ck_attribute_type_t + +#undef ck_attribute +#undef value +#undef value_len + +#undef ck_date + +#undef ck_mechanism_type_t + +#undef ck_mechanism +#undef parameter +#undef parameter_len + +#undef ck_mechanism_info +#undef min_key_size +#undef max_key_size + +#undef ck_rv_t +#undef ck_notify_t + +#undef ck_function_list + +#undef ck_createmutex_t +#undef ck_destroymutex_t +#undef ck_lockmutex_t +#undef ck_unlockmutex_t + +#undef ck_c_initialize_args +#undef create_mutex +#undef destroy_mutex +#undef lock_mutex +#undef unlock_mutex +#undef reserved + +#endif /* CRYPTOKI_COMPAT */ + + +/* System dependencies. */ +#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) +#pragma pack(pop, cryptoki) +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* PKCS11_H */ diff --git a/module/pkcs11/pkcs11n.h b/module/pkcs11/pkcs11n.h new file mode 100644 index 0000000..d611d75 --- /dev/null +++ b/module/pkcs11/pkcs11n.h @@ -0,0 +1,221 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Dr Stephen Henson + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _PKCS11N_H_ +#define _PKCS11N_H_ + +#ifdef DEBUG +static const char CKT_CVS_ID[] = "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.15 $ $Date: 2005/09/28 17:12:17 $"; +#endif /* DEBUG */ + +/* + * pkcs11n.h + * + * This file contains the NSS-specific type definitions for Cryptoki + * (PKCS#11). + */ + +/* + * NSSCK_VENDOR_NETSCAPE + * + * Cryptoki reserves the high half of all the number spaces for + * vendor-defined use. I'd like to keep all of our Netscape- + * specific values together, but not in the oh-so-obvious + * 0x80000001, 0x80000002, etc. area. So I've picked an offset, + * and constructed values for the beginnings of our spaces. + * + * Note that some "historical" Netscape values don't fall within + * this range. + */ +#define NSSCK_VENDOR_NETSCAPE 0x4E534350 /* NSCP */ + +/* + * Netscape-defined object classes + * + */ +#define CKO_NETSCAPE (CKO_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) + +#define CKO_NETSCAPE_CRL (CKO_NETSCAPE + 1) +#define CKO_NETSCAPE_SMIME (CKO_NETSCAPE + 2) +#define CKO_NETSCAPE_TRUST (CKO_NETSCAPE + 3) +#define CKO_NETSCAPE_BUILTIN_ROOT_LIST (CKO_NETSCAPE + 4) +#define CKO_NETSCAPE_NEWSLOT (CKO_NETSCAPE + 5) +#define CKO_NETSCAPE_DELSLOT (CKO_NETSCAPE + 6) + +/* + * Netscape-defined key types + * + */ +#define CKK_NETSCAPE (CKK_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) + +#define CKK_NETSCAPE_PKCS8 (CKK_NETSCAPE + 1) +/* + * Netscape-defined certificate types + * + */ +#define CKC_NETSCAPE (CKC_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) + +/* + * Netscape-defined object attributes + * + */ +#define CKA_NETSCAPE (CKA_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) + +#define CKA_NETSCAPE_URL (CKA_NETSCAPE + 1) +#define CKA_NETSCAPE_EMAIL (CKA_NETSCAPE + 2) +#define CKA_NETSCAPE_SMIME_INFO (CKA_NETSCAPE + 3) +#define CKA_NETSCAPE_SMIME_TIMESTAMP (CKA_NETSCAPE + 4) +#define CKA_NETSCAPE_PKCS8_SALT (CKA_NETSCAPE + 5) +#define CKA_NETSCAPE_PASSWORD_CHECK (CKA_NETSCAPE + 6) +#define CKA_NETSCAPE_EXPIRES (CKA_NETSCAPE + 7) +#define CKA_NETSCAPE_KRL (CKA_NETSCAPE + 8) + +#define CKA_NETSCAPE_PQG_COUNTER (CKA_NETSCAPE + 20) +#define CKA_NETSCAPE_PQG_SEED (CKA_NETSCAPE + 21) +#define CKA_NETSCAPE_PQG_H (CKA_NETSCAPE + 22) +#define CKA_NETSCAPE_PQG_SEED_BITS (CKA_NETSCAPE + 23) +#define CKA_NETSCAPE_MODULE_SPEC (CKA_NETSCAPE + 24) + +/* + * Trust attributes: + * + * If trust goes standard, these probably will too. So I'll + * put them all in one place. + */ + +#define CKA_TRUST (CKA_NETSCAPE + 0x2000) + +/* "Usage" key information */ +#define CKA_TRUST_DIGITAL_SIGNATURE (CKA_TRUST + 1) +#define CKA_TRUST_NON_REPUDIATION (CKA_TRUST + 2) +#define CKA_TRUST_KEY_ENCIPHERMENT (CKA_TRUST + 3) +#define CKA_TRUST_DATA_ENCIPHERMENT (CKA_TRUST + 4) +#define CKA_TRUST_KEY_AGREEMENT (CKA_TRUST + 5) +#define CKA_TRUST_KEY_CERT_SIGN (CKA_TRUST + 6) +#define CKA_TRUST_CRL_SIGN (CKA_TRUST + 7) + +/* "Purpose" trust information */ +#define CKA_TRUST_SERVER_AUTH (CKA_TRUST + 8) +#define CKA_TRUST_CLIENT_AUTH (CKA_TRUST + 9) +#define CKA_TRUST_CODE_SIGNING (CKA_TRUST + 10) +#define CKA_TRUST_EMAIL_PROTECTION (CKA_TRUST + 11) +#define CKA_TRUST_IPSEC_END_SYSTEM (CKA_TRUST + 12) +#define CKA_TRUST_IPSEC_TUNNEL (CKA_TRUST + 13) +#define CKA_TRUST_IPSEC_USER (CKA_TRUST + 14) +#define CKA_TRUST_TIME_STAMPING (CKA_TRUST + 15) +#define CKA_TRUST_STEP_UP_APPROVED (CKA_TRUST + 16) + +#define CKA_CERT_SHA1_HASH (CKA_TRUST + 100) +#define CKA_CERT_MD5_HASH (CKA_TRUST + 101) + +/* Netscape trust stuff */ +/* XXX fgmr new ones here-- step-up, etc. */ + +/* HISTORICAL: define used to pass in the database key for DSA private keys */ +#define CKA_NETSCAPE_DB 0xD5A0DB00L +#define CKA_NETSCAPE_TRUST 0x80000001L + +/* + * Netscape-defined crypto mechanisms + * + */ +#define CKM_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) + +#define CKM_NETSCAPE_AES_KEY_WRAP (CKM_NETSCAPE + 1) +#define CKM_NETSCAPE_AES_KEY_WRAP_PAD (CKM_NETSCAPE + 2) + +/* + * HISTORICAL: + * Do not attempt to use these. They are only used by NETSCAPE's internal + * PKCS #11 interface. Most of these are place holders for other mechanism + * and will change in the future. + */ +#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002L +#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003L +#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004L +#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005L +#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006L +#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007L +#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008L +#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009L +#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aL +#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bL + +#define CKM_TLS_PRF_GENERAL 0x80000373L + +/* + * Netscape-defined return values + * + */ +#define CKR_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) + +#define CKR_NETSCAPE_CERTDB_FAILED (CKR_NETSCAPE + 1) +#define CKR_NETSCAPE_KEYDB_FAILED (CKR_NETSCAPE + 2) + +/* + * Trust info + * + * This isn't part of the Cryptoki standard (yet), so I'm putting + * all the definitions here. Some of this would move to nssckt.h + * if trust info were made part of the standard. In view of this + * possibility, I'm putting my (Netscape) values in the netscape + * vendor space, like everything else. + */ + +typedef CK_ULONG CK_TRUST; + +/* The following trust types are defined: */ +#define CKT_VENDOR_DEFINED 0x80000000 + +#define CKT_NETSCAPE (CKT_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) + +/* If trust goes standard, these'll probably drop out of vendor space. */ +#define CKT_NETSCAPE_TRUSTED (CKT_NETSCAPE + 1) +#define CKT_NETSCAPE_TRUSTED_DELEGATOR (CKT_NETSCAPE + 2) +#define CKT_NETSCAPE_UNTRUSTED (CKT_NETSCAPE + 3) +#define CKT_NETSCAPE_MUST_VERIFY (CKT_NETSCAPE + 4) +#define CKT_NETSCAPE_TRUST_UNKNOWN (CKT_NETSCAPE + 5) /* default */ + +/* + * These may well remain Netscape-specific; I'm only using them + * to cache resolution data. + */ +#define CKT_NETSCAPE_VALID (CKT_NETSCAPE + 10) +#define CKT_NETSCAPE_VALID_DELEGATOR (CKT_NETSCAPE + 11) + + +#endif /* _PKCS11N_H_ */ diff --git a/module/x509-usages.h b/module/x509-usages.h new file mode 100644 index 0000000..e06309b --- /dev/null +++ b/module/x509-usages.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007 Nate Nielsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _X509_USAGES_H_ +#define _X509_USAGES_H_ + + +#define X509_USAGE_SERVER_AUTH "1.3.6.1.5.5.7.3.1" +#define X509_USAGE_CLIENT_AUTH "1.3.6.1.5.5.7.3.2" +#define X509_USAGE_CODE_SIGNING "1.3.6.1.5.5.7.3.3" +#define X509_USAGE_EMAIL "1.3.6.1.5.5.7.3.4" +#define X509_USAGE_TIME_STAMPING "1.3.6.1.5.5.7.3.8" +#define X509_USAGE_IPSEC_ENDPOINT "1.3.6.1.5.5.7.3.5" +#define X509_USAGE_IPSEC_TUNNEL "1.3.6.1.5.5.7.3.6" +#define X509_USAGE_IPSEC_USER "1.3.6.1.5.5.7.3.7" +#define X509_USAGE_IKE_INTERMEDIATE "1.3.6.1.5.5.8.2.2" + + +#define MS_USAGE_TRUST_LIST_SIGNING "1.3.6.1.4.1.311.10.3.1" +#define MS_USAGE_TIME_STAMPING "1.3.6.1.4.1.311.10.3.2" +#define MS_USAGE_EFS "1.3.6.1.4.1.311.10.3.4" +#define MS_USAGE_DRIVER_VERIFICATION "1.3.6.1.4.1.311.10.3.5" +#define MS_USAGE_SYSTEM_VERIFICATION "1.3.6.1.4.1.311.10.3.6" +#define MS_USAGE_OEM_VERIFICATION "1.3.6.1.4.1.311.10.3.7" +#define MS_USAGE_EMBEDDED_VERIFICATION "1.3.6.1.4.1.311.10.3.8" +#define MS_USAGE_KEY_PACK "1.3.6.1.4.1.311.10.6.1" +#define MS_USAGE_LICENSE_SERVER "1.3.6.1.4.1.311.10.6.2" +#define MS_USAGE_SMART_CARD "1.3.6.1.4.1.311.20.2.2" +#define MS_USAGE_DIGITAL_RIGHTS "1.3.6.1.4.1.311.10.5.1" +#define MS_USAGE_QUALIFIED_SUBORDINATION "1.3.6.1.4.1.311.10.3.10" +#define MS_USAGE_KEY_RECOVERY "1.3.6.1.4.1.311.10.3.11" +#define MS_USAGE_DOCUMENT_SIGNING "1.3.6.1.4.1.311.10.3.12" +#define MS_USAGE_FILE_RECOVERY "1.3.6.1.4.1.311.10.3.4.1" +#define MS_USAGE_ROOT_SIGNER_LIST "1.3.6.1.4.1.311.10.3.9" +#define MS_USAGE_APPLICATION_POLICIES "1.3.6.1.4.1.311.10.12.1" +#define MS_USAGE_AD_EMAIL_REPLICATION "1.3.6.1.4.1.311.21.19" +#define MS_USAGE_CERTIFICATE_REQUEST_AGENT "1.3.6.1.4.1.311.20.2.1" +#define MS_USAGE_KEY_RECOVERY_AGENT "1.3.6.1.4.1.311.21.6" +#define MS_USAGE_CA_ENCRYPTION_CERTIFICATE "1.3.6.1.4.1.311.21.5" +#define MS_USAGE_LIFETIME_SIGNING "1.3.6.1.4.1.311.10.3.13" + +#endif /* _X509_USAGES_H_ */ diff --git a/p11-capi-builtin.c b/p11-capi-builtin.c deleted file mode 100644 index 95fd476..0000000 --- a/p11-capi-builtin.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "p11-capi.h" -#include "p11-capi-object.h" -#include "p11-capi-session.h" -#include "p11-capi-token.h" - -#include "pkcs11/pkcs11n.h" - -/* -------------------------------------------------------------------------- - * BUILT IN VALUES - */ - -static const CK_BBOOL ck_true = CK_TRUE; -static const CK_BBOOL ck_false = CK_FALSE; - -static const CK_OBJECT_CLASS cko_netscape_builtin_root_list = CKO_NETSCAPE_BUILTIN_ROOT_LIST; - -static const char ck_root_label[] = "Windows Certificate Roots"; - -/* -------------------------------------------------------------------------- - * BUILT IN OBJECTS - */ - -#define CK_END_LIST (CK_ULONG)-1 - -static const CK_ATTRIBUTE builtin_root[] = { - { CKA_TOKEN, (void*)&ck_true, sizeof(CK_BBOOL) }, - { CKA_CLASS, (void*)&cko_netscape_builtin_root_list, sizeof(CK_OBJECT_CLASS) }, - { CKA_PRIVATE, (void*)&ck_false, sizeof(CK_BBOOL) }, - { CKA_MODIFIABLE, (void*)&ck_false, sizeof(CK_BBOOL) }, - { CKA_LABEL, (void*)ck_root_label, sizeof(ck_root_label) }, - { CK_END_LIST, NULL, 0 } -}; - -typedef struct _BuiltinMatch -{ - CK_ATTRIBUTE_PTR attr; - CK_ULONG slot_flags; -} -BuiltinMatch; - -static const BuiltinMatch all_builtins[] = { - { (CK_ATTRIBUTE_PTR)&builtin_root, P11C_SLOT_TRUSTED | P11C_SLOT_CA | P11C_SLOT_CERTS }, - { NULL, 0 } -}; - -/* This is filled in later */ -static CK_ULONG num_builtins = 0; - -/* -------------------------------------------------------------------------- - * IMPLEMENTATION - */ - -/* Represents a loaded builtin object */ -typedef struct _BuiltinObject -{ - P11cObject obj; - CK_ATTRIBUTE_PTR attr; -} -BuiltinObject; - -typedef struct _BuiltinObjectData -{ - P11cObjectData base; - CK_ATTRIBUTE_PTR attr; -} -BuiltinObjectData; - -static CK_RV -builtin_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) -{ - BuiltinObjectData* bdata = (BuiltinObjectData*)objdata; - CK_ATTRIBUTE_PTR builtin = bdata->attr; - - ASSERT(attr); - ASSERT(bdata); - - while(builtin->type != CK_END_LIST) - { - if(builtin->type == attr->type) - { - if(builtin->ulValueLen == 0) - return CKR_ATTRIBUTE_TYPE_INVALID; - return p11c_return_data(attr, builtin->pValue, builtin->ulValueLen); - } - - builtin++; - } - - return CKR_ATTRIBUTE_TYPE_INVALID; -} - -static void -builtin_data_release(void* data) -{ - BuiltinObjectData* bdata = (BuiltinObjectData*)data; - ASSERT(bdata); - free(bdata); -} - -static const P11cObjectDataVtable builtin_objdata_vtable = { - builtin_attribute, - builtin_attribute, - builtin_attribute, - builtin_data_release, -}; - -static CK_RV -builtin_load_data(P11cSession* sess, P11cObject* obj, P11cObjectData** objdata) -{ - BuiltinObject* bobj = (BuiltinObject*)obj; - BuiltinObjectData* bdata; - - ASSERT(bobj); - ASSERT(objdata); - ASSERT(num_builtins > 0); - - bdata = (BuiltinObjectData*)calloc(1, sizeof(BuiltinObjectData)); - if(!bdata) - return CKR_HOST_MEMORY; - - /* Simple, just use same data */ - bdata->attr = bobj->attr; - - bdata->base.object = obj->id; - bdata->base.data_funcs = &builtin_objdata_vtable; - - *objdata = &(bdata->base); - return CKR_OK; -} - -static unsigned int -builtin_hash_func(P11cObject* obj) -{ - return p11c_hash_pointer(((BuiltinObject*)obj)->attr); -} - -static int -builtin_equal_func(P11cObject* one, P11cObject* two) -{ - return ((BuiltinObject*)one)->attr == ((BuiltinObject*)two)->attr; -} - -static void -builtin_object_release(void* data) -{ - BuiltinObject* bobj = (BuiltinObject*)data; - ASSERT(bobj); - free(bobj); -} - -static const P11cObjectVtable builtin_object_vtable = { - builtin_load_data, - builtin_hash_func, - builtin_equal_func, - builtin_object_release, -}; - -static CK_RV -register_builtin_object(P11cSession* sess, CK_ATTRIBUTE_PTR attr, P11cObject** obj) -{ - BuiltinObject* bobj; - CK_RV ret; - - bobj = calloc(1, sizeof(BuiltinObject)); - if(!bobj) - return CKR_HOST_MEMORY; - - bobj->attr = attr; - - bobj->obj.id = 0; - bobj->obj.obj_funcs = &builtin_object_vtable; - - ret = p11c_token_register_object(sess->slot, &(bobj->obj)); - if(ret != CKR_OK) - { - free(bobj); - return ret; - } - - ASSERT(bobj->obj.id != 0); - *obj = &(bobj->obj); - return CKR_OK; -} - -CK_RV -p11c_builtin_find(P11cSession* sess, CK_OBJECT_CLASS cls, CK_ATTRIBUTE_PTR match, - CK_ULONG count, P11cArray* arr) -{ - P11cObject* obj; - BuiltinObjectData bdata; - CK_RV ret = CKR_OK; - CK_ULONG i, fl; - - /* First time around count total number */ - if(!num_builtins) - { - while(all_builtins[num_builtins].attr) - ++num_builtins; - ASSERT(num_builtins > 0); - } - - /* Match each certificate */ - for(i = 0; i < num_builtins; ++i) - { - /* Only apply built in objects to appropriate slots */ - fl = p11c_token_get_flags(sess->slot) & all_builtins[i].slot_flags; - if(fl != all_builtins[i].slot_flags) - continue; - - bdata.attr = all_builtins[i].attr; - bdata.base.object = 0; - bdata.base.data_funcs = &builtin_objdata_vtable; - - if(p11c_object_data_match(&bdata.base, match, count)) - { - ret = register_builtin_object(sess, all_builtins[i].attr, &obj); - if(ret != CKR_OK) - break; - - p11c_array_append(arr, obj->id); - } - } - - return ret; -} - diff --git a/p11-capi-builtin.h b/p11-capi-builtin.h deleted file mode 100644 index b398509..0000000 --- a/p11-capi-builtin.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef P11C_BUILTIN_H -#define P11C_BUILTIN_H - -#include "p11-capi.h" - -/* Find builtin objects matching criteria */ -CK_RV p11c_builtin_find (P11cSession* sess, CK_OBJECT_CLASS cls, - CK_ATTRIBUTE_PTR match, CK_ULONG count, - P11cArray* arr); - -#endif /* P11C_BUILTIN_H */ diff --git a/p11-capi-cert.c b/p11-capi-cert.c deleted file mode 100644 index 53e198f..0000000 --- a/p11-capi-cert.c +++ /dev/null @@ -1,775 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "p11-capi.h" -#include "p11-capi-cert.h" -#include "p11-capi-object.h" -#include "p11-capi-session.h" -#include "p11-capi-token.h" - -#include - -#ifndef CERT_FIND_KEY_IDENTIFIER -#define CERT_FIND_KEY_IDENTIFIER 983040 -#endif - -#ifndef CERT_KEY_IDENTIFIER_PROP_ID -#define CERT_KEY_IDENTIFIER_PROP_ID 20 -#endif - -typedef struct _CertObject -{ - P11cObject obj; - - /* Together these can uniquely identify a certificate */ - CRYPT_INTEGER_BLOB serial; - CERT_NAME_BLOB issuer; -} -CertObject; - -typedef struct _CertObjectData -{ - P11cObjectData base; - PCCERT_CONTEXT cert; - BOOL is_in_root; -} -CertObjectData; - -static CK_RV -parse_basic_constraints(CertObjectData* cdata, CK_ULONG* category) -{ - CERT_BASIC_CONSTRAINTS_INFO* basic; - CERT_EXTENSION* ext; - DWORD size; - BYTE bits; - CK_RV ret; - - ASSERT(cdata); - ASSERT(cdata->cert); - - *category = 0; - - ext = CertFindExtension(szOID_BASIC_CONSTRAINTS, - cdata->cert->pCertInfo->cExtension, - cdata->cert->pCertInfo->rgExtension); - - /* No key usage, don't care */ - if(!ext) - return CKR_OK; - - /* Find the size of the decoded structure */ - if(!CryptDecodeObject(P11c_ENCODINGS, X509_BASIC_CONSTRAINTS, - ext->Value.pbData, ext->Value.cbData, 0, NULL, &size)) - return p11c_winerr_to_ckr(GetLastError()); - - /* Allocate enough memory */ - basic = (CERT_BASIC_CONSTRAINTS_INFO*)calloc(1, size); - if(!basic) - return CKR_HOST_MEMORY; - - /* And get the decoded structure */ - if(CryptDecodeObject(P11c_ENCODINGS, X509_BASIC_CONSTRAINTS, - ext->Value.pbData, ext->Value.cbData, 0, basic, &size)) - { - if(basic->SubjectType.cbData != 1) - { - DBG(("basic constraints bits are of invalid size")); - ret = CKR_GENERAL_ERROR; - } - else - { - /* All of the above was for 2 bits. Lovely */ - bits = basic->SubjectType.pbData[0] & ~(0xff >> (8 - basic->SubjectType.cUnusedBits)); - if((bits & CERT_CA_SUBJECT_FLAG) == CERT_CA_SUBJECT_FLAG) - *category = 2; - else if((bits & CERT_END_ENTITY_SUBJECT_FLAG) == CERT_END_ENTITY_SUBJECT_FLAG) - *category = 3; - else - *category = 0; - ret = CKR_OK; - } - } - else - { - ret = p11c_winerr_to_ckr(GetLastError()); - } - - free(basic); - - return ret; -} - - -static CK_RV -cert_bool_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) -{ - CertObjectData* cdata = (CertObjectData*)objdata; - CK_BBOOL val; - - ASSERT(cdata); - - switch(attr->type) - { - /* - * Resides on the token - * - Always true for CAPI objects. - */ - case CKA_TOKEN: - val = CK_TRUE; - break; - - /* - * Private vs. Public object. - * - Always false for certificates. - */ - case CKA_PRIVATE: - val = CK_FALSE; - break; - - /* - * If object can be modified. - * - Currently always false. In the future with additional - * functionality this may change. - */ - case CKA_MODIFIABLE: - val = CK_FALSE; - break; - - /* - * Whether the certificate can be trusted for the application - * in which it was created. - * - We just report on whether the certificate is a trusted root. - */ - case CKA_TRUSTED: - val = cdata->is_in_root ? CK_TRUE : CK_FALSE; - break; - - default: - return CKR_ATTRIBUTE_TYPE_INVALID; - }; - - return p11c_return_data(attr, &val, sizeof(CK_BBOOL)); -} - -static CK_RV -cert_ulong_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) -{ - CertObjectData* cdata = (CertObjectData*)objdata; - CK_ULONG val; - CK_RV ret; - - ASSERT(objdata); - - switch(attr->type) - { - - /* - * Object class. - * - Always CKO_CERTIFICATE for certificates. - */ - case CKA_CLASS: - val = CKO_CERTIFICATE; - break; - - /* - * Type of certificate. - * - Always X509. - */ - case CKA_CERTIFICATE_TYPE: - val = CKC_X_509; - break; - - /* - * Whether a CA, user certificate, other. - * - Get certificate szOID_ENHANCED_KEY_USAGE - * extension or CERT_CTL_PROP_ID and look into CTL_USAGE structure. - */ - case CKA_CERTIFICATE_CATEGORY: - ret = parse_basic_constraints(cdata, &val); - if(ret != CKR_OK) - return ret; - break; - - /* - * Java MIDP security domain. - * - Have no idea what this is. Spec says default to zero. - */ - case CKA_JAVA_MIDP_SECURITY_DOMAIN: - val = 0; - break; - - default: - return CKR_ATTRIBUTE_TYPE_INVALID; - }; - - return p11c_return_data(attr, &val, sizeof(CK_ULONG)); -} - -static CK_RV -cert_bytes_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) -{ - CertObjectData* cdata = (CertObjectData*)objdata; - PCCERT_CONTEXT cert = cdata->cert; - - ASSERT(sizeof(CK_ULONG) == sizeof(DWORD)); - ASSERT(cdata); - - return p11c_cert_certificate_get_bytes(cdata->cert, attr); -} - -static void -cert_data_release(void* data) -{ - CertObjectData* cdata = (CertObjectData*)data; - ASSERT(cdata && cdata->cert); - CertFreeCertificateContext(cdata->cert); - free(cdata); -} - -static const P11cObjectDataVtable cert_objdata_vtable = { - cert_bool_attribute, - cert_ulong_attribute, - cert_bytes_attribute, - cert_data_release, -}; - -static P11cObjectData* -cert_alloc_data(P11cSession* sess, P11cObject* obj, PCCERT_CONTEXT cert) -{ - CertObjectData* cdata; - - cdata = (CertObjectData*)calloc(1, sizeof(CertObjectData)); - if(!cdata) - return NULL; - - cdata->cert = cert; - cdata->is_in_root = (p11c_token_get_flags(sess->slot) & P11C_SLOT_CA) ? TRUE : FALSE; - - cdata->base.object = obj->id; - cdata->base.data_funcs = &cert_objdata_vtable; - - return &(cdata->base); -} - -static CK_RV -cert_load_data(P11cSession* sess, P11cObject* obj, P11cObjectData** objdata) -{ - CertObject* cobj = (CertObject*)obj; - CERT_INFO info; - PCCERT_CONTEXT cert; - - ASSERT(cobj); - ASSERT(objdata); - - ASSERT(cobj->issuer.pbData); - ASSERT(cobj->issuer.cbData); - ASSERT(cobj->serial.pbData); - ASSERT(cobj->serial.cbData); - - /* No store should mean no objects were loaded */ - ASSERT(sess->store); - - /* Setup our search */ - memset(&info, 0, sizeof(info)); - memcpy(&info.SerialNumber, &cobj->serial, sizeof(info.SerialNumber)); - memcpy(&info.Issuer, &cobj->issuer, sizeof(info.Issuer)); - - cert = CertGetSubjectCertificateFromStore(sess->store, P11c_ENCODINGS, &info); - - if(!cert) - { - DWORD err = GetLastError(); - - /* TODO: Is this right for a deleted certificate? */ - ASSERT(err != E_INVALIDARG); - if(err == CRYPT_E_NOT_FOUND) - return CKR_OBJECT_HANDLE_INVALID; - else - return p11c_winerr_to_ckr(GetLastError()); - } - - *objdata = cert_alloc_data(sess, obj, cert); - if(!(*objdata)) - { - CertFreeCertificateContext(cert); - return CKR_HOST_MEMORY; - } - - return CKR_OK; -} - -static unsigned int -cert_hash_func(P11cObject* obj) -{ - CertObject* cobj = (CertObject*)obj; - return p11c_hash_data(cobj->issuer.pbData, cobj->issuer.cbData) ^ - p11c_hash_data(cobj->serial.pbData, cobj->serial.cbData); -} - -static int -cert_equal_func(P11cObject* a, P11cObject* b) -{ - CertObject* ca = (CertObject*)a; - CertObject* cb = (CertObject*)b; - return ca->issuer.cbData == cb->issuer.cbData && - memcmp(ca->issuer.pbData, cb->issuer.pbData, ca->issuer.cbData) == 0 && - ca->serial.cbData == cb->serial.cbData && - memcmp(ca->serial.pbData, cb->serial.pbData, ca->serial.cbData) == 0; -} - -static void -cert_object_release(void* data) -{ - CertObject* cobj = (CertObject*)data; - ASSERT(cobj); - free(cobj); -} - -static const P11cObjectVtable cert_object_vtable = { - cert_load_data, - cert_hash_func, - cert_equal_func, - cert_object_release, -}; - -static CK_RV -calculate_check_value(PCCERT_CONTEXT cert, CK_ATTRIBUTE_PTR attr) -{ - BYTE* buffer; - DWORD length; - CK_RV ret; - - ASSERT(cert); - ASSERT(attr); - - /* Short cut for the measuring case */ - if(!attr->pValue) - { - attr->ulValueLen = 3; - return CKR_OK; - } - - length = 0; - if(!CryptHashCertificate(0, CALG_SHA1, 0, cert->pbCertEncoded, - cert->cbCertEncoded, NULL, &length)) - return p11c_winerr_to_ckr(GetLastError()); - - if(length < 3) - { - DBG(("SHA1 hash length too short: %d", length)); - return CKR_DEVICE_ERROR; - } - - buffer = malloc(length); - if(!buffer) - return CKR_HOST_MEMORY; - - if(!CryptHashCertificate(0, CALG_SHA1, 0, cert->pbCertEncoded, - cert->cbCertEncoded, buffer, &length)) - { - free(buffer); - return p11c_winerr_to_ckr(GetLastError()); - } - - ret = p11c_return_data(attr, buffer, 3); - free(buffer); - return ret; -} - - -CK_RV -p11c_cert_certificate_get_bytes(PCCERT_CONTEXT cert, CK_ATTRIBUTE_PTR attr) -{ - DWORD err; - - ASSERT(cert); - ASSERT(attr); - - switch(attr->type) - { - - /* - * Description of the object. - * - We use CAPI's CERT_FRIENDLY_NAME_PROP_ID property, - * converted into UTF8. - * - Yes this is slow, but this is not really a property - * that's searched on or retrieved intensively. - */ - case CKA_LABEL: - { - WCHAR* utf16 = NULL; - DWORD size; - - if(!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &size)) - { - err = GetLastError(); - if(err == CRYPT_E_NOT_FOUND) - utf16 = L"Unnamed Certificate"; - else - return p11c_winerr_to_ckr(err); - } - - if(!utf16) - { - utf16 = _alloca(size); - if(!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, utf16, &size)) - return p11c_winerr_to_ckr(GetLastError()); - } - - return p11c_return_string(attr, utf16); - } - break; - - /* - * A byte array unique to this certificate. The CKA_ID of - * matching certificates and private keys should match. - * Should match the key identifier in an X.509v3 certificate. - * - * We use CAPI's CERT_KEY_IDENTIFIER_PROP_ID property directly. - */ - case CKA_ID: - if(!CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, - attr->pValue, (DWORD*)&attr->ulValueLen)) - { - err = GetLastError(); - if(err == CRYPT_E_NOT_FOUND) - return CKR_ATTRIBUTE_TYPE_INVALID; - return p11c_winerr_to_ckr(err); - } - return CKR_OK; - - - /* - * DER-encoding of the certificate subject name. - * - * We use CAPI's CERT_CONTEXT pCertInfo->Subject field - * directly. - */ - case CKA_SUBJECT: - return p11c_return_data(attr, cert->pCertInfo->Subject.pbData, - cert->pCertInfo->Subject.cbData); - - /* - * DER-encoding of the certificate issuer name. - * - * We use CAPI's CERT_CONTEXT pCertInfo->Issuer field - * directly. - */ - case CKA_ISSUER: - return p11c_return_data(attr, cert->pCertInfo->Issuer.pbData, - cert->pCertInfo->Issuer.cbData); - - /* - * DER-encoding of the certificate serial number. - */ - case CKA_SERIAL_NUMBER: - if(!CryptEncodeObject(X509_ASN_ENCODING, X509_MULTI_BYTE_INTEGER, - &cert->pCertInfo->SerialNumber, - attr->pValue, (DWORD*)&attr->ulValueLen)) - { - err = GetLastError(); - if(err == ERROR_FILE_NOT_FOUND) - return CKR_GENERAL_ERROR; - return p11c_winerr_to_ckr(err); - } - return CKR_OK; - - /* - * BER-encoding of the full certificate. - * - * We use CAPI's CERT_CONTEXT pbCertEncoded field directly. - */ - case CKA_VALUE: - return p11c_return_data(attr, cert->pbCertEncoded, - cert->cbCertEncoded); - - /* - * If CKA_VALUE not specified, this is where the full - * certificate can be found. - * - * We don't support this. All our certificates are present - * in full. - * - * - Spec says default to empty. - */ - case CKA_URL: - return p11c_return_data(attr, "", 0); - - /* - * Checksum - * - This is the first 3 bytes of the SHA hash of the DER. - */ - case CKA_CHECK_VALUE: - return calculate_check_value(cert, attr); - - /* - * Various hashes for remote retrieval. - * - Spec says default to empty. - */ - case CKA_HASH_OF_SUBJECT_PUBLIC_KEY: - case CKA_HASH_OF_ISSUER_PUBLIC_KEY: - return p11c_return_data(attr, "", 0); - - /* - * Start date for the certificate. - */ - case CKA_START_DATE: - return p11c_return_filetime(attr, &cert->pCertInfo->NotBefore); - - /* - * End date for the certificate. - */ - case CKA_END_DATE: - return p11c_return_filetime(attr, &cert->pCertInfo->NotAfter); - - default: - return CKR_ATTRIBUTE_TYPE_INVALID; - }; -} - -PCCERT_CONTEXT -p11c_cert_object_data_get_certificate(P11cObjectData* objdata) -{ - CertObjectData* cdata; - - ASSERT(objdata); - ASSERT(objdata->data_funcs == &cert_objdata_vtable); - - cdata = (CertObjectData*)objdata; - return cdata->cert; -} - -static CK_RV -register_cert_object(P11cSession* sess, PCCERT_CONTEXT cert, P11cObject** obj) -{ - CertObject* cobj; - CK_RV ret; - size_t len; - - /* We save the Issuer and SerialNumber for identification later */ - len = cert->pCertInfo->SerialNumber.cbData + - cert->pCertInfo->Issuer.cbData; - - cobj = calloc(1, sizeof(CertObject) + len); - if(!cobj) - return CKR_HOST_MEMORY; - - cobj->obj.id = 0; - cobj->obj.obj_funcs = &cert_object_vtable; - - /* Copy Issuer data in */ - cobj->issuer.cbData = cert->pCertInfo->Issuer.cbData; - cobj->issuer.pbData = (BYTE*)(cobj + 1); - memcpy(cobj->issuer.pbData, cert->pCertInfo->Issuer.pbData, - cobj->issuer.cbData); - - /* Copy Serial Number data in */ - cobj->serial.cbData = cert->pCertInfo->SerialNumber.cbData; - cobj->serial.pbData = cobj->issuer.pbData + cobj->issuer.cbData; - memcpy(cobj->serial.pbData, cert->pCertInfo->SerialNumber.pbData, - cobj->serial.cbData); - - ret = p11c_token_register_object(sess->slot, &(cobj->obj)); - if(ret != CKR_OK) - { - free(cobj); - return ret; - } - - ASSERT(cobj->obj.id != 0); - *obj = &cobj->obj; - return CKR_OK; -} - -static CK_RV -find_in_store(P11cSession* sess, DWORD find_type, const void *find_criteria, - CK_ATTRIBUTE_PTR match, CK_ULONG count, P11cArray* arr) -{ - PCCERT_CONTEXT cert = NULL; - P11cObject* obj; - P11cObjectData* objdata; - CertObjectData cdata; - DWORD err; - CK_RV ret = CKR_OK; - - /* No store, no objects */ - if(!sess->store) - return CKR_OK; - - for(;;) - { - cert = CertFindCertificateInStore(sess->store, P11c_ENCODINGS, 0, - find_type, find_criteria, cert); - if(cert == NULL) - { - err = GetLastError(); - - /* Certificate not found, we don't care */ - if(err == CRYPT_E_NOT_FOUND) - return CKR_OK; - else - return p11c_winerr_to_ckr(err); - } - - /* Match the certificate */ - cdata.cert = cert; - cdata.base.object = 0; - cdata.base.data_funcs = &cert_objdata_vtable; - - if(p11c_object_data_match(&cdata.base, match, count)) - { - ret = register_cert_object(sess, cert, &obj); - if(ret == CKR_OK) - { - ASSERT(obj); - - /* Store away the object data for performance reasons */ - objdata = cert_alloc_data(sess, obj, cert); - if(objdata) - { - p11c_session_take_object_data(sess, obj, objdata); - - /* For continuing the enumeration */ - cert = CertDuplicateCertificateContext(cert); - } - - p11c_array_append(arr, obj->id); - } - } - } - - if(ret != CKR_OK && cert) - CertFreeCertificateContext(cert); - - return ret; -} - -CK_RV -p11c_cert_find(P11cSession* sess, CK_OBJECT_CLASS cls, CK_ATTRIBUTE_PTR match, - CK_ULONG count, P11cArray* arr) -{ - CRYPT_INTEGER_BLOB* serial = NULL; - CK_RV ret; - CK_ULONG i; - DWORD size; - - CERT_INFO find_info; /* For searching by issuer and serial */ - CRYPT_HASH_BLOB find_key; /* For searching by ID */ - - /* We only have certificates here */ - if(cls != CKO_CERTIFICATE && cls != CKO_ANY) - return CKR_OK; - - /* Only work with slots that have certificates */ - if(!(p11c_token_get_flags (sess->slot) & P11C_SLOT_CERTS)) - return CKR_OK; - - /* - * There are some better searches we can do rather than - * listing everything. - * - * CKA_ISSUER + CKA_SERIAL_NUMBER - * See if we have a issuer and serial number for a - * specific certificate to find. - * - * CKA_ID - * Search by key identifier - * - * TODO: could search by hash (use CertFindCertificateInStore - * with CERT_FIND_HASH or CERT_FIND_SHA1_HASH or CERT_FIND_MD5_HASH) - * - * TODO: could search by issuer (use CertFindCertificateInStore - * with CERT_FIND_ISSUER_NAME) - * - * TODO: could search by subject (use CertFindCertificateInStore - * with CERT_FIND_SUBJECT_NAME) - * - * TODO: could search by CKA_VALUE (use CertFindCertificateInStore - * with CERT_FIND_EXISTING) - */ - memset(&find_info, 0, sizeof(find_info)); - memset(&find_key, 0, sizeof(find_key)); - - for(i = 0; i < count; ++i) - { - if(!match[i].pValue || !match[i].ulValueLen) - continue; - - if(match[i].type == CKA_ISSUER) - { - find_info.Issuer.cbData = match[i].ulValueLen; - find_info.Issuer.pbData = match[i].pValue; - } - - else if(match[i].type == CKA_SERIAL_NUMBER && !serial) - { - if(!CryptDecodeObject(P11c_ENCODINGS, X509_MULTI_BYTE_INTEGER, - match[i].pValue, match[i].ulValueLen, 0, NULL, &size)) - { - continue; - } - - serial = calloc(1, size); - if(!serial) - continue; - - if(!CryptDecodeObject(P11c_ENCODINGS, X509_MULTI_BYTE_INTEGER, - match[i].pValue, match[i].ulValueLen, 0, serial, &size)) - continue; - - ASSERT(serial->cbData); - ASSERT(serial->pbData); - - find_info.SerialNumber.cbData = serial->cbData; - find_info.SerialNumber.pbData = serial->pbData; - } - - else if(match[i].type == CKA_ID) - { - find_key.cbData = match[i].ulValueLen; - find_key.pbData = match[i].pValue; - } - } - - /* Match a specific certificate */ - if(find_info.SerialNumber.cbData && find_info.Issuer.cbData) - { - ret = find_in_store(sess, CERT_FIND_SUBJECT_CERT, &find_info, - match, count, arr); - } - - /* Find all certificates with key identifier */ - else if(find_key.cbData) - { - ret = find_in_store(sess, CERT_FIND_KEY_IDENTIFIER, &find_key, - match, count, arr); - } - - /* Match any ol certificate */ - else - { - ret = find_in_store(sess, CERT_FIND_ANY, NULL, - match, count, arr); - } - - if(serial) - free(serial); - - return ret; -} diff --git a/p11-capi-cert.h b/p11-capi-cert.h deleted file mode 100644 index f85d7b3..0000000 --- a/p11-capi-cert.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef P11C_CERT_H -#define P11C_CERT_H - -#include "p11-capi.h" -#include "p11-capi-util.h" - -/* Find certificates matching criteria */ -CK_RV p11c_cert_find (P11cSession* sess, CK_OBJECT_CLASS cls, - CK_ATTRIBUTE_PTR match, CK_ULONG count, - P11cArray* arr); - -/* Called by trust and key stuff */ -CK_RV p11c_cert_certificate_get_bytes (PCCERT_CONTEXT cert, - CK_ATTRIBUTE_PTR attr); - -PCCERT_CONTEXT p11c_cert_object_data_get_certificate (P11cObjectData* objdata); - -#endif /* P11C_CERT_H */ diff --git a/p11-capi-der.c b/p11-capi-der.c deleted file mode 100644 index 5698dff..0000000 --- a/p11-capi-der.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Portions derived from NSS source files: - * lib/ckfw/capi/cobject.c - * lib/ckfw/capi/crsa.c - * - * Portions of this file: - * Copyright (C) Stef Walter 2008 - * - */ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * Portions created by Red Hat, Inc, are Copyright (C) 2005 - * - * Contributor(s): - * Bob Relyea (rrelyea@redhat.com) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "p11-capi.h" -#include "p11-capi-der.h" - -/* - * unwrap a single DER value - */ -BYTE* -p11c_der_unwrap(BYTE* src, DWORD n_src, - DWORD* n_result, BYTE** next) -{ - BYTE* start = src; - BYTE* end = src + n_src; - DWORD len = 0; - - /* initialize error condition return values */ - *n_result = 0; - if(next) - *next = src; - - if(n_src < 2) - return start; - - src++ ; /* skip the tag -- should check it against an expected value! */ - len = (DWORD)*src++; - if(len & 0x80) - { - DWORD count = len & 0x7f; - len = 0; - - if(count + 2 > n_src) - return start; - - while(count-- > 0) - len = (len << 8) | (DWORD)*src++; - } - - if(len + (src - start) > (DWORD)n_src) - return start; - - if(next) - *next = src + len; - - *n_result = len; - return src; -} - -/* - * write a Decimal value to a string - */ - -static char* -put_decimal_string(char* cstr, DWORD value) -{ - DWORD tenpower; - BOOL first = TRUE; - - for(tenpower = 10000000; tenpower; tenpower /= 10) - { - BYTE digit = (BYTE)(value / tenpower); - value = value % tenpower; - - /* drop leading zeros */ - if(first && (0 == digit)) - continue; - - first = FALSE; - *cstr++ = digit + '0'; - } - - /* if value was zero, put one of them out */ - if(first) - *cstr++ = '0'; - - return cstr; -} - -/* - * Create a Capi OID string value from a DER OID - */ -char* -p11c_der_read_oid(BYTE* oid_tag, DWORD n_oid_tag) -{ - BYTE* oid; - char *oid_str; - char *cstr; - DWORD value; - DWORD n_oid; - - /* wasn't an oid */ - if(P11C_DER_OBJECT_ID != *oid_tag) - return NULL; - - oid = p11c_der_unwrap(oid_tag, n_oid_tag, &n_oid, NULL);; - if(n_oid < 2) - return NULL; - - oid_str = malloc(n_oid * 4); - if(!oid_str) - return NULL; - - cstr = oid_str; - cstr = put_decimal_string(cstr, (*oid) / 40); - *cstr++ = '.'; - cstr = put_decimal_string(cstr, (*oid) % 40); - n_oid--; - - value = 0; - while(n_oid--) - { - oid++; - value = (value << 7) + (*oid & 0x7f); - if(0 == (*oid & 0x80)) - { - *cstr++ = '.'; - cstr = put_decimal_string(cstr, value); - value = 0; - } - } - - *cstr = 0; /* NULL terminate */ - - if(value != 0) - { - free(oid_str); - return NULL; - } - - return oid_str; -} diff --git a/p11-capi-der.h b/p11-capi-der.h deleted file mode 100644 index 0807fcd..0000000 --- a/p11-capi-der.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2008 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef P11C_DER_H -#define P11C_DER_H - -#include "p11-capi.h" - -#define P11C_DER_OCTET_STRING 0x04 -#define P11C_DER_OBJECT_ID 0x06 -#define P11C_DER_SEQUENCE 0x10 -#define P11C_DER_CONSTRUCTED 0x20 - -BYTE* p11c_der_unwrap (BYTE* src, DWORD n_src, - DWORD* n_result, BYTE** next); - -char* p11c_der_read_oid (BYTE* oid_tag, DWORD n_oid_tag); - -#endif /* P11C_DER_H */ diff --git a/p11-capi-key.c b/p11-capi-key.c deleted file mode 100644 index ed306d4..0000000 --- a/p11-capi-key.c +++ /dev/null @@ -1,1083 +0,0 @@ -/* - * Copyright (C) 2008 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "p11-capi.h" -#include "p11-capi-cert.h" -#include "p11-capi-key.h" -#include "p11-capi-object.h" -#include "p11-capi-session.h" -#include "p11-capi-token.h" -#include "x509-usages.h" - -typedef struct _KeyObject -{ - P11cObject obj; - - /* The raw key identifier */ - CRYPT_HASH_BLOB key_identifier; - CK_OBJECT_CLASS object_class; -} -KeyObject; - -typedef struct _KeyObjectData -{ - P11cObjectData base; - CK_OBJECT_CLASS object_class; - CRYPT_INTEGER_BLOB key_identifier; - CRYPT_DATA_BLOB raw_public_key; - CRYPT_KEY_PROV_INFO* prov_info; -} -KeyObjectData; - -static CK_RV -load_key_handle(P11cObjectData* objdata, HCRYPTPROV* ret_prov, - HCRYPTKEY* ret_key) -{ - KeyObjectData* kdata = (KeyObjectData*)objdata; - HCRYPTPROV prov; - HCRYPTKEY key; - DWORD error; - - ASSERT(kdata); - ASSERT(ret_key); - ASSERT(ret_prov); - - if(!CryptAcquireContextW(&prov, kdata->prov_info->pwszContainerName, - kdata->prov_info->pwszProvName, - kdata->prov_info->dwProvType, 0)) - { - return p11c_winerr_to_ckr(GetLastError()); - } - - if(!CryptGetUserKey(prov, kdata->prov_info->dwKeySpec, &key)) - { - error = GetLastError(); - CryptReleaseContext(prov, 0); - return p11c_winerr_to_ckr(error); - } - - *ret_key = key; - *ret_prov = prov; - - return CKR_OK; -} - - -static CK_RV -load_raw_public_key(KeyObjectData* kdata) -{ - BOOL success = FALSE; - HCRYPTPROV prov; - HCRYPTKEY key; - CK_RV ret; - DWORD error; - - ASSERT(kdata); - ASSERT(!kdata->raw_public_key.pbData); - - ret = load_key_handle(&kdata->base, &prov, &key); - if(ret != CKR_OK) - return ret; - - if(CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &kdata->raw_public_key.cbData)) - { - kdata->raw_public_key.pbData = malloc(kdata->raw_public_key.cbData); - if(!kdata->raw_public_key.pbData) - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - else - { - if(CryptExportKey(key, 0, PUBLICKEYBLOB, 0, kdata->raw_public_key.pbData, - &kdata->raw_public_key.cbData)) - { - success = TRUE; - } - } - } - - CryptReleaseContext(prov, 0); - CryptDestroyKey(key); - - if(success) - { - return CKR_OK; - } - else - { - error = GetLastError(); - if(error == NTE_BAD_KEY_STATE) - return CKR_ATTRIBUTE_SENSITIVE; - return p11c_winerr_to_ckr(error); - } -} - -static CK_RV -lookup_rsa_attribute(KeyObjectData* kdata, CK_ATTRIBUTE_PTR attr) -{ - PUBLICKEYSTRUC* header; - RSAPUBKEY* pubkey; - CK_ULONG number; - CK_RV ret; - - ASSERT(kdata); - ASSERT(attr); - - if(!kdata->raw_public_key.pbData) - { - ret = load_raw_public_key(kdata); - if(ret != CKR_OK) - return ret; - } - - header = (PUBLICKEYSTRUC*)kdata->raw_public_key.pbData; - if(!header->bType == PUBLICKEYBLOB) - return CKR_GENERAL_ERROR; - - pubkey = (RSAPUBKEY*)(header + 1); - if(!pubkey->magic == 0x31415352) - return CKR_GENERAL_ERROR; - - switch(attr->type) - { - case CKA_MODULUS_BITS: - number = pubkey->bitlen; - return p11c_return_data(attr, &number, sizeof(CK_ULONG)); - - case CKA_PUBLIC_EXPONENT: - return p11c_return_dword_as_bytes(attr, pubkey->pubexp); - - case CKA_MODULUS: - return p11c_return_reversed_data(attr, (pubkey + 1), - pubkey->bitlen / 8); - - case CKA_PRIVATE_EXPONENT: - case CKA_PRIME_1: - case CKA_PRIME_2: - case CKA_EXPONENT_1: - case CKA_EXPONENT_2: - case CKA_COEFFICIENT: - if(kdata->object_class == CKO_PRIVATE_KEY) - return CKR_ATTRIBUTE_SENSITIVE; - else - return CKR_ATTRIBUTE_TYPE_INVALID; - - default: - ASSERT(FALSE); - return CKR_ATTRIBUTE_TYPE_INVALID; - } -} - -static CK_RV -key_bool_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) -{ - KeyObjectData* kdata = (KeyObjectData*)objdata; - CK_BBOOL val; - CK_BBOOL is_private, is_rsa; - - ASSERT(objdata); - ASSERT(attr); - - is_private = (kdata->object_class == CKO_PRIVATE_KEY); - is_rsa = kdata->prov_info->dwProvType == PROV_RSA_FULL; - - switch(attr->type) - { - - /* - * Whether to authenticate before every use. - * - CAPI does all authentication - */ - case CKA_ALWAYS_AUTHENTICATE: - val = CK_FALSE; - break; - - /* - * Whether this key has always been sensitive. - * TODO: Can we detect this? - */ - case CKA_ALWAYS_SENSITIVE: - val = CK_FALSE; - break; - - /* - * Whether this key can be used to decrypt. - * - CKK_RSA but not CKK_DSA. - */ - case CKA_DECRYPT: - val = is_private && is_rsa; - break; - - /* - * Whether this key can be used to derive a session or - * other key. - * - Not true for CKK_RSA or CKK_DSA. - */ - case CKA_DERIVE: - val = CK_FALSE; - break; - - /* - * Whether or not this key can be used to encrypt?. - * TODO: Support for RSA public keys. - */ - case CKA_ENCRYPT: - val = CK_FALSE; - break; - - /* - * Whether this key can be exported or not. - * TODO: We may want to support this for public keys. - */ - case CKA_EXTRACTABLE: - val = CK_FALSE; - break; - - /* - * Whether this key was created on token. - * TODO: Can we implement this properly? - */ - case CKA_LOCAL: - val = CK_FALSE; - break; - - /* - * Whether this object is modifiable. - * - Keys are generally. never modifiable. - */ - case CKA_MODIFIABLE: - val = CK_FALSE; - break; - - /* - * Whether this key was ever extractable. - * TODO: Can we determine this? - */ - case CKA_NEVER_EXTRACTABLE: - val = CK_FALSE; - break; - - /* - * Whether this is a private object or not. - * - This 'private' means login before use. But maps - * well to private key use, since we're always logged in. - */ - case CKA_PRIVATE: - val = is_private; - break; - - /* - * Whether this is a sensitive object or not. - * - Private keys are sensitive, some attributes not - * readable. - */ - case CKA_SENSITIVE: - val = is_private; - break; - - /* - * Can this key sign stuff? - * - Private keys can sign. - */ - case CKA_SIGN: - val = is_private; - break; - - /* - * Can this key sign recoverable. - * TODO: Private RSA keys can sign recoverable. - */ - case CKA_SIGN_RECOVER: - val = CK_FALSE; - break; - - /* - * Is this stored on the token? - * - All CAPI objects are. - */ - case CKA_TOKEN: - val = CK_TRUE; - break; - - /* - * Is this key trusted? - * - A nebulous question. - */ - case CKA_TRUSTED: - val = CK_FALSE; - break; - - /* - * Key wrapping with public keys. - */ - case CKA_WRAP: - if(is_private) - return CKR_ATTRIBUTE_TYPE_INVALID; - val = CK_FALSE; - break; - - /* - * Key wrapping on private keys. - */ - case CKA_WRAP_WITH_TRUSTED: - if(!is_private) - return CKR_ATTRIBUTE_TYPE_INVALID; - val = CK_FALSE; - break; - - /* - * Can do a unwrap operation? - * - We don't implement this. - */ - case CKA_UNWRAP: - val = CK_FALSE; - break; - - /* - * Wrap, and unwrap stuff. - * - We don't implement this. - */ - case CKA_UNWRAP_TEMPLATE: - return CKR_ATTRIBUTE_TYPE_INVALID; - - /* - * Whether this key can be used to verify? - * TODO: Support for public keys. - */ - case CKA_VERIFY: - val = CK_FALSE; - break; - - /* - * Whether this key can be used to verify? - * TODO: Support for public keys. - */ - case CKA_VERIFY_RECOVER: - val = CK_FALSE; - break; - - default: - return CKR_ATTRIBUTE_TYPE_INVALID; - }; - - return p11c_return_data(attr, &val, sizeof(CK_BBOOL)); -} - -static CK_RV -key_ulong_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) -{ - KeyObjectData* kdata = (KeyObjectData*)objdata; - CK_ULONG val; - - ASSERT(kdata); - ASSERT(attr); - - switch(attr->type) - { - - /* - * Object class. - */ - case CKA_CLASS: - val = kdata->object_class; - break; - - /* - * The key type. - * - Right now we only support (and load) RSA. - */ - case CKA_KEY_TYPE: - if(kdata->prov_info->dwProvType == PROV_RSA_FULL) - val = CKK_RSA; - else - val = CK_UNAVAILABLE_INFORMATION; - break; - - /* - * The key generation mechanism. - * TODO: We don't yet support key generation. - */ - case CKA_KEY_GEN_MECHANISM: - val = CK_UNAVAILABLE_INFORMATION; - break; - - /* - * The RSA modulus bits. - */ - case CKA_MODULUS_BITS: - if(kdata->prov_info->dwProvType == PROV_RSA_FULL) - return lookup_rsa_attribute(kdata, attr); - else - return CKR_ATTRIBUTE_TYPE_INVALID; - - default: - return CKR_ATTRIBUTE_TYPE_INVALID; - }; - - return p11c_return_data(attr, &val, sizeof(CK_ULONG)); -} - -static CK_RV -key_bytes_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) -{ - KeyObjectData* kdata = (KeyObjectData*)objdata; - CK_MECHANISM_TYPE allowed_mechanisms[] = { CKM_RSA_PKCS }; - WCHAR* label; - - ASSERT(kdata); - ASSERT(attr); - - switch(attr->type) - { - /* - * The ID of the key. This should match the ID we - * return for any matching certificates. - */ - case CKA_ID: - return p11c_return_data(attr, kdata->key_identifier.pbData, - kdata->key_identifier.cbData); - - /* - * The key label. - * - We use the container name. - */ - case CKA_LABEL: - label = kdata->prov_info->pwszContainerName; - if(!label) - label = L"Unnamed Key"; - return p11c_return_string(attr, label); - - /* - * The subject of the related certificate. - * TODO: Implement this lookup. - */ - case CKA_SUBJECT: - return p11c_return_data(attr, "", 0); - - /* - * Allowed mechanisms with this key. - * - RSA used with CKM_RSA - * TODO: Needs updating when DSA implemented. - */ - case CKA_ALLOWED_MECHANISMS: - return p11c_return_data(attr, &allowed_mechanisms, - sizeof(allowed_mechanisms)); - - /* - * Various RSA public attributes. - */ - case CKA_MODULUS: - case CKA_PUBLIC_EXPONENT: - case CKA_PRIVATE_EXPONENT: - case CKA_PRIME_1: - case CKA_PRIME_2: - case CKA_EXPONENT_1: - case CKA_EXPONENT_2: - case CKA_COEFFICIENT: - if(kdata->prov_info->dwProvType == PROV_RSA_FULL) - return lookup_rsa_attribute(kdata, attr); - else - return CKR_ATTRIBUTE_TYPE_INVALID; - - /* - * Last date this key can be used. - * TODO: Does CAPI support this ability? - */ - case CKA_END_DATE: - case CKA_START_DATE: - return p11c_return_data(attr, "", 0); - - default: - return CKR_ATTRIBUTE_TYPE_INVALID; - }; -} - -static void -key_release(void* data) -{ - KeyObjectData* kdata = (KeyObjectData*)data; - ASSERT(kdata); - - ASSERT(kdata->key_identifier.pbData); - ASSERT(kdata->prov_info); - - free(kdata->key_identifier.pbData); - free(kdata->prov_info); - - free(kdata); -} - -static const P11cObjectDataVtable key_objdata_vtable = { - key_bool_attribute, - key_ulong_attribute, - key_bytes_attribute, - key_release, -}; - -static CRYPT_KEY_PROV_INFO* -duplicate_prov_info(CRYPT_KEY_PROV_INFO* original) -{ - DWORD container_length, prov_length; - CRYPT_KEY_PROV_INFO* result; - DWORD length, i; - BYTE* at; - BYTE* end; - - if(!original) - return NULL; - - /* Go through and calculate the length */ - length = sizeof(CRYPT_KEY_PROV_INFO); - if(original->pwszContainerName) - { - container_length = (wcslen(original->pwszContainerName) + 1) * sizeof(WCHAR); - length += container_length; - } - - if(original->pwszProvName) - { - prov_length = (wcslen(original->pwszProvName) + 1) * sizeof(WCHAR); - length += prov_length; - } - - length += sizeof(CRYPT_KEY_PROV_PARAM) * original->cProvParam; - for(i = 0; i < original->cProvParam; ++i) - length += original->rgProvParam[i].cbData; - - /* Allocate a single block of memory for everything */ - at = (BYTE*)malloc(length); - if(!at) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return NULL; - } - - /* Copy in very carefully */ - end = at + length; - - memcpy(at, original, sizeof(CRYPT_KEY_PROV_INFO)); - result = (CRYPT_KEY_PROV_INFO*)at; - at += sizeof(CRYPT_KEY_PROV_INFO); - - if(result->pwszContainerName) - { - memcpy(at, result->pwszContainerName, container_length); - result->pwszContainerName = (LPWSTR)at; - at += container_length; - } - - if(result->pwszProvName) - { - memcpy(at, result->pwszProvName, prov_length); - result->pwszProvName = (LPWSTR)at; - at += prov_length; - } - - if(original->cProvParam) - { - memcpy(at, result->rgProvParam, sizeof(CRYPT_KEY_PROV_PARAM) * result->cProvParam); - result->rgProvParam = (CRYPT_KEY_PROV_PARAM*)at; - at += sizeof(CRYPT_KEY_PROV_PARAM) * result->cProvParam; - - for(i = 0; i < result->cProvParam; ++i) - { - memcpy(at, result->rgProvParam[i].pbData, result->rgProvParam[i].cbData); - result->rgProvParam[i].pbData = (BYTE*)at; - at += result->rgProvParam[i].cbData; - } - } - - ASSERT(at == end); - return result; -} - -static P11cObjectData* -key_alloc_data(P11cSession* sess, P11cObject* obj, CRYPT_KEY_PROV_INFO* prov_info) -{ - KeyObject* kobj = (KeyObject*)obj; - KeyObjectData* kdata; - - kdata = (KeyObjectData*)calloc(1, sizeof(KeyObjectData)); - if(!kdata) - return NULL; - - /* Allocate memory for key identifier */ - kdata->key_identifier.pbData = malloc(kobj->key_identifier.cbData); - if(!kdata->key_identifier.pbData) - { - free(kdata); - return NULL; - } - - /* Setup the object data */ - kdata->object_class = kobj->object_class; - kdata->prov_info = prov_info; - kdata->key_identifier.cbData = kobj->key_identifier.cbData; - memcpy(kdata->key_identifier.pbData, kobj->key_identifier.pbData, - kdata->key_identifier.cbData); - kdata->raw_public_key.pbData = NULL; - kdata->raw_public_key.cbData = 0; - - kdata->base.object = obj->id; - kdata->base.data_funcs = &key_objdata_vtable; - - return &(kdata->base); -} - -static BOOL WINAPI -load_key_property_info(PCRYPT_HASH_BLOB key_identifier, DWORD flags, - void* reserved, void* arg, DWORD n_props, DWORD* props, - void** datas, DWORD* n_datas) -{ - CRYPT_KEY_PROV_INFO** prov_info = (CRYPT_KEY_PROV_INFO**)arg; - DWORD i; - - /* - * Already got a provider info. This shouldn't happen - * but can occur if the same key is present twice. - */ - if(*prov_info) - return TRUE; - - /* Find the key provider info property */ - for(i = 0; i < n_props; ++i) - { - if(props[i] == CERT_KEY_PROV_INFO_PROP_ID) - { - *prov_info = duplicate_prov_info((CRYPT_KEY_PROV_INFO*)datas[i]); - break; - } - } - - return TRUE; -} - -static CK_RV -key_load_data(P11cSession* sess, P11cObject* obj, P11cObjectData** objdata) -{ - KeyObject* kobj = (KeyObject*)obj; - CRYPT_KEY_PROV_INFO* prov_info = NULL; - - ASSERT(kobj); - ASSERT(objdata); - - /* Load the provider info */ - if(!CryptEnumKeyIdentifierProperties((CRYPT_HASH_BLOB*)&kobj->key_identifier, - CERT_KEY_PROV_INFO_PROP_ID, 0, NULL, NULL, - &prov_info, load_key_property_info)) - return p11c_winerr_to_ckr(GetLastError()); - - /* No provider info, bad news */ - if(!prov_info) - return CKR_GENERAL_ERROR; - - *objdata = key_alloc_data(sess, obj, prov_info); - if(!(*objdata)) - { - free(prov_info); - return CKR_HOST_MEMORY; - } - - return CKR_OK; -} - -static unsigned int -key_hash_func(P11cObject* obj) -{ - KeyObject* kobj = (KeyObject*)obj; - return p11c_hash_data(kobj->key_identifier.pbData, kobj->key_identifier.cbData) ^ - p11c_hash_integer((int)kobj->object_class); -} - -static int -key_equal_func(P11cObject* a, P11cObject* b) -{ - KeyObject* ka = (KeyObject*)a; - KeyObject* kb = (KeyObject*)b; - return ka->object_class == kb->object_class && - ka->key_identifier.cbData == kb->key_identifier.cbData && - memcmp(ka->key_identifier.pbData, kb->key_identifier.pbData, ka->key_identifier.cbData) == 0; -} - -static void -key_object_release(void* data) -{ - KeyObject* kobj = (KeyObject*)data; - ASSERT(kobj); - free(kobj); -} - -static const P11cObjectVtable key_object_vtable = { - key_load_data, - key_hash_func, - key_equal_func, - key_object_release, -}; - -static CK_RV -register_key_object(P11cSession* sess, CK_OBJECT_CLASS cls, - CRYPT_HASH_BLOB* key_identifier, P11cObject** obj) -{ - KeyObject* kobj; - CK_RV ret; - - ASSERT(obj); - ASSERT(key_identifier); - ASSERT(cls == CKO_PRIVATE_KEY || cls == CKO_PUBLIC_KEY); - - kobj = calloc(1, sizeof(KeyObject) + key_identifier->cbData); - if(!kobj) - return CKR_HOST_MEMORY; - - kobj->obj.id = 0; - kobj->obj.obj_funcs = &key_object_vtable; - - kobj->object_class = cls; - kobj->key_identifier.pbData = (BYTE*)(kobj + 1); - kobj->key_identifier.cbData = key_identifier->cbData; - memcpy(kobj->key_identifier.pbData, key_identifier->pbData, - kobj->key_identifier.cbData); - - ret = p11c_token_register_object(sess->slot, &(kobj->obj)); - if(ret != CKR_OK) - { - free(kobj); - return ret; - } - - ASSERT(kobj->obj.id != 0); - *obj = &(kobj->obj); - - return CKR_OK; -} - -typedef struct _EnumArguments -{ - P11cSession* sess; - CK_OBJECT_CLASS object_class; - CK_ATTRIBUTE_PTR match; - CK_ULONG count; - P11cArray* results; - CK_RV ret; -} -EnumArguments; - -static BOOL WINAPI -enum_key_property_info(PCRYPT_HASH_BLOB key_identifier, DWORD flags, - void* reserved, void* arg, DWORD n_props, DWORD* props, - void** datas, DWORD* n_datas) -{ - EnumArguments* args = (EnumArguments*)arg; - CRYPT_KEY_PROV_INFO* prov_info = NULL; - P11cObject *obj = NULL; - KeyObjectData kdata; - DWORD i; - - /* Find the key provider info property */ - for(i = 0; i < n_props; ++i) - { - if(props[i] == CERT_KEY_PROV_INFO_PROP_ID) - { - prov_info = (CRYPT_KEY_PROV_INFO*)datas[i]; - break; - } - } - - /* Strange key, skip */ - if(!prov_info) - return TRUE; - - /* Match the public key */ - kdata.prov_info = prov_info; - kdata.object_class = args->object_class; - kdata.base.object = 0; - kdata.base.data_funcs = &key_objdata_vtable; - - if(p11c_object_data_match(&kdata.base, args->match, args->count)) - { - args->ret = register_key_object(args->sess, args->object_class, key_identifier, &obj); - if(args->ret == CKR_OK) - { - ASSERT(obj); - p11c_array_append(args->results, obj->id); - } - } - - return TRUE; - -} - -static CK_RV -find_any_keys(P11cSession* sess, CK_OBJECT_CLASS cls, - CK_ATTRIBUTE_PTR match, CK_ULONG count, P11cArray* arr) -{ - CRYPT_HASH_BLOB find_id; - EnumArguments enum_args; - CK_ULONG i; - - /* Try to setup for an efficient search based on key id */ - memset(&find_id, 0, sizeof(find_id)); - for(i = 0; i < count; ++i) - { - if(!match[i].pValue || !match[i].ulValueLen) - continue; - if(match[i].type == CKA_ID) - { - find_id.cbData = match[i].ulValueLen; - find_id.pbData = match[i].pValue; - } - } - - enum_args.sess = sess; - enum_args.match = match; - enum_args.count = count; - enum_args.results = arr; - enum_args.object_class = cls; - enum_args.ret = CKR_OK; - - if(!CryptEnumKeyIdentifierProperties(find_id.cbData != 0 ? &find_id : NULL, - CERT_KEY_PROV_INFO_PROP_ID, 0, NULL, NULL, - &enum_args, enum_key_property_info)) - return p11c_winerr_to_ckr(GetLastError()); - - return enum_args.ret; -} - -static CK_RV -list_matching_certificates(P11cSession* sess, CK_ATTRIBUTE_PTR match, - CK_ULONG count, P11cArray* arr) -{ - CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; - CK_ATTRIBUTE search[3]; - CK_ULONG n_search = 0; - CK_ULONG i; - - /* The class */ - search[0].type = CKA_CLASS; - search[0].pValue = &cert_class; - search[0].ulValueLen = sizeof(CK_OBJECT_CLASS); - ++n_search; - - for(i = 0; i < count && n_search < 3; ++i) - { - /* - * This is the attributes that tie a certificate - * to key object, so try match certs with these - */ - if(match[i].type == CKA_ID) - { - search[n_search].type = match[i].type; - search[n_search].pValue = match[i].pValue; - search[n_search].ulValueLen = match[i].ulValueLen; - ++n_search; - } - } - - /* Do the certificate search */ - return p11c_cert_find(sess, CKO_CERTIFICATE, search, n_search, arr); -} - -static CK_RV -find_certificate_key(P11cSession* session, CK_OBJECT_CLASS cls, - CK_ATTRIBUTE_PTR match, CK_ULONG count, - PCCERT_CONTEXT cert, P11cArray* arr) -{ - CRYPT_KEY_PROV_INFO* prov_info; - CRYPT_HASH_BLOB key_identifier; - P11cObjectData* objdata; - KeyObjectData kdata; - P11cObject* obj; - DWORD prov_length; - DWORD error; - CK_RV ret = CKR_OK; - - /* Look up the key provider info and identifier */ - if(!CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &prov_length) || - !CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &key_identifier.cbData)) - { - error = GetLastError(); - if(error == CRYPT_E_NOT_FOUND) - return CKR_OK; - return p11c_winerr_to_ckr(error); - } - - /* We own the info memory */ - prov_info = malloc(prov_length); - if(!prov_info) - return CKR_HOST_MEMORY; - key_identifier.pbData = malloc(key_identifier.cbData); - if(!key_identifier.pbData) - { - free(prov_info); - return CKR_HOST_MEMORY; - } - - /* Lookup the key provider info and identifier */ - if(CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, prov_info, &prov_length) && - CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, key_identifier.pbData, &key_identifier.cbData)) - { - kdata.object_class = cls; - kdata.prov_info = prov_info; - kdata.key_identifier = key_identifier; - kdata.base.object = 0; - kdata.base.data_funcs = &key_objdata_vtable; - - if(p11c_object_data_match(&kdata.base, match, count)) - { - ret = register_key_object(session, cls, &key_identifier, &obj); - if(ret == CKR_OK) - { - ASSERT(obj); - - /* Store away the object data for performance reasons */ - objdata = key_alloc_data(session, obj, prov_info); - if(objdata) - { - p11c_session_take_object_data(session, obj, objdata); - - /* Note these are used, and not to be freed */ - key_identifier.pbData = NULL; - key_identifier.cbData = 0; - prov_info = NULL; - } - - p11c_array_append(arr, obj->id); - } - } - } - else - { - ret = p11c_winerr_to_ckr(GetLastError()); - } - - if(key_identifier.pbData) - free(key_identifier.pbData); - if(prov_info) - free(prov_info); - - return ret; -} - -static CK_RV -find_certificate_keys(P11cSession* session, CK_OBJECT_CLASS cls, - CK_ATTRIBUTE_PTR match, CK_ULONG count, P11cArray* arr) -{ - CK_OBJECT_HANDLE id; - P11cObjectData* certdata; - P11cArray* certarr; - PCCERT_CONTEXT cert; - CK_RV ret = CKR_OK; - CK_ULONG i; - - /* Get a list of all certificates */ - certarr = p11c_array_new(0, 1, sizeof(CK_OBJECT_HANDLE)); - if(!certarr) - return CKR_HOST_MEMORY; - ret = list_matching_certificates(session, match, count, certarr); - - /* Now match each of them against our criteria */ - if(ret == CKR_OK) - { - for(i = 0; i < certarr->len; ++i) - { - id = p11c_array_index(certarr, CK_OBJECT_HANDLE, i); - ASSERT(id); - - /* Get the certificate data for this certificate object */ - if(p11c_session_get_object_data_for(session, id, &certdata) != CKR_OK) - continue; - - /* Get the certificate context */ - cert = p11c_cert_object_data_get_certificate(certdata); - if(!cert) - continue; - - /* Remember we can have either or both keys for each certificate */ - ret = find_certificate_key(session, cls, match, count, cert, arr); - } - } - - p11c_array_free(certarr, TRUE); - return ret; -} - -CK_RV -p11c_key_find(P11cSession* sess, CK_OBJECT_CLASS cls, - CK_ATTRIBUTE_PTR match, CK_ULONG count, P11cArray* arr) -{ - CK_RV ret = CKR_OK; - - /* Is this somewhere we have all keys present? */ - if(p11c_token_get_flags(sess->slot) & P11C_SLOT_ANYKEY) - { - if((cls == CKO_PRIVATE_KEY || cls == CKO_ANY) && ret == CKR_OK) - ret = find_any_keys(sess, CKO_PRIVATE_KEY, match, count, arr); - if((cls == CKO_PUBLIC_KEY || cls == CKO_ANY) && ret == CKR_OK) - ret = find_any_keys(sess, CKO_PUBLIC_KEY, match, count, arr); - } - - /* Otherwise we can only list the keys that have certificates */ - else - { - if((cls == CKO_PRIVATE_KEY || cls == CKO_ANY) && ret == CKR_OK) - ret = find_certificate_keys(sess, CKO_PRIVATE_KEY, match, count, arr); - if((cls == CKO_PUBLIC_KEY || cls == CKO_ANY) && ret == CKR_OK) - ret = find_certificate_keys(sess, CKO_PUBLIC_KEY, match, count, arr); - } - - return ret; -} - -DWORD -p11c_key_object_data_get_bits(P11cObjectData* objdata) -{ - KeyObjectData* kdata; - PUBLICKEYSTRUC* header; - RSAPUBKEY* pubkey; - CK_RV ret; - - ASSERT(objdata); - - kdata = (KeyObjectData*)objdata; - - if(!kdata->raw_public_key.pbData) - { - ret = load_raw_public_key(kdata); - if(ret != CKR_OK) - return ret; - } - - header = (PUBLICKEYSTRUC*)kdata->raw_public_key.pbData; - if(!header->bType == PUBLICKEYBLOB) - return 0; - - pubkey = (RSAPUBKEY*)(header + 1); - if(!pubkey->magic == 0x31415352) - return 0; - - return pubkey->bitlen; -} - -CRYPT_KEY_PROV_INFO* -p11c_key_object_data_get_prov_info(P11cObjectData* objdata) -{ - KeyObjectData* kdata; - - ASSERT(objdata); - kdata = (KeyObjectData*)objdata; - return kdata->prov_info; -} diff --git a/p11-capi-key.h b/p11-capi-key.h deleted file mode 100644 index b57a2d3..0000000 --- a/p11-capi-key.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2008 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef P11C_KEY_H -#define P11C_KEY_H - -#include "p11-capi.h" - -/* Find key objects matching criteria */ -CK_RV p11c_key_find (P11cSession* sess, CK_OBJECT_CLASS cls, - CK_ATTRIBUTE_PTR match, CK_ULONG count, - P11cArray* arr); - -DWORD p11c_key_object_data_get_bits (P11cObjectData* objdata); - -CRYPT_KEY_PROV_INFO* p11c_key_object_data_get_prov_info (P11cObjectData* objdata); - -#endif /* P11C_KEY_H */ diff --git a/p11-capi-object.c b/p11-capi-object.c deleted file mode 100644 index 6c2330e..0000000 --- a/p11-capi-object.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "p11-capi.h" -#include "p11-capi-object.h" - -#include "pkcs11/pkcs11n.h" - -#include - -enum -{ - DATA_UNKNOWN = 0, - DATA_BOOL, - DATA_ULONG, - DATA_BYTES -}; - -int -attribute_data_type(CK_ATTRIBUTE_TYPE type) -{ - switch(type) - { - // CK_ULONG attribute types - case CKA_CLASS: - case CKA_CERTIFICATE_TYPE: - case CKA_CERTIFICATE_CATEGORY: - case CKA_KEY_TYPE: - case CKA_MODULUS_BITS: - case CKA_PRIME_BITS: - /* case CKA_SUBPRIME_BITS: */ - case CKA_SUB_PRIME_BITS: - case CKA_VALUE_BITS: - case CKA_VALUE_LEN: - case CKA_KEY_GEN_MECHANISM: - case CKA_HW_FEATURE_TYPE: - case CKA_PIXEL_X: - case CKA_PIXEL_Y: - case CKA_RESOLUTION: - case CKA_CHAR_ROWS: - case CKA_CHAR_COLUMNS: - case CKA_BITS_PER_PIXEL: - case CKA_MECHANISM_TYPE: - case CKA_JAVA_MIDP_SECURITY_DOMAIN: - case CKA_TRUST_SERVER_AUTH: - case CKA_TRUST_CLIENT_AUTH: - case CKA_TRUST_CODE_SIGNING: - case CKA_TRUST_EMAIL_PROTECTION: - case CKA_TRUST_IPSEC_END_SYSTEM: - case CKA_TRUST_IPSEC_TUNNEL: - case CKA_TRUST_IPSEC_USER: - case CKA_TRUST_TIME_STAMPING: - return DATA_ULONG; - - // CK_BBOOL attribute types - case CKA_TOKEN: - case CKA_PRIVATE: - case CKA_MODIFIABLE: - case CKA_TRUSTED: - case CKA_SENSITIVE: - case CKA_DECRYPT: - case CKA_SIGN: - case CKA_SIGN_RECOVER: - case CKA_UNWRAP: - case CKA_EXTRACTABLE: - case CKA_NEVER_EXTRACTABLE: - case CKA_ALWAYS_SENSITIVE: - case CKA_WRAP_WITH_TRUSTED: - case CKA_ALWAYS_AUTHENTICATE: - case CKA_ENCRYPT: - case CKA_WRAP: - case CKA_VERIFY: - case CKA_VERIFY_RECOVER: - case CKA_DERIVE: - case CKA_LOCAL: - case CKA_RESET_ON_INIT: - case CKA_HAS_RESET: - case CKA_COLOR: - case CKA_TRUST_STEP_UP_APPROVED: - return DATA_BOOL; - - // Raw or string data - case CKA_LABEL: - case CKA_APPLICATION: - case CKA_VALUE: - case CKA_OBJECT_ID: - case CKA_CHECK_VALUE: - case CKA_ISSUER: - case CKA_SERIAL_NUMBER: - case CKA_SUBJECT: - case CKA_ID: - case CKA_URL: - case CKA_HASH_OF_SUBJECT_PUBLIC_KEY: - case CKA_HASH_OF_ISSUER_PUBLIC_KEY: - case CKA_AC_ISSUER: - case CKA_OWNER: - case CKA_ATTR_TYPES: - case CKA_MODULUS: - case CKA_PUBLIC_EXPONENT: - case CKA_PRIVATE_EXPONENT: - case CKA_PRIME_1: - case CKA_PRIME_2: - case CKA_EXPONENT_1: - case CKA_EXPONENT_2: - case CKA_COEFFICIENT: - case CKA_PRIME: - case CKA_SUBPRIME: - case CKA_BASE: - case CKA_ECDSA_PARAMS: - /* case CKA_EC_PARAMS: */ - case CKA_EC_POINT: - case CKA_CHAR_SETS: - case CKA_ENCODING_METHODS: - case CKA_MIME_TYPES: - case CKA_REQUIRED_CMS_ATTRIBUTES: - case CKA_DEFAULT_CMS_ATTRIBUTES: - case CKA_SUPPORTED_CMS_ATTRIBUTES: - case CKA_CERT_SHA1_HASH: - case CKA_CERT_MD5_HASH: - case CKA_ALLOWED_MECHANISMS: - case CKA_START_DATE: - case CKA_END_DATE: - return DATA_BYTES; - - // Arrays are nasty - case CKA_WRAP_TEMPLATE: - case CKA_UNWRAP_TEMPLATE: - default: - DBG(("unknown attribute type: %x", type)); - return DATA_UNKNOWN; - }; -} - -CK_BBOOL -p11c_object_data_match_attr(P11cObjectData* objdata, CK_ATTRIBUTE_PTR match) -{ - CK_ATTRIBUTE attr; - CK_RV rv; - int dtype; - - ASSERT(match); - ASSERT(objdata); - ASSERT(objdata->data_funcs); - - /* Get the data type of the attribute */ - dtype = attribute_data_type(match->type); - if(dtype == DATA_UNKNOWN) - return CK_FALSE; - - /* We only do byte matching */ - if(match->pValue == NULL) - return CK_FALSE; - - /* Only load as much data as is needed */ - attr.type = match->type; - attr.pValue = _alloca(match->ulValueLen > 4 ? match->ulValueLen : 4); - attr.ulValueLen = match->ulValueLen; - - switch(dtype) - { - case DATA_BOOL: - rv = (objdata->data_funcs->get_bool)(objdata, &attr); - break; - case DATA_ULONG: - rv = (objdata->data_funcs->get_ulong)(objdata, &attr); - break; - case DATA_BYTES: - rv = (objdata->data_funcs->get_bytes)(objdata, &attr); - break; - default: - ASSERT(0 && "unrecognized type"); - break; - }; - - /* Unrecognized attribute */ - if(rv == CKR_ATTRIBUTE_TYPE_INVALID) - return CK_FALSE; - - /* Value is longer than this one */ - if(rv == CKR_BUFFER_TOO_SMALL) - return CK_FALSE; - - /* All other errors */ - if(rv != CKR_OK) - return CK_FALSE; - - return (match->ulValueLen == attr.ulValueLen && - memcmp(match->pValue, attr.pValue, attr.ulValueLen) == 0); -} - -CK_BBOOL -p11c_object_data_match(P11cObjectData* objdata, CK_ATTRIBUTE_PTR matches, - CK_ULONG count) -{ - CK_ULONG i; - - for(i = 0; i < count; ++i) - { - if(!p11c_object_data_match_attr(objdata, &matches[i])) - return CK_FALSE; - } - - return CK_TRUE; -} - -CK_RV -p11c_object_data_get_attrs(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attrs, - CK_ULONG count) -{ - CK_ULONG i; - CK_RV rv, ret = CKR_OK; - - ASSERT(objdata); - ASSERT(!count || attrs); - - for(i = 0; i < count; ++i) - { - /* Get the data type of the attribute */ - switch(attribute_data_type(attrs[i].type)) - { - case DATA_BOOL: - rv = (objdata->data_funcs->get_bool)(objdata, &attrs[i]); - break; - case DATA_ULONG: - rv = (objdata->data_funcs->get_ulong)(objdata, &attrs[i]); - break; - case DATA_BYTES: - rv = (objdata->data_funcs->get_bytes)(objdata, &attrs[i]); - break; - case DATA_UNKNOWN: - rv = CKR_ATTRIBUTE_TYPE_INVALID; - break; - default: - ASSERT(0 && "unrecognized type"); - break; - }; - - /* Not an error if they were just requesting the size */ - if(rv != CKR_OK) - { - if(rv == CKR_BUFFER_TOO_SMALL) - { - if(!attrs[i].pValue) - rv = CKR_OK; - } - - /* Attribute is sensitive */ - else if(rv == CKR_ATTRIBUTE_SENSITIVE) - { - attrs[i].ulValueLen = (CK_ULONG)-1; - } - - /* Attribute doesn't exist */ - else if(rv == CKR_ATTRIBUTE_TYPE_INVALID) - { - DBG(("O%d: attribute not found: 0x%08x", objdata->object, attrs[i].type)); - attrs[i].ulValueLen = (CK_ULONG)-1; - } - - /* A fatal error? */ - else - { - ret = rv; - break; - } - - /* Transfer any non-fatal errors outward */ - if(rv != CKR_OK && ret == CKR_OK) - ret = rv; - } - } - - return ret; -} diff --git a/p11-capi-object.h b/p11-capi-object.h deleted file mode 100644 index e884ee1..0000000 --- a/p11-capi-object.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef P11C_OBJECT_H -#define P11C_OBJECT_H - -#include "p11-capi.h" - -/* Debug print something about an object */ -#define DBGO(obj, msg) \ - p11c_debug("O%d: %s", (obj) ? (obj)->id : 0, (msg)) - -/* A function to load data for an object */ -typedef CK_RV (*P11cLoadData)(P11cSession* sess, struct _P11cObject* obj, - P11cObjectData** objdata); - -/* Produce a hash code for an object */ -typedef CK_RV (*P11cHashObject)(struct _P11cObject* obj); - -/* Produce a hash code for an object */ -typedef CK_RV (*P11cEqualObject)(struct _P11cObject* one, struct _P11cObject* two); - -/* A function to free some data */ -typedef void (*P11cRelease)(void* data); - -/* Object functions */ -typedef struct _P11cObjectVtable -{ - P11cLoadData load_data; - P11cHashObject hash_object; - P11cEqualObject equal_object; - P11cRelease release; -} -P11cObjectVtable; - -/* Represents a object we've seen */ -struct _P11cObject -{ - CK_OBJECT_HANDLE id; - CK_SLOT_ID slot; - CK_SESSION_HANDLE session; - const P11cObjectVtable* obj_funcs; -}; - -/* A function to get an attribute from ObjectData */ -typedef CK_RV (*P11cGetAttribute)(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr); - -/* Object data functions */ -typedef struct _P11cObjectDataVtable -{ - P11cGetAttribute get_bool; - P11cGetAttribute get_ulong; - P11cGetAttribute get_bytes; - P11cRelease release; -} -P11cObjectDataVtable; - -/* - * Base class for object data. Different types of - * objects extend this with more detailed data - */ -struct _P11cObjectData -{ - CK_OBJECT_HANDLE object; - const P11cObjectDataVtable* data_funcs; -}; - -/* Match object data against all the given match attributes */ -CK_BBOOL p11c_object_data_match (P11cObjectData* objdata, - CK_ATTRIBUTE_PTR matches, CK_ULONG count); - -/* Match a single attribute against object data */ -CK_BBOOL p11c_object_data_match_attr (P11cObjectData* objdata, - CK_ATTRIBUTE_PTR match); - -/* Get a bunch of attributes from object data */ -CK_RV p11c_object_data_get_attrs (P11cObjectData* objdata, CK_ATTRIBUTE_PTR attrs, - CK_ULONG count); - -/* Debug print something about an object data */ -#define DBGOD(objdata, msg) \ - p11c_debug("O%d: %s", (objdata) ? (objdata)->obj : 0, (msg)) - -#endif /* P11C_OBJECT_H */ diff --git a/p11-capi-rsa.c b/p11-capi-rsa.c deleted file mode 100644 index 18fc4eb..0000000 --- a/p11-capi-rsa.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright (C) 2008 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "p11-capi.h" -#include "p11-capi-der.h" -#include "p11-capi-key.h" -#include "p11-capi-object.h" - -/* - * Portions derived from NSS source files: - * lib/ckfw/capi/crsa.c - */ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Red Hat, Inc. - * Portions created by the Initial Developer are Copyright (C) 2005 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Bob Relyea (rrelyea@redhat.com) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#define SSL3_SHAMD5_HASH_SIZE 36 /* LEN_MD5 (16) + LEN_SHA1 (20) */ - -/* - * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value, - * which includes the hash OID. CAPI expects to take a Hash Context. While - * CAPI does have the capability of setting a raw hash value, it does not - * have the ability to sign an arbitrary value. This function tries to - * reduce the passed in data into something that CAPI could actually sign. - */ -static CK_BYTE_PTR -parse_rsa_pkcs_der_hash(CK_BYTE_PTR input, CK_ULONG n_input, - ALG_ID* algorithm, CK_ULONG_PTR n_hash) -{ - BYTE* algid; - BYTE* oid; - BYTE* hash_data; - BYTE* oid_str; - DWORD n_oid; - DWORD n_algid; - - /* - * there are 2 types of hashes NSS typically tries to sign, regular - * RSA signature format (with encoded DER_OIDS), and SSL3 Signed hashes. - * CAPI knows not to add any oids to SSL3_Signed hashes, so if we have any - * random hash that is exactly the same size as an SSL3 hash, then we can - * just pass the data through. CAPI has know way of knowing if the value - * is really a combined hash or some other arbitrary data, so it's safe to - * handle this case first. - */ - if(SSL3_SHAMD5_HASH_SIZE == n_input) - { - *n_hash = n_input; - *algorithm = CALG_SSL3_SHAMD5; - return input; - } - - /* make sure we have a sequence tag */ - if((P11C_DER_SEQUENCE | P11C_DER_CONSTRUCTED) != *input) - return NULL; - - /* - * parse the input block to get 1) the hash oid, and 2) the raw hash value. - * unfortunatly CAPI doesn't have a builtin function to do this work, so - * we go ahead and do it by hand here. - * - * format is: - * SEQUENCE { - * SECQUENCE { // algid - * OID {} // oid - * ANY {} // optional params - * } - * OCTECT {} // hash - */ - - /* unwrap */ - algid = p11c_der_unwrap(input, n_input, &n_algid, NULL); - if(!algid) - return NULL; - - /* make sure there is not extra data at the end */ - if(algid + n_algid != input + n_input) - return NULL; - - /* wasn't an algid */ - if((P11C_DER_SEQUENCE | P11C_DER_CONSTRUCTED) != *algid) - return NULL; - - oid = p11c_der_unwrap(algid, n_algid, &n_oid, &hash_data); - if(!oid || !hash_data) - return NULL; - - if(algorithm) - { - /* - * get the real oid as a string. Again, Microsoft does not - * export anything that does this for us - */ - oid_str = p11c_der_read_oid(oid, n_oid); - if(!oid_str) - return NULL; - - /* look up the hash alg from the oid (fortunately CAPI does to this) */ - *algorithm = CertOIDToAlgId(oid_str); - free(oid_str); - } - - /* wasn't a hash? */ - if(P11C_DER_OCTET_STRING != *hash_data) - return NULL; - - /* get the real raw hash */ - return p11c_der_unwrap(hash_data, n_algid - (hash_data - algid), - n_hash, NULL); -} - -CK_RV -p11c_rsa_pkcs_sign_init(P11cObjectData *keydata, void** operation) -{ - CRYPT_KEY_PROV_INFO* prov_info; - - ASSERT(keydata); - ASSERT(operation); - ASSERT(!*operation); - - prov_info = p11c_key_object_data_get_prov_info(keydata); - if(prov_info->dwProvType != PROV_RSA_FULL) - return CKR_KEY_TYPE_INCONSISTENT; - - *operation = keydata; - return CKR_OK; -} - -CK_RV -p11c_rsa_pkcs_sign_perform (CK_BYTE_PTR data, CK_ULONG n_data, - CK_BYTE_PTR signature, CK_ULONG_PTR n_signature, - void** operation) -{ - CRYPT_KEY_PROV_INFO* prov_info; - P11cObjectData* keydata; - ALG_ID algorithm; - BYTE* hash_data; - DWORD n_hash_data; - BOOL capifail; - DWORD len, check; - DWORD bits; - CK_RV ret; - - HCRYPTPROV prov = 0; - HCRYPTHASH hash = 0; - - - ASSERT(operation); - ASSERT(*operation); - - if(!data || !n_data) - return CKR_ARGUMENTS_BAD; - - keydata = (P11cObjectData*)*operation; - - prov_info = p11c_key_object_data_get_prov_info(keydata); - ASSERT(prov_info); - - /* Calculate the number of bits */ - bits = p11c_key_object_data_get_bits (keydata); - if(!bits) - return CKR_GENERAL_ERROR; - - /* Want to know the length */ - if(!signature) - { - *n_signature = bits / 8; - return CKR_OK; - } - - /* TODO: Support arbitrary input on Vista */ - - /* - * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value, - * which includes the hash OID. CAPI expects to take a Hash Context. While - * CAPI does have the capability of setting a raw hash value, it does not - * have the ability to sign an arbitrary value. This function tries to - * reduce the passed in data into something that CAPI could actually sign. - */ - hash_data = parse_rsa_pkcs_der_hash(data, n_data, &algorithm, &n_hash_data); - if(!hash_data) - return CKR_DATA_INVALID; - - capifail = TRUE; - if(CryptAcquireContextW(&prov, prov_info->pwszContainerName, prov_info->pwszProvName, - prov_info->dwProvType, 0)) - { - if(CryptCreateHash(prov, algorithm, 0, 0, &hash)) - { - /* make sure the hash lens match before we set it */ - len = sizeof(DWORD); - if(CryptGetHashParam(hash, HP_HASHSIZE, (BYTE*)&check, &len, 0)) - { - if(check != n_hash_data) - { - capifail = FALSE; - ret = CKR_DATA_INVALID; - } - - /* - * we have an explicit hash, set it, note that the length is - * implicit by the hashAlg used in create - */ - if(CryptSetHashParam(hash, HP_HASHVAL, hash_data, 0)) - { - /* OK, we have the data in a hash structure, sign it! */ - if(CryptSignHash(hash, prov_info->dwKeySpec, - NULL, 0, signature, n_signature)) - { - /* - * OK, Microsoft likes to do things completely - * differently than anyone else. We need to reverse - * the data we recieved here - */ - if(signature) - p11c_reverse_memory(signature, *n_signature); - - capifail = FALSE; - ret = CKR_OK; - } - } - } - } - } - - if(capifail) - ret = p11c_winerr_to_ckr(GetLastError()); - - if(hash) - CryptDestroyHash(hash); - if(prov) - CryptReleaseContext(prov, 0); - - return ret; -} - -void -p11c_rsa_pkcs_sign_cleanup (void* operation) -{ - /* Nothing to do */ -} - - -CK_RV -p11c_rsa_pkcs_decrypt_init(P11cObjectData* keydata, void** operation) -{ - CRYPT_KEY_PROV_INFO* prov_info; - - ASSERT(keydata); - ASSERT(operation); - ASSERT(!*operation); - - prov_info = p11c_key_object_data_get_prov_info(keydata); - if(prov_info->dwProvType != PROV_RSA_FULL) - return CKR_KEY_TYPE_INCONSISTENT; - - *operation = keydata; - return CKR_OK; -} - -CK_RV -p11c_rsa_pkcs_decrypt_perform(CK_BYTE_PTR encdata, CK_ULONG n_encdata, - CK_BYTE_PTR result, CK_ULONG_PTR n_result, - void** operation) -{ - CRYPT_KEY_PROV_INFO* prov_info; - P11cObjectData* keydata; - BOOL capifail; - DWORD bits, error; - CK_RV ret; - - HCRYPTPROV prov = 0; - HCRYPTKEY key = 0; - void* buffer = NULL; - - ASSERT(operation); - ASSERT(*operation); - ASSERT(encdata); - ASSERT(n_encdata); - - keydata = (P11cObjectData*)*operation; - - prov_info = p11c_key_object_data_get_prov_info(keydata); - ASSERT(prov_info); - - /* Calculate the number of bits */ - bits = p11c_key_object_data_get_bits (keydata); - if(!bits) - return CKR_GENERAL_ERROR; - - /* Want to know the length */ - if(!result) - { - *n_result = bits / 8; - return CKR_OK; - } - - /* - * Copy the input, since CAPI operates in place, and - * we must also reverse it properly. - */ - buffer = malloc(n_encdata); - if(!buffer) - return CKR_HOST_MEMORY; - - memcpy(buffer, encdata, n_encdata); - p11c_reverse_memory(buffer, n_encdata); - - capifail = TRUE; - if(CryptAcquireContextW(&prov, prov_info->pwszContainerName, prov_info->pwszProvName, - prov_info->dwProvType, 0)) - { - if(CryptGetUserKey(prov, prov_info->dwKeySpec, &key)) - { - *n_result = n_encdata; - if(CryptDecrypt(key, 0, TRUE, 0, buffer, n_result)) - { - capifail = FALSE; - ret = CKR_OK; - } - } - } - - if(capifail) - { - error = GetLastError(); - switch(error) - { - case NTE_BAD_DATA: - ret = CKR_ENCRYPTED_DATA_INVALID; - default: - ret = p11c_winerr_to_ckr(error); - }; - } - - /* Copy the memory out to the result buffer */ - if(ret == CKR_OK) - ret = p11c_return_data_raw(result, n_result, buffer, *n_result); - - if(key) - CryptDestroyKey(key); - if(prov) - CryptReleaseContext(prov, 0); - if(buffer) - free(buffer); - - return ret; -} - -void -p11c_rsa_pkcs_decrypt_cleanup(void* operation) -{ - /* Nothing to do */ -} - -void -p11c_rsa_pkcs_get_info(CK_MECHANISM_TYPE mech, CK_MECHANISM_INFO_PTR info) -{ - ASSERT(mech == CKM_RSA_PKCS); - ASSERT(info != NULL); - - info->ulMinKeySize = 384; - info->ulMaxKeySize = 16384; - info->flags = 0; -} diff --git a/p11-capi-rsa.h b/p11-capi-rsa.h deleted file mode 100644 index 0ce571e..0000000 --- a/p11-capi-rsa.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2008 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef P11C_RSA_H -#define P11C_RSA_H - -#include "p11-capi.h" - -CK_RV p11c_rsa_pkcs_sign_init (P11cObjectData* keydata, void** operation); - -CK_RV p11c_rsa_pkcs_sign_perform (CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR signature, CK_ULONG_PTR signature_len, - void** operation); - -void p11c_rsa_pkcs_sign_cleanup (void* operation); - -CK_RV p11c_rsa_pkcs_decrypt_init (P11cObjectData* keydata, void** operation); - -CK_RV p11c_rsa_pkcs_decrypt_perform (CK_BYTE_PTR encdata, CK_ULONG n_encdata, - CK_BYTE_PTR result, CK_ULONG_PTR n_result, - void** operation); - -void p11c_rsa_pkcs_decrypt_cleanup (void* operation); - -void p11c_rsa_pkcs_get_info (CK_MECHANISM_TYPE mech, - CK_MECHANISM_INFO_PTR info); - -#endif /* P11C_RSA_H */ diff --git a/p11-capi-session.c b/p11-capi-session.c deleted file mode 100644 index e921875..0000000 --- a/p11-capi-session.c +++ /dev/null @@ -1,983 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include - -#include "p11-capi.h" -#include "p11-capi-builtin.h" -#include "p11-capi-cert.h" -#include "p11-capi-key.h" -#include "p11-capi-object.h" -#include "p11-capi-rsa.h" -#include "p11-capi-session.h" -#include "p11-capi-token.h" -#include "p11-capi-trust.h" - -/* For operation_type in P11cSession */ -enum -{ - OPERATION_NONE, - OPERATION_FIND, - OPERATION_SIGN, - OPERATION_DECRYPT -}; - -static P11cArray* all_sessions = NULL; - -static void -object_data_release(P11cObjectData* objdata) -{ - ASSERT(objdata->data_funcs); - ASSERT(objdata->data_funcs->release); - (objdata->data_funcs->release)(objdata); -} - -CK_RV -p11c_session_create(CK_SLOT_ID slot, P11cSession** ret) -{ - P11cSession* sess; - const char *store; - DWORD err; - - sess = calloc(1, sizeof(P11cSession)); - if(!sess) - return CKR_HOST_MEMORY; - - sess->object_data = p11c_hash_new(NULL, NULL); - if(!sess->object_data) { - free(sess); - return CKR_HOST_MEMORY; - } - - sess->mutex = CreateMutex(NULL, FALSE, NULL); - if(!sess->mutex) { - p11c_hash_free(sess->object_data, NULL); - free(sess); - return CKR_HOST_MEMORY; - } - - store = p11c_token_get_store_name(slot); - if(store) - { - sess->store = CertOpenSystemStore((HCRYPTPROV)NULL, store); - if(sess->store == NULL) - { - err = GetLastError(); - - /* Store not found, we don't care */ - if(err != ERROR_FILE_NOT_FOUND) - { - p11c_hash_free(sess->object_data, NULL); - CloseHandle(sess->mutex); - free(sess); - return p11c_winerr_to_ckr(err); - } - } - } - - sess->slot = slot; - - DBGS(sess, "created"); - - *ret = sess; - return CKR_OK; -} - -CK_RV -p11c_session_register(P11cSession* sess) -{ - P11cSession* blank = NULL; - CK_SESSION_HANDLE id = 0; - CK_RV ret = CKR_OK; - size_t i; - - ASSERT(sess); - ASSERT(sess->id == 0 && sess->refs == 0); - - DBGS(sess, "registering new session"); - - p11c_lock_global(); - - /* Find a nice session identifier */ - while(id == 0) { - - /* Allocate sessions properly */ - if(!all_sessions) - { - all_sessions = p11c_array_new(0, 1, sizeof(P11cSession*)); - if(!all_sessions) - { - ret = CKR_HOST_MEMORY; - break; - } - - /* A blank entry for '0' */ - p11c_array_append(all_sessions, blank); - - DBG(("allocated new session list")); - } - - /* - * PKCS#11 GRAY AREA: We're assuming we can reuse session - * handles. PKCS#11 spec says they're like file handles, - * and file handles get reused :) - */ - - /* Note we never put anything in array position '0' */ - for(i = 1; i < all_sessions->len; ++i) - { - /* Any empty position will do */ - if(!p11c_array_index(all_sessions, P11cSession*, i)) - { - id = i; - break; - } - } - - /* Couldn't find a handle, append a handle */ - if(id == 0) - { - id = all_sessions->len; - p11c_array_append(all_sessions, blank); - } - } - - if(ret == CKR_OK) - { - ASSERT(id > 0 && id < all_sessions->len); - ASSERT(!p11c_array_index(all_sessions, P11cSession*, id)); - - - /* And assign it to the session handle */ - p11c_array_index(all_sessions, P11cSession*, i) = sess; - sess->id = id; - - /* The session list reference */ - ASSERT(sess->refs == 0); - sess->refs++; - - DBGS(sess, "registered sesson id"); - } - - p11c_unlock_global(); - - return ret; -} - -void -p11c_session_destroy(P11cSession* sess) -{ - ASSERT(sess); - ASSERT(sess->refs == 0); - - /* Ask any pending operations to cleanup */ - if(sess->operation_type) - { - ASSERT(sess->operation_cancel); - (sess->operation_cancel)(sess); - } - - ASSERT(sess->operation_type == 0); - ASSERT(sess->operation_data == NULL); - ASSERT(sess->operation_cancel == NULL); - - if(sess->store) - CertCloseStore(sess->store, 0); - - /* Make all the object adat go away */ - ASSERT(sess->object_data != NULL); - p11c_hash_free(sess->object_data, object_data_release); - - /* And make the mutex go away */ - ASSERT(sess->mutex != NULL); - CloseHandle(sess->mutex); - - DBGS(sess, "destroyed"); - free(sess); -} - -void -p11c_session_get_info(P11cSession* sess, CK_SESSION_INFO_PTR info) -{ - ASSERT(sess); - ASSERT(info); - - info->slotID = sess->slot; - info->flags = CKF_SERIAL_SESSION; - if(sess->read_write) - info->flags |= CKF_RW_SESSION; - - if(p11c_token_is_logged_in(sess->slot)) - info->state = sess->read_write ? CKS_RW_USER_FUNCTIONS : CKS_RO_USER_FUNCTIONS; - else - info->state = sess->read_write ? CKS_RW_PUBLIC_SESSION : CKS_RO_PUBLIC_SESSION; - - /* TODO: We could implement some use of GetLastError() here */ - info->ulDeviceError = 0; -} - -static CK_RV -lock_ref_internal(P11cArray* sessions, CK_SESSION_HANDLE id, - BOOL remove, BOOL writable, P11cSession** sess_ret) -{ - P11cSession *sess; - DWORD r; - - ASSERT(sessions); - ASSERT(sess_ret); - - if(id >= sessions->len) - { - DBG(("invalid session id: %d", id)); - return CKR_SESSION_HANDLE_INVALID; - } - - /* A seemingly valid id */ - ASSERT(sessions); - sess = p11c_array_index(sessions, P11cSession*, id); - - if(!sess) - { - DBG(("session does not exist: %d", id)); - return CKR_SESSION_HANDLE_INVALID; - } - - /* Make sure it's the right kind of session */ - if(writable && !sess->read_write) - return CKR_SESSION_READ_ONLY; - - ASSERT(sess->id == id); - - /* Closing takes precedence over active operations */ - if(!remove) - { - /* - * An initial check is done to make sure this session is not active. - * This is done outside of the lock. The real check is done later - * inside a lock. This is so we can return quickly without blocking - * in most cases. - */ - - if(sess->in_call) - { - DBGS(sess, ("an operation is already active in this session")); - return CKR_OPERATION_ACTIVE; - } - } - - /* Lock the CallP11cSession */ - r = WaitForSingleObject(sess->mutex, INFINITE); - ASSERT(r == WAIT_OBJECT_0); - - /* Do the real check */ - if(!remove && sess->in_call) - { - ReleaseMutex(sess->mutex); - DBGS(sess, ("an operation is already active in this session")); - return CKR_OPERATION_ACTIVE; - } - - /* Make sure it doesn't go away */ - ASSERT(sess->refs > 0); - sess->refs++; - - DBGS(sess, "found and locked session"); - - /* And remove it if necessary */ - if(remove) - { - p11c_array_index(sessions, P11cSession*, id) = NULL; - - /* The session list reference */ - sess->refs--; - ASSERT(sess->refs > 0); - - DBGS(sess, "removed session from list"); - } - else - { - ASSERT(!sess->in_call); - sess->in_call = 1; - } - - *sess_ret = sess; - return CKR_OK; -} - -CK_RV -p11c_session_get_lock_ref(CK_ULONG id, BOOL writable, P11cSession **sess) -{ - /* This must be called without any locks held */ - - CK_RV ret = CKR_OK; - - ASSERT(sess); - - if(id <= 0) - { - DBG(("invalid session id passed: %d", id)); - return CKR_ARGUMENTS_BAD; - } - - p11c_lock_global(); - - ret = lock_ref_internal (all_sessions, id, FALSE, writable, sess); - - p11c_unlock_global(); - - return ret; -} - -CK_RV -p11c_session_remove_lock_ref(CK_ULONG id, P11cSession **sess) -{ - /* This must be called without any locks held */ - - CK_RV ret = CKR_OK; - - ASSERT(sess); - - if(id <= 0) - { - DBG(("invalid session id passed: %d", id)); - return CKR_ARGUMENTS_BAD; - } - - p11c_lock_global(); - - ret = lock_ref_internal (all_sessions, id, TRUE, FALSE, sess); - - p11c_unlock_global(); - - return ret; -} - -void -p11c_session_unref_unlock(P11cSession* sess) -{ - /* The CallP11cSession must be locked at this point */ - - int refs; - BOOL r; - - ASSERT(sess); - - ASSERT(sess->refs > 0); - sess->refs--; - refs = sess->refs; - - sess->in_call = 0; - - DBGS(sess, "unlocked session"); - - r = ReleaseMutex(sess->mutex); - ASSERT(r == TRUE); - - /* - * At this point if no references are held, then we can safely - * delete. No other thread should be involved. - */ - - if(refs == 0) - p11c_session_destroy(sess); -} - -CK_RV -p11c_session_close_all(CK_SLOT_ID slot) -{ - /* This must be called without any locks held */ - - P11cArray* sessions; - P11cSession *sess; - size_t i; - CK_RV ret = CKR_OK; - - /* - * PKCS#11 GRAY AREA: What happens when this gets called - * concurrently? We don't return an error on the second call, - * because by the time it returns, all sessions should be closed. - */ - - DBG(("closing all sessions for: %d", slot)); - - if(!all_sessions) - return CKR_OK; - - p11c_lock_global(); - - sessions = p11c_array_sized_new(0, 1, sizeof(P11cSession*), - all_sessions->len); - if(!sessions) - ret = CKR_HOST_MEMORY; - - /* Steal all the session data */ - if(ret == CKR_OK) - { - for(i = 0; i < all_sessions->len; ++i) - { - sess = p11c_array_index(all_sessions, P11cSession*, i); - if(sess && (slot == ((CK_SLOT_ID)-1) || sess->slot == slot)) - { - /* Steal this session */ - p11c_array_index(all_sessions, P11cSession*, i) = NULL; - } - else - { - /* Not a session we're interested in */ - sess = NULL; - } - - /* Both null and normal sessions are set to preserve indexes */ - p11c_array_append(sessions, sess); - } - - ASSERT(sessions->len == all_sessions->len); - } - - p11c_unlock_global(); - - if(ret != CKR_OK) - return ret; - - /* Close each session in turn */ - for(i = 0; i < sessions->len; ++i) - { - if(!p11c_array_index(sessions, P11cSession*, i)) - continue; - - /* We need any calls in other threads to finish, so wait here */ - if(lock_ref_internal(sessions, i, TRUE, FALSE, &sess) == CKR_OK) - p11c_session_unref_unlock(sess); - } - - /* We stole the memory above, free it now */ - p11c_array_free(sessions, 1); - return CKR_OK; -} - -void -p11c_session_cleanup_all() -{ - p11c_session_close_all((CK_SLOT_ID)-1); - - p11c_lock_global(); - - p11c_array_free(all_sessions, 1); - all_sessions = NULL; - - p11c_unlock_global(); -} - -/* ---------------------------------------------------------------------------- - * OBJECT DATA - */ - -CK_RV -p11c_session_get_object_data(P11cSession* sess, P11cObject* obj, - P11cObjectData** objdata) -{ - CK_OBJECT_HANDLE id; - P11cObjectData* newdata; - CK_RV ret; - - ASSERT(sess); - ASSERT(sess->object_data); - ASSERT(obj); - ASSERT(obj->obj_funcs); - ASSERT(obj->obj_funcs->load_data); - ASSERT(objdata); - - id = obj->id; - - *objdata = p11c_hash_get(sess->object_data, p11c_hash_key(id)); - if(*objdata) - return CKR_OK; - - ret = (obj->obj_funcs->load_data)(sess, obj, &newdata); - if(ret != CKR_OK) - return ret; - - newdata->object = id; - ASSERT(newdata->data_funcs); - - if(!p11c_hash_set(sess->object_data, p11c_hash_key(id), newdata)) - { - object_data_release(newdata); - return CKR_HOST_MEMORY; - } - - *objdata = newdata; - return CKR_OK; -} - -void -p11c_session_clear_object_data(P11cSession* sess, P11cObject* obj) -{ - P11cObjectData* objdata; - - ASSERT(sess); - ASSERT(sess->object_data); - ASSERT(obj); - - objdata = (P11cObjectData*)p11c_hash_rem(sess->object_data, p11c_hash_key(obj->id)); - if(objdata) - object_data_release(objdata); -} - -void -p11c_session_enum_object_data(P11cSession* sess, - P11cEnumObjectData enum_func, void* arg) -{ - CK_OBJECT_HANDLE i, max; - P11cObject* obj; - P11cObjectData* objdata; - - ASSERT(sess); - ASSERT(sess->object_data); - ASSERT(enum_func); - - max = p11c_token_get_max_handle(); - for(i = 0; i < max; ++i) - { - objdata = (P11cObjectData*)p11c_hash_get(sess->object_data, p11c_hash_key(i)); - if(!objdata) - continue; - - obj = p11c_token_lookup_object(sess->slot, i); - if(!obj) - continue; - - (enum_func)(sess, obj, objdata, arg); - } -} - -CK_RV -p11c_session_get_object_data_for(P11cSession* sess, CK_OBJECT_HANDLE hand, - P11cObjectData** objdata) -{ - P11cObject* obj; - - obj = p11c_token_lookup_object(sess->slot, hand); - if(!obj) - return CKR_OBJECT_HANDLE_INVALID; - - return p11c_session_get_object_data(sess, obj, objdata); -} - -void -p11c_session_take_object_data(P11cSession* sess, P11cObject* obj, - P11cObjectData* objdata) -{ - P11cObjectData* prev; - - ASSERT(obj); - ASSERT(sess); - ASSERT(sess->object_data); - - ASSERT(objdata); - objdata->object = obj->id; - - prev = p11c_hash_rem(sess->object_data, p11c_hash_key(obj->id)); - if(prev) - object_data_release(prev); - - if(!p11c_hash_set(sess->object_data, p11c_hash_key(obj->id), objdata)) - object_data_release(objdata); -} - - -/* ---------------------------------------------------------------------------- - * FIND OPERATION - */ - -static BOOL -get_ulong_attribute(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_PTR templ, - CK_ULONG count, CK_ULONG* val) -{ - CK_ULONG i; - - ASSERT(val); - ASSERT(!count || templ); - - for(i = 0; i < count; ++i) - { - if(templ[i].type == type) - { - *val = *((CK_ULONG*)templ[i].pValue); - return TRUE; - } - } - - return FALSE; -} - -static CK_RV -gather_objects(P11cSession* sess, CK_ATTRIBUTE_PTR match, - CK_ULONG count, P11cArray* arr) -{ - CK_OBJECT_CLASS ocls = CKO_ANY; - CK_RV ret = CKR_OK; - - get_ulong_attribute(CKA_CLASS, match, count, &ocls); - - /* Search for builtins */ - ret = p11c_builtin_find(sess, ocls, match, count, arr); - if(ret != CKR_OK) - return ret; - - /* - * Search through certificates. - * - * We always do this search first. In Windows a lots hangs off - * the certificates. For example private keys are not contained - * in the same stores that certificates are in. There are a different - * set of key containers many of which can be used together - * with a certificate stored in any store. - * - * The trust objects we expose also depend on the certificates - * loaded. - */ - ret = p11c_cert_find(sess, ocls, match, count, arr); - if(ret != CKR_OK) - return ret; - - /* Search through trust objects */ - ret = p11c_trust_find(sess, ocls, match, count, arr); - if(ret != CKR_OK) - return ret; - - /* Search through key objects */ - ret = p11c_key_find(sess, ocls, match, count, arr); - if(ret != CKR_OK) - return ret; - - return ret; -} - -void -cleanup_find_operation(P11cSession* sess) -{ - ASSERT(sess->operation_type == OPERATION_FIND); - if(sess->operation_data) - p11c_array_free((P11cArray*)sess->operation_data, TRUE); - sess->operation_type = OPERATION_NONE; - sess->operation_data = NULL; - sess->operation_cancel = NULL; -} - -void -purge_duplicate_objects(P11cArray* arr) -{ - P11cHash* checks; - CK_OBJECT_HANDLE v; - size_t i; - - checks = p11c_hash_new(NULL, NULL); - if(!checks) - return; - - for(i = 0; i < arr->len; ) - { - v = p11c_array_index(arr, CK_OBJECT_HANDLE, i); - if(p11c_hash_get(checks, p11c_hash_key(v))) - { - p11c_array_remove_index(arr, i); - /* Look at same i again */ - } - else - { - if(!p11c_hash_set(checks, p11c_hash_key(v), arr)) - break; - ++i; - } - } - - p11c_hash_free(checks, NULL); -} - -CK_RV -p11c_session_find_init(P11cSession* sess, CK_ATTRIBUTE_PTR match, - CK_ULONG count) -{ - P11cArray* arr; - CK_RV ret; - - ASSERT(sess); - ASSERT(!count || match); - - if(sess->operation_type != OPERATION_NONE) - return CKR_OPERATION_ACTIVE; - - arr = p11c_array_new(0, 1, sizeof(CK_OBJECT_HANDLE)); - if(!arr) - return CKR_HOST_MEMORY; - - ret = gather_objects(sess, match, count, arr); - if(ret != CKR_OK) - { - p11c_array_free(arr, TRUE); - return ret; - } - - /* Cleanup all duplicates in the array */ - purge_duplicate_objects(arr); - - sess->operation_type = OPERATION_FIND; - sess->operation_data = arr; - sess->operation_cancel = cleanup_find_operation; - - return CKR_OK; -} - -CK_RV -p11c_session_find(P11cSession* sess, CK_OBJECT_HANDLE_PTR objects, - CK_ULONG max_object_count, CK_ULONG_PTR object_count) -{ - P11cArray* arr; - size_t i; - - ASSERT(sess); - ASSERT(object_count); - ASSERT(!max_object_count || objects); - - if(sess->operation_type != OPERATION_FIND) - return CKR_OPERATION_NOT_INITIALIZED; - - if(!max_object_count) - { - *object_count = 0; - return CKR_OK; - } - - arr = (P11cArray*)sess->operation_data; - *object_count = (max_object_count > arr->len ? arr->len : max_object_count); - for(i = 0; i < *object_count; ++i) - objects[i] = p11c_array_index(arr, CK_OBJECT_HANDLE, i); - - p11c_array_remove_range(arr, 0, *object_count); - - return CKR_OK; -} - -CK_RV -p11c_session_find_final(P11cSession* sess) -{ - ASSERT(sess); - - if(sess->operation_type != OPERATION_FIND) - return CKR_OPERATION_NOT_INITIALIZED; - - cleanup_find_operation(sess); - return CKR_OK; -} - - -/* ---------------------------------------------------------------------------- - * CRYPTO OPERATIONS - */ - -typedef struct _CryptoContext -{ - CK_MECHANISM_TYPE mech_type; - P11cDestroyFunc mech_cleanup; - void* mech_data; -} -CryptoContext; - -void -cleanup_crypto_operation(P11cSession* sess) -{ - CryptoContext* ctx; - - if(sess->operation_data) - { - ctx = (CryptoContext*)sess->operation_data; - if(ctx->mech_cleanup) - (ctx->mech_cleanup)(ctx->mech_data); - free(ctx); - } - - sess->operation_type = OPERATION_NONE; - sess->operation_data = NULL; - sess->operation_cancel = NULL; -} - -CK_RV -p11c_session_sign_init(P11cSession* sess, CK_MECHANISM_PTR mech, - P11cObjectData *objdata) -{ - CryptoContext* ctx; - CK_RV ret; - - ASSERT(sess); - ASSERT(mech); - ASSERT(objdata); - - if(sess->operation_type != OPERATION_NONE) - return CKR_OPERATION_ACTIVE; - - ctx = calloc(1, sizeof(CryptoContext)); - if(!ctx) - return CKR_HOST_MEMORY; - - ctx->mech_type = mech->mechanism; - - switch(mech->mechanism) - { - case CKM_RSA_PKCS: - ret = p11c_rsa_pkcs_sign_init(objdata, &ctx->mech_data); - ctx->mech_cleanup = p11c_rsa_pkcs_sign_cleanup; - break; - default: - ret = CKR_MECHANISM_INVALID; - break; - }; - - if(ret != CKR_OK) - { - free(ctx); - ASSERT(!sess->operation_data); - return ret; - } - - sess->operation_type = OPERATION_SIGN; - sess->operation_data = ctx; - sess->operation_cancel = cleanup_crypto_operation; - return CKR_OK; -} - -CK_RV -p11c_session_sign(P11cSession* sess, CK_BYTE_PTR data, CK_ULONG n_data, - CK_BYTE_PTR signature, CK_ULONG_PTR n_signature) -{ - CryptoContext *ctx; - BOOL incomplete; - CK_RV ret; - - ASSERT(sess); - ASSERT(data); - ASSERT(n_data); - - if(sess->operation_type != OPERATION_SIGN) - return CKR_OPERATION_NOT_INITIALIZED; - - ctx = (CryptoContext*)sess->operation_data; - switch(ctx->mech_type) - { - case CKM_RSA_PKCS: - ret = p11c_rsa_pkcs_sign_perform(data, n_data, signature, n_signature, - &ctx->mech_data); - break; - - default: - ASSERT(FALSE); - ret = CKR_GENERAL_ERROR; - break; - } - - /* Buffer calculation, we don't end operation */ - incomplete = (ret == CKR_BUFFER_TOO_SMALL || (ret == CKR_OK && !signature)); - - if(!incomplete) - cleanup_crypto_operation(sess); - - return ret; -} - -CK_RV -p11c_session_decrypt_init(P11cSession* sess, CK_MECHANISM_PTR mech, - P11cObjectData *objdata) -{ - CryptoContext* ctx; - CK_RV ret; - - ASSERT(sess); - ASSERT(mech); - ASSERT(objdata); - - if(sess->operation_type != OPERATION_NONE) - return CKR_OPERATION_ACTIVE; - - ctx = calloc(1, sizeof(CryptoContext)); - if(!ctx) - return CKR_HOST_MEMORY; - - ctx->mech_type = mech->mechanism; - - switch(mech->mechanism) - { - case CKM_RSA_PKCS: - ret = p11c_rsa_pkcs_decrypt_init(objdata, &ctx->mech_data); - ctx->mech_cleanup = p11c_rsa_pkcs_decrypt_cleanup; - break; - default: - ret = CKR_MECHANISM_INVALID; - break; - }; - - if(ret != CKR_OK) - { - free(ctx); - ASSERT(!sess->operation_data); - return ret; - } - - sess->operation_type = OPERATION_DECRYPT; - sess->operation_data = ctx; - sess->operation_cancel = cleanup_crypto_operation; - return CKR_OK; -} - -CK_RV -p11c_session_decrypt(P11cSession* sess, CK_BYTE_PTR encdata, CK_ULONG n_encdata, - CK_BYTE_PTR result, CK_ULONG_PTR n_result) -{ - CryptoContext *ctx; - BOOL incomplete; - CK_RV ret; - - ASSERT(sess); - ASSERT(encdata); - ASSERT(n_encdata); - - if(sess->operation_type != OPERATION_DECRYPT) - return CKR_OPERATION_NOT_INITIALIZED; - - ctx = (CryptoContext*)sess->operation_data; - switch(ctx->mech_type) - { - case CKM_RSA_PKCS: - ret = p11c_rsa_pkcs_decrypt_perform(encdata, n_encdata, result, n_result, - &ctx->mech_data); - break; - - default: - ASSERT(FALSE); - ret = CKR_GENERAL_ERROR; - break; - } - - /* Buffer calculation, we don't end operation */ - incomplete = (ret == CKR_BUFFER_TOO_SMALL || (ret == CKR_OK && !result)); - - if(!incomplete) - cleanup_crypto_operation(sess); - - return ret; -} diff --git a/p11-capi-session.h b/p11-capi-session.h deleted file mode 100644 index 8f84026..0000000 --- a/p11-capi-session.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef P11C_SESSION_H -#define P11C_SESSION_H - -#include "p11-capi.h" - -/* -------------------------------------------------------------------- - * - * Session = P11cSession - * - A PKCS#11 Session - * - * Objects = P11cObject - * - There's a global list of objects in p11c-object.c indexed by - * object handle. - * - The object itself has no attributes or cached data, but knows how - * to load data when needed. - * - Each object has a unique key which guarantees we don't load the - * same object twice with two different object handles. - * - * Object Data = P11cObjectData - * - Object Data is owned by the Session - * - Loaded data and/or attributes for an object. - */ - -/* Callback to cleanup a current operation */ -typedef void (*P11cSessionCancel) (struct _P11cSession* sess); - -/* Represents an open session */ -typedef struct _P11cSession -{ - CK_SESSION_HANDLE id; /* Unique ID for this session */ - CK_SLOT_ID slot; - int in_call; /* Whether this session is use in PKCS#11 function */ - - HCERTSTORE store; /* Handle to an open certificate store */ - - BOOL read_write; /* A read-write session? */ - - int operation_type; /* Whether an operation is happening or not */ - void* operation_data; /* Data for this operation */ - P11cSessionCancel operation_cancel; /* Callback to cancel operation when necessary */ - - P11cHash* object_data; - - CK_NOTIFY notify_callback; /* Application specified callback */ - CK_VOID_PTR user_data; /* Argument for above */ - - int refs; /* Reference count */ - HANDLE mutex; /* Mutex for protecting this structure */ -} -P11cSession; - -/* Debug print something related to a session */ -#define DBGS(sess, msg) \ - p11c_debug("S%d: %s", (sess) ? (sess)->id : 0, (msg)) - -/* Create a session */ -CK_RV p11c_session_create (CK_SLOT_ID slot, P11cSession** ret); - -/* Destroy a session */ -void p11c_session_destroy (P11cSession* sess); - -/* Register a new session */ -CK_RV p11c_session_register (P11cSession* sess); - -/* Get information about a session */ -void p11c_session_get_info (P11cSession* sess, - CK_SESSION_INFO_PTR info); - -/* Get a session from a handle, and lock it */ -CK_RV p11c_session_get_lock_ref (CK_ULONG id, BOOL writable, - P11cSession **sess); - -/* Get a session from a handle, remove it from list, and lock it */ -CK_RV p11c_session_remove_lock_ref (CK_ULONG id, P11cSession **sess); - -/* Unlock and unreference a session */ -void p11c_session_unref_unlock (P11cSession* sess); - -/* Close all sessions on a certain slot/token */ -CK_RV p11c_session_close_all (CK_SLOT_ID slot); - - - -/* Start a find operation on a session */ -CK_RV p11c_session_find_init (P11cSession* sess, - CK_ATTRIBUTE_PTR templ, - CK_ULONG count); - -/* Return results from a find operation */ -CK_RV p11c_session_find (P11cSession* sess, - CK_OBJECT_HANDLE_PTR objects, - CK_ULONG max_object_count, - CK_ULONG_PTR object_count); - -/* End a find operation */ -CK_RV p11c_session_find_final (P11cSession* sess); - - -/* Start a sign operation on a session */ -CK_RV p11c_session_sign_init (P11cSession* sess, - CK_MECHANISM_PTR mech, - P11cObjectData *objdata); - -/* Perform sign operation */ -CK_RV p11c_session_sign (P11cSession* sess, - CK_BYTE_PTR data, CK_ULONG n_data, - CK_BYTE_PTR sig, CK_ULONG_PTR n_sig); - -/* Start a decrypt operation on a session */ -CK_RV p11c_session_decrypt_init (P11cSession* sess, - CK_MECHANISM_PTR mech, - P11cObjectData *objdata); - -/* Perform decrypt operation */ -CK_RV p11c_session_decrypt (P11cSession* sess, - CK_BYTE_PTR encdata, CK_ULONG n_encdata, - CK_BYTE_PTR result, CK_ULONG_PTR n_result); - -/* Get object data for an object */ -CK_RV p11c_session_get_object_data (P11cSession* sess, - P11cObject* obj, - P11cObjectData** objdata); - -/* Get object data for an object handle */ -CK_RV p11c_session_get_object_data_for (P11cSession* sess, - CK_OBJECT_HANDLE hand, - P11cObjectData** objdata); - -/* Set object data for an object */ -void p11c_session_take_object_data (P11cSession* sess, - P11cObject* obj, - P11cObjectData* objdata); - -/* Clear object data for an object */ -void p11c_session_clear_object_data (P11cSession* sess, - P11cObject* obj); - -/* Enumerate object data for all objects */ -typedef void (*P11cEnumObjectData) (P11cSession* sess, - P11cObject* obj, - P11cObjectData* data, - void* arg); - -void p11c_session_enum_object_data (P11cSession* sess, - P11cEnumObjectData enum_func, - void* arg); - -void p11c_session_cleanup_all (void); - -#endif /* P11C_SESSION_H */ diff --git a/p11-capi-token.c b/p11-capi-token.c deleted file mode 100644 index f6ef2ca..0000000 --- a/p11-capi-token.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "p11-capi.h" -#include "p11-capi-object.h" -#include "p11-capi-token.h" - -static P11cArray* object_array = NULL; -static P11cHash* object_hash = NULL; -static P11cArray* logged_in_slots = NULL; - -typedef struct _SlotInfo -{ - const char* capi_store; - const char* display_name; - CK_ULONG slot_flags; -} -SlotInfo; - -#define SLOT_OFFSET 0x00001000 - -static SlotInfo slot_info[] = { - { "My", "Personal Certificates", P11C_SLOT_TRUSTED | P11C_SLOT_CERTS }, - { "AddressBook", "Address Book Certificates", P11C_SLOT_CERTS }, - { "CA", "Certificate Authorities", P11C_SLOT_CA | P11C_SLOT_CERTS }, - { "Root", "Root Authorities", P11C_SLOT_TRUSTED | P11C_SLOT_CA | P11C_SLOT_CERTS }, - { "Trust", "Trust", P11C_SLOT_CERTS }, - { "TrustedPeople", "Trusted People", P11C_SLOT_TRUSTED | P11C_SLOT_CERTS }, - { "AuthRoot", "Auth Root", P11C_SLOT_CERTS }, - { NULL, "All User Keys", P11C_SLOT_ANYKEY } -}; - -#define SLOT_TO_OFFSET(slot) \ - ((slot) & ~(SLOT_OFFSET)) - -#define OFFSET_TO_SLOT(offset) \ - ((offset) | SLOT_OFFSET) - -unsigned int -p11c_token_get_count(void) -{ - return sizeof(slot_info) / sizeof(slot_info[0]); -} - -CK_SLOT_ID -p11c_token_get_slot_id(unsigned int offset) -{ - ASSERT(offset < p11c_token_get_count()); - return OFFSET_TO_SLOT(offset); -} - -CK_BBOOL -p11c_token_is_valid(CK_SLOT_ID slot) -{ - unsigned int offset = SLOT_TO_OFFSET(slot); - return offset >= 0 && offset < p11c_token_get_count(); -} - -const char* -p11c_token_get_display_name(CK_SLOT_ID slot) -{ - unsigned int offset = SLOT_TO_OFFSET(slot); - ASSERT(p11c_token_is_valid(slot)); - ASSERT(slot_info[offset].display_name); - return slot_info[offset].display_name; -} - -const char* -p11c_token_get_store_name(CK_SLOT_ID slot) -{ - unsigned int offset = SLOT_TO_OFFSET(slot); - ASSERT(p11c_token_is_valid(slot)); - return slot_info[offset].capi_store; -} - -CK_ULONG -p11c_token_get_flags(CK_SLOT_ID slot) -{ - unsigned int offset = SLOT_TO_OFFSET(slot); - ASSERT(p11c_token_is_valid(slot)); - return slot_info[offset].slot_flags; -} - -static void -object_free(P11cObject* obj) -{ - ASSERT(obj); - ASSERT(obj->obj_funcs); - ASSERT(obj->obj_funcs->release); - (obj->obj_funcs->release)(obj); -} - -void -p11c_token_cleanup_all(void) -{ - size_t i; - - p11c_lock_global(); - - if(object_hash) - { - p11c_hash_free(object_hash, NULL); - object_hash = NULL; - } - - if(object_array) - { - for(i = 1; i < object_array->len; ++i) - { - ASSERT(p11c_array_index(object_array, P11cObject*, i)); - object_free(p11c_array_index(object_array, P11cObject*, i)); - } - - p11c_array_free(object_array, TRUE); - object_array = NULL; - } - - if(logged_in_slots) - { - p11c_array_free(logged_in_slots, TRUE); - logged_in_slots = NULL; - } - - p11c_unlock_global(); -} - -CK_OBJECT_HANDLE -p11c_token_get_max_handle(void) -{ - if(!object_array) - return 0; - return object_array->len; -} - -P11cObject* -p11c_token_lookup_object(CK_SLOT_ID slot, CK_OBJECT_HANDLE obj) -{ - /* This must be called without any locks held */ - - P11cObject* ret = NULL; - - ASSERT(slot); - ASSERT(obj > 0); - - p11c_lock_global(); - - if(object_array && obj < object_array->len) - ret = p11c_array_index(object_array, P11cObject*, obj); - - p11c_unlock_global(); - - /* Must belong to the right slot */ - if(ret && ret->slot != slot) - ret = NULL; - - return ret; -} - -static unsigned int -object_hash_func(const void* a) -{ - P11cObject* obj = (P11cObject*)a; - unsigned int hash = p11c_hash_pointer(obj->obj_funcs); - hash ^= (obj->obj_funcs->hash_object)(obj); - return hash; -} - -static int -object_equal_func(const void* a, const void* b) -{ - P11cObject* ca = (P11cObject*)a; - P11cObject* cb = (P11cObject*)b; - if(ca == cb) - return 1; - if(ca->obj_funcs != cb->obj_funcs) - return 0; - return (ca->obj_funcs->equal_object)(ca, cb); -} - -CK_RV -p11c_token_register_object(CK_SLOT_ID slot, P11cObject* obj) -{ - P11cObject* prev; - CK_RV ret = CKR_OK; - - ASSERT(slot); - ASSERT(obj->id == 0); - - DBG(("registering object")); - - p11c_lock_global(); - - if(!object_array) - { - object_array = p11c_array_sized_new(0, 1, sizeof(P11cObject*), 16); - if(object_array) - { - /* A blank entry for '0' */ - P11cObject* blank = NULL; - p11c_array_append(object_array, blank); - } - - object_hash = p11c_hash_new(object_hash_func, object_equal_func); - - if(!object_array || !object_hash) - { - /* Allocation failed above */ - ret = CKR_HOST_MEMORY; - } - } - - if(ret == CKR_OK) - { - ASSERT(object_array); - ASSERT(object_hash); - - /* Look in the hash and find a previous object */ - prev = p11c_hash_get(object_hash, obj); - if(prev) - { - /* Register it in the previous object's place */ - obj->id = prev->id; - ASSERT(prev->id < object_array->len); - if(p11c_hash_set(object_hash, obj, obj)) - { - p11c_array_index(object_array, P11cObject*, obj->id) = obj; - object_free(prev); - DBGO(obj, "found old object id"); - } - else - { - ret = CKR_HOST_MEMORY; - } - } - else - { - /* Register it at the end of the array */ - obj->id = object_array->len; - ASSERT(obj->id > 0); - if(p11c_hash_set(object_hash, obj, obj)) - { - if(p11c_array_append(object_array, obj)) - { - DBGO(obj, "registered new object id"); - } - else - { - ret = CKR_HOST_MEMORY; - - /* Roll back our addition */ - p11c_hash_rem(object_hash, obj); - } - } - else - { - ret = CKR_HOST_MEMORY; - } - } - } - - if(ret == CKR_OK) - obj->slot = slot; - - p11c_unlock_global(); - - return ret; - -} - -CK_BBOOL -p11c_token_is_logged_in(CK_SLOT_ID slot) -{ - unsigned int count, offset; - - ASSERT(p11c_token_is_valid(slot)); - - if(!logged_in_slots) - return CK_FALSE; - - offset = SLOT_TO_OFFSET(slot); - count = p11c_token_get_count(); - - ASSERT(logged_in_slots->len == count && offset < count); - return p11c_array_index(logged_in_slots, CK_BBOOL, offset); -} - -CK_RV -p11c_token_login(CK_SLOT_ID slot) -{ - unsigned int i, count; - unsigned int offset; - CK_BBOOL value; - - ASSERT(p11c_token_is_valid(slot)); - - offset = SLOT_TO_OFFSET(slot); - count = p11c_token_get_count(); - - if(!logged_in_slots) - { - logged_in_slots = p11c_array_sized_new(0, 1, sizeof(CK_BBOOL), count); - if(!logged_in_slots) - return CKR_HOST_MEMORY; - - value = CK_FALSE; - for(i = 0; i < count; ++i) - p11c_array_append(logged_in_slots, value); - - } - - ASSERT(logged_in_slots->len == count && offset < count); - if(p11c_array_index(logged_in_slots, CK_BBOOL, offset)) - return CKR_USER_ALREADY_LOGGED_IN; - - p11c_array_index(logged_in_slots, CK_BBOOL, offset) = CK_TRUE; - return CKR_OK; -} - -CK_RV -p11c_token_logout(CK_SLOT_ID slot) -{ - unsigned int count, offset; - - ASSERT(p11c_token_is_valid(slot)); - - if(!logged_in_slots) - return CKR_USER_NOT_LOGGED_IN; - - offset = SLOT_TO_OFFSET(slot); - count = p11c_token_get_count(); - - ASSERT(logged_in_slots->len == count && offset < count); - if(!p11c_array_index(logged_in_slots, CK_BBOOL, offset)) - return CKR_USER_NOT_LOGGED_IN; - - p11c_array_index(logged_in_slots, CK_BBOOL, offset) = CK_FALSE; - return CKR_OK; -} diff --git a/p11-capi-token.h b/p11-capi-token.h deleted file mode 100644 index e97f547..0000000 --- a/p11-capi-token.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef P11C_TOKEN_H -#define P11C_TOKEN_H - -#include "p11-capi.h" - -#define P11C_SLOT_CERTS 0x00000001 -#define P11C_SLOT_ANYKEY 0x00000002 -#define P11C_SLOT_CA 0x00000100 -#define P11C_SLOT_TRUSTED 0x00000200 - -/* Register a new object, a handle will be assigned to obj->id */ -CK_RV p11c_token_register_object (CK_SLOT_ID slot, P11cObject* obj); - -/* Lookup an object for a given object handle */ -P11cObject* p11c_token_lookup_object (CK_SLOT_ID slot, CK_OBJECT_HANDLE obj); - -/* Clear all objects for all tokens. Only done when finalizing */ -void p11c_token_cleanup_all (void); - -/* Get the number of the maximum object handle currently in memory */ -CK_OBJECT_HANDLE p11c_token_get_max_handle (void); - -unsigned int p11c_token_get_count (void); - -CK_SLOT_ID p11c_token_get_slot_id (unsigned int index); - -CK_BBOOL p11c_token_is_valid (CK_SLOT_ID slot); - -const char* p11c_token_get_display_name (CK_SLOT_ID slot); - -const char* p11c_token_get_store_name (CK_SLOT_ID slot); - -CK_ULONG p11c_token_get_flags (CK_SLOT_ID slot); - -CK_RV p11c_token_login (CK_SLOT_ID slot); - -CK_RV p11c_token_logout (CK_SLOT_ID slot); - -CK_BBOOL p11c_token_is_logged_in (CK_SLOT_ID slot); - -#endif /* P11C_TOKEN_H */ diff --git a/p11-capi-trust.c b/p11-capi-trust.c deleted file mode 100644 index e45106a..0000000 --- a/p11-capi-trust.c +++ /dev/null @@ -1,569 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "p11-capi.h" -#include "p11-capi-cert.h" -#include "p11-capi-object.h" -#include "p11-capi-session.h" -#include "p11-capi-token.h" -#include "p11-capi-trust.h" -#include "x509-usages.h" - -#include "pkcs11/pkcs11n.h" - -/* - * These are the attributes expected by NSS on a trust object: - * - * CKA_CLASS - * CKA_TOKEN - * CKA_LABEL - * CKA_CERT_SHA1_HASH - * CKA_CERT_MD5_HASH - * CKA_ISSUER - * CKA_SUBJECT - * CKA_TRUST_SERVER_AUTH - * CKA_TRUST_CLIENT_AUTH - * CKA_TRUST_EMAIL_PROTECTION - * CKA_TRUST_CODE_SIGNING - * CKA_SERIAL_NUMBER - */ - -typedef struct _TrustObject -{ - P11cObject obj; - CK_OBJECT_HANDLE cert_obj; -} -TrustObject; - -typedef struct _TrustObjectData -{ - P11cObjectData base; - - PCCERT_CONTEXT cert; - CERT_ENHKEY_USAGE* enhanced_usage; - - BOOL has_usage; - BYTE usage; -} -TrustObjectData; - -static CK_TRUST -has_usage(TrustObjectData* tdata, BYTE restriction) -{ - if(!tdata->has_usage) - CKT_NETSCAPE_TRUST_UNKNOWN; - if((tdata->usage & restriction) == restriction) - return CKT_NETSCAPE_TRUSTED; - return CKT_NETSCAPE_UNTRUSTED; - -} - -static CK_TRUST -has_enhanced_usage(TrustObjectData* tdata, const char* oid) -{ - CERT_ENHKEY_USAGE* eusage = tdata->enhanced_usage; - DWORD i; - - /* No usages, means anything goes */ - if(eusage == NULL) - return CKT_NETSCAPE_TRUSTED_DELEGATOR; - - for(i = 0; i < eusage->cUsageIdentifier; ++i) - { - if(eusage->rgpszUsageIdentifier[i] && - strcmp(oid, eusage->rgpszUsageIdentifier[i]) == 0) - return CKT_NETSCAPE_TRUSTED_DELEGATOR; - } - - return CKT_NETSCAPE_TRUST_UNKNOWN; -} - -static CK_RV -trust_bool_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) -{ - CK_BBOOL val; - - ASSERT(objdata); - ASSERT(attr); - - switch(attr->type) - { - /* - * Resides on the token - * - Always true for CAPI objects. - */ - case CKA_TOKEN: - val = CK_TRUE; - break; - - /* - * Private vs. Public object. - * - Always false for certificates. - */ - case CKA_PRIVATE: - val = CK_FALSE; - break; - - /* - * If object can be modified. - */ - case CKA_MODIFIABLE: - val = CK_TRUE; - break; - - /* - * TODO: Figure out what this is. - */ - case CKA_TRUST_STEP_UP_APPROVED: - val = CK_FALSE; - break; - - default: - return CKR_ATTRIBUTE_TYPE_INVALID; - }; - - return p11c_return_data(attr, &val, sizeof(CK_BBOOL)); -} - -static CK_RV -trust_ulong_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) -{ - TrustObjectData* tdata = (TrustObjectData*)objdata; - CK_ULONG val; - - ASSERT(tdata); - ASSERT(attr); - - switch(attr->type) - { - - /* - * Object class. - * - Always CKO_NETSCAPE_TRUST for netscape trust - */ - case CKA_CLASS: - val = CKO_NETSCAPE_TRUST; - break; - - /* - * Key restrictions - */ - case CKA_TRUST_DIGITAL_SIGNATURE: - val = has_usage(tdata, CERT_DIGITAL_SIGNATURE_KEY_USAGE); - break; - case CKA_TRUST_NON_REPUDIATION: - val = has_usage(tdata, CERT_NON_REPUDIATION_KEY_USAGE); - break; - case CKA_TRUST_KEY_ENCIPHERMENT: - val = has_usage(tdata, CERT_KEY_ENCIPHERMENT_KEY_USAGE); - break; - case CKA_TRUST_DATA_ENCIPHERMENT: - val = has_usage(tdata, CERT_DATA_ENCIPHERMENT_KEY_USAGE); - break; - case CKA_TRUST_KEY_AGREEMENT: - val = has_usage(tdata, CERT_KEY_AGREEMENT_KEY_USAGE); - break; - case CKA_TRUST_KEY_CERT_SIGN: - val = has_usage(tdata, CERT_KEY_CERT_SIGN_KEY_USAGE); - break; - case CKA_TRUST_CRL_SIGN: - val = has_usage(tdata, CERT_CRL_SIGN_KEY_USAGE); - break; - - /* - * Various trust flags - */ - case CKA_TRUST_SERVER_AUTH: - val = has_enhanced_usage(tdata, X509_USAGE_SERVER_AUTH); - break; - case CKA_TRUST_CLIENT_AUTH: - val = has_enhanced_usage(tdata, X509_USAGE_CLIENT_AUTH); - break; - case CKA_TRUST_CODE_SIGNING: - val = has_enhanced_usage(tdata, X509_USAGE_CODE_SIGNING); - break; - case CKA_TRUST_EMAIL_PROTECTION: - val = has_enhanced_usage(tdata, X509_USAGE_EMAIL); - break; - case CKA_TRUST_IPSEC_END_SYSTEM: - val = has_enhanced_usage(tdata, X509_USAGE_IPSEC_ENDPOINT); - break; - case CKA_TRUST_IPSEC_TUNNEL: - val = has_enhanced_usage(tdata, X509_USAGE_IPSEC_TUNNEL); - break; - case CKA_TRUST_IPSEC_USER: - val = has_enhanced_usage(tdata, X509_USAGE_IPSEC_USER); - break; - case CKA_TRUST_TIME_STAMPING: - val = has_enhanced_usage(tdata, X509_USAGE_TIME_STAMPING); - break; - - default: - return CKR_ATTRIBUTE_TYPE_INVALID; - }; - - return p11c_return_data(attr, &val, sizeof(CK_ULONG)); -} - -static CK_RV -trust_bytes_attribute(P11cObjectData* objdata, CK_ATTRIBUTE_PTR attr) -{ - TrustObjectData* tdata = (TrustObjectData*)objdata; - - ASSERT(tdata); - ASSERT(attr); - - switch(attr->type) - { - /* - * Forward these through to the certificate itself. - */ - case CKA_SUBJECT: - case CKA_ISSUER: - case CKA_SERIAL_NUMBER: - case CKA_LABEL: - ASSERT(tdata->cert); - return p11c_cert_certificate_get_bytes(tdata->cert, attr); - - /* - * The hash of the DER encoded certificate. - */ - case CKA_CERT_MD5_HASH: - case CKA_CERT_SHA1_HASH: - if(!CryptHashCertificate(0, attr->type == CKA_CERT_MD5_HASH ? CALG_MD5 : CALG_SHA1, - 0, tdata->cert->pbCertEncoded, - tdata->cert->cbCertEncoded, attr->pValue, - (DWORD*)(&attr->ulValueLen))) - return p11c_winerr_to_ckr(GetLastError()); - return CKR_OK; - }; - - return CKR_ATTRIBUTE_TYPE_INVALID; -} - -static unsigned int -trust_hash_func(P11cObject* obj) -{ - return p11c_hash_integer(((TrustObject*)obj)->cert_obj); -} - -static int -trust_equal_func(P11cObject* a, P11cObject* b) -{ - return ((TrustObject*)a)->cert_obj == ((TrustObject*)b)->cert_obj; -} - -static void -trust_release(void* data) -{ - TrustObjectData* tdata = (TrustObjectData*)data; - ASSERT(tdata); - - ASSERT(tdata->cert); - CertFreeCertificateContext(tdata->cert); - - if(tdata->enhanced_usage) - free(tdata->enhanced_usage); - - free(tdata); -} - -static const P11cObjectDataVtable trust_objdata_vtable = { - trust_bool_attribute, - trust_ulong_attribute, - trust_bytes_attribute, - trust_release, -}; - -static CK_RV -parse_usage(TrustObjectData* tdata, DWORD flags) -{ - DWORD size, err; - CERT_ENHKEY_USAGE* eusage; - - ASSERT(!tdata->enhanced_usage); - - /* Get the size of the enhanced_usage */ - if(!CertGetEnhancedKeyUsage(tdata->cert, flags, NULL, &size)) - { - err = GetLastError(); - - /* No enhanced_usage data is not an error */ - if(err == CRYPT_E_NOT_FOUND) - return CKR_OK; - return p11c_winerr_to_ckr(err); - } - - eusage = (CERT_ENHKEY_USAGE*)calloc(1, size); - if(!eusage) - return CKR_HOST_MEMORY; - - /* Now get the actual enhanced usage property */ - if(!CertGetEnhancedKeyUsage(tdata->cert, flags, eusage, &size)) - { - err = GetLastError(); - if(err == CRYPT_E_NOT_FOUND) - return CKR_OK; - return p11c_winerr_to_ckr(err); - } - - tdata->enhanced_usage = eusage; - return CKR_OK; -} - -static CK_RV -parse_restrictions(TrustObjectData* tdata) -{ - CRYPT_BIT_BLOB* rst; - CERT_EXTENSION* ext; - DWORD size; - - ASSERT(tdata); - ASSERT(tdata->cert); - - tdata->has_usage = CK_FALSE; - tdata->usage = 0x00; - - ext = CertFindExtension(szOID_KEY_USAGE, - tdata->cert->pCertInfo->cExtension, - tdata->cert->pCertInfo->rgExtension); - - /* No key usage, don't care */ - if(!ext) - return CKR_OK; - - /* Find the size of the decoded structure */ - if(!CryptDecodeObject(P11c_ENCODINGS, X509_KEY_USAGE, - ext->Value.pbData, ext->Value.cbData, 0, NULL, &size)) - return p11c_winerr_to_ckr(GetLastError()); - - /* Allocate enough memory */ - rst = (CRYPT_BIT_BLOB*)calloc(1, size); - if(!rst) - return CKR_HOST_MEMORY; - - /* And get the decoded structure */ - if(CryptDecodeObject(P11c_ENCODINGS, X509_KEY_USAGE, - ext->Value.pbData, ext->Value.cbData, 0, rst, &size)) - { - if(rst->cbData != 1 && - rst->cUnusedBits != 0) - { - DBG(("key usage are of invalid size")); - } - else - { - /* A valid byte of key restricted usage flags. Yes all that for one byte */ - tdata->usage = *((BYTE*)(rst->pbData)); - tdata->has_usage = TRUE; - } - } - - free(rst); - return CKR_OK; -} - -static CK_RV -trust_load_data(P11cSession* sess, P11cObject* obj, P11cObjectData** objdata) -{ - TrustObject* tobj = (TrustObject*)obj; - TrustObjectData* tdata; - P11cObjectData* certdata; - CK_RV ret; - - ASSERT(tobj); - ASSERT(objdata); - - /* Get the raw data for the certificate */ - ret = p11c_session_get_object_data_for(sess, tobj->cert_obj, &certdata); - if(ret != CKR_OK) - return ret; - - tdata = (TrustObjectData*)calloc(1, sizeof(TrustObjectData)); - if(!tdata) - return CKR_HOST_MEMORY; - - tdata->cert = p11c_cert_object_data_get_certificate (certdata); - ASSERT(tdata->cert); - - /* Dig up the restrictions data extension */ - ret = parse_restrictions(tdata); - if(ret != CKR_OK) - { - free(tdata); - return ret; - } - - /* Dig up the enhanced usage data property, and then try the extension */ - ret = parse_usage(tdata, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG); - if(ret == CKR_OK && !tdata->enhanced_usage) - ret = parse_usage(tdata, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG); - - if(ret != CKR_OK) - { - free(tdata); - return ret; - } - - /* And keep a reference to the certificate */ - tdata->cert = CertDuplicateCertificateContext(tdata->cert); - - tdata->base.object = obj->id; - tdata->base.data_funcs = &trust_objdata_vtable; - - *objdata = &(tdata->base); - return CKR_OK; -} - - -static void -trust_object_release(void* data) -{ - TrustObject* tobj = (TrustObject*)data; - ASSERT(tobj); - free(tobj); -} - -static const P11cObjectVtable trust_object_vtable = { - trust_load_data, - trust_hash_func, - trust_equal_func, - trust_object_release, -}; - -static CK_RV -register_trust_object(P11cSession* sess, P11cObject* cert, P11cObject** obj) -{ - TrustObject* tobj; - CK_RV ret; - - tobj = calloc(1, sizeof(TrustObject)); - if(!tobj) - return CKR_HOST_MEMORY; - - tobj->cert_obj = cert->id; - - tobj->obj.id = 0; - tobj->obj.obj_funcs = &trust_object_vtable; - - ret = p11c_token_register_object(sess->slot, &(tobj->obj)); - if(ret != CKR_OK) - { - free(tobj); - return ret; - } - - ASSERT(tobj->obj.id != 0); - *obj = &(tobj->obj); - - return CKR_OK; -} - -static CK_RV -list_matching_certificates(P11cSession* sess, CK_ATTRIBUTE_PTR match, - CK_ULONG count, P11cArray* arr) -{ - CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; - CK_ATTRIBUTE search[3]; - CK_ULONG n_search = 0; - CK_ULONG i; - - /* The class */ - search[0].type = CKA_CLASS; - search[0].pValue = &cert_class; - search[0].ulValueLen = sizeof(CK_OBJECT_CLASS); - ++n_search; - - for(i = 0; i < count && n_search < 3; ++i) - { - /* - * These are the attributes that tie a certificate - * to trust object, so try match certs with these - */ - if(match[i].type == CKA_ISSUER || - match[i].type == CKA_SERIAL_NUMBER) - { - search[n_search].type = match[i].type; - search[n_search].pValue = match[i].pValue; - search[n_search].ulValueLen = match[i].ulValueLen; - ++n_search; - } - } - - /* Do the certificate search */ - return p11c_cert_find(sess, CKO_CERTIFICATE, search, n_search, arr); -} - -CK_RV -p11c_trust_find(P11cSession* sess, CK_OBJECT_CLASS cls, - CK_ATTRIBUTE_PTR match, CK_ULONG count, P11cArray* arr) -{ - CK_OBJECT_HANDLE id; - P11cObject* obj; - P11cObject* certobj; - P11cObjectData* objdata; - P11cArray* certarr; - CK_RV ret = CKR_OK; - CK_ULONG i; - - /* We only have trust objects in here */ - if(cls != CKO_NETSCAPE_TRUST && cls != CKO_ANY) - return CKR_OK; - - /* Only work with slots that have certificates */ - if(!(p11c_token_get_flags (sess->slot) & P11C_SLOT_CERTS)) - return CKR_OK; - - /* Get a list of all certificates */ - certarr = p11c_array_new(0, 1, sizeof(CK_OBJECT_HANDLE)); - if(!certarr) - return CKR_HOST_MEMORY; - ret = list_matching_certificates(sess, match, count, certarr); - - /* Now match each of them against our criteria */ - if(ret == CKR_OK) - { - for(i = 0; i < certarr->len; ++i) - { - id = p11c_array_index(certarr, CK_OBJECT_HANDLE, i); - ASSERT(id); - - certobj = p11c_token_lookup_object(sess->slot, id); - ASSERT(certobj); - - /* We'll register a trust object for any loaded certificate */ - ret = register_trust_object(sess, certobj, &obj); - if(ret != CKR_OK) - break; - - ASSERT(obj); - - ret = p11c_session_get_object_data(sess, obj, &objdata); - if(ret != CKR_OK) - break; - - /* Only return new object if it matches */ - if(p11c_object_data_match(objdata, match, count)) - p11c_array_append(arr, obj->id); - } - } - - p11c_array_free(certarr, TRUE); - return ret; -} diff --git a/p11-capi-trust.h b/p11-capi-trust.h deleted file mode 100644 index 639f2eb..0000000 --- a/p11-capi-trust.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef P11C_TRUST_H -#define P11C_TRUST_H - -#include "p11-capi.h" - -/* Find trust objects matching criteria */ -CK_RV p11c_trust_find (P11cSession* sess, CK_OBJECT_CLASS cls, - CK_ATTRIBUTE_PTR match, CK_ULONG count, - P11cArray* arr); - -#endif /* P11C_TRUST_H */ diff --git a/p11-capi-util.c b/p11-capi-util.c deleted file mode 100644 index 5ebb72b..0000000 --- a/p11-capi-util.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "p11-capi-util.h" - -#include -#include -#include - - -void -p11c_reverse_memory (void* data, size_t length) -{ - size_t end = length - 1; - size_t middle = length / 2; - unsigned char* buf = data; - size_t i; - - for (i = 0; i < middle; i++) - { - unsigned char tmp = buf[i]; - buf[i] = buf[end - i]; - buf[end - i] = tmp; - } -} - -/* - * Array code originially from Glib. - * Modified extensively by Stef Walter - */ - -/* GLIB - Library of useful routines for C programming - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#define MIN_ARRAY_SIZE 16 - -typedef struct _RealArray -{ - P11cArray pub; - size_t alloc; - size_t elt_size; - int zero_terminated : 1; - int clear : 1; -} -RealArray; - -#define array_elt_len(array, i) ((array)->elt_size * (i)) -#define array_elt_pos(array, i) (((char*)(array)->pub.data) + array_elt_len((array),(i))) -#define array_elt_zero(array, pos, len) \ - (memset(array_elt_pos((array), pos), 0, array_elt_len((array), len))) -#define array_zero_terminate(array) \ - { if ((array)->zero_terminated) \ - array_elt_zero((array), (array)->pub.len, 1); } - -static unsigned int -nearest_pow(unsigned int num) -{ - unsigned int n = 1; - while(n < num) - n <<= 1; - return n; -} - -static int -maybe_expand(RealArray *array, size_t len) -{ - void* mem; - size_t want_alloc = array_elt_len(array, array->pub.len + len + - array->zero_terminated); - - if(want_alloc > array->alloc) - { - want_alloc = nearest_pow(want_alloc); - want_alloc = want_alloc > MIN_ARRAY_SIZE ? want_alloc : MIN_ARRAY_SIZE; - - mem = realloc(array->pub.data, want_alloc); - if(!mem) - return 0; - array->pub.data = mem; - - memset((char*)array->pub.data + array->alloc, 0, want_alloc - array->alloc); - array->alloc = want_alloc; - } - - return 1; -} - -P11cArray* -p11c_array_new(int zero_terminated, int clear, size_t elt_size) -{ - return p11c_array_sized_new(zero_terminated, clear, elt_size, 0); -} - -P11cArray* -p11c_array_sized_new(int zero_terminated, int clear, size_t elt_size, - size_t reserved_size) -{ - RealArray *array = malloc(sizeof(RealArray)); - if(!array) - return NULL; - - array->pub.data = NULL; - array->pub.len = 0; - array->alloc = 0; - array->zero_terminated = (zero_terminated ? 1 : 0); - array->clear = (clear ? 1 : 0); - array->elt_size = elt_size; - - if(array->zero_terminated || reserved_size != 0) - { - maybe_expand(array, reserved_size); - array_zero_terminate(array); - } - - return (P11cArray*)array; -} - -void* -p11c_array_free(P11cArray* array, int free_segment) -{ - void* segment; - - if(array == NULL) - return NULL; - - if(free_segment) - { - if(array->data) - free(array->data); - segment = NULL; - } - else - segment = array->data; - - free(array); - return segment; -} - -int -p11c_array_append_vals(P11cArray* parray, const void* data, size_t len) -{ - RealArray* array = (RealArray*)parray; - if(!maybe_expand(array, len)) - return 0; - - memcpy(array_elt_pos(array, array->pub.len), data, - array_elt_len(array, len)); - - array->pub.len += len; - array_zero_terminate(array); - - return 1; -} - -void -p11c_array_remove_index(P11cArray* parray, unsigned int index) -{ - RealArray* array = (RealArray*)parray; - - if(index >= array->pub.len) - return; - - if(index != array->pub.len - 1) - memmove(array_elt_pos (array, index), - array_elt_pos (array, index + 1), - array_elt_len (array, array->pub.len - index - 1)); - - array->pub.len -= 1; - - array_elt_zero (array, array->pub.len, 1); -} - -void -p11c_array_remove_range(P11cArray* parray, unsigned int index, size_t length) -{ - RealArray *array = (RealArray*)parray; - - if(index >= array->pub.len) - return; - if(index + length > array->pub.len) - length = array->pub.len - index; - if(length == 0) - return; - - if(index + length != array->pub.len) - memmove(array_elt_pos (array, index), - array_elt_pos (array, index + length), - (array->pub.len - (index + length)) * array->elt_size); - - array->pub.len -= length; - array_elt_zero(array, array->pub.len, length); -} - - -/* - * Originally from apache 2.0 - * Extensive modifications by - */ - -/* Copyright 2000-2004 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -/* - * The internal form of a hash table. - * - * The table is an array indexed by the hash of the key; collisions - * are resolved by hanging a linked list of hash entries off each - * element of the array. Although this is a really simple design it - * isn't too bad given that pools have a low allocation overhead. - */ - -typedef struct _HashEntry -{ - struct _HashEntry* next; - unsigned int hash; - const void* key; - void* val; -} -HashEntry; - -/* - * The size of the array is always a power of two. We use the maximum - * index rather than the size so that we can use bitwise-AND for - * modular arithmetic. - * The count of hash entries may be greater depending on the chosen - * collision rate. - */ -struct _P11cHash -{ - HashEntry** array; - P11cHashFunc hash_func; - P11cHashEqual equal_func; - size_t count; - size_t max; -}; - - -#define INITIAL_MAX 15 /* tunable == 2^n - 1 */ - -static int -equal_default(const void* a, const void* b) -{ - return a == b; -} - -/* - * Hash creation functions. - */ - -static HashEntry** -alloc_array(P11cHash* ht, size_t max) -{ - return calloc(1, sizeof(*(ht->array)) * (max + 1)); -} - -P11cHash* -p11c_hash_new(P11cHashFunc hash_func, P11cHashEqual equal_func) -{ - P11cHash* ht = malloc(sizeof(P11cHash)); - if(ht) - { - ht->hash_func = hash_func ? hash_func : p11c_hash_pointer; - ht->equal_func = equal_func ? equal_func : equal_default; - ht->count = 0; - ht->max = INITIAL_MAX; - ht->array = alloc_array(ht, ht->max); - if(!ht->array) - { - free(ht); - ht = NULL; - } - } - return ht; -} - -void -p11c_hash_free(P11cHash* ht, P11cHashDestroy destroy_func) -{ - HashEntry* he; - HashEntry* next; - size_t i; - - for(i = 0; i <= ht->max; ++i) - { - for(he = ht->array[i]; he; ) - { - next = he->next; - if(destroy_func) - (destroy_func)((void*)he->val); - free(he); - he = next; - } - } - - if(ht->array) - free(ht->array); - free(ht); -} - -/* - * Expanding a hash table - */ -static int -expand_array(P11cHash* ht) -{ - HashEntry** new_array; - size_t new_max; - HashEntry* he; - HashEntry* next; - size_t i; - - new_max = ht->max * 2 + 1; - new_array = alloc_array(ht, new_max); - - if(!new_array) - return 0; - - for(i = 0; i <= ht->max; ++i) - { - for(he = ht->array[i], next = he ? he->next : NULL; - he != NULL; he = next, next = next ? next->next : NULL) - { - unsigned int j = he->hash & new_max; - he->next = new_array[j]; - new_array[j] = he; - } - } - - if(ht->array) - free(ht->array); - - ht->array = new_array; - ht->max = new_max; - return 1; -} - -/* - * This is where we keep the details of the hash function and control - * the maximum collision rate. - * - * If val is non-NULL it creates and initializes a new hash entry if - * there isn't already one there; it returns an updatable pointer so - * that hash entries can be removed. - */ - -static HashEntry** -find_entry(P11cHash* ht, const void* key, void* val) -{ - HashEntry** hep; - HashEntry* he; - unsigned int hash; - - hash = (ht->hash_func)(key); - - /* scan linked list */ - for(hep = &ht->array[hash & ht->max], he = *hep; - he; hep = &he->next, he = *hep) - { - if(he->hash == hash && (ht->equal_func)(he->key, key)) - break; - } - - if(he || !val) - return hep; - - /* add a new entry for non-NULL val */ - he = malloc(sizeof(*he)); - if(he) - { - /* Key points to external data */ - he->key = key; - he->next = NULL; - he->hash = hash; - he->val = val; - - *hep = he; - ht->count++; - } - - return hep; -} - -void* -p11c_hash_get(P11cHash* ht, const void *key) -{ - HashEntry** he = find_entry(ht, key, NULL); - if(he && *he) - return (void*)((*he)->val); - else - return NULL; -} - -int -p11c_hash_set(P11cHash* ht, const void* key, void* val) -{ - HashEntry** hep = find_entry(ht, key, val); - if(hep && *hep) - { - /* replace entry */ - (*hep)->key = key; - (*hep)->val = val; - - /* check that the collision rate isn't too high */ - if(ht->count > ht->max) - { - if(!expand_array(ht)) - return 0; - } - - return 1; - } - - return 0; -} - -void* -p11c_hash_rem(P11cHash* ht, const void* key) -{ - HashEntry** hep = find_entry(ht, key, NULL); - void* val = NULL; - - if(hep && *hep) - { - HashEntry* old = *hep; - *hep = (*hep)->next; - --ht->count; - val = (void*)old->val; - free(old); - } - - return val; -} - -size_t -p11c_hash_count(P11cHash* ht) -{ - return ht->count; -} - -unsigned int -p11c_hash_pointer(const void* ptr) -{ - return (unsigned int)ptr; -} - -unsigned int -p11c_hash_data(const void* data, size_t n_data) -{ - unsigned int hash = 0; - const unsigned char* end; - const unsigned char* p; - - /* - * This is the popular `times 33' hash algorithm which is used by - * perl and also appears in Berkeley DB. This is one of the best - * known hash functions for strings because it is both computed - * very fast and distributes very well. - * - * The originator may be Dan Bernstein but the code in Berkeley DB - * cites Chris Torek as the source. The best citation I have found - * is "Chris Torek, Hash function for text in C, Usenet message - * <27038@mimsy.umd.edu> in comp.lang.c , October, 1990." in Rich - * Salz's USENIX 1992 paper about INN which can be found at - * . - * - * The magic of number 33, i.e. why it works better than many other - * constants, prime or not, has never been adequately explained by - * anyone. So I try an explanation: if one experimentally tests all - * multipliers between 1 and 256 (as I did while writing a low-level - * data structure library some time ago) one detects that even - * numbers are not useable at all. The remaining 128 odd numbers - * (except for the number 1) work more or less all equally well. - * They all distribute in an acceptable way and this way fill a hash - * table with an average percent of approx. 86%. - * - * If one compares the chi^2 values of the variants (see - * Bob Jenkins ``Hashing Frequently Asked Questions'' at - * http://burtleburtle.net/bob/hash/hashfaq.html for a description - * of chi^2), the number 33 not even has the best value. But the - * number 33 and a few other equally good numbers like 17, 31, 63, - * 127 and 129 have nevertheless a great advantage to the remaining - * numbers in the large set of possible multipliers: their multiply - * operation can be replaced by a faster operation based on just one - * shift plus either a single addition or subtraction operation. And - * because a hash function has to both distribute good _and_ has to - * be very fast to compute, those few numbers should be preferred. - * - * -- Ralf S. Engelschall - */ - - for(p = data, end = p + n_data; p != end; ++p) - hash = hash * 33 + *p; - - return hash; -} - -unsigned int -p11c_hash_integer(int integer) -{ - return integer; -} diff --git a/p11-capi-util.h b/p11-capi-util.h deleted file mode 100644 index ed3507d..0000000 --- a/p11-capi-util.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __P11C_UTIL_H__ -#define __P11C_UTIL_H__ - -#include - - -void p11c_reverse_memory (void* data, size_t length); - -/* -------------------------------------------------------------------------------- - * ARRAYS - */ - -typedef struct _Array -{ - void* data; - size_t len; -} -P11cArray; - -#define p11c_array_append(a,v) p11c_array_append_vals(a, &(v), 1) -#define p11c_array_index(a,t,i) (((t*) (a)->data) [(i)]) - -P11cArray* p11c_array_new (int zero_terminated, int zero, - size_t element_size); - -P11cArray* p11c_array_sized_new (int zero_terminated, int zero, - size_t element_size, size_t reserved_size); - -void* p11c_array_free (P11cArray* array, int free_segment); - -int p11c_array_append_vals (P11cArray* array, const void* data, - size_t num); - -void p11c_array_remove_index (P11cArray* array, unsigned int index); - -void p11c_array_remove_range (P11cArray* array, unsigned int index, - size_t count); - - -/* -------------------------------------------------------------------------------- - * HASHTABLE - */ - -struct _P11cHash; -typedef struct _P11cHash P11cHash; - -typedef unsigned int (*P11cHashFunc)(const void* key); - -typedef int (*P11cHashEqual)(const void* a, const void* b); - -typedef void (*P11cHashDestroy)(void* val); - -P11cHash* p11c_hash_new (P11cHashFunc hash_func, P11cHashEqual equal_func); - -void p11c_hash_free (P11cHash* ht, P11cHashDestroy destroy_func); - -size_t p11c_hash_count (P11cHash* ht); - -void* p11c_hash_get (P11cHash* ht, const void* key); - -int p11c_hash_set (P11cHash* ht, const void* key, void* val); - -void* p11c_hash_rem (P11cHash* ht, const void* key); - -unsigned int p11c_hash_pointer (const void* ptr); - -unsigned int p11c_hash_data (const void* data, size_t n_data); - -unsigned int p11c_hash_integer (int integer); - -#define p11c_hash_key(num) (((char*)NULL) + (size_t)(num)) - -#endif /* __P11C_UTIL_H__ */ diff --git a/p11-capi.c b/p11-capi.c deleted file mode 100644 index b5f7f62..0000000 --- a/p11-capi.c +++ /dev/null @@ -1,1515 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include -#include -#include - -#include "p11-capi.h" -#include "p11-capi-object.h" -#include "p11-capi-session.h" -#include "p11-capi-rsa.h" -#include "p11-capi-token.h" - -/* Warns about all the raw string usage in this file */ -#pragma warning (disable : 4996) - -/* ------------------------------------------------------------------- - * GLOBALS / DEFINES - */ - -static int cryptoki_initialized = 0; -static HANDLE global_mutex = NULL; - -#define MANUFACTURER_ID "Cryptoki CAPI " -#define LIBRARY_DESCRIPTION "Cryptoki CAPI Provider " -#define LIBRARY_VERSION_MAJOR 1 -#define LIBRARY_VERSION_MINOR 1 -#define HARDWARE_VERSION_MAJOR 0 -#define HARDWARE_VERSION_MINOR 0 -#define FIRMWARE_VERSION_MAJOR 0 -#define FIRMWARE_VERSION_MINOR 0 -#define SLOT_TOKEN_SERIAL "1.0 " -#define SLOT_TOKEN_MODEL "1.0 " -#define MAX_PIN_LEN 256 -#define MIN_PIN_LEN 1 - -static CK_MECHANISM_TYPE all_mechanisms[] = { - CKM_RSA_PKCS -}; - -/* ------------------------------------------------------------------- - * MODULE GLOBAL FUNCTIONS - */ - -#define LINE 1024 - -void -p11c_debug(const char* msg, ...) -{ - char buf[LINE]; - va_list va; - size_t len; - - va_start(va, msg); - _vsnprintf(buf, 1024, msg, va); - va_end(va); - - buf[LINE - 1] = 0; - len = strlen (buf); - - strncpy(buf + len, "\n", 1024 - len); - buf[LINE - 1] = 0; - // OutputDebugStringA(buf); -} - -/* Bah humbug, MSVC doesn't have __func__ */ -#define ENTER(func) \ - char* _func = #func; \ - p11c_debug("%s: enter", _func) - -#define RETURN(ret) \ - return (p11c_debug("%s: %d", _func, ret), ret) - -#define PREREQ(cond, ret) \ - if (!(cond)) { p11c_debug("%s: %s failed: %d", _func, #cond, ret); return ret; } - -void -p11c_lock_global(void) -{ - DWORD r; - - ASSERT(global_mutex); - - r = WaitForSingleObject(global_mutex, INFINITE); - ASSERT(r == WAIT_OBJECT_0); -} - -void -p11c_unlock_global(void) -{ - BOOL r; - - ASSERT(global_mutex); - - r = ReleaseMutex(global_mutex); - ASSERT(r); -} - -CK_RV -p11c_winerr_to_ckr(DWORD werr) -{ - switch(werr) - { - case ERROR_NOT_ENOUGH_MEMORY: - case ERROR_OUTOFMEMORY: - return CKR_HOST_MEMORY; - break; - case NTE_NO_MEMORY: - return CKR_DEVICE_MEMORY; - break; - case ERROR_MORE_DATA: - return CKR_BUFFER_TOO_SMALL; - case ERROR_INVALID_PARAMETER: /* these params were derived from the */ - case ERROR_INVALID_HANDLE: /* inputs, so if they are bad, the input */ - case NTE_BAD_ALGID: /* data is bad */ - case NTE_BAD_HASH: - case NTE_BAD_TYPE: - case NTE_BAD_PUBLIC_KEY: - return CKR_DATA_INVALID; - case ERROR_BUSY: - case NTE_FAIL: - case NTE_BAD_UID: - return CKR_DEVICE_ERROR; - default: - return CKR_GENERAL_ERROR; - }; -} - -CK_RV -p11c_return_data_raw(CK_VOID_PTR output, CK_ULONG_PTR n_output, - CK_VOID_PTR input, CK_ULONG n_input) -{ - ASSERT(n_output); - ASSERT(input); - - /* Just asking for the length */ - if(!output) - { - *n_output = n_input; - return CKR_OK; - } - - /* Buffer is too short */ - if(n_input > *n_output) - { - *n_output = n_input; - return CKR_BUFFER_TOO_SMALL; - } - - *n_output = n_input; - memcpy(output, input, n_input); - return CKR_OK; -} - -CK_RV -p11c_return_data(CK_ATTRIBUTE_PTR attr, CK_VOID_PTR input, DWORD n_input) -{ - return p11c_return_data_raw(attr->pValue, &(attr->ulValueLen), - input, n_input); -} - -CK_RV -p11c_return_string(CK_ATTRIBUTE_PTR attr, WCHAR* string) -{ - CK_UTF8CHAR_PTR buffer; - int result; - - SetLastError(0); - - /* - * Sadly WideCharToMultiByte doesn't handle zero - * length strings properly. So we have to special - * case this part. - */ - if(!string[0]) - return p11c_return_data(attr, "", 0); - - /* The length of the string, including null termination */ - result = WideCharToMultiByte(CP_UTF8, 0, string, -1, - NULL, 0, NULL, NULL); - - if(result) - { - /* Did the caller just want the length? */ - if(!attr->pValue) - { - attr->ulValueLen = result - 1; - return CKR_OK; - } - - /* Is the callers buffer too short? */ - if((int)attr->ulValueLen < result - 1) - { - attr->ulValueLen = result - 1; - return CKR_BUFFER_TOO_SMALL; - } - - /* - * Allocate a buffer for the conversion. We have to - * do this because strings in PKCS#11 are not null - * terminated and strings returned from - * WideCharToMultiByte are always null terminated. - */ - buffer = malloc(result); - if(!buffer) - return CKR_HOST_MEMORY; - - /* Do the actual conversion */ - result = WideCharToMultiByte(CP_UTF8, 0, string, -1, - buffer, result, NULL, NULL); - - if(result) - { - attr->ulValueLen = result - 1; - memcpy(attr->pValue, buffer, attr->ulValueLen); - - free(buffer); - return CKR_OK; - } - - free(buffer); - } - - /* - * We should never have too little buffer, or - * get a zero length success code. It's a very - * strange error that arrives here. - */ - return CKR_GENERAL_ERROR; -} - -CK_RV -p11c_return_dword_as_bytes(CK_ATTRIBUTE_PTR attr, DWORD value) -{ - int i; - CK_ULONG count = 0; - BOOL first = TRUE; - BYTE* at = attr->pValue; - CK_RV ret = CKR_OK; - - for(i = 0; i < sizeof(DWORD); i++) - { - BYTE digit = (BYTE)((value >> (((sizeof(DWORD)-1)*8))) & 0xFF); - value = value << 8; - - /* No leading zero */ - if (first && digit == 0) - continue; - - first = FALSE; - if(at) - { - if(count > attr->ulValueLen) - ret = CKR_BUFFER_TOO_SMALL; - else - *(at++) = digit; - } - - count++; - } - - attr->ulValueLen = count; - return ret; -} - -CK_RV -p11c_return_reversed_data(CK_ATTRIBUTE_PTR attr, CK_VOID_PTR data, CK_ULONG length) -{ - CK_RV ret = p11c_return_data(attr, data, length); - if(ret != CKR_OK || !attr->pValue) - return ret; - - p11c_reverse_memory(attr->pValue, attr->ulValueLen); - return CKR_OK; -} - -static void -print_zero_decimal(CK_BYTE_PTR buffer, CK_ULONG length, WORD value) -{ - int i; - for(i = (int)length - 1; i >= 0; --i) - { - BYTE digit = value % 10; - buffer[i] = '0' + digit; - value /= 10; - } -} - -CK_RV -p11c_return_filetime(CK_ATTRIBUTE_PTR attr, FILETIME *ftime) -{ - SYSTEMTIME stime; - CK_DATE* date; - - ASSERT(attr); - ASSERT(ftime); - - if(!attr->pValue) - { - attr->ulValueLen = sizeof(CK_DATE); - return CKR_OK; - } - - if(attr->ulValueLen < sizeof(CK_DATE)) - { - attr->ulValueLen = sizeof(CK_DATE); - return CKR_BUFFER_TOO_SMALL; - } - - if(!FileTimeToSystemTime(ftime, &stime)) - { - DBG(("An invalid FILETIME was encountered")); - return CKR_GENERAL_ERROR; - } - - date = (CK_DATE*)attr->pValue; - attr->ulValueLen = sizeof(CK_DATE); - print_zero_decimal(date->year, sizeof(date->year), stime.wYear); - print_zero_decimal(date->month, sizeof(date->month), stime.wMonth); - print_zero_decimal(date->day, sizeof(date->day), stime.wDay); - - return CKR_OK; -} - -/* ---------------------------------------------------------------- */ - -static CK_RV -PC_C_Initialize(CK_VOID_PTR init_args) -{ - ENTER(C_Initialize); - PREREQ(!cryptoki_initialized, CKR_CRYPTOKI_ALREADY_INITIALIZED); - - if (init_args != NULL) { - CK_C_INITIALIZE_ARGS_PTR args; - int supplied_ok; - - /* pReserved must be NULL */ - args = init_args; - PREREQ(!args->pReserved, CKR_ARGUMENTS_BAD); - - /* ALL supplied function pointers need to have the value either NULL or non-NULL. */ - supplied_ok = (args->CreateMutex == NULL && args->DestroyMutex == NULL && - args->LockMutex == NULL && args->UnlockMutex == NULL) || - (args->CreateMutex != NULL && args->DestroyMutex != NULL && - args->LockMutex != NULL && args->UnlockMutex != NULL); - PREREQ(supplied_ok, CKR_ARGUMENTS_BAD); - - /* - * When the CKF_OS_LOCKING_OK flag isn't set and mutex function pointers are supplied - * by an application, return an error. We must be able to use our own locks. - */ - if(!(args->flags & CKF_OS_LOCKING_OK) && (args->CreateMutex != NULL)) - RETURN(CKR_CANT_LOCK); - } - - if(!global_mutex) - { - global_mutex = CreateMutex(NULL, FALSE, NULL); - if(!global_mutex) - RETURN(CKR_CANT_LOCK); - } - - cryptoki_initialized = 1; - - RETURN(CKR_OK); -} - -static CK_RV -PC_C_Finalize(CK_VOID_PTR pReserved) -{ - ENTER(C_Finalize); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(!pReserved, CKR_ARGUMENTS_BAD); - - cryptoki_initialized = 0; - - p11c_session_cleanup_all(); - p11c_token_cleanup_all(); - - RETURN(CKR_OK); -} - -static CK_RV -PC_C_GetInfo(CK_INFO_PTR info) -{ - ENTER(C_GetInfo); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(info, CKR_ARGUMENTS_BAD); - - ASSERT(strlen(MANUFACTURER_ID) == 32); - ASSERT(strlen(LIBRARY_DESCRIPTION) == 32); - - info->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR; - info->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR; - info->libraryVersion.major = LIBRARY_VERSION_MAJOR; - info->libraryVersion.minor = LIBRARY_VERSION_MINOR; - info->flags = 0; - strncpy((char*)info->manufacturerID, MANUFACTURER_ID, 32); - strncpy((char*)info->libraryDescription, LIBRARY_DESCRIPTION, 32); - - RETURN(CKR_OK); -} - -static CK_RV -PC_C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR list) -{ - /* This would be a strange call to receive */ - return C_GetFunctionList(list); -} - -static CK_RV -PC_C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR slot_list, CK_ULONG_PTR count) -{ - unsigned int n_tokens, i; - - ENTER(C_GetSlotList); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(count, CKR_ARGUMENTS_BAD); - - /* All tokens are always present */ - - n_tokens = p11c_token_get_count(); - - /* Application only wants to know the number of slots. */ - if(slot_list == NULL) - { - *count = n_tokens; - RETURN(CKR_OK); - } - - if(*count < n_tokens) - { - *count = n_tokens; - RETURN(CKR_BUFFER_TOO_SMALL); - } - - *count = n_tokens; - for(i = 0; i < n_tokens; ++i) - slot_list[i] = p11c_token_get_slot_id (i); - RETURN(CKR_OK); -} - -static CK_RV -PC_C_GetSlotInfo(CK_SLOT_ID id, CK_SLOT_INFO_PTR info) -{ - const char* name; - - ENTER(C_GetSlotInfo); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(info, CKR_ARGUMENTS_BAD); - - /* Make sure the slot ID is valid */ - if(!p11c_token_is_valid(id)) - RETURN(CKR_SLOT_ID_INVALID); - - ASSERT(strlen(MANUFACTURER_ID) == 32); - - /* Provide information about the slot in the provided buffer */ - strncpy((char*)info->manufacturerID, MANUFACTURER_ID, 32); - info->hardwareVersion.major = HARDWARE_VERSION_MAJOR; - info->hardwareVersion.minor = HARDWARE_VERSION_MINOR; - info->firmwareVersion.major = FIRMWARE_VERSION_MAJOR; - info->firmwareVersion.minor = FIRMWARE_VERSION_MINOR; - - /* Token is always present */ - info->flags = CKF_TOKEN_PRESENT; - - /* Slot name is blank padded, odd */ - name = p11c_token_get_display_name(id); - memset((char*)info->slotDescription, ' ', - sizeof(info->slotDescription)); - memcpy((char*)info->slotDescription, name, - min(strlen(name), sizeof(info->slotDescription))); - - RETURN(CKR_OK); -} - -static CK_RV -PC_C_GetTokenInfo(CK_SLOT_ID id, CK_TOKEN_INFO_PTR info) -{ - const char* name; - - ENTER(C_GetTokenInfo); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(info, CKR_ARGUMENTS_BAD); - - /* Make sure the slot ID is valid */ - if(!p11c_token_is_valid(id)) - RETURN(CKR_SLOT_ID_INVALID); - - ASSERT(strlen(MANUFACTURER_ID) == 32); - ASSERT(strlen(SLOT_TOKEN_MODEL) == 16); - ASSERT(strlen(SLOT_TOKEN_SERIAL) == 16); - - /* Provide information about a token in the provided buffer */ - strncpy((char*)info->manufacturerID, MANUFACTURER_ID, 32); - strncpy((char*)info->model, SLOT_TOKEN_MODEL, 16); - strncpy((char*)info->serialNumber, SLOT_TOKEN_SERIAL, 16); - - /* Protected authentication path: Windows prompts for it's own PINs */ - info->flags = CKF_TOKEN_INITIALIZED | CKF_PROTECTED_AUTHENTICATION_PATH; - info->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE; - info->ulSessionCount = CK_EFFECTIVELY_INFINITE; - info->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE; - info->ulRwSessionCount = CK_EFFECTIVELY_INFINITE; - info->ulMaxPinLen = MAX_PIN_LEN; - info->ulMinPinLen = MIN_PIN_LEN; - info->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION; - info->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION; - info->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION; - info->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION; - info->hardwareVersion.major = HARDWARE_VERSION_MAJOR; - info->hardwareVersion.minor = HARDWARE_VERSION_MINOR; - info->firmwareVersion.major = FIRMWARE_VERSION_MAJOR; - info->firmwareVersion.minor = FIRMWARE_VERSION_MINOR; - memset(info->utcTime, ' ', 16); - - /* Slot name is blank padded, odd */ - name = p11c_token_get_display_name(id); - memset((char*)info->label, ' ', sizeof(info->label)); - memcpy((char*)info->label, name, - min(strlen(name), sizeof(info->label))); - - RETURN(CKR_OK); -} - -static CK_RV -PC_C_GetMechanismList(CK_SLOT_ID id, CK_MECHANISM_TYPE_PTR mechanism_list, - CK_ULONG_PTR count) -{ - CK_ULONG n_mechs; - - ENTER(C_GetMechanismList); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(count, CKR_ARGUMENTS_BAD); - - if(!p11c_token_is_valid(id)) - RETURN(CKR_SLOT_ID_INVALID); - - n_mechs = sizeof(all_mechanisms) / sizeof(all_mechanisms[0]); - - if(mechanism_list == NULL) - { - *count = n_mechs; - RETURN(CKR_OK); - } - - if(*count < n_mechs) - { - *count = n_mechs; - RETURN(CKR_BUFFER_TOO_SMALL); - } - - memcpy(mechanism_list, all_mechanisms, - n_mechs * sizeof(CK_MECHANISM_TYPE)); - *count = n_mechs; - RETURN(CKR_OK); -} - -static CK_RV -PC_C_GetMechanismInfo(CK_SLOT_ID id, CK_MECHANISM_TYPE type, - CK_MECHANISM_INFO_PTR info) -{ - ENTER(C_GetMechanismInfo); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(info, CKR_ARGUMENTS_BAD); - - if(!p11c_token_is_valid(id)) - RETURN(CKR_SLOT_ID_INVALID); - - if(type == CKM_RSA_PKCS) - { - p11c_rsa_pkcs_get_info(type, info); - RETURN(CKR_OK); - } - - RETURN(CKR_MECHANISM_INVALID); -} - -static CK_RV -PC_C_InitToken(CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len, - CK_UTF8CHAR_PTR label) -{ - ENTER(C_InitToken); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved) -{ - ENTER(C_WaitForSlotEvent); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* - * PKCS#11 GRAY AREA: What happens when we know we'll *never* - * have any slot events, and someone calls us without CKR_DONT_BLOCK? - * In case there's a thread dedicated to calling this function in a - * loop, we wait 1 seconds when called without CKR_DONT_BLOCK. - */ - - if(!(flags & CKF_DONT_BLOCK)) - Sleep(1000); - - RETURN(CKR_NO_EVENT); -} - -static CK_RV -PC_C_OpenSession(CK_SLOT_ID id, CK_FLAGS flags, CK_VOID_PTR application, - CK_NOTIFY notify, CK_SESSION_HANDLE_PTR session) -{ - P11cSession* sess; - CK_RV ret; - - ENTER(C_OpenSession); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(session, CKR_ARGUMENTS_BAD); - PREREQ(flags & CKF_SERIAL_SESSION, CKR_SESSION_PARALLEL_NOT_SUPPORTED); - - if(!p11c_token_is_valid(id)) - RETURN(CKR_SLOT_ID_INVALID); - - ret = p11c_session_create(id, &sess); - if(ret != CKR_OK) - RETURN(ret); - - sess->notify_callback = notify; - sess->user_data = application; - - if(flags & CKF_RW_SESSION) - sess->read_write = TRUE; - - ret = p11c_session_register(sess); - if(ret == CKR_OK) - { - /* ID should have been assigned when registering */ - ASSERT(sess->id > 0); - *session = sess->id; - } - else - { - p11c_session_destroy(sess); - } - - RETURN(ret); -} - -static CK_RV -PC_C_CloseSession(CK_SESSION_HANDLE session) -{ - P11cSession* sess; - CK_RV ret; - - ENTER(C_CloseSession); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - ret = p11c_session_remove_lock_ref(session, &sess); - if(ret == CKR_OK) - { - /* This will unref and possibly destroy the session */ - p11c_session_unref_unlock(sess); - } - - RETURN(ret); -} - -static CK_RV -PC_C_CloseAllSessions(CK_SLOT_ID id) -{ - ENTER(C_CloseAllSession); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - if(!p11c_token_is_valid(id)) - RETURN(CKR_SLOT_ID_INVALID); - - p11c_session_close_all(id); - RETURN(CKR_OK); -} - -static CK_RV -PC_C_GetFunctionStatus(CK_SESSION_HANDLE session) -{ - ENTER(C_GetFunctionStatus); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - RETURN(CKR_FUNCTION_NOT_PARALLEL); -} - -static CK_RV -PC_C_CancelFunction(CK_SESSION_HANDLE session) -{ - ENTER(C_CancelFunction); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - RETURN(CKR_FUNCTION_NOT_PARALLEL); -} - -static CK_RV -PC_C_GetSessionInfo(CK_SESSION_HANDLE session, CK_SESSION_INFO_PTR info) -{ - P11cSession* sess; - CK_RV ret; - - ENTER(C_GetSessionInfo); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(info, CKR_ARGUMENTS_BAD); - - ret = p11c_session_get_lock_ref(session, FALSE, &sess); - if(ret == CKR_OK) - { - p11c_session_get_info(sess, info); - p11c_session_unref_unlock(sess); - } - - RETURN(ret); -} - -static CK_RV -PC_C_InitPIN(CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR pin, - CK_ULONG pin_len) -{ - ENTER(C_InitPIN); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* We don't support this stuff. We don't support 'SO' logins. */ - RETURN(CKR_USER_NOT_LOGGED_IN); -} - -static CK_RV -PC_C_SetPIN(CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR old_pin, - CK_ULONG old_len, CK_UTF8CHAR_PTR new_pin, CK_ULONG new_len) -{ - ENTER(C_SetPIN); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* Not supported, Windows takes care of this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_GetOperationState(CK_SESSION_HANDLE session, CK_BYTE_PTR operation_state, - CK_ULONG_PTR operation_state_len) -{ - ENTER(C_GetOperationState); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* Nasty, no sirrr */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_SetOperationState(CK_SESSION_HANDLE session, CK_BYTE_PTR operation_state, - CK_ULONG operation_state_len, CK_OBJECT_HANDLE encryption_key, - CK_OBJECT_HANDLE authentication_key) -{ - ENTER(C_SetOperationState); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* Nasty, no sirrr */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_Login(CK_SESSION_HANDLE session, CK_USER_TYPE user_type, - CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) -{ - P11cSession* sess; - CK_RV ret; - - ENTER(C_Login); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - ret = p11c_session_get_lock_ref(session, FALSE, &sess); - if(ret == CKR_OK) - { - switch(user_type) - { - case CKU_USER: - ret = p11c_token_login(sess->slot); - break; - case CKU_SO: - ret = CKR_USER_TYPE_INVALID; - break; - default: - ret = CKR_USER_TYPE_INVALID; - break; - } - - p11c_session_unref_unlock(sess); - } - - RETURN(ret); -} - -static CK_RV -PC_C_Logout(CK_SESSION_HANDLE session) -{ - P11cSession* sess; - CK_RV ret; - - ENTER(C_Logout); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - ret = p11c_session_get_lock_ref(session, FALSE, &sess); - if(ret == CKR_OK) - { - ret = p11c_token_logout(sess->slot); - p11c_session_unref_unlock(sess); - } - - RETURN(ret); -} - -static CK_RV -PC_C_CreateObject(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR templ, - CK_ULONG count, CK_OBJECT_HANDLE_PTR object) -{ - ENTER(C_CreateObject); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: See if we need to support this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_CopyObject(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, - CK_ATTRIBUTE_PTR templ, CK_ULONG count, - CK_OBJECT_HANDLE_PTR new_object) -{ - ENTER(C_CopyObject); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: See if we need to support this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - - -static CK_RV -PC_C_DestroyObject(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object) -{ - ENTER(C_DestroyObject); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: See if we need to support this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_GetObjectSize(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, - CK_ULONG_PTR size) -{ - ENTER(C_GetObjectSize); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: Implement this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_GetAttributeValue(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, - CK_ATTRIBUTE_PTR templ, CK_ULONG count) -{ - P11cSession* sess; - P11cObjectData* objdata; - CK_RV ret; - - ENTER(C_GetAttributeValue); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(object, CKR_OBJECT_HANDLE_INVALID); - PREREQ(!count || templ, CKR_ARGUMENTS_BAD); - - ret = p11c_session_get_lock_ref(session, FALSE, &sess); - if(ret == CKR_OK) - { - ret = p11c_session_get_object_data_for(sess, object, &objdata); - if(ret == CKR_OK) - ret = p11c_object_data_get_attrs(objdata, templ, count); - - p11c_session_unref_unlock(sess); - } - - RETURN(ret); -} - -static CK_RV -PC_C_SetAttributeValue(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object, - CK_ATTRIBUTE_PTR templ, CK_ULONG count) -{ - ENTER(C_SetAttributeValue); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: See if we need to implement this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_FindObjectsInit(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR templ, - CK_ULONG count) -{ - P11cSession* sess; - CK_RV ret; - - ENTER(C_FindObjectsInit); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(!count || templ, CKR_ARGUMENTS_BAD); - - ret = p11c_session_get_lock_ref(session, FALSE, &sess); - if(ret == CKR_OK) - { - ret = p11c_session_find_init(sess, templ, count); - p11c_session_unref_unlock(sess); - } - - RETURN(ret); -} - -static CK_RV -PC_C_FindObjects(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE_PTR objects, - CK_ULONG max_object_count, CK_ULONG_PTR object_count) -{ - P11cSession* sess; - CK_RV ret; - - ENTER(C_FindObjects); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(object_count, CKR_ARGUMENTS_BAD); - PREREQ(!max_object_count || objects, CKR_ARGUMENTS_BAD); - - ret = p11c_session_get_lock_ref(session, FALSE, &sess); - if(ret == CKR_OK) - { - ret = p11c_session_find(sess, objects, max_object_count, object_count); - p11c_session_unref_unlock(sess); - } - - RETURN(ret); -} - -static CK_RV -PC_C_FindObjectsFinal(CK_SESSION_HANDLE session) -{ - P11cSession* sess; - CK_RV ret; - - ENTER(C_FindObjectsFinal); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - ret = p11c_session_get_lock_ref(session, FALSE, &sess); - if(ret == CKR_OK) - { - ret = p11c_session_find_final(sess); - p11c_session_unref_unlock(sess); - } - - RETURN(ret); -} - -static CK_RV -PC_C_EncryptInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - ENTER(C_EncryptInit); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: See if we need to implement this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_Encrypt(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR encrypted_data, CK_ULONG_PTR encrypted_data_len) -{ - ENTER(C_Encrypt); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: See if we need to implement this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_EncryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, - CK_ULONG part_len, CK_BYTE_PTR encrypted_part, - CK_ULONG_PTR encrypted_part_len) -{ - ENTER(C_EncryptUpdate); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support incremental crypto operations. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_EncryptFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR last_encrypted_part, - CK_ULONG_PTR last_encrypted_part_len) -{ - ENTER(C_EncryptFinal); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support incremental crypto operations. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_DecryptInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - P11cObjectData* objdata; - P11cSession* sess; - CK_RV ret; - - ENTER(C_DecryptInit); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(mechanism, CKR_ARGUMENTS_BAD); - PREREQ(key, CKR_ARGUMENTS_BAD); - - ret = p11c_session_get_lock_ref(session, FALSE, &sess); - if(ret == CKR_OK) - { - ret = p11c_session_get_object_data_for(sess, key, &objdata); - if(ret == CKR_OK) - ret = p11c_session_decrypt_init(sess, mechanism, objdata); - - p11c_session_unref_unlock(sess); - } - - RETURN(ret); -} - -static CK_RV -PC_C_Decrypt(CK_SESSION_HANDLE session, CK_BYTE_PTR encrypted_data, - CK_ULONG encrypted_data_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len) -{ - P11cSession* sess; - CK_RV ret; - - ENTER(C_Decrypt); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(encrypted_data, CKR_ARGUMENTS_BAD); - PREREQ(encrypted_data_len, CKR_ARGUMENTS_BAD); - - ret = p11c_session_get_lock_ref(session, FALSE, &sess); - if(ret == CKR_OK) - { - ret = p11c_session_decrypt(sess, encrypted_data, encrypted_data_len, - data, data_len); - p11c_session_unref_unlock(sess); - } - - RETURN(ret); -} - -static CK_RV -PC_C_DecryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR encrypted_part, - CK_ULONG encrypted_part_len, CK_BYTE_PTR part, CK_ULONG_PTR part_len) -{ - ENTER(C_DecryptUpdate); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support incremental crypto operations. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_DecryptFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR pLastPart, - CK_ULONG_PTR last_part_len) -{ - ENTER(C_DecryptFinal); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support incremental crypto operations. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_DigestInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism) -{ - ENTER(C_DigestInit); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support digest. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_Digest(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR digest, CK_ULONG_PTR digest_len) -{ - ENTER(C_Digest); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support digest. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_DigestUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len) -{ - ENTER(C_DigestUpdate); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support digest. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_DigestKey(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) -{ - ENTER(C_DigestKey); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support digest. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_DigestFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR digest, - CK_ULONG_PTR digest_len) -{ - ENTER(C_DigestFinal); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support digest. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_SignInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - P11cObjectData* objdata; - P11cSession* sess; - CK_RV ret; - - ENTER(C_SignInit); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(mechanism, CKR_ARGUMENTS_BAD); - PREREQ(key, CKR_ARGUMENTS_BAD); - - ret = p11c_session_get_lock_ref(session, FALSE, &sess); - if(ret == CKR_OK) - { - ret = p11c_session_get_object_data_for(sess, key, &objdata); - if(ret == CKR_OK) - ret = p11c_session_sign_init(sess, mechanism, objdata); - - p11c_session_unref_unlock(sess); - } - - RETURN(ret); -} - -static CK_RV -PC_C_Sign(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR signature, CK_ULONG_PTR signature_len) -{ - P11cSession* sess; - CK_RV ret; - - ENTER(C_Sign); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - PREREQ(data, CKR_ARGUMENTS_BAD); - PREREQ(data_len, CKR_ARGUMENTS_BAD); - - ret = p11c_session_get_lock_ref(session, FALSE, &sess); - if(ret == CKR_OK) - { - ret = p11c_session_sign(sess, data, data_len, signature, signature_len); - p11c_session_unref_unlock(sess); - } - - RETURN(ret); -} - -static CK_RV -PC_C_SignUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len) -{ - ENTER(C_SignUpdate); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support incremental crypto operations. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_SignFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR signature, - CK_ULONG_PTR signature_len) -{ - ENTER(C_SignFinal); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support incremental crypto operations. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_SignRecoverInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - ENTER(C_SignRecoverInit); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: Implement this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_SignRecover(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR signature, CK_ULONG_PTR signature_len) -{ - ENTER(C_SignRecover); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: Implement this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_VerifyInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - ENTER(C_VerifyInit); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: See if we need to implement this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_Verify(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len, - CK_BYTE_PTR signature, CK_ULONG signature_len) -{ - ENTER(C_Verify); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: See if we need to implement this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_VerifyUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len) -{ - ENTER(C_VerifyUpdate); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support incremental crypto operations. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_VerifyFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR signature, - CK_ULONG signature_len) -{ - ENTER(C_VerifyFinal); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support incremental crypto operations. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_VerifyRecoverInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE key) -{ - ENTER(C_VerifyRecoverInit); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: See if we need to implement this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_VerifyRecover(CK_SESSION_HANDLE session, CK_BYTE_PTR signature, - CK_ULONG signature_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len) -{ - ENTER(C_VerifyRecover); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: See if we need to implement this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_DigestEncryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, - CK_ULONG part_len, CK_BYTE_PTR encrypted_part, - CK_ULONG_PTR encrypted_part_len) -{ - ENTER(C_DigestEncryptUpdate); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support incremental crypto operations. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_DecryptDigestUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR encrypted_part, - CK_ULONG encrypted_part_len, CK_BYTE_PTR part, - CK_ULONG_PTR part_len) -{ - ENTER(C_DecryptDigestUpdate); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support incremental crypto operations. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_SignEncryptUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, - CK_ULONG part_len, CK_BYTE_PTR encrypted_part, - CK_ULONG_PTR encrypted_part_len) -{ - ENTER(C_SignEncryptUpdate); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support incremental crypto operations. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_DecryptVerifyUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR encrypted_part, - CK_ULONG encrypted_part_len, CK_BYTE_PTR part, - CK_ULONG_PTR part_len) -{ - ENTER(C_DecryptVerifyUpdate); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* RSA/DSA mechs don't support incremental crypto operations. */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_GenerateKey(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_ATTRIBUTE_PTR templ, CK_ULONG count, - CK_OBJECT_HANDLE_PTR key) -{ - ENTER(C_GenerateKey); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* Let key generation happen via Windows interfaces */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_GenerateKeyPair(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_ATTRIBUTE_PTR public_key_template, CK_ULONG public_key_attribute_count, - CK_ATTRIBUTE_PTR private_key_template, CK_ULONG private_key_attribute_count, - CK_OBJECT_HANDLE_PTR public_key, CK_OBJECT_HANDLE_PTR private_key) -{ - ENTER(C_GenerateKeyPair); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* Let key generation happen via Windows interfaces */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_WrapKey(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, - CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len) -{ - ENTER(C_WrapKey); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: See if we need to implement this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_UnwrapKey(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key, - CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR templ, - CK_ULONG count, CK_OBJECT_HANDLE_PTR key) -{ - ENTER(C_UnwrapKey); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* TODO: See if we need to implement this */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_DeriveKey(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, - CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE_PTR templ, - CK_ULONG count, CK_OBJECT_HANDLE_PTR key) -{ - ENTER(C_DeriveKey); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* Can't do this with RSA */ - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_SeedRandom(CK_SESSION_HANDLE session, CK_BYTE_PTR seed, CK_ULONG seed_len) -{ - ENTER(C_SeedRandom); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* - * TODO: Perhaps at some point in the future we may want - * to see if we can hook into the Windows RNG - */ - - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_RV -PC_C_GenerateRandom(CK_SESSION_HANDLE session, CK_BYTE_PTR random_data, - CK_ULONG random_len) -{ - ENTER(C_GenerateRandom); - PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); - - /* - * TODO: Perhaps at some point in the future we may want - * to see if we can hook into the Windows RNG - */ - - RETURN(CKR_FUNCTION_NOT_SUPPORTED); -} - -static CK_FUNCTION_LIST functionList = { - { 2, 11 }, /* version */ - PC_C_Initialize, - PC_C_Finalize, - PC_C_GetInfo, - PC_C_GetFunctionList, - PC_C_GetSlotList, - PC_C_GetSlotInfo, - PC_C_GetTokenInfo, - PC_C_GetMechanismList, - PC_C_GetMechanismInfo, - PC_C_InitToken, - PC_C_InitPIN, - PC_C_SetPIN, - PC_C_OpenSession, - PC_C_CloseSession, - PC_C_CloseAllSessions, - PC_C_GetSessionInfo, - PC_C_GetOperationState, - PC_C_SetOperationState, - PC_C_Login, - PC_C_Logout, - PC_C_CreateObject, - PC_C_CopyObject, - PC_C_DestroyObject, - PC_C_GetObjectSize, - PC_C_GetAttributeValue, - PC_C_SetAttributeValue, - PC_C_FindObjectsInit, - PC_C_FindObjects, - PC_C_FindObjectsFinal, - PC_C_EncryptInit, - PC_C_Encrypt, - PC_C_EncryptUpdate, - PC_C_EncryptFinal, - PC_C_DecryptInit, - PC_C_Decrypt, - PC_C_DecryptUpdate, - PC_C_DecryptFinal, - PC_C_DigestInit, - PC_C_Digest, - PC_C_DigestUpdate, - PC_C_DigestKey, - PC_C_DigestFinal, - PC_C_SignInit, - PC_C_Sign, - PC_C_SignUpdate, - PC_C_SignFinal, - PC_C_SignRecoverInit, - PC_C_SignRecover, - PC_C_VerifyInit, - PC_C_Verify, - PC_C_VerifyUpdate, - PC_C_VerifyFinal, - PC_C_VerifyRecoverInit, - PC_C_VerifyRecover, - PC_C_DigestEncryptUpdate, - PC_C_DecryptDigestUpdate, - PC_C_SignEncryptUpdate, - PC_C_DecryptVerifyUpdate, - PC_C_GenerateKey, - PC_C_GenerateKeyPair, - PC_C_WrapKey, - PC_C_UnwrapKey, - PC_C_DeriveKey, - PC_C_SeedRandom, - PC_C_GenerateRandom, - PC_C_GetFunctionStatus, - PC_C_CancelFunction, - PC_C_WaitForSlotEvent -}; - -__declspec(dllexport) CK_RV -C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR list) -{ - if(!list) - return CKR_ARGUMENTS_BAD; - - *list = &functionList; - return CKR_OK; -} diff --git a/p11-capi.dep b/p11-capi.dep deleted file mode 100644 index c04832a..0000000 --- a/p11-capi.dep +++ /dev/null @@ -1,69 +0,0 @@ -# Microsoft Developer Studio Generated Dependency File, included by p11c.mak - -".\p11-capi-builtin.c" : \ - "..\..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ - ".\p11-capi-util.h"\ - ".\p11-capi.h"\ - ".\pkcs11\cryptoki.h"\ - ".\pkcs11\pkcs11.h"\ - ".\pkcs11\pkcs11f.h"\ - ".\pkcs11\pkcs11n.h"\ - ".\pkcs11\pkcs11t.h"\ - - -".\p11-capi-cert.c" : \ - "..\..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ - ".\p11-capi-util.h"\ - ".\p11-capi.h"\ - ".\pkcs11\cryptoki.h"\ - ".\pkcs11\pkcs11.h"\ - ".\pkcs11\pkcs11f.h"\ - ".\pkcs11\pkcs11t.h"\ - - -".\p11-capi-object.c" : \ - "..\..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ - ".\p11-capi-util.h"\ - ".\p11-capi.h"\ - ".\pkcs11\cryptoki.h"\ - ".\pkcs11\pkcs11.h"\ - ".\pkcs11\pkcs11f.h"\ - ".\pkcs11\pkcs11n.h"\ - ".\pkcs11\pkcs11t.h"\ - - -".\p11-capi-session.c" : \ - "..\..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ - ".\p11-capi-util.h"\ - ".\p11-capi.h"\ - ".\pkcs11\cryptoki.h"\ - ".\pkcs11\pkcs11.h"\ - ".\pkcs11\pkcs11f.h"\ - ".\pkcs11\pkcs11t.h"\ - - -".\p11-capi-trust.c" : \ - "..\..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ - ".\p11-capi-util.h"\ - ".\p11-capi.h"\ - ".\pkcs11\cryptoki.h"\ - ".\pkcs11\pkcs11.h"\ - ".\pkcs11\pkcs11f.h"\ - ".\pkcs11\pkcs11n.h"\ - ".\pkcs11\pkcs11t.h"\ - ".\x509-usages.h"\ - - -".\p11-capi-util.c" : \ - ".\p11-capi-util.h"\ - - -.\p11-capi.c : \ - "..\..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ - ".\p11-capi-util.h"\ - ".\p11-capi.h"\ - ".\pkcs11\cryptoki.h"\ - ".\pkcs11\pkcs11.h"\ - ".\pkcs11\pkcs11f.h"\ - ".\pkcs11\pkcs11t.h"\ - diff --git a/p11-capi.h b/p11-capi.h deleted file mode 100644 index e522bfa..0000000 --- a/p11-capi.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2007 Stef Walter - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef P11C_H -#define P11C_H - -/* -------------------------------------------------------------------- - * - * Session = P11cSession - * - A PKCS#11 Session - * - * Objects = P11cObject - * - There's a global list of objects in p11c-object.c indexed by - * object handle. - * - The object itself has no attributes or cached data, but knows how - * to load data when needed. - * - Each object has a unique key which guarantees we don't load the - * same object twice with two different object handles. - * - * Object Data = P11cObjectData - * - Object Data is owned by the Session - * - Loaded data and/or attributes for an object. - */ - -#define WIN32_LEAN_AND_MEAN -#define _WIN32_WINNT 0x400 -#include -#include - -#define P11c_ENCODINGS (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING) - -#define CRYPTOKI_EXPORTS -#include "pkcs11/pkcs11.h" - -#include "p11-capi-util.h" - -struct _P11cSlot; -struct _P11cObject; -struct _P11cObjectData; -struct _P11cSession; - -typedef struct _P11cSlot P11cSlot; -typedef struct _P11cObject P11cObject; -typedef struct _P11cObjectData P11cObjectData; -typedef struct _P11cSession P11cSession; - -/* ------------------------------------------------------------------ - * cryptoki-capi.c - * - * Module helper and logging functions. - */ - -#define DBG(args) p11c_debug args - -void p11c_debug (const char* msg, ...); - -/* - * Protect global data with these. - */ -void p11c_lock_global (void); -void p11c_unlock_global (void); - -/* - * Convert a GetLastError() windows error to a - * PKCS#11 return code. - */ -CK_RV p11c_winerr_to_ckr (DWORD werr); - -/* - * This stores data in the output buffer with appropriate - * PKCS#11 codes when the buffer is too short, or the caller - * just wants to know the length, etc. - */ -CK_RV p11c_return_data (CK_ATTRIBUTE_PTR attr, - CK_VOID_PTR src, DWORD slen); - -CK_RV p11c_return_data_raw (CK_VOID_PTR output, CK_ULONG_PTR n_output, - CK_VOID_PTR input, CK_ULONG n_input); - -/* - * This stores a string in the output buffer with appropriate - * PKCS#11 codes when the buffer is too short, or the caller - * just wants to know the length, etc. - */ -CK_RV p11c_return_string (CK_ATTRIBUTE_PTR attr, - WCHAR* string); - -CK_RV p11c_return_dword_as_bytes (CK_ATTRIBUTE_PTR attr, - DWORD value); - -CK_RV p11c_return_reversed_data (CK_ATTRIBUTE_PTR attr, - CK_VOID_PTR data, CK_ULONG length); - -CK_RV p11c_return_filetime (CK_ATTRIBUTE_PTR attr, - FILETIME* ftime); - -/* ------------------------------------------------------------------ */ - -typedef void (*P11cDestroyFunc)(void* data); - -#ifndef ASSERT -#include "assert.h" -#define ASSERT assert -#endif - -/* Represents 'any' class in searches */ -#define CKO_ANY CK_INVALID_HANDLE - - -#endif /* P11C_CAPI_H */ diff --git a/p11-capi.vcproj b/p11-capi.vcproj deleted file mode 100644 index 7c554d1..0000000 --- a/p11-capi.vcproj +++ /dev/null @@ -1,428 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pkcs11/Makefile.am b/pkcs11/Makefile.am deleted file mode 100644 index b3598ba..0000000 --- a/pkcs11/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ - -EXTRA_DIST = \ - cryptoki.h \ - pkcs11.h \ - pkcs11f.h \ - pkcs11t.h \ - pkcs-11v2-20a3.h - - diff --git a/pkcs11/pkcs11.h b/pkcs11/pkcs11.h deleted file mode 100644 index 2e6a1e3..0000000 --- a/pkcs11/pkcs11.h +++ /dev/null @@ -1,1357 +0,0 @@ -/* pkcs11.h - Copyright 2006, 2007 g10 Code GmbH - Copyright 2006 Andreas Jellinghaus - - This file is free software; as a special exception the author gives - unlimited permission to copy and/or distribute it, with or without - modifications, as long as this notice is preserved. - - This file is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY, to the extent permitted by law; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. */ - -/* Please submit changes back to the Scute project at - http://www.scute.org/ (or send them to marcus@g10code.com), so that - they can be picked up by other projects from there as well. */ - -/* This file is a modified implementation of the PKCS #11 standard by - RSA Security Inc. It is mostly a drop-in replacement, with the - following change: - - This header file does not require any macro definitions by the user - (like CK_DEFINE_FUNCTION etc). In fact, it defines those macros - for you (if useful, some are missing, let me know if you need - more). - - There is an additional API available that does comply better to the - GNU coding standard. It can be switched on by defining - CRYPTOKI_GNU before including this header file. For this, the - following changes are made to the specification: - - All structure types are changed to a "struct ck_foo" where CK_FOO - is the type name in PKCS #11. - - All non-structure types are changed to ck_foo_t where CK_FOO is the - lowercase version of the type name in PKCS #11. The basic types - (CK_ULONG et al.) are removed without substitute. - - All members of structures are modified in the following way: Type - indication prefixes are removed, and underscore characters are - inserted before words. Then the result is lowercased. - - Note that function names are still in the original case, as they - need for ABI compatibility. - - CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute. Use - . - - If CRYPTOKI_COMPAT is defined before including this header file, - then none of the API changes above take place, and the API is the - one defined by the PKCS #11 standard. */ - -#ifndef PKCS11_H -#define PKCS11_H 1 - -#if defined(__cplusplus) -extern "C" { -#endif - - -/* The version of cryptoki we implement. The revision is changed with - each modification of this file. If you do not use the "official" - version of this file, please consider deleting the revision macro - (you may use a macro with a different name to keep track of your - versions). */ -#define CRYPTOKI_VERSION_MAJOR 2 -#define CRYPTOKI_VERSION_MINOR 20 -#define CRYPTOKI_VERSION_REVISION 6 - - -/* Compatibility interface is default, unless CRYPTOKI_GNU is - given. */ -#ifndef CRYPTOKI_GNU -#ifndef CRYPTOKI_COMPAT -#define CRYPTOKI_COMPAT 1 -#endif -#endif - -/* System dependencies. */ - -#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) - -/* There is a matching pop below. */ -#pragma pack(push, cryptoki, 1) - -#ifdef CRYPTOKI_EXPORTS -#define CK_SPEC __declspec(dllexport) -#else -#define CK_SPEC __declspec(dllimport) -#endif - -#else - -#define CK_SPEC - -#endif - - -#ifdef CRYPTOKI_COMPAT - /* If we are in compatibility mode, switch all exposed names to the - PKCS #11 variant. There are corresponding #undefs below. */ - -#define ck_flags_t CK_FLAGS -#define ck_version _CK_VERSION - -#define ck_info _CK_INFO -#define cryptoki_version cryptokiVersion -#define manufacturer_id manufacturerID -#define library_description libraryDescription -#define library_version libraryVersion - -#define ck_notification_t CK_NOTIFICATION -#define ck_slot_id_t CK_SLOT_ID - -#define ck_slot_info _CK_SLOT_INFO -#define slot_description slotDescription -#define hardware_version hardwareVersion -#define firmware_version firmwareVersion - -#define ck_token_info _CK_TOKEN_INFO -#define serial_number serialNumber -#define max_session_count ulMaxSessionCount -#define session_count ulSessionCount -#define max_rw_session_count ulMaxRwSessionCount -#define rw_session_count ulRwSessionCount -#define max_pin_len ulMaxPinLen -#define min_pin_len ulMinPinLen -#define total_public_memory ulTotalPublicMemory -#define free_public_memory ulFreePublicMemory -#define total_private_memory ulTotalPrivateMemory -#define free_private_memory ulFreePrivateMemory -#define utc_time utcTime - -#define ck_session_handle_t CK_SESSION_HANDLE -#define ck_user_type_t CK_USER_TYPE -#define ck_state_t CK_STATE - -#define ck_session_info _CK_SESSION_INFO -#define slot_id slotID -#define device_error ulDeviceError - -#define ck_object_handle_t CK_OBJECT_HANDLE -#define ck_object_class_t CK_OBJECT_CLASS -#define ck_hw_feature_type_t CK_HW_FEATURE_TYPE -#define ck_key_type_t CK_KEY_TYPE -#define ck_certificate_type_t CK_CERTIFICATE_TYPE -#define ck_attribute_type_t CK_ATTRIBUTE_TYPE - -#define ck_attribute _CK_ATTRIBUTE -#define value pValue -#define value_len ulValueLen - -#define ck_date _CK_DATE - -#define ck_mechanism_type_t CK_MECHANISM_TYPE - -#define ck_mechanism _CK_MECHANISM -#define parameter pParameter -#define parameter_len ulParameterLen - -#define ck_mechanism_info _CK_MECHANISM_INFO -#define min_key_size ulMinKeySize -#define max_key_size ulMaxKeySize - -#define ck_rv_t CK_RV -#define ck_notify_t CK_NOTIFY - -#define ck_function_list _CK_FUNCTION_LIST - -#define ck_createmutex_t CK_CREATEMUTEX -#define ck_destroymutex_t CK_DESTROYMUTEX -#define ck_lockmutex_t CK_LOCKMUTEX -#define ck_unlockmutex_t CK_UNLOCKMUTEX - -#define ck_c_initialize_args _CK_C_INITIALIZE_ARGS -#define create_mutex CreateMutex -#define destroy_mutex DestroyMutex -#define lock_mutex LockMutex -#define unlock_mutex UnlockMutex -#define reserved pReserved - -#endif /* CRYPTOKI_COMPAT */ - - - -typedef unsigned long ck_flags_t; - -struct ck_version -{ - unsigned char major; - unsigned char minor; -}; - - -struct ck_info -{ - struct ck_version cryptoki_version; - unsigned char manufacturer_id[32]; - ck_flags_t flags; - unsigned char library_description[32]; - struct ck_version library_version; -}; - - -typedef unsigned long ck_notification_t; - -#define CKN_SURRENDER (0) - - -typedef unsigned long ck_slot_id_t; - - -struct ck_slot_info -{ - unsigned char slot_description[64]; - unsigned char manufacturer_id[32]; - ck_flags_t flags; - struct ck_version hardware_version; - struct ck_version firmware_version; -}; - - -#define CKF_TOKEN_PRESENT (1 << 0) -#define CKF_REMOVABLE_DEVICE (1 << 1) -#define CKF_HW_SLOT (1 << 2) -#define CKF_ARRAY_ATTRIBUTE (1 << 30) - - -struct ck_token_info -{ - unsigned char label[32]; - unsigned char manufacturer_id[32]; - unsigned char model[16]; - unsigned char serial_number[16]; - ck_flags_t flags; - unsigned long max_session_count; - unsigned long session_count; - unsigned long max_rw_session_count; - unsigned long rw_session_count; - unsigned long max_pin_len; - unsigned long min_pin_len; - unsigned long total_public_memory; - unsigned long free_public_memory; - unsigned long total_private_memory; - unsigned long free_private_memory; - struct ck_version hardware_version; - struct ck_version firmware_version; - unsigned char utc_time[16]; -}; - - -#define CKF_RNG (1 << 0) -#define CKF_WRITE_PROTECTED (1 << 1) -#define CKF_LOGIN_REQUIRED (1 << 2) -#define CKF_USER_PIN_INITIALIZED (1 << 3) -#define CKF_RESTORE_KEY_NOT_NEEDED (1 << 5) -#define CKF_CLOCK_ON_TOKEN (1 << 6) -#define CKF_PROTECTED_AUTHENTICATION_PATH (1 << 8) -#define CKF_DUAL_CRYPTO_OPERATIONS (1 << 9) -#define CKF_TOKEN_INITIALIZED (1 << 10) -#define CKF_SECONDARY_AUTHENTICATION (1 << 11) -#define CKF_USER_PIN_COUNT_LOW (1 << 16) -#define CKF_USER_PIN_FINAL_TRY (1 << 17) -#define CKF_USER_PIN_LOCKED (1 << 18) -#define CKF_USER_PIN_TO_BE_CHANGED (1 << 19) -#define CKF_SO_PIN_COUNT_LOW (1 << 20) -#define CKF_SO_PIN_FINAL_TRY (1 << 21) -#define CKF_SO_PIN_LOCKED (1 << 22) -#define CKF_SO_PIN_TO_BE_CHANGED (1 << 23) - -#define CK_UNAVAILABLE_INFORMATION ((unsigned long) -1) -#define CK_EFFECTIVELY_INFINITE (0) - - -typedef unsigned long ck_session_handle_t; - -#define CK_INVALID_HANDLE (0) - - -typedef unsigned long ck_user_type_t; - -#define CKU_SO (0) -#define CKU_USER (1) -#define CKU_CONTEXT_SPECIFIC (2) - - -typedef unsigned long ck_state_t; - -#define CKS_RO_PUBLIC_SESSION (0) -#define CKS_RO_USER_FUNCTIONS (1) -#define CKS_RW_PUBLIC_SESSION (2) -#define CKS_RW_USER_FUNCTIONS (3) -#define CKS_RW_SO_FUNCTIONS (4) - - -struct ck_session_info -{ - ck_slot_id_t slot_id; - ck_state_t state; - ck_flags_t flags; - unsigned long device_error; -}; - -#define CKF_RW_SESSION (1 << 1) -#define CKF_SERIAL_SESSION (1 << 2) - - -typedef unsigned long ck_object_handle_t; - - -typedef unsigned long ck_object_class_t; - -#define CKO_DATA (0) -#define CKO_CERTIFICATE (1) -#define CKO_PUBLIC_KEY (2) -#define CKO_PRIVATE_KEY (3) -#define CKO_SECRET_KEY (4) -#define CKO_HW_FEATURE (5) -#define CKO_DOMAIN_PARAMETERS (6) -#define CKO_MECHANISM (7) -#define CKO_VENDOR_DEFINED ((unsigned long) (1 << 31)) - - -typedef unsigned long ck_hw_feature_type_t; - -#define CKH_MONOTONIC_COUNTER (1) -#define CKH_CLOCK (2) -#define CKH_USER_INTERFACE (3) -#define CKH_VENDOR_DEFINED ((unsigned long) (1 << 31)) - - -typedef unsigned long ck_key_type_t; - -#define CKK_RSA (0) -#define CKK_DSA (1) -#define CKK_DH (2) -#define CKK_ECDSA (3) -#define CKK_EC (3) -#define CKK_X9_42_DH (4) -#define CKK_KEA (5) -#define CKK_GENERIC_SECRET (0x10) -#define CKK_RC2 (0x11) -#define CKK_RC4 (0x12) -#define CKK_DES (0x13) -#define CKK_DES2 (0x14) -#define CKK_DES3 (0x15) -#define CKK_CAST (0x16) -#define CKK_CAST3 (0x17) -#define CKK_CAST128 (0x18) -#define CKK_RC5 (0x19) -#define CKK_IDEA (0x1a) -#define CKK_SKIPJACK (0x1b) -#define CKK_BATON (0x1c) -#define CKK_JUNIPER (0x1d) -#define CKK_CDMF (0x1e) -#define CKK_AES (0x1f) -#define CKK_BLOWFISH (0x20) -#define CKK_TWOFISH (0x21) -#define CKK_VENDOR_DEFINED ((unsigned long) (1 << 31)) - - -typedef unsigned long ck_certificate_type_t; - -#define CKC_X_509 (0) -#define CKC_X_509_ATTR_CERT (1) -#define CKC_WTLS (2) -#define CKC_VENDOR_DEFINED ((unsigned long) (1 << 31)) - - -typedef unsigned long ck_attribute_type_t; - -#define CKA_CLASS (0) -#define CKA_TOKEN (1) -#define CKA_PRIVATE (2) -#define CKA_LABEL (3) -#define CKA_APPLICATION (0x10) -#define CKA_VALUE (0x11) -#define CKA_OBJECT_ID (0x12) -#define CKA_CERTIFICATE_TYPE (0x80) -#define CKA_ISSUER (0x81) -#define CKA_SERIAL_NUMBER (0x82) -#define CKA_AC_ISSUER (0x83) -#define CKA_OWNER (0x84) -#define CKA_ATTR_TYPES (0x85) -#define CKA_TRUSTED (0x86) -#define CKA_CERTIFICATE_CATEGORY (0x87) -#define CKA_JAVA_MIDP_SECURITY_DOMAIN (0x88) -#define CKA_URL (0x89) -#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY (0x8a) -#define CKA_HASH_OF_ISSUER_PUBLIC_KEY (0x8b) -#define CKA_CHECK_VALUE (0x90) -#define CKA_KEY_TYPE (0x100) -#define CKA_SUBJECT (0x101) -#define CKA_ID (0x102) -#define CKA_SENSITIVE (0x103) -#define CKA_ENCRYPT (0x104) -#define CKA_DECRYPT (0x105) -#define CKA_WRAP (0x106) -#define CKA_UNWRAP (0x107) -#define CKA_SIGN (0x108) -#define CKA_SIGN_RECOVER (0x109) -#define CKA_VERIFY (0x10a) -#define CKA_VERIFY_RECOVER (0x10b) -#define CKA_DERIVE (0x10c) -#define CKA_START_DATE (0x110) -#define CKA_END_DATE (0x111) -#define CKA_MODULUS (0x120) -#define CKA_MODULUS_BITS (0x121) -#define CKA_PUBLIC_EXPONENT (0x122) -#define CKA_PRIVATE_EXPONENT (0x123) -#define CKA_PRIME_1 (0x124) -#define CKA_PRIME_2 (0x125) -#define CKA_EXPONENT_1 (0x126) -#define CKA_EXPONENT_2 (0x127) -#define CKA_COEFFICIENT (0x128) -#define CKA_PRIME (0x130) -#define CKA_SUBPRIME (0x131) -#define CKA_BASE (0x132) -#define CKA_PRIME_BITS (0x133) -#define CKA_SUB_PRIME_BITS (0x134) -#define CKA_VALUE_BITS (0x160) -#define CKA_VALUE_LEN (0x161) -#define CKA_EXTRACTABLE (0x162) -#define CKA_LOCAL (0x163) -#define CKA_NEVER_EXTRACTABLE (0x164) -#define CKA_ALWAYS_SENSITIVE (0x165) -#define CKA_KEY_GEN_MECHANISM (0x166) -#define CKA_MODIFIABLE (0x170) -#define CKA_ECDSA_PARAMS (0x180) -#define CKA_EC_PARAMS (0x180) -#define CKA_EC_POINT (0x181) -#define CKA_SECONDARY_AUTH (0x200) -#define CKA_AUTH_PIN_FLAGS (0x201) -#define CKA_ALWAYS_AUTHENTICATE (0x202) -#define CKA_WRAP_WITH_TRUSTED (0x210) -#define CKA_HW_FEATURE_TYPE (0x300) -#define CKA_RESET_ON_INIT (0x301) -#define CKA_HAS_RESET (0x302) -#define CKA_PIXEL_X (0x400) -#define CKA_PIXEL_Y (0x401) -#define CKA_RESOLUTION (0x402) -#define CKA_CHAR_ROWS (0x403) -#define CKA_CHAR_COLUMNS (0x404) -#define CKA_COLOR (0x405) -#define CKA_BITS_PER_PIXEL (0x406) -#define CKA_CHAR_SETS (0x480) -#define CKA_ENCODING_METHODS (0x481) -#define CKA_MIME_TYPES (0x482) -#define CKA_MECHANISM_TYPE (0x500) -#define CKA_REQUIRED_CMS_ATTRIBUTES (0x501) -#define CKA_DEFAULT_CMS_ATTRIBUTES (0x502) -#define CKA_SUPPORTED_CMS_ATTRIBUTES (0x503) -#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x211) -#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x212) -#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600) -#define CKA_VENDOR_DEFINED ((unsigned long) (1 << 31)) - - -struct ck_attribute -{ - ck_attribute_type_t type; - void *value; - unsigned long value_len; -}; - - -struct ck_date -{ - unsigned char year[4]; - unsigned char month[2]; - unsigned char day[2]; -}; - - -typedef unsigned long ck_mechanism_type_t; - -#define CKM_RSA_PKCS_KEY_PAIR_GEN (0) -#define CKM_RSA_PKCS (1) -#define CKM_RSA_9796 (2) -#define CKM_RSA_X_509 (3) -#define CKM_MD2_RSA_PKCS (4) -#define CKM_MD5_RSA_PKCS (5) -#define CKM_SHA1_RSA_PKCS (6) -#define CKM_RIPEMD128_RSA_PKCS (7) -#define CKM_RIPEMD160_RSA_PKCS (8) -#define CKM_RSA_PKCS_OAEP (9) -#define CKM_RSA_X9_31_KEY_PAIR_GEN (0xa) -#define CKM_RSA_X9_31 (0xb) -#define CKM_SHA1_RSA_X9_31 (0xc) -#define CKM_RSA_PKCS_PSS (0xd) -#define CKM_SHA1_RSA_PKCS_PSS (0xe) -#define CKM_DSA_KEY_PAIR_GEN (0x10) -#define CKM_DSA (0x11) -#define CKM_DSA_SHA1 (0x12) -#define CKM_DH_PKCS_KEY_PAIR_GEN (0x20) -#define CKM_DH_PKCS_DERIVE (0x21) -#define CKM_X9_42_DH_KEY_PAIR_GEN (0x30) -#define CKM_X9_42_DH_DERIVE (0x31) -#define CKM_X9_42_DH_HYBRID_DERIVE (0x32) -#define CKM_X9_42_MQV_DERIVE (0x33) -#define CKM_SHA256_RSA_PKCS (0x40) -#define CKM_SHA384_RSA_PKCS (0x41) -#define CKM_SHA512_RSA_PKCS (0x42) -#define CKM_SHA256_RSA_PKCS_PSS (0x43) -#define CKM_SHA384_RSA_PKCS_PSS (0x44) -#define CKM_SHA512_RSA_PKCS_PSS (0x45) -#define CKM_RC2_KEY_GEN (0x100) -#define CKM_RC2_ECB (0x101) -#define CKM_RC2_CBC (0x102) -#define CKM_RC2_MAC (0x103) -#define CKM_RC2_MAC_GENERAL (0x104) -#define CKM_RC2_CBC_PAD (0x105) -#define CKM_RC4_KEY_GEN (0x110) -#define CKM_RC4 (0x111) -#define CKM_DES_KEY_GEN (0x120) -#define CKM_DES_ECB (0x121) -#define CKM_DES_CBC (0x122) -#define CKM_DES_MAC (0x123) -#define CKM_DES_MAC_GENERAL (0x124) -#define CKM_DES_CBC_PAD (0x125) -#define CKM_DES2_KEY_GEN (0x130) -#define CKM_DES3_KEY_GEN (0x131) -#define CKM_DES3_ECB (0x132) -#define CKM_DES3_CBC (0x133) -#define CKM_DES3_MAC (0x134) -#define CKM_DES3_MAC_GENERAL (0x135) -#define CKM_DES3_CBC_PAD (0x136) -#define CKM_CDMF_KEY_GEN (0x140) -#define CKM_CDMF_ECB (0x141) -#define CKM_CDMF_CBC (0x142) -#define CKM_CDMF_MAC (0x143) -#define CKM_CDMF_MAC_GENERAL (0x144) -#define CKM_CDMF_CBC_PAD (0x145) -#define CKM_MD2 (0x200) -#define CKM_MD2_HMAC (0x201) -#define CKM_MD2_HMAC_GENERAL (0x202) -#define CKM_MD5 (0x210) -#define CKM_MD5_HMAC (0x211) -#define CKM_MD5_HMAC_GENERAL (0x212) -#define CKM_SHA_1 (0x220) -#define CKM_SHA_1_HMAC (0x221) -#define CKM_SHA_1_HMAC_GENERAL (0x222) -#define CKM_RIPEMD128 (0x230) -#define CKM_RIPEMD128_HMAC (0x231) -#define CKM_RIPEMD128_HMAC_GENERAL (0x232) -#define CKM_RIPEMD160 (0x240) -#define CKM_RIPEMD160_HMAC (0x241) -#define CKM_RIPEMD160_HMAC_GENERAL (0x242) -#define CKM_SHA256 (0x250) -#define CKM_SHA256_HMAC (0x251) -#define CKM_SHA256_HMAC_GENERAL (0x252) -#define CKM_SHA384 (0x260) -#define CKM_SHA384_HMAC (0x261) -#define CKM_SHA384_HMAC_GENERAL (0x262) -#define CKM_SHA512 (0x270) -#define CKM_SHA512_HMAC (0x271) -#define CKM_SHA512_HMAC_GENERAL (0x272) -#define CKM_CAST_KEY_GEN (0x300) -#define CKM_CAST_ECB (0x301) -#define CKM_CAST_CBC (0x302) -#define CKM_CAST_MAC (0x303) -#define CKM_CAST_MAC_GENERAL (0x304) -#define CKM_CAST_CBC_PAD (0x305) -#define CKM_CAST3_KEY_GEN (0x310) -#define CKM_CAST3_ECB (0x311) -#define CKM_CAST3_CBC (0x312) -#define CKM_CAST3_MAC (0x313) -#define CKM_CAST3_MAC_GENERAL (0x314) -#define CKM_CAST3_CBC_PAD (0x315) -#define CKM_CAST5_KEY_GEN (0x320) -#define CKM_CAST128_KEY_GEN (0x320) -#define CKM_CAST5_ECB (0x321) -#define CKM_CAST128_ECB (0x321) -#define CKM_CAST5_CBC (0x322) -#define CKM_CAST128_CBC (0x322) -#define CKM_CAST5_MAC (0x323) -#define CKM_CAST128_MAC (0x323) -#define CKM_CAST5_MAC_GENERAL (0x324) -#define CKM_CAST128_MAC_GENERAL (0x324) -#define CKM_CAST5_CBC_PAD (0x325) -#define CKM_CAST128_CBC_PAD (0x325) -#define CKM_RC5_KEY_GEN (0x330) -#define CKM_RC5_ECB (0x331) -#define CKM_RC5_CBC (0x332) -#define CKM_RC5_MAC (0x333) -#define CKM_RC5_MAC_GENERAL (0x334) -#define CKM_RC5_CBC_PAD (0x335) -#define CKM_IDEA_KEY_GEN (0x340) -#define CKM_IDEA_ECB (0x341) -#define CKM_IDEA_CBC (0x342) -#define CKM_IDEA_MAC (0x343) -#define CKM_IDEA_MAC_GENERAL (0x344) -#define CKM_IDEA_CBC_PAD (0x345) -#define CKM_GENERIC_SECRET_KEY_GEN (0x350) -#define CKM_CONCATENATE_BASE_AND_KEY (0x360) -#define CKM_CONCATENATE_BASE_AND_DATA (0x362) -#define CKM_CONCATENATE_DATA_AND_BASE (0x363) -#define CKM_XOR_BASE_AND_DATA (0x364) -#define CKM_EXTRACT_KEY_FROM_KEY (0x365) -#define CKM_SSL3_PRE_MASTER_KEY_GEN (0x370) -#define CKM_SSL3_MASTER_KEY_DERIVE (0x371) -#define CKM_SSL3_KEY_AND_MAC_DERIVE (0x372) -#define CKM_SSL3_MASTER_KEY_DERIVE_DH (0x373) -#define CKM_TLS_PRE_MASTER_KEY_GEN (0x374) -#define CKM_TLS_MASTER_KEY_DERIVE (0x375) -#define CKM_TLS_KEY_AND_MAC_DERIVE (0x376) -#define CKM_TLS_MASTER_KEY_DERIVE_DH (0x377) -#define CKM_SSL3_MD5_MAC (0x380) -#define CKM_SSL3_SHA1_MAC (0x381) -#define CKM_MD5_KEY_DERIVATION (0x390) -#define CKM_MD2_KEY_DERIVATION (0x391) -#define CKM_SHA1_KEY_DERIVATION (0x392) -#define CKM_PBE_MD2_DES_CBC (0x3a0) -#define CKM_PBE_MD5_DES_CBC (0x3a1) -#define CKM_PBE_MD5_CAST_CBC (0x3a2) -#define CKM_PBE_MD5_CAST3_CBC (0x3a3) -#define CKM_PBE_MD5_CAST5_CBC (0x3a4) -#define CKM_PBE_MD5_CAST128_CBC (0x3a4) -#define CKM_PBE_SHA1_CAST5_CBC (0x3a5) -#define CKM_PBE_SHA1_CAST128_CBC (0x3a5) -#define CKM_PBE_SHA1_RC4_128 (0x3a6) -#define CKM_PBE_SHA1_RC4_40 (0x3a7) -#define CKM_PBE_SHA1_DES3_EDE_CBC (0x3a8) -#define CKM_PBE_SHA1_DES2_EDE_CBC (0x3a9) -#define CKM_PBE_SHA1_RC2_128_CBC (0x3aa) -#define CKM_PBE_SHA1_RC2_40_CBC (0x3ab) -#define CKM_PKCS5_PBKD2 (0x3b0) -#define CKM_PBA_SHA1_WITH_SHA1_HMAC (0x3c0) -#define CKM_KEY_WRAP_LYNKS (0x400) -#define CKM_KEY_WRAP_SET_OAEP (0x401) -#define CKM_SKIPJACK_KEY_GEN (0x1000) -#define CKM_SKIPJACK_ECB64 (0x1001) -#define CKM_SKIPJACK_CBC64 (0x1002) -#define CKM_SKIPJACK_OFB64 (0x1003) -#define CKM_SKIPJACK_CFB64 (0x1004) -#define CKM_SKIPJACK_CFB32 (0x1005) -#define CKM_SKIPJACK_CFB16 (0x1006) -#define CKM_SKIPJACK_CFB8 (0x1007) -#define CKM_SKIPJACK_WRAP (0x1008) -#define CKM_SKIPJACK_PRIVATE_WRAP (0x1009) -#define CKM_SKIPJACK_RELAYX (0x100a) -#define CKM_KEA_KEY_PAIR_GEN (0x1010) -#define CKM_KEA_KEY_DERIVE (0x1011) -#define CKM_FORTEZZA_TIMESTAMP (0x1020) -#define CKM_BATON_KEY_GEN (0x1030) -#define CKM_BATON_ECB128 (0x1031) -#define CKM_BATON_ECB96 (0x1032) -#define CKM_BATON_CBC128 (0x1033) -#define CKM_BATON_COUNTER (0x1034) -#define CKM_BATON_SHUFFLE (0x1035) -#define CKM_BATON_WRAP (0x1036) -#define CKM_ECDSA_KEY_PAIR_GEN (0x1040) -#define CKM_EC_KEY_PAIR_GEN (0x1040) -#define CKM_ECDSA (0x1041) -#define CKM_ECDSA_SHA1 (0x1042) -#define CKM_ECDH1_DERIVE (0x1050) -#define CKM_ECDH1_COFACTOR_DERIVE (0x1051) -#define CKM_ECMQV_DERIVE (0x1052) -#define CKM_JUNIPER_KEY_GEN (0x1060) -#define CKM_JUNIPER_ECB128 (0x1061) -#define CKM_JUNIPER_CBC128 (0x1062) -#define CKM_JUNIPER_COUNTER (0x1063) -#define CKM_JUNIPER_SHUFFLE (0x1064) -#define CKM_JUNIPER_WRAP (0x1065) -#define CKM_FASTHASH (0x1070) -#define CKM_AES_KEY_GEN (0x1080) -#define CKM_AES_ECB (0x1081) -#define CKM_AES_CBC (0x1082) -#define CKM_AES_MAC (0x1083) -#define CKM_AES_MAC_GENERAL (0x1084) -#define CKM_AES_CBC_PAD (0x1085) -#define CKM_DSA_PARAMETER_GEN (0x2000) -#define CKM_DH_PKCS_PARAMETER_GEN (0x2001) -#define CKM_X9_42_DH_PARAMETER_GEN (0x2002) -#define CKM_VENDOR_DEFINED ((unsigned long) (1 << 31)) - - -struct ck_mechanism -{ - ck_mechanism_type_t mechanism; - void *parameter; - unsigned long parameter_len; -}; - - -struct ck_mechanism_info -{ - unsigned long min_key_size; - unsigned long max_key_size; - ck_flags_t flags; -}; - -#define CKF_HW (1 << 0) -#define CKF_ENCRYPT (1 << 8) -#define CKF_DECRYPT (1 << 9) -#define CKF_DIGEST (1 << 10) -#define CKF_SIGN (1 << 11) -#define CKF_SIGN_RECOVER (1 << 12) -#define CKF_VERIFY (1 << 13) -#define CKF_VERIFY_RECOVER (1 << 14) -#define CKF_GENERATE (1 << 15) -#define CKF_GENERATE_KEY_PAIR (1 << 16) -#define CKF_WRAP (1 << 17) -#define CKF_UNWRAP (1 << 18) -#define CKF_DERIVE (1 << 19) -#define CKF_EXTENSION ((unsigned long) (1 << 31)) - - -/* Flags for C_WaitForSlotEvent. */ -#define CKF_DONT_BLOCK (1) - - -typedef unsigned long ck_rv_t; - - -typedef ck_rv_t (*ck_notify_t) (ck_session_handle_t session, - ck_notification_t event, void *application); - -/* Forward reference. */ -struct ck_function_list; - -#define _CK_DECLARE_FUNCTION(name, args) \ -typedef ck_rv_t (*CK_ ## name) args; \ -ck_rv_t CK_SPEC name args - -_CK_DECLARE_FUNCTION (C_Initialize, (void *init_args)); -_CK_DECLARE_FUNCTION (C_Finalize, (void *reserved)); -_CK_DECLARE_FUNCTION (C_GetInfo, (struct ck_info *info)); -_CK_DECLARE_FUNCTION (C_GetFunctionList, - (struct ck_function_list **function_list)); - -_CK_DECLARE_FUNCTION (C_GetSlotList, - (unsigned char token_present, ck_slot_id_t *slot_list, - unsigned long *count)); -_CK_DECLARE_FUNCTION (C_GetSlotInfo, - (ck_slot_id_t slot_id, struct ck_slot_info *info)); -_CK_DECLARE_FUNCTION (C_GetTokenInfo, - (ck_slot_id_t slot_id, struct ck_token_info *info)); -_CK_DECLARE_FUNCTION (C_WaitForSlotEvent, - (ck_flags_t flags, ck_slot_id_t *slot, void *reserved)); -_CK_DECLARE_FUNCTION (C_GetMechanismList, - (ck_slot_id_t slot_id, - ck_mechanism_type_t *mechanism_list, - unsigned long *count)); -_CK_DECLARE_FUNCTION (C_GetMechanismInfo, - (ck_slot_id_t slot_id, ck_mechanism_type_t type, - struct ck_mechanism_info *info)); -_CK_DECLARE_FUNCTION (C_InitToken, - (ck_slot_id_t slot_id, unsigned char *pin, - unsigned long pin_len, unsigned char *label)); -_CK_DECLARE_FUNCTION (C_InitPIN, - (ck_session_handle_t session, unsigned char *pin, - unsigned long pin_len)); -_CK_DECLARE_FUNCTION (C_SetPIN, - (ck_session_handle_t session, unsigned char *old_pin, - unsigned long old_len, unsigned char *new_pin, - unsigned long new_len)); - -_CK_DECLARE_FUNCTION (C_OpenSession, - (ck_slot_id_t slot_id, ck_flags_t flags, - void *application, ck_notify_t notify, - ck_session_handle_t *session)); -_CK_DECLARE_FUNCTION (C_CloseSession, (ck_session_handle_t session)); -_CK_DECLARE_FUNCTION (C_CloseAllSessions, (ck_slot_id_t slot_id)); -_CK_DECLARE_FUNCTION (C_GetSessionInfo, - (ck_session_handle_t session, - struct ck_session_info *info)); -_CK_DECLARE_FUNCTION (C_GetOperationState, - (ck_session_handle_t session, - unsigned char *operation_state, - unsigned long *operation_state_len)); -_CK_DECLARE_FUNCTION (C_SetOperationState, - (ck_session_handle_t session, - unsigned char *operation_state, - unsigned long operation_state_len, - ck_object_handle_t encryption_key, - ck_object_handle_t authentiation_key)); -_CK_DECLARE_FUNCTION (C_Login, - (ck_session_handle_t session, ck_user_type_t user_type, - unsigned char *pin, unsigned long pin_len)); -_CK_DECLARE_FUNCTION (C_Logout, (ck_session_handle_t session)); - -_CK_DECLARE_FUNCTION (C_CreateObject, - (ck_session_handle_t session, - struct ck_attribute *templ, - unsigned long count, ck_object_handle_t *object)); -_CK_DECLARE_FUNCTION (C_CopyObject, - (ck_session_handle_t session, ck_object_handle_t object, - struct ck_attribute *templ, unsigned long count, - ck_object_handle_t *new_object)); -_CK_DECLARE_FUNCTION (C_DestroyObject, - (ck_session_handle_t session, - ck_object_handle_t object)); -_CK_DECLARE_FUNCTION (C_GetObjectSize, - (ck_session_handle_t session, - ck_object_handle_t object, - unsigned long *size)); -_CK_DECLARE_FUNCTION (C_GetAttributeValue, - (ck_session_handle_t session, - ck_object_handle_t object, - struct ck_attribute *templ, - unsigned long count)); -_CK_DECLARE_FUNCTION (C_SetAttributeValue, - (ck_session_handle_t session, - ck_object_handle_t object, - struct ck_attribute *templ, - unsigned long count)); -_CK_DECLARE_FUNCTION (C_FindObjectsInit, - (ck_session_handle_t session, - struct ck_attribute *templ, - unsigned long count)); -_CK_DECLARE_FUNCTION (C_FindObjects, - (ck_session_handle_t session, - ck_object_handle_t *object, - unsigned long max_object_count, - unsigned long *object_count)); -_CK_DECLARE_FUNCTION (C_FindObjectsFinal, - (ck_session_handle_t session)); - -_CK_DECLARE_FUNCTION (C_EncryptInit, - (ck_session_handle_t session, - struct ck_mechanism *mechanism, - ck_object_handle_t key)); -_CK_DECLARE_FUNCTION (C_Encrypt, - (ck_session_handle_t session, - unsigned char *data, unsigned long data_len, - unsigned char *encrypted_data, - unsigned long *encrypted_data_len)); -_CK_DECLARE_FUNCTION (C_EncryptUpdate, - (ck_session_handle_t session, - unsigned char *part, unsigned long part_len, - unsigned char *encrypted_part, - unsigned long *encrypted_part_len)); -_CK_DECLARE_FUNCTION (C_EncryptFinal, - (ck_session_handle_t session, - unsigned char *last_encrypted_part, - unsigned long *last_encrypted_part_len)); - -_CK_DECLARE_FUNCTION (C_DecryptInit, - (ck_session_handle_t session, - struct ck_mechanism *mechanism, - ck_object_handle_t key)); -_CK_DECLARE_FUNCTION (C_Decrypt, - (ck_session_handle_t session, - unsigned char *encrypted_data, - unsigned long encrypted_data_len, - unsigned char *data, unsigned long *data_len)); -_CK_DECLARE_FUNCTION (C_DecryptUpdate, - (ck_session_handle_t session, - unsigned char *encrypted_part, - unsigned long encrypted_part_len, - unsigned char *part, unsigned long *part_len)); -_CK_DECLARE_FUNCTION (C_DecryptFinal, - (ck_session_handle_t session, - unsigned char *last_part, - unsigned long *last_part_len)); - -_CK_DECLARE_FUNCTION (C_DigestInit, - (ck_session_handle_t session, - struct ck_mechanism *mechanism)); -_CK_DECLARE_FUNCTION (C_Digest, - (ck_session_handle_t session, - unsigned char *data, unsigned long data_len, - unsigned char *digest, - unsigned long *digest_len)); -_CK_DECLARE_FUNCTION (C_DigestUpdate, - (ck_session_handle_t session, - unsigned char *part, unsigned long part_len)); -_CK_DECLARE_FUNCTION (C_DigestKey, - (ck_session_handle_t session, ck_object_handle_t key)); -_CK_DECLARE_FUNCTION (C_DigestFinal, - (ck_session_handle_t session, - unsigned char *digest, - unsigned long *digest_len)); - -_CK_DECLARE_FUNCTION (C_SignInit, - (ck_session_handle_t session, - struct ck_mechanism *mechanism, - ck_object_handle_t key)); -_CK_DECLARE_FUNCTION (C_Sign, - (ck_session_handle_t session, - unsigned char *data, unsigned long data_len, - unsigned char *signature, - unsigned long *signature_len)); -_CK_DECLARE_FUNCTION (C_SignUpdate, - (ck_session_handle_t session, - unsigned char *part, unsigned long part_len)); -_CK_DECLARE_FUNCTION (C_SignFinal, - (ck_session_handle_t session, - unsigned char *signature, - unsigned long *signature_len)); -_CK_DECLARE_FUNCTION (C_SignRecoverInit, - (ck_session_handle_t session, - struct ck_mechanism *mechanism, - ck_object_handle_t key)); -_CK_DECLARE_FUNCTION (C_SignRecover, - (ck_session_handle_t session, - unsigned char *data, unsigned long data_len, - unsigned char *signature, - unsigned long *signature_len)); - -_CK_DECLARE_FUNCTION (C_VerifyInit, - (ck_session_handle_t session, - struct ck_mechanism *mechanism, - ck_object_handle_t key)); -_CK_DECLARE_FUNCTION (C_Verify, - (ck_session_handle_t session, - unsigned char *data, unsigned long data_len, - unsigned char *signature, - unsigned long signature_len)); -_CK_DECLARE_FUNCTION (C_VerifyUpdate, - (ck_session_handle_t session, - unsigned char *part, unsigned long part_len)); -_CK_DECLARE_FUNCTION (C_VerifyFinal, - (ck_session_handle_t session, - unsigned char *signature, - unsigned long signature_len)); -_CK_DECLARE_FUNCTION (C_VerifyRecoverInit, - (ck_session_handle_t session, - struct ck_mechanism *mechanism, - ck_object_handle_t key)); -_CK_DECLARE_FUNCTION (C_VerifyRecover, - (ck_session_handle_t session, - unsigned char *signature, - unsigned long signature_len, - unsigned char *data, - unsigned long *data_len)); - -_CK_DECLARE_FUNCTION (C_DigestEncryptUpdate, - (ck_session_handle_t session, - unsigned char *part, unsigned long part_len, - unsigned char *encrypted_part, - unsigned long *encrypted_part_len)); -_CK_DECLARE_FUNCTION (C_DecryptDigestUpdate, - (ck_session_handle_t session, - unsigned char *encrypted_part, - unsigned long encrypted_part_len, - unsigned char *part, - unsigned long *part_len)); -_CK_DECLARE_FUNCTION (C_SignEncryptUpdate, - (ck_session_handle_t session, - unsigned char *part, unsigned long part_len, - unsigned char *encrypted_part, - unsigned long *encrypted_part_len)); -_CK_DECLARE_FUNCTION (C_DecryptVerifyUpdate, - (ck_session_handle_t session, - unsigned char *encrypted_part, - unsigned long encrypted_part_len, - unsigned char *part, - unsigned long *part_len)); - -_CK_DECLARE_FUNCTION (C_GenerateKey, - (ck_session_handle_t session, - struct ck_mechanism *mechanism, - struct ck_attribute *templ, - unsigned long count, - ck_object_handle_t *key)); -_CK_DECLARE_FUNCTION (C_GenerateKeyPair, - (ck_session_handle_t session, - struct ck_mechanism *mechanism, - struct ck_attribute *public_key_template, - unsigned long public_key_attribute_count, - struct ck_attribute *private_key_template, - unsigned long private_key_attribute_count, - ck_object_handle_t *public_key, - ck_object_handle_t *private_key)); -_CK_DECLARE_FUNCTION (C_WrapKey, - (ck_session_handle_t session, - struct ck_mechanism *mechanism, - ck_object_handle_t wrapping_key, - ck_object_handle_t key, - unsigned char *wrapped_key, - unsigned long *wrapped_key_len)); -_CK_DECLARE_FUNCTION (C_UnwrapKey, - (ck_session_handle_t session, - struct ck_mechanism *mechanism, - ck_object_handle_t unwrapping_key, - unsigned char *wrapped_key, - unsigned long wrapped_key_len, - struct ck_attribute *templ, - unsigned long attribute_count, - ck_object_handle_t *key)); -_CK_DECLARE_FUNCTION (C_DeriveKey, - (ck_session_handle_t session, - struct ck_mechanism *mechanism, - ck_object_handle_t base_key, - struct ck_attribute *templ, - unsigned long attribute_count, - ck_object_handle_t *key)); - -_CK_DECLARE_FUNCTION (C_SeedRandom, - (ck_session_handle_t session, unsigned char *seed, - unsigned long seed_len)); -_CK_DECLARE_FUNCTION (C_GenerateRandom, - (ck_session_handle_t session, - unsigned char *random_data, - unsigned long random_len)); - -_CK_DECLARE_FUNCTION (C_GetFunctionStatus, (ck_session_handle_t session)); -_CK_DECLARE_FUNCTION (C_CancelFunction, (ck_session_handle_t session)); - - -struct ck_function_list -{ - struct ck_version version; - CK_C_Initialize C_Initialize; - CK_C_Finalize C_Finalize; - CK_C_GetInfo C_GetInfo; - CK_C_GetFunctionList C_GetFunctionList; - CK_C_GetSlotList C_GetSlotList; - CK_C_GetSlotInfo C_GetSlotInfo; - CK_C_GetTokenInfo C_GetTokenInfo; - CK_C_GetMechanismList C_GetMechanismList; - CK_C_GetMechanismInfo C_GetMechanismInfo; - CK_C_InitToken C_InitToken; - CK_C_InitPIN C_InitPIN; - CK_C_SetPIN C_SetPIN; - CK_C_OpenSession C_OpenSession; - CK_C_CloseSession C_CloseSession; - CK_C_CloseAllSessions C_CloseAllSessions; - CK_C_GetSessionInfo C_GetSessionInfo; - CK_C_GetOperationState C_GetOperationState; - CK_C_SetOperationState C_SetOperationState; - CK_C_Login C_Login; - CK_C_Logout C_Logout; - CK_C_CreateObject C_CreateObject; - CK_C_CopyObject C_CopyObject; - CK_C_DestroyObject C_DestroyObject; - CK_C_GetObjectSize C_GetObjectSize; - CK_C_GetAttributeValue C_GetAttributeValue; - CK_C_SetAttributeValue C_SetAttributeValue; - CK_C_FindObjectsInit C_FindObjectsInit; - CK_C_FindObjects C_FindObjects; - CK_C_FindObjectsFinal C_FindObjectsFinal; - CK_C_EncryptInit C_EncryptInit; - CK_C_Encrypt C_Encrypt; - CK_C_EncryptUpdate C_EncryptUpdate; - CK_C_EncryptFinal C_EncryptFinal; - CK_C_DecryptInit C_DecryptInit; - CK_C_Decrypt C_Decrypt; - CK_C_DecryptUpdate C_DecryptUpdate; - CK_C_DecryptFinal C_DecryptFinal; - CK_C_DigestInit C_DigestInit; - CK_C_Digest C_Digest; - CK_C_DigestUpdate C_DigestUpdate; - CK_C_DigestKey C_DigestKey; - CK_C_DigestFinal C_DigestFinal; - CK_C_SignInit C_SignInit; - CK_C_Sign C_Sign; - CK_C_SignUpdate C_SignUpdate; - CK_C_SignFinal C_SignFinal; - CK_C_SignRecoverInit C_SignRecoverInit; - CK_C_SignRecover C_SignRecover; - CK_C_VerifyInit C_VerifyInit; - CK_C_Verify C_Verify; - CK_C_VerifyUpdate C_VerifyUpdate; - CK_C_VerifyFinal C_VerifyFinal; - CK_C_VerifyRecoverInit C_VerifyRecoverInit; - CK_C_VerifyRecover C_VerifyRecover; - CK_C_DigestEncryptUpdate C_DigestEncryptUpdate; - CK_C_DecryptDigestUpdate C_DecryptDigestUpdate; - CK_C_SignEncryptUpdate C_SignEncryptUpdate; - CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate; - CK_C_GenerateKey C_GenerateKey; - CK_C_GenerateKeyPair C_GenerateKeyPair; - CK_C_WrapKey C_WrapKey; - CK_C_UnwrapKey C_UnwrapKey; - CK_C_DeriveKey C_DeriveKey; - CK_C_SeedRandom C_SeedRandom; - CK_C_GenerateRandom C_GenerateRandom; - CK_C_GetFunctionStatus C_GetFunctionStatus; - CK_C_CancelFunction C_CancelFunction; - CK_C_WaitForSlotEvent C_WaitForSlotEvent; -}; - - -typedef ck_rv_t (*ck_createmutex_t) (void **mutex); -typedef ck_rv_t (*ck_destroymutex_t) (void *mutex); -typedef ck_rv_t (*ck_lockmutex_t) (void *mutex); -typedef ck_rv_t (*ck_unlockmutex_t) (void *mutex); - - -struct ck_c_initialize_args -{ - ck_createmutex_t create_mutex; - ck_destroymutex_t destroy_mutex; - ck_lockmutex_t lock_mutex; - ck_unlockmutex_t unlock_mutex; - ck_flags_t flags; - void *reserved; -}; - - -#define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1 << 0) -#define CKF_OS_LOCKING_OK (1 << 1) - -#define CKR_OK (0) -#define CKR_CANCEL (1) -#define CKR_HOST_MEMORY (2) -#define CKR_SLOT_ID_INVALID (3) -#define CKR_GENERAL_ERROR (5) -#define CKR_FUNCTION_FAILED (6) -#define CKR_ARGUMENTS_BAD (7) -#define CKR_NO_EVENT (8) -#define CKR_NEED_TO_CREATE_THREADS (9) -#define CKR_CANT_LOCK (0xa) -#define CKR_ATTRIBUTE_READ_ONLY (0x10) -#define CKR_ATTRIBUTE_SENSITIVE (0x11) -#define CKR_ATTRIBUTE_TYPE_INVALID (0x12) -#define CKR_ATTRIBUTE_VALUE_INVALID (0x13) -#define CKR_DATA_INVALID (0x20) -#define CKR_DATA_LEN_RANGE (0x21) -#define CKR_DEVICE_ERROR (0x30) -#define CKR_DEVICE_MEMORY (0x31) -#define CKR_DEVICE_REMOVED (0x32) -#define CKR_ENCRYPTED_DATA_INVALID (0x40) -#define CKR_ENCRYPTED_DATA_LEN_RANGE (0x41) -#define CKR_FUNCTION_CANCELED (0x50) -#define CKR_FUNCTION_NOT_PARALLEL (0x51) -#define CKR_FUNCTION_NOT_SUPPORTED (0x54) -#define CKR_KEY_HANDLE_INVALID (0x60) -#define CKR_KEY_SIZE_RANGE (0x62) -#define CKR_KEY_TYPE_INCONSISTENT (0x63) -#define CKR_KEY_NOT_NEEDED (0x64) -#define CKR_KEY_CHANGED (0x65) -#define CKR_KEY_NEEDED (0x66) -#define CKR_KEY_INDIGESTIBLE (0x67) -#define CKR_KEY_FUNCTION_NOT_PERMITTED (0x68) -#define CKR_KEY_NOT_WRAPPABLE (0x69) -#define CKR_KEY_UNEXTRACTABLE (0x6a) -#define CKR_MECHANISM_INVALID (0x70) -#define CKR_MECHANISM_PARAM_INVALID (0x71) -#define CKR_OBJECT_HANDLE_INVALID (0x82) -#define CKR_OPERATION_ACTIVE (0x90) -#define CKR_OPERATION_NOT_INITIALIZED (0x91) -#define CKR_PIN_INCORRECT (0xa0) -#define CKR_PIN_INVALID (0xa1) -#define CKR_PIN_LEN_RANGE (0xa2) -#define CKR_PIN_EXPIRED (0xa3) -#define CKR_PIN_LOCKED (0xa4) -#define CKR_SESSION_CLOSED (0xb0) -#define CKR_SESSION_COUNT (0xb1) -#define CKR_SESSION_HANDLE_INVALID (0xb3) -#define CKR_SESSION_PARALLEL_NOT_SUPPORTED (0xb4) -#define CKR_SESSION_READ_ONLY (0xb5) -#define CKR_SESSION_EXISTS (0xb6) -#define CKR_SESSION_READ_ONLY_EXISTS (0xb7) -#define CKR_SESSION_READ_WRITE_SO_EXISTS (0xb8) -#define CKR_SIGNATURE_INVALID (0xc0) -#define CKR_SIGNATURE_LEN_RANGE (0xc1) -#define CKR_TEMPLATE_INCOMPLETE (0xd0) -#define CKR_TEMPLATE_INCONSISTENT (0xd1) -#define CKR_TOKEN_NOT_PRESENT (0xe0) -#define CKR_TOKEN_NOT_RECOGNIZED (0xe1) -#define CKR_TOKEN_WRITE_PROTECTED (0xe2) -#define CKR_UNWRAPPING_KEY_HANDLE_INVALID (0xf0) -#define CKR_UNWRAPPING_KEY_SIZE_RANGE (0xf1) -#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT (0xf2) -#define CKR_USER_ALREADY_LOGGED_IN (0x100) -#define CKR_USER_NOT_LOGGED_IN (0x101) -#define CKR_USER_PIN_NOT_INITIALIZED (0x102) -#define CKR_USER_TYPE_INVALID (0x103) -#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN (0x104) -#define CKR_USER_TOO_MANY_TYPES (0x105) -#define CKR_WRAPPED_KEY_INVALID (0x110) -#define CKR_WRAPPED_KEY_LEN_RANGE (0x112) -#define CKR_WRAPPING_KEY_HANDLE_INVALID (0x113) -#define CKR_WRAPPING_KEY_SIZE_RANGE (0x114) -#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT (0x115) -#define CKR_RANDOM_SEED_NOT_SUPPORTED (0x120) -#define CKR_RANDOM_NO_RNG (0x121) -#define CKR_DOMAIN_PARAMS_INVALID (0x130) -#define CKR_BUFFER_TOO_SMALL (0x150) -#define CKR_SAVED_STATE_INVALID (0x160) -#define CKR_INFORMATION_SENSITIVE (0x170) -#define CKR_STATE_UNSAVEABLE (0x180) -#define CKR_CRYPTOKI_NOT_INITIALIZED (0x190) -#define CKR_CRYPTOKI_ALREADY_INITIALIZED (0x191) -#define CKR_MUTEX_BAD (0x1a0) -#define CKR_MUTEX_NOT_LOCKED (0x1a1) -#define CKR_FUNCTION_REJECTED (0x200) -#define CKR_VENDOR_DEFINED ((unsigned long) (1 << 31)) - - - -/* Compatibility layer. */ - -#ifdef CRYPTOKI_COMPAT - -#undef CK_DEFINE_FUNCTION -#define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name - -/* For NULL. */ -#include - -typedef unsigned char CK_BYTE; -typedef unsigned char CK_CHAR; -typedef unsigned char CK_UTF8CHAR; -typedef unsigned char CK_BBOOL; -typedef unsigned long int CK_ULONG; -typedef long int CK_LONG; -typedef CK_BYTE *CK_BYTE_PTR; -typedef CK_CHAR *CK_CHAR_PTR; -typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR; -typedef CK_ULONG *CK_ULONG_PTR; -typedef void *CK_VOID_PTR; -typedef void **CK_VOID_PTR_PTR; -#define CK_FALSE 0 -#define CK_TRUE 1 -#ifndef CK_DISABLE_TRUE_FALSE -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif -#endif - -typedef struct ck_version CK_VERSION; -typedef struct ck_version *CK_VERSION_PTR; - -typedef struct ck_info CK_INFO; -typedef struct ck_info *CK_INFO_PTR; - -typedef ck_slot_id_t *CK_SLOT_ID_PTR; - -typedef struct ck_slot_info CK_SLOT_INFO; -typedef struct ck_slot_info *CK_SLOT_INFO_PTR; - -typedef struct ck_token_info CK_TOKEN_INFO; -typedef struct ck_token_info *CK_TOKEN_INFO_PTR; - -typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR; - -typedef struct ck_session_info CK_SESSION_INFO; -typedef struct ck_session_info *CK_SESSION_INFO_PTR; - -typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR; - -typedef ck_object_class_t *CK_OBJECT_CLASS_PTR; - -typedef struct ck_attribute CK_ATTRIBUTE; -typedef struct ck_attribute *CK_ATTRIBUTE_PTR; - -typedef struct ck_date CK_DATE; -typedef struct ck_date *CK_DATE_PTR; - -typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR; - -typedef struct ck_mechanism CK_MECHANISM; -typedef struct ck_mechanism *CK_MECHANISM_PTR; - -typedef struct ck_mechanism_info CK_MECHANISM_INFO; -typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR; - -typedef struct ck_function_list CK_FUNCTION_LIST; -typedef struct ck_function_list *CK_FUNCTION_LIST_PTR; -typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR; - -typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS; -typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; - -#define NULL_PTR NULL - -/* Delete the helper macros defined at the top of the file. */ -#undef ck_flags_t -#undef ck_version - -#undef ck_info -#undef cryptoki_version -#undef manufacturer_id -#undef library_description -#undef library_version - -#undef ck_notification_t -#undef ck_slot_id_t - -#undef ck_slot_info -#undef slot_description -#undef hardware_version -#undef firmware_version - -#undef ck_token_info -#undef serial_number -#undef max_session_count -#undef session_count -#undef max_rw_session_count -#undef rw_session_count -#undef max_pin_len -#undef min_pin_len -#undef total_public_memory -#undef free_public_memory -#undef total_private_memory -#undef free_private_memory -#undef utc_time - -#undef ck_session_handle_t -#undef ck_user_type_t -#undef ck_state_t - -#undef ck_session_info -#undef slot_id -#undef device_error - -#undef ck_object_handle_t -#undef ck_object_class_t -#undef ck_hw_feature_type_t -#undef ck_key_type_t -#undef ck_certificate_type_t -#undef ck_attribute_type_t - -#undef ck_attribute -#undef value -#undef value_len - -#undef ck_date - -#undef ck_mechanism_type_t - -#undef ck_mechanism -#undef parameter -#undef parameter_len - -#undef ck_mechanism_info -#undef min_key_size -#undef max_key_size - -#undef ck_rv_t -#undef ck_notify_t - -#undef ck_function_list - -#undef ck_createmutex_t -#undef ck_destroymutex_t -#undef ck_lockmutex_t -#undef ck_unlockmutex_t - -#undef ck_c_initialize_args -#undef create_mutex -#undef destroy_mutex -#undef lock_mutex -#undef unlock_mutex -#undef reserved - -#endif /* CRYPTOKI_COMPAT */ - - -/* System dependencies. */ -#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) -#pragma pack(pop, cryptoki) -#endif - -#if defined(__cplusplus) -} -#endif - -#endif /* PKCS11_H */ diff --git a/pkcs11/pkcs11n.h b/pkcs11/pkcs11n.h deleted file mode 100644 index d611d75..0000000 --- a/pkcs11/pkcs11n.h +++ /dev/null @@ -1,221 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Dr Stephen Henson - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef _PKCS11N_H_ -#define _PKCS11N_H_ - -#ifdef DEBUG -static const char CKT_CVS_ID[] = "@(#) $RCSfile: pkcs11n.h,v $ $Revision: 1.15 $ $Date: 2005/09/28 17:12:17 $"; -#endif /* DEBUG */ - -/* - * pkcs11n.h - * - * This file contains the NSS-specific type definitions for Cryptoki - * (PKCS#11). - */ - -/* - * NSSCK_VENDOR_NETSCAPE - * - * Cryptoki reserves the high half of all the number spaces for - * vendor-defined use. I'd like to keep all of our Netscape- - * specific values together, but not in the oh-so-obvious - * 0x80000001, 0x80000002, etc. area. So I've picked an offset, - * and constructed values for the beginnings of our spaces. - * - * Note that some "historical" Netscape values don't fall within - * this range. - */ -#define NSSCK_VENDOR_NETSCAPE 0x4E534350 /* NSCP */ - -/* - * Netscape-defined object classes - * - */ -#define CKO_NETSCAPE (CKO_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -#define CKO_NETSCAPE_CRL (CKO_NETSCAPE + 1) -#define CKO_NETSCAPE_SMIME (CKO_NETSCAPE + 2) -#define CKO_NETSCAPE_TRUST (CKO_NETSCAPE + 3) -#define CKO_NETSCAPE_BUILTIN_ROOT_LIST (CKO_NETSCAPE + 4) -#define CKO_NETSCAPE_NEWSLOT (CKO_NETSCAPE + 5) -#define CKO_NETSCAPE_DELSLOT (CKO_NETSCAPE + 6) - -/* - * Netscape-defined key types - * - */ -#define CKK_NETSCAPE (CKK_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -#define CKK_NETSCAPE_PKCS8 (CKK_NETSCAPE + 1) -/* - * Netscape-defined certificate types - * - */ -#define CKC_NETSCAPE (CKC_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -/* - * Netscape-defined object attributes - * - */ -#define CKA_NETSCAPE (CKA_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -#define CKA_NETSCAPE_URL (CKA_NETSCAPE + 1) -#define CKA_NETSCAPE_EMAIL (CKA_NETSCAPE + 2) -#define CKA_NETSCAPE_SMIME_INFO (CKA_NETSCAPE + 3) -#define CKA_NETSCAPE_SMIME_TIMESTAMP (CKA_NETSCAPE + 4) -#define CKA_NETSCAPE_PKCS8_SALT (CKA_NETSCAPE + 5) -#define CKA_NETSCAPE_PASSWORD_CHECK (CKA_NETSCAPE + 6) -#define CKA_NETSCAPE_EXPIRES (CKA_NETSCAPE + 7) -#define CKA_NETSCAPE_KRL (CKA_NETSCAPE + 8) - -#define CKA_NETSCAPE_PQG_COUNTER (CKA_NETSCAPE + 20) -#define CKA_NETSCAPE_PQG_SEED (CKA_NETSCAPE + 21) -#define CKA_NETSCAPE_PQG_H (CKA_NETSCAPE + 22) -#define CKA_NETSCAPE_PQG_SEED_BITS (CKA_NETSCAPE + 23) -#define CKA_NETSCAPE_MODULE_SPEC (CKA_NETSCAPE + 24) - -/* - * Trust attributes: - * - * If trust goes standard, these probably will too. So I'll - * put them all in one place. - */ - -#define CKA_TRUST (CKA_NETSCAPE + 0x2000) - -/* "Usage" key information */ -#define CKA_TRUST_DIGITAL_SIGNATURE (CKA_TRUST + 1) -#define CKA_TRUST_NON_REPUDIATION (CKA_TRUST + 2) -#define CKA_TRUST_KEY_ENCIPHERMENT (CKA_TRUST + 3) -#define CKA_TRUST_DATA_ENCIPHERMENT (CKA_TRUST + 4) -#define CKA_TRUST_KEY_AGREEMENT (CKA_TRUST + 5) -#define CKA_TRUST_KEY_CERT_SIGN (CKA_TRUST + 6) -#define CKA_TRUST_CRL_SIGN (CKA_TRUST + 7) - -/* "Purpose" trust information */ -#define CKA_TRUST_SERVER_AUTH (CKA_TRUST + 8) -#define CKA_TRUST_CLIENT_AUTH (CKA_TRUST + 9) -#define CKA_TRUST_CODE_SIGNING (CKA_TRUST + 10) -#define CKA_TRUST_EMAIL_PROTECTION (CKA_TRUST + 11) -#define CKA_TRUST_IPSEC_END_SYSTEM (CKA_TRUST + 12) -#define CKA_TRUST_IPSEC_TUNNEL (CKA_TRUST + 13) -#define CKA_TRUST_IPSEC_USER (CKA_TRUST + 14) -#define CKA_TRUST_TIME_STAMPING (CKA_TRUST + 15) -#define CKA_TRUST_STEP_UP_APPROVED (CKA_TRUST + 16) - -#define CKA_CERT_SHA1_HASH (CKA_TRUST + 100) -#define CKA_CERT_MD5_HASH (CKA_TRUST + 101) - -/* Netscape trust stuff */ -/* XXX fgmr new ones here-- step-up, etc. */ - -/* HISTORICAL: define used to pass in the database key for DSA private keys */ -#define CKA_NETSCAPE_DB 0xD5A0DB00L -#define CKA_NETSCAPE_TRUST 0x80000001L - -/* - * Netscape-defined crypto mechanisms - * - */ -#define CKM_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -#define CKM_NETSCAPE_AES_KEY_WRAP (CKM_NETSCAPE + 1) -#define CKM_NETSCAPE_AES_KEY_WRAP_PAD (CKM_NETSCAPE + 2) - -/* - * HISTORICAL: - * Do not attempt to use these. They are only used by NETSCAPE's internal - * PKCS #11 interface. Most of these are place holders for other mechanism - * and will change in the future. - */ -#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002L -#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003L -#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004L -#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005L -#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006L -#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007L -#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008L -#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009L -#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aL -#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bL - -#define CKM_TLS_PRF_GENERAL 0x80000373L - -/* - * Netscape-defined return values - * - */ -#define CKR_NETSCAPE (CKM_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -#define CKR_NETSCAPE_CERTDB_FAILED (CKR_NETSCAPE + 1) -#define CKR_NETSCAPE_KEYDB_FAILED (CKR_NETSCAPE + 2) - -/* - * Trust info - * - * This isn't part of the Cryptoki standard (yet), so I'm putting - * all the definitions here. Some of this would move to nssckt.h - * if trust info were made part of the standard. In view of this - * possibility, I'm putting my (Netscape) values in the netscape - * vendor space, like everything else. - */ - -typedef CK_ULONG CK_TRUST; - -/* The following trust types are defined: */ -#define CKT_VENDOR_DEFINED 0x80000000 - -#define CKT_NETSCAPE (CKT_VENDOR_DEFINED|NSSCK_VENDOR_NETSCAPE) - -/* If trust goes standard, these'll probably drop out of vendor space. */ -#define CKT_NETSCAPE_TRUSTED (CKT_NETSCAPE + 1) -#define CKT_NETSCAPE_TRUSTED_DELEGATOR (CKT_NETSCAPE + 2) -#define CKT_NETSCAPE_UNTRUSTED (CKT_NETSCAPE + 3) -#define CKT_NETSCAPE_MUST_VERIFY (CKT_NETSCAPE + 4) -#define CKT_NETSCAPE_TRUST_UNKNOWN (CKT_NETSCAPE + 5) /* default */ - -/* - * These may well remain Netscape-specific; I'm only using them - * to cache resolution data. - */ -#define CKT_NETSCAPE_VALID (CKT_NETSCAPE + 10) -#define CKT_NETSCAPE_VALID_DELEGATOR (CKT_NETSCAPE + 11) - - -#endif /* _PKCS11N_H_ */ diff --git a/x509-usages.h b/x509-usages.h deleted file mode 100644 index e06309b..0000000 --- a/x509-usages.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2007 Nate Nielsen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _X509_USAGES_H_ -#define _X509_USAGES_H_ - - -#define X509_USAGE_SERVER_AUTH "1.3.6.1.5.5.7.3.1" -#define X509_USAGE_CLIENT_AUTH "1.3.6.1.5.5.7.3.2" -#define X509_USAGE_CODE_SIGNING "1.3.6.1.5.5.7.3.3" -#define X509_USAGE_EMAIL "1.3.6.1.5.5.7.3.4" -#define X509_USAGE_TIME_STAMPING "1.3.6.1.5.5.7.3.8" -#define X509_USAGE_IPSEC_ENDPOINT "1.3.6.1.5.5.7.3.5" -#define X509_USAGE_IPSEC_TUNNEL "1.3.6.1.5.5.7.3.6" -#define X509_USAGE_IPSEC_USER "1.3.6.1.5.5.7.3.7" -#define X509_USAGE_IKE_INTERMEDIATE "1.3.6.1.5.5.8.2.2" - - -#define MS_USAGE_TRUST_LIST_SIGNING "1.3.6.1.4.1.311.10.3.1" -#define MS_USAGE_TIME_STAMPING "1.3.6.1.4.1.311.10.3.2" -#define MS_USAGE_EFS "1.3.6.1.4.1.311.10.3.4" -#define MS_USAGE_DRIVER_VERIFICATION "1.3.6.1.4.1.311.10.3.5" -#define MS_USAGE_SYSTEM_VERIFICATION "1.3.6.1.4.1.311.10.3.6" -#define MS_USAGE_OEM_VERIFICATION "1.3.6.1.4.1.311.10.3.7" -#define MS_USAGE_EMBEDDED_VERIFICATION "1.3.6.1.4.1.311.10.3.8" -#define MS_USAGE_KEY_PACK "1.3.6.1.4.1.311.10.6.1" -#define MS_USAGE_LICENSE_SERVER "1.3.6.1.4.1.311.10.6.2" -#define MS_USAGE_SMART_CARD "1.3.6.1.4.1.311.20.2.2" -#define MS_USAGE_DIGITAL_RIGHTS "1.3.6.1.4.1.311.10.5.1" -#define MS_USAGE_QUALIFIED_SUBORDINATION "1.3.6.1.4.1.311.10.3.10" -#define MS_USAGE_KEY_RECOVERY "1.3.6.1.4.1.311.10.3.11" -#define MS_USAGE_DOCUMENT_SIGNING "1.3.6.1.4.1.311.10.3.12" -#define MS_USAGE_FILE_RECOVERY "1.3.6.1.4.1.311.10.3.4.1" -#define MS_USAGE_ROOT_SIGNER_LIST "1.3.6.1.4.1.311.10.3.9" -#define MS_USAGE_APPLICATION_POLICIES "1.3.6.1.4.1.311.10.12.1" -#define MS_USAGE_AD_EMAIL_REPLICATION "1.3.6.1.4.1.311.21.19" -#define MS_USAGE_CERTIFICATE_REQUEST_AGENT "1.3.6.1.4.1.311.20.2.1" -#define MS_USAGE_KEY_RECOVERY_AGENT "1.3.6.1.4.1.311.21.6" -#define MS_USAGE_CA_ENCRYPTION_CERTIFICATE "1.3.6.1.4.1.311.21.5" -#define MS_USAGE_LIFETIME_SIGNING "1.3.6.1.4.1.311.10.3.13" - -#endif /* _X509_USAGES_H_ */ -- cgit v1.2.3