[SmartcardServices-Changes] [72] trunk/SmartCardServices/src
source_changes at macosforge.org
source_changes at macosforge.org
Thu Dec 17 00:49:39 PST 2009
Revision: 72
http://trac.macosforge.org/projects/smartcardservices/changeset/72
Author: ludovic.rousseau at gmail.com
Date: 2009-12-17 00:49:36 -0800 (Thu, 17 Dec 2009)
Log Message:
-----------
Add Gemalto PKCS#11 module for .net v2 cards.
The library is licensed GNU LGPL v2.1.
Closes ticket #18
Added Paths:
-----------
trunk/SmartCardServices/src/PKCS11dotNetV2/
trunk/SmartCardServices/src/PKCS11dotNetV2/LGPL-2.1
trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/Makefile.am
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/config.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11f.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11t.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/platconfig.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/resource.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_global.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/ha_config.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.h
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.h
trunk/SmartCardServices/src/PKCS11dotNetV2/aclocal.m4
trunk/SmartCardServices/src/PKCS11dotNetV2/acx_pthread.m4
trunk/SmartCardServices/src/PKCS11dotNetV2/autogen.sh
trunk/SmartCardServices/src/PKCS11dotNetV2/c-mac.sh
trunk/SmartCardServices/src/PKCS11dotNetV2/configure.in
trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/
trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.h
trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Except.h
trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.h
trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/MarshallerCfg.h
trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.cpp
trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.h
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/LGPL-2.1
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/LGPL-2.1 (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/LGPL-2.1 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,510 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+ Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/Makefile.am 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,3 @@
+SUBDIRS = PKCS11Module2
+
+EXTRA_DIST = autogen.sh c-mac.sh LGPL-2.1
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/Makefile.am
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/Makefile.am (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/Makefile.am 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,136 @@
+lib_LTLIBRARIES = libgtop11dotnet.la
+
+libgtop11dotnet_la_LDFLAGS = -shared
+
+libgtop11dotnet_la_SOURCES = \
+ $(top_srcdir)/cppMarshaller/Array.cpp \
+ $(top_srcdir)/cppMarshaller/Array.h \
+ $(top_srcdir)/cppMarshaller/Except.h \
+ $(top_srcdir)/cppMarshaller/MarshallerCfg.h \
+ $(top_srcdir)/cppMarshaller/Marshaller.cpp \
+ $(top_srcdir)/cppMarshaller/Marshaller.h \
+ $(top_srcdir)/cppMarshaller/PCSC.cpp \
+ $(top_srcdir)/cppMarshaller/PCSC.h \
+ algo_des.cpp \
+ algo_des.h \
+ algo_md5.cpp \
+ algo_md5.h \
+ algo_sha1.cpp \
+ algo_sha1.h \
+ algo_sha256.cpp \
+ algo_sha256.h \
+ algo_utils.cpp \
+ algo_utils.h \
+ application.cpp \
+ application.h \
+ attrcert.cpp \
+ attrcert.h \
+ beroctet.cpp \
+ beroctet.h \
+ cardcache.cpp \
+ cardcache.h \
+ cardmoduleservice.cpp \
+ cardmoduleservice.h \
+ certificateobject.cpp \
+ certificateobject.h \
+ cert_utils.cpp \
+ cert_utils.h \
+ config.h \
+ critsect.cpp \
+ critsect.h \
+ dataobject.cpp \
+ dataobject.h \
+ des.cpp \
+ des.h \
+ digest.cpp \
+ digest.h \
+ error.cpp \
+ error.h \
+ event.cpp \
+ event.h \
+ keyobject.cpp \
+ keyobject.h \
+ md5.cpp \
+ md5.h \
+ mutex.cpp \
+ mutex.h \
+ pkcs11.cpp \
+ pkcs11f.h \
+ pkcs11.h \
+ pkcs11t.h \
+ platconfig.h \
+ privatekeyobject.cpp \
+ privatekeyobject.h \
+ publickeyobject.cpp \
+ publickeyobject.h \
+ resource.h \
+ rsa/cr_digit.cpp \
+ rsa/cr_digit.h \
+ rsa/cr_global.h \
+ rsa/cr_nn.cpp \
+ rsa/cr_nn.h \
+ rsa/cr_random.cpp \
+ rsa/cr_random.h \
+ rsa/cr_rsa.cpp \
+ rsa/cr_rsa.h \
+ rsa/ha_config.h \
+ rsaprivatekeyobject.cpp \
+ rsaprivatekeyobject.h \
+ rsapublickeyobject.cpp \
+ rsapublickeyobject.h \
+ sctoken.cpp \
+ sctoken.h \
+ secretkeyobject.cpp \
+ secretkeyobject.h \
+ session.cpp \
+ session.h \
+ sha1.cpp \
+ sha1.h \
+ sha256.cpp \
+ sha256.h \
+ slot.cpp \
+ slot.h \
+ stdafx.cpp \
+ stdafx.h \
+ storageobject.cpp \
+ storageobject.h \
+ symmalgo.cpp \
+ symmalgo.h \
+ tdes.cpp \
+ tdes.h \
+ template.cpp \
+ template.h \
+ thread.cpp \
+ thread.h \
+ timer.cpp \
+ timer.h \
+ transaction.cpp \
+ transaction.h \
+ util.cpp \
+ util.h \
+ x509cert.cpp \
+ x509cert.h \
+ x509pubkeycertobject.cpp \
+ x509pubkeycertobject.h \
+ log.h \
+ log.cpp
+
+AM_CPPFLAGS = -DINCLUDE_EVENTING=1 -DCRYPTOKI_EXPORTS=1 \
+ -DUNIX $(PTHREAD_CFLAGS) \
+ -Wall \
+ -Wextra \
+ -pedantic
+
+INCLUDES = \
+ -I$(top_srcdir)/cppMarshaller \
+ -I$(top_srcdir)/PKCS11Module2 \
+ -I$(top_srcdir)/PKCS11Module2/rsa \
+ $(PCSC_CFLAGS)
+
+LIBS = $(PCSC_LIBS) $(PTHREAD_LIBS) -lz
+
+# see http://wiki.cacert.org/wiki/Pkcs11TaskForce
+install-exec-hook:
+ $(MKDIR_P) $(DESTDIR)/$(prefix)/lib/pkcs11
+ cd $(DESTDIR)/$(prefix)/lib/pkcs11 ; rm -f libgtop11dotnet. at DYN_LIB_EXT@ ; $(LN_S) ../libgtop11dotnet. at DYN_LIB_EXT@
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,410 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_des.h"
+
+typedef struct _DES_Context
+{
+ u4 encrypt_subkeys[32];
+ u4 decrypt_subkeys[32];
+} _DES_Context;
+
+typedef struct _3DES_Context
+{
+ u4 encrypt_subkeys[96];
+ u4 decrypt_subkeys[96];
+} _3DES_Context;
+
+/*
+ * The s-box values are permuted according to the 'primitive function P'
+ * and are rotated one bit to the left.
+ */
+static const u4 sbox1[64] =
+{
+ 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000,
+ 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004,
+ 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404,
+ 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000,
+ 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400,
+ 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404,
+ 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400,
+ 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004
+};
+
+static const u4 sbox2[64] =
+{
+ 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020,
+ 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020,
+ 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000,
+ 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020,
+ 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000,
+ 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000,
+ 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020,
+ 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000
+};
+
+static const u4 sbox3[64] =
+{
+ 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200,
+ 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208,
+ 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208,
+ 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000,
+ 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000,
+ 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008,
+ 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008,
+ 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200
+};
+
+static const u4 sbox4[64] =
+{
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001,
+ 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001,
+ 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080,
+ 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081,
+ 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000,
+ 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081,
+ 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080
+};
+
+static const u4 sbox5[64] =
+{
+ 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000,
+ 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000,
+ 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100,
+ 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100,
+ 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100,
+ 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000,
+ 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000,
+ 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100
+};
+
+static const u4 sbox6[64] =
+{
+ 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000,
+ 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010,
+ 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010,
+ 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000,
+ 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010,
+ 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000,
+ 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010,
+ 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010
+};
+
+static const u4 sbox7[64] =
+{
+ 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800,
+ 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802,
+ 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002,
+ 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800,
+ 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002,
+ 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800,
+ 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802,
+ 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002
+};
+
+static const u4 sbox8[64] =
+{
+ 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000,
+ 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040,
+ 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000,
+ 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000,
+ 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040,
+ 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040,
+ 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000,
+ 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000
+};
+
+static const u4 leftkey_swap[16] =
+{
+ 0x00000000, 0x00000001, 0x00000100, 0x00000101,
+ 0x00010000, 0x00010001, 0x00010100, 0x00010101,
+ 0x01000000, 0x01000001, 0x01000100, 0x01000101,
+ 0x01010000, 0x01010001, 0x01010100, 0x01010101
+};
+
+static const u4 rightkey_swap[16] =
+{
+ 0x00000000, 0x01000000, 0x00010000, 0x01010000,
+ 0x00000100, 0x01000100, 0x00010100, 0x01010100,
+ 0x00000001, 0x01000001, 0x00010001, 0x01010001,
+ 0x00000101, 0x01000101, 0x00010101, 0x01010101,
+};
+
+static const u1 encrypt_rotate_tab[16] =
+{
+ 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
+};
+
+#define DO_PERMUTATION(a, temp, b, offset, mask) \
+ temp = ((a>>offset) ^ b) & mask; \
+ b ^= temp; \
+ a ^= temp<<offset;
+
+#define INITIAL_PERMUTATION(left, temp, right) \
+ DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \
+ DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \
+ DO_PERMUTATION(right, temp, left, 2, 0x33333333) \
+ DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \
+ right = (right << 1) | (right >> 31); \
+ temp = (left ^ right) & 0xaaaaaaaa; \
+ right ^= temp; \
+ left ^= temp; \
+ left = (left << 1) | (left >> 31);
+
+#define FINAL_PERMUTATION(left, temp, right) \
+ left = (left << 31) | (left >> 1); \
+ temp = (left ^ right) & 0xaaaaaaaa; \
+ left ^= temp; \
+ right ^= temp; \
+ right = (right << 31) | (right >> 1); \
+ DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \
+ DO_PERMUTATION(right, temp, left, 2, 0x33333333) \
+ DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \
+ DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f)
+
+#define DES_ROUND(from, to, work, subkey) \
+ work = from ^ *subkey++; \
+ to ^= sbox8[ work & 0x3f ]; \
+ to ^= sbox6[ (work>>8) & 0x3f ]; \
+ to ^= sbox4[ (work>>16) & 0x3f ]; \
+ to ^= sbox2[ (work>>24) & 0x3f ]; \
+ work = ((from << 28) | (from >> 4)) ^ *subkey++; \
+ to ^= sbox7[ work & 0x3f ]; \
+ to ^= sbox5[ (work>>8) & 0x3f ]; \
+ to ^= sbox3[ (work>>16) & 0x3f ]; \
+ to ^= sbox1[ (work>>24) & 0x3f ];
+
+#define READ_64BIT_DATA(data, left, right) \
+ left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \
+ right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7];
+
+#define WRITE_64BIT_DATA(data, left, right) \
+ data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \
+ data[2] = (left >> 8) &0xff; data[3] = left &0xff; \
+ data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \
+ data[6] = (right >> 8) &0xff; data[7] = right &0xff;
+
+
+static void algo_DES_KeySchedule(const u1 * rawkey, u4 * subkey)
+{
+ u4 left, right, work;
+ u1 round;
+
+ READ_64BIT_DATA (rawkey, left, right)
+
+ DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f)
+ DO_PERMUTATION (right, work, left, 0, 0x10101010)
+
+ left = (leftkey_swap[(left >> 0) & 0xf] << 3) | (leftkey_swap[(left >> 8) & 0xf] << 2)
+ | (leftkey_swap[(left >> 16) & 0xf] << 1) | (leftkey_swap[(left >> 24) & 0xf])
+ | (leftkey_swap[(left >> 5) & 0xf] << 7) | (leftkey_swap[(left >> 13) & 0xf] << 6)
+ | (leftkey_swap[(left >> 21) & 0xf] << 5) | (leftkey_swap[(left >> 29) & 0xf] << 4);
+
+ left &= 0x0fffffff;
+
+ right = (rightkey_swap[(right >> 1) & 0xf] << 3) | (rightkey_swap[(right >> 9) & 0xf] << 2)
+ | (rightkey_swap[(right >> 17) & 0xf] << 1) | (rightkey_swap[(right >> 25) & 0xf])
+ | (rightkey_swap[(right >> 4) & 0xf] << 7) | (rightkey_swap[(right >> 12) & 0xf] << 6)
+ | (rightkey_swap[(right >> 20) & 0xf] << 5) | (rightkey_swap[(right >> 28) & 0xf] << 4);
+
+ right &= 0x0fffffff;
+
+ for (round = 0; round < 16; ++round) {
+
+ left = ((left << encrypt_rotate_tab[round]) | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff;
+ right = ((right << encrypt_rotate_tab[round]) | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff;
+
+ *subkey++ = ((left << 4) & 0x24000000)
+ | ((left << 28) & 0x10000000)
+ | ((left << 14) & 0x08000000)
+ | ((left << 18) & 0x02080000)
+ | ((left << 6) & 0x01000000)
+ | ((left << 9) & 0x00200000)
+ | ((left >> 1) & 0x00100000)
+ | ((left << 10) & 0x00040000)
+ | ((left << 2) & 0x00020000)
+ | ((left >> 10) & 0x00010000)
+ | ((right >> 13) & 0x00002000)
+ | ((right >> 4) & 0x00001000)
+ | ((right << 6) & 0x00000800)
+ | ((right >> 1) & 0x00000400)
+ | ((right >> 14) & 0x00000200)
+ | (right & 0x00000100)
+ | ((right >> 5) & 0x00000020)
+ | ((right >> 10) & 0x00000010)
+ | ((right >> 3) & 0x00000008)
+ | ((right >> 18) & 0x00000004)
+ | ((right >> 26) & 0x00000002)
+ | ((right >> 24) & 0x00000001);
+
+ *subkey++ = ((left << 15) & 0x20000000)
+ | ((left << 17) & 0x10000000)
+ | ((left << 10) & 0x08000000)
+ | ((left << 22) & 0x04000000)
+ | ((left >> 2) & 0x02000000)
+ | ((left << 1) & 0x01000000)
+ | ((left << 16) & 0x00200000)
+ | ((left << 11) & 0x00100000)
+ | ((left << 3) & 0x00080000)
+ | ((left >> 6) & 0x00040000)
+ | ((left << 15) & 0x00020000)
+ | ((left >> 4) & 0x00010000)
+ | ((right >> 2) & 0x00002000)
+ | ((right << 8) & 0x00001000)
+ | ((right >> 14) & 0x00000808)
+ | ((right >> 9) & 0x00000400)
+ | ((right) & 0x00000200)
+ | ((right << 7) & 0x00000100)
+ | ((right >> 7) & 0x00000020)
+ | ((right >> 3) & 0x00000011)
+ | ((right << 2) & 0x00000004)
+ | ((right >> 21) & 0x00000002);
+ }
+}
+
+static void algo_DES_Setkey(_DES_Context *ctx, const u1 * key)
+{
+ u1 i;
+
+ algo_DES_KeySchedule(key, ctx->encrypt_subkeys);
+
+ for(i = 0; i < 32; i += 2) {
+ ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i];
+ ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i];
+ }
+}
+
+static void algo_DES_Set2keys(_3DES_Context *ctx, const u1 * key1, const u1 * key2)
+{
+ u1 i;
+
+ algo_DES_KeySchedule(key1, ctx->encrypt_subkeys);
+ algo_DES_KeySchedule(key2, &(ctx->decrypt_subkeys[32]));
+
+ for(i = 0; i < 32; i += 2) {
+ ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i];
+ ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i];
+
+ ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i];
+ ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i];
+
+ ctx->encrypt_subkeys[i+64] = ctx->encrypt_subkeys[i];
+ ctx->encrypt_subkeys[i+65] = ctx->encrypt_subkeys[i+1];
+
+ ctx->decrypt_subkeys[i+64] = ctx->decrypt_subkeys[i];
+ ctx->decrypt_subkeys[i+65] = ctx->decrypt_subkeys[i+1];
+ }
+}
+
+static void algo_DES_Set3keys(_3DES_Context *ctx, const u1 * key1, const u1 * key2, const u1 * key3)
+{
+ u1 i;
+
+ algo_DES_KeySchedule(key1, ctx->encrypt_subkeys);
+ algo_DES_KeySchedule(key2, &(ctx->decrypt_subkeys[32]));
+ algo_DES_KeySchedule(key3, &(ctx->encrypt_subkeys[64]));
+
+ for(i = 0; i < 32; i += 2) {
+ ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[94-i];
+ ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[95-i];
+ ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i];
+ ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i];
+ ctx->decrypt_subkeys[i+64] = ctx->encrypt_subkeys[30-i];
+ ctx->decrypt_subkeys[i+65] = ctx->encrypt_subkeys[31-i];
+ }
+}
+
+void algo_DES_DESProcess(u1* key, u1* from, u1* to, u1 mode)
+{
+ _DES_Context ctx;
+ u4 left, right, work;
+ u4 *keys;
+
+ algo_DES_Setkey(&ctx, key);
+
+ keys = (mode == TRUE) ? ctx.encrypt_subkeys : ctx.decrypt_subkeys;
+
+ READ_64BIT_DATA(from, left, right)
+ INITIAL_PERMUTATION(left, work, right)
+
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+
+ FINAL_PERMUTATION(right, work, left)
+ WRITE_64BIT_DATA(to, right, left)
+}
+
+void algo_DES_3DESProcess(u1 keyLength, u1* key, u1 * from, u1 * to, u1 mode)
+{
+ _3DES_Context ctx;
+ u4 left, right, work;
+ u4 *keys;
+
+ if (keyLength == 0x10) {
+ algo_DES_Set2keys(&ctx, &key[0], &key[8]);
+ } else {
+ algo_DES_Set3keys(&ctx, &key[0], &key[8], &key[16]);
+ }
+
+ keys = (mode == TRUE) ? ctx.encrypt_subkeys : ctx.decrypt_subkeys;
+
+ READ_64BIT_DATA(from, left, right)
+ INITIAL_PERMUTATION(left, work, right)
+
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+
+ DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+ DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+ DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+ DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+ DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+ DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+ DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+ DES_ROUND(left, right, work, keys) DES_ROUND(right, left, work, keys)
+
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+ DES_ROUND(right, left, work, keys) DES_ROUND(left, right, work, keys)
+
+ FINAL_PERMUTATION(right, work, left)
+ WRITE_64BIT_DATA(to, right, left)
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_des.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,28 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_algo_des_h
+#define _include_algo_des_h
+
+extern void algo_DES_DESProcess(u1* key, u1* input, u1* output, u1 mode);
+extern void algo_DES_3DESProcess(u1 keyLength, u1* key, u1* input, u1* output, u1 mode);
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,225 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_utils.h"
+#include "algo_md5.h"
+
+const u1 md5_padding[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#define md5_S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define md5_P(a,b,c,d,k,s,t) {a += F(b,c,d) + data[k] + t; a = md5_S(a,s) + b;}
+
+void algo_md5_starts(algo_md5_context* ctx)
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->digest[0] = 0x67452301;
+ ctx->digest[1] = 0xEFCDAB89;
+ ctx->digest[2] = 0x98BADCFE;
+ ctx->digest[3] = 0x10325476;
+}
+
+
+static void algo_md5_compress(algo_md5_context *ctx, u4* data)
+{
+ u4 A, B, C, D;
+
+ // big endian processing
+ if (IS_BIG_ENDIAN)
+ {
+ u1 i;
+ for (i = 0; i < (MD5_BLOCK_LENGTH / sizeof(u4)); i++) {
+ data[i] = swapbytes_u4(data[i]);
+ }
+ }
+
+ A = ctx->digest[0];
+ B = ctx->digest[1];
+ C = ctx->digest[2];
+ D = ctx->digest[3];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+
+ md5_P(A, B, C, D, 0, 7, 0xD76AA478);
+ md5_P(D, A, B, C, 1, 12, 0xE8C7B756);
+ md5_P(C, D, A, B, 2, 17, 0x242070DB);
+ md5_P(B, C, D, A, 3, 22, 0xC1BDCEEE);
+ md5_P(A, B, C, D, 4, 7, 0xF57C0FAF);
+ md5_P(D, A, B, C, 5, 12, 0x4787C62A);
+ md5_P(C, D, A, B, 6, 17, 0xA8304613);
+ md5_P(B, C, D, A, 7, 22, 0xFD469501);
+ md5_P(A, B, C, D, 8, 7, 0x698098D8);
+ md5_P(D, A, B, C, 9, 12, 0x8B44F7AF);
+ md5_P(C, D, A, B, 10, 17, 0xFFFF5BB1);
+ md5_P(B, C, D, A, 11, 22, 0x895CD7BE);
+ md5_P(A, B, C, D, 12, 7, 0x6B901122);
+ md5_P(D, A, B, C, 13, 12, 0xFD987193);
+ md5_P(C, D, A, B, 14, 17, 0xA679438E);
+ md5_P(B, C, D, A, 15, 22, 0x49B40821);
+
+#undef F
+
+#define F(x,y,z) (y ^ (z & (x ^ y)))
+
+ md5_P(A, B, C, D, 1, 5, 0xF61E2562);
+ md5_P(D, A, B, C, 6, 9, 0xC040B340);
+ md5_P(C, D, A, B, 11, 14, 0x265E5A51);
+ md5_P(B, C, D, A, 0, 20, 0xE9B6C7AA);
+ md5_P(A, B, C, D, 5, 5, 0xD62F105D);
+ md5_P(D, A, B, C, 10, 9, 0x02441453);
+ md5_P(C, D, A, B, 15, 14, 0xD8A1E681);
+ md5_P(B, C, D, A, 4, 20, 0xE7D3FBC8);
+ md5_P(A, B, C, D, 9, 5, 0x21E1CDE6);
+ md5_P(D, A, B, C, 14, 9, 0xC33707D6);
+ md5_P(C, D, A, B, 3, 14, 0xF4D50D87);
+ md5_P(B, C, D, A, 8, 20, 0x455A14ED);
+ md5_P(A, B, C, D, 13, 5, 0xA9E3E905);
+ md5_P(D, A, B, C, 2, 9, 0xFCEFA3F8);
+ md5_P(C, D, A, B, 7, 14, 0x676F02D9);
+ md5_P(B, C, D, A, 12, 20, 0x8D2A4C8A);
+
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+
+ md5_P(A, B, C, D, 5, 4, 0xFFFA3942);
+ md5_P(D, A, B, C, 8, 11, 0x8771F681);
+ md5_P(C, D, A, B, 11, 16, 0x6D9D6122);
+ md5_P(B, C, D, A, 14, 23, 0xFDE5380C);
+ md5_P(A, B, C, D, 1, 4, 0xA4BEEA44);
+ md5_P(D, A, B, C, 4, 11, 0x4BDECFA9);
+ md5_P(C, D, A, B, 7, 16, 0xF6BB4B60);
+ md5_P(B, C, D, A, 10, 23, 0xBEBFBC70);
+ md5_P(A, B, C, D, 13, 4, 0x289B7EC6);
+ md5_P(D, A, B, C, 0, 11, 0xEAA127FA);
+ md5_P(C, D, A, B, 3, 16, 0xD4EF3085);
+ md5_P(B, C, D, A, 6, 23, 0x04881D05);
+ md5_P(A, B, C, D, 9, 4, 0xD9D4D039);
+ md5_P(D, A, B, C, 12, 11, 0xE6DB99E5);
+ md5_P(C, D, A, B, 15, 16, 0x1FA27CF8);
+ md5_P(B, C, D, A, 2, 23, 0xC4AC5665);
+
+#undef F
+
+#define F(x,y,z) (y ^ (x | ~z))
+
+ md5_P(A, B, C, D, 0, 6, 0xF4292244);
+ md5_P(D, A, B, C, 7, 10, 0x432AFF97);
+ md5_P(C, D, A, B, 14, 15, 0xAB9423A7);
+ md5_P(B, C, D, A, 5, 21, 0xFC93A039);
+ md5_P(A, B, C, D, 12, 6, 0x655B59C3);
+ md5_P(D, A, B, C, 3, 10, 0x8F0CCC92);
+ md5_P(C, D, A, B, 10, 15, 0xFFEFF47D);
+ md5_P(B, C, D, A, 1, 21, 0x85845DD1);
+ md5_P(A, B, C, D, 8, 6, 0x6FA87E4F);
+ md5_P(D, A, B, C, 15, 10, 0xFE2CE6E0);
+ md5_P(C, D, A, B, 6, 15, 0xA3014314);
+ md5_P(B, C, D, A, 13, 21, 0x4E0811A1);
+ md5_P(A, B, C, D, 4, 6, 0xF7537E82);
+ md5_P(D, A, B, C, 11, 10, 0xBD3AF235);
+ md5_P(C, D, A, B, 2, 15, 0x2AD7D2BB);
+ md5_P(B, C, D, A, 9, 21, 0xEB86D391);
+
+#undef F
+
+ ctx->digest[0] += A;
+ ctx->digest[1] += B;
+ ctx->digest[2] += C;
+ ctx->digest[3] += D;
+}
+
+void algo_md5_update(algo_md5_context* ctx, u1* input, u4 length)
+{
+ u4 left, fill;
+
+ if (!length) return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = MD5_BLOCK_LENGTH - left;
+
+ ctx->total[0] += length;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if(ctx->total[0] < length) {
+ ctx->total[1]++;
+ }
+
+ if (left && (length >= fill)) {
+ memcpy(ctx->input + left,input,fill);
+ algo_md5_compress(ctx, (u4*)ctx->input);
+ length -= fill;
+ input += fill;
+ left = 0;
+ }
+
+ while(length >= MD5_BLOCK_LENGTH) {
+ algo_md5_compress(ctx, (u4*)input);
+ length -= MD5_BLOCK_LENGTH;
+ input += MD5_BLOCK_LENGTH;
+ }
+
+ if (length) {
+ memcpy(ctx->input + left,input,length);
+ }
+}
+
+void algo_md5_finish(algo_md5_context *ctx)
+{
+ u4 last, padn;
+ u4 msglen[2];
+
+ // little endian processing
+ if (IS_LITTLE_ENDIAN)
+ {
+ msglen[0] = (ctx->total[0] << 3);
+ msglen[1] = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
+ }
+ // big endian processing
+ else
+ {
+ msglen[0] = swapbytes_u4((ctx->total[0] >> 29) | (ctx->total[1] << 3));
+ msglen[1] = swapbytes_u4((ctx->total[0] << 3));
+ }
+
+ last = ctx->total[0] & 0x3F;
+ padn = (last < (MD5_BLOCK_LENGTH - sizeof(msglen))) ? ((MD5_BLOCK_LENGTH - sizeof(msglen)) - last) : (((2 * MD5_BLOCK_LENGTH) - sizeof(msglen)) - last);
+
+ algo_md5_update(ctx, (u1*)md5_padding, padn);
+ algo_md5_update(ctx, (u1*)msglen, sizeof(msglen));
+
+ // big endian processing
+ if (IS_BIG_ENDIAN)
+ {
+ u1 i;
+ for (i = 0; i < (MD5_HASH_LENGTH / sizeof(u4)); i++) {
+ ctx->digest[i] = swapbytes_u4(ctx->digest[i]);
+ }
+ }
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_md5.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,38 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_algo_md5_h
+#define _include_algo_md5_h
+
+typedef struct algo_md5_context{
+ u4 total[2];
+ u4* digest;
+ u1* input;
+} algo_md5_context;
+
+#define MD5_HASH_LENGTH 16
+#define MD5_BLOCK_LENGTH 64
+
+extern void algo_md5_starts(algo_md5_context* ctx);
+extern void algo_md5_update(algo_md5_context* ctx, u1* input, u4 length);
+extern void algo_md5_finish(algo_md5_context* ctx);
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,254 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_utils.h"
+#include "algo_sha1.h"
+
+const u1 sha1_padding[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#define sha1_S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define sha1_R(t) (temp = data[(t - 3) & 0x0F] ^ data[(t - 8) & 0x0F] ^ data[(t - 14) & 0x0F] ^ data[t & 0x0F], (data[t & 0x0F] = sha1_S(temp,1)))
+
+#define sha1_P(a,b,c,d,e,x) {e += sha1_S(a,5) + F(b,c,d) + K + x; b = sha1_S(b,30);}
+
+void algo_sha1_starts(algo_sha1_context *ctx)
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->digest[0] = 0x67452301;
+ ctx->digest[1] = 0xEFCDAB89;
+ ctx->digest[2] = 0x98BADCFE;
+ ctx->digest[3] = 0x10325476;
+ ctx->digest[4] = 0xC3D2E1F0;
+}
+
+static void algo_sha1_compress(algo_sha1_context *ctx, u4* data)
+{
+ u4 temp, A, B, C, D, E;
+ u1 i;
+
+ // little endian processing
+ if (IS_LITTLE_ENDIAN)
+ {
+ for (i = 0; i < (SHA1_BLOCK_LENGTH / sizeof(u4)); i++) {
+ data[i] = swapbytes_u4(data[i]);
+ }
+ }
+
+ A = ctx->digest[0];
+ B = ctx->digest[1];
+ C = ctx->digest[2];
+ D = ctx->digest[3];
+ E = ctx->digest[4];
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+ sha1_P(A, B, C, D, E, data[0]);
+ sha1_P(E, A, B, C, D, data[1]);
+ sha1_P(D, E, A, B, C, data[2]);
+ sha1_P(C, D, E, A, B, data[3]);
+ sha1_P(B, C, D, E, A, data[4]);
+ sha1_P(A, B, C, D, E, data[5]);
+ sha1_P(E, A, B, C, D, data[6]);
+ sha1_P(D, E, A, B, C, data[7]);
+ sha1_P(C, D, E, A, B, data[8]);
+ sha1_P(B, C, D, E, A, data[9]);
+ sha1_P(A, B, C, D, E, data[10]);
+ sha1_P(E, A, B, C, D, data[11]);
+ sha1_P(D, E, A, B, C, data[12]);
+ sha1_P(C, D, E, A, B, data[13]);
+ sha1_P(B, C, D, E, A, data[14]);
+ sha1_P(A, B, C, D, E, data[15]);
+ sha1_P(E, A, B, C, D, sha1_R(16));
+ sha1_P(D, E, A, B, C, sha1_R(17));
+ sha1_P(C, D, E, A, B, sha1_R(18));
+ sha1_P(B, C, D, E, A, sha1_R(19));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+ sha1_P(A, B, C, D, E, sha1_R(20));
+ sha1_P(E, A, B, C, D, sha1_R(21));
+ sha1_P(D, E, A, B, C, sha1_R(22));
+ sha1_P(C, D, E, A, B, sha1_R(23));
+ sha1_P(B, C, D, E, A, sha1_R(24));
+ sha1_P(A, B, C, D, E, sha1_R(25));
+ sha1_P(E, A, B, C, D, sha1_R(26));
+ sha1_P(D, E, A, B, C, sha1_R(27));
+ sha1_P(C, D, E, A, B, sha1_R(28));
+ sha1_P(B, C, D, E, A, sha1_R(29));
+ sha1_P(A, B, C, D, E, sha1_R(30));
+ sha1_P(E, A, B, C, D, sha1_R(31));
+ sha1_P(D, E, A, B, C, sha1_R(32));
+ sha1_P(C, D, E, A, B, sha1_R(33));
+ sha1_P(B, C, D, E, A, sha1_R(34));
+ sha1_P(A, B, C, D, E, sha1_R(35));
+ sha1_P(E, A, B, C, D, sha1_R(36));
+ sha1_P(D, E, A, B, C, sha1_R(37));
+ sha1_P(C, D, E, A, B, sha1_R(38));
+ sha1_P(B, C, D, E, A, sha1_R(39));
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+ sha1_P(A, B, C, D, E, sha1_R(40));
+ sha1_P(E, A, B, C, D, sha1_R(41));
+ sha1_P(D, E, A, B, C, sha1_R(42));
+ sha1_P(C, D, E, A, B, sha1_R(43));
+ sha1_P(B, C, D, E, A, sha1_R(44));
+ sha1_P(A, B, C, D, E, sha1_R(45));
+ sha1_P(E, A, B, C, D, sha1_R(46));
+ sha1_P(D, E, A, B, C, sha1_R(47));
+ sha1_P(C, D, E, A, B, sha1_R(48));
+ sha1_P(B, C, D, E, A, sha1_R(49));
+ sha1_P(A, B, C, D, E, sha1_R(50));
+ sha1_P(E, A, B, C, D, sha1_R(51));
+ sha1_P(D, E, A, B, C, sha1_R(52));
+ sha1_P(C, D, E, A, B, sha1_R(53));
+ sha1_P(B, C, D, E, A, sha1_R(54));
+ sha1_P(A, B, C, D, E, sha1_R(55));
+ sha1_P(E, A, B, C, D, sha1_R(56));
+ sha1_P(D, E, A, B, C, sha1_R(57));
+ sha1_P(C, D, E, A, B, sha1_R(58));
+ sha1_P(B, C, D, E, A, sha1_R(59));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+ sha1_P(A, B, C, D, E, sha1_R(60));
+ sha1_P(E, A, B, C, D, sha1_R(61));
+ sha1_P(D, E, A, B, C, sha1_R(62));
+ sha1_P(C, D, E, A, B, sha1_R(63));
+ sha1_P(B, C, D, E, A, sha1_R(64));
+ sha1_P(A, B, C, D, E, sha1_R(65));
+ sha1_P(E, A, B, C, D, sha1_R(66));
+ sha1_P(D, E, A, B, C, sha1_R(67));
+ sha1_P(C, D, E, A, B, sha1_R(68));
+ sha1_P(B, C, D, E, A, sha1_R(69));
+ sha1_P(A, B, C, D, E, sha1_R(70));
+ sha1_P(E, A, B, C, D, sha1_R(71));
+ sha1_P(D, E, A, B, C, sha1_R(72));
+ sha1_P(C, D, E, A, B, sha1_R(73));
+ sha1_P(B, C, D, E, A, sha1_R(74));
+ sha1_P(A, B, C, D, E, sha1_R(75));
+ sha1_P(E, A, B, C, D, sha1_R(76));
+ sha1_P(D, E, A, B, C, sha1_R(77));
+ sha1_P(C, D, E, A, B, sha1_R(78));
+ sha1_P(B, C, D, E, A, sha1_R(79));
+
+#undef K
+#undef F
+
+ ctx->digest[0] += A;
+ ctx->digest[1] += B;
+ ctx->digest[2] += C;
+ ctx->digest[3] += D;
+ ctx->digest[4] += E;
+}
+
+void algo_sha1_update(algo_sha1_context* ctx, u1* input, u4 length)
+{
+ u4 left, fill;
+
+ if (!length) return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = SHA1_BLOCK_LENGTH - left;
+
+ ctx->total[0] += length;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if(ctx->total[0] < length) {
+ ctx->total[1]++;
+ }
+
+ if (left && (length >= fill)) {
+ //CopyVolatile(input, ctx->input + left, fill);
+ memcpy(ctx->input + left,input,fill);
+ algo_sha1_compress(ctx, (u4*)ctx->input);
+ length -= fill;
+ input += fill;
+ left = 0;
+ }
+
+ while(length >= SHA1_BLOCK_LENGTH) {
+ algo_sha1_compress(ctx, (u4*)input);
+ length -= SHA1_BLOCK_LENGTH;
+ input += SHA1_BLOCK_LENGTH;
+ }
+
+ if (length) {
+ //CopyVolatile(input, ctx->input + left, length);
+ memcpy(ctx->input + left,input,length);
+ }
+}
+
+void algo_sha1_finish(algo_sha1_context *ctx)
+{
+ u4 last, padn;
+ u4 msglen[2];
+ u1 i;
+
+ // little endian processing
+ if (IS_LITTLE_ENDIAN)
+ {
+ msglen[0] = swapbytes_u4((ctx->total[0] >> 29) | (ctx->total[1] << 3));
+ msglen[1] = swapbytes_u4((ctx->total[0] << 3));
+ }
+ else
+ {
+ msglen[0] = (ctx->total[0] << 3);
+ msglen[1] = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
+ }
+
+ last = ctx->total[0] & 0x3F;
+ padn = (last < (SHA1_BLOCK_LENGTH - sizeof(msglen))) ? ((SHA1_BLOCK_LENGTH - sizeof(msglen)) - last) : (((2 * SHA1_BLOCK_LENGTH) - sizeof(msglen)) - last);
+
+ algo_sha1_update(ctx, (u1*)sha1_padding, padn);
+ algo_sha1_update(ctx, (u1*)msglen, 8);
+
+ // little endian processing
+ if (IS_LITTLE_ENDIAN)
+ {
+ for (i = 0; i < (SHA1_HASH_LENGTH / sizeof(u4)); i++) {
+ ctx->digest[i] = swapbytes_u4(ctx->digest[i]);
+ }
+ }
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha1.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,39 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_algo_sha1_h
+#define _include_algo_sha1_h
+
+typedef struct algo_sha1_context
+{
+ u4 total[2];
+ u4* digest;
+ u1* input;
+} algo_sha1_context;
+
+#define SHA1_HASH_LENGTH 20
+#define SHA1_BLOCK_LENGTH 64
+
+extern void algo_sha1_starts(algo_sha1_context* ctx);
+extern void algo_sha1_update(algo_sha1_context* ctx, u1* input, u4 length);
+extern void algo_sha1_finish(algo_sha1_context* ctx);
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,370 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_utils.h"
+#include "algo_sha256.h"
+
+const u1 sha256_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define SHA256_S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
+#define SHA256_S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
+#define SHA256_S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
+#define SHA256_S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+
+#define SHA256_F0(x,y,z) ((x & y) | (z & (x | y)))
+#define SHA256_F1(x,y,z) (z ^ (x & (y ^ z)))
+
+void algo_sha256_starts(algo_sha256_context *ctx )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ ctx->digest[0] = 0x6A09E667;
+ ctx->digest[1] = 0xBB67AE85;
+ ctx->digest[2] = 0x3C6EF372;
+ ctx->digest[3] = 0xA54FF53A;
+ ctx->digest[4] = 0x510E527F;
+ ctx->digest[5] = 0x9B05688C;
+ ctx->digest[6] = 0x1F83D9AB;
+ ctx->digest[7] = 0x5BE0CD19;
+}
+
+#ifdef _SHA256_SIZE_OPTIMIZED_VERSION
+
+ static algo_sha256_context* algo_sha256_tmpCtx;
+
+ static void sha256_P(u4 a, u4 b, u4 c, u4* d, u4 e, u4 f, u4 g, u4* h, u1 i, u4 K)
+ {
+ u4 temp1;
+ u4 temp2;
+
+ if (i > 15) {
+ algo_sha256_tmpCtx->processingBuffer[i] = SHA256_S1(algo_sha256_tmpCtx->processingBuffer[i - 2]) + algo_sha256_tmpCtx->processingBuffer[i - 7] + SHA256_S0(algo_sha256_tmpCtx->processingBuffer[i - 15]) + algo_sha256_tmpCtx->processingBuffer[i - 16];
+ }
+
+ temp1 = *h + SHA256_S3(e) + SHA256_F1(e,f,g) + K + algo_sha256_tmpCtx->processingBuffer[i];
+ temp2 = SHA256_S2(a) + SHA256_F0(a,b,c);
+
+ *d += temp1;
+ *h = temp1 + temp2;
+ }
+
+ static void algo_sha256_compress(algo_sha256_context *ctx, u4* input)
+ {
+
+ u4 A, B, C, D, E, F, G, H;
+ u1 i;
+
+ // little endian processing
+ if (IS_LITTLE_ENDIAN)
+ {
+ for (i = 0; i < (SHA256_BLOCK_LENGTH / sizeof(u4)); i++) {
+ ctx->processingBuffer[i] = swapbytes_u4(input[i]);
+ }
+ }
+ A = ctx->digest[0];
+ B = ctx->digest[1];
+ C = ctx->digest[2];
+ D = ctx->digest[3];
+ E = ctx->digest[4];
+ F = ctx->digest[5];
+ G = ctx->digest[6];
+ H = ctx->digest[7];
+
+ algo_sha256_tmpCtx = ctx;
+
+ sha256_P(A, B, C, &D, E, F, G, &H, 0, 0x428A2F98);
+ sha256_P(H, A, B, &C, D, E, F, &G, 1, 0x71374491);
+ sha256_P(G, H, A, &B, C, D, E, &F, 2, 0xB5C0FBCF);
+ sha256_P(F, G, H, &A, B, C, D, &E, 3, 0xE9B5DBA5);
+ sha256_P(E, F, G, &H, A, B, C, &D, 4, 0x3956C25B);
+ sha256_P(D, E, F, &G, H, A, B, &C, 5, 0x59F111F1);
+ sha256_P(C, D, E, &F, G, H, A, &B, 6, 0x923F82A4);
+ sha256_P(B, C, D, &E, F, G, H, &A, 7, 0xAB1C5ED5);
+ sha256_P(A, B, C, &D, E, F, G, &H, 8, 0xD807AA98);
+ sha256_P(H, A, B, &C, D, E, F, &G, 9, 0x12835B01);
+ sha256_P(G, H, A, &B, C, D, E, &F, 10, 0x243185BE);
+ sha256_P(F, G, H, &A, B, C, D, &E, 11, 0x550C7DC3);
+ sha256_P(E, F, G, &H, A, B, C, &D, 12, 0x72BE5D74);
+ sha256_P(D, E, F, &G, H, A, B, &C, 13, 0x80DEB1FE);
+ sha256_P(C, D, E, &F, G, H, A, &B, 14, 0x9BDC06A7);
+ sha256_P(B, C, D, &E, F, G, H, &A, 15, 0xC19BF174);
+ sha256_P(A, B, C, &D, E, F, G, &H, 16, 0xE49B69C1);
+ sha256_P(H, A, B, &C, D, E, F, &G, 17, 0xEFBE4786);
+ sha256_P(G, H, A, &B, C, D, E, &F, 18, 0x0FC19DC6);
+ sha256_P(F, G, H, &A, B, C, D, &E, 19, 0x240CA1CC);
+ sha256_P(E, F, G, &H, A, B, C, &D, 20, 0x2DE92C6F);
+ sha256_P(D, E, F, &G, H, A, B, &C, 21, 0x4A7484AA);
+ sha256_P(C, D, E, &F, G, H, A, &B, 22, 0x5CB0A9DC);
+ sha256_P(B, C, D, &E, F, G, H, &A, 23, 0x76F988DA);
+ sha256_P(A, B, C, &D, E, F, G, &H, 24, 0x983E5152);
+ sha256_P(H, A, B, &C, D, E, F, &G, 25, 0xA831C66D);
+ sha256_P(G, H, A, &B, C, D, E, &F, 26, 0xB00327C8);
+ sha256_P(F, G, H, &A, B, C, D, &E, 27, 0xBF597FC7);
+ sha256_P(E, F, G, &H, A, B, C, &D, 28, 0xC6E00BF3);
+ sha256_P(D, E, F, &G, H, A, B, &C, 29, 0xD5A79147);
+ sha256_P(C, D, E, &F, G, H, A, &B, 30, 0x06CA6351);
+ sha256_P(B, C, D, &E, F, G, H, &A, 31, 0x14292967);
+ sha256_P(A, B, C, &D, E, F, G, &H, 32, 0x27B70A85);
+ sha256_P(H, A, B, &C, D, E, F, &G, 33, 0x2E1B2138);
+ sha256_P(G, H, A, &B, C, D, E, &F, 34, 0x4D2C6DFC);
+ sha256_P(F, G, H, &A, B, C, D, &E, 35, 0x53380D13);
+ sha256_P(E, F, G, &H, A, B, C, &D, 36, 0x650A7354);
+ sha256_P(D, E, F, &G, H, A, B, &C, 37, 0x766A0ABB);
+ sha256_P(C, D, E, &F, G, H, A, &B, 38, 0x81C2C92E);
+ sha256_P(B, C, D, &E, F, G, H, &A, 39, 0x92722C85);
+ sha256_P(A, B, C, &D, E, F, G, &H, 40, 0xA2BFE8A1);
+ sha256_P(H, A, B, &C, D, E, F, &G, 41, 0xA81A664B);
+ sha256_P(G, H, A, &B, C, D, E, &F, 42, 0xC24B8B70);
+ sha256_P(F, G, H, &A, B, C, D, &E, 43, 0xC76C51A3);
+ sha256_P(E, F, G, &H, A, B, C, &D, 44, 0xD192E819);
+ sha256_P(D, E, F, &G, H, A, B, &C, 45, 0xD6990624);
+ sha256_P(C, D, E, &F, G, H, A, &B, 46, 0xF40E3585);
+ sha256_P(B, C, D, &E, F, G, H, &A, 47, 0x106AA070);
+ sha256_P(A, B, C, &D, E, F, G, &H, 48, 0x19A4C116);
+ sha256_P(H, A, B, &C, D, E, F, &G, 49, 0x1E376C08);
+ sha256_P(G, H, A, &B, C, D, E, &F, 50, 0x2748774C);
+ sha256_P(F, G, H, &A, B, C, D, &E, 51, 0x34B0BCB5);
+ sha256_P(E, F, G, &H, A, B, C, &D, 52, 0x391C0CB3);
+ sha256_P(D, E, F, &G, H, A, B, &C, 53, 0x4ED8AA4A);
+ sha256_P(C, D, E, &F, G, H, A, &B, 54, 0x5B9CCA4F);
+ sha256_P(B, C, D, &E, F, G, H, &A, 55, 0x682E6FF3);
+ sha256_P(A, B, C, &D, E, F, G, &H, 56, 0x748F82EE);
+ sha256_P(H, A, B, &C, D, E, F, &G, 57, 0x78A5636F);
+ sha256_P(G, H, A, &B, C, D, E, &F, 58, 0x84C87814);
+ sha256_P(F, G, H, &A, B, C, D, &E, 59, 0x8CC70208);
+ sha256_P(E, F, G, &H, A, B, C, &D, 60, 0x90BEFFFA);
+ sha256_P(D, E, F, &G, H, A, B, &C, 61, 0xA4506CEB);
+ sha256_P(C, D, E, &F, G, H, A, &B, 62, 0xBEF9A3F7);
+ sha256_P(B, C, D, &E, F, G, H, &A, 63, 0xC67178F2);
+
+ ctx->digest[0] += A;
+ ctx->digest[1] += B;
+ ctx->digest[2] += C;
+ ctx->digest[3] += D;
+ ctx->digest[4] += E;
+ ctx->digest[5] += F;
+ ctx->digest[6] += G;
+ ctx->digest[7] += H;
+ }
+
+#else
+
+ #define SHA256_R(t) \
+ ( \
+ ctx->processingBuffer[t] = SHA256_S1(ctx->processingBuffer[t - 2]) + ctx->processingBuffer[t - 7] + \
+ SHA256_S0(ctx->processingBuffer[t - 15]) + ctx->processingBuffer[t - 16] \
+ )
+
+ #define SHA256_P(a,b,c,d,e,f,g,h,x,K) \
+ { \
+ temp1 = h + SHA256_S3(e) + SHA256_F1(e,f,g) + K + x; \
+ temp2 = SHA256_S2(a) + SHA256_F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+ }
+
+ static void algo_sha256_compress(algo_sha256_context *ctx, u4* input)
+ {
+ u4 temp1, temp2;
+ u4 A, B, C, D, E, F, G, H;
+ u1 i;
+
+ // little endian processing
+ if (IS_LITTLE_ENDIAN)
+ {
+ for (i = 0; i < (SHA256_BLOCK_LENGTH / sizeof(u4)); i++) {
+ ctx->processingBuffer[i] = swapbytes_u4(input[i]);
+ }
+ }
+ else
+ {
+ for (i = 0; i < (SHA256_BLOCK_LENGTH / sizeof(u4)); i++) {
+ ctx->processingBuffer[i] = input[i];
+ }
+ }
+
+ A = ctx->digest[0];
+ B = ctx->digest[1];
+ C = ctx->digest[2];
+ D = ctx->digest[3];
+ E = ctx->digest[4];
+ F = ctx->digest[5];
+ G = ctx->digest[6];
+ H = ctx->digest[7];
+
+ SHA256_P( A, B, C, D, E, F, G, H, ctx->processingBuffer[ 0], 0x428A2F98 );
+ SHA256_P( H, A, B, C, D, E, F, G, ctx->processingBuffer[ 1], 0x71374491 );
+ SHA256_P( G, H, A, B, C, D, E, F, ctx->processingBuffer[ 2], 0xB5C0FBCF );
+ SHA256_P( F, G, H, A, B, C, D, E, ctx->processingBuffer[ 3], 0xE9B5DBA5 );
+ SHA256_P( E, F, G, H, A, B, C, D, ctx->processingBuffer[ 4], 0x3956C25B );
+ SHA256_P( D, E, F, G, H, A, B, C, ctx->processingBuffer[ 5], 0x59F111F1 );
+ SHA256_P( C, D, E, F, G, H, A, B, ctx->processingBuffer[ 6], 0x923F82A4 );
+ SHA256_P( B, C, D, E, F, G, H, A, ctx->processingBuffer[ 7], 0xAB1C5ED5 );
+ SHA256_P( A, B, C, D, E, F, G, H, ctx->processingBuffer[ 8], 0xD807AA98 );
+ SHA256_P( H, A, B, C, D, E, F, G, ctx->processingBuffer[ 9], 0x12835B01 );
+ SHA256_P( G, H, A, B, C, D, E, F, ctx->processingBuffer[10], 0x243185BE );
+ SHA256_P( F, G, H, A, B, C, D, E, ctx->processingBuffer[11], 0x550C7DC3 );
+ SHA256_P( E, F, G, H, A, B, C, D, ctx->processingBuffer[12], 0x72BE5D74 );
+ SHA256_P( D, E, F, G, H, A, B, C, ctx->processingBuffer[13], 0x80DEB1FE );
+ SHA256_P( C, D, E, F, G, H, A, B, ctx->processingBuffer[14], 0x9BDC06A7 );
+ SHA256_P( B, C, D, E, F, G, H, A, ctx->processingBuffer[15], 0xC19BF174 );
+ SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(16), 0xE49B69C1 );
+ SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(17), 0xEFBE4786 );
+ SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(18), 0x0FC19DC6 );
+ SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(19), 0x240CA1CC );
+ SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(20), 0x2DE92C6F );
+ SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(21), 0x4A7484AA );
+ SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(22), 0x5CB0A9DC );
+ SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(23), 0x76F988DA );
+ SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(24), 0x983E5152 );
+ SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(25), 0xA831C66D );
+ SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(26), 0xB00327C8 );
+ SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(27), 0xBF597FC7 );
+ SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(28), 0xC6E00BF3 );
+ SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(29), 0xD5A79147 );
+ SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(30), 0x06CA6351 );
+ SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(31), 0x14292967 );
+ SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(32), 0x27B70A85 );
+ SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(33), 0x2E1B2138 );
+ SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(34), 0x4D2C6DFC );
+ SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(35), 0x53380D13 );
+ SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(36), 0x650A7354 );
+ SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(37), 0x766A0ABB );
+ SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(38), 0x81C2C92E );
+ SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(39), 0x92722C85 );
+ SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(40), 0xA2BFE8A1 );
+ SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(41), 0xA81A664B );
+ SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(42), 0xC24B8B70 );
+ SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(43), 0xC76C51A3 );
+ SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(44), 0xD192E819 );
+ SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(45), 0xD6990624 );
+ SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(46), 0xF40E3585 );
+ SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(47), 0x106AA070 );
+ SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(48), 0x19A4C116 );
+ SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(49), 0x1E376C08 );
+ SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(50), 0x2748774C );
+ SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(51), 0x34B0BCB5 );
+ SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(52), 0x391C0CB3 );
+ SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(53), 0x4ED8AA4A );
+ SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(54), 0x5B9CCA4F );
+ SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(55), 0x682E6FF3 );
+ SHA256_P( A, B, C, D, E, F, G, H, SHA256_R(56), 0x748F82EE );
+ SHA256_P( H, A, B, C, D, E, F, G, SHA256_R(57), 0x78A5636F );
+ SHA256_P( G, H, A, B, C, D, E, F, SHA256_R(58), 0x84C87814 );
+ SHA256_P( F, G, H, A, B, C, D, E, SHA256_R(59), 0x8CC70208 );
+ SHA256_P( E, F, G, H, A, B, C, D, SHA256_R(60), 0x90BEFFFA );
+ SHA256_P( D, E, F, G, H, A, B, C, SHA256_R(61), 0xA4506CEB );
+ SHA256_P( C, D, E, F, G, H, A, B, SHA256_R(62), 0xBEF9A3F7 );
+ SHA256_P( B, C, D, E, F, G, H, A, SHA256_R(63), 0xC67178F2 );
+
+ ctx->digest[0] += A;
+ ctx->digest[1] += B;
+ ctx->digest[2] += C;
+ ctx->digest[3] += D;
+ ctx->digest[4] += E;
+ ctx->digest[5] += F;
+ ctx->digest[6] += G;
+ ctx->digest[7] += H;
+ }
+
+#endif
+
+
+void algo_sha256_update(algo_sha256_context *ctx, u1 *input, u4 length )
+{
+ u4 left, fill;
+
+ if(!length ) return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = SHA256_BLOCK_LENGTH - left;
+
+ ctx->total[0] += length;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < length )
+ ctx->total[1]++;
+
+ if( left && length >= fill )
+ {
+ memcpy(ctx->input + left,input,fill);
+
+ algo_sha256_compress( ctx,(u4*)ctx->input );
+ length -= fill;
+ input += fill;
+ left = 0;
+ }
+
+ while( length >= SHA256_BLOCK_LENGTH )
+ {
+ algo_sha256_compress( ctx, (u4*)input );
+ length -= SHA256_BLOCK_LENGTH;
+ input += SHA256_BLOCK_LENGTH;
+ }
+
+ if( length ){
+ memcpy(ctx->input + left,input,length);
+ }
+}
+
+void algo_sha256_finish(algo_sha256_context *ctx)
+{
+ u4 last, padn;
+ u4 msglen[2];
+ u1 i;
+
+ // little endian processing
+ if (IS_LITTLE_ENDIAN)
+ {
+ msglen[0] = swapbytes_u4((ctx->total[0] >> 29) | (ctx->total[1] << 3));
+ msglen[1] = swapbytes_u4((ctx->total[0] << 3));
+ }
+ else
+ {
+ msglen[0] = (ctx->total[0] << 3);
+ msglen[1] = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
+ }
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ algo_sha256_update( ctx, (u1*)sha256_padding, padn );
+ algo_sha256_update( ctx, (u1*)msglen, 8 );
+
+ // little endian processing
+ if (IS_LITTLE_ENDIAN)
+ {
+ for (i = 0; i < (SHA256_HASH_LENGTH / sizeof(u4)); i++) {
+ ctx->digest[i] = swapbytes_u4(ctx->digest[i]);
+ }
+ }
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_sha256.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,40 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_algo_sha256_h
+#define _include_algo_sha256_h
+
+#define SHA256_HASH_LENGTH 32
+#define SHA256_BLOCK_LENGTH 64
+
+typedef struct algo_sha256_context
+{
+ u4 total[2];
+ u4 processingBuffer[SHA256_BLOCK_LENGTH];
+ u4* digest;
+ u1* input;
+} algo_sha256_context;
+
+extern void algo_sha256_starts(algo_sha256_context* ctx);
+extern void algo_sha256_update(algo_sha256_context* ctx, u1* input, u4 length);
+extern void algo_sha256_finish(algo_sha256_context* ctx);
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,34 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "MarshallerCfg.h"
+#include "algo_utils.h"
+
+u4 swapbytes_u4(u4 val)
+{
+ u4 res;
+ res = val << 24;
+ res |= (val << 8) & 0x00FF0000;
+ res |= (val >> 8) & 0x0000FF00;
+ res |= val >> 24;
+ return (res);
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/algo_utils.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,27 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_algo_utils_h
+#define _include_algo_utils_h
+
+extern u4 swapbytes_u4(u4 val);
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,738 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <winscard.h>
+#include "cardmoduleservice.h"
+
+#include <string>
+
+#include <assert.h>
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "thread.h"
+#include "event.h"
+#include "session.h"
+#include "slot.h"
+#include "application.h"
+#include "log.h"
+
+#ifdef _XCL_
+#include <xcl_utils.h>
+#endif // _XCL_
+
+#ifdef __sun
+typedef LPSTR LPTSTR;
+#endif
+
+// Initialization of Static fields
+SCARDCONTEXT Application::_hContext = 0;
+
+Slot* Application::_slotCache[CONFIG_MAX_SLOT] = {
+ NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,
+ NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR,NULL_PTR
+};
+
+CK_ULONG Application::_numSlots = 0;
+
+#ifdef _XCL_
+xCL_DeviceHandle Application::_deviceHandle = 0; // asadali
+#endif // _XCL_
+
+
+/*
+*/
+#ifndef _XCL_
+CK_RV Application::InitApplication( )
+{
+ Log::begin( "Application::InitApplication" );
+
+ // do the enumeration of slots
+ CK_ULONG hResult = SCardEstablishContext( SCARD_SCOPE_USER, NULL, NULL, &Application::_hContext );
+
+ Log::log( "Application::InitApplication - SCardEstablishContext <%#02x>", hResult );
+ Log::log( "Application::InitApplication - Application::_hContext <%#02x>", Application::_hContext );
+
+ if( SCARD_S_SUCCESS != hResult )
+ {
+ return CKR_GENERAL_ERROR;
+ }
+
+#ifdef __APPLE__
+ /* Apple bug 5256035 */
+ {
+ SCARDHANDLE h;
+ DWORD p;
+ SCardConnect(Application::_hContext, "fake reader", SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &h, &p);
+ }
+#endif
+
+ Log::end( "Application::InitApplication" );
+
+ return CKR_OK;
+}
+
+#else // _XCL_
+
+CK_RV Application::InitApplication( )
+{
+ Log::begin( "Application::InitApplication" );
+ u4 deviceID;
+ u4 rv;
+ xCL_DevicePtr deviceList;
+ xCL_DevicePtr device;
+ u4 numberOfDevices;
+ u4 i;
+
+ PRINT_MSG("IN Application::Init");
+
+ rv = xCL_InterfaceInit();
+
+ rv = xCL_DiscoverDevices(&deviceList, &numberOfDevices);
+ if (rv == 0 && numberOfDevices != 0)
+ {
+ // Pick the first device, with ID=0
+ device = deviceList + 0;
+ deviceID = device->deviceID ;
+ PRINT_DATA(NULL, 0, (char*)device->uniqueName);
+
+ // Create device handle
+ rv = xCL_CreateHandleFromDeviceID(deviceID, &Application::_deviceHandle);
+ if (rv == 0)
+ {
+ PRINT_MSG("IN Application::Init , device handle created");
+ }
+
+ // Free memory for all devices
+ for (i=0; i<numberOfDevices; i++)
+ {
+ rv = xCL_FreeDeviceMemory(deviceList + i);
+ }
+ }
+ return CKR_OK;
+}
+
+#endif // _XCL_
+
+
+/*
+*/
+
+#ifndef _XCL_
+
+CK_RV Application::Enumerate( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount )
+{
+ Log::begin( "Application::Enumerate" );
+
+ CK_ULONG slotNb = 0;
+ LPTSTR pReader = NULL;
+ CK_LONG hResult = 0;
+ CK_SLOT_ID sid = 0;
+
+ if( NULL_PTR == pulCount )
+ {
+ Log::error( "Application::Enumerate", "CKR_ARGUMENTS_BAD" );
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ // Get the supported readers from the current cache
+ std::string currentCache[ CONFIG_MAX_SLOT ];
+ for( CK_SLOT_ID i = 0; i < CONFIG_MAX_SLOT; i++ )
+ {
+ currentCache[ i ] = "";
+ if( NULL_PTR != Application::_slotCache[ i ] )
+ {
+ currentCache[ i ] = *(Application::_slotCache[ i ]->_readerName);
+ Log::log( "Application::Enumerate - currentCache[ %d ] <%s>", i, currentCache[ i ].c_str( ) );
+ }
+ }
+
+ // Get the readers from the PCSC layer
+ DWORD readerListCharLength = 0;
+ hResult = SCardListReaders( Application::_hContext, NULL, NULL, &readerListCharLength );
+ Log::log( "Application::Enumerate - readerListCharLength <%#02x>", readerListCharLength );
+ Log::log( "Application::Enumerate - SCardListReaders <%#02x>", hResult );
+ if( SCARD_S_SUCCESS != hResult )
+ {
+ Log::error( "Application::Enumerate", "CKR_GENERAL_ERROR" );
+ return CKR_GENERAL_ERROR;
+ }
+
+ LPTSTR pReaderList = (lpCharPtr)malloc( sizeof(char) * readerListCharLength );
+ if( NULL == pReaderList )
+ {
+ Log::error( "Application::Enumerate", "CKR_HOST_MEMORY" );
+ return CKR_HOST_MEMORY;
+ }
+ memset( pReaderList, 0, sizeof(char) * readerListCharLength );
+
+ hResult = SCardListReaders( Application::_hContext, NULL, pReaderList, &readerListCharLength);
+ Log::log( "Application::Enumerate - SCardListReaders 2 <%#02x>", hResult );
+ if( SCARD_S_SUCCESS != hResult )
+ {
+ free( pReaderList );
+ Log::error( "Application::Enumerate", "CKR_GENERAL_ERROR" );
+ return CKR_GENERAL_ERROR;
+ }
+
+ // Construct the PCSC reader list
+ std::string currentPcscList[ CONFIG_MAX_SLOT ];
+ for( CK_SLOT_ID i = 0; i < CONFIG_MAX_SLOT; i++ )
+ {
+ currentPcscList[ i ] = "";
+ }
+ pReader = pReaderList; //readers;
+ int i = 0;
+ while( pReader && ( '\0' != *pReader ) )
+ {
+ currentPcscList[ i ] = pReader;
+ Log::log( "Application::Enumerate - PCSC List[ %d ] <%s>", i, currentPcscList[ i ].c_str( ) );
+ i++;
+ if( i > CONFIG_MAX_SLOT )
+ {
+ /*
+ free( pReaderList );
+ Log::error( "Application::Enumerate", "CKR_HOST_MEMORY" );
+ return CKR_HOST_MEMORY;
+ */
+ break;
+ }
+
+ // Advance to the next value.
+ size_t readerNameLen = strlen( (const char*)pReader );
+ pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
+ }
+ free( pReaderList );
+
+ // Does a reader desappeared ?
+ for( CK_SLOT_ID i = 0; i < CONFIG_MAX_SLOT; i++ )
+ {
+ if( NULL_PTR != Application::_slotCache[ i ] )
+ {
+ //printf( "Application::_slotCache[ %lu ]->_readerName <%s>\n", i, Application::_slotCache[ i ]->_readerName->c_str( ) );
+
+ bool bFound = false;
+ for( int j = 0 ; j < CONFIG_MAX_SLOT; j++ )
+ {
+ //printf( "currentPcscList[ %d ] <%s>\n", j, currentPcscList[ j ].c_str( ) );
+
+ if( 0 == (Application::_slotCache[ i ]->_readerName)->compare( currentPcscList[ j ] ) )
+ {
+ bFound = true;
+ //printf( "!! Found !!\n" );
+ break;
+ }
+ }
+ if( false == bFound )
+ {
+ // Not found into the PCSC reader list
+ deleteSlot( i );
+ //printf( "!! Not Found -> delete !!\n" );
+ }
+ }
+ }
+
+ // Does a new reader appears ?
+ //printf( "\n\nDoes a new reader appears ?\n" );
+ for( int i = 0; i < CONFIG_MAX_SLOT; i++ )
+ {
+ if( false == currentPcscList[ i ].empty( ) )
+ {
+ //printf( "currentPcscList[ %d ] <%s>\n", i, currentPcscList[ i ].c_str( ) );
+
+ bool bFound = false;
+ for( int j = 0 ; j < CONFIG_MAX_SLOT; j++ )
+ {
+ if( 0 != Application::_slotCache[ j ] )
+ {
+ //printf( " Application::_slotCache[ %d ] <%s>\n", j, Application::_slotCache[ j ]->_readerName->c_str( ) );
+ if( 0 == ( currentPcscList[ i ].compare( *(Application::_slotCache[ j ]->_readerName) ) ) )
+ {
+ bFound = true;
+ //printf( " !! Found !!\n" );
+ break;
+ }
+ }
+ }
+ if( false == bFound )
+ {
+ //printf( "!! Not Found -> add !!\n" );
+
+ CK_RV rv = addSlot( currentPcscList[ i ] );
+ if( CKR_OK != rv )
+ {
+ Log::error( "Application::Enumerate", "addSlot failed" );
+ return rv;
+ }
+ }
+ }
+ }
+
+
+ // Scan Reader List
+ slotNb = 0;
+ Application::_numSlots = 0;
+ for (int i = 0; i < CONFIG_MAX_SLOT; i++)
+ {
+ // Existing Slots only are scanned
+ if (Application::_slotCache[i] != NULL_PTR)
+ {
+ //Log::log( "Application::Enumerate - New Cache[ %d ] <%s>", i, Application::_slotCache[ i ]->_readerName->c_str( ) );
+ Application::_numSlots++;
+
+ SCARD_READERSTATE readerStates;
+ memset( &readerStates, 0, sizeof( SCARD_READERSTATE ) );
+ readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+ readerStates.szReader = Application::_slotCache[i]->_readerName->c_str();
+
+ // Lets check if token is present or not
+ if (SCardGetStatusChange(Application::_hContext, 100, &readerStates, 1) == SCARD_S_SUCCESS)
+ {
+ if ((readerStates.dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT)
+ {
+ // We found a card in this reader
+ Application::_slotCache[i]->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+ Log::log( "Application::Enumerate - New Cache[ %d ] - Name <%s> - Token present", i, Application::_slotCache[ i ]->_readerName->c_str( ) );
+ }
+ else
+ {
+ // No card in this reader
+ Application::_slotCache[i]->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+ Log::log( "Application::Enumerate - New Cache[ %d ] - Name <%s> - Token NOT present", i, Application::_slotCache[ i ]->_readerName->c_str( ) );
+ }
+ }
+
+ // Slots with Token Present
+ if((tokenPresent == TRUE) &&
+ (Application::_slotCache[i]->_slotInfo.flags & CKF_TOKEN_PRESENT))
+ {
+ slotNb++;
+ }
+ // All slots
+ else if (tokenPresent == FALSE)
+ {
+ slotNb++;
+ }
+ }
+ }
+
+ // If pSlotList is not NULL then *pulCount contains the buffer size of pSlotList
+ // so we need to check if size passed is valid or not.
+ if((pSlotList != NULL_PTR)&&(*pulCount < slotNb))
+ {
+ *pulCount = slotNb;
+ Log::error( "Application::Enumerate", "CKR_BUFFER_TOO_SMALL" );
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ *pulCount = slotNb;
+
+ // Fill slot list if not NULL
+ if (pSlotList != NULL_PTR)
+ {
+ for (int i = 0; i < CONFIG_MAX_SLOT; i++)
+ {
+ // Existing Slots only are scanned
+ if (Application::_slotCache[i] != NULL_PTR)
+ {
+ CK_BBOOL IsFound = FALSE;
+
+ // Slots with Token Present
+ if((tokenPresent == TRUE) &&
+ (Application::_slotCache[i]->_slotInfo.flags & CKF_TOKEN_PRESENT))
+ {
+ IsFound = TRUE;
+ }
+
+ // All slots
+ else if (tokenPresent == FALSE)
+ {
+ IsFound = TRUE;
+ }
+
+ // Fill Slot List
+ if(IsFound == TRUE)
+ {
+ pSlotList[sid++] = Application::_slotCache[i]->_slotId;
+ }
+ }
+ }
+ }
+
+ Log::end( "Application::Enumerate" );
+
+ return CKR_OK;
+}
+
+#else // _XCL_
+
+CK_RV Application::Enumerate( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount )
+{
+ PRINT_MSG("IN Application::Enumerate");
+
+ LPTSTR pReaderList = NULL;
+ CK_SLOT_ID slotIdx = 0;
+ CK_ULONG slotNb = 0;
+ LPTSTR pReader = NULL;
+ CK_LONG hResult = 0;
+ CK_SLOT_ID sid = 0;
+
+ if(pulCount == NULL_PTR){
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ DWORD readerListCharLength = SCARD_AUTOALLOCATE;
+
+ // asadali
+ // Get reader list, For now only ONE SEG-Lite token ...
+ pReaderList = (char *) malloc(64);
+ strcpy(pReaderList, "xCL_Token");
+ readerListCharLength = strlen(pReaderList);
+ *(pReaderList + readerListCharLength) = '\0';
+ *(pReaderList + readerListCharLength + 1) = '\0';
+
+ // Get Reader List if not already Get
+ if (Application::_numSlots == 0)
+ {
+ // clear the slot cache
+ //CSlot::ClearCache();
+
+ pReader = pReaderList;
+
+ while ('\0' != *pReader )
+ {
+ size_t readerNameLen = strlen((const char*)pReader);
+ size_t sd;
+
+ Slot* slot = new Slot();
+ slot->_slotId = slotIdx++;
+
+ // fill in the slot description
+ for(sd = 0; sd < readerNameLen; sd++)
+ {
+ slot->_slotInfo.slotDescription[sd] = pReader[sd];
+ }
+
+ if(slotIdx > CONFIG_MAX_SLOT){
+ return CKR_HOST_MEMORY;
+ }
+
+ slotNb++;
+
+ slot->_readerName = new std::string(pReader);
+
+// GD Application::AddSlotToCache(slot);
+ Application::addSlot (slot);
+
+ // Advance to the next value.
+ pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
+ }
+
+ free(pReaderList);
+ Application::_numSlots = slotNb;
+ }
+
+ // Scan Reader List
+ slotNb = 0;
+
+ for (int i = 0; i < CONFIG_MAX_SLOT; i++)
+ {
+ // Existing Slots only are scanned
+ if (Application::_slotCache[i] != NULL_PTR)
+ {
+ SCARD_READERSTATE readerStates;
+
+ readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+ readerStates.szReader = Application::_slotCache[i]->_readerName->c_str();
+
+ // Lets check if token is present or not
+
+ // asadali
+ if (xCL_IsTokenPresent())
+ {
+ // We found a card in this reader
+ Application::_slotCache[i]->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+ }
+ else
+ {
+ // No card in reader
+ Application::_slotCache[i]->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+ }
+
+ // Slots with Token Present
+ if((tokenPresent == TRUE) &&
+ (Application::_slotCache[i]->_slotInfo.flags & CKF_TOKEN_PRESENT))
+ {
+ slotNb++;
+ }
+ // All slots
+ else if (tokenPresent == FALSE)
+ {
+ slotNb++;
+ }
+ }
+ }
+
+ // If pSlotList is not NULL then *pulCount contains the buffer size of pSlotList
+ // so we need to check if size passed is valid or not.
+ if((pSlotList != NULL_PTR)&&(*pulCount < slotNb))
+ {
+ *pulCount = slotNb;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ *pulCount = slotNb;
+
+ // Fill slot list if not NULL
+ if (pSlotList != NULL_PTR)
+ {
+ for (int i = 0; i < CONFIG_MAX_SLOT; i++)
+ {
+ // Existing Slots only are scanned
+ if (Application::_slotCache[i] != NULL_PTR)
+ {
+ CK_BBOOL IsFound = FALSE;
+
+ // Slots with Token Present
+ if((tokenPresent == TRUE) &&
+ (Application::_slotCache[i]->_slotInfo.flags & CKF_TOKEN_PRESENT))
+ {
+ IsFound = TRUE;
+ }
+
+ // All slots
+ else if (tokenPresent == FALSE)
+ {
+ IsFound = TRUE;
+ }
+
+ // Fill Slot List
+ if(IsFound == TRUE)
+ {
+ pSlotList[sid++] = Application::_slotCache[i]->_slotId;
+ }
+ }
+ }
+ }
+
+ return CKR_OK;
+}
+
+#endif // _XCL_
+
+/*
+*/
+CK_RV Application::GetSlotFromSlotId( CK_SLOT_ID slotId, Slot** slot )
+{
+ if(((int)slotId < 0) || (slotId >= CONFIG_MAX_SLOT))
+ {
+ return CKR_SLOT_ID_INVALID;
+ }
+
+ if (Application::_slotCache[slotId] != NULL_PTR)
+ {
+ *slot = Application::_slotCache[slotId];
+ return CKR_OK;
+ }
+
+ return CKR_SLOT_ID_INVALID;
+}
+
+
+/*
+*/
+void Application::ClearCache(void)
+{
+ // initialize the slot cache
+ CK_SLOT_ID sid = 0;
+ for(;sid<CONFIG_MAX_SLOT;sid++)
+ {
+ if(Application::_slotCache[sid] != NULL_PTR)
+ {
+ Slot* slot = Application::_slotCache[sid];
+#ifdef INCLUDE_EVENTING
+ if(slot->_tracker != NULL_PTR)
+ {
+ slot->_tracker->stop();
+ }
+#endif
+
+ delete slot;
+ Application::_slotCache[sid] = NULL_PTR;
+ }
+ }
+
+ // set the number of actual slots present to zero
+ Application::_numSlots = 0;
+
+#ifdef INCLUDE_EVENTING
+ // we should just signal all the events
+ CryptokiEvent.Signal();
+#endif
+}
+
+
+/*
+*/
+void Application::Release( void )
+{
+ if( 0 != Application::_hContext )
+ {
+#ifndef _XCL_
+ SCardReleaseContext( Application::_hContext );
+#endif // _XCL_
+ Application::_hContext = 0;
+ }
+}
+
+
+/*
+*/
+void Application::End( void )
+{
+ Application::ClearCache( );
+ Application::Release( );
+}
+
+
+/*
+*/
+void Application::deleteSlot( int i )
+{
+ if( NULL_PTR != Application::_slotCache[ i ] )
+ {
+#ifdef INCLUDE_EVENTING
+ if( NULL_PTR != (Application::_slotCache[ i ]->_tracker) )
+ {
+ (Application::_slotCache[ i ])->_tracker->stop( );
+ }
+#endif
+ delete (Application::_slotCache[ i ]);
+ Application::_slotCache[ i ] = NULL_PTR;
+
+#ifdef INCLUDE_EVENTING
+ // we should just signal all the events
+ CryptokiEvent.Signal( );
+#endif
+
+ }
+}
+
+
+/*
+*/
+
+#ifndef _XCL_
+
+CK_RV Application::addSlot( std::string& a_readerName )
+{
+ int iSlotID = -1;
+ for( int j = 0 ; j < CONFIG_MAX_SLOT ; j++ )
+ {
+ if( NULL_PTR == Application::_slotCache[ j ] )
+ {
+ iSlotID = j;
+ break;
+ }
+ }
+ if( -1 == iSlotID )
+ {
+ return CKR_HOST_MEMORY;
+ }
+
+ Slot* slot = new Slot( );
+ slot->_readerName = new std::string( a_readerName );
+
+ // Fill in the slot description
+ size_t l = ( a_readerName.length( ) > sizeof( slot->_slotInfo.slotDescription ) ) ? sizeof( slot->_slotInfo.slotDescription ) : a_readerName.length( );
+ for( size_t i = 0 ; i < l ; i++ )
+ {
+ slot->_slotInfo.slotDescription[ i ] = a_readerName[ i ];
+ }
+
+ // Add Slot in Cache
+ slot->_slotId = iSlotID;
+ Application::_slotCache[ iSlotID ] = slot;
+
+#ifdef INCLUDE_EVENTING
+ SCARD_READERSTATE readerStates;
+
+ readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+ readerStates.szReader = slot->_readerName->c_str();
+
+ if (SCardGetStatusChange(Application::_hContext, 0, &readerStates, 1) == SCARD_S_SUCCESS)
+ {
+ if ((readerStates.dwEventState & SCARD_STATE_PRESENT) != SCARD_STATE_PRESENT)
+ {
+ // we not found a card in this reader
+ slot->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+ }
+ else
+ {
+ // we found a card in this reader
+ slot->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+ }
+ }
+
+ // Start the monitoring also
+ slot->_tracker = new CardMonitoringThread(slot->_readerName->c_str());
+ slot->_tracker->SetSlot(slot);
+ slot->_tracker->start();
+
+#endif
+
+ return CKR_OK;
+}
+
+#else // _XCL_
+
+void Application::addSlot( Slot* slot )
+{
+ PRINT_MSG("IN Application::AddslotToCache");
+
+ // Add Slot in Cache
+ Application::_slotCache[slot->_slotId] = slot;
+
+#ifdef INCLUDE_EVENTING
+ SCARD_READERSTATE readerStates;
+
+ readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+ readerStates.szReader = slot->_readerName->c_str();
+
+ // asadali
+ if (xCL_IsTokenPresent())
+ {
+ // we found a card in this reader
+ slot->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+ }
+ else
+ {
+ // No card in reader
+ slot->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+ }
+
+ // Start the monitoring also
+ slot->_tracker = new CardMonitoringThread(slot->_readerName->c_str());
+ slot->_tracker->SetSlot(slot);
+ slot->_tracker->start();
+#endif
+}
+
+#endif // _XCL_
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/application.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,66 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_application_h
+#define _include_application_h
+
+#include <vector>
+#include <list>
+
+#ifdef _XCL_
+#include <xcl_utils.h>
+#endif // _XCL_
+
+using namespace std;
+
+class Application {
+
+public:
+ static CK_ULONG _numSlots;
+ static Slot* _slotCache[CONFIG_MAX_SLOT];
+ static SCARDCONTEXT _hContext;
+
+#ifdef _XCL_
+ static xCL_DeviceHandle _deviceHandle;
+#endif // _XCL_
+
+public:
+ static CK_RV InitApplication(void);
+
+ static CK_RV Enumerate(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount);
+
+ static CK_RV GetSlotFromSlotId(CK_SLOT_ID slotId, Slot** slot);
+
+// static void AddSlotToCache(Slot* slot);
+ static void addSlot( Slot* slot );
+
+ static void ClearCache();
+
+ static void Release( void );
+ static void End( void );
+ //static void ReleaseThreads( void );
+
+ static void deleteSlot( int i );
+ static CK_RV addSlot( std::string& a_readerName );
+
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,221 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+// This code is based on class in ACS baseline.
+
+//#pragma warning(disable : 4251)
+
+#include "stdafx.h"
+#include "platconfig.h"
+//#include "config.h"
+//#include "dbg.h"
+
+
+
+#include <numeric>
+#include <functional>
+#include "attrcert.h"
+#include "digest.h"
+#include "sha1.h"
+
+using namespace std;
+
+namespace
+{
+
+ class JoinWith
+ : public binary_function<string, string, string>
+ {
+ public:
+
+ explicit
+ JoinWith(second_argument_type const &rGlue)
+ : m_Glue(rGlue)
+ {}
+
+
+ result_type
+ operator()(string const &rFirst,
+ string const &rSecond) const
+ {
+ return rFirst + m_Glue + rSecond;
+ }
+
+ private:
+
+ second_argument_type const m_Glue;
+ };
+
+ string
+ Combine(vector<string> const &rvsNames)
+ {
+ static string::value_type const cBlank = ' ';
+ static string const sBlank(1, cBlank);
+
+ if(!rvsNames.empty())
+ return accumulate(rvsNames.begin() + 1, rvsNames.end(),
+ *rvsNames.begin(), JoinWith(sBlank));
+ else
+ return string();
+ }
+
+} // namespace
+
+CAttributedCertificate::CAttributedCertificate(BEROctet::Blob const &cert) : m_x509cert(cert)
+{
+}
+
+CAttributedCertificate::CAttributedCertificate(const unsigned char * cert, size_t length)
+ : m_x509cert(cert, static_cast<unsigned long>(length))
+{
+}
+
+CAttributedCertificate::~CAttributedCertificate()
+{
+}
+
+BEROctet::Blob
+CAttributedCertificate::Modulus() const
+{
+ return m_x509cert.Modulus();
+}
+
+BEROctet::Blob
+CAttributedCertificate::PublicExponent() const
+{
+ return m_x509cert.PublicExponent();
+}
+
+BEROctet::Blob
+CAttributedCertificate::Subject() const
+{
+ return m_x509cert.Subject();
+}
+
+BEROctet::Blob
+CAttributedCertificate::Issuer() const
+{
+ return m_x509cert.Issuer();
+}
+
+BEROctet::Blob
+CAttributedCertificate::SerialNumber() const
+{
+ return m_x509cert.SerialNumber();
+}
+
+string
+CAttributedCertificate::DerivedName() const
+{
+ string sDerivedName(Combine(m_x509cert.UTF8SubjectCommonName()));
+ if(sDerivedName.empty())
+ sDerivedName.assign("Smart Card User");
+ return sDerivedName;
+}
+
+string
+CAttributedCertificate::DerivedLabel() const
+{
+ return Combine(m_x509cert.SubjectCommonName());
+}
+
+BEROctet::Blob
+CAttributedCertificate::DerivedId() const
+{
+ return DerivedId(m_x509cert.Modulus());
+}
+
+BEROctet::Blob
+CAttributedCertificate::DerivedId(BEROctet::Blob const & data)
+{
+ return DerivedId(data.c_str(), data.size());
+}
+
+BEROctet::Blob
+CAttributedCertificate::DerivedId(unsigned char const * data, size_t length)
+{
+ CSHA1 sha1;
+ u1 hash[20];
+ sha1.HashCore(const_cast<CK_BYTE_PTR>(data), 0, static_cast<CK_LONG>(length));
+ sha1.HashFinal(hash);
+
+ return BEROctet::Blob(hash, 20);
+}
+
+string
+CAttributedCertificate::DerivedUniqueName() const
+{
+ return DerivedUniqueName(m_x509cert.Modulus());
+}
+
+string
+CAttributedCertificate::DerivedUniqueName(BEROctet::Blob const & data)
+{
+ return DerivedUniqueName(data.c_str(), data.size());
+}
+
+string
+CAttributedCertificate::DerivedUniqueName(unsigned char const * data, size_t length)
+{
+ CSHA1 sha1;
+ u1 hash[20];
+ sha1.HashCore(const_cast<CK_BYTE_PTR>(data), 0, static_cast<CK_LONG>(length));
+ sha1.HashFinal(hash);
+
+ // Format as a GUID
+
+ char name[40];
+
+ u1 *id = hash;
+
+ int i, n = 0;
+ char *c = name;
+
+ for(i=0; i<4; i++) {
+ sprintf(c,"%02x",id[n]);
+ n++; c+=2;
+ }
+ sprintf(c,"-");
+ c++;
+ for(i=0; i<2; i++) {
+ sprintf(c,"%02x",id[n]);
+ n++; c+=2;
+ }
+ sprintf(c,"-");
+ c++;
+ for(i=0; i<2; i++) {
+ sprintf(c,"%02x",id[n]);
+ n++; c+=2;
+ }
+ sprintf(c,"-");
+ c++;
+ for(i=0; i<2; i++) {
+ sprintf(c,"%02x",id[n]);
+ n++; c+=2;
+ }
+ sprintf(c,"-");
+ c++;
+ for(i=0; i<6; i++) {
+ sprintf(c,"%02x",id[n]);
+ n++; c+=2;
+ }
+
+ return string(name);
+}
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/attrcert.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,84 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+// This code is based on class in ACS baseline.
+
+#ifndef _include_attrcert_h
+#define _include_attrcert_h
+
+#include "x509cert.h"
+
+
+class CAttributedCertificate
+{
+
+public:
+ explicit CAttributedCertificate(BEROctet::Blob const &cert);
+ CAttributedCertificate(const unsigned char * cert, size_t length);
+
+ virtual ~CAttributedCertificate();
+
+ BEROctet::Blob
+ Modulus() const;
+
+ BEROctet::Blob
+ PublicExponent() const;
+
+ BEROctet::Blob
+ Subject() const;
+
+ BEROctet::Blob
+ Issuer() const;
+
+ BEROctet::Blob
+ SerialNumber() const;
+
+ std::string
+ DerivedName() const;
+
+ std::string
+ DerivedLabel() const;
+
+ BEROctet::Blob
+ DerivedId() const;
+
+ static BEROctet::Blob
+ DerivedId(BEROctet::Blob const & data);
+
+ static BEROctet::Blob
+ DerivedId(unsigned char const * data, size_t length);
+
+ std::string
+ DerivedUniqueName() const;
+
+ static std::string
+ DerivedUniqueName(BEROctet::Blob const & data);
+
+ static std::string
+ DerivedUniqueName(unsigned char const * data, size_t length);
+
+private:
+ X509Cert m_x509cert;
+
+};
+
+
+#endif // _include_attrcert_h
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,739 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+// This implementation is based on X.690 specification. Access to this
+// specification is a pre-requisite to understand the logic. The spec
+// can be purchased from International Telecommunication Union (ITU)
+// at http://www.itu.int
+
+// This code is based on class in ACS baseline.
+
+#include <string.h>
+#include <stdlib.h>
+#include "beroctet.h"
+
+using namespace std;
+
+BEROctet::BEROctet() : m_tcClass(tcUniversal),
+ m_fConstructed(fBerPcPrimitive),
+ m_dwTag(dwBerUnivZero),
+ m_fDefinite(true),
+ m_fModified(true)
+{
+}
+
+BEROctet::BEROctet(BEROctet const &oct)
+{
+ *this = oct;
+}
+
+BEROctet::BEROctet(Blob const &blb)
+{
+ Decode(blb);
+}
+
+BEROctet::BEROctet(TagClass tcClass, bool fConstructed, unsigned int dwTag, bool fDefinite) :
+ m_tcClass(tcClass),
+ m_fConstructed(fConstructed),
+ m_dwTag(dwTag),
+ m_fDefinite(fDefinite),
+ m_fModified(true)
+{
+ if(!m_fDefinite && !m_fConstructed)
+ throw runtime_error("BERPrimitiveIndefiniteLength");
+}
+
+BEROctet::~BEROctet(void)
+{
+ for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+ delete m_SubOctetList[i];
+}
+
+BEROctet& BEROctet::operator=(BEROctet const &Oct)
+{
+
+ for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+ delete m_SubOctetList[i];
+
+ m_SubOctetList.resize(0);
+ m_blbData.resize(0);
+
+ m_fModified = Oct.m_fModified;
+ m_blbOrigOctet = Oct.m_blbOrigOctet;
+
+ m_fConstructed = Oct.m_fConstructed;
+ m_tcClass = Oct.m_tcClass;
+ m_dwTag = Oct.m_dwTag;
+ m_fDefinite = Oct.m_fDefinite;
+
+
+ if(m_fConstructed)
+ {
+ for(std::vector<BEROctet const*>::size_type i=0; i<Oct.m_SubOctetList.size(); i++)
+ m_SubOctetList.push_back(new BEROctet(*Oct.m_SubOctetList[i]));
+ }
+ else
+ m_blbData = Oct.m_blbData;
+
+ return *this;
+}
+
+// Returns a the data part of the octet
+
+BEROctet::Blob BEROctet::Data() const
+{
+
+ if(m_fConstructed)
+ {
+
+ // Traverse the tree
+
+ Blob data;
+
+ for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+ data += m_SubOctetList[i]->Octet();
+
+ return data;
+ }
+ else
+ return m_blbData;
+
+}
+
+// Sets the data part of the octet
+
+void BEROctet::Data(Blob const &blb)
+{
+
+ if(m_fConstructed)
+ throw runtime_error("BERInconsistentOperation");
+
+ m_blbData = blb;
+ m_fModified = true;
+
+}
+
+// If the octet is a constructed type, this returns list of sub-octets
+
+vector<BEROctet*> BEROctet::SubOctetList() const
+{
+ if(!m_fConstructed)
+ throw runtime_error("BERInconsistentOperation");
+
+ return m_SubOctetList;
+}
+
+// Insert an octet as a sub-octet of a constructed octet
+
+void BEROctet::Insert(BEROctet const &oct)
+{
+ if(!m_fConstructed)
+ throw runtime_error("BERInconsistentOperation");
+
+ BEROctet *pOct = new BEROctet(oct);
+ m_SubOctetList.push_back(pOct);
+ m_fModified = true;
+
+}
+
+// Returns the whole octet
+
+BEROctet::Blob BEROctet::Octet() const
+{
+ if(Modified())
+ {
+
+ Blob blbOct = IdentOctets(m_tcClass, m_fConstructed, m_dwTag);
+ Blob blbData = Data();
+
+ if(m_fDefinite)
+ blbOct += LengthOctets(static_cast<unsigned int>(blbData.size()));
+ else
+ blbOct += 0x80; // Indefinite length octet
+
+ blbOct += blbData;
+
+ if(!m_fDefinite)
+ {
+
+ // Terminate with end-of-contents octet
+
+ BEROctet blbZero;
+ blbOct += blbZero.Octet();
+ }
+
+ return blbOct;
+ }
+ else
+ return m_blbOrigOctet;
+
+}
+
+// Returns the class of the octet
+
+TagClass BEROctet::Class() const
+{
+ return m_tcClass;
+}
+
+// Returns true if the octet is constructet, false otherwise
+
+bool BEROctet::Constructed() const
+{
+ return m_fConstructed;
+}
+
+// Returns the tag of the octet
+
+unsigned int BEROctet::Tag() const
+{
+ return m_dwTag;
+}
+
+// Decode the contents of an OID
+
+string BEROctet::ObjectID() const
+{
+
+ if(m_tcClass!=tcUniversal || m_dwTag!=dwBerUnivObjectIdent)
+ throw runtime_error("BERInconsistentOperation");
+
+ if(!m_blbData.size())
+ throw runtime_error("BEREmptyOctet");
+
+ string OID;
+
+ // The scratch buffer "text" below needs to be large enough to hold
+ // the decimal encoding of two 32 bit integers, including a space
+ // and the terminating zero.
+
+ char text[40];
+
+ unsigned int subid;
+ const unsigned char *c = m_blbData.data();
+ const unsigned char *Last = c + m_blbData.size();
+ bool First = true;
+
+ while(c<Last)
+ {
+ subid = (*c)&0x7F;
+ while((*c)&0x80)
+ {
+ c++;
+ if(c>=Last)
+ throw runtime_error("BERUnexpectedEndOfOctet");
+ if(subid>0x01FFFFFF)
+ throw runtime_error("BEROIDSubIdentifierOverflow");
+ subid = (subid<<7) | ((*c)&0x7F);
+ }
+ if(First)
+ {
+ unsigned int X,Y;
+ if(subid<40)
+ X=0;
+ else if(subid<80)
+ X=1;
+ else
+ X=2;
+ Y = subid-X*40;
+ sprintf(text,"%d %d",X,Y);
+ OID = text;
+ First = false;
+ }
+ else
+ {
+ sprintf(text," %d",subid);
+ OID += text;
+ }
+ c++;
+ }
+
+ return OID;
+}
+
+// Encode an OID
+
+void BEROctet::ObjectID(string const &str)
+{
+
+ if(m_tcClass!=tcUniversal)
+ throw runtime_error("BERInconsistentOperation");
+
+ if(m_dwTag==dwBerUnivZero)
+ m_dwTag = dwBerUnivObjectIdent;
+
+ if(m_dwTag!=dwBerUnivObjectIdent)
+ throw runtime_error("BERInconsistentOperation");
+
+ char *oid = 0;
+
+ try
+ {
+#if defined(_WIN32)
+ oid = _strdup(str.c_str());
+#else
+ oid = strdup(str.c_str());
+#endif
+ char *s;
+
+ if(0==(s = strtok(oid," ")))
+ throw runtime_error("BERIllegalObjectIdentifier");
+
+ unsigned int X,Y,dwSubOID;
+
+ if(sscanf(s,"%u",&X)!=1)
+ throw runtime_error("BERIllegalObjectIdentifier");
+
+ if(X>2)
+ throw runtime_error("BERIllegalObjectIdentifier");
+
+ if(0==(s = strtok(0," ")))
+ throw runtime_error("BERIllegalObjectIdentifier");
+
+ if(sscanf(s,"%u",&Y)!=1)
+ throw runtime_error("BERIllegalObjectIdentifier");
+
+ if(X<2 && Y>39)
+ throw runtime_error("BERIllegalObjectIdentifier");
+
+ dwSubOID = X*40;
+ if(Y>0xFFFFFFFF-dwSubOID)
+ throw runtime_error("BERDataOverflow");
+
+ dwSubOID += Y;
+
+ Blob blbData;
+
+ while(true)
+ {
+
+ unsigned char buf[2*sizeof(dwSubOID)];
+ int n=0;
+ while(dwSubOID>0x7F)
+ {
+ buf[n] = static_cast<unsigned char>(dwSubOID & 0x7F);
+ dwSubOID >>=7;
+ n++;
+ }
+ buf[n] = static_cast<unsigned char>(dwSubOID & 0x7F);
+ n++;
+
+ for(int i=0; i<n; i++)
+ {
+ unsigned char b = buf[n-i-1];
+ if((i+1)<n) b |= 0x80;
+ blbData += b;
+ }
+
+ if(0==(s = strtok(0," ")))
+ break;
+ if(sscanf(s,"%u",&dwSubOID)!=1)
+ break;
+ }
+
+ Data(blbData);
+
+ }
+ catch(...)
+ {
+ if(oid)
+ free(oid);
+ throw;
+ }
+
+ if(oid)
+ free(oid);
+
+}
+
+// Decode a Time octet. Output format: "YYYYMMDDHHMMSS"
+
+// We here apply the convention from RFC 2459 that the 2 digit year
+// encoded in UTCTime is in the range 1950-2049.
+
+string BEROctet::Time() const
+{
+
+ static const Blob::size_type UnivUTCTimeSize = 13;
+ static const Blob::size_type UnivGenTimeSize = 15;
+
+ if(m_tcClass!=tcUniversal)
+ throw runtime_error("BERInconsistentOperation");
+
+ if(m_dwTag==dwBerUnivUTCTime)
+ {
+ // UTCTime
+
+ if(m_blbData.size()!=UnivUTCTimeSize)
+ throw runtime_error("BERInconsistentDataLength");
+
+ string strCentury, strYear((char*)m_blbData.data(),2);
+ int iYear;
+ if(sscanf(strYear.c_str(),"%d",&iYear)!=1)
+ throw runtime_error("FormatDecodingError");
+
+ if(iYear>=50) strCentury = "19";
+ else strCentury = "20";
+
+ // Add century and strip off the 'Z'
+
+ return strCentury + string((char*)m_blbData.data(),UnivUTCTimeSize-1);
+ }
+ else if(m_dwTag==dwBerUnivGenTime)
+ {
+ // GeneralizedTime
+
+ if(m_blbData.size()!=UnivGenTimeSize)
+ throw runtime_error("BERInconsistentDataLength");
+
+ // Return the string as is, stripping off the 'Z'
+
+ return string((char*)m_blbData.data(),UnivGenTimeSize-1);
+ }
+ else
+ throw runtime_error("BERInconsistentOperation");
+
+}
+
+// Encode a Time. Input format: "YYYYMMDDHHMMSS"
+
+// If the Tag is not set to be either UTC Time or Generalized Time,
+// we apply the convention from RFC 2459 where years in the range
+// 1950-2049 are encoded as UTC Time and years later are encoded as
+// Generalized time. In this case, years < 1950 are not allowed.
+
+void BEROctet::Time(string const &str)
+{
+ static const Blob::size_type ExpectedSize = 14;
+
+ if(m_tcClass!=tcUniversal)
+ throw runtime_error("BERInconsistentOperation");
+
+ if(str.size()!=ExpectedSize)
+ throw runtime_error("IllegalParameter");
+
+ // If m_dwTag is zero, chose appropriate tag according to year
+
+ int iYear;
+ if(sscanf(str.substr(0,4).c_str(),"%d",&iYear)!=1)
+ throw runtime_error("IllegalParameter");
+
+ if(m_dwTag==dwBerUnivZero)
+ {
+ if(iYear<1950)
+ throw runtime_error("IllegalParameter");
+ else if(iYear<2050)
+ m_dwTag = dwBerUnivUTCTime;
+ else
+ m_dwTag = dwBerUnivGenTime;
+ }
+
+ Blob blbData;
+
+ if(m_dwTag==dwBerUnivUTCTime)
+ blbData.assign(((unsigned char*)str.data()+2),str.size()-2);
+
+ else if(m_dwTag==dwBerUnivGenTime)
+ blbData.assign((unsigned char*)str.data(),str.size());
+
+ else
+ throw runtime_error("BERInconsistentOperation");
+
+ blbData += 'Z';
+
+ Data(blbData);
+
+}
+
+// SearchOID returns all the constructed octets that contain a particular OID
+
+void BEROctet::SearchOID(string const &OID, vector<BEROctet const*> &result) const
+{
+
+ for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+ {
+
+ if(m_SubOctetList[i]->Class()==tcUniversal &&
+ m_SubOctetList[i]->Tag()==dwBerUnivObjectIdent)
+ {
+ if(OID==m_SubOctetList[i]->ObjectID())
+ result.push_back(this);
+ }
+ else if(m_SubOctetList[i]->Constructed())
+ m_SubOctetList[i]->SearchOID(OID,result);
+ }
+
+ return;
+
+}
+
+// SearchOIDNext returns all the octets following a particular OID
+
+void BEROctet::SearchOIDNext(string const &OID, vector<BEROctet const*> &result) const
+{
+ for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+ {
+ if(m_SubOctetList[i]->Class()==tcUniversal &&
+ m_SubOctetList[i]->Tag()==dwBerUnivObjectIdent)
+ {
+ if(OID==m_SubOctetList[i]->ObjectID())
+ {
+ if((i+1) < m_SubOctetList.size())
+ result.push_back(m_SubOctetList[i+1]);
+ }
+ }
+ else if(m_SubOctetList[i]->Constructed())
+ m_SubOctetList[i]->SearchOIDNext(OID,result);
+ }
+
+ return;
+
+}
+
+// Construct the Identifier octets
+
+BEROctet::Blob BEROctet::IdentOctets(TagClass tcClass, bool fConstructed, unsigned int dwTag)
+{
+
+ unsigned char bLeadingOct;
+ switch(tcClass)
+ {
+
+ case tcUniversal:
+ bLeadingOct = 0x00;
+ break;
+
+ case tcApplication:
+ bLeadingOct = 0x40;
+ break;
+
+ case tcContext:
+ bLeadingOct = 0x80;
+ break;
+
+ case tcPrivate:
+ bLeadingOct = 0xC0;
+ break;
+
+ default:
+ throw runtime_error("BERIllegalClass");
+ }
+
+ if(fConstructed)
+ bLeadingOct |= 0x20;
+
+ int n = 0;
+ unsigned char buf[sizeof(dwTag)];
+
+ if(dwTag<=30)
+ bLeadingOct |= dwTag;
+
+ else
+ {
+ bLeadingOct |= 0x1F;
+ while(dwTag>0)
+ {
+ buf[n] = static_cast<unsigned char>(dwTag & 0x000000FF);
+ dwTag >>= 8;
+ n++;
+ }
+ }
+
+ Blob IdentOcts(&bLeadingOct,1);
+
+ for(int i=0; i<n; i++)
+ IdentOcts +=buf[n-i-1];
+
+ return IdentOcts;
+
+}
+
+// Construct the Length octets
+
+BEROctet::Blob BEROctet::LengthOctets(unsigned int dwLength)
+{
+
+ int n = 0;
+ unsigned char buf[sizeof(dwLength)];
+ unsigned char bLeadingOct;
+
+ if(dwLength<=0x7F)
+ bLeadingOct = static_cast<unsigned char>(dwLength);
+ else
+ {
+ bLeadingOct = 0x80;
+ while(dwLength>0)
+ {
+ buf[n] = static_cast<unsigned char>(dwLength & 0x000000FF);
+ dwLength >>= 8;
+ n++;
+ }
+ bLeadingOct |= n;
+ }
+
+ Blob LengthOcts(&bLeadingOct,1);
+ for(int i=0; i<n; i++)
+ LengthOcts +=buf[n-i-1];
+
+ return LengthOcts;
+
+}
+
+// Decodes recursively a BER octet.
+
+void BEROctet::Decode(Blob const &blb)
+{
+
+ if(!blb.size())
+ throw runtime_error("BEREmptyOctet");
+
+ size_t BufferSize = blb.size();
+
+ m_fConstructed = (blb[0]&0x20) ? true : false;
+
+ switch(blb[0]&0xC0)
+ {
+
+ case 0x00:
+ m_tcClass = tcUniversal;
+ break;
+
+ case 0x40:
+ m_tcClass = tcApplication;
+ break;
+
+ case 0x80:
+ m_tcClass = tcContext;
+ break;
+
+ case 0xC0:
+ m_tcClass = tcPrivate;
+ break;
+
+ default:
+ throw runtime_error("BERIllegalClass");
+ }
+
+ const unsigned char *c = blb.data();
+ const unsigned char *Last = c + blb.size() - 1;
+ m_dwTag = *c & 0x1F;
+
+ if(m_dwTag>30)
+ {
+ m_dwTag = 0;
+
+ c++;
+ if(c>Last)
+ throw runtime_error("BERUnexpectedEndOfOctet");
+
+ while (*c & 0x80)
+ {
+ m_dwTag = (m_dwTag << 7) | ((*c) & 0x7F);
+ c++;
+ if(c>Last)
+ throw runtime_error("BERUnexpectedEndOfOctet");
+ }
+
+ if(m_dwTag > 0x01FFFFFF)
+ throw runtime_error("BERTagValueOverflow");
+
+ m_dwTag = (m_dwTag << 7) | ((*c) & 0x7F);
+
+ }
+
+ c++;
+ if(c>Last)
+ throw runtime_error("BERUnexpectedEndOfOctet");
+
+ size_t DataSize;
+
+ if((*c)&0x80)
+ {
+ int n = (*c) & 0x7F;
+ if(n)
+ {
+ DataSize = 0;
+ for(int i=0; i<n; i++)
+ {
+ c++; if(c>Last)
+ throw runtime_error("BERUnexpectedEndOfOctet");
+ if(DataSize>0x007FFFFF)
+ throw runtime_error("BERDataOverflow");
+ DataSize = (DataSize<<8) | (*c);
+ }
+ }
+ else
+ throw runtime_error("BERUnexpectedIndefiniteLength");
+ }
+ else DataSize = *c;
+
+ c++;
+
+ const unsigned char *bpData = c;
+
+ size_t OctetSize = DataSize + (bpData-blb.data());
+
+ m_blbOrigOctet = blb.substr(0,OctetSize);
+ m_fModified = false;
+
+ if(OctetSize>static_cast<unsigned int>(BufferSize))
+ throw runtime_error("BERInconsistentDataLength");
+
+ for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+ delete m_SubOctetList[i];
+
+ m_SubOctetList.resize(0);
+ m_blbData = Blob();
+
+ if(m_fConstructed)
+ {
+
+ // Constructed type
+
+ while(DataSize)
+ {
+
+ BEROctet *suboct = new BEROctet(Blob(bpData,DataSize));
+
+ m_SubOctetList.push_back(suboct);
+
+ Blob blbSubOct = suboct->Octet();
+
+ bpData += blbSubOct.size();
+ DataSize -= blbSubOct.size();
+ }
+ }
+ else
+ m_blbData = Blob(bpData,DataSize);
+
+}
+
+bool BEROctet::Modified() const
+{
+ if(m_fModified)
+ return true;
+
+ if(m_fConstructed)
+ for(std::vector<BEROctet const*>::size_type i=0; i<m_SubOctetList.size(); i++)
+ if(m_SubOctetList[i]->Modified()) return true;
+
+ return false;
+
+}
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/beroctet.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,221 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+// This code is based on class in ACS baseline.
+
+#ifndef _include_beroctet_h
+#define _include_beroctet_h
+
+#include <string>
+#include <vector>
+#include <stdexcept>
+
+enum TagClass {tcAny = -1, tcUniversal = 0, tcApplication = 1, tcContext = 2, tcPrivate = 3};
+
+// Defined tags
+
+const unsigned int dwBerUnivZero = 0;
+const unsigned int dwBerUnivBool = 1;
+const unsigned int dwBerUnivInteger = 2;
+const unsigned int dwBerUnivBitString = 3;
+const unsigned int dwBerUnivOctetString = 4;
+const unsigned int dwBerUnivNull = 5;
+const unsigned int dwBerUnivObjectIdent = 6;
+const unsigned int dwBerUnivObjectDesc = 7;
+const unsigned int dwBerUnivReal = 9;
+const unsigned int dwBerUnivEnum = 10;
+const unsigned int dwBerUnivUTF8String = 12;
+const unsigned int dwBerUnivSequence = 16;
+const unsigned int dwBerUnivSet = 17;
+const unsigned int dwBerUnivPrintString = 19;
+const unsigned int dwBerUnivIA5String = 22;
+const unsigned int dwBerUnivUTCTime = 23;
+const unsigned int dwBerUnivGenTime = 24;
+const unsigned int dwBerGraphicString = 25;
+const unsigned int dwBerISO646String = 26;
+const unsigned int dwBerGeneralString = 27;
+const unsigned int dwBerUniversalString = 28;
+const unsigned int dwBerCharacterString = 29;
+const unsigned int dwBerBMPString = 30;
+const unsigned int dwBerDate = 31;
+const unsigned int dwBerTimeOfDay = 32;
+const unsigned int dwBerDateTime = 33;
+const unsigned int dwBerDuration = 34;
+
+const char OID_pkcs1[] = "1 2 840 113549 1 1";
+const char OID_pkcs1_rsaEncryption[] = "1 2 840 113549 1 1 1";
+const char OID_pkcs1_md2WithRSAEncryption[] = "1 2 840 113549 1 1 2";
+const char OID_pkcs1_md4WithRSAEncryption[] = "1 2 840 113549 1 1 3";
+const char OID_pkcs1_md5WithRSAEncryption[] = "1 2 840 113549 1 1 4";
+const char OID_pkcs1_sha1WithRSAEncryption[] = "1 2 840 113549 1 1 5";
+const char OID_pkcs1_sha256WithRSAEncryption[] = "1 2 840 113549 1 1 11";
+
+const char OID_pkcs7_data[] = "1 2 840 113549 1 7 1";
+const char OID_pkcs7_signedData[] = "1 2 840 113549 1 7 2";
+const char OID_pkcs7_envelopedData[] = "1 2 840 113549 1 7 3";
+const char OID_pkcs7_signedAndEnvelopedData[] = "1 2 840 113549 1 7 4";
+const char OID_pkcs7_digestedData[] = "1 2 840 113549 1 7 5";
+const char OID_pkcs7_encryptedData[] = "1 2 840 113549 1 7 6";
+
+const char OID_pkcs9_emailAddress[] = "1 2 840 113549 1 9 1";
+const char OID_pkcs9_unstructuredName[] = "1 2 840 113549 1 9 2";
+const char OID_pkcs9_contentType[] = "1 2 840 113549 1 9 3";
+const char OID_pkcs9_messageDigest[] = "1 2 840 113549 1 9 4";
+const char OID_pkcs9_signingTime[] = "1 2 840 113549 1 9 5";
+const char OID_pkcs9_countersignature[] = "1 2 840 113549 1 9 6";
+const char OID_pkcs9_challengePassword[] = "1 2 840 113549 1 9 7";
+const char OID_pkcs9_unstructuredAddress[] = "1 2 840 113549 1 9 8";
+const char OID_pkcs9_extendedCertificateAttr[] = "1 2 840 113549 1 9 9";
+const char OID_pkcs9_sMIMECapabilities[] = "1 2 840 113549 1 9 15";
+const char OID_pkcs9_id_smime[] = "1 2 840 113549 1 9 16";
+
+const char OID_digestAlogrithm_md2[] = "1 2 840 113549 2 2";
+const char OID_digestAlogrithm_md4[] = "1 2 840 113549 2 4";
+const char OID_digestAlogrithm_md5[] = "1 2 840 113549 2 5";
+
+const char OID_RC2_CBC[] = "1 2 840 113549 3 2";
+const char OID_dES_EDE3_CBC[] = "1 2 840 113549 3 7";
+
+const char OID_ms_enrollmentAgent[] = "1 3 6 1 4 1 311 20 2 1";
+const char OID_ms_smartCardLogin[] = "1 3 6 1 4 1 311 20 2 2";
+
+const char OID_id_kp_serverAuth[] = "1 3 6 1 5 5 7 3 1";
+const char OID_id_kp_clientAuth[] = "1 3 6 1 5 5 7 3 2";
+const char OID_id_kp_codeSigning[] = "1 3 6 1 5 5 7 3 3";
+const char OID_id_kp_emailProtection[] = "1 3 6 1 5 5 7 3 4";
+const char OID_id_kp_ipsecEndSystem[] = "1 3 6 1 5 5 7 3 5";
+const char OID_id_kp_ipsecTunnel[] = "1 3 6 1 5 5 7 3 6";
+const char OID_id_kp_ipsecUser[] = "1 3 6 1 5 5 7 3 7";
+const char OID_id_kp_timeStamping[] = "1 3 6 1 5 5 7 3 8";
+
+const char OID_md4WithRSA[] = "1 3 14 3 2 2";
+const char OID_md5WithRSA[] = "1 3 14 3 2 3";
+const char OID_md4WithRSAEncryption[] = "1 3 14 3 2 4";
+const char OID_desECB[] = "1 3 14 3 2 6";
+const char OID_desCBC[] = "1 3 14 3 2 7";
+const char OID_desOFB[] = "1 3 14 3 2 8";
+const char OID_desCFB[] = "1 3 14 3 2 9";
+const char OID_desMAC[] = "1 3 14 3 2 10";
+const char OID_rsaSignature[] = "1 3 14 3 2 11";
+const char OID_mdc2WithRSASignature[] = "1 3 14 3 2 14";
+const char OID_shaWithRSASignature[] = "1 3 14 3 2 15";
+const char OID_desEDE[] = "1 3 14 3 2 17";
+const char OID_sha[] = "1 3 14 3 2 18";
+const char OID_rsaKeyTransport[] = "1 3 14 3 2 22";
+const char OID_md2WithRSASignature[] = "1 3 14 3 2 24";
+const char OID_md5WithRSASignature[] = "1 3 14 3 2 25";
+const char OID_sha1[] = "1 3 14 3 2 26";
+const char OID_sha1WithRSASignature[] = "1 3 14 3 2 29";
+
+const char OID_id_at_organizationName[] = "2 5 4 10";
+const char OID_id_at_organizationalUnitName[] = "2 5 4 11";
+const char OID_id_at_commonName[] = "2 5 4 3";
+const char OID_id_at_countryName[] = "2 5 4 6";
+const char OID_id_at_localityName[] = "2 5 4 7";
+const char OID_id_at_stateOrProvinceName[] = "2 5 4 8";
+const char OID_id_ce_subjectDirectoryAttributes[] = "2 5 29 9";
+const char OID_id_ce_subjectKeyIdentifier[] = "2 5 29 14";
+const char OID_id_ce_keyUsage[] = "2 5 29 15";
+const char OID_id_ce_privateKeyUsagePeriod[] = "2 5 29 16";
+const char OID_id_ce_subjectAltName[] = "2 5 29 17";
+const char OID_id_ce_issuerAltName[] = "2 5 29 18";
+const char OID_id_ce_basicConstraints[] = "2 5 29 19";
+const char OID_id_ce_cRLNumber[] = "2 5 29 20";
+const char OID_id_ce_reasonCode[] = "2 5 29 21";
+const char OID_id_ce_instructionCode[] = "2 5 29 23";
+const char OID_id_ce_invalidityDate[] = "2 5 29 24";
+const char OID_id_ce_deltaCRLIndicator[] = "2 5 29 27";
+const char OID_id_ce_issuingDistributionPoint[] = "2 5 29 28";
+const char OID_id_ce_certificateIssuer[] = "2 5 29 29";
+const char OID_id_ce_nameConstraints[] = "2 5 29 30";
+const char OID_id_ce_cRLDistributionPoints[] = "2 5 29 31";
+const char OID_id_ce_certificatePolicies[] = "2 5 29 32";
+const char OID_id_ce_policyMappings[] = "2 5 29 33";
+const char OID_id_ce_policyConstraints[] = "2 5 29 36";
+const char OID_id_ce_authorityKeyIdentifier[] = "2 5 29 35";
+const char OID_id_ce_extKeyUsage[] = "2 5 29 37";
+
+const char OID_sha256[] = "2 16 840 1 101 3 4 2 1";
+const char OID_Netscape_certificate_type[] = "2 16 840 1 113730 1 1";
+//
+////
+
+const bool fBerPcPrimitive = false;
+const bool fBerPcConstructed = true;
+
+class BEROctet
+{
+
+public:
+ typedef std::basic_string<unsigned char> Blob;
+
+ BEROctet();
+ BEROctet(BEROctet const &oct);
+ BEROctet(Blob const &blb);
+ BEROctet(TagClass tcClass, bool fConstructed, unsigned int dwTag, bool fDefinite=true);
+ ~BEROctet();
+
+ BEROctet& operator=(BEROctet const &oct);
+
+ Blob Data() const;
+ void Data(Blob const &data);
+ std::vector<BEROctet*> SubOctetList() const;
+ void Insert(BEROctet const &oct);
+
+ Blob Octet() const;
+
+ TagClass Class() const;
+ bool Constructed() const;
+ unsigned int Tag() const;
+
+ std::string ObjectID() const;
+ void ObjectID(std::string const &str);
+
+ std::string Time() const;
+ void Time(std::string const &str);
+
+ void SearchOID(std::string const &OID, std::vector<BEROctet const*> &result) const;
+ void SearchOIDNext(std::string const &OID, std::vector<BEROctet const*> &result) const;
+
+private:
+ static Blob IdentOctets(TagClass tcClass, bool fConstructed, unsigned int dwTag);
+ static Blob LengthOctets(unsigned int dwLength);
+
+ void Decode(Blob const &blb);
+ bool Modified() const; // =true if octet or sub-octets are modified since decoding
+
+ Blob m_blbOrigOctet; // Original octet that was decoded
+
+ TagClass m_tcClass; // Tag class
+ bool m_fConstructed; // =true if a constructed octed, false if primitive
+ unsigned int m_dwTag; // Tag
+ bool m_fDefinite; // =true for definite form of length octet, false if indefinite
+ bool m_fModified; // =true if octet is modified since decoded, false otherwise
+
+ Blob m_blbData; // Data octets (When primitive)
+ std::vector<BEROctet*> m_SubOctetList; // List of sub-octets (when constructed)
+
+};
+
+
+#endif // _include_beroctet_h
+
+
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,304 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <memory>
+#include "stdafx.h"
+#include "cardcache.h"
+#include "error.h"
+#include "log.h"
+
+
+#define KEYSPEC_KEYEXCHANGE 0x01
+#define KEYSPEC_SIGNATURE 0x02
+#define MAX_RETRY 2
+#define LOW_MEMORY_LIMIT 5000
+
+
+/* Constructor
+*/
+CardCache::CardCache( CardModuleService * mscm ) : _mscm( mscm )
+{
+ if( !mscm )
+ {
+ throw CkError( CKR_FUNCTION_FAILED );
+ }
+}
+
+/*
+*/
+void CardCache::ManageGC( void )
+{
+ try
+ {
+ s4 freeMemory = _mscm->GetMemory( );
+
+ if ( freeMemory < LOW_MEMORY_LIMIT )
+ {
+ Log::error( "CardCache::ManageGC", "ForceGarbageCollector" );
+ _mscm->ForceGarbageCollector( );
+ }
+ }
+ catch( ... )
+ {
+ }
+}
+
+
+/* WriteFile
+Write the incoming data into the incoming pointed path into the smartcard
+and then into the cache
+*/
+void CardCache::WriteFile( std::string const & path, u1Array const & data )
+{
+ int ntry = 0;
+ while( ntry < MAX_RETRY )
+ {
+ try
+ {
+ ManageGC( );
+ ntry++;
+ _mscm->WriteFile( const_cast< std::string* >( &path ), const_cast< u1Array* >( &data ) );
+ _fileCache[ path ] = data;
+ break;
+ }
+ catch( Marshaller::Exception & x )
+ {
+ CK_RV rv = CkError::CheckMarshallerException( x );
+ if( CKR_DEVICE_MEMORY == rv )
+ {
+ Log::error( "CardCache::WriteFile", "ForceGarbageCollector" );
+ _mscm->ForceGarbageCollector( );
+ if( ntry >= MAX_RETRY )
+ {
+ _fileCache.erase( path );
+ throw CkError( rv );
+ }
+ }
+ else
+ {
+ _fileCache.erase( path );
+ throw CkError( rv );
+ }
+ }
+ catch( ... )
+ {
+ _fileCache.erase( path );
+ throw CkError( CKR_FUNCTION_FAILED );
+ }
+ }
+}
+
+
+/* ReadFile
+*/
+const u1Array & CardCache::ReadFile( std::string const & path )
+{
+ // V2+ cards may throw OutOfMemoryException from ReadFile, however
+ // it may recover from this by forcing the garbage collection to
+ // occur. In fact as a result of a ReadFile command that throws
+ // OutOfMemoryException, GC has already occured, so the command may
+ // be re-tried with high chance of success.
+
+ map<string, u1Array>::const_iterator ifile = _fileCache.find( path );
+ if( ifile == _fileCache.end( ) )
+ {
+ int ntry = 0;
+ while( ntry < MAX_RETRY )
+ {
+ try
+ {
+ ManageGC( );
+ ntry++;
+ auto_ptr< u1Array > data( _mscm->ReadFile( const_cast< std::string* >( &path ), 0 ) );
+ _fileCache[ path ] = *data;
+ break;
+ }
+ catch( Marshaller::Exception & x )
+ {
+ CK_RV rv = CkError::CheckMarshallerException( x );
+ if( CKR_DEVICE_MEMORY == rv )
+ {
+ Log::error( "CardCache::ReadFile", "ForceGarbageCollector" );
+ _mscm->ForceGarbageCollector( );
+ if( ntry >= MAX_RETRY )
+ {
+ throw CkError( rv );
+ }
+ }
+ else
+ {
+ throw CkError( rv );
+ }
+ }
+ catch( ... )
+ {
+ throw CkError( CKR_FUNCTION_FAILED );
+ }
+ }
+ }
+
+ return _fileCache[ path ];
+}
+
+
+/* ClearFile
+Erase a file from the cache
+*/
+void CardCache::ClearFile( std::string const &path )
+{
+ _fileCache.erase( path );
+}
+
+
+/* ReadContainer
+Read the contained pointed by the incoming index from the smartcard
+and compute an instance into the cache
+*/
+const CardCache::Container& CardCache::ReadContainer( int const &ctrIndex ) const
+{
+ map< int, Container >::const_iterator icont = _contCache.find( ctrIndex );
+ if( icont == _contCache.end( ) )
+ {
+ try
+ {
+ Container cont;
+ auto_ptr< u1Array > cInfo( _mscm->GetCAPIContainer( ctrIndex ) );
+ u4 offset = 2;
+ for( int ikeySpec = 0; ikeySpec < 2 ; ++ikeySpec )
+ {
+ if( offset < cInfo->GetLength( ) )
+ {
+ u1 keySpec = cInfo->ReadU1At( offset );
+ offset += 2;
+ u1 expontLen = cInfo->ReadU1At( offset );
+ offset++;
+ u1Array publicExponent( expontLen );
+ memcpy( publicExponent.GetBuffer( ), cInfo->GetBuffer( ) + offset, expontLen );
+ offset += ( expontLen + 1 );
+ u4 modulusLen = cInfo->ReadU1At( offset ) << 4; // Modulus Len
+ offset++;
+ u1Array modulus( modulusLen );
+ memcpy( modulus.GetBuffer( ), cInfo->GetBuffer( ) + offset, modulusLen );
+
+ if( keySpec == KEYSPEC_KEYEXCHANGE )
+ {
+ cont.exchModulus = modulus;
+ cont.exchPublicExponent = publicExponent;
+ }
+ else if( keySpec == KEYSPEC_SIGNATURE )
+ {
+ cont.signModulus = modulus;
+ cont.signPublicExponent = publicExponent;
+ }
+ offset += modulusLen;
+ offset += 2;
+ }
+ }
+ _contCache[ ctrIndex ] = cont;
+ }
+ catch( ... )
+ {
+ _contCache[ ctrIndex ] = Container( ); // Empty
+ }
+ }
+ return _contCache[ ctrIndex ];
+}
+
+
+/* ClearContainer
+Erase the container pointed by the incoming index from the cache
+*/
+void CardCache::ClearContainer( int const &ctrIndex )
+{
+ _contCache.erase( ctrIndex );
+}
+
+
+/* FileList
+Retreive the list of the files contained into the incoming directory path
+and returns a string vectors
+*/
+const vector< std::string > & CardCache::FileList( std::string const &dir )
+{
+ map< std::string, vector< std::string > >::const_iterator idir = _fileList.find( dir );
+ if( idir == _fileList.end( ) )
+ {
+ vector< std::string > vfile;
+ int ntry = 0;
+ while( ntry < MAX_RETRY )
+ {
+ try
+ {
+ ManageGC( );
+ ntry++;
+ auto_ptr<StringArray> files( _mscm->GetFiles( const_cast<string*>( &dir ) ) );
+ for( u4 i = 0; i < files->GetLength( ) ; i++ )
+ {
+ vfile.push_back( *files->GetStringAt( i ) );
+ }
+ break;
+ }
+ catch( Marshaller::Exception & x )
+ {
+ CK_RV rv = CkError::CheckMarshallerException( x );
+ if( CKR_DEVICE_MEMORY == rv )
+ {
+ Log::error( "CardCache::FileList", "ForceGarbageCollector" );
+ _mscm->ForceGarbageCollector( );
+ if( ntry >= MAX_RETRY )
+ {
+ throw CkError( rv );
+ }
+ }
+ else
+ {
+ throw CkError( rv );
+ }
+ }
+ catch( ... )
+ {
+ throw CkError( CKR_FUNCTION_FAILED );
+ }
+ }
+ _fileList[ dir ] = vfile;
+ }
+
+ return _fileList[ dir ];
+}
+
+
+/* ClearFileList
+Erase the dir from the cache
+*/
+void CardCache::ClearFileList( std::string const & dir )
+{
+ _fileList.erase( dir );
+}
+
+
+/* ClearAll
+Erase all cache
+*/
+void CardCache::ClearAll( )
+{
+ _fileCache.clear( );
+ _contCache.clear( );
+ _fileList.clear( );
+}
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardcache.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,65 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_cardcache_h
+#define _include_cardcache_h
+
+
+#include "cardmoduleservice.h"
+
+
+#include <map>
+#include <string>
+#include <vector>
+
+class CardCache
+{
+public:
+ struct Container
+ {
+ u1Array exchPublicExponent;
+ u1Array exchModulus;
+ u1Array signPublicExponent;
+ u1Array signModulus;
+ };
+
+ CardCache(CardModuleService * mscm);
+ void WriteFile(std::string const & path, u1Array const & data);
+ const u1Array & ReadFile(std::string const & path);
+ void ClearFile(std::string const & path);
+
+ const Container & ReadContainer( int const &ctrIndex ) const;
+ void ClearContainer(int const &ctrIndex);
+
+ const std::vector<std::string> & FileList(std::string const & dir);
+ void ClearFileList(std::string const & dir);
+
+ void ClearAll();
+
+private:
+ void ManageGC( void );
+ CardModuleService * _mscm;
+ mutable std::map<std::string, u1Array> _fileCache;
+ mutable std::map<int, Container> _contCache;
+ mutable std::map<std::string, vector<string> > _fileList;
+
+};
+
+#endif // _include_cardcache_h
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,346 @@
+// Machine generated C++ stub file (.cpp) for remote object CardModuleService
+// Created on : 06/05/2008 12:22:51
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+#include <winscard.h>
+#include "cardmoduleservice.h"
+
+using namespace std;
+using namespace Marshaller;
+
+
+// Constructors
+CardModuleService::CardModuleService(string* uri) : SmartCardMarshaller(NULL, 0, uri, (u4)0xC04B4E, (u2)0x7FBD, 0) { return; }
+CardModuleService::CardModuleService(string* uri, u4 index) : SmartCardMarshaller(NULL, 0, uri, (u4)0xC04B4E, (u2)0x7FBD, index) { return; }
+CardModuleService::CardModuleService(u2 portNumber, string* uri) : SmartCardMarshaller(NULL, portNumber, uri, (u4)0xC04B4E, (u2)0x7FBD, 0) { return; }
+CardModuleService::CardModuleService(u2 portNumber, string* uri, u4 index) : SmartCardMarshaller(NULL, portNumber, uri, (u4)0xC04B4E, (u2)0x7FBD, index) { return; }
+CardModuleService::CardModuleService(string* readerName, string* uri) : SmartCardMarshaller(readerName, 0, uri, (u4)0xC04B4E, (u2)0x7FBD, 0) { return; }
+CardModuleService::CardModuleService(string* readerName, u2 portNumber, string* uri) : SmartCardMarshaller(readerName, portNumber, uri, (u4)0xC04B4E, (u2)0x7FBD, 0) { return; }
+CardModuleService::CardModuleService(SCARDHANDLE cardHandle, string* uri) : SmartCardMarshaller(cardHandle, 0, uri, (u4)0xC04B4E, (u2)0x7FBD) { return; }
+CardModuleService::CardModuleService(SCARDHANDLE cardHandle, u2 portNumber, string* uri) : SmartCardMarshaller(cardHandle, portNumber, uri, (u4)0xC04B4E, (u2)0x7FBD) { return; }
+
+// Extra method (Microsoft CardModule only)
+void CardModuleService::UpdateCardHandle(SCARDHANDLE cardHandle)
+{
+ UpdatePCSCCardHandle(cardHandle);
+}
+
+// Pre-defined methods
+std::string* CardModuleService::GetReader(void){return GetReaderName();}
+SCARDHANDLE CardModuleService::GetPcscCardHandle(void){return GetCardHandle();}
+void CardModuleService::DoSCardTransact(bool flag){DoTransact(flag);}
+
+// Exposed methods
+
+void CardModuleService::ChangeReferenceData(u1 mode,u1 role,u1Array* oldPin,u1Array* newPin,s4 maxTries){
+ Invoke(5, 0xE08A, MARSHALLER_TYPE_IN_U1, mode, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_IN_U1ARRAY, oldPin, MARSHALLER_TYPE_IN_U1ARRAY, newPin, MARSHALLER_TYPE_IN_S4, maxTries, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+s4 CardModuleService::GetTriesRemaining(u1 role){
+ s4 _s4 = 0;
+ Invoke(1, 0x6D08, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_S4, &_s4);
+ return _s4;
+}
+
+
+void CardModuleService::CreateCAPIContainer(u1 ctrIndex,u1 keyImport,u1 keySpec,s4 keySize,u1Array* keyValue){
+ Invoke(5, 0x0234, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_IN_BOOL, keyImport, MARSHALLER_TYPE_IN_U1, keySpec, MARSHALLER_TYPE_IN_S4, keySize, MARSHALLER_TYPE_IN_U1ARRAY, keyValue, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::DeleteCAPIContainer(u1 ctrIndex){
+ Invoke(1, 0xF152, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::GetCAPIContainer(u1 ctrIndex){
+ u1Array* _u1Array = NULL;
+ Invoke(1, 0x9B2E, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+ return _u1Array;
+}
+
+
+u1Array* CardModuleService::PrivateKeyDecrypt(u1 ctrIndex,u1 keyType,u1Array* encryptedData){
+ u1Array* _u1Array = NULL;
+ Invoke(3, 0x6144, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_IN_U1, keyType, MARSHALLER_TYPE_IN_U1ARRAY, encryptedData, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+ return _u1Array;
+}
+
+
+void CardModuleService::CreateFile(string* path,u1Array* acls,s4 initialSize){
+ Invoke(3, 0xBEF1, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_IN_U1ARRAY, acls, MARSHALLER_TYPE_IN_S4, initialSize, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::CreateDirectory(string* path,u1Array* acls){
+ Invoke(2, 0xACE9, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_IN_U1ARRAY, acls, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::WriteFile(string* path,u1Array* data){
+ Invoke(2, 0xF20E, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_IN_U1ARRAY, data, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::ReadFile(string* path,s4 maxBytesToRead){
+ u1Array* _u1Array = NULL;
+ Invoke(2, 0x744C, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_IN_S4, maxBytesToRead, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+ return _u1Array;
+}
+
+
+void CardModuleService::DeleteFile(string* path){
+ Invoke(1, 0x6E2B, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::DeleteDirectory(string* path){
+ Invoke(1, 0x9135, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+StringArray* CardModuleService::GetFiles(string* path){
+ StringArray* _StringArray = NULL;
+ Invoke(1, 0xE72B, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_STRINGARRAY, &_StringArray);
+ return _StringArray;
+}
+
+
+u1Array* CardModuleService::GetFileProperties(string* path){
+ u1Array* _u1Array = NULL;
+ Invoke(1, 0xA01B, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+ return _u1Array;
+}
+
+
+void CardModuleService::ChangeAuthenticatorEx(u1 mode,u1 oldRole,u1Array* oldPin,u1 newRole,u1Array* newPin,s4 maxTries){
+ Invoke(6, 0x9967, MARSHALLER_TYPE_IN_U1, mode, MARSHALLER_TYPE_IN_U1, oldRole, MARSHALLER_TYPE_IN_U1ARRAY, oldPin, MARSHALLER_TYPE_IN_U1, newRole, MARSHALLER_TYPE_IN_U1ARRAY, newPin, MARSHALLER_TYPE_IN_S4, maxTries, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::GetContainerProperty(u1 ctrIndex,u1 property,u1 flags){
+ u1Array* _u1Array = NULL;
+ Invoke(3, 0x279C, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_IN_U1, property, MARSHALLER_TYPE_IN_U1, flags, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+ return _u1Array;
+}
+
+
+void CardModuleService::SetContainerProperty(u1 ctrIndex,u1 property,u1Array* data,u1 flags){
+ Invoke(4, 0x98D1, MARSHALLER_TYPE_IN_U1, ctrIndex, MARSHALLER_TYPE_IN_U1, property, MARSHALLER_TYPE_IN_U1ARRAY, data, MARSHALLER_TYPE_IN_U1, flags, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::SetCardProperty(u1 property,u1Array* data,u1 flags){
+ Invoke(3, 0xB0E4, MARSHALLER_TYPE_IN_U1, property, MARSHALLER_TYPE_IN_U1ARRAY, data, MARSHALLER_TYPE_IN_U1, flags, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+s4 CardModuleService::GetMemory(){
+ s4 _s4 = 0;
+ Invoke(0, 0x1DB4, MARSHALLER_TYPE_RET_S4, &_s4);
+ return _s4;
+}
+
+
+void CardModuleService::ForceGarbageCollector(){
+ Invoke(0, 0x3D38, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::RecursiveDelete(string* path){
+ Invoke(1, 0xEDD5, MARSHALLER_TYPE_IN_STRING, path, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::Select(MemoryStream* AID){
+ Invoke(1, 0x32E1, MARSHALLER_TYPE_IN_MEMORYSTREAM, AID, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::Verify(u1 P1,u1 P2,u1Array* pin){
+ Invoke(3, 0xD845, MARSHALLER_TYPE_IN_U1, P1, MARSHALLER_TYPE_IN_U1, P2, MARSHALLER_TYPE_IN_U1ARRAY, pin, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+u1 CardModuleService::get_AdminPersonalized(){
+ u1 _u1 = 0;
+ Invoke(0, 0xCFBE, MARSHALLER_TYPE_RET_BOOL, &_u1);
+ return _u1;
+}
+
+
+u1 CardModuleService::get_UserPersonalized(){
+ u1 _u1 = 0;
+ Invoke(0, 0xE710, MARSHALLER_TYPE_RET_BOOL, &_u1);
+ return _u1;
+}
+
+
+u1Array* CardModuleService::GetChallenge(){
+ u1Array* _u1Array = NULL;
+ Invoke(0, 0xFA3B, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+ return _u1Array;
+}
+
+
+s8 CardModuleService::get_AuthenticationDelay(){
+ s8 _s8 = 0;
+ Invoke(0, 0x5321, MARSHALLER_TYPE_RET_S8, &_s8);
+ return _s8;
+}
+
+void CardModuleService::ExternalAuthenticate(u1Array* response){
+ Invoke(1, 0x24FE, MARSHALLER_TYPE_IN_U1ARRAY, response, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::VerifyPin(u1 role,u1Array* pin){
+ Invoke(2, 0x506B, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_IN_U1ARRAY, pin, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1 CardModuleService::IsAuthenticated(u1 role){
+ u1 _u1 = 0;
+ Invoke(1, 0x9B0B, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_BOOL, &_u1);
+ return _u1;
+}
+
+
+s4Array* CardModuleService::QueryFreeSpace(){
+ s4Array* _s4Array = NULL;
+ Invoke(0, 0x00E5, MARSHALLER_TYPE_RET_S4ARRAY, &_s4Array);
+ return _s4Array;
+}
+
+
+s4Array* CardModuleService::QueryKeySizes(){
+ s4Array* _s4Array = NULL;
+ Invoke(0, 0x5EE4, MARSHALLER_TYPE_RET_S4ARRAY, &_s4Array);
+ return _s4Array;
+}
+
+
+void CardModuleService::LogOut(u1 role){
+ Invoke(1, 0xC4E4, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+
+
+void CardModuleService::SerializeData(string* filename){
+ Invoke(1, 0x9AEA, MARSHALLER_TYPE_IN_STRING, filename, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+void CardModuleService::DeSerializeData(string* filename){
+ Invoke(1, 0xA373, MARSHALLER_TYPE_IN_STRING, filename, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::get_SerialNumber(){
+ u1Array* _u1Array = NULL;
+ Invoke(0, 0xD017, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+ return _u1Array;
+}
+
+
+string* CardModuleService::get_Version(){
+ string* _string = NULL;
+ Invoke(0, 0xDEEC, MARSHALLER_TYPE_RET_STRING, &_string);
+ return _string;
+}
+
+
+void CardModuleService::SetHostVersion(u4 hostVersion){
+ Invoke(1, 0xD9B1, MARSHALLER_TYPE_IN_U4, hostVersion, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::GetChallengeEx(u1 role){
+ u1Array* _u1Array = NULL;
+ Invoke(1, 0x8F0B, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+ return _u1Array;
+}
+
+
+u1Array* CardModuleService::AuthenticateEx(u1 mode,u1 role,u1Array* pin){
+ u1Array* _u1Array = NULL;
+ Invoke(3, 0x5177, MARSHALLER_TYPE_IN_U1, mode, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_IN_U1ARRAY, pin, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+ return _u1Array;
+}
+
+
+void CardModuleService::DeauthenticateEx(u1 roles){
+ Invoke(1, 0xBD7B, MARSHALLER_TYPE_IN_U1, roles, MARSHALLER_TYPE_RET_VOID);
+}
+
+
+u1Array* CardModuleService::GetCardProperty(u1 property,u1 flags){
+ u1Array* _u1Array = NULL;
+ Invoke(2, 0x8187, MARSHALLER_TYPE_IN_U1, property, MARSHALLER_TYPE_IN_U1, flags, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+ return _u1Array;
+}
+
+
+u1Array* CardModuleService::BM_GetBioHeader(u1 role){
+ u1Array* _u1Array = NULL;
+ Invoke(1, 0x4838, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+ return _u1Array;
+}
+
+
+u1 CardModuleService::BM_BioMatch(u1 role,u1Array* verificationData){
+ u1 _u1 = 0;
+ Invoke(2, 0x2D3D, MARSHALLER_TYPE_IN_U1, role, MARSHALLER_TYPE_IN_U1ARRAY, verificationData, MARSHALLER_TYPE_RET_BOOL, &_u1);
+ return _u1;
+}
+
+u1Array* CardModuleService::BM_GetRoles(){
+ u1Array* _u1Array = NULL;
+ Invoke(0, 0xA77A, MARSHALLER_TYPE_RET_U1ARRAY, &_u1Array);
+ return _u1Array;
+}
+
+u1 CardModuleService::get_BM_DefaultRole(){
+ u1 _u1 = 0;
+ Invoke(0, 0x17FD, MARSHALLER_TYPE_RET_U1, &_u1);
+ return _u1;
+}
+
+
+void CardModuleService::set_BM_DefaultRole(u1 value){
+ Invoke(1, 0x4F1E, MARSHALLER_TYPE_IN_U1, value, MARSHALLER_TYPE_RET_VOID);
+}
+
+u1 CardModuleService::get_BM_AuthPinAllowed(){
+ u1 _u1 = 0;
+ Invoke(0, 0x9063, MARSHALLER_TYPE_RET_BOOL, &_u1);
+ return _u1;
+}
+
+string* CardModuleService::BM_GetVerifUIName(){
+ string* _string = NULL;
+ Invoke(0, 0x7BB7, MARSHALLER_TYPE_RET_STRING, &_string);
+ return _string;
+}
+
+
+string* CardModuleService::BM_GetEnrollUIName(){
+ string* _string = NULL;
+ Invoke(0, 0x0D17, MARSHALLER_TYPE_RET_STRING, &_string);
+ return _string;
+}
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cardmoduleservice.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,98 @@
+// Machine generated C++ stub file (.h) for remote object CardModuleService
+// Created on : 06/05/2008 12:22:51
+
+
+#ifndef _include_CardModuleService_h
+#define _include_CardModuleService_h
+
+#include <string>
+#include "MarshallerCfg.h"
+#include "Array.h"
+#include "PCSC.h"
+#include "Marshaller.h"
+
+#ifdef CardModuleService_EXPORTS
+#define CardModuleService_API __declspec(dllexport)
+#else
+#define CardModuleService_API
+#endif
+
+using namespace std;
+using namespace Marshaller;
+
+class CardModuleService_API CardModuleService : private SmartCardMarshaller {
+public:
+ // Constructors
+ CardModuleService(string* uri);
+ CardModuleService(string* uri, u4 index);
+ CardModuleService(u2 portNumber, string* uri);
+ CardModuleService(u2 portNumber, string* uri, u4 index);
+ CardModuleService(string* readerName, string* uri);
+ CardModuleService(string* readerName, u2 portNumber, string* uri);
+ CardModuleService(SCARDHANDLE cardHandle, string* uri);
+ CardModuleService(SCARDHANDLE cardHandle, u2 portNumber, string* uri);
+
+ // Extra method (Microsoft CardModule only)
+ void UpdateCardHandle(SCARDHANDLE cardHandle);
+
+ // Pre-defined methods
+ string* GetReader(void);
+ SCARDHANDLE GetPcscCardHandle(void);
+ void DoSCardTransact(bool flag);
+
+ // Exposed methods
+ void ChangeReferenceData(u1 mode,u1 role,u1Array* oldPin,u1Array* newPin,s4 maxTries);
+ s4 GetTriesRemaining(u1 role);
+ void CreateCAPIContainer(u1 ctrIndex,u1 keyImport,u1 keySpec,s4 keySize,u1Array* keyValue);
+ void DeleteCAPIContainer(u1 ctrIndex);
+ u1Array* GetCAPIContainer(u1 ctrIndex);
+ u1Array* PrivateKeyDecrypt(u1 ctrIndex,u1 keyType,u1Array* encryptedData);
+ void CreateFile(string* path,u1Array* acls,s4 initialSize);
+ void CreateDirectory(string* path,u1Array* acls);
+ void WriteFile(string* path,u1Array* data);
+ u1Array* ReadFile(string* path,s4 maxBytesToRead);
+ void DeleteFile(string* path);
+ void DeleteDirectory(string* path);
+ StringArray* GetFiles(string* path);
+ u1Array* GetFileProperties(string* path);
+ void ChangeAuthenticatorEx(u1 mode,u1 oldRole,u1Array* oldPin,u1 newRole,u1Array* newPin,s4 maxTries);
+ u1Array* GetContainerProperty(u1 ctrIndex,u1 property,u1 flags);
+ void SetContainerProperty(u1 ctrIndex,u1 property,u1Array* data,u1 flags);
+ void SetCardProperty(u1 property,u1Array* data,u1 flags);
+ s4 GetMemory();
+ void ForceGarbageCollector();
+ void RecursiveDelete(string* path);
+ void Select(MemoryStream* AID);
+ void Verify(u1 P1,u1 P2,u1Array* pin);
+ u1 get_AdminPersonalized();
+ u1 get_UserPersonalized();
+ u1Array* GetChallenge();
+ s8 get_AuthenticationDelay();
+ void ExternalAuthenticate(u1Array* response);
+ void VerifyPin(u1 role,u1Array* pin);
+ u1 IsAuthenticated(u1 role);
+ s4Array* QueryFreeSpace();
+ s4Array* QueryKeySizes();
+ void LogOut(u1 role);
+ void SerializeData(string* filename);
+ void DeSerializeData(string* filename);
+ u1Array* get_SerialNumber();
+ string* get_Version();
+ void SetHostVersion(u4 hostVersion);
+ u1Array* GetChallengeEx(u1 role);
+ u1Array* AuthenticateEx(u1 mode,u1 role,u1Array* pin);
+ void DeauthenticateEx(u1 roles);
+ u1Array* GetCardProperty(u1 property,u1 flags);
+
+ u1Array* BM_GetBioHeader(u1 role);
+ u1 BM_BioMatch(u1 role,u1Array* verificationData);
+ u1Array* BM_GetRoles();
+ u1 get_BM_DefaultRole();
+ void set_BM_DefaultRole(u1 value);
+ u1 get_BM_AuthPinAllowed();
+ string* BM_GetVerifUIName();
+ string* BM_GetEnrollUIName();
+};
+
+
+#endif
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,879 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "cert_utils.h"
+
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+CCertUtils::CCertUtils(void)
+{
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+CCertUtils::~CCertUtils(void)
+{
+}
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+bool CCertUtils::IsSequence(BYTE *content)
+{
+ return (content[0] == 0x30);
+}
+
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+bool CCertUtils::IsInteger(BYTE *content)
+{
+ return (content[0] == 0x02);
+}
+
+
+//------------------------------------------------------------------------------
+// int ExtractContent(ASN1 *pAsn1)
+//
+// Description : Extract contents of a Asn1 block 'pAsn1->Asn1' and place it
+// in 'pAsn1->Content'.
+//
+// Remarks : Field Asn1.pData is allocated by calling function.
+//
+// In : pAsn1->Asn1.pData
+//
+// Out : This fileds are filled (if RV_SUCCESS) :
+// - Tag
+// - Asn1.usLen
+// - Content.usLen
+// - Content.pData
+//
+// Responses : RV_SUCCESS : All is OK.
+// RV_INVALID_DATA : Asn1 block format not supported.
+//
+//------------------------------------------------------------------------------
+int CCertUtils::ExtractContent(ASN1 *pAsn1)
+
+{
+ BYTE
+ *pData;
+ int
+ NbBytes,
+ i;
+
+ pData = pAsn1->Asn1.pData;
+
+ if ((pData[0] & 0x1F) == 0x1F)
+ {
+ // High-tag-number : not supported
+ return(RV_INVALID_DATA);
+ }
+ else
+ {
+ pAsn1->Tag = pData[0];
+ }
+
+ if (pData[1] == 0x80)
+ {
+ // Constructed, indefinite-length method : not supported
+ return(RV_INVALID_DATA);
+ }
+ else if (pData[1] > 0x82)
+ {
+ // Constructed, definite-length method : too long
+ return(RV_INVALID_DATA);
+ }
+ else if (pData[1] < 0x80)
+ {
+ // Primitive, definite-length method
+
+ pAsn1->Content.usLen = pData[1];
+ pAsn1->Content.pData = &pData[2];
+
+ pAsn1->Asn1.usLen = pAsn1->Content.usLen + 2;
+ }
+ else
+ {
+ // Constructed, definite-length method
+
+ NbBytes = pData[1] & 0x7F;
+
+ pAsn1->Content.usLen = 0;
+ for (i = 0; i < NbBytes; i++)
+ {
+ pAsn1->Content.usLen = (pAsn1->Content.usLen << 8) + pData[2+i];
+ }
+ pAsn1->Content.pData = &pData[2+NbBytes];
+
+ pAsn1->Asn1.usLen = pAsn1->Content.usLen + 2 + NbBytes;
+ }
+
+ return(RV_SUCCESS);
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void CCertUtils::MemReverse(BYTE *pbOut, BYTE *pbIn, DWORD dwLen)
+{
+ DWORD i;
+
+ for (i = 0; i < dwLen; i++)
+ {
+ pbOut[i] = pbIn[dwLen - i -1];
+ }
+}
+
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void CCertUtils::ConvAscii (BYTE *pIn,
+ DWORD dwLen,
+ BYTE *pOut
+ )
+{
+#define tohex(x) (((x) >= 0xA) ? ((x) - 0xA + 'A') : ((x) + '0'))
+ register DWORD i;
+
+ for(i=0; i < dwLen; i++)
+ {
+ pOut[i*2] = tohex((pIn[i] >> 4) & 0xF);
+ pOut[i*2+1] = tohex(pIn[i] & 0xF);
+ }
+}
+
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void CCertUtils::ConvHex (BYTE *pIn,
+ DWORD dwLen,
+ BYTE *pOut
+ )
+{
+#define fromhex(x) (x-((x>='0')&&(x<='9')?'0':((x>='A')&&(x<='F')?'7':'W')))
+ register DWORD i;
+
+ for(i=0; i < dwLen; i+=2)
+ {
+ pOut[i/2] = (fromhex(pIn[i]) << 4) + fromhex(pIn[i+1]);
+ }
+}
+
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+BYTE* CCertUtils::GetDERLength(BYTE *content, DWORD *len)
+{
+ DWORD NBBytesForLength = 0;
+ unsigned short usLen = 0,i=0;
+
+
+ if(content == NULL){
+ *len = 0;
+ return NULL;
+ }
+ if(content[1] < 0x80){
+ *len = content[1];
+ return &content[2];
+ }
+
+ NBBytesForLength = content[1] & 0x7F;
+
+ usLen = 0;
+ for (i = 0; i < NBBytesForLength; i++)
+ {
+ usLen = (usLen << 8) + content[2+i];
+ }
+
+ *len = usLen;
+ return &content[2+NBBytesForLength];
+
+}
+
+
+//------------------------------------------------------------------------------
+// bool ParseCertificateValue(BYTE *pCert, DWORD dwCertLen,
+// BYTE *pSerialNumber, DWORD *pdwSerialNumberLen,
+// BYTE *pIssuer, DWORD *pdwIssuerLen,
+// BYTE *pSubject, DWORD *pdwSubjectLen
+// )
+//
+// In : pCert : Value of a valid X509 certificate.
+// dwCertLen : Length of value.
+//
+// Out : pSerialNumber : Field 'SerialNumber'
+// pusSerialNumberLen : Serial number length
+// pIssuer : Field 'Issuer'
+// pusIssuerLen : Issuer length
+// pSubject : Field 'Subject'
+// pusSubjectLen : Subject length
+//
+// Responses : true: All is OK.
+// false: Parsing fails.
+//
+//------------------------------------------------------------------------------
+bool CCertUtils::ParseCertificateValue(BYTE *pCert, DWORD /*dwCertLen*/,
+ BYTE *pSerialNumber, DWORD *pdwSerialNumberLen,
+ BYTE *pIssuer, DWORD *pdwIssuerLen,
+ BYTE *pSubject, DWORD *pdwSubjectLen
+ )
+
+{
+ ASN1
+ Value,
+ tbsCert,
+ serialNumberPart,
+ signaturePart,
+ issuerPart,
+ validityPart,
+ subjectPart;
+ bool
+ bValuesToBeReturned;
+ BYTE
+ *pCurrent;
+ int
+ rv;
+ DWORD
+ SerialNumberLen,
+ IssuerLen,
+ SubjectLen;
+
+
+ bValuesToBeReturned = (pSerialNumber != NULL)
+ && (pIssuer != NULL)
+ && (pSubject != NULL);
+
+
+ Value.Asn1.pData = pCert;
+ rv = ExtractContent(&Value);
+ if (rv != RV_SUCCESS) return false;
+
+ tbsCert.Asn1.pData = Value.Content.pData;
+ rv = ExtractContent(&tbsCert);
+ if (rv != RV_SUCCESS) return false;
+
+
+ pCurrent = tbsCert.Content.pData;
+ if (pCurrent[0] == TAG_OPTION_VERSION)
+ {
+ // We have A0 03 02 01 vv where vv is the version
+ pCurrent += 5;
+ }
+
+ serialNumberPart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&serialNumberPart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = serialNumberPart.Content.pData + serialNumberPart.Content.usLen;
+
+ signaturePart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&signaturePart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = signaturePart.Content.pData + signaturePart.Content.usLen;
+
+ issuerPart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&issuerPart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = issuerPart.Content.pData + issuerPart.Content.usLen;
+
+ validityPart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&validityPart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = validityPart.Content.pData + validityPart.Content.usLen;
+
+ subjectPart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&subjectPart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = subjectPart.Content.pData + subjectPart.Content.usLen;
+
+
+ SerialNumberLen = serialNumberPart.Content.usLen;
+ IssuerLen = issuerPart.Asn1.usLen;
+ SubjectLen = subjectPart.Asn1.usLen;
+
+ if (bValuesToBeReturned)
+ {
+ if ( (*pdwSerialNumberLen < SerialNumberLen)
+ || (*pdwIssuerLen < IssuerLen)
+ || (*pdwSubjectLen < SubjectLen)
+ )
+ {
+ return(false);
+ }
+ memcpy(pSerialNumber, serialNumberPart.Content.pData, SerialNumberLen);
+ memcpy(pIssuer, issuerPart.Asn1.pData, IssuerLen);
+ memcpy(pSubject, subjectPart.Asn1.pData, SubjectLen);
+ *pdwSerialNumberLen = SerialNumberLen;
+ *pdwIssuerLen = IssuerLen;
+ *pdwSubjectLen = SubjectLen;
+ }
+ else
+ {
+ *pdwSerialNumberLen = SerialNumberLen;
+ *pdwIssuerLen = IssuerLen;
+ *pdwSubjectLen = SubjectLen;
+ }
+
+ return(true);
+}
+
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+bool CCertUtils::MakeCertificateLabel(BYTE *pCert,
+ DWORD /*dwCertLen*/,
+ BYTE *pLabel,
+ DWORD *pdwLabelLen
+ )
+{
+ ASN1
+ AttributeTypePart,
+ AttributeValuePart,
+ AVA,
+ RDN,
+ Value,
+ tbsCert,
+ serialNumberPart,
+ signaturePart,
+ issuerPart,
+ validityPart,
+ subjectPart;
+ BLOC
+ OrganizationName,
+ CommonName;
+ bool
+ bValuesToBeReturned;
+ BYTE
+ *pCurrentRDN,
+ *pCurrent;
+ int
+ rv;
+
+ OrganizationName.pData = NULL;
+ OrganizationName.usLen = 0;
+ CommonName.pData = NULL;
+ CommonName.usLen = 0;
+
+ bValuesToBeReturned = (pLabel != NULL);
+
+ Value.Asn1.pData = pCert;
+ rv = ExtractContent(&Value);
+ if (rv != RV_SUCCESS) return false;
+
+ tbsCert.Asn1.pData = Value.Content.pData;
+ rv = ExtractContent(&tbsCert);
+ if (rv != RV_SUCCESS) return false;
+
+
+ pCurrent = tbsCert.Content.pData;
+ if (pCurrent[0] == TAG_OPTION_VERSION)
+ {
+ /* We have A0 03 02 01 vv where vv is the version */
+ pCurrent += 5;
+ }
+
+ serialNumberPart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&serialNumberPart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = serialNumberPart.Content.pData + serialNumberPart.Content.usLen;
+
+ signaturePart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&signaturePart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = signaturePart.Content.pData + signaturePart.Content.usLen;
+
+ issuerPart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&issuerPart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = issuerPart.Content.pData + issuerPart.Content.usLen;
+
+ validityPart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&validityPart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = validityPart.Content.pData + validityPart.Content.usLen;
+
+ subjectPart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&subjectPart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = subjectPart.Content.pData + subjectPart.Content.usLen;
+
+
+ // Search field 'OrganizationName' in 'Issuer'
+ pCurrent = issuerPart.Content.pData;
+
+ while (pCurrent < issuerPart.Content.pData + issuerPart.Content.usLen)
+ {
+ RDN.Asn1.pData = pCurrent;
+ rv = ExtractContent(&RDN);
+ if (rv != RV_SUCCESS) return false;
+
+ pCurrentRDN = RDN.Content.pData;
+
+ while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+ {
+ AVA.Asn1.pData = pCurrentRDN;
+ rv = ExtractContent(&AVA);
+ if (rv != RV_SUCCESS) return false;
+
+ AttributeTypePart.Asn1.pData = AVA.Content.pData;
+ rv = ExtractContent(&AttributeTypePart);
+ if (rv != RV_SUCCESS) return false;
+
+ AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+ + AttributeTypePart.Content.usLen;
+ rv = ExtractContent(&AttributeValuePart);
+ if (rv != RV_SUCCESS) return false;
+
+ // Search 'OrganisationName'
+ if (!memcmp("\x55\x04\x0A",
+ AttributeTypePart.Content.pData,
+ AttributeTypePart.Content.usLen)
+ )
+ {
+ OrganizationName = AttributeValuePart.Content;
+ }
+
+ pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+ }
+
+ pCurrent = RDN.Content.pData + RDN.Content.usLen;
+ }
+
+ // If no 'OrganizationName' is 'Issuer' search for 'CommonName' in 'Subject'
+ if (OrganizationName.usLen == 0)
+ {
+ pCurrent = issuerPart.Content.pData;
+
+ while (pCurrent < issuerPart.Content.pData + issuerPart.Content.usLen)
+ {
+ RDN.Asn1.pData = pCurrent;
+ rv = ExtractContent(&RDN);
+ if (rv != RV_SUCCESS) return false;
+
+ pCurrentRDN = RDN.Content.pData;
+
+ while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+ {
+ AVA.Asn1.pData = pCurrentRDN;
+ rv = ExtractContent(&AVA);
+ if (rv != RV_SUCCESS) return false;
+
+ AttributeTypePart.Asn1.pData = AVA.Content.pData;
+ rv = ExtractContent(&AttributeTypePart);
+ if (rv != RV_SUCCESS) return false;
+
+ AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+ + AttributeTypePart.Content.usLen;
+ rv = ExtractContent(&AttributeValuePart);
+ if (rv != RV_SUCCESS) return false;
+
+ // Search 'CommonName'
+ if (!memcmp("\x55\x04\x03",
+ AttributeTypePart.Content.pData,
+ AttributeTypePart.Content.usLen)
+ )
+ {
+ OrganizationName = AttributeValuePart.Content;
+ }
+
+ pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+ }
+
+ pCurrent = RDN.Content.pData + RDN.Content.usLen;
+ }
+ }
+
+ // Search 'CommonName' in 'Subject'
+ pCurrent = subjectPart.Content.pData;
+
+ while (pCurrent < subjectPart.Content.pData + subjectPart.Content.usLen)
+ {
+ RDN.Asn1.pData = pCurrent;
+ rv = ExtractContent(&RDN);
+ if (rv != RV_SUCCESS) return false;
+
+ pCurrentRDN = RDN.Content.pData;
+
+ while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+ {
+ AVA.Asn1.pData = pCurrentRDN;
+ rv = ExtractContent(&AVA);
+ if (rv != RV_SUCCESS) return false;
+
+ AttributeTypePart.Asn1.pData = AVA.Content.pData;
+ rv = ExtractContent(&AttributeTypePart);
+ if (rv != RV_SUCCESS) return false;
+
+ AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+ + AttributeTypePart.Content.usLen;
+ rv = ExtractContent(&AttributeValuePart);
+ if (rv != RV_SUCCESS) return false;
+
+ // Search 'CommonName'
+ if (!memcmp("\x55\x04\x03",
+ AttributeTypePart.Content.pData,
+ AttributeTypePart.Content.usLen)
+ )
+ {
+ CommonName = AttributeValuePart.Content;
+ }
+
+ pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+ }
+
+ pCurrent = RDN.Content.pData + RDN.Content.usLen;
+ }
+
+ if (bValuesToBeReturned)
+ {
+ if ( (*pdwLabelLen < (DWORD)(OrganizationName.usLen + CommonName.usLen))
+ )
+ {
+ return(false);
+ }
+
+ if (CommonName.usLen > 0)
+ {
+ memcpy(pLabel,
+ CommonName.pData,
+ CommonName.usLen
+ );
+ memcpy(&pLabel[CommonName.usLen],
+ "'s ",
+ 3
+ );
+ memcpy(&pLabel[CommonName.usLen+3],
+ OrganizationName.pData,
+ OrganizationName.usLen
+ );
+ memcpy(&pLabel[CommonName.usLen+3+OrganizationName.usLen],
+ " ID",
+ 3
+ );
+
+ *pdwLabelLen = OrganizationName.usLen + CommonName.usLen + 6;
+ }
+ else
+ {
+ memcpy(pLabel,
+ OrganizationName.pData,
+ OrganizationName.usLen
+ );
+ memcpy(&pLabel[OrganizationName.usLen],
+ " ID",
+ 3
+ );
+
+ *pdwLabelLen = OrganizationName.usLen + 3;
+ }
+ }
+ else
+ {
+ if (CommonName.usLen > 0)
+ {
+ *pdwLabelLen = OrganizationName.usLen + CommonName.usLen + 6;
+ }
+ else
+ {
+ *pdwLabelLen = OrganizationName.usLen + 3;
+ }
+ }
+
+ return(true);
+}
+
+
+// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+bool CCertUtils::MakeCertificateLabelEx(BYTE *pCert,
+ DWORD /*dwCertLen*/,
+ BYTE *pLabel,
+ DWORD *pdwLabelLen
+ )
+{
+ ASN1
+ AttributeTypePart,
+ AttributeValuePart,
+ AVA,
+ RDN,
+ Value,
+ tbsCert,
+ serialNumberPart,
+ signaturePart,
+ issuerPart,
+ validityPart,
+ subjectPart;
+ BLOC
+ OrganizationName,
+ CommonName;
+ bool
+ bValuesToBeReturned;
+ BYTE
+ *pCurrentRDN,
+ *pCurrent,
+ szSerialNumber[256] = "";
+ int
+ rv;
+
+ OrganizationName.pData = NULL;
+ OrganizationName.usLen = 0;
+ CommonName.pData = NULL;
+ CommonName.usLen = 0;
+
+ bValuesToBeReturned = (pLabel != NULL);
+
+ Value.Asn1.pData = pCert;
+ rv = ExtractContent(&Value);
+ if (rv != RV_SUCCESS) return false;
+
+ tbsCert.Asn1.pData = Value.Content.pData;
+ rv = ExtractContent(&tbsCert);
+ if (rv != RV_SUCCESS) return false;
+
+
+ pCurrent = tbsCert.Content.pData;
+ if (pCurrent[0] == TAG_OPTION_VERSION)
+ {
+ /* We have A0 03 02 01 vv where vv is the version */
+ pCurrent += 5;
+ }
+
+ serialNumberPart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&serialNumberPart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = serialNumberPart.Content.pData + serialNumberPart.Content.usLen;
+
+ memset(szSerialNumber, 0x00, sizeof(szSerialNumber));
+
+ ConvAscii(serialNumberPart.Asn1.pData, serialNumberPart.Asn1.usLen, szSerialNumber);
+
+ signaturePart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&signaturePart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = signaturePart.Content.pData + signaturePart.Content.usLen;
+
+ issuerPart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&issuerPart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = issuerPart.Content.pData + issuerPart.Content.usLen;
+
+ validityPart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&validityPart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = validityPart.Content.pData + validityPart.Content.usLen;
+
+ subjectPart.Asn1.pData = pCurrent;
+ rv = ExtractContent(&subjectPart);
+ if (rv != RV_SUCCESS) return false;
+ pCurrent = subjectPart.Content.pData + subjectPart.Content.usLen;
+
+
+ // Search field 'OrganizationName' in 'Issuer'
+ pCurrent = issuerPart.Content.pData;
+
+ while (pCurrent < issuerPart.Content.pData + issuerPart.Content.usLen)
+ {
+ RDN.Asn1.pData = pCurrent;
+ rv = ExtractContent(&RDN);
+ if (rv != RV_SUCCESS) return false;
+
+ pCurrentRDN = RDN.Content.pData;
+
+ while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+ {
+ AVA.Asn1.pData = pCurrentRDN;
+ rv = ExtractContent(&AVA);
+ if (rv != RV_SUCCESS) return false;
+
+ AttributeTypePart.Asn1.pData = AVA.Content.pData;
+ rv = ExtractContent(&AttributeTypePart);
+ if (rv != RV_SUCCESS) return false;
+
+ AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+ + AttributeTypePart.Content.usLen;
+ rv = ExtractContent(&AttributeValuePart);
+ if (rv != RV_SUCCESS) return false;
+
+ // Search 'OrganisationName'
+ if (!memcmp("\x55\x04\x0A",
+ AttributeTypePart.Content.pData,
+ AttributeTypePart.Content.usLen)
+ )
+ {
+ OrganizationName = AttributeValuePart.Content;
+ }
+
+ pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+ }
+
+ pCurrent = RDN.Content.pData + RDN.Content.usLen;
+ }
+
+ // If no 'OrganizationName' is 'Issuer' search for 'CommonName' in 'Subject'
+ if (OrganizationName.usLen == 0)
+ {
+ pCurrent = issuerPart.Content.pData;
+
+ while (pCurrent < issuerPart.Content.pData + issuerPart.Content.usLen)
+ {
+ RDN.Asn1.pData = pCurrent;
+ rv = ExtractContent(&RDN);
+ if (rv != RV_SUCCESS) return false;
+
+ pCurrentRDN = RDN.Content.pData;
+
+ while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+ {
+ AVA.Asn1.pData = pCurrentRDN;
+ rv = ExtractContent(&AVA);
+ if (rv != RV_SUCCESS) return false;
+
+ AttributeTypePart.Asn1.pData = AVA.Content.pData;
+ rv = ExtractContent(&AttributeTypePart);
+ if (rv != RV_SUCCESS) return false;
+
+ AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+ + AttributeTypePart.Content.usLen;
+ rv = ExtractContent(&AttributeValuePart);
+ if (rv != RV_SUCCESS) return false;
+
+ // Search 'CommonName'
+ if (!memcmp("\x55\x04\x03",
+ AttributeTypePart.Content.pData,
+ AttributeTypePart.Content.usLen)
+ )
+ {
+ OrganizationName = AttributeValuePart.Content;
+ }
+
+ pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+ }
+
+ pCurrent = RDN.Content.pData + RDN.Content.usLen;
+ }
+ }
+
+ // Search 'CommonName' in 'Subject'
+ pCurrent = subjectPart.Content.pData;
+
+ while (pCurrent < subjectPart.Content.pData + subjectPart.Content.usLen)
+ {
+ RDN.Asn1.pData = pCurrent;
+ rv = ExtractContent(&RDN);
+ if (rv != RV_SUCCESS) return false;
+
+ pCurrentRDN = RDN.Content.pData;
+
+ while (pCurrentRDN < RDN.Content.pData + RDN.Content.usLen)
+ {
+ AVA.Asn1.pData = pCurrentRDN;
+ rv = ExtractContent(&AVA);
+ if (rv != RV_SUCCESS) return false;
+
+ AttributeTypePart.Asn1.pData = AVA.Content.pData;
+ rv = ExtractContent(&AttributeTypePart);
+ if (rv != RV_SUCCESS) return false;
+
+ AttributeValuePart.Asn1.pData = AttributeTypePart.Content.pData
+ + AttributeTypePart.Content.usLen;
+ rv = ExtractContent(&AttributeValuePart);
+ if (rv != RV_SUCCESS) return false;
+
+ // Search 'CommonName'
+ if (!memcmp("\x55\x04\x03",
+ AttributeTypePart.Content.pData,
+ AttributeTypePart.Content.usLen)
+ )
+ {
+ CommonName = AttributeValuePart.Content;
+ }
+
+ pCurrentRDN = AVA.Content.pData + AVA.Content.usLen;
+ }
+
+ pCurrent = RDN.Content.pData + RDN.Content.usLen;
+ }
+
+ if (bValuesToBeReturned)
+ {
+ if ( (*pdwLabelLen < (DWORD)(OrganizationName.usLen + CommonName.usLen))
+ )
+ {
+ return(false);
+ }
+
+ if (CommonName.usLen > 0)
+ {
+ memcpy(pLabel,
+ CommonName.pData,
+ CommonName.usLen
+ );
+ memcpy(&pLabel[CommonName.usLen],
+ "'s ",
+ 3
+ );
+ memcpy(&pLabel[CommonName.usLen+3],
+ OrganizationName.pData,
+ OrganizationName.usLen
+ );
+ memcpy(&pLabel[CommonName.usLen+3+OrganizationName.usLen],
+ " ID - ",
+ 6
+ );
+ memcpy(&pLabel[CommonName.usLen+3+OrganizationName.usLen+6],
+ szSerialNumber,
+ strlen((char *)szSerialNumber)
+ );
+
+ *pdwLabelLen = OrganizationName.usLen + CommonName.usLen + (DWORD)strlen((char *)szSerialNumber) + 9;
+ }
+ else
+ {
+ memcpy(pLabel,
+ OrganizationName.pData,
+ OrganizationName.usLen
+ );
+ memcpy(&pLabel[OrganizationName.usLen],
+ " ID - ",
+ 6
+ );
+ memcpy(&pLabel[OrganizationName.usLen+6],
+ szSerialNumber,
+ strlen((char *)szSerialNumber)
+ );
+
+ *pdwLabelLen = OrganizationName.usLen + (DWORD)strlen((char *)szSerialNumber) + 6;
+ }
+ }
+ else
+ {
+ if (CommonName.usLen > 0)
+ {
+ *pdwLabelLen = OrganizationName.usLen + CommonName.usLen + (DWORD)strlen((char *)szSerialNumber) + 9;
+ }
+ else
+ {
+ *pdwLabelLen = OrganizationName.usLen + (DWORD)strlen((char *)szSerialNumber) + 6;
+ }
+ }
+
+ return(true);
+}
+
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/cert_utils.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,119 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#pragma once
+
+#define CERT_TYPE_UNKNOWN (0)
+#define CERT_TYPE_USER (1)
+#define CERT_TYPE_CA_ROOT (2)
+
+#define CERT_USAGE_UNKNOWN (0)
+#define CERT_USAGE_EXCHANGE (AT_KEYEXCHANGE)
+#define CERT_USAGE_SIGNATURE (AT_SIGNATURE)
+
+// Errors code
+#define RV_SUCCESS 0 // Info
+#define RV_COMPRESSION_FAILED 1 // Warning
+#define RV_MALLOC_FAILED 2 // Error
+#define RV_BAD_DICTIONARY 3 // Error
+#define RV_INVALID_DATA 4 // Error
+#define RV_BLOC_TOO_LONG 5 // Warning
+#define RV_FILE_OPEN_FAILED 6 // Error
+#define RV_BUFFER_TOO_SMALL 7 // Error
+
+#define TAG_OPTION_VERSION 0xA0
+
+/*------------------------------------------------------------------------------
+ Types definitions
+------------------------------------------------------------------------------*/
+typedef unsigned char TAG;
+typedef TAG* TAG_PTR;
+typedef BYTE* BYTE_PTR;
+
+typedef struct
+{
+ USHORT usLen;
+ BYTE_PTR pData;
+} BLOC, * BLOC_PTR;
+
+typedef struct
+{
+ BLOC Asn1;
+ BLOC Content;
+ TAG Tag;
+} ASN1, * ASN1_PTR;
+
+
+class CCertUtils
+{
+public:
+ CCertUtils(void);
+ ~CCertUtils(void);
+
+void MemReverse (BYTE *pbOut,
+ BYTE *pbIn,
+ DWORD dwLen
+ );
+
+void ConvAscii (BYTE *pIn,
+ DWORD dwLen,
+ BYTE *pOut
+ );
+
+void ConvHex (BYTE *pIn,
+ DWORD dwLen,
+ BYTE *pOut
+ );
+
+BYTE *GetDERLength (BYTE *content,
+ DWORD *len
+ );
+
+bool ParseCertificateValue (BYTE *pCert,
+ DWORD dwCertLen,
+ BYTE *pSerialNumber,
+ DWORD *pdwSerialNumberLen,
+ BYTE *pIssuer,
+ DWORD *pdwIssuerLen,
+ BYTE *pSubject,
+ DWORD *pdwSubjectLen
+ );
+
+bool MakeCertificateLabel (BYTE *pCert,
+ DWORD dwCertLen,
+ BYTE *pLabel,
+ DWORD *pdwLabelLen
+ );
+
+bool MakeCertificateLabelEx (BYTE *pCert,
+ DWORD dwCertLen,
+ BYTE *pLabel,
+ DWORD *pdwLabelLen
+ );
+
+
+private:
+int ExtractContent (ASN1 *pAsn1);
+
+bool IsSequence (BYTE *content);
+
+bool IsInteger (BYTE *content);
+};
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,258 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+//#include "dbg.h"
+#include "util.h"
+
+#include "certificateobject.h"
+
+CertificateObject::CertificateObject() : StorageObject()
+{
+ this->_trusted = CK_FALSE;
+ this->_checkSum = NULL_PTR;
+ this->_startDate = NULL_PTR;
+ this->_endDate = NULL_PTR;
+
+ this->_class = CKO_CERTIFICATE;
+
+ this->_ctrIndex = 0xFF;
+ this->_keySpec = 0xFF;
+}
+
+CertificateObject::~CertificateObject()
+{
+ if(this->_checkSum != NULL_PTR)
+ delete this->_checkSum;
+
+ if(this->_startDate != NULL_PTR)
+ delete this->_startDate;
+
+ if(this->_endDate != NULL_PTR)
+ delete this->_endDate;
+
+}
+
+bool CertificateObject::IsEqual(const StorageObject * that) const
+{
+ if(_uniqueId != 0 && that->_uniqueId != 0)
+ return (_uniqueId == that->_uniqueId);
+
+ // Only objects that have been stored under p11 directory
+ // will have a non-zero _uniqueId. For other objects, do
+ // a deep comparison based on other attributes.
+ if(_class != that->_class)
+ return false;
+
+ const CertificateObject * thatCert = static_cast<const CertificateObject*>(that);
+ return ( (_ctrIndex == thatCert->_ctrIndex) &&
+ (_keySpec == thatCert->_keySpec) &&
+ (_checkValue == thatCert->_checkValue));
+}
+
+CK_BBOOL CertificateObject::Compare(CK_ATTRIBUTE attribute)
+{
+ switch(attribute.type){
+
+ case CKA_CERTIFICATE_TYPE:
+ return (this->_certType == *(CK_ULONG*)attribute.pValue);
+
+ case CKA_CERTIFICATE_CATEGORY:
+ return (this->_certCategory == *(CK_ULONG*)attribute.pValue);
+
+ case CKA_TRUSTED:
+ return (this->_trusted == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_CHECK_VALUE:
+ return Util::CompareU1Arrays(this->_checkSum,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_START_DATE:
+ return Util::CompareU1Arrays(this->_startDate,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_END_DATE:
+ return Util::CompareU1Arrays(this->_endDate,attribute.pValue,attribute.ulValueLen);
+
+ default:
+ return StorageObject::Compare(attribute);
+ }
+}
+
+CK_RV CertificateObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+ CK_RV rv = CKR_OK;
+
+ if( 0 == attribute.ulValueLen )
+ {
+ return CKR_OK;
+ }
+
+ if(objCreation == CK_FALSE){
+ switch(attribute.type){
+ case CKA_CERTIFICATE_TYPE:
+ case CKA_CERTIFICATE_CATEGORY:
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ switch(attribute.type){
+
+ case CKA_CERTIFICATE_TYPE:
+ {
+ CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_certType = utemp;}
+ }
+ break;
+
+ case CKA_CERTIFICATE_CATEGORY:
+ {
+ CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_certCategory = utemp;}
+ }
+ break;
+
+ case CKA_TRUSTED:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_trusted = btemp; }
+ }
+ break;
+
+ case CKA_CHECK_VALUE:
+ if(this->_checkSum != NULL_PTR){
+ delete this->_checkSum;
+ }
+ this->_checkSum = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ case CKA_START_DATE:
+ {
+ u1Array* dtemp = StorageObject::ReadDateFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){
+ if(this->_startDate != NULL_PTR){
+ delete this->_startDate;
+ }
+ this->_startDate = dtemp;
+ }
+ }
+ break;
+
+ case CKA_END_DATE:
+ {
+ u1Array* dtemp = StorageObject::ReadDateFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){
+ if(this->_endDate != NULL_PTR){
+ delete this->_endDate;
+ }
+ this->_endDate = dtemp;
+ }
+ }
+ break;
+
+ default:
+ return StorageObject::SetAttribute(attribute,objCreation);
+ }
+
+ return rv;
+}
+
+CK_RV CertificateObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+ switch(attribute->type){
+
+ case CKA_CERTIFICATE_TYPE:
+ return StorageObject::PutULongInAttribute(this->_certType,attribute);
+
+ case CKA_CERTIFICATE_CATEGORY:
+ return StorageObject::PutULongInAttribute(this->_certCategory,attribute);
+
+ case CKA_TRUSTED:
+ return StorageObject::PutBBoolInAttribute(this->_trusted,attribute);
+
+ case CKA_CHECK_VALUE:
+ return StorageObject::PutU1ArrayInAttribute(this->_checkSum,attribute);
+
+ case CKA_START_DATE:
+ return StorageObject::PutU1ArrayInAttribute(this->_startDate,attribute);
+
+ case CKA_END_DATE:
+ return StorageObject::PutU1ArrayInAttribute(this->_endDate,attribute);
+
+ default:
+ return StorageObject::GetAttribute(attribute);
+ }
+}
+
+void CertificateObject::Serialize(std::vector<u1> *to)
+{
+ StorageObject::Serialize(to);
+
+ Util::PushULongInVector(to,this->_certType);
+
+ Util::PushULongInVector(to,this->_certCategory);
+
+ Util::PushBBoolInVector(to,this->_trusted);
+
+ Util::PushByteArrayInVector(to,this->_startDate);
+
+ Util::PushByteArrayInVector(to,this->_endDate);
+
+ Util::PushByteArrayInVector(to,this->_checkSum);
+
+ // serialize the extra fields
+
+ PKCS11_ASSERT(_checkValue != 0);
+ PKCS11_ASSERT(_ctrIndex < 100);
+ PKCS11_ASSERT(_keySpec == 1 || _keySpec == 2 );
+
+ Util::PushULongLongInVector(to,this->_checkValue);
+
+ Util::PushBBoolInVector(to,this->_ctrIndex);
+
+ Util::PushBBoolInVector(to,this->_keySpec);
+}
+
+void CertificateObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+ StorageObject::Deserialize(from,idx);
+
+ this->_certType = Util::ReadULongFromVector(from,idx);
+
+ this->_certCategory = Util::ReadULongFromVector(from,idx);
+
+ this->_trusted = Util::ReadBBoolFromVector(from,idx);
+
+ this->_startDate = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_endDate = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_checkSum = Util::ReadByteArrayFromVector(from,idx);
+
+ // serialize the extra fields
+
+ this->_checkValue = Util::ReadULongLongFromVector(from,idx);
+
+ this->_ctrIndex = Util::ReadBBoolFromVector(from,idx);
+
+ this->_keySpec = Util::ReadBBoolFromVector(from,idx);
+
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/certificateobject.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,57 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_certificateobject_h
+#define _include_certificateobject_h
+
+#include "storageobject.h"
+
+class CertificateObject : public StorageObject{
+
+public:
+ CK_ULONG _certType;
+ CK_BBOOL _trusted;
+ CK_ULONG _certCategory;
+ u1Array* _checkSum;
+ u1Array* _startDate;
+ u1Array* _endDate;
+
+ // extra fields
+ std::string _certName;
+ u8 _checkValue;
+ CK_BYTE _ctrIndex;
+ CK_BYTE _keySpec;
+
+public:
+ CertificateObject();
+ virtual ~CertificateObject();
+
+ virtual bool IsEqual(const StorageObject * that) const;
+ virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+ virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+ virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+ virtual void Serialize(vector<u1>* to);
+ virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/config.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/config.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/config.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,26 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_config_h
+#define _include_config_h
+
+#define CONFIG_MAX_SLOT 16
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,112 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+// Copied from ACS
+
+#include "stdafx.h"
+#include "critsect.h"
+
+#if !defined (_WIN32)
+#include <stdexcept>
+#endif
+
+CCriticalSection::CCriticalSection()
+{
+ Init();
+}
+
+/*
+CCriticalSection::CCriticalSection(bool)
+{
+ Init();
+}
+*/
+
+CCriticalSection::~CCriticalSection(void)
+{
+#if defined (_WIN32)
+
+ DeleteCriticalSection(&m_CriticalSection);
+
+#else
+
+ pthread_mutex_destroy(&m_Mutex);
+
+#endif
+}
+
+
+void CCriticalSection::Enter()
+{
+#if defined (_WIN32)
+
+ EnterCriticalSection(&m_CriticalSection);
+
+#else
+
+ if(pthread_equal(m_OwnerThread,pthread_self())) m_RefCount++;
+ else {
+ int Stat = pthread_mutex_lock(&m_Mutex);
+ if(Stat)
+ throw std::runtime_error("pthread_mutex_lock");
+
+ m_OwnerThread = pthread_self();
+ m_RefCount = 1;
+ }
+
+#endif
+}
+
+void CCriticalSection::Leave()
+{
+
+#if defined (_WIN32)
+
+ LeaveCriticalSection(&m_CriticalSection);
+
+#else
+
+ if(pthread_equal(m_OwnerThread,pthread_self())) {
+ m_RefCount--;
+ if(!m_RefCount) {
+ m_OwnerThread = 0;
+ pthread_mutex_unlock(&m_Mutex);
+ }
+ }
+
+#endif
+
+ return;
+}
+
+void CCriticalSection::Init()
+{
+#if defined (_WIN32)
+
+ InitializeCriticalSection(&m_CriticalSection);
+
+#else
+
+ pthread_mutex_init(&m_Mutex,0);
+ m_OwnerThread = 0;
+ m_RefCount = 0;
+
+#endif
+}
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/critsect.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,95 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+// Copied from ACS
+
+#ifndef _include_critsect_h
+#define _include_critsect_h
+
+#if defined(_WIN32)
+
+#include <windows.h>
+
+#else
+
+#include <pthread.h>
+
+#endif
+
+class CCriticalSection
+{
+
+public:
+
+ // A non-default constructor with a dummy parameter is added since
+ // it is needed when CCriticalSection is used as static member in
+ // template classes to instantiate properly with GCC. See for instance
+ // http://gcc.gnu.org/ml/gcc-bugs/2005-01/msg03798.html
+
+ CCriticalSection();
+ //explicit CCriticalSection(bool dummy);
+ ~CCriticalSection();
+ void Enter();
+ void Leave();
+
+private:
+ void Init();
+
+#if defined(_WIN32)
+
+ CRITICAL_SECTION m_CriticalSection;
+
+#else
+
+ pthread_mutex_t m_Mutex;
+ pthread_t m_OwnerThread;
+ unsigned long m_RefCount;
+
+#endif
+
+};
+
+// Convenience class to manage locking
+
+class CCriticalSectionLocker
+{
+public:
+ CCriticalSectionLocker(CCriticalSection & cs) : m_cs(&cs)
+ {
+ m_cs->Enter();
+ }
+ CCriticalSectionLocker(CCriticalSection * cs) : m_cs(cs)
+ {
+ if(m_cs)
+ m_cs->Enter();
+ }
+ ~CCriticalSectionLocker()
+ {
+ if(m_cs)
+ m_cs->Leave();
+ }
+
+private:
+ CCriticalSection * m_cs;
+};
+
+
+#endif // _include_critsect_h
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,175 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+#include "dataobject.h"
+
+DataObject::DataObject() : StorageObject()
+{
+ this->_class = CKO_DATA;
+ this->_appName = NULL_PTR;
+ this->_objId = NULL_PTR;
+ this->_objValue = NULL_PTR;
+}
+
+DataObject::~DataObject(){
+
+ if(this->_appName != NULL_PTR){
+ delete this->_appName;
+ }
+
+ if(this->_objId != NULL_PTR){
+ delete this->_objId;
+ }
+
+ if(this->_objValue != NULL_PTR){
+ delete this->_objValue;
+ }
+}
+
+CK_BBOOL DataObject::Compare(CK_ATTRIBUTE attribute)
+{
+ CK_BBOOL bRet = CK_FALSE;
+
+ switch(attribute.type)
+ {
+ case CKA_APPLICATION:
+ bRet = Util::CompareU1Arrays(this->_appName,attribute.pValue,attribute.ulValueLen);
+ break;
+
+ case CKA_OBJECT_ID:
+ bRet = Util::CompareU1Arrays(this->_objId,attribute.pValue,attribute.ulValueLen);
+ break;
+
+ case CKA_VALUE:
+ bRet = Util::CompareU1Arrays(this->_objValue,attribute.pValue,attribute.ulValueLen);
+ break;
+
+ default:
+ bRet = StorageObject::Compare( attribute );
+ break;
+ }
+
+ return bRet;
+}
+
+CK_RV DataObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+ if( 0 == attribute.ulValueLen )
+ {
+ return CKR_OK;
+ }
+
+ CK_RV rv = CKR_OK;
+
+ switch(attribute.type){
+
+ case CKA_APPLICATION:
+ {
+ u1Array* stemp = StorageObject::ReadStringFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){
+ if(this->_appName != NULL_PTR){
+ delete this->_appName;
+ }
+ this->_appName = stemp;
+ }
+ }
+ break;
+
+
+ case CKA_OBJECT_ID:
+ if(this->_objId != NULL_PTR){
+ delete this->_objId;
+ }
+ this->_objId = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ case CKA_VALUE:
+ if(this->_objValue != NULL_PTR){
+ delete this->_objValue;
+ }
+ this->_objValue = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ default:
+ return StorageObject::SetAttribute(attribute,objCreation);
+
+ }
+
+ return rv;
+}
+
+CK_RV DataObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+ CK_RV ulRet = CKR_OK;
+ switch(attribute->type)
+ {
+ case CKA_APPLICATION:
+ ulRet = StorageObject::PutU1ArrayInAttribute(this->_appName,attribute);
+ break;
+
+ case CKA_OBJECT_ID:
+ ulRet = StorageObject::PutU1ArrayInAttribute(this->_objId,attribute);
+ break;
+
+ case CKA_VALUE:
+ ulRet = StorageObject::PutU1ArrayInAttribute(this->_objValue,attribute);
+ break;
+
+ default:
+ ulRet = StorageObject::GetAttribute(attribute);
+ break;
+ }
+
+ return ulRet;
+}
+
+
+void DataObject::Serialize(std::vector<u1>* to)
+{
+ // first go ahead and serialize the fields in base class
+ StorageObject::Serialize(to);
+
+ // serialize label attribute
+ Util::PushByteArrayInVector(to,this->_appName);
+
+ // serialize label attribute
+ Util::PushByteArrayInVector(to,this->_objId);
+
+ // serialize label attribute
+ Util::PushByteArrayInVector(to,this->_objValue);
+}
+
+void DataObject::Deserialize(std::vector<u1> from,CK_ULONG_PTR idx)
+{
+ // first go ahead and de-serialize the fields in base class
+ StorageObject::Deserialize(from,idx);
+
+ this->_appName = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_objId = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_objValue = Util::ReadByteArrayFromVector(from,idx);
+}
+
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/dataobject.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,51 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_dataobject_h
+#define _include_dataobject_h
+
+#include "storageobject.h"
+
+class DataObject : public StorageObject
+{
+
+public:
+ u1Array* _appName;
+ u1Array* _objId;
+ u1Array* _objValue;
+
+public:
+
+ DataObject();
+ ~DataObject();
+
+ CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+ CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+ CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+ void Serialize(vector<u1>* to);
+ void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+
+};
+
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,54 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "symmalgo.h"
+#include "des.h"
+
+CDES::CDES(){
+ this->_blockSize = 8;
+}
+
+CDES::~CDES(){
+}
+
+void CDES::TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+ CK_BYTE_PTR input,CK_LONG input_offset,
+ CK_BYTE_PTR output,CK_LONG output_offset)
+{
+ // encryprtMode == ENCRYPT then we need to XOR input with iv
+ if(iv != NULL_PTR && this->_encryptMode == ENCRYPT){
+ for(CK_LONG i=0;i<8;i++){
+ input[input_offset+i] ^= iv[i];
+ }
+ }
+
+ algo_DES_DESProcess(key,&input[input_offset],&output[output_offset],(u1)encryptMode);
+
+ if(iv != NULL_PTR && this->_encryptMode == DECRYPT){
+ for(CK_LONG i=0;i<8;i++){
+ output[output_offset+i] ^= iv[i];
+ }
+ }
+
+
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/des.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,42 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_des_h
+#define _include_des_h
+
+#include "MarshallerCfg.h"
+#include "algo_des.h"
+
+class CDES : public CSymmAlgo
+{
+
+public:
+ CDES();
+ ~CDES();
+
+private:
+ void TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+ CK_BYTE_PTR input,CK_LONG input_offset,
+ CK_BYTE_PTR output,CK_LONG output_offset);
+
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,74 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "digest.h"
+
+CDigest::CDigest(){
+ this->_counter = 0;
+ this->_workingOffset = 0;
+ this->_workingLength = 0;
+}
+
+CDigest::~CDigest(){
+ free(this->_hashValue);
+ free(this->_workingBuffer);
+}
+
+void CDigest::HashCore(CK_BYTE_PTR data,CK_LONG offset,CK_LONG count)
+{
+ while (count > 0)
+ {
+ // prepare working buffer.
+ if ((_workingOffset + count) >= this->_blockLength){
+ _workingLength = this->_blockLength - _workingOffset;
+ }
+ else{
+ _workingLength = count;
+ }
+
+ memcpy(&_workingBuffer[_workingOffset],&data[offset],_workingLength);
+
+ _workingOffset += _workingLength;
+ count -= _workingLength;
+ offset += _workingLength;
+
+ if ((_workingOffset == this->_blockLength) && (count > 0)){
+
+ TransformBlock(_workingBuffer,_counter,_hashValue);
+
+ _counter += this->_blockLength;
+ _workingOffset = 0;
+ }
+ }
+}
+
+void CDigest::HashFinal(CK_BYTE_PTR hash)
+{
+ TransformFinalBlock(_workingBuffer,_workingOffset,_counter,_hashValue);
+ memcpy(hash,_hashValue,this->_hashLength);
+}
+
+CK_LONG CDigest::HashLength(void)
+{
+ return this->_hashLength;
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/digest.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,49 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_digest_h
+#define _include_digest_h
+
+class CDigest
+{
+protected:
+ CK_BYTE_PTR _workingBuffer;
+ CK_LONG _workingOffset;
+ CK_LONG _workingLength;
+ CK_LONG _counter;
+ CK_BYTE_PTR _hashValue;
+ CK_LONG _hashLength;
+ CK_LONG _blockLength;
+
+ virtual void TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result) = 0;
+ virtual void TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result) = 0;
+
+public:
+ CDigest();
+ virtual ~CDigest();
+
+ void HashCore(CK_BYTE_PTR data,CK_LONG offset,CK_LONG count);
+ void HashFinal(CK_BYTE_PTR hash);
+ CK_LONG HashLength(void);
+};
+
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,340 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "error.h"
+#include "log.h"
+
+
+#define ERROR_MEMORY "Persistent"
+
+
+/* CheckMarshallerException
+*/
+CK_RV CkError::CheckMarshallerException( Marshaller::Exception &x )
+{
+ UnauthorizedAccessException* uae = dynamic_cast< UnauthorizedAccessException* >( &x );
+ if( uae )
+ {
+ Log::log( "CheckMarshallerException", "## Error ## UnauthorizedAccessException <%s>", x.what( ) );
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ OutOfMemoryException* oome = dynamic_cast< OutOfMemoryException* >( &x );
+ if( oome )
+ {
+ Log::log( "CheckMarshallerException", "## Error ## OutOfMemoryException <%s>", x.what( ) );
+ return CKR_DEVICE_MEMORY;
+ }
+
+ if( NULL != x.what( ) )
+ {
+ if( 0 == strcmp( x.what( ), ERROR_MEMORY ) )
+ {
+ Log::log( "CheckMarshallerException", "## Error ## OutOfMemoryException %s <%s>", ERROR_MEMORY, x.what( ) );
+ return CKR_DEVICE_MEMORY;
+ }
+ }
+
+ {
+ DirectoryNotFoundException * e = dynamic_cast<DirectoryNotFoundException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## DirectoryNotFoundException <%s>", x.what( ) );
+ return CKR_TOKEN_NOT_RECOGNIZED;
+ }
+ }
+ {
+ FileNotFoundException * e = dynamic_cast<FileNotFoundException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## FileNotFoundException <%s>", x.what( ) );
+ return CKR_TOKEN_NOT_RECOGNIZED;
+ }
+ }
+ {
+ IOException * e = dynamic_cast<IOException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## IOException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ RemotingException * e = dynamic_cast<RemotingException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## RemotingException <%s>", x.what( ) );
+ return CKR_TOKEN_NOT_PRESENT;
+ }
+ }
+
+ {
+ CryptographicException * e = dynamic_cast<CryptographicException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## CryptographicException <%s>", x.what( ) );
+ return CKR_DEVICE_MEMORY;
+ }
+ }
+
+ {
+ SystemException * e = dynamic_cast<SystemException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## SystemException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ ArgumentException * e = dynamic_cast<ArgumentException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## ArgumentException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ ArgumentNullException * e = dynamic_cast<ArgumentNullException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## ArgumentNullException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ ArgumentOutOfRangeException * e = dynamic_cast<ArgumentOutOfRangeException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## ArgumentOutOfRangeException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ IndexOutOfRangeException * e = dynamic_cast<IndexOutOfRangeException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## IndexOutOfRangeException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ InvalidCastException * e = dynamic_cast<InvalidCastException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## InvalidCastException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ InvalidOperationException * e = dynamic_cast<InvalidOperationException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## InvalidOperationException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ NotImplementedException * e = dynamic_cast<NotImplementedException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## NotImplementedException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ NotSupportedException * e = dynamic_cast<NotSupportedException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## NotSupportedException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ NullReferenceException * e = dynamic_cast<NullReferenceException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## NullReferenceException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ ObjectDisposedException * e = dynamic_cast<ObjectDisposedException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## ObjectDisposedException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ ApplicationException * e = dynamic_cast<ApplicationException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## ApplicationException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ ArithmeticException * e = dynamic_cast<ArithmeticException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## ArithmeticException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ ArrayTypeMismatchException * e = dynamic_cast<ArrayTypeMismatchException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## ArrayTypeMismatchException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ BadImageFormatException * e = dynamic_cast<BadImageFormatException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## BadImageFormatException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ DirectoryNotFoundException * e = dynamic_cast<DirectoryNotFoundException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## DirectoryNotFoundException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ DivideByZeroException * e = dynamic_cast<DivideByZeroException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## DivideByZeroException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ FormatException * e = dynamic_cast<FormatException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## FormatException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ RankException * e = dynamic_cast<RankException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## RankException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ RemotingException * e = dynamic_cast<RemotingException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## RemotingException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ StackOverflowException * e = dynamic_cast<StackOverflowException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## StackOverflowException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ TypeLoadException * e = dynamic_cast<TypeLoadException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## TypeLoadException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ MemberAccessException * e = dynamic_cast<MemberAccessException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## MemberAccessException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ MissingFieldException * e = dynamic_cast<MissingFieldException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## MissingFieldException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ MissingMemberException * e = dynamic_cast<MissingMemberException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## MissingMemberException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ MissingMethodException * e = dynamic_cast<MissingMethodException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## MissingMethodException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ OverflowException * e = dynamic_cast<OverflowException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## OverflowException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ SecurityException * e = dynamic_cast<SecurityException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## SecurityException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ VerificationException * e = dynamic_cast<VerificationException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## VerificationException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+ {
+ SerializationException * e = dynamic_cast<SerializationException *>( &x );
+ if(e)
+ {
+ Log::log( "CheckMarshallerException", "## Error ## SerializationException <%s>", x.what( ) );
+ return CKR_DEVICE_ERROR;
+ }
+ }
+
+ return CKR_FUNCTION_FAILED;
+}
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/error.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,62 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_error_h
+#define _include_error_h
+
+#include <string>
+#include <stdexcept>
+#include "cardmoduleservice.h"
+#include "platconfig.h"
+#include "Except.h"
+
+class PcscError : public std::runtime_error
+{
+public:
+ PcscError() : std::runtime_error(""), _err(0) {}
+ PcscError(unsigned long err) : std::runtime_error(""), _err(err) {}
+ PcscError(const std::string & message, unsigned long err = 0) : std::runtime_error(message), _err(err) {}
+
+ unsigned long Error() const {return _err;}
+
+private:
+ unsigned long _err;
+
+};
+
+
+class CkError : public std::runtime_error
+{
+public:
+ CkError() : std::runtime_error(""), _err(0) {}
+ CkError(CK_RV err) : std::runtime_error(""), _err(err) {}
+ CkError(const std::string & message, unsigned long err = 0) : std::runtime_error(message), _err(err) {}
+
+ CK_RV Error() const {return _err;}
+
+ static CK_RV CheckMarshallerException( Marshaller::Exception & x );
+
+private:
+ unsigned long _err;
+
+};
+
+#endif // _include_error_h
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,141 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef INCLUDE_EVENTING
+
+#include "stdafx.h"
+#include "platconfig.h"
+//#include "dbg.h"
+#ifndef WIN32
+#include <pthread.h>
+#include <sys/time.h>
+#endif
+#include "event.h"
+
+CEvent::CEvent(CK_ULONG timeOut)
+{
+ #ifdef WIN32
+ m_eventHandle = CreateEvent(NULL,TRUE,FALSE,NULL);
+ #else
+ pthread_mutex_init(&m_Mutex,0);
+ pthread_cond_init(&m_Condition,0);
+ #endif
+ m_timeOut = timeOut;
+}
+
+CEvent::~CEvent(void)
+{
+ #ifdef WIN32
+ CloseHandle(m_eventHandle);
+ #else
+ pthread_mutex_destroy(&m_Mutex);
+ pthread_cond_destroy(&m_Condition);
+ #endif
+}
+
+void CEvent::Signal()
+{
+ #ifdef WIN32
+
+ if(!m_eventHandle)
+ assert(FALSE); // throw CError(CKR_FUNCTION_FAILED);
+
+ PulseEvent(m_eventHandle);
+
+ #else
+
+ if(pthread_cond_broadcast(&m_Condition) == 0)
+ {
+ //assert(FALSE);
+ }
+
+ #endif
+
+}
+
+void CEvent::Set()
+{
+ #ifdef WIN32
+
+ if(!m_eventHandle)
+ assert(FALSE); // throw CError(CKR_FUNCTION_FAILED);
+
+ SetEvent(m_eventHandle);
+
+ #else
+
+ if(pthread_cond_signal( &m_Condition ) != 0)
+ {
+ //assert(FALSE);
+ }
+
+
+ #endif
+}
+
+void CEvent::Reset()
+{
+ #ifdef WIN32
+ if(!m_eventHandle)
+ assert(FALSE); // throw CError(CKR_FUNCTION_FAILED);
+
+ ResetEvent(m_eventHandle);
+ #endif
+}
+
+void CEvent::Wait()
+{
+ #ifdef WIN32
+ if(!m_eventHandle)
+ assert(FALSE); // throw CError(CKR_FUNCTION_FAILED);
+
+ DWORD rv = WaitForSingleObject(m_eventHandle,m_timeOut);
+
+ if(rv == WAIT_TIMEOUT)
+ assert(FALSE); // throw CError(CKR_FUNCTION_FAILED);
+
+ #else
+
+ struct timeval CurrTime;
+
+ gettimeofday(&CurrTime, NULL);
+
+ timespec Abstime;
+
+ // Calculate absolute time to time out.
+
+ Abstime.tv_sec = CurrTime.tv_sec + m_timeOut/1000;
+ Abstime.tv_nsec = CurrTime.tv_usec*1000 + (m_timeOut % 1000)*1000000;
+
+ if(Abstime.tv_nsec>999999999) {
+ Abstime.tv_sec++;
+ Abstime.tv_nsec -= 1000000000;
+ }
+
+ if(pthread_cond_timedwait(&m_Condition,&m_Mutex,&Abstime) == 0)
+ {
+ //assert(FALSE);
+ }
+
+ #endif
+}
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/event.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,57 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_event_h
+#define _include_event_h
+
+#ifdef INCLUDE_EVENTING
+
+class CEvent
+{
+
+private:
+ #ifdef WIN32
+ HANDLE m_eventHandle;
+ #else
+ pthread_mutex_t m_Mutex;
+ pthread_cond_t m_Condition;
+ #endif
+ CK_ULONG m_timeOut;
+
+public:
+ CEvent(CK_ULONG timeOut);
+ ~CEvent(void);
+
+ void Signal(void);
+ void Set(void);
+ void Reset(void);
+ void Wait(void); // Throws CK_RV exception on error
+
+ #ifdef WIN32
+ HANDLE GetHandle() { return m_eventHandle;}
+ #endif
+};
+
+extern CEvent CryptokiEvent;
+
+#endif
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,258 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "keyobject.h"
+
+KeyObject::KeyObject() : StorageObject()
+{
+ this->_keyType = 0;
+ this->_id = NULL_PTR;
+ this->_startDate = NULL_PTR;
+ this->_endDate = NULL_PTR;
+ this->_allowedMechanism = NULL_PTR;
+
+ this->_local = CK_FALSE;
+ this->_mechanismType = CK_UNAVAILABLE_INFORMATION;//-1;
+}
+
+KeyObject::~KeyObject()
+{
+ if(this->_startDate != NULL_PTR){
+ delete this->_startDate;
+ }
+
+ if(this->_endDate != NULL_PTR){
+ delete this->_endDate;
+ }
+
+ if(this->_id != NULL_PTR){
+ delete this->_id;
+ }
+}
+
+CK_BBOOL KeyObject::Compare(CK_ATTRIBUTE attribute)
+{
+ switch(attribute.type)
+ {
+ case CKA_KEY_TYPE:
+ return (this->_keyType == *(CK_ULONG*)attribute.pValue);
+
+ case CKA_ID:
+ return Util::CompareU1Arrays(this->_id,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_START_DATE:
+ return Util::CompareU1Arrays(this->_startDate,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_END_DATE:
+ return Util::CompareU1Arrays(this->_endDate,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_LOCAL:
+ return (this->_local == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_DERIVE:
+ return (this->_derive == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_MECHANISM_TYPE:
+ return (this->_mechanismType == *(CK_ULONG*)attribute.pValue);
+
+ case CKA_ALLOWED_MECHANISMS:
+ return Util::CompareU4Arrays(this->_allowedMechanism,attribute.pValue,attribute.ulValueLen);
+
+ default:
+ return StorageObject::Compare(attribute);
+
+ }
+}
+
+CK_RV KeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+ if( 0 == attribute.ulValueLen )
+ {
+ return CKR_OK;
+ }
+
+ CK_RV rv = CKR_OK;
+
+ if(objCreation == CK_FALSE){
+ switch(attribute.type){
+ case CKA_KEY_TYPE:
+ case CKA_LOCAL:
+ case CKA_MECHANISM_TYPE:
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ switch(attribute.type){
+
+ case CKA_KEY_TYPE:
+ {
+ CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_keyType = utemp;}
+ }
+ break;
+
+ case CKA_ID:
+ if(this->_id != NULL_PTR){
+ delete this->_id;
+ }
+ this->_id = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ case CKA_START_DATE:
+ {
+ u1Array* dtemp = StorageObject::ReadDateFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){
+ if(this->_startDate != NULL_PTR){
+ delete this->_startDate;
+ }
+ this->_startDate = dtemp;
+ }
+ }
+ break;
+
+ case CKA_END_DATE:
+ {
+ u1Array* dtemp = StorageObject::ReadDateFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){
+ if(this->_endDate != NULL_PTR){
+ delete this->_endDate;
+ }
+ this->_endDate = dtemp;
+ }
+ }
+ break;
+
+ case CKA_LOCAL:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_local = btemp; }
+ }
+ break;
+
+ case CKA_DERIVE:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_derive = btemp; }
+ }
+ break;
+
+ case CKA_MECHANISM_TYPE:
+ {
+ CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_mechanismType = utemp;}
+ }
+ break;
+
+ case CKA_ALLOWED_MECHANISMS:
+ if(this->_allowedMechanism != NULL_PTR){
+ delete this->_allowedMechanism;
+ }
+ this->_allowedMechanism = new u4Array(attribute.ulValueLen/4);
+ memcpy((u1*)this->_allowedMechanism->GetBuffer(),(CK_BYTE_PTR)attribute.pValue,attribute.ulValueLen);
+ break;
+
+ default:
+ return StorageObject::SetAttribute(attribute,objCreation);
+
+ }
+
+ return rv;
+}
+
+CK_RV KeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+ switch(attribute->type)
+ {
+ case CKA_KEY_TYPE:
+ return StorageObject::PutULongInAttribute(this->_keyType,attribute);
+
+ case CKA_ID:
+ return StorageObject::PutU1ArrayInAttribute(this->_id,attribute);
+
+ case CKA_START_DATE:
+ return StorageObject::PutU1ArrayInAttribute(this->_startDate,attribute);
+
+ case CKA_END_DATE:
+ return StorageObject::PutU1ArrayInAttribute(this->_endDate,attribute);
+
+ case CKA_LOCAL:
+ return StorageObject::PutBBoolInAttribute(this->_local,attribute);
+
+ case CKA_DERIVE:
+ return StorageObject::PutBBoolInAttribute(this->_derive,attribute);
+
+ case CKA_MECHANISM_TYPE:
+ return StorageObject::PutULongInAttribute(this->_mechanismType,attribute);
+
+ case CKA_ALLOWED_MECHANISMS:
+ return StorageObject::PutU4ArrayInAttribute(this->_allowedMechanism,attribute);
+
+ default:
+ return StorageObject::GetAttribute(attribute);
+ }
+}
+
+void KeyObject::Serialize(std::vector<u1> *to)
+{
+ StorageObject::Serialize(to);
+
+ Util::PushULongInVector(to,this->_keyType);
+
+ Util::PushByteArrayInVector(to,this->_id);
+
+ Util::PushByteArrayInVector(to,this->_startDate);
+
+ Util::PushByteArrayInVector(to,this->_endDate);
+
+ Util::PushBBoolInVector(to,this->_local);
+
+ Util::PushBBoolInVector(to,this->_derive);
+
+ Util::PushULongInVector(to,this->_mechanismType);
+
+ Util::PushIntArrayInVector(to,this->_allowedMechanism);
+}
+
+void KeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+ StorageObject::Deserialize(from,idx);
+
+ this->_keyType = Util::ReadULongFromVector(from,idx);
+
+ this->_id = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_startDate = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_endDate = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_local = Util::ReadBBoolFromVector(from,idx);
+
+ this->_derive = Util::ReadBBoolFromVector(from,idx);
+
+ this->_mechanismType = Util::ReadULongFromVector(from,idx);
+
+ this->_allowedMechanism = Util::ReadIntArrayFromVector(from,idx);
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/keyobject.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,52 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_keyobject_h
+#define _include_keyobject_h
+
+#include "storageobject.h"
+
+class KeyObject : public StorageObject
+{
+public:
+ CK_ULONG _keyType;
+ u1Array* _id;
+ u1Array* _startDate;
+ u1Array* _endDate;
+ CK_BBOOL _derive;
+ CK_BBOOL _local;
+ CK_ULONG _mechanismType;
+ u4Array* _allowedMechanism;
+
+public:
+ KeyObject();
+ virtual ~KeyObject();
+
+ virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+ virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+ virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+ virtual void Serialize(vector<u1>* to);
+ virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,2182 @@
+
+/* ---------------- Gemalto Debug -------------- */
+
+
+#include <string.h>
+#include "log.h"
+
+
+// Define to unable if you want to activate trace into the code or at compilation time
+//#define __DEBUG_GEMALTO__
+
+#ifdef WIN32
+#include <windows.h>
+#define LOG_FILE_NAME "c:\\Gemalto.NET.PKCS11.log"
+#else
+#define LOG_FILE_NAME "/tmp/Gemalto.NET.PKCS11.log"
+#endif
+
+
+#define T_BOOL 0
+#define T_BYTES 1
+#define T_LONG 2
+#define T_KEY_TYPE 3
+#define T_CERTIFICATE_TYPE 4
+#define T_CLASS 5
+#define T_DATE 6
+#define T_KEY_GEN_MECHANISM 7
+#define T_UNKNOWN 8
+
+
+/* Log a message into the log file
+*/
+void Log::log( const char * format, ... )
+{
+#ifdef __DEBUG_GEMALTO__
+ // Try to open the file
+ FILE* pLog = fopen( LOG_FILE_NAME, "a" );
+ if( NULL == pLog )
+ {
+ // The file does not exit. Nothing to log
+ return;
+ }
+
+ // Write the message to the log file
+ va_list args;
+ va_start( args, format );
+ vfprintf( pLog, format, args );
+ va_end( args );
+ fprintf(pLog, "\n");
+
+#ifndef WIN32
+ // Write the message to stderr stream
+ va_start( args, format );
+ vfprintf( stderr, format, args );
+ va_end( args );
+ fprintf( stderr, "\n");
+#else
+ // Get the size of the buffer necessary to write the message
+ // The size must be extended to include the '\n' and the '\0' characters.
+ va_start( args, format );
+ size_t len = _vscprintf( format, args );
+ va_end( args );
+
+ // Allocate the buffer for the message
+ char *buffer = new char[ len + 2 ];
+ memset( buffer, '\0', len + 2 );
+
+ // Write the message into the buffer.
+ va_start( args, format );
+ vsprintf_s( buffer, len + 1, format, args );
+ va_end( args );
+ buffer[ len ] = '\n';
+
+ // Write the message to the console
+ OutputDebugString( buffer );
+
+ // Release the buffer
+ delete[] buffer;
+#endif
+
+ va_end( args );
+
+ // Close the file
+ fclose( pLog );
+#endif
+}
+
+/*
+
+#ifdef __DEBUG_GEMALTO__
+void Log::log( const char * format, ... )
+{
+ // Try to open the file
+ FILE* pLog = fopen( LOG_FILE_NAME, "a" );
+ if( NULL == pLog )
+ {
+ // The file does not exit. Nothing to log
+ return;
+ }
+
+ // Get the size of the buffer necessary to write the message
+ // The size must be extended to include the '\n' and the '\0' characters.
+ va_list args;
+ va_start( args, format );
+#ifdef WIN32
+ size_t len = _vscprintf( format, args );
+#else
+ char tmp[1];
+ int len = vsnprintf( tmp, sizeof(tmp), format, args );
+#endif
+ va_end( args );
+
+ // Allocate the buffer for the message
+ char *buffer = new char[ len + 2 ];
+ memset( buffer, '\0', len + 2 );
+
+ // Write the message into the buffer.
+ va_start( args, format );
+#ifdef WIN32
+ vsprintf_s( buffer, len + 1, format, args );
+#else
+ vsprintf( buffer, format, args );
+#endif
+ va_end( args );
+ buffer[ len ] = '\n';
+
+ // Write the message to the console
+#ifdef WIN32
+ OutputDebugString( buffer );
+#else
+ printf( buffer );
+#endif
+
+ // Write the message to the log file
+ fputs( buffer, pLog );
+ fflush( pLog );
+
+ // Close the file
+ fclose( pLog );
+
+ // Release the buffer
+ delete[] buffer;
+}
+#else
+void Log::log( const char*, ... )
+{
+}
+#endif
+*/
+
+
+
+/*
+*/
+void Log::begin( const char* a_pMethod )
+{
+#ifdef __DEBUG_GEMALTO__
+ log( "%s - <BEGIN>", a_pMethod );
+#else
+ (void)a_pMethod;
+#endif
+}
+
+
+/*
+*/
+void Log::end( const char* a_pMethod )
+{
+#ifdef __DEBUG_GEMALTO__
+ log( "%s - <END>", a_pMethod );
+#endif
+}
+
+
+/*
+*/
+void Log::in( const char* a_pMethod )
+{
+#ifdef __DEBUG_GEMALTO__
+ log( "%s - [IN]", a_pMethod );
+#endif
+}
+
+
+/*
+*/
+void Log::out( const char* a_pMethod )
+{
+#ifdef __DEBUG_GEMALTO__
+ log( "%s - [OUT]", a_pMethod );
+#endif
+}
+
+
+/*
+*/
+void Log::error( const char* a_pMethod, const char* a_pError )
+{
+#ifdef __DEBUG_GEMALTO__
+ log( "%s - ## Error ## %s", a_pMethod, a_pError );
+#endif
+}
+
+
+
+void Log::logCK_UTF8CHAR_PTR( const char* a_pName, const unsigned char* a_pBuffer, const std::size_t& a_Size )
+{
+#ifdef __DEBUG_GEMALTO__
+ std::string s = "";
+ if( NULL_PTR != a_pBuffer )
+ {
+ toString( a_pBuffer, a_Size, s );
+ }
+ log( "%s - <%#02x> - size <%ld> - buffer <%s>", a_pName, a_pBuffer, a_Size, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_MECHANISM_INFO_PTR( const char* a_pMethod, CK_MECHANISM_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR != pInfo )
+ {
+ std::string flags = "";
+ CK_FLAGS f = pInfo->flags;
+ mechanismFlagsToString( f, flags );
+
+ log( "%s - CK_MECHANISM_INFO - ulMinKeySize <%#02x> - ulMaxKeySize <%#02x> - flags <%s>", a_pMethod, pInfo->ulMinKeySize, pInfo->ulMaxKeySize, flags.c_str( ) );
+ }
+ else
+ {
+ log( "%s - CK_MECHANISM_INFO - NULL_PTR", a_pMethod );
+ }
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_INFO( const char* a_pMethod, const CK_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR != pInfo )
+ {
+ std::string s = "";
+ CK_INFOToString( pInfo, s );
+ log( "%s - CK_INFO <%s>", a_pMethod, s.c_str( ) );
+ }
+ else
+ {
+ log( "%s - CK_INFO <NULL_PTR>", a_pMethod );
+ }
+#endif
+}
+
+
+void Log::logCK_RV( const char* a_pMethod, const CK_RV& rv )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( CKR_OK == rv )
+ {
+ log( "%s - [RV] <0x00> (CKR_OK)", a_pMethod );
+ }
+ else
+ {
+ std::string s = "";
+ CK_RVToString( rv, s );
+ log( "%s - [RV] <%#02x> (%s)", a_pMethod, rv, s.c_str( ) );
+ }
+#endif
+}
+
+
+void Log::logCK_C_INITIALIZE_ARGS_PTR( const char* a_pMethod, CK_C_INITIALIZE_ARGS_PTR a_pArgs )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR != a_pArgs )
+ {
+ //log( a_pMethod, "pInitArgs->CreateMutex <%#02x>", a_pArgs.CreateMutex );
+ log( "%s - CK_C_INITIALIZE_ARGS - DestroyMutex <%#02x> - LockMutex <%#02x> - UnlockMutex <%#02x> - flags <%#02x> - pReserved <%#02x>",
+ a_pMethod, a_pArgs->DestroyMutex, a_pArgs->LockMutex, a_pArgs->UnlockMutex, a_pArgs->flags, a_pArgs->pReserved );
+ }
+ else
+ {
+ log( "%s - CK_C_INITIALIZE_ARGS - CreateMutex <NULL_PTR> - DestroyMutex <NULL_PTR> - LockMutex <NULL_PTR> - UnlockMutex <NULL_PTR> - flags <NULL_PTR> - pReserved <NULL_PTR>", a_pMethod );
+ }
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_SLOT_ID_PTR( const char* a_pMethod, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR == pSlotList )
+ {
+ log( "%s - CK_SLOT_ID_PTR - pulCount <%#02x> (%ld) - pSlotList <NULL_PTR>", a_pMethod, pulCount, ( NULL_PTR != pulCount ) ? *pulCount : 0 );
+ }
+ else
+ {
+ std::string sList = "";
+ if( NULL_PTR != pulCount )
+ {
+ for( size_t i = 0 ; i < (size_t)*pulCount ; i++ )
+ {
+ std::string s = "";
+ toString( (unsigned long) pSlotList[ i ], s );
+ sList += s;
+ if( i != (size_t)( *pulCount - 1 ) )
+ {
+ sList += ", " ;
+ }
+ }
+ }
+ log( "%s - CK_SLOT_ID_PTR - pulCount <%#02x> (%ld) - pSlotList <%#02x> (%s)", a_pMethod, pulCount, ( NULL_PTR != pulCount ) ? *pulCount : 0, pSlotList, sList.c_str( ) );
+ }
+#endif
+}
+
+
+void Log::logCK_SLOT_INFO_PTR( const char* a_pMethod, CK_SLOT_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR != pInfo )
+ {
+ std::string slotDescription = "";
+ toString( pInfo->slotDescription, 64, slotDescription );
+
+ std::string manufacturerID = "";
+ toString( pInfo->manufacturerID, 32, manufacturerID );
+
+ std::string flags = "";
+ CK_FLAGS f = pInfo->flags;
+ slotFlagsToString( f, flags );
+
+ std::string hardwareVersion = "";
+ CK_VERSIONToString( &(pInfo->hardwareVersion), hardwareVersion );
+
+ std::string firmwareVersion = "";
+ CK_VERSIONToString( &(pInfo->firmwareVersion), firmwareVersion );
+
+ log( "%s - CK_SLOT_INFO_PTR - slotDescription <%s> - manufacturerID <%s> - flags <%s> - hardwareVersion <%s> - firmwareVersion <%s>",
+ a_pMethod, slotDescription.c_str( ), manufacturerID.c_str( ), flags.c_str( ), hardwareVersion.c_str( ), firmwareVersion.c_str( ) );
+ }
+ else
+ {
+ log( "%s - CK_SLOT_INFO_PTR - NULL_PTR", a_pMethod );
+ }
+#endif
+}
+
+
+void Log::logCK_TOKEN_INFO_PTR( const char* a_pMethod, CK_TOKEN_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR != pInfo )
+ {
+ std::string label = "";
+ toString( pInfo->label, 32, label );
+
+ std::string manufacturerID = "";
+ toString( pInfo->manufacturerID, 32, manufacturerID );
+
+ std::string model = "";
+ toString( pInfo->model, 16, model );
+
+ std::string serialNumber = "";
+ toString( pInfo->serialNumber, 16, serialNumber );
+
+ std::string hardwareVersion = "";
+ CK_VERSIONToString( &(pInfo->hardwareVersion), hardwareVersion );
+
+ std::string firmwareVersion = "";
+ CK_VERSIONToString( &(pInfo->firmwareVersion), firmwareVersion );
+
+ std::string utcTime = "";
+ toString( pInfo->utcTime, 16, utcTime );
+
+ log( "%s - CK_TOKEN_INFO_PTR - <%#02x> - label <%s> - manufacturerID <%s> - model <%s> - serialNumber <%s> - flags <%#02x> - ulMaxSessionCount <%#02x> - ulSessionCount <%#02x> - \
+ ulMaxRwSessionCount <%#02x> - ulRwSessionCount <%#02x> - ulMaxPinLen <%#02x> - ulMinPinLen <%#02x> - ulTotalPublicMemory <%#02x> - \
+ ulFreePublicMemory <%#02x> - ulTotalPrivateMemory <%#02x> - ulFreePrivateMemory <%#02x> - hardwareVersion <%s> - \
+ firmwareVersion <%s> - utcTime <%s>",
+ a_pMethod,
+ pInfo,
+ label.c_str( ),
+ manufacturerID.c_str( ),
+ model.c_str( ),
+ serialNumber.c_str( ),
+ pInfo->flags,
+ pInfo->ulMaxSessionCount,
+ pInfo->ulSessionCount,
+ pInfo->ulMaxRwSessionCount,
+ pInfo->ulRwSessionCount,
+ pInfo->ulMaxPinLen,
+ pInfo->ulMinPinLen,
+ pInfo->ulTotalPublicMemory,
+ pInfo->ulFreePublicMemory,
+ pInfo->ulTotalPrivateMemory,
+ pInfo->ulFreePrivateMemory,
+ hardwareVersion.c_str( ),
+ firmwareVersion.c_str( ),
+ utcTime.c_str( ) );
+ }
+ else
+ {
+ log( "%s - CK_TOKEN_INFO_PTR - <NULL_PTR>", a_pMethod );
+ }
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_MECHANISM_TYPE( const char* a_pMethod, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount )
+{
+#ifdef __DEBUG_GEMALTO__
+ std::string s = "";
+ if( ( NULL_PTR != pMechanismList ) && ( NULL_PTR != pulCount ) )
+ {
+ CK_MECHANISM_TYPEToString( pMechanismList, *pulCount, s );
+ }
+ log( "%s - CK_MECHANISM_TYPE_PTR - pulCount <%#02x> (%ld) - pMechanismList <%#02x> (%s)", a_pMethod, pulCount, ( ( NULL_PTR != pulCount ) ? *pulCount : 0 ), pMechanismList, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_MECHANISM_TYPE( const char* a_pMethod, CK_MECHANISM_TYPE & ulMechanism )
+{
+#ifdef __DEBUG_GEMALTO__
+ std::string s = "";
+ CK_MECHANISM_TYPEToString( ulMechanism, s );
+ log( "%s - CK_MECHANISM_TYPE <%s>", a_pMethod, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logSessionFlags( const char* a_pMethod, CK_FLAGS & flags )
+{
+#ifdef __DEBUG_GEMALTO__
+ std::string s = "";
+ sessionFlagsToString( flags, s );
+ log( "%s - CK_FLAGS <%s>", a_pMethod, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_SESSION_INFO_PTR( const char* a_pMethod, CK_SESSION_INFO_PTR pInfo )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR != pInfo )
+ {
+ std::string s = "";
+ CK_SESSION_INFOToString( pInfo, s );
+ log( "%s - CK_SESSION_INFO <%#02x> (%s)", a_pMethod, pInfo, s.c_str( ) );
+ }
+ else
+ {
+ log( "%s - CK_SESSION_INFO <NULL_PTR>", a_pMethod );
+ }
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_USER_TYPE( const char* a_pMethod, CK_USER_TYPE &userType )
+{
+#ifdef __DEBUG_GEMALTO__
+ std::string s = "";
+ CK_USER_TYPEToString( userType, s );
+ log( "%s - CK_USER_TYPE <%s>", a_pMethod, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_MECHANISM_PTR( const char* a_pMethod, CK_MECHANISM_PTR pMechanism )
+{
+#ifdef __DEBUG_GEMALTO__
+ std::string s = "";
+ CK_MECHANISMToString( pMechanism, s );
+ log( "%s - CK_MECHANISM_PTR <%s>", a_pMethod, s.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::logCK_ATTRIBUTE_PTR( const char* a_pMethod, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG& ulCount )
+{
+#ifdef __DEBUG_GEMALTO__
+ log( "%s - pTemplate <%#02x> - ulCount <%ld>", a_pMethod, pTemplate, ulCount );
+ if( NULL_PTR != pTemplate )
+ {
+ for( size_t i = 0; i < (size_t)ulCount; i++ )
+ {
+ CK_ATTRIBUTE a = pTemplate[ i ];
+ std::string attribute = "";
+ CK_ATTRIBUTEToString( &a, attribute );
+
+ log( "%s - Attribute #%d - %s", a_pMethod, i, attribute.c_str( ) );
+ }
+ }
+#endif
+}
+
+
+/*
+*/
+void Log::CK_MECHANISMToString( CK_MECHANISM_PTR m, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR == m )
+ {
+ return;
+ }
+
+ std::string mechanismType = "";
+ CK_MECHANISM_TYPE t = m->mechanism;
+ CK_MECHANISM_TYPEToString( t, mechanismType );
+
+ std::string mechanismParam = "";
+ toString( (const unsigned char*)m->pParameter, m->ulParameterLen, mechanismParam );
+
+ toString( result,
+ "Type <%s> - Parameter <%s> - ParameterLen <%#02x>",
+ mechanismType.c_str( ),
+ mechanismParam.c_str( ),
+ m->ulParameterLen );
+#endif
+}
+
+
+void Log::CK_ATTRIBUTEToString( const CK_ATTRIBUTE_PTR a, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR == a )
+ {
+ return;
+ }
+
+ std::string t = "";
+ int type = T_UNKNOWN;
+ CK_ATTRIBUTE_TYPEToString( a->type, t, type );
+
+ if( ( (CK_ULONG)(-1) ) == a->ulValueLen )
+ {
+ toString( result, "Type <%s> - Length <-1> - Value <UNKNOWN>", t.c_str( ) );
+ return;
+ }
+
+ std::string v = "";
+ if( NULL_PTR == a->pValue )
+ {
+ v = "null";
+ }
+ else
+ {
+ switch( type )
+ {
+ case T_BOOL:
+ toString( ((bool*)a->pValue)[0], v );
+ break;
+
+ case T_BYTES:
+ toString( (CK_BYTE_PTR) a->pValue, a->ulValueLen, v );
+ break;
+
+ case T_LONG:
+ toString( ((CK_ULONG*)a->pValue)[0], v );
+ break;
+
+ case T_KEY_TYPE:
+ CK_KEY_TYPEToString( ((CK_KEY_TYPE *)a->pValue)[0], v );
+ break;
+
+ case T_CERTIFICATE_TYPE:
+ CK_CERTIFICATE_TYPEToString( ((CK_CERTIFICATE_TYPE *)a->pValue)[0], v );
+ break;
+
+ case T_CLASS:
+ CK_OBJECT_CLASSToString( ((CK_OBJECT_CLASS *)a->pValue)[0], v );
+ break;
+
+ case T_DATE:
+ CK_DATEToString( (CK_DATE*) a->pValue, v );
+ break;
+
+ case T_KEY_GEN_MECHANISM:
+ CK_MECHANISM_TYPEToString( ((CK_MECHANISM_TYPE *)a->pValue)[0], v );
+ break;
+
+ default:
+ v = "UNPREDICTABLE VALUE";
+ }
+ }
+
+ toString( result, "Type <%s> - Length <%#02x> - Value <%s>", t.c_str( ), a->ulValueLen, v.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::CK_ATTRIBUTE_TYPEToString( const CK_ATTRIBUTE_TYPE& a, std::string &t, int& type )
+{
+#ifdef __DEBUG_GEMALTO__
+ switch( a )
+ {
+ case CKA_CLASS:
+ t = "CKA_CLASS";
+ type = T_CLASS;
+ break;
+
+ case CKA_TOKEN:
+ t = "CKA_TOKEN";
+ type = T_BOOL;
+ break;
+
+ case CKA_PRIVATE:
+ t = "CKA_PRIVATE";
+ type = T_BOOL;
+ break;
+
+ case CKA_LABEL:
+ t = "CKA_LABEL";
+ type = T_BYTES;
+ break;
+
+ case CKA_APPLICATION:
+ t = "CKA_APPLICATION";
+ type = T_BYTES;
+ break;
+
+ case CKA_VALUE:
+ t = "CKA_VALUE";
+ type = T_BYTES;
+ break;
+
+ case CKA_CERTIFICATE_TYPE:
+ t = "CKA_CERTIFICATE_TYPE";
+ type = T_CERTIFICATE_TYPE;
+ break;
+
+ case CKA_ISSUER:
+ t = "CKA_ISSUER";
+ type = T_BYTES;
+ break;
+
+ case CKA_SERIAL_NUMBER:
+ t = "CKA_SERIAL_NUMBER";
+ type = T_BYTES;
+ break;
+
+ case CKA_KEY_TYPE:
+ t = "CKA_KEY_TYPE";
+ type = T_KEY_TYPE;
+ break;
+
+ case CKA_SUBJECT:
+ t = "CKA_SUBJECT";
+ type = T_BYTES;
+ break;
+
+ case CKA_ID:
+ t = "CKA_ID";
+ type = T_BYTES;
+ break;
+
+ case CKA_SENSITIVE:
+ t = "CKA_SENSITIVE";
+ type = T_BOOL;
+ break;
+
+ case CKA_ENCRYPT:
+ t = "CKA_ENCRYPT";
+ type = T_BOOL;
+ break;
+
+ case CKA_DECRYPT:
+ t = "CKA_DECRYPT";
+ type = T_BOOL;
+ break;
+
+ case CKA_WRAP:
+ t = "CKA_WRAP";
+ type = T_BOOL;
+ break;
+
+ case CKA_UNWRAP:
+ t = "CKA_UNWRAP";
+ type = T_BOOL;
+ break;
+
+ case CKA_SIGN:
+ t = "CKA_SIGN";
+ type = T_BOOL;
+ break;
+
+ case CKA_SIGN_RECOVER:
+ t = "CKA_SIGN_RECOVER";
+ type = T_BOOL;
+ break;
+
+ case CKA_VERIFY:
+ t = "CKA_VERIFY";
+ type = T_BOOL;
+ break;
+
+ case CKA_VERIFY_RECOVER:
+ t = "CKA_VERIFY_RECOVER";
+ type = T_BOOL;
+ break;
+
+ case CKA_DERIVE:
+ t = "CKA_DERIVE";
+ type = T_BOOL;
+ break;
+
+ case CKA_START_DATE:
+ t = "CKA_START_DATE";
+ type = T_DATE;
+ break;
+
+ case CKA_END_DATE:
+ t = "CKA_END_DATE";
+ type = T_DATE;
+ break;
+
+ case CKA_MODULUS:
+ t = "CKA_MODULUS";
+ type = T_BYTES;
+ break;
+
+ case CKA_MODULUS_BITS:
+ t = "CKA_MODULUS_BITS";
+ type = T_LONG;
+ break;
+
+ case CKA_PUBLIC_EXPONENT:
+ t = "CKA_PUBLIC_EXPONENT";
+ type = T_BYTES;
+ break;
+
+ case CKA_PRIVATE_EXPONENT:
+ t = "CKA_PRIVATE_EXPONENT";
+ type = T_BYTES;
+ break;
+
+ case CKA_PRIME_1:
+ t = "CKA_PRIME_1";
+ type = T_BYTES;
+ break;
+
+ case CKA_PRIME_2:
+ t = "CKA_PRIME_2";
+ type = T_BYTES;
+ break;
+
+ case CKA_EXPONENT_1:
+ t = "CKA_EXPONENT_1";
+ type = T_BYTES;
+ break;
+
+ case CKA_EXPONENT_2:
+ t = "CKA_EXPONENT_2";
+ type = T_BYTES;
+ break;
+
+ case CKA_COEFFICIENT:
+ t = "CKA_COEFFICIENT";
+ type = T_BYTES;
+ break;
+
+ case CKA_PRIME:
+ t = "CKA_PRIME";
+ type = T_BYTES;
+ break;
+
+ case CKA_SUBPRIME:
+ t = "CKA_SUBPRIME";
+ type = T_BYTES;
+ break;
+
+ case CKA_BASE:
+ t = "CKA_BASE";
+ type = T_BYTES;
+ break;
+
+ case CKA_VALUE_BITS:
+ t = "CKA_VALUE_BITS";
+ type = T_BYTES;
+ break;
+
+ case CKA_VALUE_LEN:
+ t = "CKA_VALUE_LEN";
+ type = T_LONG;
+ break;
+
+ case CKA_EXTRACTABLE:
+ t = "CKA_EXTRACTABLE";
+ type = T_BOOL;
+ break;
+
+ case CKA_LOCAL:
+ t = "CKA_LOCAL";
+ type = T_BOOL;
+ break;
+
+ case CKA_NEVER_EXTRACTABLE:
+ t = "CKA_NEVER_EXTRACTABLE";
+ type = T_BOOL;
+ break;
+
+ case CKA_ALWAYS_SENSITIVE:
+ t = "CKA_ALWAYS_SENSITIVE";
+ type = T_BOOL;
+ break;
+
+ case CKA_MODIFIABLE:
+ t = "CKA_MODIFIABLE";
+ type = T_BOOL;
+ break;
+
+ case CKA_ECDSA_PARAMS:
+ t = "CKA_ECDSA_PARAMS";
+ type = T_BYTES;
+ break;
+
+ case CKA_EC_POINT:
+ t = "CKA_EC_POINT";
+ type = T_BYTES;
+ break;
+
+ case CKA_VENDOR_DEFINED:
+ t = "CKA_VENDOR_DEFINED";
+ type = T_BYTES;
+ break;
+
+ //case CKA_KEY_GEN_MECHANISM:
+ // t = "CKA_KEY_GEN_MECHANISM";
+ // type = T_KEY_GEN_MECHANISM;
+ // break;
+
+ default:
+ toString( t, "UNKNOWN TYPE <%#02x>", a );
+ type = T_UNKNOWN;
+ }
+#endif
+}
+
+
+/*
+*/
+void Log::CK_DATEToString( const CK_DATE* t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR == t )
+ {
+ return;
+ }
+
+ std::string year = "";
+ toString( t->year, 4, year );
+
+ std::string month = "";
+ toString( t->month, 2, month );
+
+ std::string day = "";
+ toString( t->day, 2, day );
+
+ result = "Year <" + year + "> - Month <" + month + "> - Day <" + day + ">";
+#endif
+}
+
+
+/*
+*/
+void Log::CK_OBJECT_CLASSToString( const CK_OBJECT_CLASS& t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ switch( t )
+ {
+ case CKO_DATA:
+ result = "CKO_DATA";
+ break;
+
+ case CKO_CERTIFICATE:
+ result = "CKO_CERTIFICATE";
+ break;
+
+ case CKO_PUBLIC_KEY:
+ result = "CKO_PUBLIC_KEY";
+ break;
+
+ case CKO_PRIVATE_KEY:
+ result = "CKO_PRIVATE_KEY";
+ break;
+
+ case CKO_SECRET_KEY:
+ result = "CKO_SECRET_KEY";
+ break;
+
+ case CKO_VENDOR_DEFINED:
+ result = "CKO_VENDOR_DEFINED";
+ break;
+
+ default:
+ toString( result, "UNKNOWN OBJECT CLASS <%#02x>", t );
+ }
+#endif
+}
+
+
+/*
+*/
+void Log::CK_KEY_TYPEToString( const CK_KEY_TYPE& t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ switch( t )
+ {
+ case CKK_RSA:
+ result = "CKK_RSA";
+ break;
+
+ case CKK_DSA:
+ result = "CKK_DSA";
+ break;
+
+ case CKK_ECDSA:
+ result = "CKK_ECDSA";
+ break;
+
+ case CKK_DH:
+ result = "CKK_DH";
+ break;
+
+ case CKK_KEA:
+ result = "CKK_KEA";
+ break;
+
+ case CKK_GENERIC_SECRET:
+ result = "CKK_GENERIC_SECRET";
+ break;
+
+ case CKK_RC2:
+ result = "CKK_RC2";
+ break;
+
+ case CKK_RC4:
+ result = "CKK_RC4";
+ break;
+
+ case CKK_DES:
+ result = "CKK_DES";
+ break;
+
+ case CKK_DES2:
+ result = "CKK_DES2";
+ break;
+
+ case CKK_DES3:
+ result = "CKK_DES3";
+ break;
+
+ case CKK_CAST:
+ result = "CKK_CAST";
+ break;
+
+ case CKK_CAST3:
+ result = "CKK_CAST3";
+ break;
+
+ case CKK_CAST5:
+ result = "CKK_CAST5/128";
+ break;
+
+ case CKK_RC5:
+ result = "CKK_RC5";
+ break;
+
+ case CKK_IDEA:
+ result = "CKK_IDEA";
+ break;
+
+ case CKK_SKIPJACK:
+ result = "CKK_SKIPJACK";
+ break;
+
+ case CKK_BATON:
+ result = "CKK_BATON";
+ break;
+
+ case CKK_JUNIPER:
+ result = "CKK_JUNIPER";
+ break;
+
+ case CKK_CDMF:
+ result = "CKK_CDMF";
+ break;
+
+ case CKK_VENDOR_DEFINED:
+ result = "CKK_VENDOR_DEFINED";
+ break;
+
+ default:
+ toString( result, "UNKNOWN KEY TYPE <%#02x>", t );
+ }
+#endif
+}
+
+
+/*
+*/
+void Log::CK_CERTIFICATE_TYPEToString( const CK_CERTIFICATE_TYPE &t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ switch( t )
+ {
+ case CKC_X_509:
+ result = "CKC_X_509";
+ break;
+
+ case CKC_VENDOR_DEFINED:
+ result = "CKC_VENDOR_DEFINED";
+ break;
+
+ default:
+ toString( result, "UNKNOWN CERTIFICATE TYPE <%#02x>", t );
+ }
+#endif
+}
+
+
+/*
+*/
+void Log::CK_INFOToString( CK_INFO_PTR pInfo, std::string& result )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR == pInfo )
+ {
+ return;
+ }
+
+ std::string cryptokiVersion = "";
+ CK_VERSIONToString( &(pInfo->cryptokiVersion), cryptokiVersion );
+
+ std::string manufacturerID = "";
+ toString( pInfo->manufacturerID, 32, manufacturerID );
+
+ std::string flags = "";
+ CK_FLAGS f = pInfo->flags;
+ toString( f, flags );
+
+ std::string libraryDescription = "";
+ toString( pInfo->libraryDescription, 32, libraryDescription );
+
+ std::string libraryVersion = "";
+ CK_VERSIONToString( &(pInfo->libraryVersion), libraryVersion );
+
+ result = "cryptokiVersion <" + cryptokiVersion
+ + "> - manufacturerID <" + manufacturerID
+ + "> - flags <" + flags
+ + "> - libraryDescription <" + libraryDescription
+ + "> - libraryVersion <" + libraryVersion
+ + ">";
+#endif
+}
+
+
+/*
+*/
+void Log::CK_RVToString( const CK_RV& rv, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ switch( rv )
+ {
+ case CKR_OK:
+ result = "CKR_OK";
+ break;
+ case CKR_CANCEL:
+ result = "CKR_CANCEL";
+ break;
+ case CKR_HOST_MEMORY:
+ result = "CKR_HOST_MEMORY";
+ break;
+ case CKR_SLOT_ID_INVALID:
+ result = "CKR_SLOT_ID_INVALID";
+ break;
+ case CKR_GENERAL_ERROR:
+ result = "CKR_GENERAL_ERROR";
+ break;
+ case CKR_FUNCTION_FAILED:
+ result = "CKR_FUNCTION_FAILED";
+ break;
+ case CKR_ARGUMENTS_BAD:
+ result = "CKR_ARGUMENTS_BAD";
+ break;
+ case CKR_NO_EVENT:
+ result = "CKR_NO_EVENT";
+ break;
+ case CKR_NEED_TO_CREATE_THREADS:
+ result = "CKR_NEED_TO_CREATE_THREADS";
+ break;
+ case CKR_CANT_LOCK:
+ result = "CKR_CANT_LOCK";
+ break;
+ case CKR_ATTRIBUTE_READ_ONLY:
+ result = "CKR_ATTRIBUTE_READ_ONLY";
+ break;
+ case CKR_ATTRIBUTE_SENSITIVE:
+ result = "CKR_ATTRIBUTE_SENSITIVE";
+ break;
+ case CKR_ATTRIBUTE_TYPE_INVALID:
+ result = "CKR_ATTRIBUTE_TYPE_INVALID";
+ break;
+ case CKR_ATTRIBUTE_VALUE_INVALID:
+ result = "CKR_ATTRIBUTE_VALUE_INVALID";
+ break;
+ case CKR_DATA_INVALID:
+ result = "CKR_DATA_INVALID";
+ break;
+ case CKR_DATA_LEN_RANGE:
+ result = "CKR_DATA_LEN_RANGE";
+ break;
+ case CKR_DEVICE_ERROR:
+ result = "CKR_DEVICE_ERROR";
+ break;
+ case CKR_DEVICE_MEMORY:
+ result = "CKR_DEVICE_MEMORY";
+ break;
+ case CKR_DEVICE_REMOVED:
+ result = "CKR_DEVICE_REMOVED";
+ break;
+ case CKR_ENCRYPTED_DATA_INVALID:
+ result = "CKR_ENCRYPTED_DATA_INVALID";
+ break;
+ case CKR_ENCRYPTED_DATA_LEN_RANGE:
+ result = "CKR_ENCRYPTED_DATA_LEN_RANGE";
+ break;
+ case CKR_FUNCTION_CANCELED:
+ result = "CKR_FUNCTION_CANCELED";
+ break;
+ case CKR_FUNCTION_NOT_PARALLEL:
+ result = "CKR_FUNCTION_NOT_PARALLEL";
+ break;
+ case CKR_FUNCTION_NOT_SUPPORTED:
+ result = "CKR_FUNCTION_NOT_SUPPORTED";
+ break;
+ case CKR_KEY_HANDLE_INVALID:
+ result = "CKR_KEY_HANDLE_INVALID";
+ break;
+ case CKR_KEY_SIZE_RANGE:
+ result = "CKR_KEY_SIZE_RANGE";
+ break;
+ case CKR_KEY_TYPE_INCONSISTENT:
+ result = "CKR_KEY_TYPE_INCONSISTENT";
+ break;
+ case CKR_KEY_NOT_NEEDED:
+ result = "CKR_KEY_NOT_NEEDED";
+ break;
+ case CKR_KEY_CHANGED:
+ result = "CKR_KEY_CHANGED";
+ break;
+ case CKR_KEY_NEEDED:
+ result = "CKR_KEY_NEEDED";
+ break;
+ case CKR_KEY_INDIGESTIBLE:
+ result = "CKR_KEY_INDIGESTIBLE";
+ break;
+ case CKR_KEY_FUNCTION_NOT_PERMITTED:
+ result = "CKR_KEY_FUNCTION_NOT_PERMITTED";
+ break;
+ case CKR_KEY_NOT_WRAPPABLE:
+ result = "CKR_KEY_NOT_WRAPPABLE";
+ break;
+ case CKR_KEY_UNEXTRACTABLE:
+ result = "CKR_KEY_UNEXTRACTABLE";
+ break;
+ case CKR_MECHANISM_INVALID:
+ result = "CKR_MECHANISM_INVALID";
+ break;
+ case CKR_MECHANISM_PARAM_INVALID:
+ result = "CKR_MECHANISM_PARAM_INVALID";
+ break;
+ case CKR_OBJECT_HANDLE_INVALID:
+ result = "CKR_OBJECT_HANDLE_INVALID";
+ break;
+ case CKR_OPERATION_ACTIVE:
+ result = "CKR_OPERATION_ACTIVE";
+ break;
+ case CKR_OPERATION_NOT_INITIALIZED:
+ result = "CKR_OPERATION_NOT_INITIALIZED";
+ break;
+ case CKR_PIN_INCORRECT:
+ result = "CKR_PIN_INCORRECT";
+ break;
+ case CKR_PIN_INVALID:
+ result = "CKR_PIN_INVALID";
+ break;
+ case CKR_PIN_LEN_RANGE:
+ result = "CKR_PIN_LEN_RANGE";
+ break;
+ case CKR_PIN_EXPIRED:
+ result = "CKR_PIN_EXPIRED";
+ break;
+ case CKR_PIN_LOCKED:
+ result = "CKR_PIN_LOCKED";
+ break;
+ case CKR_SESSION_CLOSED:
+ result = "CKR_SESSION_CLOSED";
+ break;
+ case CKR_SESSION_COUNT:
+ result = "CKR_SESSION_COUNT";
+ break;
+ case CKR_SESSION_HANDLE_INVALID:
+ result = "CKR_SESSION_HANDLE_INVALID";
+ break;
+ case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
+ result = "CKR_SESSION_PARALLEL_NOT_SUPPORTED";
+ break;
+ case CKR_SESSION_READ_ONLY:
+ result = "CKR_SESSION_READ_ONLY";
+ break;
+ case CKR_SESSION_EXISTS:
+ result = "CKR_SESSION_EXISTS";
+ break;
+ case CKR_SESSION_READ_ONLY_EXISTS:
+ result = "CKR_SESSION_READ_ONLY_EXISTS";
+ break;
+ case CKR_SESSION_READ_WRITE_SO_EXISTS:
+ result = "CKR_SESSION_READ_WRITE_SO_EXISTS";
+ break;
+ case CKR_SIGNATURE_INVALID:
+ result = "CKR_SIGNATURE_INVALID";
+ break;
+ case CKR_SIGNATURE_LEN_RANGE:
+ result = "CKR_SIGNATURE_LEN_RANGE";
+ break;
+ case CKR_TEMPLATE_INCOMPLETE:
+ result = "CKR_TEMPLATE_INCOMPLETE";
+ break;
+ case CKR_TEMPLATE_INCONSISTENT:
+ result = "CKR_TEMPLATE_INCONSISTENT";
+ break;
+ case CKR_TOKEN_NOT_PRESENT:
+ result = "CKR_TOKEN_NOT_PRESENT";
+ break;
+ case CKR_TOKEN_NOT_RECOGNIZED:
+ result = "CKR_TOKEN_NOT_RECOGNIZED";
+ break;
+ case CKR_TOKEN_WRITE_PROTECTED:
+ result = "CKR_TOKEN_WRITE_PROTECTED";
+ break;
+ case CKR_UNWRAPPING_KEY_HANDLE_INVALID:
+ result = "CKR_UNWRAPPING_KEY_HANDLE_INVALID";
+ break;
+ case CKR_UNWRAPPING_KEY_SIZE_RANGE:
+ result = "CKR_UNWRAPPING_KEY_SIZE_RANGE";
+ break;
+ case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT:
+ result = "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT";
+ break;
+ case CKR_USER_ALREADY_LOGGED_IN:
+ result = "CKR_USER_ALREADY_LOGGED_IN";
+ break;
+ case CKR_USER_NOT_LOGGED_IN:
+ result = "CKR_USER_NOT_LOGGED_IN";
+ break;
+ case CKR_USER_PIN_NOT_INITIALIZED:
+ result = "CKR_USER_PIN_NOT_INITIALIZED";
+ break;
+ case CKR_USER_TYPE_INVALID:
+ result = "CKR_USER_TYPE_INVALID";
+ break;
+ case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
+ result = "CKR_USER_ANOTHER_ALREADY_LOGGED_IN";
+ break;
+ case CKR_USER_TOO_MANY_TYPES:
+ result = "CKR_USER_TOO_MANY_TYPES";
+ break;
+ case CKR_WRAPPED_KEY_INVALID:
+ result = "CKR_WRAPPED_KEY_INVALID";
+ break;
+ case CKR_WRAPPED_KEY_LEN_RANGE:
+ result = "CKR_WRAPPED_KEY_LEN_RANGE";
+ break;
+ case CKR_WRAPPING_KEY_HANDLE_INVALID:
+ result = "CKR_WRAPPING_KEY_HANDLE_INVALID";
+ break;
+ case CKR_WRAPPING_KEY_SIZE_RANGE:
+ result = "CKR_WRAPPING_KEY_SIZE_RANGE";
+ break;
+ case CKR_WRAPPING_KEY_TYPE_INCONSISTENT:
+ result = "CKR_WRAPPING_KEY_TYPE_INCONSISTENT";
+ break;
+ case CKR_RANDOM_SEED_NOT_SUPPORTED:
+ result = "CKR_RANDOM_SEED_NOT_SUPPORTED";
+ break;
+ case CKR_RANDOM_NO_RNG:
+ result = "CKR_RANDOM_NO_RNG";
+ break;
+ case CKR_BUFFER_TOO_SMALL:
+ result = "CKR_BUFFER_TOO_SMALL";
+ break;
+ case CKR_SAVED_STATE_INVALID:
+ result = "CKR_SAVED_STATE_INVALID";
+ break;
+ case CKR_INFORMATION_SENSITIVE:
+ result = "CKR_INFORMATION_SENSITIVE";
+ break;
+ case CKR_STATE_UNSAVEABLE:
+ result = "CKR_STATE_UNSAVEABLE";
+ break;
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ result = "CKR_CRYPTOKI_NOT_INITIALIZED";
+ break;
+ case CKR_CRYPTOKI_ALREADY_INITIALIZED:
+ result = "CKR_CRYPTOKI_ALREADY_INITIALIZED";
+ break;
+ case CKR_MUTEX_BAD:
+ result = "CKR_MUTEX_BAD";
+ break;
+ case CKR_MUTEX_NOT_LOCKED:
+ result = "CKR_MUTEX_NOT_LOCKED";
+ break;
+ case CKR_VENDOR_DEFINED:
+ result = "CKR_VENDOR_DEFINED";
+ break;
+ default:
+ toString( result, "UNKNOWN ERROR <%#02x>", rv );
+ }
+#endif
+}
+
+/*
+*/
+void Log::toString( std::string &result, const char * format, ... )
+{
+#ifdef __DEBUG_GEMALTO__
+ result = "";
+
+ // Get the size of the buffer necessary to write the message
+ // The size must be extended to include the '\n' and the '\0' characters.
+ va_list args;
+ va_start( args, format );
+#ifdef WIN32
+ size_t len = _vscprintf( format, args );
+#else
+ char tmp[1];
+ int len = vsnprintf( tmp, sizeof(tmp), format, args );
+#endif
+ va_end( args );
+
+ // Allocate the buffer for the message
+ char *buffer = new char[ len + 2 ];
+ memset( buffer, '\0', len + 2 );
+
+ // Write the message into the buffer.
+ va_start( args, format );
+#ifdef WIN32
+ vsprintf_s( buffer, len + 1, format, args );
+#else
+ vsprintf( buffer, format, args );
+#endif
+ va_end( args );
+
+ // Write the message to the string
+ result = buffer;
+
+ // Release the buffer
+ delete[] buffer;
+#endif
+}
+
+
+/*
+*/
+void Log::toString( const unsigned char* buffer, std::size_t size, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( ( NULL == buffer ) || ( 1 > size ) )
+ {
+ //result.assign( "null" );
+ return;
+ }
+
+ std::ostringstream oss;
+ oss.rdbuf( )->str( "" );
+
+ // Afficher en héxadécimal et en majuscule
+ oss << std::hex << std::uppercase;
+
+ // Remplir les blancs avec des zéros
+ oss << std::setfill('0');
+
+ for( std::size_t i = 0; i < size; ++i )
+ {
+ // Séparer chaque octet par un espace
+ if (i != 0)
+ oss << ' ';
+
+ // Afficher sa valeur hexadécimale précédée de "0x"
+ // setw(2) permet de forcer l'affichage à 2 caractères
+ oss << /*"0x" <<*/ std::setw(2) << static_cast<int>( buffer[i] );
+ }
+
+ result.assign( oss.str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::toString( const unsigned long &l, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ classtoString<unsigned long>( l, result );
+#endif
+}
+
+
+template<typename T> void Log::classtoString( const T & value, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL == &value )
+ {
+ return;
+ }
+ std::ostringstream str;
+ str << value;
+ result.assign( str.str( ) );
+#endif
+}
+
+
+void Log::slotFlagsToString( const CK_FLAGS& f, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ result = "";
+
+ // Slot Information Flags
+ if( f & CKF_TOKEN_PRESENT )
+ {
+ result += "CKF_TOKEN_PRESENT";
+ }
+
+ if( f & CKF_REMOVABLE_DEVICE )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_REMOVABLE_DEVICE";
+ }
+
+ if( f & CKF_HW_SLOT )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_HW_SLOT";
+ }
+#endif
+}
+
+
+/*
+*/
+void Log::CK_VERSIONToString( CK_VERSION_PTR pVersion, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR == pVersion )
+ {
+ return;
+ }
+
+ toString( result, "%#02x - %#02x", pVersion->major, pVersion->minor );
+#endif
+}
+
+
+/*
+*/
+void Log::CK_MECHANISM_TYPEToString( CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG mechanismListLen, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR == pMechanismList )
+ {
+ return;
+ }
+
+ result = "";
+
+ for( size_t i = 0 ; i < (size_t)mechanismListLen; i++ )
+ {
+ std::string m = "";
+ CK_MECHANISM_TYPEToString( pMechanismList[ i ], m );
+ result += m;
+ if( i != (size_t)( mechanismListLen - 1 ) )
+ {
+ result +=", ";
+ }
+ }
+#endif
+}
+
+
+/*
+*/
+void Log::CK_MECHANISM_TYPEToString( const CK_MECHANISM_TYPE &t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ switch( t )
+ {
+ case CKM_RSA_PKCS_KEY_PAIR_GEN:
+ result = "CKM_RSA_PKCS_KEY_PAIR_GEN";
+ break;
+ case CKM_RSA_PKCS:
+ result = "CKM_RSA_PKCS";
+ break;
+ case CKM_RSA_9796:
+ result = "CKM_RSA_9796";
+ break;
+ case CKM_RSA_X_509:
+ result = "CKM_RSA_X_509";
+ break;
+ case CKM_MD2_RSA_PKCS:
+ result = "CKM_MD2_RSA_PKCS";
+ break;
+ case CKM_MD5_RSA_PKCS:
+ result = "CKM_MD5_RSA_PKCS";
+ break;
+ case CKM_SHA1_RSA_PKCS:
+ result = "CKM_SHA1_RSA_PKCS";
+ break;
+ case CKM_DSA_KEY_PAIR_GEN:
+ result = "CKM_DSA_KEY_PAIR_GEN";
+ break;
+ case CKM_DSA:
+ result = "CKM_DSA";
+ break;
+ case CKM_DSA_SHA1:
+ result = "CKM_DSA_SHA1";
+ break;
+ case CKM_DH_PKCS_KEY_PAIR_GEN:
+ result = "CKM_DH_PKCS_KEY_PAIR_GEN";
+ break;
+ case CKM_DH_PKCS_DERIVE:
+ result = "CKM_DH_PKCS_DERIVE";
+ break;
+ case CKM_RC2_KEY_GEN:
+ result = "CKM_RC2_KEY_GEN";
+ break;
+ case CKM_RC2_ECB:
+ result = "CKM_RC2_ECB";
+ break;
+ case CKM_RC2_CBC:
+ result = "CKM_RC2_CBC";
+ break;
+ case CKM_RC2_MAC:
+ result = "CKM_RC2_MAC";
+ break;
+ case CKM_RC2_MAC_GENERAL:
+ result = "CKM_RC2_MAC_GENERAL";
+ break;
+ case CKM_RC2_CBC_PAD:
+ result = "CKM_RC2_CBC_PAD";
+ break;
+ case CKM_RC4_KEY_GEN:
+ result = "CKM_RC4_KEY_GEN";
+ break;
+ case CKM_RC4:
+ result = "CKM_RC4";
+ break;
+ case CKM_DES_KEY_GEN:
+ result = "CKM_DES_KEY_GEN";
+ break;
+ case CKM_DES_ECB:
+ result = "CKM_DES_ECB";
+ break;
+ case CKM_DES_CBC:
+ result = "CKM_DES_CBC";
+ break;
+ case CKM_DES_MAC:
+ result = "CKM_DES_MAC";
+ break;
+ case CKM_DES_MAC_GENERAL:
+ result = "CKM_DES_MAC_GENERAL";
+ break;
+ case CKM_DES_CBC_PAD:
+ result = "CKM_DES_CBC_PAD";
+ break;
+ case CKM_DES2_KEY_GEN:
+ result = "CKM_DES2_KEY_GEN";
+ break;
+ case CKM_DES3_KEY_GEN:
+ result = "CKM_DES3_KEY_GEN";
+ break;
+ case CKM_DES3_ECB:
+ result = "CKM_DES3_ECB";
+ break;
+ case CKM_DES3_CBC:
+ result = "CKM_DES3_CBC";
+ break;
+ case CKM_DES3_MAC:
+ result = "CKM_DES3_MAC";
+ break;
+ case CKM_DES3_MAC_GENERAL:
+ result = "CKM_DES3_MAC_GENERAL";
+ break;
+ case CKM_DES3_CBC_PAD:
+ result = "CKM_DES3_CBC_PAD";
+ break;
+ case CKM_CDMF_KEY_GEN:
+ result = "CKM_CDMF_KEY_GEN";
+ break;
+ case CKM_CDMF_ECB:
+ result = "CKM_CDMF_ECB";
+ break;
+ case CKM_CDMF_CBC:
+ result = "CKM_CDMF_CBC";
+ break;
+ case CKM_CDMF_MAC:
+ result = "CKM_CDMF_MAC";
+ break;
+ case CKM_CDMF_MAC_GENERAL:
+ result = "CKM_CDMF_MAC_GENERAL";
+ break;
+ case CKM_CDMF_CBC_PAD:
+ result = "CKM_CDMF_CBC_PAD";
+ break;
+ case CKM_MD2:
+ result = "CKM_MD2";
+ break;
+ case CKM_MD2_HMAC:
+ result = "CKM_MD2_HMAC";
+ break;
+ case CKM_MD2_HMAC_GENERAL:
+ result = "CKM_MD2_HMAC_GENERAL";
+ break;
+ case CKM_MD5:
+ result = "CKM_MD5";
+ break;
+ case CKM_MD5_HMAC:
+ result = "CKM_MD5_HMAC";
+ break;
+ case CKM_MD5_HMAC_GENERAL:
+ result = "CKM_MD5_HMAC_GENERAL";
+ break;
+ case CKM_SHA_1:
+ result = "CKM_SHA_1";
+ break;
+ case CKM_SHA_1_HMAC:
+ result = "CKM_SHA_1_HMAC";
+ break;
+ case CKM_SHA_1_HMAC_GENERAL:
+ result = "CKM_SHA_1_HMAC_GENERAL";
+ break;
+ case CKM_CAST_KEY_GEN:
+ result = "CKM_CAST_KEY_GEN";
+ break;
+ case CKM_CAST_ECB:
+ result = "CKM_CAST_ECB";
+ break;
+ case CKM_CAST_CBC:
+ result = "CKM_CAST_CBC";
+ break;
+ case CKM_CAST_MAC:
+ result = "CKM_CAST_MAC";
+ break;
+ case CKM_CAST_MAC_GENERAL:
+ result = "CKM_CAST_MAC_GENERAL";
+ break;
+ case CKM_CAST_CBC_PAD:
+ result = "CKM_CAST_CBC_PAD";
+ break;
+ case CKM_CAST3_KEY_GEN:
+ result = "CKM_CAST3_KEY_GEN";
+ break;
+ case CKM_CAST3_ECB:
+ result = "CKM_CAST3_ECB";
+ break;
+ case CKM_CAST3_CBC:
+ result = "CKM_CAST3_CBC";
+ break;
+ case CKM_CAST3_MAC:
+ result = "CKM_CAST3_MAC";
+ break;
+ case CKM_CAST3_MAC_GENERAL:
+ result = "CKM_CAST3_MAC_GENERAL";
+ break;
+ case CKM_CAST3_CBC_PAD:
+ result = "CKM_CAST3_CBC_PAD";
+ break;
+ /*case CKM_CAST5_KEY_GEN:
+ result = "CKM_CAST5_KEY_GEN";
+ break;*/
+ case CKM_CAST128_KEY_GEN:
+ result = "CKM_CAST128_KEY_GEN/CKM_CAST5_KEY_GEN";
+ break;
+ /*case CKM_CAST5_ECB:
+ result = "CKM_CAST5_ECB";
+ break;*/
+ case CKM_CAST128_ECB:
+ result = "CKM_CAST128_ECB/CKM_CAST5_ECB";
+ break;
+ /*case CKM_CAST5_CBC:
+ result = "CKM_CAST5_CBC";
+ break;*/
+ case CKM_CAST128_CBC:
+ result = "CKM_CAST128_CBC/CKM_CAST5_CBC";
+ break;
+ /*case CKM_CAST5_MAC:
+ result = "CKM_CAST5_MAC";
+ break;*/
+ case CKM_CAST128_MAC:
+ result = "CKM_CAST128_MAC/CKM_CAST5_MAC";
+ break;
+ /*case CKM_CAST5_MAC_GENERAL:
+ result = "CKM_CAST5_MAC_GENERAL";
+ break;*/
+ case CKM_CAST128_MAC_GENERAL:
+ result = "CKM_CAST128_MAC_GENERAL/CKM_CAST5_MAC_GENERAL";
+ break;
+ /*case CKM_CAST5_CBC_PAD:
+ result = "CKM_CAST5_CBC_PAD";
+ break;*/
+ case CKM_CAST128_CBC_PAD:
+ result = "CKM_CAST128_CBC_PAD/CKM_CAST5_CBC_PAD";
+ break;
+ case CKM_RC5_KEY_GEN:
+ result = "CKM_RC5_KEY_GEN";
+ break;
+ case CKM_RC5_ECB:
+ result = "CKM_RC5_ECB";
+ break;
+ case CKM_RC5_CBC:
+ result = "CKM_RC5_CBC";
+ break;
+ case CKM_RC5_MAC:
+ result = "CKM_RC5_MAC";
+ break;
+ case CKM_RC5_MAC_GENERAL:
+ result = "CKM_RC5_MAC_GENERAL";
+ break;
+ case CKM_RC5_CBC_PAD:
+ result = "CKM_RC5_CBC_PAD";
+ break;
+ case CKM_IDEA_KEY_GEN:
+ result = "CKM_IDEA_KEY_GEN";
+ break;
+ case CKM_IDEA_ECB:
+ result = "CKM_IDEA_ECB";
+ break;
+ case CKM_IDEA_CBC:
+ result = "CKM_IDEA_CBC";
+ break;
+ case CKM_IDEA_MAC:
+ result = "CKM_IDEA_MAC";
+ break;
+ case CKM_IDEA_MAC_GENERAL:
+ result = "CKM_IDEA_MAC_GENERAL";
+ break;
+ case CKM_IDEA_CBC_PAD:
+ result = "CKM_IDEA_CBC_PAD";
+ break;
+ case CKM_GENERIC_SECRET_KEY_GEN:
+ result = "CKM_GENERIC_SECRET_KEY_GEN";
+ break;
+ case CKM_CONCATENATE_BASE_AND_KEY:
+ result = "CKM_CONCATENATE_BASE_AND_KEY";
+ break;
+ case CKM_CONCATENATE_BASE_AND_DATA:
+ result = "CKM_CONCATENATE_BASE_AND_DATA";
+ break;
+ case CKM_CONCATENATE_DATA_AND_BASE:
+ result = "CKM_CONCATENATE_DATA_AND_BASE";
+ break;
+ case CKM_XOR_BASE_AND_DATA:
+ result = "CKM_XOR_BASE_AND_DATA";
+ break;
+ case CKM_EXTRACT_KEY_FROM_KEY:
+ result = "CKM_EXTRACT_KEY_FROM_KEY";
+ break;
+ case CKM_SSL3_PRE_MASTER_KEY_GEN:
+ result = "CKM_SSL3_PRE_MASTER_KEY_GEN";
+ break;
+ case CKM_SSL3_MASTER_KEY_DERIVE:
+ result = "CKM_SSL3_MASTER_KEY_DERIVE";
+ break;
+ case CKM_SSL3_KEY_AND_MAC_DERIVE:
+ result = "CKM_SSL3_KEY_AND_MAC_DERIVE";
+ break;
+ case CKM_SSL3_MD5_MAC:
+ result = "CKM_SSL3_MD5_MAC";
+ break;
+ case CKM_SSL3_SHA1_MAC:
+ result = "CKM_SSL3_SHA1_MAC";
+ break;
+ case CKM_MD5_KEY_DERIVATION:
+ result = "CKM_MD5_KEY_DERIVATION";
+ break;
+ case CKM_MD2_KEY_DERIVATION:
+ result = "CKM_MD2_KEY_DERIVATION";
+ break;
+ case CKM_SHA1_KEY_DERIVATION:
+ result = "CKM_SHA1_KEY_DERIVATION";
+ break;
+ case CKM_PBE_MD2_DES_CBC:
+ result = "CKM_PBE_MD2_DES_CBC";
+ break;
+ case CKM_PBE_MD5_DES_CBC:
+ result = "CKM_PBE_MD5_DES_CBC";
+ break;
+ case CKM_PBE_MD5_CAST_CBC:
+ result = "CKM_PBE_MD5_CAST_CBC";
+ break;
+ case CKM_PBE_MD5_CAST3_CBC:
+ result = "CKM_PBE_MD5_CAST3_CBC";
+ break;
+ /*case CKM_PBE_MD5_CAST5_CBC:
+ result = "CKM_PBE_MD5_CAST5_CBC";
+ break;*/
+ case CKM_PBE_MD5_CAST128_CBC:
+ result = "CKM_PBE_MD5_CAST128_CBC/CKM_PBE_MD5_CAST5_CBC";
+ break;
+ /*case CKM_PBE_SHA1_CAST5_CBC:
+ result = "CKM_PBE_SHA1_CAST5_CBC";
+ break;*/
+ case CKM_PBE_SHA1_CAST128_CBC:
+ result = "CKM_PBE_SHA1_CAST128_CBC/CKM_PBE_SHA1_CAST5_CBC";
+ break;
+ case CKM_PBE_SHA1_RC4_128:
+ result = "CKM_PBE_SHA1_RC4_128";
+ break;
+ case CKM_PBE_SHA1_RC4_40:
+ result = "CKM_PBE_SHA1_RC4_40";
+ break;
+ case CKM_PBE_SHA1_DES3_EDE_CBC:
+ result = "CKM_PBE_SHA1_DES3_EDE_CBC";
+ break;
+ case CKM_PBE_SHA1_DES2_EDE_CBC:
+ result = "CKM_PBE_SHA1_DES2_EDE_CBC";
+ break;
+ case CKM_PBE_SHA1_RC2_128_CBC:
+ result = "CKM_PBE_SHA1_RC2_128_CBC";
+ break;
+ case CKM_PBE_SHA1_RC2_40_CBC:
+ result = "CKM_PBE_SHA1_RC2_40_CBC";
+ break;
+ case CKM_PBA_SHA1_WITH_SHA1_HMAC:
+ result = "CKM_PBA_SHA1_WITH_SHA1_HMAC";
+ break;
+ case CKM_KEY_WRAP_LYNKS:
+ result = "CKM_KEY_WRAP_LYNKS";
+ break;
+ case CKM_KEY_WRAP_SET_OAEP:
+ result = "CKM_KEY_WRAP_SET_OAEP";
+ break;
+ case CKM_SKIPJACK_KEY_GEN:
+ result = "CKM_SKIPJACK_KEY_GEN";
+ break;
+ case CKM_SKIPJACK_ECB64:
+ result = "CKM_SKIPJACK_ECB64";
+ break;
+ case CKM_SKIPJACK_CBC64:
+ result = "CKM_SKIPJACK_CBC64";
+ break;
+ case CKM_SKIPJACK_OFB64:
+ result = "CKM_SKIPJACK_OFB64";
+ break;
+ case CKM_SKIPJACK_CFB64:
+ result = "CKM_SKIPJACK_CFB64";
+ break;
+ case CKM_SKIPJACK_CFB32:
+ result = "CKM_SKIPJACK_CFB32";
+ break;
+ case CKM_SKIPJACK_CFB16:
+ result = "CKM_SKIPJACK_CFB16";
+ break;
+ case CKM_SKIPJACK_CFB8:
+ result = "CKM_SKIPJACK_CFB8";
+ break;
+ case CKM_SKIPJACK_WRAP:
+ result = "CKM_SKIPJACK_WRAP";
+ break;
+ case CKM_SKIPJACK_PRIVATE_WRAP:
+ result = "CKM_SKIPJACK_PRIVATE_WRAP";
+ break;
+ case CKM_SKIPJACK_RELAYX:
+ result = "CKM_SKIPJACK_RELAYX";
+ break;
+ case CKM_KEA_KEY_PAIR_GEN:
+ result = "CKM_KEA_KEY_PAIR_GEN";
+ break;
+ case CKM_KEA_KEY_DERIVE:
+ result = "CKM_KEA_KEY_DERIVE";
+ break;
+ case CKM_FORTEZZA_TIMESTAMP:
+ result = "CKM_FORTEZZA_TIMESTAMP";
+ break;
+ case CKM_BATON_KEY_GEN:
+ result = "CKM_BATON_KEY_GEN";
+ break;
+ case CKM_BATON_ECB128:
+ result = "CKM_BATON_ECB128";
+ break;
+ case CKM_BATON_ECB96:
+ result = "CKM_BATON_ECB96";
+ break;
+ case CKM_BATON_CBC128:
+ result = "CKM_BATON_CBC128";
+ break;
+ case CKM_BATON_COUNTER:
+ result = "CKM_BATON_COUNTER";
+ break;
+ case CKM_BATON_SHUFFLE:
+ result = "CKM_BATON_SHUFFLE";
+ break;
+ case CKM_BATON_WRAP:
+ result = "CKM_RSA_9796";
+ break;
+ case CKM_ECDSA:
+ result = "CKM_ECDSA";
+ break;
+ case CKM_ECDSA_SHA1:
+ result = "CKM_ECDSA_SHA1";
+ break;
+ case CKM_JUNIPER_KEY_GEN:
+ result = "CKM_JUNIPER_KEY_GEN";
+ break;
+ case CKM_JUNIPER_ECB128:
+ result = "CKM_JUNIPER_ECB128";
+ break;
+ case CKM_JUNIPER_CBC128:
+ result = "CKM_JUNIPER_CBC128";
+ break;
+ case CKM_JUNIPER_COUNTER:
+ result = "CKM_JUNIPER_COUNTER";
+ break;
+ case CKM_JUNIPER_SHUFFLE:
+ result = "CKM_JUNIPER_SHUFFLE";
+ break;
+ case CKM_JUNIPER_WRAP:
+ result = "CKM_JUNIPER_WRAP";
+ break;
+ case CKM_FASTHASH:
+ result = "CKM_FASTHASH";
+ break;
+ case CKM_VENDOR_DEFINED:
+ result = "CKM_VENDOR_DEFINED";
+ break;
+ case CKM_SHA256:
+ result = "CKM_SHA256";
+ break;
+ case CKM_SHA256_RSA_PKCS:
+ result = "CKM_SHA256_RSA_PKCS";
+ break;
+ default:
+ toString( result, "UNKNOWN MECHANISM <%#02x>", t );
+ }
+#endif
+}
+
+
+/*
+*/
+void Log::CK_MECHANISM_INFOToString( CK_MECHANISM_INFO_PTR pInfo, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR == pInfo )
+ {
+ return;
+ }
+
+ std::string flags = "";
+ CK_FLAGS f = pInfo->flags;
+ mechanismFlagsToString( f, flags );
+
+ toString( result, "ulMinKeySize <%#02x> - ulMaxKeySize <%#02x> - flags <%s>", pInfo->ulMinKeySize, pInfo->ulMaxKeySize, flags.c_str( ) );
+#endif
+}
+
+
+/*
+*/
+void Log::mechanismFlagsToString( const CK_FLAGS& f, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( f & CKF_EXTENSION )
+ {
+ result += "CKF_EXTENSION";
+ }
+ if( f & CKF_DERIVE )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_DERIVE";
+ }
+ if( f & CKF_UNWRAP )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_UNWRAP";
+ }
+ if( f & CKF_WRAP )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_WRAP";
+ }
+ if( f & CKF_GENERATE_KEY_PAIR )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_GENERATE_KEY_PAIR";
+ }
+ if( f & CKF_GENERATE )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_GENERATE";
+ }
+ if( f & CKF_VERIFY_RECOVER )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_VERIFY_RECOVER";
+ }
+ if( f & CKF_VERIFY )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_VERIFY";
+ }
+ if( f & CKF_SIGN_RECOVER )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_SIGN_RECOVER";
+ }
+ if( f & CKF_HW )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_HW";
+ }
+ if( f & CKF_ENCRYPT )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_ENCRYPT";
+ }
+ if( f & CKF_DECRYPT )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_DECRYPT";
+ }
+ if( f & CKF_DIGEST )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_DIGEST";
+ }
+ if( f & CKF_SIGN )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_SIGN";
+ }
+#endif
+}
+
+
+/*
+*/
+void Log::sessionFlagsToString( const CK_FLAGS &f, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ result = "";
+
+ // Session information flags
+ if( f & CKF_SERIAL_SESSION )
+ {
+ result += "CKF_SERIAL_SESSION";
+ }
+
+ if( f & CKF_RW_SESSION )
+ {
+ if( !result.empty( ) )
+ {
+ result += " | ";
+ }
+ result += "CKF_RW_SESSION";
+ }
+#endif
+}
+
+
+/*
+*/
+void Log::CK_SESSION_INFOToString( CK_SESSION_INFO_PTR pInfo, std::string& result )
+{
+#ifdef __DEBUG_GEMALTO__
+ if( NULL_PTR == pInfo )
+ {
+ return;
+ }
+
+ std::string flags = "";
+ CK_FLAGS f = pInfo->flags;
+ sessionFlagsToString( f, flags );
+
+ toString( result, "slotID <%#02x> - state <%#02x> - flags <%#02x> (%s) - ulDeviceError <%#02x>",
+ pInfo->slotID,
+ pInfo->state,
+ pInfo->flags,
+ flags.c_str( ),
+ pInfo->ulDeviceError );
+#endif
+}
+
+/*
+*/
+void Log::CK_USER_TYPEToString( const CK_USER_TYPE& t, std::string &result )
+{
+#ifdef __DEBUG_GEMALTO__
+ switch( t )
+ {
+ case CKU_USER:
+ result = "CKU_USER";
+ break;
+
+ case CKU_SO:
+ result = "CKU_SO";
+ break;
+
+ default:
+ toString( result, "UNKNOWN USER TYPE <%#02x>", t );
+ }
+#endif
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/log.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,90 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_log_h
+#define _include_log_h
+
+#include <string>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+#include "platconfig.h"
+
+
+class Log
+{
+public:
+
+ static void log( const char * format, ... );
+
+ static void error( const char*, const char* );
+ static void in( const char* a_pMethod );
+ static void out( const char* a_pMethod );
+ static void begin( const char* a_pMethod );
+ static void end( const char* a_pMethod );
+
+ static void logCK_SLOT_ID_PTR( const char*, CK_SLOT_ID_PTR, CK_ULONG_PTR );
+ static void logCK_SLOT_INFO_PTR( const char*, CK_SLOT_INFO_PTR );
+ static void logCK_C_INITIALIZE_ARGS_PTR( const char*, CK_C_INITIALIZE_ARGS_PTR );
+ static void logCK_INFO( const char*, const CK_INFO_PTR );
+ static void logCK_RV( const char*, const CK_RV & );
+ static void logCK_UTF8CHAR_PTR( const char*, const unsigned char*, const std::size_t& );
+ static void logCK_TOKEN_INFO_PTR( const char*, CK_TOKEN_INFO_PTR );
+ static void logCK_MECHANISM_TYPE( const char*, CK_MECHANISM_TYPE_PTR, CK_ULONG_PTR );
+ static void logCK_MECHANISM_TYPE( const char*, CK_MECHANISM_TYPE & );
+ static void logCK_SESSION_INFO_PTR( const char*, CK_SESSION_INFO_PTR );
+ static void logCK_USER_TYPE( const char*, CK_USER_TYPE & );
+ static void logCK_ATTRIBUTE_PTR( const char*, CK_ATTRIBUTE_PTR, CK_ULONG & );
+ static void logSessionFlags( const char*, CK_FLAGS & );
+ static void logCK_MECHANISM_INFO_PTR( const char*, CK_MECHANISM_INFO_PTR );
+ static void logCK_MECHANISM_PTR( const char*, CK_MECHANISM_PTR );
+
+ static void CK_MECHANISMToString( CK_MECHANISM_PTR, std::string & );
+ static void CK_CERTIFICATE_TYPEToString( const CK_CERTIFICATE_TYPE &, std::string & );
+ static void CK_KEY_TYPEToString( const CK_KEY_TYPE&, std::string & );
+ static void CK_OBJECT_CLASSToString( const CK_OBJECT_CLASS&, std::string & );
+ static void CK_DATEToString( const CK_DATE*, std::string & );
+ static void CK_INFOToString( CK_INFO_PTR pInfo, std::string &result );
+ static void slotFlagsToString( const CK_FLAGS& f, std::string &result );
+ static void mechanismFlagsToString( const CK_FLAGS &, std::string & );
+ static void sessionFlagsToString( const CK_FLAGS & , std::string & );
+ static void CK_VERSIONToString( CK_VERSION_PTR pVersion, std::string& result );
+ static void CK_RVToString( const CK_RV& rv, std::string &result );
+ static void CK_MECHANISM_TYPEToString( CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG mechanismListLen, std::string &result );
+ static void CK_MECHANISM_TYPEToString( const CK_MECHANISM_TYPE &, std::string & );
+ static void CK_MECHANISM_INFOToString( CK_MECHANISM_INFO_PTR pInfo, std::string &result );
+ static void CK_SESSION_INFOToString( CK_SESSION_INFO_PTR, std::string& );
+ static void CK_USER_TYPEToString( const CK_USER_TYPE&, std::string & );
+ static void CK_ATTRIBUTEToString( const CK_ATTRIBUTE_PTR, std::string & );
+ static void CK_ATTRIBUTE_TYPEToString( const CK_ATTRIBUTE_TYPE& , std::string &, int& );
+
+ static void toStringHex( const unsigned char* buffer, const std::size_t& size, std::string &result );
+ static void toString( std::string &result, const char * format, ... );
+ static void toString( const unsigned char* buffer, std::size_t size, std::string &result );
+ static void toString( const unsigned long &l, std::string &result );
+
+ template<typename T> static void classtoString( const T & value, std::string &result );
+
+};
+
+
+#endif
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,74 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "digest.h"
+#include "md5.h"
+
+CMD5::CMD5(){
+ this->_hashValue = (CK_BYTE_PTR)malloc(MD5_HASH_LENGTH);
+ this->_workingBuffer = (CK_BYTE_PTR)malloc(MD5_BLOCK_LENGTH);
+ this->_hashLength = MD5_HASH_LENGTH;
+ this->_blockLength = MD5_BLOCK_LENGTH;
+}
+
+CMD5::~CMD5(){
+}
+
+void CMD5::TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result)
+{
+ algo_md5_context ctx;
+
+ ctx.digest = (u4*)result;
+
+ if (counter == 0) {
+ algo_md5_starts(&ctx);
+ } else {
+ ctx.total[0] = counter;
+ ctx.total[1] = 0;
+ }
+
+ algo_md5_update(&ctx, data, MD5_BLOCK_LENGTH);
+}
+
+void CMD5::TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result)
+{
+ algo_md5_context ctx;
+
+ ctx.digest = (u4*)result;
+
+ if (counter == 0) {
+ algo_md5_starts(&ctx);
+ } else {
+ ctx.total[0] = counter;
+ ctx.total[1] = 0;
+ }
+
+ // allocate tempory working buffer
+ ctx.input = (u1*)malloc(MD5_BLOCK_LENGTH);
+ memset(ctx.input,0,MD5_BLOCK_LENGTH);
+
+ algo_md5_update(&ctx,data,length);
+ algo_md5_finish(&ctx);
+
+ free(ctx.input);
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/md5.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,39 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_md5_h
+#define _include_md5_h
+
+#include "MarshallerCfg.h"
+#include "algo_md5.h"
+
+class CMD5 : public CDigest
+{
+private:
+ void TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result);
+ void TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result);
+
+public:
+ CMD5();
+ ~CMD5();
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,144 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef INCLUDE_EVENTING
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include <string>
+#ifndef WIN32
+#include <pthread.h>
+#endif
+#include "mutex.h"
+
+CMutex::CMutex()
+{
+#ifdef WIN32
+ m_hMutex = NULL;
+#endif
+ m_strName = "";
+}
+
+CMutex::CMutex(const char* nm)
+{
+ m_strName = nm;
+
+#ifdef WIN32
+ m_hMutex = (unsigned long*)CreateMutex(NULL,FALSE,nm);
+
+ if(m_hMutex == NULL)
+ {
+ assert(FALSE); //throw ThreadException("Failed to create mutex");
+ }
+#else
+ pthread_mutex_init(&m_hMutex,0);
+ m_ownerThread = 0;
+ m_refCount = 0;
+#endif
+}
+
+#ifdef WIN32
+void CMutex::create(const char* nm)
+#else
+void CMutex::create(const char*)
+#endif
+{
+
+#ifdef WIN32
+ if(m_hMutex != NULL)
+ {
+ CloseHandle(m_hMutex);
+ m_hMutex = NULL;
+ }
+
+ m_strName = nm;
+ m_hMutex = (unsigned long*)CreateMutex(NULL,FALSE,nm);
+
+ if(m_hMutex == NULL)
+ {
+ assert(FALSE); //throw ThreadException("Failed to create mutex");
+ }
+#else
+ if(pthread_equal(m_ownerThread,pthread_self()))
+ {
+ m_refCount++;
+ }
+ else
+ {
+ if(pthread_mutex_lock(&m_hMutex) == 0)
+ {
+ //assert(FALSE);
+ }
+ m_ownerThread = pthread_self();
+ m_refCount = 1;
+ }
+
+
+#endif
+}
+
+#ifdef WIN32
+unsigned long* CMutex::getMutexHandle()
+{
+ return m_hMutex;
+}
+#endif
+
+std::string CMutex::getName()
+{
+ return m_strName;
+}
+
+void CMutex::release()
+{
+#ifdef WIN32
+ if(m_hMutex != NULL)
+ {
+ CloseHandle(m_hMutex);
+ m_hMutex = NULL;
+ }
+#else
+ if(pthread_equal(m_ownerThread,pthread_self()))
+ {
+ m_refCount--;
+
+ if(!m_refCount)
+ {
+ m_ownerThread = 0;
+ pthread_mutex_unlock(&m_hMutex);
+ }
+ }
+#endif
+}
+
+CMutex::~CMutex()
+{
+#ifdef WIN32
+ if(m_hMutex != NULL)
+ {
+ CloseHandle(m_hMutex);
+ }
+#else
+ pthread_mutex_destroy(&m_hMutex);
+#endif
+}
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/mutex.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,54 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_mutex_h
+#define _include_mutex_h
+
+#ifdef INCLUDE_EVENTING
+
+class CMutex
+{
+private:
+ // unsigned long* to the low-level mutex object
+#ifdef WIN32
+ unsigned long* m_hMutex;
+#else
+ pthread_mutex_t m_hMutex;
+ pthread_t m_ownerThread;
+ unsigned long m_refCount;
+#endif
+ // name to identify the mutex
+ std::string m_strName;
+
+public:
+ CMutex();
+ CMutex(const char* nm);
+ ~CMutex();
+
+ void create(const char* nm);
+ unsigned long* getMutexHandle();
+ std::string getName();
+ void release();
+};
+
+#endif
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,2189 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#define CRYPTOKIVERSION_INTERFACE_MAJOR 0x02
+#define CRYPTOKIVERSION_INTERFACE_MINOR 0x14
+
+#define CRYPTOKIVERSION_LIBRARY_MAJOR 0x02
+#define CRYPTOKIVERSION_LIBRARY_MINOR 0x00
+
+#define LIBRARY_DESCRIPTION "CF .NET PKCS#11 Module"
+#define MANUFACTURER_ID "Gemalto"
+
+#include <string>
+
+#include "stdafx.h"
+#include <winscard.h>
+#include "error.h"
+#include "platconfig.h"
+#include "config.h"
+#include "digest.h"
+#include "symmalgo.h"
+#include "thread.h"
+#include "event.h"
+#include "mutex.h"
+#include "session.h"
+#include "slot.h"
+#include "application.h"
+#include "critsect.h"
+#include "log.h"
+
+
+static CK_BBOOL _isInitialized = FALSE;
+
+
+// This libarary is thread protected by a single critical section
+// This coarse grained approach is for simplicty, the alternative
+// require significant work.
+CCriticalSection _critSect;
+
+static const CK_FUNCTION_LIST FunctionList = {
+ { CRYPTOKIVERSION_LIBRARY_MAJOR, CRYPTOKIVERSION_LIBRARY_MINOR },
+
+#undef CK_PKCS11_FUNCTION_INFO
+#undef CK_NEED_ARG_LIST
+
+#define CK_PKCS11_FUNCTION_INFO(func) func,
+
+#include "pkcs11f.h"
+
+#undef CK_PKCS11_FUNCTION_INFO
+#undef CK_NEED_ARG_LIST
+};
+
+
+#define PKCS11_TRY \
+ if (!_isInitialized) { \
+ return CKR_CRYPTOKI_NOT_INITIALIZED; } \
+ CCriticalSectionLocker __cslock(_critSect); \
+ try
+
+
+#define PKCS11_CATCH(rv) \
+ catch(CkError & err) { rv = err.Error(); } \
+ catch(PcscError & ) { rv = CKR_FUNCTION_FAILED; } \
+ catch(Marshaller::Exception & exc) { rv = CkError::CheckMarshallerException(exc); } \
+ catch(...) { rv = CKR_GENERAL_ERROR; }
+
+
+// Put all static initializations here to ensure they
+// occur in correct order.
+
+CEvent CryptokiEvent(0xFFFFFFFF);
+
+// CStartStopControl to support clean up at DLL unload
+class CStartStopControl
+{
+public:
+ CStartStopControl() {};
+ ~CStartStopControl() {
+ Application::End( );
+ }
+} foo;
+
+
+extern "C"
+{
+
+
+ /**
+ * C_Initialize initializes the Cryptoki library.
+ *
+ * @param pInitArgs
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_Initialize )( CK_VOID_PTR pInitArgs )
+ {
+ Log::begin( "C_Initialize" );
+ Log::in( "C_Initialize" );
+ Log::log( "C_Initialize - pInitArgs <%#02x>", pInitArgs );
+ Log::log( "C_Initialize - isInitialized <%#02x>", _isInitialized );
+
+ CK_RV rv = CKR_OK;
+
+ // Already Initialized
+ if( TRUE == _isInitialized )
+ {
+ Log::error( "C_Initialize", "CKR_CRYPTOKI_ALREADY_INITIALIZED" );
+ rv = CKR_CRYPTOKI_ALREADY_INITIALIZED;
+ }
+ else if( NULL_PTR != pInitArgs )
+ {
+ CK_C_INITIALIZE_ARGS initArgs = *(CK_C_INITIALIZE_ARGS_PTR)pInitArgs;
+
+ Log::logCK_C_INITIALIZE_ARGS_PTR( "C_Initialize", (CK_C_INITIALIZE_ARGS_PTR)pInitArgs );
+
+ if( NULL_PTR != initArgs.pReserved )
+ {
+ Log::error( "C_Initialize", "CKR_ARGUMENTS_BAD" );
+ rv = CKR_ARGUMENTS_BAD;
+ }
+ else if( initArgs.flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS )
+ {
+ Log::error( "C_Initialize", "CKR_NEED_TO_CREATE_THREADS" );
+ rv = CKR_NEED_TO_CREATE_THREADS;
+ }
+ else if( initArgs.flags & CKF_OS_LOCKING_OK )
+ {
+ if( initArgs.CreateMutex || initArgs.DestroyMutex || initArgs.LockMutex || initArgs.UnlockMutex )
+ {
+ Log::error( "C_Initialize", "CKR_CANT_LOCK" );
+ rv = CKR_CANT_LOCK;
+ }
+ }
+ else if( initArgs.CreateMutex || initArgs.DestroyMutex || initArgs.LockMutex || initArgs.UnlockMutex )
+ {
+ if( !initArgs.CreateMutex || !initArgs.DestroyMutex || !initArgs.LockMutex || !initArgs.UnlockMutex )
+ {
+ Log::error( "C_Initialize", "CKR_ARGUMENTS_BAD" );
+ rv = CKR_ARGUMENTS_BAD;
+ }
+ else if( !( initArgs.flags & CKF_OS_LOCKING_OK ) )
+ {
+ Log::error( "C_Initialize", "CKR_CANT_LOCK" );
+ rv = CKR_CANT_LOCK;
+ }
+ }
+ }
+
+ if (rv == CKR_OK)
+ {
+ Application::InitApplication( );
+ _isInitialized = TRUE;
+ }
+
+ Log::log( "C_Initialize - isInitialized <%#02x>", _isInitialized );
+
+ Log::logCK_RV( "C_Initialize", rv );
+ Log::end( "C_Initialize" );
+
+ return rv;
+ }
+
+
+ /**
+ * C_Finalize indicates that an application is done with the
+ * Cryptoki library.
+ *
+ * @param pReserved reserved.Should be NULL_PTR
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_Finalize )( CK_VOID_PTR pReserved )
+ {
+ Log::begin( "C_Finalize" );
+ Log::in( "C_Finalize" );
+ Log::log( "C_Finalize - pReserved <%#02x>", pReserved );
+
+ CK_RV rv = CKR_OK;
+
+ // Not Initialized
+ if( !_isInitialized )
+ {
+ Log::error( "C_Finalize", "CKR_CRYPTOKI_NOT_INITIALIZED" );
+ rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ else if( NULL_PTR != pReserved )
+ {
+ Log::error( "C_Finalize", "CKR_ARGUMENTS_BAD" );
+ rv = CKR_ARGUMENTS_BAD;
+ }
+ else
+ {
+ _isInitialized = FALSE;
+ Application::End( );
+ }
+
+ Log::logCK_RV( "C_Finalize", rv );
+ Log::end( "C_Finalize" );
+
+ return rv;
+ }
+
+
+ /**
+ * C_GetInfo returns general information about Cryptoki.
+ *
+ * @param pInfo location that receives information
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_GetInfo )( CK_INFO_PTR pInfo )
+ {
+ Log::begin( "C_GetInfo" );
+ Log::in( "C_GetInfo" );
+ Log::logCK_INFO( "C_GetInfo", pInfo );
+
+ CK_RV rv = CKR_OK;
+ if( FALSE == _isInitialized )
+ {
+ rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+ else if( NULL_PTR == pInfo )
+ {
+ rv = CKR_ARGUMENTS_BAD;
+ }
+ else
+ {
+ pInfo->cryptokiVersion.major = CRYPTOKIVERSION_INTERFACE_MAJOR;
+ pInfo->cryptokiVersion.minor = CRYPTOKIVERSION_INTERFACE_MINOR;
+ pInfo->flags = 0;
+ memset(pInfo->libraryDescription, ' ', sizeof(pInfo->libraryDescription));
+ memcpy(pInfo->libraryDescription, LIBRARY_DESCRIPTION, strlen(LIBRARY_DESCRIPTION));
+ memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID));
+ memcpy(pInfo->manufacturerID, MANUFACTURER_ID, strlen(MANUFACTURER_ID));
+ pInfo->libraryVersion.major = CRYPTOKIVERSION_LIBRARY_MAJOR;
+ pInfo->libraryVersion.minor = CRYPTOKIVERSION_LIBRARY_MINOR;
+ }
+
+ Log::logCK_RV( "C_GetInfo", rv );
+ Log::out( "C_GetInfo" );
+ Log::logCK_INFO( "C_GetInfo", pInfo );
+ Log::end( "C_GetInfo" );
+
+ return rv;
+ }
+
+ /**
+ * C_GetFunctionList returns the function list.
+ *
+ * @param ppFunctionList receives pointer to function list
+ */
+ CK_DEFINE_FUNCTION( CK_RV,C_GetFunctionList )( CK_FUNCTION_LIST_PTR_PTR ppFunctionList )
+ {
+ Log::begin( "C_GetFunctionList" );
+ Log::in( "C_GetFunctionList" );
+ Log::log( "C_GetFunctionList - CK_FUNCTION_LIST_PTR_PTR <%#02x>", ppFunctionList );
+
+ CK_RV rv = CKR_OK;
+ if( NULL_PTR == ppFunctionList )
+ {
+ rv = CKR_ARGUMENTS_BAD;
+ }
+ else
+ {
+ // this is the only function which an application can call before calling C_Initialize
+ *ppFunctionList = (CK_FUNCTION_LIST_PTR)&FunctionList;
+ }
+
+ Log::logCK_RV( "C_GetFunctionList", rv );
+ Log::out( "C_GetFunctionList" );
+ Log::log( "C_GetFunctionList - CK_FUNCTION_LIST_PTR_PTR <%#02x>", ppFunctionList );
+ Log::end( "C_GetFunctionList" );
+
+ return rv;
+ }
+
+
+ /**
+ * C_GetSlotList obtains a list of slots in the system.
+ *
+ * @param tokenPresent only slots with tokens
+ * @param pSlotList receives array of slot IDs
+ * @param pulCount receives number of slots
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_GetSlotList )( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount )
+ {
+ Log::begin( "C_GetSlotList" );
+ Log::in( "C_GetSlotList" );
+ Log::log( "C_GetSlotList - tokenPresent <%d>", tokenPresent );
+ Log::logCK_SLOT_ID_PTR( "C_GetSlotList", pSlotList, pulCount );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Application::Enumerate( tokenPresent, pSlotList, pulCount );
+ }
+ PKCS11_CATCH( rv )
+
+ Log::logCK_RV( "C_GetSlotList", rv );
+ Log::out( "C_GetSlotList" );
+ Log::logCK_SLOT_ID_PTR( "C_GetSlotList", pSlotList, pulCount );
+ Log::end( "C_GetSlotList" );
+
+ return rv;
+ }
+
+
+ /**
+ * C_GetSlotInfo obtains information about a particular slot in
+ * the system.
+ *
+ * @param slotId the ID of the slot
+ * @param pInfo received the slot information
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_GetSlotInfo )( CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo )
+ {
+ Log::begin( "C_GetSlotInfo" );
+ Log::in( "C_GetSlotInfo" );
+ Log::log( "C_GetSlotInfo - slotID <%ld>", slotID );
+ Log::logCK_SLOT_INFO_PTR( "C_GetSlotInfo", pInfo );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ if(Application::_numSlots == 0)
+ {
+ CK_ULONG slotCount = 0;
+ Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+ CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR)malloc(sizeof(CK_SLOT_ID)*slotCount);
+ Application::Enumerate(CK_FALSE,slots,&slotCount);
+ free(slots);
+ }
+
+ Slot* pSlot = NULL_PTR;
+ rv = Application::GetSlotFromSlotId( slotID, &pSlot );
+
+ if(rv == CKR_OK)
+ {
+ rv = pSlot->GetInfo( pInfo );
+ }
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_GetSlotInfo", rv );
+ Log::out( "C_GetSlotInfo" );
+ Log::logCK_SLOT_INFO_PTR( "C_GetSlotInfo", pInfo );
+ Log::end( "C_GetSlotInfo" );
+
+ return rv;
+ }
+
+
+ /**
+ * C_GetTokenInfo obtains information about a particular token
+ * in the system.
+ *
+ * @param slotID ID of the token's slot
+ * @param pInfo receives the token information
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_GetTokenInfo )( CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo )
+ {
+ Log::begin( "C_GetTokenInfo" );
+ Log::in( "C_GetTokenInfo" );
+ Log::log( "C_GetTokenInfo - slotID <%ld>", slotID );
+ Log::logCK_TOKEN_INFO_PTR( "C_GetTokenInfo", pInfo );
+
+ CK_RV rv = CKR_OK;
+
+ PKCS11_TRY
+ {
+ if(Application::_numSlots == 0)
+ {
+ CK_ULONG slotCount = 0;
+ Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+ CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR)malloc(sizeof(CK_SLOT_ID)*slotCount);
+ Application::Enumerate(CK_FALSE,slots,&slotCount);
+ free(slots);
+ }
+
+ Slot* slot = NULL_PTR;
+ rv = Application::GetSlotFromSlotId(slotID,&slot);
+
+ if(rv == CKR_OK)
+ {
+ rv = slot->GetTokenInfo(pInfo);
+ }
+ }
+ //PKCS11_CATCH(rv)
+ catch( CkError & e )
+ {
+ rv = e.Error( );
+ Log::log( "C_GetTokenInfo - ## Error ## CkError <%s> <%#02x>", e.what( ), e.Error( ) );
+ }
+ catch( PcscError & e )
+ {
+ rv = CKR_FUNCTION_FAILED;
+ Log::log( "C_GetTokenInfo - ## Error ## PcscError <%s> <%#02x> <%#02x>", e.what( ), e.Error( ), rv );
+ }
+ catch( Marshaller::Exception & e )
+ {
+ rv = CkError::CheckMarshallerException( e );
+ Log::log( "C_GetTokenInfo - ## Error ## PcscError <%s> <%#02x>", e.what( ), rv );
+ }
+ catch( ... )
+ {
+ rv = CKR_GENERAL_ERROR;
+ Log::log( "C_GetTokenInfo - ## Error ## (...) <%#02x>", rv );
+ }
+
+ Log::logCK_RV( "C_GetTokenInfo", rv );
+ Log::out( "C_GetTokenInfo" );
+ Log::logCK_TOKEN_INFO_PTR( "C_GetTokenInfo", pInfo );
+ Log::end( "C_GetTokenInfo" );
+
+ return rv;
+ }
+
+
+ /**
+ * C_GetMechanismList obtains a list of mechanism types
+ * supported by a token.
+ *
+ * @param slotID ID of token's slot
+ * @param pMechanismList gets mech. array
+ * @param pulCount get number of mechs
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_GetMechanismList )( CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount )
+ {
+ Log::begin( "C_GetMechanismList" );
+ Log::in( "C_GetMechanismList" );
+ Log::log( "C_GetMechanismList - slotID <%#02x>", slotID );
+ Log::logCK_MECHANISM_TYPE( "C_GetMechanismList", pMechanismList, pulCount );
+
+ CK_RV rv = CKR_OK;
+
+ PKCS11_TRY
+ {
+ if(Application::_numSlots == 0)
+ {
+ CK_ULONG slotCount = 0;
+ Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+ CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR)malloc(sizeof(CK_SLOT_ID)*slotCount);
+ Application::Enumerate(CK_FALSE,slots,&slotCount);
+ free(slots);
+ }
+
+ Slot* slot = NULL_PTR;
+ rv = Application::GetSlotFromSlotId(slotID,&slot);
+
+ if(rv == CKR_OK)
+ {
+ rv = slot->GetMechanismList(pMechanismList,pulCount);
+ }
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_GetMechanismList", rv );
+ Log::out( "C_GetMechanismList" );
+ Log::logCK_MECHANISM_TYPE( "C_GetMechanismList", pMechanismList, pulCount );
+ Log::end( "C_GetMechanismList" );
+ return rv;
+ }
+
+
+ /**
+ * C_GetMechanismInfo obtains information about a particular
+ * mechanism possibly supported by a token.
+ *
+ * @param slotID ID of the token's slot
+ * @param type type of mechanism
+ * @param pInfo receives mechanism info
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_GetMechanismInfo )( CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo )
+ {
+ Log::begin( "C_GetMechanismInfo" );
+ Log::in( "C_GetMechanismInfo" );
+ Log::log( "C_GetMechanismInfo - slotID <%#02x>", slotID );
+ Log::logCK_MECHANISM_TYPE( "C_GetMechanismInfo", type );
+ Log::logCK_MECHANISM_INFO_PTR( "C_GetMechanismInfo", pInfo );
+
+ CK_RV rv = CKR_OK;
+
+ PKCS11_TRY
+ {
+ if(Application::_numSlots == 0)
+ {
+ CK_ULONG slotCount = 0;
+ Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+ CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR)malloc(sizeof(CK_SLOT_ID)*slotCount);
+ Application::Enumerate(CK_FALSE,slots,&slotCount);
+ free(slots);
+ }
+
+ Slot* slot = NULL_PTR;
+ rv = Application::GetSlotFromSlotId(slotID,&slot);
+
+ if(rv == CKR_OK)
+ {
+ rv = slot->GetMechanismInfo(type,pInfo);
+ }
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_GetMechanismInfo", rv );
+ Log::out( "C_GetMechanismInfo" );
+ Log::logCK_MECHANISM_INFO_PTR( "C_GetMechanismInfo", pInfo );
+ Log::end( "C_GetMechanismInfo" );
+ return rv;
+ }
+
+
+ /**
+ * C_InitToken initializes a token.
+ *
+ * @param slotID ID of the token's slot
+ * @param pPin the SO's initial PIN
+ * @param ulPinLen length in bytes of the PIN
+ * @param pLabel 32-byte token label (blank padded) pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_InitToken )( CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel )
+ {
+ Log::begin( "C_InitToken" );
+ Log::in( "C_InitToken" );
+ Log::log( "C_InitToken - slotID <%#02x>", slotID );
+ Log::logCK_UTF8CHAR_PTR( "C_InitToken - pPin", pPin, ulPinLen );
+ Log::logCK_UTF8CHAR_PTR( "C_InitToken - pLabel", pLabel, 32 );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ if(Application::_numSlots == 0)
+ {
+ CK_ULONG slotCount = 0;
+ Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+ CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR)malloc(sizeof(CK_SLOT_ID)*slotCount);
+ Application::Enumerate(CK_FALSE,slots,&slotCount);
+ free(slots);
+ }
+
+ Slot* slot = NULL_PTR;
+ rv = Application::GetSlotFromSlotId(slotID,&slot);
+
+ if(rv == CKR_OK)
+ {
+ rv = slot->InitToken(pPin,ulPinLen,pLabel);
+ }
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_InitToken", rv );
+ Log::end( "C_InitToken" );
+ return rv;
+ }
+
+
+ /**
+ * C_InitPIN initializes the normal user's PIN.
+ *
+ * @param hSession the session's handle
+ * @param pPin the noraml user's PIN
+ * @param ulPinLen length in bytes of the PIN
+ */
+ CK_DEFINE_FUNCTION( CK_RV,C_InitPIN )( CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen )
+ {
+ Log::begin( "C_InitPIN" );
+ Log::in( "C_InitPIN" );
+ Log::log( "C_InitPIN - hSession <%#02x>", hSession );
+ Log::logCK_UTF8CHAR_PTR( "C_InitPIN - pPin", pPin, ulPinLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::InitPIN( hSession, pPin, ulPinLen );
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_InitPIN", rv );
+ Log::end( "C_InitPIN" );
+ return rv;
+ }
+
+
+ /**
+ * C_SetPIN modifies the PIN of the user who is logged in.
+ *
+ * @param hSession the session's handle
+ * @param pOldPin the old PIN
+ * @param ulOldPin length of the old PIN
+ * @param pNewPin the new PIN
+ * @param ulNewLen length of the new PIN
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_SetPIN )( CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen )
+ {
+ Log::begin( "C_SetPIN" );
+ Log::in( "C_SetPIN" );
+ Log::log( "C_SetPIN - hSession <%#02x>", hSession );
+ Log::logCK_UTF8CHAR_PTR( "C_SetPIN - pOldPin", pOldPin, ulOldLen );
+ Log::logCK_UTF8CHAR_PTR( "C_SetPIN - pNewPin", pNewPin, ulNewLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::SetPIN( hSession, pOldPin, ulOldLen, pNewPin, ulNewLen );
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_SetPIN", rv );
+ Log::end( "C_SetPIN" );
+ return rv;
+ }
+
+
+ /**
+ * C_OpenSession opens a session between an application and a
+ * token.
+ *
+ * @param slotID the slot's ID
+ * @param flags from CK_SESSION_INFO
+ * @param pApplication passed to callback
+ * @param Notify callback function
+ * @param phSession gets session handle
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_OpenSession )( CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession )
+ {
+ Log::begin( "C_OpenSession" );
+ Log::in( "C_OpenSession" );
+ Log::log( "C_OpenSession - slotID <%#02x>", slotID );
+ Log::logSessionFlags( "C_OpenSession", flags );
+ Log::log( "C_OpenSession - pApplication <%#02x>", pApplication );
+ Log::log( "C_OpenSession - Notify <%#02x>", Notify );
+ Log::log( "C_OpenSession - phSession <%#02x> (%#02x)", phSession, ( ( NULL_PTR != phSession ) ? *phSession : 0 ) );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ if(Application::_numSlots == 0)
+ {
+ CK_ULONG slotCount = 0;
+ Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+ CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR)malloc(sizeof(CK_SLOT_ID)*slotCount);
+ Application::Enumerate(CK_FALSE,slots,&slotCount);
+ free(slots);
+ }
+
+ Slot* slot = NULL_PTR;
+ rv = Application::GetSlotFromSlotId(slotID,&slot);
+
+ if(rv == CKR_OK)
+ {
+ PKCS11_ASSERT(slot != NULL_PTR);
+ rv = slot->OpenSession(flags,pApplication,Notify,phSession);
+ }
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_OpenSession", rv );
+ Log::out( "C_OpenSession" );
+ Log::log( "C_OpenSession - phSession <%#02x> (%ld)", phSession, ( ( NULL_PTR != phSession ) ? *phSession : 0 ) );
+ Log::end( "C_OpenSession" );
+ return rv;
+ }
+
+
+ /**
+ * C_CloseSession closes a session between an application and a
+ * token.
+ *
+ * @param hSession the session's handle
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_CloseSession )( CK_SESSION_HANDLE hSession )
+ {
+ Log::begin( "C_CloseSession" );
+ Log::in( "C_CloseSession" );
+ Log::log( "C_CloseSession - hSession <%#02x>", hSession );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::CloseSession(hSession);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_CloseSession", rv );
+ Log::end( "C_CloseSession" );
+ return rv;
+ }
+
+
+ /**
+ * C_CloseAllSessions closes all sessions with a token.
+ *
+ * @param slotID the token's slot
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_CloseAllSessions )( CK_SLOT_ID slotID )
+ {
+ Log::begin( "C_CloseAllSessions" );
+ Log::in( "C_CloseAllSessions" );
+ Log::log( "C_CloseAllSessions - slotID <%#02x>", slotID );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ if(Application::_numSlots == 0)
+ {
+ CK_ULONG slotCount = 0;
+ Application::Enumerate(CK_FALSE,NULL_PTR,&slotCount);
+ CK_SLOT_ID_PTR slots = (CK_SLOT_ID_PTR)malloc(sizeof(CK_SLOT_ID)*slotCount);
+ Application::Enumerate(CK_FALSE,slots,&slotCount);
+ free(slots);
+ }
+
+ Slot* slot = NULL_PTR;
+ rv = Application::GetSlotFromSlotId(slotID,&slot);
+
+ if(rv == CKR_OK)
+ {
+ rv = slot->CloseAllSessions();
+ }
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_CloseAllSessions", rv );
+ Log::end( "C_CloseAllSessions" );
+ return rv;
+ }
+
+
+ /**
+ * C_GetSessionInfo obtains information about the session.
+ *
+ * @param hSession the session's handle
+ * @param receives session info
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_GetSessionInfo )( CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo )
+ {
+ Log::begin( "C_GetSessionInfo" );
+ Log::in( "C_GetSessionInfo" );
+ Log::log( "C_GetSessionInfo - hSession <%#02x>", hSession );
+ Log::logCK_SESSION_INFO_PTR( "C_GetSessionInfo", pInfo );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::GetSessionInfo(hSession,pInfo);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_GetSessionInfo", rv );
+ Log::out( "C_GetSessionInfo" );
+ Log::logCK_SESSION_INFO_PTR( "C_GetSessionInfo", pInfo );
+ Log::end( "C_GetSessionInfo" );
+ return rv;
+ }
+
+
+ /**
+ * C_GetOperationState obtains the state of the cryptographic operation
+ * in a session.
+ *
+ * @param hSession session's handle
+ * @param pOperationState gets State
+ * @param pulOperationStateLen gets state length
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_GetOperationState )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR )
+ {
+ Log::begin( "C_GetOperationState" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+ Log::logCK_RV( "C_GetOperationState", rv );
+ Log::end( "C_GetOperationState" );
+ return rv;
+ }
+
+
+ /**
+ * C_SetOperationState restores the state of the cryptographic
+ * operation in a session.
+ *
+ * @param hSession session's handle
+ * @param pOperationState hold state
+ * @param ulOperationStateLen holds state length
+ * @param hEncryptionKey en/decryption key
+ * @param hAuthenticationKey sig/verify key
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_SetOperationState )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE )
+ {
+ Log::begin( "C_SetOperationState" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+ Log::logCK_RV( "C_SetOperationState", rv );
+ Log::end( "C_SetOperationState" );
+ return rv;
+ }
+
+ /**
+ * C_Login logs a user into a token.
+ *
+ * @param hSession the session's handle
+ * @param userType the user type
+ * @param pPin the user's PIN
+ * @param ulPinLen the length of the PIN
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_Login )( CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen )
+ {
+ Log::begin( "C_Login" );
+ Log::in( "C_Login" );
+ Log::log( "C_Login - hSession <%#02x>", hSession );
+ Log::logCK_USER_TYPE( "C_Login", userType );
+ Log::logCK_UTF8CHAR_PTR( "C_Login - pPin", pPin, ulPinLen );
+ Log::log( "C_Login - ulPinLen <%ld>", ulPinLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::Login(hSession,userType,pPin,ulPinLen);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_Login", rv );
+ Log::end( "C_Login" );
+ return rv;
+ }
+
+
+ /**
+ * C_Logout logs a user out from a token.
+ *
+ * @param hSession the session's handle
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_Logout )( CK_SESSION_HANDLE hSession )
+ {
+ Log::begin( "C_Logout" );
+ Log::in( "C_Logout" );
+ Log::log( "C_Logout - hSession <%#02x>", hSession );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::Logout(hSession);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_Logout", rv );
+ Log::end( "C_Logout" );
+ return rv;
+ }
+
+
+ /**
+ * C_CreateObject creates a new object.
+ *
+ * @param hSession the session's handle
+ * @param pTemplate the object's template
+ * @param ulCount attributes in template
+ * @param phObject gets new object's handle.
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_CreateObject )( CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject )
+ {
+ Log::begin( "C_CreateObject" );
+ Log::in( "C_CreateObject" );
+ Log::log( "C_CreateObject - hSession <%#02x>", hSession );
+ Log::logCK_ATTRIBUTE_PTR( "C_CreateObject", pTemplate, ulCount );
+ Log::log( "C_CreateObject - phObject <%#02x>", phObject );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::CreateObject( hSession, pTemplate, ulCount, phObject );
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_CreateObject", rv );
+ Log::out( "C_CreateObject" );
+ Log::log( "C_CreateObject - phObject <%#02x> (%ld)", phObject, ( ( NULL_PTR != phObject ) ? *phObject : 0 ) );
+ Log::end( "C_CreateObject" );
+ return rv;
+ }
+
+
+ /* C_CopyObject copies an object, creating a new object for the
+ * copy. */
+ CK_DEFINE_FUNCTION(CK_RV,C_CopyObject )( CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR )
+ {
+ Log::begin( "C_CopyObject" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_CopyObject", rv );
+ Log::end( "C_CopyObject" );
+ return rv;
+ }
+
+
+ /**
+ * C_DestroyObject destroys an object.
+ *
+ * @param hSession the session's handle
+ * @param hObject the object's handle
+ *
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_DestroyObject )( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject )
+ {
+ Log::begin( "C_DestroyObject" );
+ Log::in( "C_DestroyObject" );
+ Log::log( "C_DestroyObject - hSession <%#02x>", hSession );
+ Log::log( "C_DestroyObject - hObject <%#02x>", hObject );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::DestroyObject( hSession, hObject );
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_DestroyObject", rv );
+ Log::end( "C_DestroyObject" );
+ return rv;
+ }
+
+
+ /* C_GetObjectSize gets the size of an object in bytes. */
+ CK_DEFINE_FUNCTION( CK_RV, C_GetObjectSize )( CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ULONG_PTR )
+ {
+ Log::begin( "C_GetObjectSize" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_GetObjectSize", rv );
+ Log::end( "C_GetObjectSize" );
+ return rv;
+ }
+
+
+ /**
+ * C_GetAttributeValue obtains the value of one or more object
+ * attributes.
+ *
+ * @param hSession the session's handle
+ * @param hObject the object's handle
+ * @param pTemplate specifies attrs; gets vals
+ * @param ulCount attributes in template
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_GetAttributeValue )( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+ {
+ Log::begin( "C_GetAttributeValue" );
+ Log::in( "C_GetAttributeValue" );
+ Log::log( "C_GetAttributeValue - hSession <%#02x>", hSession );
+ Log::logCK_ATTRIBUTE_PTR( "C_GetAttributeValue", pTemplate, ulCount );
+ Log::log( "C_GetAttributeValue - hObject <%#02x>", hObject );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::GetAttributeValue(hSession,hObject,pTemplate,ulCount);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_GetAttributeValue", rv );
+ Log::out( "C_GetAttributeValue" );
+ Log::logCK_ATTRIBUTE_PTR( "C_GetAttributeValue", pTemplate, ulCount );
+ Log::end( "C_GetAttributeValue" );
+ return rv;
+ }
+
+
+ /**
+ * C_SetAttributeValue modifies the value of one or more object
+ * attributes
+ *
+ * @param hSession the session's handle
+ * @param hObject the object's handle
+ * @param pTemplate specifies attrs and values
+ * @param ulCount attributes in template
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_SetAttributeValue )( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+ {
+ Log::begin( "C_SetAttributeValue" );
+ Log::in( "C_SetAttributeValue" );
+ Log::log( "C_SetAttributeValue - hSession <%#02x>", hSession );
+ Log::logCK_ATTRIBUTE_PTR( "C_SetAttributeValue", pTemplate, ulCount );
+ Log::log( "C_SetAttributeValue - hObject <%#02x>", hObject );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::SetAttributeValue( hSession, hObject, pTemplate, ulCount );
+ }
+ PKCS11_CATCH( rv )
+
+ Log::logCK_RV( "C_SetAttributeValue", rv );
+ Log::end( "C_SetAttributeValue" );
+ return rv;
+ }
+
+
+ /**
+ * C_FindObjectsInit initializes a search for token and session
+ * objects that match a template.
+ *
+ * @param hSession the session's handle
+ * @param pTemplate attribute values to match
+ * @param ulCount atrs in search template
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_FindObjectsInit )( CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+ {
+ Log::begin( "C_FindObjectsInit" );
+ Log::in( "C_FindObjectsInit" );
+ Log::log( "C_FindObjectsInit - hSession <%#02x>", hSession );
+ Log::logCK_ATTRIBUTE_PTR( "C_FindObjectsInit", pTemplate, ulCount );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::FindObjectsInit(hSession,pTemplate,ulCount);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_FindObjectsInit", rv );
+ Log::end( "C_FindObjectsInit" );
+ return rv;
+ }
+
+
+ /**
+ * C_FindObjects continues a search for token and session
+ * objects that match a template, obtaining additional object
+ * handles.
+ *
+ * @param hSession session's handle
+ * @param phObject gets obj. handles
+ * @param ulMaxObjectCount max handles to get
+ * @param pulObjectCount actual # returned
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_FindObjects )(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount )
+ {
+ Log::begin( "C_FindObjects" );
+ Log::in( "C_FindObjects" );
+ Log::log( "C_FindObjects - hSession <%#02x>", hSession );
+ Log::log( "C_FindObjects - phObject <%#02x> (%#02x)", phObject, ( ( NULL_PTR != phObject ) ? *phObject : 0 ) );
+ Log::log( "C_FindObjects - ulMaxObjectCount <%#02x>", ulMaxObjectCount );
+ Log::log( "C_FindObjects - pulObjectCount <%#02x> (%#02x)", pulObjectCount, ( ( NULL_PTR != pulObjectCount ) ? *pulObjectCount : 0 ) );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::FindObjects( hSession, phObject, ulMaxObjectCount, pulObjectCount );
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_FindObjects", rv );
+ Log::out( "C_FindObjects" );
+ Log::log( "C_FindObjects - phObject <%#02x> (%#02x)", phObject, ( ( NULL_PTR != phObject ) ? *phObject : 0 ) );
+ Log::log( "C_FindObjects - pulObjectCount <%#02x> (%#02x)", pulObjectCount, ( ( NULL_PTR != pulObjectCount ) ? *pulObjectCount : 0 ) );
+ Log::end( "C_FindObjects" );
+ return rv;
+ }
+
+
+ /**
+ * C_FindObjectsFinal finishes a search for token and session
+ * objects.
+ *
+ * @param hSession the session's handle
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_FindObjectsFinal )( CK_SESSION_HANDLE hSession )
+ {
+ Log::begin( "C_FindObjectsFinal" );
+ Log::in( "C_FindObjectsFinal" );
+ Log::log( "C_FindObjectsFinal - hSession <%#02x>", hSession );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::FindObjectsFinal(hSession);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_FindObjectsFinal", rv );
+ Log::end( "C_FindObjectsFinal" );
+ return rv;
+ }
+
+
+ /**
+ * C_EncryptInit initializes an encryption operation.
+ *
+ * @param hSession the session's handle
+ * @param pMechanism the encryption mechanism
+ * @param hKey handle of encryption key
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_EncryptInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey )
+ {
+ Log::begin( "C_EncryptInit" );
+ Log::in( "C_EncryptInit" );
+ Log::log( "C_EncryptInit - hSession <%#02x>", hSession );
+ Log::logCK_MECHANISM_PTR( "C_EncryptInit", pMechanism );
+ Log::log( "C_EncryptInit - hKey <%#02x>", hKey );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::EncryptInit(hSession,pMechanism,hKey);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_EncryptInit", rv );
+ Log::end( "C_EncryptInit" );
+ return rv;
+ }
+
+
+ /**
+ * C_Encrypt encrypts single-part data.
+ *
+ * @param hSession session's handle
+ * @param pData the plaintext data
+ * @param ulDataLen bytes of plaintext
+ * @param pEncryptedData gets ciphertext
+ * @param pulEncryptedData Len gets c-text size
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_Encrypt )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen )
+ {
+ Log::begin( "C_Encrypt" );
+ Log::in( "C_Encrypt" );
+ Log::log( "C_Encrypt - hSession <%#02x>", hSession );
+ Log::logCK_UTF8CHAR_PTR( "C_Encrypt - pData", pData, ulDataLen );
+ Log::logCK_UTF8CHAR_PTR( "C_Encrypt - pEncryptedData", pEncryptedData, (NULL_PTR == pulEncryptedDataLen) ? 0 : *pulEncryptedDataLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::Encrypt( hSession, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen );
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_Encrypt", rv );
+ Log::out( "C_Encrypt" );
+ Log::logCK_UTF8CHAR_PTR( "C_Encrypt - pEncryptedData", pEncryptedData, (NULL_PTR == pulEncryptedDataLen) ? 0 : *pulEncryptedDataLen );
+ Log::end( "C_Encrypt" );
+ return rv;
+ }
+
+
+ /**
+ * C_EncryptUpdate continues a multiple-part encryption
+ * operation.
+ *
+ * @param hSession session's handle
+ * @param pPart the plaintext data
+ * @param ulPartLen plaintext data len
+ * @param pEncryptedPart gets ciphertext
+ * @param pulEncryptedPartLen gets c-text size
+ *
+ */
+ CK_DEFINE_FUNCTION(CK_RV,C_EncryptUpdate)( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+ {
+ Log::begin( "C_EncryptUpdate" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_EncryptUpdate", rv );
+ Log::end( "C_EncryptUpdate" );
+ return rv;
+ }
+
+
+ /**
+ * C_EncryptFinal finishes a multiple-part encryption
+ * operation.
+ *
+ * @param hSession session handle
+ * @param pLastEncryptedPart last c-text
+ * @param pulLastEncryptedPartLen gets last size
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_EncryptFinal )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR )
+ {
+ Log::begin( "C_EncryptFinal" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_EncryptFinal", rv );
+ Log::end( "C_EncryptFinal" );
+ return rv;
+ }
+
+
+ /**
+ * C_DecryptInit initializes a decryption operation.
+ *
+ * @param hSession the session's handle
+ * @param pMechanism the decryption mechanism
+ * @param hKey handle of decrypting key
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_DecryptInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey )
+ {
+ Log::begin( "C_DecryptInit" );
+ Log::in( "C_DecryptInit" );
+ Log::log( "C_DecryptInit - hSession <%#02x>", hSession );
+ Log::logCK_MECHANISM_PTR( "C_DecryptInit", pMechanism );
+ Log::log( "C_DecryptInit - hKey <%#02x>", hKey );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::DecryptInit( hSession, pMechanism, hKey );
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_DecryptInit", rv );
+ Log::end( "C_DecryptInit" );
+ return rv;
+ }
+
+
+
+ /**
+ * C_Decrypt decrypts encrypted data in a single part.
+ *
+ * @param hSession session's handle
+ * @param pEncryptedData ciphertext
+ * @param ulEncryptedDataLen ciphertext length
+ * @param pData gets plaintext
+ * @param pulDataLen gets p-text size
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_Decrypt )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen )
+ {
+ Log::begin( "C_Decrypt" );
+ Log::in( "C_Decrypt" );
+ Log::log( "C_Decrypt - hSession <%#02x>", hSession );
+ Log::logCK_UTF8CHAR_PTR( "C_Decrypt - pEncryptedData", pEncryptedData, ulEncryptedDataLen );
+ Log::logCK_UTF8CHAR_PTR( "C_Decrypt - pData", pData, (NULL_PTR == pulDataLen) ? 0 : *pulDataLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::Decrypt(hSession,pEncryptedData,ulEncryptedDataLen,pData,pulDataLen);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_Decrypt", rv );
+ Log::out( "C_Decrypt" );
+ Log::logCK_UTF8CHAR_PTR( "C_Decrypt - pData", pData, (NULL_PTR == pulDataLen) ? 0 : *pulDataLen );
+ Log::end( "C_Decrypt" );
+ return rv;
+ }
+
+
+ /**
+ * C_DecryptUpdate continues a multiple-part decryption
+ * operation.
+ *
+ * @param hSession session's handle
+ * @param pEncryptedPart encrypted data
+ * @param ulEncryptedPart input length
+ * @param pPart gets plaintext
+ * @param pulPartLen p-text size
+ */
+ CK_DEFINE_FUNCTION(CK_RV,C_DecryptUpdate)( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+ {
+ Log::begin( "C_DecryptUpdate" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_DecryptUpdate", rv );
+ Log::end( "C_DecryptUpdate" );
+ return rv;
+ }
+
+
+ /**
+ * C_DecryptFinal finishes a multiple-part decryption
+ * operation.
+ *
+ * @param hSession the session's handle
+ * @param pLastPart gets plaintext
+ * @param pulLastPartLen p-text size
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_DecryptFinal )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR )
+ {
+ Log::begin( "C_DecryptFinal" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_DecryptFinal", rv );
+ Log::end( "C_DecryptFinal" );
+ return rv;
+ }
+
+
+ /**
+ * C_DigestInit initializes a message-digesting operation.
+ *
+ * @param hSession the session's handle
+ * @param pMechanism the digesting mechanism
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_DigestInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism )
+ {
+ Log::begin( "C_DigestInit" );
+ Log::in( "C_DigestInit" );
+ Log::log( "C_DigestInit - hSession <%#02x>", hSession );
+ Log::logCK_MECHANISM_PTR( "C_DigestInit", pMechanism );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::DigestInit(hSession,pMechanism);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_DigestInit", rv );
+ Log::end( "C_DigestInit" );
+ return rv;
+ }
+
+
+ /**
+ * C_Digest digests data in a single part.
+ *
+ * @param hSession the session's handle
+ * @param pData data to be digested
+ * @param ulDataLen bytes of data to digest
+ * @param pDigest gets the message digest
+ * @param pulDigestLen gets digest length
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_Digest )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen )
+ {
+ Log::begin( "C_Digest" );
+ Log::in( "C_Digest" );
+ Log::log( "C_Digest - hSession <%#02x>", hSession );
+ Log::logCK_UTF8CHAR_PTR( "C_Digest - pData", pData, ulDataLen );
+ Log::logCK_UTF8CHAR_PTR( "C_Digest - pDigest", pDigest, (NULL_PTR == pulDigestLen) ? 0 : *pulDigestLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::Digest( hSession, pData, ulDataLen, pDigest, pulDigestLen );
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_Digest", rv );
+ Log::out( "C_Digest" );
+ Log::logCK_UTF8CHAR_PTR( "C_Digest - pDigest", pDigest, (NULL_PTR == pulDigestLen) ? 0 : *pulDigestLen );
+ Log::end( "C_Digest" );
+ return rv;
+ }
+
+
+ /**
+ * C_DigestUpdate continues a multiple-part message-digesting
+ * operation.
+ *
+ * @param hSession the session's handle
+ * @param pPart data to be digested
+ * @param ulPartLen bytes of data to be digested
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_DigestUpdate )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen )
+ {
+ Log::begin( "C_DigestUpdate" );
+ Log::in( "C_DigestUpdate" );
+ Log::log( "C_DigestUpdate - hSession <%#02x>", hSession );
+ Log::logCK_UTF8CHAR_PTR( "C_DigestUpdate - pPart", pPart, ulPartLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::DigestUpdate( hSession, pPart, ulPartLen );
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_DigestUpdate", rv );
+ Log::end( "C_DigestUpdate" );
+ return rv;
+ }
+
+
+ /* C_DigestKey continues a multi-part message-digesting
+ * operation, by digesting the value of a secret key as part of
+ * the data already digested. */
+ CK_DEFINE_FUNCTION( CK_RV, C_DigestKey )( CK_SESSION_HANDLE, CK_OBJECT_HANDLE )
+ {
+ Log::begin( "C_DigestKey" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_DigestKey", rv );
+ Log::end( "C_DigestKey" );
+ return rv;
+ }
+
+
+ /**
+ * C_DigestFinal finishes a multiple-part message-digesting
+ * operation.
+ *
+ * @param hSession the session's handle
+ * @param pDigest gets the message digest
+ * @param pulDigestLen gets byte count of digest
+ *
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_DigestFinal )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen )
+ {
+ Log::begin( "C_DigestFinal" );
+ Log::in( "C_DigestFinal" );
+ Log::log( "C_DigestFinal - hSession <%#02x>", hSession );
+ Log::logCK_UTF8CHAR_PTR( "C_DigestFinal - pDigest", pDigest, (NULL_PTR == pulDigestLen) ? 0 : *pulDigestLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::DigestFinal( hSession, pDigest, pulDigestLen );
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_DigestFinal", rv );
+ Log::out( "C_DigestFinal" );
+ Log::logCK_UTF8CHAR_PTR( "C_DigestFinal - pDigest", pDigest, (NULL_PTR == pulDigestLen) ? 0 : *pulDigestLen );
+ Log::end( "C_DigestFinal" );
+ return rv;
+ }
+
+
+ /**
+ * C_SignInit initializes a signature (private key encryption)
+ * operation, where the signature is (will be) an appendix to
+ * the data, and plaintext cannot be recovered from the
+ * signature.
+ *
+ * @param hSession the session's handle
+ * @param pMechanism the signature mechanism
+ * @param hKey handle of signature key
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_SignInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey )
+ {
+ Log::begin( "C_SignInit" );
+ Log::in( "C_SignInit" );
+ Log::log( "C_SignInit - hSession <%#02x>", hSession );
+ Log::logCK_MECHANISM_PTR( "C_SignInit", pMechanism );
+ Log::log( "C_SignInit - hKey <%#02x>", hKey );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::SignInit(hSession,pMechanism,hKey);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_SignInit", rv );
+ Log::end( "C_SignInit" );
+ return rv;
+ }
+
+
+ /**
+ * C_Sign signs (encrypts with private key) data in a single
+ * part, where the signature is (will be) an appendix to the
+ * data, and plaintext cannot be recovered from the signature.
+ *
+ * @param hSession the session's handle
+ * @param pData the data to sign
+ * @param ulDataLen count of bytes to sign
+ * @param pSignature gets the signature
+ * @param pulSignatureLen gets signature length
+ *
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_Sign )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen )
+ {
+ Log::begin( "C_Sign" );
+ Log::in( "C_Sign" );
+ Log::log( "C_Sign - hSession <%#02x>", hSession );
+ Log::logCK_UTF8CHAR_PTR( "C_Sign - pData", pData, ulDataLen );
+ Log::logCK_UTF8CHAR_PTR( "C_Sign - pSignature", pSignature, (NULL_PTR == pulSignatureLen) ? 0 : *pulSignatureLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::Sign( hSession, pData, ulDataLen, pSignature, pulSignatureLen );
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_Sign", rv );
+ Log::out( "C_Sign" );
+ Log::logCK_UTF8CHAR_PTR( "C_Sign - pSignature", pSignature, (NULL_PTR == pulSignatureLen) ? 0 : *pulSignatureLen );
+ Log::end( "C_Sign" );
+ return rv;
+ }
+
+
+ /**
+ * C_SignUpdate continues a multiple-part signature operation,
+ * where the signature is (will be) an appendix to the data,
+ * and plaintext cannot be recovered from the signature.
+ *
+ * @param hSession the session's handle
+ * @param pPart the data to sign
+ * @param ulPartLen count of bytes to sign
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_SignUpdate )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen )
+ {
+ Log::begin( "C_SignUpdate" );
+ Log::in( "C_SignUpdate" );
+ Log::log( "C_SignUpdate - hSession <%#02x>", hSession );
+ Log::logCK_UTF8CHAR_PTR( "C_SignUpdate - pPart", pPart, ulPartLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::SignUpdate(hSession,pPart,ulPartLen);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_SignUpdate", rv );
+ Log::end( "C_SignUpdate" );
+ return rv;
+ }
+
+
+ /**
+ * C_SignFinal finishes a multiple-part signature operation,
+ * returning the signature.
+ *
+ * @param hSession the session's handle
+ * @param pSignature gets the signature
+ * @param pulSignatureLen gets signature length
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_SignFinal )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen )
+ {
+ Log::begin( "C_SignFinal" );
+ Log::in( "C_SignFinal" );
+ Log::log( "C_SignFinal - hSession <%#02x>", hSession );
+ Log::logCK_UTF8CHAR_PTR( "C_SignFinal - pSignature", pSignature, (NULL_PTR == pulSignatureLen) ? 0 : *pulSignatureLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::SignFinal(hSession,pSignature,pulSignatureLen);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_SignFinal", rv );
+ Log::out( "C_SignFinal" );
+ Log::logCK_UTF8CHAR_PTR( "C_SignFinal - pSignature", pSignature, (NULL_PTR == pulSignatureLen) ? 0 : *pulSignatureLen );
+ Log::end( "C_SignFinal" );
+ return rv;
+ }
+
+
+ /* C_SignRecoverInit initializes a signature operation, where
+ * the data can be recovered from the signature. */
+ CK_DEFINE_FUNCTION( CK_RV, C_SignRecoverInit )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE )
+ {
+ Log::begin( "C_SignRecoverInit" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_SignRecoverInit", rv );
+ Log::end( "C_SignRecoverInit" );
+ return rv;
+ }
+
+
+ /* C_SignRecover signs data in a single operation, where the data can be recovered from the signature. */
+ CK_DEFINE_FUNCTION( CK_RV, C_SignRecover )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+ {
+ Log::begin( "C_SignRecover" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_SignRecover", rv );
+ Log::end( "C_SignRecover" );
+ return rv;
+ }
+
+
+ /**
+ * C_VerifyInit initializes a verification operation, where the
+ * signature is an appendix to the data, and plaintext cannot
+ * cannot be recovered from the signature (e.g. DSA).
+ *
+ * @param hSession the session's handle
+ * @param pMechanism the verification mechanism
+ * @param hKey verification key
+ *
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_VerifyInit )( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey )
+ {
+ Log::begin( "C_VerifyInit" );
+ Log::in( "C_VerifyInit" );
+ Log::log( "C_VerifyInit - hSession <%#02x>", hSession );
+ Log::logCK_MECHANISM_PTR( "C_VerifyInit", pMechanism );
+ Log::log( "C_VerifyInit - hKey <%#02x>", hKey );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::VerifyInit( hSession, pMechanism, hKey );
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_VerifyInit", rv );
+ Log::end( "C_VerifyInit" );
+ return rv;
+ }
+
+
+ /**
+ * C_Verify verifies a signature in a single-part operation,
+ * where the signature is an appendix to the data, and plaintext
+ * cannot be recovered from the signature.
+ *
+ * @param hSession the session's handle
+ * @param pData signed data
+ * @param ulDataLen length of signed data
+ * @param pSignature signature
+ * @param ulSignatureLen signature length
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_Verify )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen )
+ {
+ Log::begin( "C_Verify" );
+ Log::in( "C_Verify" );
+ Log::log( "C_Verify - hSession <%#02x>", hSession );
+ Log::logCK_UTF8CHAR_PTR( "C_Verify - pData", pData, ulDataLen );
+ Log::logCK_UTF8CHAR_PTR( "C_Verify - pSignature", pSignature, ulSignatureLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::Verify(hSession,pData,ulDataLen,pSignature,ulSignatureLen);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_Verify", rv );
+ Log::out( "C_Verify" );
+ Log::logCK_UTF8CHAR_PTR( "C_Verify - pSignature", pSignature, ulSignatureLen );
+ Log::end( "C_Verify" );
+ return rv;
+ }
+
+
+ /* C_VerifyUpdate continues a multiple-part verification
+ * operation, where the signature is an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+ CK_DEFINE_FUNCTION( CK_RV, C_VerifyUpdate )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen )
+ {
+ Log::begin( "C_VerifyUpdate" );
+ Log::in( "C_VerifyUpdate" );
+ Log::log( "C_VerifyUpdate - hSession <%#02x>", hSession );
+ Log::logCK_UTF8CHAR_PTR( "C_VerifyUpdate - pPart", pPart, ulPartLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::VerifyUpdate(hSession,pPart,ulPartLen);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_VerifyUpdate", rv );
+ Log::end( "C_VerifyUpdate" );
+ return rv;
+ }
+
+
+ /* C_VerifyFinal finishes a multiple-part verification
+ * operation, checking the signature. */
+ CK_DEFINE_FUNCTION( CK_RV, C_VerifyFinal )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen )
+ {
+ Log::begin( "C_VerifyFinal" );
+ Log::in( "C_VerifyFinal" );
+ Log::log( "C_VerifyFinal - hSession <%#02x>", hSession );
+ Log::logCK_UTF8CHAR_PTR( "C_VerifyFinal - pSignature", pSignature, ulSignatureLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::VerifyFinal(hSession,pSignature,ulSignatureLen);
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_VerifyFinal", rv );
+ Log::end( "C_VerifyFinal" );
+ return rv;
+ }
+
+
+ /* C_VerifyRecoverInit initializes a signature verification
+ * operation, where the data is recovered from the signature. */
+ CK_DEFINE_FUNCTION( CK_RV, C_VerifyRecoverInit )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE )
+ {
+ Log::begin( "C_VerifyRecoverInit" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_VerifyRecoverInit", rv );
+ Log::end( "C_VerifyRecoverInit" );
+ return rv;
+ }
+
+
+ /* C_VerifyRecover verifies a signature in a single-part
+ * operation, where the data is recovered from the signature. */
+ CK_DEFINE_FUNCTION( CK_RV, C_VerifyRecover )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+ {
+ Log::begin( "C_VerifyRecover" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_VerifyRecover", rv );
+ Log::end( "C_VerifyRecover" );
+ return rv;
+ }
+
+
+ /* C_DigestEncryptUpdate continues a multiple-part digesting and encryption operation. */
+ CK_DEFINE_FUNCTION( CK_RV, C_DigestEncryptUpdate )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+ {
+ Log::begin( "C_DigestEncryptUpdate" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_DigestEncryptUpdate", rv );
+ Log::end( "C_DigestEncryptUpdate" );
+ return rv;
+ }
+
+
+ /* C_DecryptDigestUpdate continues a multiple-part decryption and digesting operation. */
+ CK_DEFINE_FUNCTION( CK_RV, C_DecryptDigestUpdate )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+ {
+ Log::begin( "C_DecryptDigestUpdate" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_DecryptDigestUpdate", rv );
+ Log::end( "C_DecryptDigestUpdate" );
+ return rv;
+ }
+
+
+ /* C_SignEncryptUpdate continues a multiple-part signing and encryption operation. */
+ CK_DEFINE_FUNCTION( CK_RV, C_SignEncryptUpdate )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR )
+ {
+ Log::begin( "C_SignEncryptUpdate" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_SignEncryptUpdate", rv );
+ Log::end( "C_SignEncryptUpdate" );
+ return rv;
+ }
+
+
+ /**
+ * C_DecryptVerifyUpdate continues a multiple-part decryption and verify operation. */
+ CK_DEFINE_FUNCTION( CK_RV, C_DecryptVerifyUpdate )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR , CK_ULONG_PTR )
+ {
+ Log::begin( "C_DecryptVerifyUpdate" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_DecryptVerifyUpdate", rv );
+ Log::end( "C_DecryptVerifyUpdate" );
+ return rv;
+ }
+
+
+ /**
+ * C_GenerateKey generates a secret key, creating a new key object.
+ *
+ * @param hSession, the session's handle
+ * @param pMechanism key generation mech.
+ * @param pTemplate template for new key
+ * @param ulCount # of attrs in template
+ * @param phKey gets handle of new key
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_GenerateKey )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR )
+ {
+ Log::begin( "C_GenerateKey" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_GenerateKey", rv );
+ Log::end( "C_GenerateKey" );
+ return rv;
+ }
+
+
+ /**
+ * C_GenerateKeyPair generates a public-key/private-key pair,
+ * creating new key objects.
+ *
+ * @param hSession, session handle
+ * @param pMechanism, key-gen mech.
+ * @param pPublicKeyTemplate, template for pub. key
+ * @param ulPublicKeyAttributeCount, # pub. attrs.
+ * @param pPrivateKeyTemplate, template for priv. key
+ * @param ulPrivateKeyAttributeCount, # priv. attrs.
+ * @param phPublicKey, gets pub. key handle
+ * @param phPrivateKey gets priv key handle
+ *
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_GenerateKeyPair )(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey )
+ {
+ Log::begin( "C_GenerateKeyPair" );
+ Log::in( "C_GenerateKeyPair" );
+ Log::log( "C_GenerateKeyPair - hSession <%#02x>", hSession );
+ Log::logCK_MECHANISM_PTR( "C_GenerateKeyPair", pMechanism );
+ Log::logCK_ATTRIBUTE_PTR( "C_GenerateKeyPair", pPublicKeyTemplate, ulPublicKeyAttributeCount );
+ Log::logCK_ATTRIBUTE_PTR( "C_GenerateKeyPair", pPrivateKeyTemplate, ulPrivateKeyAttributeCount );
+ Log::log( "C_GenerateKeyPair - phPublicKey <%#02x>", (phPublicKey == NULL_PTR) ? 0 : *phPublicKey );
+ Log::log( "C_GenerateKeyPair - phPrivateKey <%#02x>", (phPrivateKey == NULL_PTR) ? 0 : *phPrivateKey );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::GenerateKeyPair( hSession, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey );
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_GenerateKeyPair", rv );
+ Log::out( "C_GenerateKeyPair" );
+ Log::log( "C_GenerateKeyPair - phPublicKey <%#02x>", (phPublicKey == NULL_PTR) ? 0 : *phPublicKey );
+ Log::log( "C_GenerateKeyPair - phPrivateKey <%#02x>", (phPrivateKey == NULL_PTR) ? 0 : *phPrivateKey );
+ Log::end( "C_GenerateKeyPair" );
+ return rv;
+ }
+
+
+ /**
+ * C_WrapKey wraps (i.e., encrypts) a key.
+ *
+ * @param hSession the session's handle
+ * @param pMechanism the wrapping mechanism
+ * @param hWrappingKey wrapping key
+ * @param hKey key to be wrapped
+ * @param pWrapperKey gets wrapped key
+ * @param pulWrappedKeyLen gets wrapped key size
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_WrapKey )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR )
+ {
+ Log::begin( "C_WrapKey" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_WrapKey", rv );
+ Log::end( "C_WrapKey" );
+ return rv;
+ }
+
+
+ /**
+ * C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
+ * key object.
+ *
+ * @param hSession session's handle
+ * @param pMechanism unwrapping mech.
+ * @param hUnwrappingKey unwrapping key
+ * @param pWrappedKey the wrapped key
+ * @param ulWrappedKeyLen wrapped key len
+ * @param pTemplate new key template
+ * @param ulAttributeCount template length
+ * @param phKey gets new handle
+ *
+ */
+ CK_DEFINE_FUNCTION( CK_RV,C_UnwrapKey )(CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR )
+ {
+ Log::begin( "C_UnwrapKey" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_UnwrapKey", rv );
+ Log::end( "C_UnwrapKey" );
+ return rv;
+ }
+
+
+ /**
+ * C_DeriveKey derives a key from a base key, creating a new key
+ * object.
+ *
+ * @param hSession session's handle
+ * @param pMechanism key deriv. mech.
+ * @param hBaseKey base key
+ * @param pTemplate new key template
+ * @param ulAttributeCount template length
+ * @param phKey gets new handle
+ *
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_DeriveKey )( CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR )
+ {
+ Log::begin( "C_DeriveKey" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_DeriveKey", rv );
+ Log::end( "C_DeriveKey" );
+ return rv;
+ }
+
+
+ /**
+ * C_SeedRandom mixes additional seed material into the token's
+ * random number generator.
+ *
+ * @param hSession the session's handle
+ * @param pSeed the seed material
+ * @param ulSeedLen length of seed material
+ */
+ CK_DEFINE_FUNCTION( CK_RV,C_SeedRandom )( CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG )
+ {
+ Log::begin( "C_SeedRandom" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_RANDOM_SEED_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_SeedRandom", rv );
+ Log::end( "C_SeedRandom" );
+ return rv;
+ }
+
+
+ /**
+ * C_GenerateRandom generates random data.
+ *
+ * @param hSession the session's handle
+ * @param RandomData receives the random data
+ * @param ulRandomLen # of bytes to generate
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_GenerateRandom )( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen )
+ {
+ Log::begin( "C_GenerateRandom" );
+ Log::in( "C_GenerateRandom" );
+ Log::logCK_UTF8CHAR_PTR( "C_GenerateRandom", pRandomData, ulRandomLen );
+
+ CK_RV rv = CKR_OK;
+ PKCS11_TRY
+ {
+ rv = Slot::GenerateRandom( hSession, pRandomData, ulRandomLen );
+ }
+ PKCS11_CATCH(rv)
+
+ Log::logCK_RV( "C_GenerateRandom", rv );
+ Log::out( "C_GenerateRandom" );
+ Log::logCK_UTF8CHAR_PTR( "C_GenerateRandom", pRandomData, ulRandomLen );
+ Log::end( "C_GenerateRandom" );
+ return rv;
+ }
+
+
+ /**
+ * C_GetFunctionStatus is a legacy function; it obtains an
+ * updated status of a function running in parallel with an
+ * application.
+ *
+ * @param hSession the session's handle
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_GetFunctionStatus )( CK_SESSION_HANDLE )
+ {
+ Log::begin( "C_GetFunctionStatus" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_GetFunctionStatus", rv );
+ Log::end( "C_GetFunctionStatus" );
+ return rv;
+ }
+
+
+ /**
+ * C_CancelFunction is a legacy function; it cancels a function
+ * running in parallel.
+ *
+ * @param hSession the session's handle
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_CancelFunction )( CK_SESSION_HANDLE )
+ {
+ Log::begin( "C_CancelFunction" );
+
+ CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED;
+ if( _isInitialized )
+ {
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ }
+
+ Log::logCK_RV( "C_CancelFunction", rv );
+ Log::end( "C_CancelFunction" );
+ return rv;
+ }
+
+ /* Functions added in for Cryptoki Version 2.01 or later */
+
+ /**
+ * C_WaitForSlotEvent waits for a slot event (token insertion,
+ * removal, etc.) to occur.
+ *
+ * @param flags blocking/nonblocking flag
+ * @param pSlot location that receives the slot ID
+ * @param pReserved reserved. Should be NULL_PTR
+ */
+ CK_DEFINE_FUNCTION( CK_RV, C_WaitForSlotEvent )( CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved )
+ {
+ //Log::begin("C_WaitForSlotEvent");
+
+ // Not Initialized
+ if (!_isInitialized)
+ {
+ Log::error( "C_WaitForSlotEvent", "CKR_CRYPTOKI_NOT_INITIALIZED" );
+ return CKR_CRYPTOKI_NOT_INITIALIZED;
+ }
+
+ if((pReserved != NULL_PTR) || (pSlot == NULL_PTR))
+ {
+ Log::error( "C_WaitForSlotEvent", "CKR_ARGUMENTS_BAD" );
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ *pSlot = CK_UNAVAILABLE_INFORMATION;// -1;
+
+#ifdef INCLUDE_EVENTING
+ CMutex mut("a");
+
+ CK_SLOT_ID sid = 0;
+ for(;sid<CONFIG_MAX_SLOT;sid++)
+ {
+ Slot* slot = Application::_slotCache[sid];
+ if(slot != NULL_PTR)
+ {
+ if(slot->GetEvent())
+ {
+ *pSlot = slot->GetSlotId();
+ slot->SetEvent(CK_FALSE);
+ break;
+ }
+ }
+ }
+
+ mut.release();
+
+ if(*pSlot == (CK_SLOT_ID)-1)
+ {
+
+ if(flags & CKF_DONT_BLOCK)
+ {
+ //Log::log("CKR_NO_EVENT");
+ return CKR_NO_EVENT;
+ }
+ else
+ {
+ CryptokiEvent.Wait();
+ //Log::log("CryptokiEvent signal received in WaitForSlotEvent..");
+
+ CMutex mut("b");
+
+ CK_SLOT_ID sid = 0;
+
+ for(;sid<CONFIG_MAX_SLOT;sid++)
+ {
+ Slot* slot = Application::_slotCache[sid];
+
+ if(slot != NULL_PTR)
+ {
+ if(slot->GetEvent())
+ {
+ *pSlot = slot->GetSlotId();
+ Log::log( "C_WaitForSlotEvent - SlotID <%#02x>\n", *pSlot );
+ slot->SetEvent(CK_FALSE);
+ break;
+ }
+ }
+ }
+
+ mut.release();
+
+ if(*pSlot == (CK_SLOT_ID)-1)
+ {
+ //Log::log("CKR_NO_EVENT");
+ return CKR_NO_EVENT;
+ }
+ }
+ }
+
+ return CKR_OK;
+#else
+ return CKR_NO_EVENT;
+#endif
+ }
+
+} // extern "C"
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,300 @@
+/* pkcs11.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+#ifndef _PKCS11_H_
+#define _PKCS11_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Before including this file (pkcs11.h) (or pkcs11t.h by
+ * itself), 6 platform-specific macros must be defined. These
+ * macros are described below, and typical definitions for them
+ * are also given. Be advised that these definitions can depend
+ * on both the platform and the compiler used (and possibly also
+ * on whether a Cryptoki library is linked statically or
+ * dynamically).
+ *
+ * In addition to defining these 6 macros, the packing convention
+ * for Cryptoki structures should be set. The Cryptoki
+ * convention on packing is that structures should be 1-byte
+ * aligned.
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, this might be done by using the following
+ * preprocessor directive before including pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(push, cryptoki, 1)
+ *
+ * and using the following preprocessor directive after including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(pop, cryptoki)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, this might be done by using
+ * the following preprocessor directive before including
+ * pkcs11.h or pkcs11t.h:
+ *
+ * #pragma pack(1)
+ *
+ * In a UNIX environment, you're on your own for this. You might
+ * not need to do (or be able to do!) anything.
+ *
+ *
+ * Now for the macros:
+ *
+ *
+ * 1. CK_PTR: The indirection string for making a pointer to an
+ * object. It can be used like this:
+ *
+ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to produce
+ * Win32 stuff, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to produce Win16 stuff, it might be defined by:
+ *
+ * #define CK_PTR far *
+ *
+ * In a typical UNIX environment, it might be defined by:
+ *
+ * #define CK_PTR *
+ *
+ *
+ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
+ * an exportable Cryptoki library function definition out of a
+ * return type and a function name. It should be used in the
+ * following fashion to define the exposed Cryptoki functions in
+ * a Cryptoki library:
+ *
+ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
+ * CK_VOID_PTR pReserved
+ * )
+ * {
+ * ...
+ * }
+ *
+ * If you're using Microsoft Developer Studio 5.0 to define a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType __declspec(dllexport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to define a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DEFINE_FUNCTION(returnType, name) \
+ * returnType name
+ *
+ *
+ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
+ * an importable Cryptoki library function declaration out of a
+ * return type and a function name. It should be used in the
+ * following fashion:
+ *
+ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
+ * CK_VOID_PTR pReserved
+ * );
+ *
+ * If you're using Microsoft Developer Studio 5.0 to declare a
+ * function in a Win32 Cryptoki .dll, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType __declspec(dllimport) name
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to declare a function in a Win16 Cryptoki .dll, it
+ * might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType __export _far _pascal name
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION(returnType, name) \
+ * returnType name
+ *
+ *
+ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
+ * which makes a Cryptoki API function pointer declaration or
+ * function pointer type declaration out of a return type and a
+ * function name. It should be used in the following fashion:
+ *
+ * // Define funcPtr to be a pointer to a Cryptoki API function
+ * // taking arguments args and returning CK_RV.
+ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
+ *
+ * or
+ *
+ * // Define funcPtrType to be the type of a pointer to a
+ * // Cryptoki API function taking arguments args and returning
+ * // CK_RV, and then define funcPtr to be a variable of type
+ * // funcPtrType.
+ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
+ * funcPtrType funcPtr;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to access
+ * functions in a Win32 Cryptoki .dll, in might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType __declspec(dllimport) (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to access functions in a Win16 Cryptoki .dll, it might
+ * be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType __export _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ * returnType (* name)
+ *
+ *
+ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
+ * a function pointer type for an application callback out of
+ * a return type for the callback and a name for the callback.
+ * It should be used in the following fashion:
+ *
+ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
+ *
+ * to declare a function pointer, myCallback, to a callback
+ * which takes arguments args and returns a CK_RV. It can also
+ * be used like this:
+ *
+ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
+ * myCallbackType myCallback;
+ *
+ * If you're using Microsoft Developer Studio 5.0 to do Win32
+ * Cryptoki development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType (* name)
+ *
+ * If you're using an earlier version of Microsoft Developer
+ * Studio to do Win16 development, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType _far _pascal (* name)
+ *
+ * In a UNIX environment, it might be defined by:
+ *
+ * #define CK_CALLBACK_FUNCTION(returnType, name) \
+ * returnType (* name)
+ *
+ *
+ * 6. NULL_PTR: This macro is the value of a NULL pointer.
+ *
+ * In any ANSI/ISO C environment (and in many others as well),
+ * this should best be defined by
+ *
+ * #ifndef NULL_PTR
+ * #define NULL_PTR 0
+ * #endif
+ */
+
+
+/* All the various Cryptoki types and #define'd values are in the
+ * file pkcs11t.h. */
+#include "pkcs11t.h"
+
+#define __PASTE(x,y) x##y
+
+
+/* ==============================================================
+ * Define the "extern" form of all the entry points.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST 1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ extern CK_DECLARE_FUNCTION(CK_RV, name)
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define the typedef form of all the entry points. That is, for
+ * each Cryptoki function C_XXX, define a type CK_C_XXX which is
+ * a pointer to that kind of function.
+ * ==============================================================
+ */
+
+#define CK_NEED_ARG_LIST 1
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
+
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+#undef CK_NEED_ARG_LIST
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+/* ==============================================================
+ * Define structed vector of entry points. A CK_FUNCTION_LIST
+ * contains a CK_VERSION indicating a library's Cryptoki version
+ * and then a whole slew of function pointers to the routines in
+ * the library. This type was declared, but not defined, in
+ * pkcs11t.h.
+ * ==============================================================
+ */
+
+#define CK_PKCS11_FUNCTION_INFO(name) \
+ __PASTE(CK_,name) name;
+
+struct CK_FUNCTION_LIST {
+
+ CK_VERSION version; /* Cryptoki version */
+
+/* Pile all the function pointers into the CK_FUNCTION_LIST. */
+/* pkcs11f.h has all the information about the Cryptoki
+ * function prototypes. */
+#include "pkcs11f.h"
+
+};
+
+#undef CK_PKCS11_FUNCTION_INFO
+
+
+#undef __PASTE
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11f.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11f.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11f.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,903 @@
+/* pkcs11f.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* This header file contains pretty much everything about all the */
+/* Cryptoki function prototypes. Because this information is */
+/* used for more than just declaring function prototypes, the */
+/* order of the functions appearing herein is important, and */
+/* should not be altered. */
+
+/* General-purpose */
+
+/* C_Initialize initializes the Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Initialize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
+ * cast to CK_C_INITIALIZE_ARGS_PTR
+ * and dereferenced */
+);
+#endif
+
+
+/* C_Finalize indicates that an application is done with the
+ * Cryptoki library. */
+CK_PKCS11_FUNCTION_INFO(C_Finalize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
+);
+#endif
+
+
+/* C_GetInfo returns general information about Cryptoki. */
+CK_PKCS11_FUNCTION_INFO(C_GetInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_INFO_PTR pInfo /* location that receives information */
+);
+#endif
+
+/* C_GetFunctionList returns the function list. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
+ * function list */
+);
+#endif
+
+/* Slot and token management */
+
+/* C_GetSlotList obtains a list of slots in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_BBOOL tokenPresent, /* only slots with tokens? */
+ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
+ CK_ULONG_PTR pulCount /* receives number of slots */
+);
+#endif
+
+/* C_GetSlotInfo obtains information about a particular slot in
+ * the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* the ID of the slot */
+ CK_SLOT_INFO_PTR pInfo /* receives the slot information */
+);
+#endif
+
+
+
+/* C_GetTokenInfo obtains information about a particular token
+ * in the system. */
+CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_TOKEN_INFO_PTR pInfo /* receives the token information */
+);
+#endif
+
+/* C_GetMechanismList obtains a list of mechanism types
+ * supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of token's slot */
+ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
+ CK_ULONG_PTR pulCount /* gets # of mechs. */
+);
+#endif
+
+/* C_GetMechanismInfo obtains information about a particular
+ * mechanism possibly supported by a token. */
+CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_MECHANISM_TYPE type, /* type of mechanism */
+ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
+);
+#endif
+
+
+/* C_InitToken initializes a token. */
+CK_PKCS11_FUNCTION_INFO(C_InitToken)
+#ifdef CK_NEED_ARG_LIST
+/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
+(
+ CK_SLOT_ID slotID, /* ID of the token's slot */
+ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
+ CK_ULONG ulPinLen, /* length in bytes of the PIN */
+ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
+);
+#endif
+
+
+/* C_InitPIN initializes the normal user's PIN. */
+CK_PKCS11_FUNCTION_INFO(C_InitPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
+ CK_ULONG ulPinLen /* length in bytes of the PIN */
+);
+#endif
+
+
+/* C_SetPIN modifies the PIN of the user who is logged in. */
+CK_PKCS11_FUNCTION_INFO(C_SetPIN)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
+ CK_ULONG ulOldLen, /* length of the old PIN */
+ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
+ CK_ULONG ulNewLen /* length of the new PIN */
+);
+#endif
+
+
+
+/* Session management */
+
+/* C_OpenSession opens a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_OpenSession)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID, /* the slot's ID */
+ CK_FLAGS flags, /* from CK_SESSION_INFO */
+ CK_VOID_PTR pApplication, /* passed to callback */
+ CK_NOTIFY Notify, /* callback function */
+ CK_SESSION_HANDLE_PTR phSession /* gets session handle */
+);
+#endif
+
+
+/* C_CloseSession closes a session between an application and a
+ * token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseSession)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+/* C_CloseAllSessions closes all sessions with a token. */
+CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SLOT_ID slotID /* the token's slot */
+);
+#endif
+
+
+/* C_GetSessionInfo obtains information about the session. */
+CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_SESSION_INFO_PTR pInfo /* receives session info */
+);
+#endif
+
+
+/* C_GetOperationState obtains the state of the cryptographic operation
+ * in a session. */
+CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pOperationState, /* gets state */
+ CK_ULONG_PTR pulOperationStateLen /* gets state length */
+);
+#endif
+
+
+/* C_SetOperationState restores the state of the cryptographic
+ * operation in a session. */
+CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pOperationState, /* holds state */
+ CK_ULONG ulOperationStateLen, /* holds state length */
+ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
+ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
+);
+#endif
+
+
+/* C_Login logs a user into a token. */
+CK_PKCS11_FUNCTION_INFO(C_Login)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_USER_TYPE userType, /* the user type */
+ CK_UTF8CHAR_PTR pPin, /* the user's PIN */
+ CK_ULONG ulPinLen /* the length of the PIN */
+);
+#endif
+
+
+/* C_Logout logs a user out from a token. */
+CK_PKCS11_FUNCTION_INFO(C_Logout)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+/* Object management */
+
+/* C_CreateObject creates a new object. */
+CK_PKCS11_FUNCTION_INFO(C_CreateObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
+);
+#endif
+
+
+/* C_CopyObject copies an object, creating a new object for the
+ * copy. */
+CK_PKCS11_FUNCTION_INFO(C_CopyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
+ CK_ULONG ulCount, /* attributes in template */
+ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
+);
+#endif
+
+
+/* C_DestroyObject destroys an object. */
+CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject /* the object's handle */
+);
+#endif
+
+
+/* C_GetObjectSize gets the size of an object in bytes. */
+CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ULONG_PTR pulSize /* receives size of object */
+);
+#endif
+
+
+/* C_GetAttributeValue obtains the value of one or more object
+ * attributes. */
+CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
+ CK_ULONG ulCount /* attributes in template */
+);
+#endif
+
+
+/* C_SetAttributeValue modifies the value of one or more object
+ * attributes */
+CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hObject, /* the object's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
+ CK_ULONG ulCount /* attributes in template */
+);
+#endif
+
+
+/* C_FindObjectsInit initializes a search for token and session
+ * objects that match a template. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
+ CK_ULONG ulCount /* attrs in search template */
+);
+#endif
+
+
+/* C_FindObjects continues a search for token and session
+ * objects that match a template, obtaining additional object
+ * handles. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjects)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
+ CK_ULONG ulMaxObjectCount, /* max handles to get */
+ CK_ULONG_PTR pulObjectCount /* actual # returned */
+);
+#endif
+
+
+/* C_FindObjectsFinal finishes a search for token and session
+ * objects. */
+CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+/* Encryption and decryption */
+
+/* C_EncryptInit initializes an encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of encryption key */
+);
+#endif
+
+
+/* C_Encrypt encrypts single-part data. */
+CK_PKCS11_FUNCTION_INFO(C_Encrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pData, /* the plaintext data */
+ CK_ULONG ulDataLen, /* bytes of plaintext */
+ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptUpdate continues a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext data len */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
+);
+#endif
+
+
+/* C_EncryptFinal finishes a multiple-part encryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session handle */
+ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
+ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
+);
+#endif
+
+
+/* C_DecryptInit initializes a decryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of decryption key */
+);
+#endif
+
+
+/* C_Decrypt decrypts encrypted data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Decrypt)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedData, /* ciphertext */
+ CK_ULONG ulEncryptedDataLen, /* ciphertext length */
+ CK_BYTE_PTR pData, /* gets plaintext */
+ CK_ULONG_PTR pulDataLen /* gets p-text size */
+);
+#endif
+
+
+/* C_DecryptUpdate continues a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* encrypted data */
+ CK_ULONG ulEncryptedPartLen, /* input length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* p-text size */
+);
+#endif
+
+
+/* C_DecryptFinal finishes a multiple-part decryption
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pLastPart, /* gets plaintext */
+ CK_ULONG_PTR pulLastPartLen /* p-text size */
+);
+#endif
+
+
+
+/* Message digesting */
+
+/* C_DigestInit initializes a message-digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
+);
+#endif
+
+
+/* C_Digest digests data in a single part. */
+CK_PKCS11_FUNCTION_INFO(C_Digest)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* data to be digested */
+ CK_ULONG ulDataLen, /* bytes of data to digest */
+ CK_BYTE_PTR pDigest, /* gets the message digest */
+ CK_ULONG_PTR pulDigestLen /* gets digest length */
+);
+#endif
+
+
+/* C_DigestUpdate continues a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* data to be digested */
+ CK_ULONG ulPartLen /* bytes of data to be digested */
+);
+#endif
+
+
+/* C_DigestKey continues a multi-part message-digesting
+ * operation, by digesting the value of a secret key as part of
+ * the data already digested. */
+CK_PKCS11_FUNCTION_INFO(C_DigestKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_OBJECT_HANDLE hKey /* secret key to digest */
+);
+#endif
+
+
+/* C_DigestFinal finishes a multiple-part message-digesting
+ * operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pDigest, /* gets the message digest */
+ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
+);
+#endif
+
+
+
+/* Signing and MACing */
+
+/* C_SignInit initializes a signature (private key encryption)
+ * operation, where the signature is (will be) an appendix to
+ * the data, and plaintext cannot be recovered from the
+ *signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of signature key */
+);
+#endif
+
+
+/* C_Sign signs (encrypts with private key) data in a single
+ * part, where the signature is (will be) an appendix to the
+ * data, and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Sign)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* the data to sign */
+ CK_ULONG ulDataLen, /* count of bytes to sign */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+/* C_SignUpdate continues a multiple-part signature operation,
+ * where the signature is (will be) an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* the data to sign */
+ CK_ULONG ulPartLen /* count of bytes to sign */
+);
+#endif
+
+
+/* C_SignFinal finishes a multiple-part signature operation,
+ * returning the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+/* C_SignRecoverInit initializes a signature operation, where
+ * the data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
+ CK_OBJECT_HANDLE hKey /* handle of the signature key */
+);
+#endif
+
+
+/* C_SignRecover signs data in a single operation, where the
+ * data can be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_SignRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* the data to sign */
+ CK_ULONG ulDataLen, /* count of bytes to sign */
+ CK_BYTE_PTR pSignature, /* gets the signature */
+ CK_ULONG_PTR pulSignatureLen /* gets signature length */
+);
+#endif
+
+
+
+/* Verifying signatures and MACs */
+
+/* C_VerifyInit initializes a verification operation, where the
+ * signature is an appendix to the data, and plaintext cannot
+ * cannot be recovered from the signature (e.g. DSA). */
+CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey /* verification key */
+);
+#endif
+
+
+/* C_Verify verifies a signature in a single-part operation,
+ * where the signature is an appendix to the data, and plaintext
+ * cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_Verify)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pData, /* signed data */
+ CK_ULONG ulDataLen, /* length of signed data */
+ CK_BYTE_PTR pSignature, /* signature */
+ CK_ULONG ulSignatureLen /* signature length*/
+);
+#endif
+
+
+/* C_VerifyUpdate continues a multiple-part verification
+ * operation, where the signature is an appendix to the data,
+ * and plaintext cannot be recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pPart, /* signed data */
+ CK_ULONG ulPartLen /* length of signed data */
+);
+#endif
+
+
+/* C_VerifyFinal finishes a multiple-part verification
+ * operation, checking the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* signature to verify */
+ CK_ULONG ulSignatureLen /* signature length */
+);
+#endif
+
+
+/* C_VerifyRecoverInit initializes a signature verification
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
+ CK_OBJECT_HANDLE hKey /* verification key */
+);
+#endif
+
+
+/* C_VerifyRecover verifies a signature in a single-part
+ * operation, where the data is recovered from the signature. */
+CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSignature, /* signature to verify */
+ CK_ULONG ulSignatureLen, /* signature length */
+ CK_BYTE_PTR pData, /* gets signed data */
+ CK_ULONG_PTR pulDataLen /* gets signed data len */
+);
+#endif
+
+
+
+/* Dual-function cryptographic operations */
+
+/* C_DigestEncryptUpdate continues a multiple-part digesting
+ * and encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext length */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptDigestUpdate continues a multiple-part decryption and
+ * digesting operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* gets plaintext len */
+);
+#endif
+
+
+/* C_SignEncryptUpdate continues a multiple-part signing and
+ * encryption operation. */
+CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pPart, /* the plaintext data */
+ CK_ULONG ulPartLen, /* plaintext length */
+ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
+ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
+);
+#endif
+
+
+/* C_DecryptVerifyUpdate continues a multiple-part decryption and
+ * verify operation. */
+CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
+ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
+ CK_BYTE_PTR pPart, /* gets plaintext */
+ CK_ULONG_PTR pulPartLen /* gets p-text length */
+);
+#endif
+
+
+
+/* Key management */
+
+/* C_GenerateKey generates a secret key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* key generation mech. */
+ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
+ CK_ULONG ulCount, /* # of attrs in template */
+ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
+);
+#endif
+
+
+/* C_GenerateKeyPair generates a public-key/private-key pair,
+ * creating new key objects. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session
+ * handle */
+ CK_MECHANISM_PTR pMechanism, /* key-gen
+ * mech. */
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template
+ * for pub.
+ * key */
+ CK_ULONG ulPublicKeyAttributeCount, /* # pub.
+ * attrs. */
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template
+ * for priv.
+ * key */
+ CK_ULONG ulPrivateKeyAttributeCount, /* # priv.
+ * attrs. */
+ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub.
+ * key
+ * handle */
+ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets
+ * priv. key
+ * handle */
+);
+#endif
+
+
+/* C_WrapKey wraps (i.e., encrypts) a key. */
+CK_PKCS11_FUNCTION_INFO(C_WrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
+ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
+ CK_OBJECT_HANDLE hKey, /* key to be wrapped */
+ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
+ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
+);
+#endif
+
+
+/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
+ * key object. */
+CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
+ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
+ CK_BYTE_PTR pWrappedKey, /* the wrapped key */
+ CK_ULONG ulWrappedKeyLen, /* wrapped key len */
+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
+);
+#endif
+
+
+/* C_DeriveKey derives a key from a base key, creating a new key
+ * object. */
+CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* session's handle */
+ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
+ CK_OBJECT_HANDLE hBaseKey, /* base key */
+ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
+ CK_ULONG ulAttributeCount, /* template length */
+ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
+);
+#endif
+
+
+
+/* Random number generation */
+
+/* C_SeedRandom mixes additional seed material into the token's
+ * random number generator. */
+CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR pSeed, /* the seed material */
+ CK_ULONG ulSeedLen /* length of seed material */
+);
+#endif
+
+
+/* C_GenerateRandom generates random data. */
+CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_BYTE_PTR RandomData, /* receives the random data */
+ CK_ULONG ulRandomLen /* # of bytes to generate */
+);
+#endif
+
+
+
+/* Parallel function management */
+
+/* C_GetFunctionStatus is a legacy function; it obtains an
+ * updated status of a function running in parallel with an
+ * application. */
+CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+
+/* C_CancelFunction is a legacy function; it cancels a function
+ * running in parallel. */
+CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_SESSION_HANDLE hSession /* the session's handle */
+);
+#endif
+
+/* Functions added in for Cryptoki Version 2.01 or later */
+
+/* C_WaitForSlotEvent waits for a slot event (token insertion,
+ * removal, etc.) to occur. */
+CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
+#ifdef CK_NEED_ARG_LIST
+(
+ CK_FLAGS flags, /* blocking/nonblocking flag */
+ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
+ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
+);
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11t.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11t.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/pkcs11t.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,1701 @@
+/* pkcs11t.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* See top of pkcs11.h for information about the macros that
+ * must be defined and the structure-packing conventions that
+ * must be set before including this file. */
+
+#ifndef _PKCS11T_H_
+#define _PKCS11T_H_ 1
+
+#define CK_TRUE 1
+#define CK_FALSE 0
+
+#ifndef CK_DISABLE_TRUE_FALSE
+#ifndef FALSE
+#define FALSE CK_FALSE
+#endif
+
+#ifndef TRUE
+#define TRUE CK_TRUE
+#endif
+#endif
+
+typedef unsigned short CK_USHORT;
+
+/* an unsigned 8-bit value */
+typedef unsigned char CK_BYTE;
+
+/* an unsigned 8-bit character */
+typedef CK_BYTE CK_CHAR;
+
+/* an 8-bit UTF-8 character */
+typedef CK_BYTE CK_UTF8CHAR;
+
+/* a BYTE-sized Boolean flag */
+typedef CK_BYTE CK_BBOOL;
+
+/* an unsigned value, at least 32 bits long */
+typedef unsigned long int CK_ULONG;
+
+/* a signed value, the same size as a CK_ULONG */
+/* CK_LONG is new for v2.0 */
+typedef long int CK_LONG;
+
+/* at least 32 bits; each bit is a Boolean flag */
+typedef CK_ULONG CK_FLAGS;
+
+
+/* some special values for certain CK_ULONG variables */
+#define CK_UNAVAILABLE_INFORMATION (~0UL)
+#define CK_EFFECTIVELY_INFINITE 0
+
+
+typedef CK_BYTE CK_PTR CK_BYTE_PTR;
+typedef CK_CHAR CK_PTR CK_CHAR_PTR;
+typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
+typedef CK_ULONG CK_PTR CK_ULONG_PTR;
+typedef void CK_PTR CK_VOID_PTR;
+
+/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
+typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
+
+
+/* The following value is always invalid if used as a session */
+/* handle or object handle */
+#define CK_INVALID_HANDLE 0
+
+
+typedef struct CK_VERSION {
+ CK_BYTE major; /* integer portion of version number */
+ CK_BYTE minor; /* 1/100ths portion of version number */
+} CK_VERSION;
+
+typedef CK_VERSION CK_PTR CK_VERSION_PTR;
+
+
+typedef struct CK_INFO {
+ /* manufacturerID and libraryDecription have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_VERSION cryptokiVersion; /* Cryptoki interface ver */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_FLAGS flags; /* must be zero */
+
+ /* libraryDescription and libraryVersion are new for v2.0 */
+ CK_UTF8CHAR libraryDescription[32]; /* blank padded */
+ CK_VERSION libraryVersion; /* version of library */
+} CK_INFO;
+
+typedef CK_INFO CK_PTR CK_INFO_PTR;
+
+
+/* CK_NOTIFICATION enumerates the types of notifications that
+ * Cryptoki provides to an application */
+/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG CK_NOTIFICATION;
+#define CKN_SURRENDER 0
+
+
+typedef CK_ULONG CK_SLOT_ID;
+
+typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
+
+
+/* CK_SLOT_INFO provides information about a slot */
+typedef struct CK_SLOT_INFO {
+ /* slotDescription and manufacturerID have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_UTF8CHAR slotDescription[64]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_FLAGS flags;
+
+ /* hardwareVersion and firmwareVersion are new for v2.0 */
+ CK_VERSION hardwareVersion; /* version of hardware */
+ CK_VERSION firmwareVersion; /* version of firmware */
+} CK_SLOT_INFO;
+
+/* flags: bit flags that provide capabilities of the slot
+ * Bit Flag Mask Meaning
+ */
+#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */
+#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/
+#define CKF_HW_SLOT 0x00000004 /* hardware slot */
+
+typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
+
+
+/* CK_TOKEN_INFO provides information about a token */
+typedef struct CK_TOKEN_INFO {
+ /* label, manufacturerID, and model have been changed from
+ * CK_CHAR to CK_UTF8CHAR for v2.10 */
+ CK_UTF8CHAR label[32]; /* blank padded */
+ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
+ CK_UTF8CHAR model[16]; /* blank padded */
+ CK_CHAR serialNumber[16]; /* blank padded */
+ CK_FLAGS flags; /* see below */
+
+ /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
+ * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
+ * changed from CK_USHORT to CK_ULONG for v2.0 */
+ CK_ULONG ulMaxSessionCount; /* max open sessions */
+ CK_ULONG ulSessionCount; /* sess. now open */
+ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */
+ CK_ULONG ulRwSessionCount; /* R/W sess. now open */
+ CK_ULONG ulMaxPinLen; /* in bytes */
+ CK_ULONG ulMinPinLen; /* in bytes */
+ CK_ULONG ulTotalPublicMemory; /* in bytes */
+ CK_ULONG ulFreePublicMemory; /* in bytes */
+ CK_ULONG ulTotalPrivateMemory; /* in bytes */
+ CK_ULONG ulFreePrivateMemory; /* in bytes */
+
+ /* hardwareVersion, firmwareVersion, and time are new for
+ * v2.0 */
+ CK_VERSION hardwareVersion; /* version of hardware */
+ CK_VERSION firmwareVersion; /* version of firmware */
+ CK_CHAR utcTime[16]; /* time */
+} CK_TOKEN_INFO;
+
+/* The flags parameter is defined as follows:
+ * Bit Flag Mask Meaning
+ */
+#define CKF_RNG 0x00000001 /* has random #
+ * generator */
+#define CKF_WRITE_PROTECTED 0x00000002 /* token is
+ * write-
+ * protected */
+#define CKF_LOGIN_REQUIRED 0x00000004 /* user must
+ * login */
+#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's
+ * PIN is set */
+
+/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set,
+ * that means that *every* time the state of cryptographic
+ * operations of a session is successfully saved, all keys
+ * needed to continue those operations are stored in the state */
+#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020
+
+/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means
+ * that the token has some sort of clock. The time on that
+ * clock is returned in the token info structure */
+#define CKF_CLOCK_ON_TOKEN 0x00000040
+
+/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is
+ * set, that means that there is some way for the user to login
+ * without sending a PIN through the Cryptoki library itself */
+#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
+
+/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true,
+ * that means that a single session with the token can perform
+ * dual simultaneous cryptographic operations (digest and
+ * encrypt; decrypt and digest; sign and encrypt; and decrypt
+ * and sign) */
+#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200
+
+/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
+ * token has been initialized using C_InitializeToken or an
+ * equivalent mechanism outside the scope of PKCS #11.
+ * Calling C_InitializeToken when this flag is set will cause
+ * the token to be reinitialized. */
+#define CKF_TOKEN_INITIALIZED 0x00000400
+
+/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
+ * true, the token supports secondary authentication for
+ * private key objects. This flag is deprecated in v2.11 and
+ onwards. */
+#define CKF_SECONDARY_AUTHENTICATION 0x00000800
+
+/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect user login PIN has been entered at least once
+ * since the last successful authentication. */
+#define CKF_USER_PIN_COUNT_LOW 0x00010000
+
+/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect user PIN will it to become locked. */
+#define CKF_USER_PIN_FINAL_TRY 0x00020000
+
+/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
+ * user PIN has been locked. User login to the token is not
+ * possible. */
+#define CKF_USER_PIN_LOCKED 0x00040000
+
+/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the user PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000
+
+/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
+ * incorrect SO login PIN has been entered at least once since
+ * the last successful authentication. */
+#define CKF_SO_PIN_COUNT_LOW 0x00100000
+
+/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
+ * supplying an incorrect SO PIN will it to become locked. */
+#define CKF_SO_PIN_FINAL_TRY 0x00200000
+
+/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
+ * PIN has been locked. SO login to the token is not possible.
+ */
+#define CKF_SO_PIN_LOCKED 0x00400000
+
+/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
+ * the SO PIN value is the default value set by token
+ * initialization or manufacturing, or the PIN has been
+ * expired by the card. */
+#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000
+
+typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
+
+
+/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
+ * identifies a session */
+typedef CK_ULONG CK_SESSION_HANDLE;
+
+typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
+
+
+/* CK_USER_TYPE enumerates the types of Cryptoki users */
+/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_USER_TYPE;
+/* Security Officer */
+#define CKU_SO 0
+/* Normal user */
+#define CKU_USER 1
+/* Context specific (added in v2.20) */
+#define CKU_CONTEXT_SPECIFIC 2
+
+/* Not defined in PKCS#11, Add by KS */
+#define CKU_NONE 99
+#define CO_OBJECT_HANDLE_MASK 0x0000FFFF
+#define CO_SESSION_OBJECT 0x00000000
+#define CO_TOKEN_OBJECT 0x10000000
+
+
+/* CK_STATE enumerates the session states */
+/* CK_STATE has been changed from an enum to a CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_STATE;
+#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
+
+
+/* CK_SESSION_INFO provides information about a session */
+typedef struct CK_SESSION_INFO {
+ CK_SLOT_ID slotID;
+ CK_STATE state;
+ CK_FLAGS flags; /* see below */
+
+ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulDeviceError; /* device-dependent error code */
+} CK_SESSION_INFO;
+
+/* The flags are defined in the following table:
+ * Bit Flag Mask Meaning
+ */
+#define CKF_RW_SESSION 0x00000002 /* session is r/w */
+#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */
+
+typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
+
+
+/* CK_OBJECT_HANDLE is a token-specific identifier for an
+ * object */
+typedef CK_ULONG CK_OBJECT_HANDLE;
+
+typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
+
+
+/* CK_OBJECT_CLASS is a value that identifies the classes (or
+ * types) of objects that Cryptoki recognizes. It is defined
+ * as follows: */
+/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_OBJECT_CLASS;
+
+/* The following classes of objects are defined: */
+/* CKO_HW_FEATURE is new for v2.10 */
+/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
+/* CKO_MECHANISM is new for v2.20 */
+#define CKO_DATA 0x00000000
+#define CKO_CERTIFICATE 0x00000001
+#define CKO_PUBLIC_KEY 0x00000002
+#define CKO_PRIVATE_KEY 0x00000003
+#define CKO_SECRET_KEY 0x00000004
+#define CKO_HW_FEATURE 0x00000005
+#define CKO_DOMAIN_PARAMETERS 0x00000006
+#define CKO_MECHANISM 0x00000007
+#define CKO_VENDOR_DEFINED 0x80000000
+
+typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
+
+/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
+ * value that identifies the hardware feature type of an object
+ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
+typedef CK_ULONG CK_HW_FEATURE_TYPE;
+
+/* The following hardware feature types are defined */
+/* CKH_USER_INTERFACE is new for v2.20 */
+#define CKH_MONOTONIC_COUNTER 0x00000001
+#define CKH_CLOCK 0x00000002
+#define CKH_USER_INTERFACE 0x00000003
+#define CKH_VENDOR_DEFINED 0x80000000
+
+/* CK_KEY_TYPE is a value that identifies a key type */
+/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG CK_KEY_TYPE;
+
+/* the following key types are defined: */
+#define CKK_RSA 0x00000000
+#define CKK_DSA 0x00000001
+#define CKK_DH 0x00000002
+
+/* CKK_ECDSA and CKK_KEA are new for v2.0 */
+/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
+#define CKK_ECDSA 0x00000003
+#define CKK_EC 0x00000003
+#define CKK_X9_42_DH 0x00000004
+#define CKK_KEA 0x00000005
+
+#define CKK_GENERIC_SECRET 0x00000010
+#define CKK_RC2 0x00000011
+#define CKK_RC4 0x00000012
+#define CKK_DES 0x00000013
+#define CKK_DES2 0x00000014
+#define CKK_DES3 0x00000015
+
+/* all these key types are new for v2.0 */
+#define CKK_CAST 0x00000016
+#define CKK_CAST3 0x00000017
+/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
+#define CKK_CAST5 0x00000018
+#define CKK_CAST128 0x00000018
+#define CKK_RC5 0x00000019
+#define CKK_IDEA 0x0000001A
+#define CKK_SKIPJACK 0x0000001B
+#define CKK_BATON 0x0000001C
+#define CKK_JUNIPER 0x0000001D
+#define CKK_CDMF 0x0000001E
+#define CKK_AES 0x0000001F
+
+/* BlowFish and TwoFish are new for v2.20 */
+#define CKK_BLOWFISH 0x00000020
+#define CKK_TWOFISH 0x00000021
+
+#define CKK_VENDOR_DEFINED 0x80000000
+
+
+/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
+ * type */
+/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
+ * for v2.0 */
+typedef CK_ULONG CK_CERTIFICATE_TYPE;
+
+/* The following certificate types are defined: */
+/* CKC_X_509_ATTR_CERT is new for v2.10 */
+/* CKC_WTLS is new for v2.20 */
+#define CKC_X_509 0x00000000
+#define CKC_X_509_ATTR_CERT 0x00000001
+#define CKC_WTLS 0x00000002
+#define CKC_VENDOR_DEFINED 0x80000000
+
+
+/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
+ * type */
+/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_ATTRIBUTE_TYPE;
+
+/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which
+ consists of an array of values. */
+#define CKF_ARRAY_ATTRIBUTE 0x40000000
+
+/* The following attribute types are defined: */
+#define CKA_CLASS 0x00000000
+#define CKA_TOKEN 0x00000001
+#define CKA_PRIVATE 0x00000002
+#define CKA_LABEL 0x00000003
+#define CKA_APPLICATION 0x00000010
+#define CKA_VALUE 0x00000011
+
+/* CKA_OBJECT_ID is new for v2.10 */
+#define CKA_OBJECT_ID 0x00000012
+
+#define CKA_CERTIFICATE_TYPE 0x00000080
+#define CKA_ISSUER 0x00000081
+#define CKA_SERIAL_NUMBER 0x00000082
+
+/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
+ * for v2.10 */
+#define CKA_AC_ISSUER 0x00000083
+#define CKA_OWNER 0x00000084
+#define CKA_ATTR_TYPES 0x00000085
+
+/* CKA_TRUSTED is new for v2.11 */
+#define CKA_TRUSTED 0x00000086
+
+/* CKA_CERTIFICATE_CATEGORY ...
+ * CKA_CHECK_VALUE are new for v2.20 */
+#define CKA_CERTIFICATE_CATEGORY 0x00000087
+#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088
+#define CKA_URL 0x00000089
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B
+#define CKA_CHECK_VALUE 0x00000090
+
+#define CKA_KEY_TYPE 0x00000100
+#define CKA_SUBJECT 0x00000101
+#define CKA_ID 0x00000102
+#define CKA_SENSITIVE 0x00000103
+#define CKA_ENCRYPT 0x00000104
+#define CKA_DECRYPT 0x00000105
+#define CKA_WRAP 0x00000106
+#define CKA_UNWRAP 0x00000107
+#define CKA_SIGN 0x00000108
+#define CKA_SIGN_RECOVER 0x00000109
+#define CKA_VERIFY 0x0000010A
+#define CKA_VERIFY_RECOVER 0x0000010B
+#define CKA_DERIVE 0x0000010C
+#define CKA_START_DATE 0x00000110
+#define CKA_END_DATE 0x00000111
+#define CKA_MODULUS 0x00000120
+#define CKA_MODULUS_BITS 0x00000121
+#define CKA_PUBLIC_EXPONENT 0x00000122
+#define CKA_PRIVATE_EXPONENT 0x00000123
+#define CKA_PRIME_1 0x00000124
+#define CKA_PRIME_2 0x00000125
+#define CKA_EXPONENT_1 0x00000126
+#define CKA_EXPONENT_2 0x00000127
+#define CKA_COEFFICIENT 0x00000128
+#define CKA_PRIME 0x00000130
+#define CKA_SUBPRIME 0x00000131
+#define CKA_BASE 0x00000132
+
+/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
+#define CKA_PRIME_BITS 0x00000133
+#define CKA_SUBPRIME_BITS 0x00000134
+#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS
+/* (To retain backwards-compatibility) */
+
+#define CKA_VALUE_BITS 0x00000160
+#define CKA_VALUE_LEN 0x00000161
+
+/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
+ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
+ * and CKA_EC_POINT are new for v2.0 */
+#define CKA_EXTRACTABLE 0x00000162
+#define CKA_LOCAL 0x00000163
+#define CKA_NEVER_EXTRACTABLE 0x00000164
+#define CKA_ALWAYS_SENSITIVE 0x00000165
+
+/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
+#define CKA_KEY_GEN_MECHANISM 0x00000166
+
+#define CKA_MODIFIABLE 0x00000170
+
+/* CKA_ECDSA_PARAMS is deprecated in v2.11,
+ * CKA_EC_PARAMS is preferred. */
+#define CKA_ECDSA_PARAMS 0x00000180
+#define CKA_EC_PARAMS 0x00000180
+
+#define CKA_EC_POINT 0x00000181
+
+/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
+ * are new for v2.10. Deprecated in v2.11 and onwards. */
+#define CKA_SECONDARY_AUTH 0x00000200
+#define CKA_AUTH_PIN_FLAGS 0x00000201
+
+/* CKA_ALWAYS_AUTHENTICATE ...
+ * CKA_UNWRAP_TEMPLATE are new for v2.20 */
+#define CKA_ALWAYS_AUTHENTICATE 0x00000202
+
+#define CKA_WRAP_WITH_TRUSTED 0x00000210
+#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211)
+#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212)
+
+/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
+ * are new for v2.10 */
+#define CKA_HW_FEATURE_TYPE 0x00000300
+#define CKA_RESET_ON_INIT 0x00000301
+#define CKA_HAS_RESET 0x00000302
+
+/* The following attributes are new for v2.20 */
+#define CKA_PIXEL_X 0x00000400
+#define CKA_PIXEL_Y 0x00000401
+#define CKA_RESOLUTION 0x00000402
+#define CKA_CHAR_ROWS 0x00000403
+#define CKA_CHAR_COLUMNS 0x00000404
+#define CKA_COLOR 0x00000405
+#define CKA_BITS_PER_PIXEL 0x00000406
+#define CKA_CHAR_SETS 0x00000480
+#define CKA_ENCODING_METHODS 0x00000481
+#define CKA_MIME_TYPES 0x00000482
+#define CKA_MECHANISM_TYPE 0x00000500
+#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501
+#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502
+#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503
+#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600)
+
+#define CKA_VENDOR_DEFINED 0x80000000
+
+// Gemalto CKA
+#define CKA_GEMALTO_CTRINDEX 0x80000001
+#define CKA_GEMALTO_KEYSPEC 0x80000002
+
+/* CK_ATTRIBUTE is a structure that includes the type, length
+ * and value of an attribute */
+typedef struct CK_ATTRIBUTE {
+ CK_ATTRIBUTE_TYPE type;
+ CK_VOID_PTR pValue;
+
+ /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
+ CK_ULONG ulValueLen; /* in bytes */
+} CK_ATTRIBUTE;
+
+typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
+
+
+/* CK_DATE is a structure that defines a date */
+typedef struct CK_DATE{
+ CK_CHAR year[4]; /* the year ("1900" - "9999") */
+ CK_CHAR month[2]; /* the month ("01" - "12") */
+ CK_CHAR day[2]; /* the day ("01" - "31") */
+} CK_DATE;
+
+
+/* CK_MECHANISM_TYPE is a value that identifies a mechanism
+ * type */
+/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+typedef CK_ULONG CK_MECHANISM_TYPE;
+
+/* the following mechanism types are defined: */
+#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
+#define CKM_RSA_PKCS 0x00000001
+#define CKM_RSA_9796 0x00000002
+#define CKM_RSA_X_509 0x00000003
+
+/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
+ * are new for v2.0. They are mechanisms which hash and sign */
+#define CKM_MD2_RSA_PKCS 0x00000004
+#define CKM_MD5_RSA_PKCS 0x00000005
+#define CKM_SHA1_RSA_PKCS 0x00000006
+
+/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
+ * CKM_RSA_PKCS_OAEP are new for v2.10 */
+#define CKM_RIPEMD128_RSA_PKCS 0x00000007
+#define CKM_RIPEMD160_RSA_PKCS 0x00000008
+#define CKM_RSA_PKCS_OAEP 0x00000009
+
+/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
+ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
+#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A
+#define CKM_RSA_X9_31 0x0000000B
+#define CKM_SHA1_RSA_X9_31 0x0000000C
+#define CKM_RSA_PKCS_PSS 0x0000000D
+#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E
+
+#define CKM_DSA_KEY_PAIR_GEN 0x00000010
+#define CKM_DSA 0x00000011
+#define CKM_DSA_SHA1 0x00000012
+#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
+#define CKM_DH_PKCS_DERIVE 0x00000021
+
+/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
+ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
+ * v2.11 */
+#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030
+#define CKM_X9_42_DH_DERIVE 0x00000031
+#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032
+#define CKM_X9_42_MQV_DERIVE 0x00000033
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256_RSA_PKCS 0x00000040
+#define CKM_SHA384_RSA_PKCS 0x00000041
+#define CKM_SHA512_RSA_PKCS 0x00000042
+#define CKM_SHA256_RSA_PKCS_PSS 0x00000043
+#define CKM_SHA384_RSA_PKCS_PSS 0x00000044
+#define CKM_SHA512_RSA_PKCS_PSS 0x00000045
+
+#define CKM_RC2_KEY_GEN 0x00000100
+#define CKM_RC2_ECB 0x00000101
+#define CKM_RC2_CBC 0x00000102
+#define CKM_RC2_MAC 0x00000103
+
+/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
+#define CKM_RC2_MAC_GENERAL 0x00000104
+#define CKM_RC2_CBC_PAD 0x00000105
+
+#define CKM_RC4_KEY_GEN 0x00000110
+#define CKM_RC4 0x00000111
+#define CKM_DES_KEY_GEN 0x00000120
+#define CKM_DES_ECB 0x00000121
+#define CKM_DES_CBC 0x00000122
+#define CKM_DES_MAC 0x00000123
+
+/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
+#define CKM_DES_MAC_GENERAL 0x00000124
+#define CKM_DES_CBC_PAD 0x00000125
+
+#define CKM_DES2_KEY_GEN 0x00000130
+#define CKM_DES3_KEY_GEN 0x00000131
+#define CKM_DES3_ECB 0x00000132
+#define CKM_DES3_CBC 0x00000133
+#define CKM_DES3_MAC 0x00000134
+
+/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
+ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
+ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
+#define CKM_DES3_MAC_GENERAL 0x00000135
+#define CKM_DES3_CBC_PAD 0x00000136
+#define CKM_CDMF_KEY_GEN 0x00000140
+#define CKM_CDMF_ECB 0x00000141
+#define CKM_CDMF_CBC 0x00000142
+#define CKM_CDMF_MAC 0x00000143
+#define CKM_CDMF_MAC_GENERAL 0x00000144
+#define CKM_CDMF_CBC_PAD 0x00000145
+
+/* the following four DES mechanisms are new for v2.20 */
+#define CKM_DES_OFB64 0x00000150
+#define CKM_DES_OFB8 0x00000151
+#define CKM_DES_CFB64 0x00000152
+#define CKM_DES_CFB8 0x00000153
+
+#define CKM_MD2 0x00000200
+
+/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD2_HMAC 0x00000201
+#define CKM_MD2_HMAC_GENERAL 0x00000202
+
+#define CKM_MD5 0x00000210
+
+/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
+#define CKM_MD5_HMAC 0x00000211
+#define CKM_MD5_HMAC_GENERAL 0x00000212
+
+#define CKM_SHA_1 0x00000220
+
+/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
+#define CKM_SHA_1_HMAC 0x00000221
+#define CKM_SHA_1_HMAC_GENERAL 0x00000222
+
+/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
+ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
+ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
+#define CKM_RIPEMD128 0x00000230
+#define CKM_RIPEMD128_HMAC 0x00000231
+#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232
+#define CKM_RIPEMD160 0x00000240
+#define CKM_RIPEMD160_HMAC 0x00000241
+#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256 0x00000250
+#define CKM_SHA256_HMAC 0x00000251
+#define CKM_SHA256_HMAC_GENERAL 0x00000252
+#define CKM_SHA384 0x00000260
+#define CKM_SHA384_HMAC 0x00000261
+#define CKM_SHA384_HMAC_GENERAL 0x00000262
+#define CKM_SHA512 0x00000270
+#define CKM_SHA512_HMAC 0x00000271
+#define CKM_SHA512_HMAC_GENERAL 0x00000272
+
+/* All of the following mechanisms are new for v2.0 */
+/* Note that CAST128 and CAST5 are the same algorithm */
+#define CKM_CAST_KEY_GEN 0x00000300
+#define CKM_CAST_ECB 0x00000301
+#define CKM_CAST_CBC 0x00000302
+#define CKM_CAST_MAC 0x00000303
+#define CKM_CAST_MAC_GENERAL 0x00000304
+#define CKM_CAST_CBC_PAD 0x00000305
+#define CKM_CAST3_KEY_GEN 0x00000310
+#define CKM_CAST3_ECB 0x00000311
+#define CKM_CAST3_CBC 0x00000312
+#define CKM_CAST3_MAC 0x00000313
+#define CKM_CAST3_MAC_GENERAL 0x00000314
+#define CKM_CAST3_CBC_PAD 0x00000315
+#define CKM_CAST5_KEY_GEN 0x00000320
+#define CKM_CAST128_KEY_GEN 0x00000320
+#define CKM_CAST5_ECB 0x00000321
+#define CKM_CAST128_ECB 0x00000321
+#define CKM_CAST5_CBC 0x00000322
+#define CKM_CAST128_CBC 0x00000322
+#define CKM_CAST5_MAC 0x00000323
+#define CKM_CAST128_MAC 0x00000323
+#define CKM_CAST5_MAC_GENERAL 0x00000324
+#define CKM_CAST128_MAC_GENERAL 0x00000324
+#define CKM_CAST5_CBC_PAD 0x00000325
+#define CKM_CAST128_CBC_PAD 0x00000325
+#define CKM_RC5_KEY_GEN 0x00000330
+#define CKM_RC5_ECB 0x00000331
+#define CKM_RC5_CBC 0x00000332
+#define CKM_RC5_MAC 0x00000333
+#define CKM_RC5_MAC_GENERAL 0x00000334
+#define CKM_RC5_CBC_PAD 0x00000335
+#define CKM_IDEA_KEY_GEN 0x00000340
+#define CKM_IDEA_ECB 0x00000341
+#define CKM_IDEA_CBC 0x00000342
+#define CKM_IDEA_MAC 0x00000343
+#define CKM_IDEA_MAC_GENERAL 0x00000344
+#define CKM_IDEA_CBC_PAD 0x00000345
+#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350
+#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360
+#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362
+#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363
+#define CKM_XOR_BASE_AND_DATA 0x00000364
+#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365
+#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370
+#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371
+#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372
+
+/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
+ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
+ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373
+#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374
+#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375
+#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376
+#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377
+
+/* CKM_TLS_PRF is new for v2.20 */
+#define CKM_TLS_PRF 0x00000378
+
+#define CKM_SSL3_MD5_MAC 0x00000380
+#define CKM_SSL3_SHA1_MAC 0x00000381
+#define CKM_MD5_KEY_DERIVATION 0x00000390
+#define CKM_MD2_KEY_DERIVATION 0x00000391
+#define CKM_SHA1_KEY_DERIVATION 0x00000392
+
+/* CKM_SHA256/384/512 are new for v2.20 */
+#define CKM_SHA256_KEY_DERIVATION 0x00000393
+#define CKM_SHA384_KEY_DERIVATION 0x00000394
+#define CKM_SHA512_KEY_DERIVATION 0x00000395
+
+#define CKM_PBE_MD2_DES_CBC 0x000003A0
+#define CKM_PBE_MD5_DES_CBC 0x000003A1
+#define CKM_PBE_MD5_CAST_CBC 0x000003A2
+#define CKM_PBE_MD5_CAST3_CBC 0x000003A3
+#define CKM_PBE_MD5_CAST5_CBC 0x000003A4
+#define CKM_PBE_MD5_CAST128_CBC 0x000003A4
+#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5
+#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5
+#define CKM_PBE_SHA1_RC4_128 0x000003A6
+#define CKM_PBE_SHA1_RC4_40 0x000003A7
+#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8
+#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9
+#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA
+#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB
+
+/* CKM_PKCS5_PBKD2 is new for v2.10 */
+#define CKM_PKCS5_PBKD2 0x000003B0
+
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0
+
+/* WTLS mechanisms are new for v2.20 */
+#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0
+#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1
+#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2
+#define CKM_WTLS_PRF 0x000003D3
+#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4
+#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5
+
+#define CKM_KEY_WRAP_LYNKS 0x00000400
+#define CKM_KEY_WRAP_SET_OAEP 0x00000401
+
+/* CKM_CMS_SIG is new for v2.20 */
+#define CKM_CMS_SIG 0x00000500
+
+/* Fortezza mechanisms */
+#define CKM_SKIPJACK_KEY_GEN 0x00001000
+#define CKM_SKIPJACK_ECB64 0x00001001
+#define CKM_SKIPJACK_CBC64 0x00001002
+#define CKM_SKIPJACK_OFB64 0x00001003
+#define CKM_SKIPJACK_CFB64 0x00001004
+#define CKM_SKIPJACK_CFB32 0x00001005
+#define CKM_SKIPJACK_CFB16 0x00001006
+#define CKM_SKIPJACK_CFB8 0x00001007
+#define CKM_SKIPJACK_WRAP 0x00001008
+#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009
+#define CKM_SKIPJACK_RELAYX 0x0000100a
+#define CKM_KEA_KEY_PAIR_GEN 0x00001010
+#define CKM_KEA_KEY_DERIVE 0x00001011
+#define CKM_FORTEZZA_TIMESTAMP 0x00001020
+#define CKM_BATON_KEY_GEN 0x00001030
+#define CKM_BATON_ECB128 0x00001031
+#define CKM_BATON_ECB96 0x00001032
+#define CKM_BATON_CBC128 0x00001033
+#define CKM_BATON_COUNTER 0x00001034
+#define CKM_BATON_SHUFFLE 0x00001035
+#define CKM_BATON_WRAP 0x00001036
+
+/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
+ * CKM_EC_KEY_PAIR_GEN is preferred */
+#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040
+#define CKM_EC_KEY_PAIR_GEN 0x00001040
+
+#define CKM_ECDSA 0x00001041
+#define CKM_ECDSA_SHA1 0x00001042
+
+/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
+ * are new for v2.11 */
+#define CKM_ECDH1_DERIVE 0x00001050
+#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051
+#define CKM_ECMQV_DERIVE 0x00001052
+
+#define CKM_JUNIPER_KEY_GEN 0x00001060
+#define CKM_JUNIPER_ECB128 0x00001061
+#define CKM_JUNIPER_CBC128 0x00001062
+#define CKM_JUNIPER_COUNTER 0x00001063
+#define CKM_JUNIPER_SHUFFLE 0x00001064
+#define CKM_JUNIPER_WRAP 0x00001065
+#define CKM_FASTHASH 0x00001070
+
+/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
+ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
+ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
+ * new for v2.11 */
+#define CKM_AES_KEY_GEN 0x00001080
+#define CKM_AES_ECB 0x00001081
+#define CKM_AES_CBC 0x00001082
+#define CKM_AES_MAC 0x00001083
+#define CKM_AES_MAC_GENERAL 0x00001084
+#define CKM_AES_CBC_PAD 0x00001085
+
+/* BlowFish and TwoFish are new for v2.20 */
+#define CKM_BLOWFISH_KEY_GEN 0x00001090
+#define CKM_BLOWFISH_CBC 0x00001091
+#define CKM_TWOFISH_KEY_GEN 0x00001092
+#define CKM_TWOFISH_CBC 0x00001093
+
+
+/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */
+#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100
+#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101
+#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102
+#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103
+#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104
+#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105
+
+#define CKM_DSA_PARAMETER_GEN 0x00002000
+#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
+#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002
+
+#define CKM_VENDOR_DEFINED 0x80000000
+
+typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
+
+
+/* CK_MECHANISM is a structure that specifies a particular
+ * mechanism */
+typedef struct CK_MECHANISM {
+ CK_MECHANISM_TYPE mechanism;
+ CK_VOID_PTR pParameter;
+
+ /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulParameterLen; /* in bytes */
+} CK_MECHANISM;
+
+typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
+
+
+/* CK_MECHANISM_INFO provides information about a particular
+ * mechanism */
+typedef struct CK_MECHANISM_INFO {
+ CK_ULONG ulMinKeySize;
+ CK_ULONG ulMaxKeySize;
+ CK_FLAGS flags;
+} CK_MECHANISM_INFO;
+
+/* The flags are defined as follows:
+ * Bit Flag Mask Meaning */
+#define CKF_HW 0x00000001 /* performed by HW */
+
+// Added by KS
+#define CKF_SW 0x00000000 /* performed by SW */
+
+/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
+ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
+ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
+ * and CKF_DERIVE are new for v2.0. They specify whether or not
+ * a mechanism can be used for a particular task */
+#define CKF_ENCRYPT 0x00000100
+#define CKF_DECRYPT 0x00000200
+#define CKF_DIGEST 0x00000400
+#define CKF_SIGN 0x00000800
+#define CKF_SIGN_RECOVER 0x00001000
+#define CKF_VERIFY 0x00002000
+#define CKF_VERIFY_RECOVER 0x00004000
+#define CKF_GENERATE 0x00008000
+#define CKF_GENERATE_KEY_PAIR 0x00010000
+#define CKF_WRAP 0x00020000
+#define CKF_UNWRAP 0x00040000
+#define CKF_DERIVE 0x00080000
+
+/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
+ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
+ * describe a token's EC capabilities not available in mechanism
+ * information. */
+#define CKF_EC_F_P 0x00100000
+#define CKF_EC_F_2M 0x00200000
+#define CKF_EC_ECPARAMETERS 0x00400000
+#define CKF_EC_NAMEDCURVE 0x00800000
+#define CKF_EC_UNCOMPRESS 0x01000000
+#define CKF_EC_COMPRESS 0x02000000
+
+#define CKF_EXTENSION 0x80000000 /* FALSE for this version */
+
+typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
+
+
+/* CK_RV is a value that identifies the return value of a
+ * Cryptoki function */
+/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
+typedef CK_ULONG CK_RV;
+
+#define CKR_OK 0x00000000
+#define CKR_CANCEL 0x00000001
+#define CKR_HOST_MEMORY 0x00000002
+#define CKR_SLOT_ID_INVALID 0x00000003
+
+/* CKR_FLAGS_INVALID was removed for v2.0 */
+
+/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
+#define CKR_GENERAL_ERROR 0x00000005
+#define CKR_FUNCTION_FAILED 0x00000006
+
+/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
+ * and CKR_CANT_LOCK are new for v2.01 */
+#define CKR_ARGUMENTS_BAD 0x00000007
+#define CKR_NO_EVENT 0x00000008
+#define CKR_NEED_TO_CREATE_THREADS 0x00000009
+#define CKR_CANT_LOCK 0x0000000A
+
+#define CKR_ATTRIBUTE_READ_ONLY 0x00000010
+#define CKR_ATTRIBUTE_SENSITIVE 0x00000011
+#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012
+#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013
+#define CKR_DATA_INVALID 0x00000020
+#define CKR_DATA_LEN_RANGE 0x00000021
+#define CKR_DEVICE_ERROR 0x00000030
+#define CKR_DEVICE_MEMORY 0x00000031
+#define CKR_DEVICE_REMOVED 0x00000032
+#define CKR_ENCRYPTED_DATA_INVALID 0x00000040
+#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041
+#define CKR_FUNCTION_CANCELED 0x00000050
+#define CKR_FUNCTION_NOT_PARALLEL 0x00000051
+
+/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
+#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054
+
+#define CKR_KEY_HANDLE_INVALID 0x00000060
+
+/* CKR_KEY_SENSITIVE was removed for v2.0 */
+
+#define CKR_KEY_SIZE_RANGE 0x00000062
+#define CKR_KEY_TYPE_INCONSISTENT 0x00000063
+
+/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
+ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
+ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
+ * v2.0 */
+#define CKR_KEY_NOT_NEEDED 0x00000064
+#define CKR_KEY_CHANGED 0x00000065
+#define CKR_KEY_NEEDED 0x00000066
+#define CKR_KEY_INDIGESTIBLE 0x00000067
+#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068
+#define CKR_KEY_NOT_WRAPPABLE 0x00000069
+#define CKR_KEY_UNEXTRACTABLE 0x0000006A
+
+#define CKR_MECHANISM_INVALID 0x00000070
+#define CKR_MECHANISM_PARAM_INVALID 0x00000071
+
+/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
+ * were removed for v2.0 */
+#define CKR_OBJECT_HANDLE_INVALID 0x00000082
+#define CKR_OPERATION_ACTIVE 0x00000090
+#define CKR_OPERATION_NOT_INITIALIZED 0x00000091
+#define CKR_PIN_INCORRECT 0x000000A0
+#define CKR_PIN_INVALID 0x000000A1
+#define CKR_PIN_LEN_RANGE 0x000000A2
+
+/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
+#define CKR_PIN_EXPIRED 0x000000A3
+#define CKR_PIN_LOCKED 0x000000A4
+
+#define CKR_SESSION_CLOSED 0x000000B0
+#define CKR_SESSION_COUNT 0x000000B1
+#define CKR_SESSION_HANDLE_INVALID 0x000000B3
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4
+#define CKR_SESSION_READ_ONLY 0x000000B5
+#define CKR_SESSION_EXISTS 0x000000B6
+
+/* CKR_SESSION_READ_ONLY_EXISTS and
+ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
+#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7
+#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8
+
+#define CKR_SIGNATURE_INVALID 0x000000C0
+#define CKR_SIGNATURE_LEN_RANGE 0x000000C1
+#define CKR_TEMPLATE_INCOMPLETE 0x000000D0
+#define CKR_TEMPLATE_INCONSISTENT 0x000000D1
+#define CKR_TOKEN_NOT_PRESENT 0x000000E0
+#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1
+#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2
+#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2
+#define CKR_USER_ALREADY_LOGGED_IN 0x00000100
+#define CKR_USER_NOT_LOGGED_IN 0x00000101
+#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102
+#define CKR_USER_TYPE_INVALID 0x00000103
+
+/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
+ * are new to v2.01 */
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104
+#define CKR_USER_TOO_MANY_TYPES 0x00000105
+
+#define CKR_WRAPPED_KEY_INVALID 0x00000110
+#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112
+#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113
+#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115
+#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120
+
+/* These are new to v2.0 */
+#define CKR_RANDOM_NO_RNG 0x00000121
+
+/* These are new to v2.11 */
+#define CKR_DOMAIN_PARAMS_INVALID 0x00000130
+
+/* These are new to v2.0 */
+#define CKR_BUFFER_TOO_SMALL 0x00000150
+#define CKR_SAVED_STATE_INVALID 0x00000160
+#define CKR_INFORMATION_SENSITIVE 0x00000170
+#define CKR_STATE_UNSAVEABLE 0x00000180
+
+/* These are new to v2.01 */
+#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191
+#define CKR_MUTEX_BAD 0x000001A0
+#define CKR_MUTEX_NOT_LOCKED 0x000001A1
+
+/* This is new to v2.20 */
+#define CKR_FUNCTION_REJECTED 0x00000200
+
+#define CKR_VENDOR_DEFINED 0x80000000
+
+
+/* CK_NOTIFY is an application callback that processes events */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
+ CK_SESSION_HANDLE hSession, /* the session's handle */
+ CK_NOTIFICATION event,
+ CK_VOID_PTR pApplication /* passed to C_OpenSession */
+);
+
+
+/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
+ * version and pointers of appropriate types to all the
+ * Cryptoki functions */
+/* CK_FUNCTION_LIST is new for v2.0 */
+typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
+
+typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
+
+typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
+
+
+/* CK_CREATEMUTEX is an application callback for creating a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
+ CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */
+);
+
+
+/* CK_DESTROYMUTEX is an application callback for destroying a
+ * mutex object */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_LOCKMUTEX is an application callback for locking a mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_UNLOCKMUTEX is an application callback for unlocking a
+ * mutex */
+typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
+ CK_VOID_PTR pMutex /* pointer to mutex */
+);
+
+
+/* CK_C_INITIALIZE_ARGS provides the optional arguments to
+ * C_Initialize */
+typedef struct CK_C_INITIALIZE_ARGS {
+ CK_CREATEMUTEX CreateMutex;
+ CK_DESTROYMUTEX DestroyMutex;
+ CK_LOCKMUTEX LockMutex;
+ CK_UNLOCKMUTEX UnlockMutex;
+ CK_FLAGS flags;
+ CK_VOID_PTR pReserved;
+} CK_C_INITIALIZE_ARGS;
+
+/* flags: bit flags that provide capabilities of the slot
+ * Bit Flag Mask Meaning
+ */
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
+#define CKF_OS_LOCKING_OK 0x00000002
+
+typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
+
+
+/* additional flags for parameters to functions */
+
+/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
+#define CKF_DONT_BLOCK 1
+
+/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message
+ * Generation Function (MGF) applied to a message block when
+ * formatting a message block for the PKCS #1 OAEP encryption
+ * scheme. */
+typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
+
+typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
+
+/* The following MGFs are defined */
+/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512
+ * are new for v2.20 */
+#define CKG_MGF1_SHA1 0x00000001
+#define CKG_MGF1_SHA256 0x00000002
+#define CKG_MGF1_SHA384 0x00000003
+#define CKG_MGF1_SHA512 0x00000004
+
+/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
+ * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
+ * of the encoding parameter when formatting a message block
+ * for the PKCS #1 OAEP encryption scheme. */
+typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
+
+typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
+
+/* The following encoding parameter sources are defined */
+#define CKZ_DATA_SPECIFIED 0x00000001
+
+/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
+ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_OAEP mechanism. */
+typedef struct CK_RSA_PKCS_OAEP_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
+ CK_VOID_PTR pSourceData;
+ CK_ULONG ulSourceDataLen;
+} CK_RSA_PKCS_OAEP_PARAMS;
+
+typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
+
+/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
+ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
+ * CKM_RSA_PKCS_PSS mechanism(s). */
+typedef struct CK_RSA_PKCS_PSS_PARAMS {
+ CK_MECHANISM_TYPE hashAlg;
+ CK_RSA_PKCS_MGF_TYPE mgf;
+ CK_ULONG sLen;
+} CK_RSA_PKCS_PSS_PARAMS;
+
+typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
+
+/* CK_EC_KDF_TYPE is new for v2.11. */
+typedef CK_ULONG CK_EC_KDF_TYPE;
+
+/* The following EC Key Derivation Functions are defined */
+#define CKD_NULL 0x00000001
+#define CKD_SHA1_KDF 0x00000002
+
+/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
+ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
+ * where each party contributes one key pair.
+ */
+typedef struct CK_ECDH1_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_ECDH1_DERIVE_PARAMS;
+
+typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
+
+
+/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
+ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
+typedef struct CK_ECDH2_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+} CK_ECDH2_DERIVE_PARAMS;
+
+typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
+
+typedef struct CK_ECMQV_DERIVE_PARAMS {
+ CK_EC_KDF_TYPE kdf;
+ CK_ULONG ulSharedDataLen;
+ CK_BYTE_PTR pSharedData;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+ CK_OBJECT_HANDLE publicKey;
+} CK_ECMQV_DERIVE_PARAMS;
+
+typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;
+
+/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
+ * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
+typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
+typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
+
+/* The following X9.42 DH key derivation functions are defined
+ (besides CKD_NULL already defined : */
+#define CKD_SHA1_KDF_ASN1 0x00000003
+#define CKD_SHA1_KDF_CONCATENATE 0x00000004
+
+/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
+ * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
+ * contributes one key pair */
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_X9_42_DH1_DERIVE_PARAMS;
+
+typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
+
+/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
+ * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
+ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
+ * mechanisms, where each party contributes two key pairs */
+typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+} CK_X9_42_DH2_DERIVE_PARAMS;
+
+typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
+
+typedef struct CK_X9_42_MQV_DERIVE_PARAMS {
+ CK_X9_42_DH_KDF_TYPE kdf;
+ CK_ULONG ulOtherInfoLen;
+ CK_BYTE_PTR pOtherInfo;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPrivateDataLen;
+ CK_OBJECT_HANDLE hPrivateData;
+ CK_ULONG ulPublicDataLen2;
+ CK_BYTE_PTR pPublicData2;
+ CK_OBJECT_HANDLE publicKey;
+} CK_X9_42_MQV_DERIVE_PARAMS;
+
+typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;
+
+/* CK_KEA_DERIVE_PARAMS provides the parameters to the
+ * CKM_KEA_DERIVE mechanism */
+/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
+typedef struct CK_KEA_DERIVE_PARAMS {
+ CK_BBOOL isSender;
+ CK_ULONG ulRandomLen;
+ CK_BYTE_PTR pRandomA;
+ CK_BYTE_PTR pRandomB;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+} CK_KEA_DERIVE_PARAMS;
+
+typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
+
+
+/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
+ * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just
+ * holds the effective keysize */
+typedef CK_ULONG CK_RC2_PARAMS;
+
+typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
+
+
+/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
+ * mechanism */
+typedef struct CK_RC2_CBC_PARAMS {
+ /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
+ * v2.0 */
+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
+
+ CK_BYTE iv[8]; /* IV for CBC mode */
+} CK_RC2_CBC_PARAMS;
+
+typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
+
+
+/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC2_MAC_GENERAL mechanism */
+/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC2_MAC_GENERAL_PARAMS {
+ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
+ CK_ULONG ulMacLength; /* Length of MAC in bytes */
+} CK_RC2_MAC_GENERAL_PARAMS;
+
+typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
+ CK_RC2_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
+ * CKM_RC5_MAC mechanisms */
+/* CK_RC5_PARAMS is new for v2.0 */
+typedef struct CK_RC5_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+} CK_RC5_PARAMS;
+
+typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
+
+
+/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
+ * mechanism */
+/* CK_RC5_CBC_PARAMS is new for v2.0 */
+typedef struct CK_RC5_CBC_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+ CK_BYTE_PTR pIv; /* pointer to IV */
+ CK_ULONG ulIvLen; /* length of IV in bytes */
+} CK_RC5_CBC_PARAMS;
+
+typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
+
+
+/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
+ * CKM_RC5_MAC_GENERAL mechanism */
+/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef struct CK_RC5_MAC_GENERAL_PARAMS {
+ CK_ULONG ulWordsize; /* wordsize in bits */
+ CK_ULONG ulRounds; /* number of rounds */
+ CK_ULONG ulMacLength; /* Length of MAC in bytes */
+} CK_RC5_MAC_GENERAL_PARAMS;
+
+typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
+ CK_RC5_MAC_GENERAL_PARAMS_PTR;
+
+
+/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
+ * ciphers' MAC_GENERAL mechanisms. Its value is the length of
+ * the MAC */
+/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
+typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
+
+typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
+
+/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */
+typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[8];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_DES_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
+ CK_BYTE iv[16];
+ CK_BYTE_PTR pData;
+ CK_ULONG length;
+} CK_AES_CBC_ENCRYPT_DATA_PARAMS;
+
+typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
+/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
+ CK_ULONG ulPasswordLen;
+ CK_BYTE_PTR pPassword;
+ CK_ULONG ulPublicDataLen;
+ CK_BYTE_PTR pPublicData;
+ CK_ULONG ulPAndGLen;
+ CK_ULONG ulQLen;
+ CK_ULONG ulRandomLen;
+ CK_BYTE_PTR pRandomA;
+ CK_BYTE_PTR pPrimeP;
+ CK_BYTE_PTR pBaseG;
+ CK_BYTE_PTR pSubprimeQ;
+} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
+
+typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
+ CK_SKIPJACK_PRIVATE_WRAP_PTR;
+
+
+/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
+ * CKM_SKIPJACK_RELAYX mechanism */
+/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
+typedef struct CK_SKIPJACK_RELAYX_PARAMS {
+ CK_ULONG ulOldWrappedXLen;
+ CK_BYTE_PTR pOldWrappedX;
+ CK_ULONG ulOldPasswordLen;
+ CK_BYTE_PTR pOldPassword;
+ CK_ULONG ulOldPublicDataLen;
+ CK_BYTE_PTR pOldPublicData;
+ CK_ULONG ulOldRandomLen;
+ CK_BYTE_PTR pOldRandomA;
+ CK_ULONG ulNewPasswordLen;
+ CK_BYTE_PTR pNewPassword;
+ CK_ULONG ulNewPublicDataLen;
+ CK_BYTE_PTR pNewPublicData;
+ CK_ULONG ulNewRandomLen;
+ CK_BYTE_PTR pNewRandomA;
+} CK_SKIPJACK_RELAYX_PARAMS;
+
+typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
+ CK_SKIPJACK_RELAYX_PARAMS_PTR;
+
+
+typedef struct CK_PBE_PARAMS {
+ CK_BYTE_PTR pInitVector;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG ulPasswordLen;
+ CK_BYTE_PTR pSalt;
+ CK_ULONG ulSaltLen;
+ CK_ULONG ulIteration;
+} CK_PBE_PARAMS;
+
+typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
+
+
+/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
+ * CKM_KEY_WRAP_SET_OAEP mechanism */
+/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
+typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
+ CK_BYTE bBC; /* block contents byte */
+ CK_BYTE_PTR pX; /* extra data */
+ CK_ULONG ulXLen; /* length of extra data in bytes */
+} CK_KEY_WRAP_SET_OAEP_PARAMS;
+
+typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
+ CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
+
+
+typedef struct CK_SSL3_RANDOM_DATA {
+ CK_BYTE_PTR pClientRandom;
+ CK_ULONG ulClientRandomLen;
+ CK_BYTE_PTR pServerRandom;
+ CK_ULONG ulServerRandomLen;
+} CK_SSL3_RANDOM_DATA;
+
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_VERSION_PTR pVersion;
+} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
+
+typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
+ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_OUT {
+ CK_OBJECT_HANDLE hClientMacSecret;
+ CK_OBJECT_HANDLE hServerMacSecret;
+ CK_OBJECT_HANDLE hClientKey;
+ CK_OBJECT_HANDLE hServerKey;
+ CK_BYTE_PTR pIVClient;
+ CK_BYTE_PTR pIVServer;
+} CK_SSL3_KEY_MAT_OUT;
+
+typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
+
+
+typedef struct CK_SSL3_KEY_MAT_PARAMS {
+ CK_ULONG ulMacSizeInBits;
+ CK_ULONG ulKeySizeInBits;
+ CK_ULONG ulIVSizeInBits;
+ CK_BBOOL bIsExport;
+ CK_SSL3_RANDOM_DATA RandomInfo;
+ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_SSL3_KEY_MAT_PARAMS;
+
+typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
+
+/* CK_TLS_PRF_PARAMS is new for version 2.20 */
+typedef struct CK_TLS_PRF_PARAMS {
+ CK_BYTE_PTR pSeed;
+ CK_ULONG ulSeedLen;
+ CK_BYTE_PTR pLabel;
+ CK_ULONG ulLabelLen;
+ CK_BYTE_PTR pOutput;
+ CK_ULONG_PTR pulOutputLen;
+} CK_TLS_PRF_PARAMS;
+
+typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;
+
+/* WTLS is new for version 2.20 */
+typedef struct CK_WTLS_RANDOM_DATA {
+ CK_BYTE_PTR pClientRandom;
+ CK_ULONG ulClientRandomLen;
+ CK_BYTE_PTR pServerRandom;
+ CK_ULONG ulServerRandomLen;
+} CK_WTLS_RANDOM_DATA;
+
+typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;
+
+typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {
+ CK_MECHANISM_TYPE DigestMechanism;
+ CK_WTLS_RANDOM_DATA RandomInfo;
+ CK_BYTE_PTR pVersion;
+} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;
+
+typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \
+ CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;
+
+typedef struct CK_WTLS_PRF_PARAMS {
+ CK_MECHANISM_TYPE DigestMechanism;
+ CK_BYTE_PTR pSeed;
+ CK_ULONG ulSeedLen;
+ CK_BYTE_PTR pLabel;
+ CK_ULONG ulLabelLen;
+ CK_BYTE_PTR pOutput;
+ CK_ULONG_PTR pulOutputLen;
+} CK_WTLS_PRF_PARAMS;
+
+typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;
+
+typedef struct CK_WTLS_KEY_MAT_OUT {
+ CK_OBJECT_HANDLE hMacSecret;
+ CK_OBJECT_HANDLE hKey;
+ CK_BYTE_PTR pIV;
+} CK_WTLS_KEY_MAT_OUT;
+
+typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
+
+typedef struct CK_WTLS_KEY_MAT_PARAMS {
+ CK_MECHANISM_TYPE DigestMechanism;
+ CK_ULONG ulMacSizeInBits;
+ CK_ULONG ulKeySizeInBits;
+ CK_ULONG ulIVSizeInBits;
+ CK_ULONG ulSequenceNumber;
+ CK_BBOOL bIsExport;
+ CK_WTLS_RANDOM_DATA RandomInfo;
+ CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
+} CK_WTLS_KEY_MAT_PARAMS;
+
+typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
+
+/* CMS is new for version 2.20 */
+typedef struct CK_CMS_SIG_PARAMS {
+ CK_OBJECT_HANDLE certificateHandle;
+ CK_MECHANISM_PTR pSigningMechanism;
+ CK_MECHANISM_PTR pDigestMechanism;
+ CK_UTF8CHAR_PTR pContentType;
+ CK_BYTE_PTR pRequestedAttributes;
+ CK_ULONG ulRequestedAttributesLen;
+ CK_BYTE_PTR pRequiredAttributes;
+ CK_ULONG ulRequiredAttributesLen;
+} CK_CMS_SIG_PARAMS;
+
+typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;
+
+typedef struct CK_KEY_DERIVATION_STRING_DATA {
+ CK_BYTE_PTR pData;
+ CK_ULONG ulLen;
+} CK_KEY_DERIVATION_STRING_DATA;
+
+typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
+ CK_KEY_DERIVATION_STRING_DATA_PTR;
+
+
+/* The CK_EXTRACT_PARAMS is used for the
+ * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit
+ * of the base key should be used as the first bit of the
+ * derived key */
+/* CK_EXTRACT_PARAMS is new for v2.0 */
+typedef CK_ULONG CK_EXTRACT_PARAMS;
+
+typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
+
+/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
+ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
+ * indicate the Pseudo-Random Function (PRF) used to generate
+ * key bits using PKCS #5 PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
+
+typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
+
+/* The following PRFs are defined in PKCS #5 v2.0. */
+#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
+
+
+/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
+ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
+ * source of the salt value when deriving a key using PKCS #5
+ * PBKDF2. */
+typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
+
+typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
+
+/* The following salt value sources are defined in PKCS #5 v2.0. */
+#define CKZ_SALT_SPECIFIED 0x00000001
+
+/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
+ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
+ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
+typedef struct CK_PKCS5_PBKD2_PARAMS {
+ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
+ CK_VOID_PTR pSaltSourceData;
+ CK_ULONG ulSaltSourceDataLen;
+ CK_ULONG iterations;
+ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
+ CK_VOID_PTR pPrfData;
+ CK_ULONG ulPrfDataLen;
+ CK_UTF8CHAR_PTR pPassword;
+ CK_ULONG_PTR ulPasswordLen;
+} CK_PKCS5_PBKD2_PARAMS;
+
+typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/platconfig.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/platconfig.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/platconfig.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,97 @@
+/* cryptoki.h include file for PKCS #11. */
+/* $Revision: 1.4 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* This is a sample file containing the top level include directives
+ * for building Win32 Cryptoki libraries and applications.
+ */
+
+#ifndef _include_platconfig_h
+#define _include_platconfig_h
+
+#ifndef NULL_PTR
+ #define NULL_PTR 0
+#endif
+
+#ifdef _WIN32
+
+#pragma pack(push, plcryptoki, 1)
+
+/* Specifies that the function is a DLL entry point. */
+#define CK_IMPORT_SPEC __declspec(dllimport)
+
+#ifdef CRYPTOKI_EXPORTS
+#define CK_EXPORT_SPEC __declspec(dllexport)
+#else
+#define CK_EXPORT_SPEC CK_IMPORT_SPEC
+#endif
+
+/* Ensures the calling convention for Win32 builds */
+#define CK_CALL_SPEC __cdecl
+
+#define CK_PTR *
+
+#define CK_DEFINE_FUNCTION(returnType, name) \
+ returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION(returnType, name) \
+ returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ returnType CK_IMPORT_SPEC (CK_CALL_SPEC CK_PTR name)
+
+#define CK_CALLBACK_FUNCTION(returnType, name) \
+ returnType (CK_CALL_SPEC CK_PTR name)
+
+#ifdef _DEBUG
+ #define PKCS11_ASSERT(X) assert(X)
+#else
+ #define PKCS11_ASSERT(X)
+#endif
+
+#include "pkcs11.h"
+
+#pragma pack(pop, plcryptoki)
+
+#else
+
+#define CK_IMPORT_SPEC
+#define CK_EXPORT_SPEC
+#define CK_CALL_SPEC
+
+#define CK_PTR *
+
+#define CK_DEFINE_FUNCTION(returnType, name) \
+ returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION(returnType, name) \
+ returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ returnType CK_IMPORT_SPEC (CK_CALL_SPEC CK_PTR name)
+
+#define CK_CALLBACK_FUNCTION(returnType, name) \
+ returnType (CK_CALL_SPEC CK_PTR name)
+
+#define PKCS11_ASSERT(X)
+
+#include "pkcs11.h"
+
+#endif
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,372 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "privatekeyobject.h"
+
+PrivateKeyObject :: PrivateKeyObject() : KeyObject()
+{
+ this->_class = CKO_PRIVATE_KEY;
+
+ this->_subject = NULL_PTR;
+ this->_sensitive = CK_TRUE;
+ this->_decrypt = CK_TRUE;
+ this->_sign = CK_TRUE;
+ this->_signRecover = CK_TRUE;
+ this->_unwrap = CK_FALSE;
+ this->_extractable = CK_FALSE;
+ this->_alwaysSensitive = CK_TRUE;
+ this->_neverExtractable = CK_TRUE;
+ this->_wrapWithTrusted = CK_FALSE;
+ this->_alwaysAuthenticate = CK_FALSE;
+
+ this->_ctrIndex = 0xFF; //-1;
+ this->_keyType = CK_UNAVAILABLE_INFORMATION; //-1;
+}
+
+PrivateKeyObject :: ~PrivateKeyObject(){
+
+ if(this->_subject != NULL_PTR){
+ delete this->_subject;
+ }
+}
+
+bool PrivateKeyObject::IsEqual(const StorageObject * that) const
+{
+ if(_uniqueId != 0 && that->_uniqueId != 0)
+ return (_uniqueId == that->_uniqueId);
+
+ // Only objects that have been stored under p11 directory
+ // will have a non-zero _uniqueId. For other objects, do
+ // a deep comparison based on other attributes.
+ if(_class != that->_class)
+ return false;
+
+ const PrivateKeyObject * thatCert = static_cast<const PrivateKeyObject*>(that);
+ return ( (_ctrIndex == thatCert->_ctrIndex) &&
+ (_keySpec == thatCert->_keySpec) &&
+ (_checkValue == thatCert->_checkValue));
+}
+
+CK_BBOOL PrivateKeyObject::Compare(CK_ATTRIBUTE attribute)
+{
+ switch(attribute.type){
+
+ case CKA_SENSITIVE:
+ return (this->_sensitive == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_DECRYPT:
+ return (this->_decrypt == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_SIGN:
+ return (this->_sign == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_SIGN_RECOVER:
+ return (this->_signRecover == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_UNWRAP:
+ return (this->_unwrap == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_EXTRACTABLE:
+ return (this->_extractable == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_ALWAYS_SENSITIVE:
+ return (this->_alwaysSensitive == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_NEVER_EXTRACTABLE:
+ return (this->_neverExtractable == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_WRAP_WITH_TRUSTED:
+ return (this->_wrapWithTrusted == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_ALWAYS_AUTHENTICATE:
+ return (this->_alwaysAuthenticate == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_SUBJECT:
+ return Util::CompareU1Arrays(this->_subject,attribute.pValue,attribute.ulValueLen);
+
+ default:
+ return KeyObject::Compare(attribute);
+
+ }
+}
+
+CK_RV PrivateKeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+ switch(attribute->type){
+
+ case CKA_SENSITIVE:
+ return StorageObject::PutBBoolInAttribute(this->_sensitive,attribute);
+
+ case CKA_DECRYPT:
+ return StorageObject::PutBBoolInAttribute(this->_decrypt,attribute);
+
+ case CKA_SIGN:
+ return StorageObject::PutBBoolInAttribute(this->_sign,attribute);
+
+ case CKA_SIGN_RECOVER:
+ return StorageObject::PutBBoolInAttribute(this->_signRecover,attribute);
+
+ case CKA_UNWRAP:
+ return StorageObject::PutBBoolInAttribute(this->_unwrap,attribute);
+
+ case CKA_EXTRACTABLE:
+ return StorageObject::PutBBoolInAttribute(this->_extractable,attribute);
+
+ case CKA_ALWAYS_SENSITIVE:
+ return StorageObject::PutBBoolInAttribute(this->_alwaysSensitive,attribute);
+
+ case CKA_NEVER_EXTRACTABLE:
+ return StorageObject::PutBBoolInAttribute(this->_neverExtractable,attribute);
+
+ case CKA_WRAP_WITH_TRUSTED:
+ return StorageObject::PutBBoolInAttribute(this->_wrapWithTrusted,attribute);
+
+ case CKA_ALWAYS_AUTHENTICATE:
+ return StorageObject::PutBBoolInAttribute(this->_alwaysAuthenticate,attribute);
+
+ case CKA_SUBJECT:
+ return StorageObject::PutU1ArrayInAttribute(this->_subject,attribute);
+
+ default:
+ return KeyObject::GetAttribute(attribute);
+ }
+}
+
+CK_RV PrivateKeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+ if( 0 == attribute.ulValueLen )
+ {
+ return CKR_OK;
+ }
+
+ CK_RV rv = CKR_OK;
+
+ if(objCreation == CK_FALSE)
+ {
+ switch(attribute.type)
+ {
+ case CKA_ALWAYS_AUTHENTICATE:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_NEVER_EXTRACTABLE:
+ return CKR_ATTRIBUTE_READ_ONLY;
+
+ case CKA_DECRYPT:
+ case CKA_EXTRACTABLE:
+ case CKA_SENSITIVE:
+ case CKA_SIGN:
+ case CKA_SIGN_RECOVER:
+ case CKA_UNWRAP:
+ case CKA_WRAP_WITH_TRUSTED:
+ if(*(CK_BBOOL*)attribute.pValue == CK_TRUE){
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ break;
+ }
+ }
+
+ switch(attribute.type){
+
+ case CKA_SENSITIVE:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){
+
+ if((objCreation == CK_FALSE) && (this->_sensitive == CK_TRUE) && (btemp == CK_FALSE)){
+ rv = CKR_ATTRIBUTE_READ_ONLY;
+ }else{
+ this->_sensitive = btemp;
+
+ if(btemp == CK_FALSE){
+ this->_alwaysSensitive = CK_FALSE;
+ }
+ }
+ }
+ }
+ break;
+
+ case CKA_DECRYPT:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_decrypt = btemp; }
+ }
+ break;
+
+ case CKA_SIGN:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_sign = btemp; }
+ }
+ break;
+
+ case CKA_SIGN_RECOVER:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_signRecover = btemp; }
+ }
+ break;
+
+ case CKA_UNWRAP:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_unwrap = btemp; }
+ }
+ break;
+
+ case CKA_EXTRACTABLE:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){
+
+ if((objCreation == CK_FALSE) && (this->_extractable == CK_FALSE) && (btemp == CK_TRUE)){
+ rv = CKR_ATTRIBUTE_READ_ONLY;
+ }else{
+ this->_extractable = btemp;
+
+ if(btemp == CK_TRUE){
+ this->_neverExtractable = CK_FALSE;
+ }
+ }
+ }
+ }
+ break;
+
+ case CKA_ALWAYS_SENSITIVE:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_alwaysSensitive = btemp; }
+ }
+ break;
+
+
+ case CKA_NEVER_EXTRACTABLE:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_neverExtractable = btemp; }
+ }
+ break;
+
+ case CKA_WRAP_WITH_TRUSTED:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_wrapWithTrusted = btemp; }
+ }
+ break;
+
+ case CKA_ALWAYS_AUTHENTICATE:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_alwaysAuthenticate = btemp; }
+ }
+ break;
+
+ case CKA_SUBJECT:
+ if(this->_subject != NULL_PTR){
+ delete this->_subject;
+ }
+ this->_subject = StorageObject::ReadU1ArrayFromAttribute(attribute);
+
+ break;
+
+ default:
+ return KeyObject::SetAttribute(attribute,objCreation);
+ }
+
+ return rv;
+}
+
+void PrivateKeyObject::Serialize(std::vector<u1> *to)
+{
+ KeyObject::Serialize(to);
+
+ Util::PushBBoolInVector(to,this->_sensitive);
+
+ Util::PushBBoolInVector(to,this->_decrypt);
+
+ Util::PushBBoolInVector(to,this->_sign);
+
+ Util::PushBBoolInVector(to,this->_signRecover);
+
+ Util::PushBBoolInVector(to,this->_unwrap);
+
+ Util::PushBBoolInVector(to,this->_extractable);
+
+ Util::PushBBoolInVector(to,this->_alwaysSensitive);
+
+ Util::PushBBoolInVector(to,this->_neverExtractable);
+
+ Util::PushBBoolInVector(to,this->_wrapWithTrusted);
+
+ Util::PushBBoolInVector(to,this->_alwaysAuthenticate);
+
+ Util::PushByteArrayInVector(to,this->_subject);
+
+ // serialize the extra fields
+
+ PKCS11_ASSERT(_checkValue != 0);
+ PKCS11_ASSERT(_ctrIndex < 100);
+ PKCS11_ASSERT(_keySpec == 1 || _keySpec == 2 );
+
+ Util::PushULongLongInVector(to,this->_checkValue);
+
+ Util::PushBBoolInVector(to,this->_ctrIndex);
+
+ Util::PushBBoolInVector(to,this->_keySpec);
+}
+
+void PrivateKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+ KeyObject::Deserialize(from,idx);
+
+ this->_sensitive = Util::ReadBBoolFromVector(from,idx);
+
+ this->_decrypt = Util::ReadBBoolFromVector(from,idx);
+
+ this->_sign = Util::ReadBBoolFromVector(from,idx);
+
+ this->_signRecover = Util::ReadBBoolFromVector(from,idx);
+
+ this->_unwrap = Util::ReadBBoolFromVector(from,idx);
+
+ this->_extractable = Util::ReadBBoolFromVector(from,idx);
+
+ this->_alwaysSensitive = Util::ReadBBoolFromVector(from,idx);
+
+ this->_neverExtractable = Util::ReadBBoolFromVector(from,idx);
+
+ this->_wrapWithTrusted = Util::ReadBBoolFromVector(from,idx);
+
+ this->_alwaysAuthenticate = Util::ReadBBoolFromVector(from,idx);
+
+ this->_subject = Util::ReadByteArrayFromVector(from,idx);
+
+ // deserialize extra fields
+
+ this->_checkValue = Util::ReadULongLongFromVector(from,idx);
+
+ this->_ctrIndex = Util::ReadBBoolFromVector(from,idx);
+
+ this->_keySpec = Util::ReadBBoolFromVector(from,idx);
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/privatekeyobject.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,63 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_privatekeyobject_h
+#define _include_privatekeyobject_h
+
+#include "keyobject.h"
+
+class PrivateKeyObject : public KeyObject
+{
+
+public:
+ u1Array* _subject;
+ CK_BBOOL _sensitive;
+ CK_BBOOL _decrypt;
+ CK_BBOOL _sign;
+ CK_BBOOL _signRecover;
+ CK_BBOOL _unwrap;
+ CK_BBOOL _extractable;
+ CK_BBOOL _alwaysSensitive;
+ CK_BBOOL _neverExtractable;
+ CK_BBOOL _wrapWithTrusted;
+ CK_BBOOL _alwaysAuthenticate;
+
+ // extra fields which are not part of PKCS#11
+ // but are needed as extra information in card
+ u8 _checkValue;
+ CK_BYTE _ctrIndex;
+ CK_BYTE _keySpec;
+
+public:
+ PrivateKeyObject();
+ virtual ~PrivateKeyObject();
+
+ virtual bool IsEqual(const StorageObject * that) const;
+ virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+ virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+ virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+ virtual void Serialize(vector<u1>* to);
+ virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,205 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "publickeyobject.h"
+
+PublicKeyObject :: PublicKeyObject() : KeyObject()
+{
+ this->_class = CKO_PUBLIC_KEY;
+
+ this->_encrypt = CK_TRUE;
+ this->_verify = CK_TRUE;
+ this->_verifyRecover = CK_TRUE;
+ this->_wrap = CK_FALSE;
+
+ this->_subject = NULL_PTR;
+
+ this->_ctrIndex = 0xFF; //-1;
+ this->_keyType = CK_UNAVAILABLE_INFORMATION; //-1;
+}
+
+PublicKeyObject :: ~PublicKeyObject(){
+
+ if(this->_subject != NULL_PTR){
+ delete this->_subject;
+ }
+}
+
+CK_BBOOL PublicKeyObject::Compare(CK_ATTRIBUTE attribute)
+{
+ switch(attribute.type){
+
+ case CKA_ENCRYPT:
+ return (this->_encrypt == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_VERIFY:
+ return (this->_verify == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_VERIFY_RECOVER:
+ return (this->_verifyRecover == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_WRAP:
+ return (this->_wrap == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_SUBJECT:
+ return Util::CompareU1Arrays(this->_subject,attribute.pValue,attribute.ulValueLen);
+
+ default:
+ return KeyObject::Compare(attribute);
+ }
+}
+
+CK_RV PublicKeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+ switch(attribute->type){
+
+ case CKA_ENCRYPT:
+ return StorageObject::PutBBoolInAttribute(this->_encrypt,attribute);
+
+ case CKA_VERIFY:
+ return StorageObject::PutBBoolInAttribute(this->_verify,attribute);
+
+ case CKA_VERIFY_RECOVER:
+ return StorageObject::PutBBoolInAttribute(this->_verifyRecover,attribute);
+
+ case CKA_WRAP:
+ return StorageObject::PutBBoolInAttribute(this->_wrap,attribute);
+
+ case CKA_SUBJECT:
+ return StorageObject::PutU1ArrayInAttribute(this->_subject,attribute);
+
+ default:
+ return KeyObject::GetAttribute(attribute);
+
+ }
+}
+
+CK_RV PublicKeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+ if( 0 == attribute.ulValueLen )
+ {
+ return CKR_OK;
+ }
+
+ CK_RV rv = CKR_OK;
+
+ if(objCreation == CK_FALSE){
+ switch(attribute.type){
+ case CKA_ENCRYPT:
+ case CKA_TRUSTED:
+ case CKA_VERIFY:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ if(*(CK_BBOOL*)attribute.pValue == CK_TRUE){
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ break;
+ }
+ }
+
+ switch(attribute.type){
+
+ case CKA_ENCRYPT:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_encrypt = btemp; }
+ }
+ break;
+
+ case CKA_VERIFY:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_verify = btemp; }
+ }
+ break;
+
+ case CKA_VERIFY_RECOVER:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_verifyRecover = btemp; }
+ }
+ break;
+
+ case CKA_WRAP:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_wrap = btemp; }
+ }
+ break;
+
+ case CKA_SUBJECT:
+ if(this->_subject != NULL_PTR){
+ delete this->_subject;
+ }
+ this->_subject = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ default:
+ return KeyObject::SetAttribute(attribute,objCreation);
+ }
+
+ return rv;
+}
+
+void PublicKeyObject::Serialize(std::vector<u1> *to)
+{
+ KeyObject::Serialize(to);
+
+ Util::PushBBoolInVector(to,this->_encrypt);
+
+ Util::PushBBoolInVector(to,this->_verify);
+
+ Util::PushBBoolInVector(to,this->_verifyRecover);
+
+ Util::PushBBoolInVector(to,this->_wrap);
+
+ Util::PushByteArrayInVector(to,this->_subject);
+
+ // serialize the extra fields
+ Util::PushBBoolInVector(to,this->_ctrIndex);
+
+ Util::PushBBoolInVector(to,this->_keySpec);
+}
+
+void PublicKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+ KeyObject::Deserialize(from,idx);
+
+ this->_encrypt = Util::ReadBBoolFromVector(from,idx);
+
+ this->_verify = Util::ReadBBoolFromVector(from,idx);
+
+ this->_verifyRecover = Util::ReadBBoolFromVector(from,idx);
+
+ this->_wrap = Util::ReadBBoolFromVector(from,idx);
+
+ this->_subject = Util::ReadByteArrayFromVector(from,idx);
+
+ // deserialize extra fields
+ this->_ctrIndex = Util::ReadBBoolFromVector(from,idx);
+
+ this->_keySpec = Util::ReadBBoolFromVector(from,idx);
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/publickeyobject.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,56 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_publickeyobject_h
+#define _include_publickeyobject_h
+
+#include "keyobject.h"
+
+class PublicKeyObject : public KeyObject
+{
+
+public:
+ u1Array* _subject;
+ CK_BBOOL _encrypt;
+ CK_BBOOL _verify;
+ CK_BBOOL _verifyRecover;
+ CK_BBOOL _wrap;
+ CK_BBOOL _trusted;
+
+ // extra fields which are not part of PKCS#11
+ // but are needed as extra information in card
+ CK_BYTE _ctrIndex;
+ CK_BYTE _keySpec;
+
+public:
+ PublicKeyObject();
+ virtual ~PublicKeyObject();
+
+ virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+ virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+ virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+ virtual void Serialize(vector<u1>* to);
+ virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/resource.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/resource.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/resource.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by PKCS11Module.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,132 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "cr_global.h"
+#include "cr_nn.h"
+#include "cr_digit.h"
+
+/**
+ * Computes a = b * c, where b and c are digits.
+ *
+ * Lengths: a[2].
+ */
+void NN_DigitMult (NN_DIGIT a[2], NN_DIGIT b, NN_DIGIT c)
+{
+ NN_DIGIT t, u;
+ NN_HALF_DIGIT bHigh, bLow, cHigh, cLow;
+
+ bHigh = (NN_HALF_DIGIT)HIGH_HALF (b);
+ bLow = (NN_HALF_DIGIT)LOW_HALF (b);
+ cHigh = (NN_HALF_DIGIT)HIGH_HALF (c);
+ cLow = (NN_HALF_DIGIT)LOW_HALF (c);
+
+ a[0] = (NN_DIGIT)bLow * (NN_DIGIT)cLow;
+ t = (NN_DIGIT)bLow * (NN_DIGIT)cHigh;
+ u = (NN_DIGIT)bHigh * (NN_DIGIT)cLow;
+ a[1] = (NN_DIGIT)bHigh * (NN_DIGIT)cHigh;
+
+ if ((t += u) < u)
+ a[1] += TO_HIGH_HALF (1);
+ u = TO_HIGH_HALF (t);
+
+ if ((a[0] += u) < u)
+ a[1]++;
+ a[1] += HIGH_HALF (t);
+
+ return ;
+}
+
+/**
+ * Sets a = b / c, where a and c are digits.
+ *
+ * Lengths: b[2].
+ * Assumes b[1] < c and HIGH_HALF (c) > 0. For efficiency, c should be
+ * normalized.
+ */
+void NN_DigitDiv (NN_DIGIT *a, NN_DIGIT b[2], NN_DIGIT c)
+{
+ NN_DIGIT t[2], u, v;
+ NN_HALF_DIGIT aHigh, aLow, cHigh, cLow;
+
+ cHigh = (NN_HALF_DIGIT)HIGH_HALF (c);
+ cLow = (NN_HALF_DIGIT)LOW_HALF (c);
+
+ t[0] = b[0];
+ t[1] = b[1];
+
+ /**
+ * Underestimate high half of quotient and subtract.
+ */
+ if (cHigh == MAX_NN_HALF_DIGIT)
+ aHigh = (NN_HALF_DIGIT)HIGH_HALF (t[1]);
+ else
+ aHigh = (NN_HALF_DIGIT)(t[1] / (cHigh + 1));
+
+ u = (NN_DIGIT)aHigh * (NN_DIGIT)cLow;
+ v = (NN_DIGIT)aHigh * (NN_DIGIT)cHigh;
+ if ((t[0] -= TO_HIGH_HALF (u)) > (MAX_NN_DIGIT - TO_HIGH_HALF (u)))
+ t[1]--;
+ t[1] -= HIGH_HALF (u);
+ t[1] -= v;
+
+ /**
+ * Correct estimate.
+ */
+ while ((t[1] > cHigh) ||
+ ((t[1] == cHigh) && (t[0] >= TO_HIGH_HALF (cLow))))
+ {
+ if ((t[0] -= TO_HIGH_HALF (cLow)) > MAX_NN_DIGIT - TO_HIGH_HALF (cLow))
+ t[1]--;
+ t[1] -= cHigh;
+ aHigh++;
+ }
+
+ /**
+ * Underestimate low half of quotient and subtract.
+ */
+ if (cHigh == MAX_NN_HALF_DIGIT)
+ aLow = (NN_HALF_DIGIT)LOW_HALF (t[1]);
+ else
+ aLow = (NN_HALF_DIGIT)((TO_HIGH_HALF (t[1]) + HIGH_HALF (t[0])) / (cHigh + 1));
+
+ u = (NN_DIGIT)aLow * (NN_DIGIT)cLow;
+ v = (NN_DIGIT)aLow * (NN_DIGIT)cHigh;
+ if ((t[0] -= u) > (MAX_NN_DIGIT - u))
+ t[1]--;
+ if ((t[0] -= TO_HIGH_HALF (v)) > (MAX_NN_DIGIT - TO_HIGH_HALF (v)))
+ t[1]--;
+ t[1] -= HIGH_HALF (v);
+
+ /**
+ * Correct estimate.
+ */
+ while ((t[1] > 0) || ((t[1] == 0) && t[0] >= c))
+ {
+ if ((t[0] -= c) > (MAX_NN_DIGIT - c))
+ t[1]--;
+ aLow++;
+ }
+
+ *a = TO_HIGH_HALF (aHigh) + aLow;
+
+ return ;
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_digit.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,28 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _CR_DIGIT_H_
+#define _CR_DIGIT_H_
+
+void NN_DigitMult(NN_DIGIT [2], NN_DIGIT, NN_DIGIT) ;
+void NN_DigitDiv(NN_DIGIT *, NN_DIGIT [2], NN_DIGIT) ;
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_global.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_global.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_global.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,55 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _CR_GLOBAL_H_
+#define _CR_GLOBAL_H_
+
+/* POINTER defines a generic pointer type */
+typedef unsigned char *POINTER;
+
+/* UINT2 defines a two byte word */
+typedef unsigned short int UINT2;
+
+/* UINT4 defines a four byte word */
+typedef unsigned long int UINT4;
+
+/* Error codes.
+ */
+#define RE_CONTENT_ENCODING 0x0400
+#define RE_DATA 0x0401
+#define RE_DIGEST_ALGORITHM 0x0402
+#define RE_ENCODING 0x0403
+#define RE_KEY 0x0404
+#define RE_KEY_ENCODING 0x0405
+#define RE_LEN 0x0406
+#define RE_MODULUS_LEN 0x0407
+#define RE_NEED_RANDOM 0x0408
+#define RE_PRIVATE_KEY 0x0409
+#define RE_PUBLIC_KEY 0x040a
+#define RE_SIGNATURE 0x040b
+#define RE_SIGNATURE_ENCODING 0x040c
+#define RE_ENCRYPTION_ALGORITHM 0x040d
+
+#define R_memset(x, y, z) memset(x, y, z)
+#define R_memcpy(x, y, z) memcpy(x, y, z)
+#define R_memcmp(x, y, z) memcmp(x, y, z)
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,695 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "cr_rsa.h"
+#include "cr_global.h"
+#include "cr_nn.h"
+#include "cr_digit.h"
+
+static NN_DIGIT NN_AddDigitMult(NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int);
+static NN_DIGIT NN_SubDigitMult(NN_DIGIT *, NN_DIGIT *, NN_DIGIT, NN_DIGIT *, unsigned int);
+
+static unsigned int NN_DigitBits(NN_DIGIT);
+
+/**
+ * Decodes character string b into a, where character string is ordered
+ * from most to least significant.
+ *
+ * Lengths: a[digits], b[len].
+ * Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most
+ * significant bytes are truncated.)
+ */
+void NN_Decode (NN_DIGIT *a,
+ unsigned int digits,
+ const unsigned char *b,
+ unsigned int len)
+{
+ NN_DIGIT t;
+ int j;
+ unsigned int i, u;
+
+ for (i = 0, j = len - 1; i < digits && j >= 0; i++)
+ {
+ t = 0;
+ for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
+ t |= ((NN_DIGIT)b[j]) << u;
+ a[i] = t;
+ }
+
+ for (; i < digits; i++)
+ a[i] = 0;
+
+ return ;
+}
+
+/**
+ * Encodes b into character string a, where character string is ordered
+ * from most to least significant.
+ *
+ * Lengths: a[len], b[digits].
+ * Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant
+ * digits are truncated.)
+ */
+void NN_Encode (unsigned char *a,
+ unsigned int len,
+ NN_DIGIT *b,
+ unsigned int digits)
+{
+ NN_DIGIT t;
+ int j;
+ unsigned int i, u;
+
+ for (i = 0, j = len - 1; i < digits && j >= 0; i++)
+ {
+ t = b[i];
+ for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8)
+ a[j] = (unsigned char)(t >> u);
+ }
+
+ for (; j >= 0; j--)
+ a[j] = 0;
+
+ return ;
+}
+
+/**
+ * Assigns a = b.
+ *
+ * Lengths: a[digits], b[digits].
+ */
+void NN_Assign (NN_DIGIT *a, NN_DIGIT *b, unsigned int digits)
+{
+ unsigned int i;
+
+ for (i = 0; i < digits; i++)
+ a[i] = b[i];
+
+ return ;
+}
+
+/**
+ * Assigns a = 0.
+ *
+ * Lengths: a[digits].
+ */
+void NN_AssignZero (NN_DIGIT *a, unsigned int digits)
+{
+ unsigned int i;
+
+ for (i = 0; i < digits; i++)
+ a[i] = 0;
+
+ return ;
+}
+
+/**
+ * Assigns a = 2^b.
+ *
+ * Lengths: a[digits].
+ * Requires b < digits * NN_DIGIT_BITS.
+ */
+void NN_Assign2Exp (NN_DIGIT *a, unsigned int b, unsigned int digits)
+{
+ NN_AssignZero (a, digits);
+
+ if (b >= digits * NN_DIGIT_BITS)
+ return;
+
+ a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS);
+
+ return ;
+}
+
+/**
+ * Computes a = b + c. Returns carry.
+ *
+ * Lengths: a[digits], b[digits], c[digits].
+ */
+NN_DIGIT NN_Add (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+ NN_DIGIT ai, carry;
+ unsigned int i;
+
+ carry = 0;
+
+ for (i = 0; i < digits; i++)
+ {
+ if ((ai = b[i] + carry) < carry)
+ ai = c[i];
+ else if ((ai += c[i]) < c[i])
+ carry = 1;
+ else
+ carry = 0;
+ a[i] = ai;
+ }
+
+ return (carry);
+}
+
+/**
+ * Computes a = b - c. Returns borrow.
+ *
+ * Lengths: a[digits], b[digits], c[digits].
+ */
+NN_DIGIT NN_Sub (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+ NN_DIGIT ai, borrow;
+ unsigned int i;
+
+ borrow = 0;
+
+ for (i = 0; i < digits; i++)
+ {
+ if ((ai = b[i] - borrow) > (MAX_NN_DIGIT - borrow))
+ ai = MAX_NN_DIGIT - c[i];
+ else if ((ai -= c[i]) > (MAX_NN_DIGIT - c[i]))
+ borrow = 1;
+ else
+ borrow = 0;
+
+ a[i] = ai;
+ }
+
+ return (borrow);
+}
+
+/**
+ * Computes a = b * c.
+ *
+ * Lengths: a[2*digits], b[digits], c[digits].
+ * Assumes digits < MAX_NN_DIGITS.
+ */
+void NN_Mult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+ NN_DIGIT t[2*MAX_NN_DIGITS];
+ unsigned int bDigits, cDigits, i;
+
+ NN_AssignZero (t, 2 * digits);
+
+ bDigits = NN_Digits (b, digits);
+ cDigits = NN_Digits (c, digits);
+
+ for (i = 0; i < bDigits; i++)
+ t[i+cDigits] += NN_AddDigitMult (&t[i], &t[i], b[i], c, cDigits);
+
+ NN_Assign (a, t, 2 * digits);
+
+ /**
+ * Zeroize potentially sensitive information.
+ */
+ R_memset ((POINTER)t, 0, sizeof (t));
+
+ return ;
+}
+
+/**
+ * Computes a = b * 2^c (i.e., shifts left c bits), returning carry.
+ *
+ * Lengths: a[digits], b[digits].
+ * Requires c < NN_DIGIT_BITS.
+ */
+NN_DIGIT NN_LShift (NN_DIGIT *a, NN_DIGIT *b, unsigned int c, unsigned int digits)
+{
+ NN_DIGIT bi, carry;
+ unsigned int i, t;
+
+ if (c >= NN_DIGIT_BITS)
+ return (0);
+
+ t = NN_DIGIT_BITS - c;
+
+ carry = 0;
+
+ for (i = 0; i < digits; i++)
+ {
+ bi = b[i];
+ a[i] = (bi << c) | carry;
+ carry = c ? (bi >> t) : 0;
+ }
+
+ return (carry);
+}
+
+/**
+ * Computes a = c div 2^c (i.e., shifts right c bits), returning carry.
+ *
+ * Lengths: a[digits], b[digits].
+ * Requires: c < NN_DIGIT_BITS.
+ */
+NN_DIGIT NN_RShift (NN_DIGIT *a, NN_DIGIT *b, unsigned int c, unsigned int digits)
+{
+ NN_DIGIT bi, carry;
+ int i;
+ unsigned int t;
+
+ if (c >= NN_DIGIT_BITS)
+ return (0);
+
+ t = NN_DIGIT_BITS - c;
+
+ carry = 0;
+
+ for (i = digits - 1; i >= 0; i--)
+ {
+ bi = b[i];
+ a[i] = (bi >> c) | carry;
+ carry = c ? (bi << t) : 0;
+ }
+
+ return (carry);
+}
+
+/**
+ * Computes a = c div d and b = c mod d.
+ *
+ * Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits].
+ * Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS,
+ * dDigits < MAX_NN_DIGITS.
+ */
+void NN_Div (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c,
+ unsigned int cDigits, NN_DIGIT *d, unsigned int dDigits)
+{
+ NN_DIGIT ai, cc[2*MAX_NN_DIGITS+1], dd[MAX_NN_DIGITS], t;
+ int i;
+ unsigned int ddDigits, shift;
+
+ ddDigits = NN_Digits (d, dDigits);
+ if (ddDigits == 0)
+ return;
+
+ /**
+ * Normalize operands.
+ */
+ shift = NN_DIGIT_BITS - NN_DigitBits (d[ddDigits-1]);
+ NN_AssignZero (cc, ddDigits);
+ cc[cDigits] = NN_LShift (cc, c, shift, cDigits);
+ NN_LShift (dd, d, shift, ddDigits);
+ t = dd[ddDigits-1];
+
+ NN_AssignZero (a, cDigits);
+
+ for (i = cDigits-ddDigits; i >= 0; i--)
+ {
+ /**
+ * Underestimate quotient digit and subtract.
+ */
+ if (t == MAX_NN_DIGIT)
+ ai = cc[i+ddDigits];
+ else
+ NN_DigitDiv (&ai, &cc[i+ddDigits-1], t + 1);
+
+ cc[i+ddDigits] -= NN_SubDigitMult (&cc[i], &cc[i], ai, dd, ddDigits);
+
+ /**
+ * Correct estimate.
+ */
+ while (cc[i+ddDigits] || (NN_Cmp (&cc[i], dd, ddDigits) >= 0))
+ {
+ ai++;
+ cc[i+ddDigits] -= NN_Sub (&cc[i], &cc[i], dd, ddDigits);
+ }
+
+ a[i] = ai;
+ }
+
+ /**
+ * Restore result.
+ */
+ NN_AssignZero (b, dDigits);
+ NN_RShift (b, cc, shift, ddDigits);
+
+ /**
+ * Zeroize potentially sensitive information.
+ */
+ R_memset ((POINTER)cc, 0, sizeof (cc));
+ R_memset ((POINTER)dd, 0, sizeof (dd));
+
+ return ;
+}
+
+/**
+ * Computes a = b mod c.
+ *
+ * Lengths: a[cDigits], b[bDigits], c[cDigits].
+ * Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS.
+ */
+void NN_Mod (NN_DIGIT *a, NN_DIGIT *b, unsigned int bDigits,
+ NN_DIGIT *c, unsigned int cDigits)
+{
+ NN_DIGIT t[2 * MAX_NN_DIGITS];
+
+ NN_Div (t, a, b, bDigits, c, cDigits);
+
+ /**
+ * Zeroize potentially sensitive information.
+ */
+ R_memset ((POINTER)t, 0, sizeof (t));
+
+ return ;
+}
+
+/**
+ * Computes a = b * c mod d.
+ *
+ * Lengths: a[digits], b[digits], c[digits], d[digits].
+ * Assumes d > 0, digits < MAX_NN_DIGITS.
+ */
+void NN_ModMult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, NN_DIGIT *d,
+ unsigned int digits)
+{
+ NN_DIGIT t[2*MAX_NN_DIGITS];
+
+ NN_Mult (t, b, c, digits);
+ NN_Mod (a, t, 2 * digits, d, digits);
+
+ /**
+ * Zeroize potentially sensitive information.
+ */
+ R_memset ((POINTER)t, 0, sizeof (t));
+
+ return ;
+}
+
+/**
+ * Computes a = b^c mod d.
+ *
+ * Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits].
+ * Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS.
+ *
+ * NOTE:
+ * PGP 2.5's mpilib contains a faster modular exponentiation routine, mp_modexp.
+ * If USEMPILIB is defined, NN_ModExp is replaced in the PGP 2.5 sources with a
+ * stub call to mp_modexp. If USEMPILIB is not defined, we'll get a pure (albeit
+ * slower) RSAREF implementation.
+ *
+ * The RSAREF 2.0 license, clause 1(c), permits "...modify[ing] the Program in any
+ * manner for porting or performance improvement purposes..."
+ */
+
+#ifndef USEMPILIB
+void NN_ModExp (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c,
+ unsigned int cDigits, NN_DIGIT *d,
+ unsigned int dDigits)
+{
+ NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS];
+ int i;
+ unsigned int ciBits, j, s;
+
+ /**
+ * Store b, b^2 mod d, and b^3 mod d.
+ */
+ NN_Assign (bPower[0], b, dDigits);
+ NN_ModMult (bPower[1], bPower[0], b, d, dDigits);
+ NN_ModMult (bPower[2], bPower[1], b, d, dDigits);
+
+ NN_ASSIGN_DIGIT (t, 1, dDigits);
+
+ cDigits = NN_Digits (c, cDigits);
+ for (i = cDigits - 1; i >= 0; i--)
+ {
+ ci = c[i];
+ ciBits = NN_DIGIT_BITS;
+
+ /**
+ * Scan past leading zero bits of most significant digit.
+ */
+ if (i == (int)(cDigits - 1))
+ {
+ while (! DIGIT_2MSB (ci))
+ {
+ ci <<= 2;
+ ciBits -= 2;
+ }
+ }
+
+ for (j = 0; j < ciBits; j += 2, ci <<= 2)
+ {
+ /**
+ * Compute t = t^4 * b^s mod d, where s = two MSB's of ci.
+ */
+ NN_ModMult (t, t, t, d, dDigits);
+ NN_ModMult (t, t, t, d, dDigits);
+
+ if ((s = DIGIT_2MSB (ci)) != 0)
+ NN_ModMult (t, t, bPower[s-1], d, dDigits);
+ }
+ }
+
+ NN_Assign (a, t, dDigits);
+
+ /**
+ * Zeroize potentially sensitive information.
+ */
+ R_memset ((POINTER)bPower, 0, sizeof (bPower));
+ R_memset ((POINTER)t, 0, sizeof (t));
+
+ return ;
+}
+#endif
+
+/**
+ * Compute a = 1/b mod c, assuming inverse exists.
+ *
+ * Lengths: a[digits], b[digits], c[digits].
+ * Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS.
+ */
+void NN_ModInv (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+ NN_DIGIT q[MAX_NN_DIGITS], t1[MAX_NN_DIGITS], t3[MAX_NN_DIGITS],
+ u1[MAX_NN_DIGITS], u3[MAX_NN_DIGITS], v1[MAX_NN_DIGITS],
+ v3[MAX_NN_DIGITS], w[2*MAX_NN_DIGITS];
+ int u1Sign;
+
+ /**
+ * Apply extended Euclidean algorithm, modified to avoid negative
+ * numbers.
+ */
+ NN_ASSIGN_DIGIT (u1, 1, digits);
+ NN_AssignZero (v1, digits);
+ NN_Assign (u3, b, digits);
+ NN_Assign (v3, c, digits);
+ u1Sign = 1;
+
+ while (! NN_Zero (v3, digits))
+ {
+ NN_Div (q, t3, u3, digits, v3, digits);
+ NN_Mult (w, q, v1, digits);
+ NN_Add (t1, u1, w, digits);
+ NN_Assign (u1, v1, digits);
+ NN_Assign (v1, t1, digits);
+ NN_Assign (u3, v3, digits);
+ NN_Assign (v3, t3, digits);
+ u1Sign = -u1Sign;
+ }
+
+ /**
+ * Negate result if sign is negative.
+ */
+ if (u1Sign < 0)
+ NN_Sub (a, c, u1, digits);
+ else
+ NN_Assign (a, u1, digits);
+
+ /**
+ * Zeroize potentially sensitive information.
+ */
+ R_memset ((POINTER)q, 0, sizeof (q));
+ R_memset ((POINTER)t1, 0, sizeof (t1));
+ R_memset ((POINTER)t3, 0, sizeof (t3));
+ R_memset ((POINTER)u1, 0, sizeof (u1));
+ R_memset ((POINTER)u3, 0, sizeof (u3));
+ R_memset ((POINTER)v1, 0, sizeof (v1));
+ R_memset ((POINTER)v3, 0, sizeof (v3));
+ R_memset ((POINTER)w, 0, sizeof (w));
+
+ return ;
+}
+
+/**
+ * Computes a = gcd(b, c).
+ *
+ * Lengths: a[digits], b[digits], c[digits].
+ * Assumes b > c, digits < MAX_NN_DIGITS.
+ */
+void NN_Gcd (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, unsigned int digits)
+{
+ NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS];
+
+ NN_Assign (u, b, digits);
+ NN_Assign (v, c, digits);
+
+ while (! NN_Zero (v, digits))
+ {
+ NN_Mod (t, u, digits, v, digits);
+ NN_Assign (u, v, digits);
+ NN_Assign (v, t, digits);
+ }
+
+ NN_Assign (a, u, digits);
+
+ /**
+ * Zeroize potentially sensitive information.
+ */
+ R_memset ((POINTER)t, 0, sizeof (t));
+ R_memset ((POINTER)u, 0, sizeof (u));
+ R_memset ((POINTER)v, 0, sizeof (v));
+}
+
+/**
+ * Returns sign of a - b.
+ *
+ * Lengths: a[digits], b[digits].
+ */
+int NN_Cmp (NN_DIGIT *a, NN_DIGIT *b, unsigned int digits)
+{
+ int i;
+
+ for (i = digits - 1; i >= 0; i--)
+ {
+ if (a[i] > b[i])
+ return (1);
+ if (a[i] < b[i])
+ return (-1);
+ }
+
+ return (0);
+}
+
+/**
+ * Returns nonzero iff a is zero.
+ *
+ * Lengths: a[digits].
+ */
+int NN_Zero (NN_DIGIT *a, unsigned int digits)
+{
+ unsigned int i;
+
+ for (i = 0; i < digits; i++)
+ if (a[i])
+ return (0);
+
+ return (1);
+}
+
+/**
+ * Returns the significant length of a in bits.
+ *
+ * Lengths: a[digits].
+ */
+unsigned int NN_Bits (NN_DIGIT *a, unsigned int digits)
+{
+ if ((digits = NN_Digits (a, digits)) == 0)
+ return (0);
+
+ return ((digits - 1) * NN_DIGIT_BITS + NN_DigitBits (a[digits-1]));
+}
+
+/**
+ * Returns the significant length of a in digits.
+ *
+ * Lengths: a[digits].
+ */
+unsigned int NN_Digits (NN_DIGIT *a, unsigned int digits)
+{
+ int i;
+
+ for (i = digits - 1; i >= 0; i--)
+ if (a[i])
+ break;
+
+ return (i + 1);
+}
+
+/**
+ * Computes a = b + c*d, where c is a digit. Returns carry.
+ *
+ * Lengths: a[digits], b[digits], d[digits].
+ */
+static NN_DIGIT NN_AddDigitMult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT c,
+ NN_DIGIT *d, unsigned int digits)
+{
+ NN_DIGIT carry, t[2];
+ unsigned int i;
+
+ if (c == 0)
+ return (0);
+
+ carry = 0;
+ for (i = 0; i < digits; i++)
+ {
+ NN_DigitMult (t, c, d[i]);
+ if ((a[i] = b[i] + carry) < carry)
+ carry = 1;
+ else
+ carry = 0;
+ if ((a[i] += t[0]) < t[0])
+ carry++;
+ carry += t[1];
+ }
+
+ return (carry);
+}
+
+/**
+ * Computes a = b - c*d, where c is a digit. Returns borrow.
+ *
+ * Lengths: a[digits], b[digits], d[digits].
+ */
+static NN_DIGIT NN_SubDigitMult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT c,
+ NN_DIGIT *d, unsigned int digits)
+{
+ NN_DIGIT borrow, t[2];
+ unsigned int i;
+
+ if (c == 0)
+ return (0);
+
+ borrow = 0;
+ for (i = 0; i < digits; i++)
+ {
+ NN_DigitMult (t, c, d[i]);
+ if ((a[i] = b[i] - borrow) > (MAX_NN_DIGIT - borrow))
+ borrow = 1;
+ else
+ borrow = 0;
+ if ((a[i] -= t[0]) > (MAX_NN_DIGIT - t[0]))
+ borrow++;
+ borrow += t[1];
+ }
+
+ return (borrow);
+}
+
+/**
+ * Returns the significant length of a in bits, where a is a digit.
+ */
+static unsigned int NN_DigitBits (NN_DIGIT a)
+{
+ unsigned int i;
+
+ for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1)
+ if (a == 0)
+ break;
+
+ return (i);
+}
+
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_nn.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,147 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _CR_NN_H_
+#define _CR_NN_H_
+
+
+/**
+ * Type definitions.
+ */
+typedef UINT4 NN_DIGIT;
+typedef UINT2 NN_HALF_DIGIT;
+
+/**
+ * Constants:
+ *
+ * Note: MAX_NN_DIGITS is long enough to hold any RSA modulus, plus
+ * one more digit as required by R_GeneratePEMKeys (for n and phiN,
+ * whose lengths must be even). All natural numbers have at most
+ * MAX_NN_DIGITS digits, except for double-length intermediate values
+ * in NN_Mult (t), NN_ModMult (t), NN_ModInv (w), and NN_Div (c).
+ */
+
+/**
+ * Length of digit in bits
+ */
+#define NN_DIGIT_BITS 32
+#define NN_HALF_DIGIT_BITS 16
+
+/**
+ * Length of digit in bytes
+ */
+#define NN_DIGIT_LEN (NN_DIGIT_BITS / 8)
+
+/**
+ * Maximum length in digits
+ */
+#define MAX_NN_DIGITS \
+ ((MAX_RSA_MODULUS_LEN + NN_DIGIT_LEN - 1) / NN_DIGIT_LEN + 1)
+
+/**
+ * Maximum digits
+ */
+#define MAX_NN_DIGIT 0xffffffff
+#define MAX_NN_HALF_DIGIT 0xffff
+
+/**
+ * Some macros:
+ */
+#define LOW_HALF(x) ((x) & MAX_NN_HALF_DIGIT)
+#define HIGH_HALF(x) (((x) >> NN_HALF_DIGIT_BITS) & MAX_NN_HALF_DIGIT)
+#define TO_HIGH_HALF(x) (((NN_DIGIT)(x)) << NN_HALF_DIGIT_BITS)
+#define DIGIT_MSB(x) (unsigned int)(((x) >> (NN_DIGIT_BITS - 1)) & 1)
+#define DIGIT_2MSB(x) (unsigned int)(((x) >> (NN_DIGIT_BITS - 2)) & 3)
+
+#define NN_ASSIGN_DIGIT(a, b, digits) {NN_AssignZero (a, digits); a[0] = b;}
+#define NN_EQUAL(a, b, digits) (! NN_Cmp (a, b, digits))
+#define NN_EVEN(a, digits) (((digits) == 0) || ! (a[0] & 1))
+
+
+/**
+ * Declaration of conversion functions:
+ *
+ NN_Decode (a, digits, b, len) Decodes character string b into a.
+ NN_Encode (a, len, b, digits) Encodes a into character string b.
+
+ ASSIGNMENTS
+ NN_Assign (a, b, digits) Assigns a = b.
+ NN_ASSIGN_DIGIT (a, b, digits) Assigns a = b, where b is a digit.
+ NN_AssignZero (a, b, digits) Assigns a = 0.
+ NN_Assign2Exp (a, b, digits) Assigns a = 2^b.
+
+ ARITHMETIC OPERATIONS
+ NN_Add (a, b, c, digits) Computes a = b + c.
+ NN_Sub (a, b, c, digits) Computes a = b - c.
+ NN_Mult (a, b, c, digits) Computes a = b * c.
+ NN_LShift (a, b, c, digits) Computes a = b * 2^c.
+ NN_RShift (a, b, c, digits) Computes a = b / 2^c.
+ NN_Div (a, b, c, cDigits, d, dDigits) Computes a = c div d and b = c mod d.
+
+ NUMBER THEORY
+ NN_Mod (a, b, bDigits, c, cDigits) Computes a = b mod c.
+ NN_ModMult (a, b, c, d, digits) Computes a = b * c mod d.
+ NN_ModExp (a, b, c, cDigits, d, dDigits) Computes a = b^c mod d.
+ NN_ModInv (a, b, c, digits) Computes a = 1/b mod c.
+ NN_Gcd (a, b, c, digits) Computes a = gcd (b, c).
+
+ OTHER OPERATIONS
+ NN_EVEN (a, digits) Returns 1 iff a is even.
+ NN_Cmp (a, b, digits) Returns sign of a - b.
+ NN_EQUAL (a, digits) Returns 1 iff a = b.
+ NN_Zero (a, digits) Returns 1 iff a = 0.
+ NN_Digits (a, digits) Returns significant length of a in digits.
+ NN_Bits (a, digits) Returns significant length of a in bits.
+ *
+ */
+
+/**
+ * The third parameter changed from 'unsigned char *'
+ */
+void NN_Decode(NN_DIGIT *, unsigned int, const unsigned char *, unsigned int);
+
+void NN_Encode(unsigned char *, unsigned int, NN_DIGIT *, unsigned int);
+
+void NN_Assign(NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_AssignZero(NN_DIGIT *, unsigned int);
+void NN_Assign2Exp(NN_DIGIT *, unsigned int, unsigned int);
+
+NN_DIGIT NN_Add(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+NN_DIGIT NN_Sub(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_Mult(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_Div(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int);
+NN_DIGIT NN_LShift(NN_DIGIT *, NN_DIGIT *, unsigned int, unsigned int);
+NN_DIGIT NN_RShift(NN_DIGIT *, NN_DIGIT *, unsigned int, unsigned int);
+
+void NN_Mod(NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int);
+void NN_ModMult(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_ModExp(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int, NN_DIGIT *, unsigned int);
+void NN_ModInv(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+void NN_Gcd(NN_DIGIT *, NN_DIGIT *, NN_DIGIT *, unsigned int);
+
+int NN_Cmp(NN_DIGIT *, NN_DIGIT *, unsigned int);
+int NN_Zero(NN_DIGIT *, unsigned int);
+unsigned int NN_Bits(NN_DIGIT *, unsigned int);
+unsigned int NN_Digits(NN_DIGIT *, unsigned int);
+
+
+#endif /* _CR_NN_H_ */
+
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,170 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "ha_config.h"
+#include "cr_random.h"
+#include "cr_global.h"
+#include "platconfig.h"
+#include "digest.h"
+#include "md5.h"
+
+#include "cr_rsa.h"
+
+#define RANDOM_BYTES_NEEDED 256
+
+int R_GenerateBytes(
+ unsigned char *block, /* block */
+ unsigned int blockLen, /* length of block */
+ R_RANDOM_STRUCT *randomStruct) /* random structure */
+{
+ unsigned int available, i;
+
+ if (randomStruct->bytesNeeded)
+ {
+ return (RE_NEED_RANDOM);
+ }
+
+ available = randomStruct->outputAvailable;
+
+ while (blockLen > available)
+ {
+ R_memcpy( (POINTER)block,
+ (POINTER)&randomStruct->output[16-available],
+ available) ;
+ block += available;
+ blockLen -= available;
+
+ // Generate new output
+ CMD5* md4Ctx = new CMD5();
+ md4Ctx->HashCore(randomStruct->state,0,16);
+ md4Ctx->HashFinal(randomStruct->output);
+ delete md4Ctx;
+
+ available = 16;
+
+ /**
+ * increment state
+ */
+ for (i = 0; i < 16; i++)
+ {
+ if (randomStruct->state[15-i]++)
+ break;
+ }
+ }
+
+ R_memcpy((POINTER)block, (POINTER)&randomStruct->output[16-available], blockLen);
+ randomStruct->outputAvailable = available - blockLen;
+
+ return (0);
+}
+
+
+int R_RandomInit(R_RANDOM_STRUCT *randomStruct)
+{
+ randomStruct->bytesNeeded = RANDOM_BYTES_NEEDED;
+ R_memset ((POINTER)randomStruct->state, 0, sizeof (randomStruct->state));
+ randomStruct->outputAvailable = 0;
+
+ return (0);
+}
+
+
+int R_RandomUpdate(
+ R_RANDOM_STRUCT *randomStruct, /* random structure */
+ unsigned char *block, /* block of values to mix in */
+ unsigned int blockLen) /* length of block */
+{
+ unsigned char digest[16];
+ unsigned int i, x;
+
+ CMD5* md5Ctx = new CMD5();
+ md5Ctx->HashCore(block,0,blockLen);
+ md5Ctx->HashFinal(digest);
+ delete md5Ctx;
+
+ /* add digest to state */
+ x = 0;
+ for (i = 0; i < 16; i++)
+ {
+ x += randomStruct->state[15-i] + digest[15-i];
+ randomStruct->state[15-i] = (unsigned char)x;
+ x >>= 8;
+ }
+
+ if (randomStruct->bytesNeeded < blockLen)
+ randomStruct->bytesNeeded = 0;
+ else
+ randomStruct->bytesNeeded -= blockLen;
+
+ /**
+ * Zeroize sensitive information.
+ */
+ R_memset ((POINTER)digest, 0, sizeof (digest));
+ x = 0;
+
+ return (0);
+}
+
+
+int R_GetRandomBytesNeeded(
+ unsigned int *bytesNeeded, /* number of mix-in bytes needed */
+ R_RANDOM_STRUCT *randomStruct) /* random structure */
+{
+ *bytesNeeded = randomStruct->bytesNeeded;
+ return (0);
+}
+
+
+void R_RandomFinal(R_RANDOM_STRUCT *randomStruct)
+{
+ R_memset((POINTER)randomStruct, 0, sizeof (*randomStruct)) ;
+}
+
+
+/**
+ * Initialize the random structure with all zero seed bytes.
+ *
+ * NOTE: that this will cause the output of the "random" process
+ * to be the same every time. To produce random bytes, the random
+ * struct needs random seeds.
+ */
+void InitRandomStruct(R_RANDOM_STRUCT *randomStruct)
+{
+ static unsigned char seedByte = 0;
+ unsigned int bytesNeeded;
+
+ R_RandomInit (randomStruct);
+
+ /**
+ * Initialize with all zero seed bytes, which will not yield
+ * an actual random number output.
+ */
+ int iCondition = 1;
+ while( iCondition )
+ {
+ R_GetRandomBytesNeeded (&bytesNeeded, randomStruct);
+ if (bytesNeeded == 0)
+ break;
+
+ R_RandomUpdate (randomStruct, &seedByte, 1);
+ }
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_random.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,46 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _CR_RANDOM_H_
+#define _CR_RANDOM_H_
+
+
+/**
+ * RSA Random structure.
+ */
+typedef struct {
+ unsigned int bytesNeeded;
+ unsigned char state[16];
+ unsigned int outputAvailable;
+ unsigned char output[16];
+} R_RANDOM_STRUCT;
+
+
+int R_GenerateBytes(unsigned char *, unsigned int, R_RANDOM_STRUCT *);
+
+int R_RandomInit(R_RANDOM_STRUCT *randomStruct) ;
+void InitRandomStruct(R_RANDOM_STRUCT *randomStruct) ;
+int R_GetRandomBytesNeeded(unsigned int *bytesNeeded, R_RANDOM_STRUCT *randomStruct) ;
+int R_RandomUpdate(R_RANDOM_STRUCT *randomStruct, unsigned char *block, unsigned int blockLen) ;
+void R_RandomFinal(R_RANDOM_STRUCT *randomStruct) ;
+
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,375 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "cr_rsa.h"
+#include "cr_global.h"
+#include "cr_nn.h"
+#include "cr_random.h"
+
+#include "ha_config.h"
+
+/**
+ * RSA private-key decryption, according to PKCS #1.
+ */
+int RSAPrivateDecrypt(
+ unsigned char *output, /* output block */
+ unsigned int *outputLen, /* length of output block */
+ unsigned char *input, /* input block */
+ unsigned int inputLen, /* length of input block */
+ R_RSA_PRIVATE_KEY *privateKey) /* RSA private key */
+{
+ int status;
+ unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
+ unsigned int i, modulusLen, pkcsBlockLen;
+
+ modulusLen = (privateKey->bits + 7) / 8;
+ if (inputLen > modulusLen)
+ return (RE_LEN);
+
+ //if (status = RSAPrivateBlock(pkcsBlock, &pkcsBlockLen, input, inputLen, privateKey))
+ status = RSAPrivateBlock(pkcsBlock, &pkcsBlockLen, input, inputLen, privateKey);
+ if ( status )
+ return (status);
+
+ if (pkcsBlockLen != modulusLen)
+ return (RE_LEN);
+
+ /* Require block type 2.
+ */
+ if ((pkcsBlock[0] != 0) || (pkcsBlock[1] != 2))
+ return (RE_DATA);
+
+ for (i = 2; i < modulusLen-1; i++)
+ {
+ if (pkcsBlock[i] == 0)
+ break;
+ }
+
+ i++;
+ if (i >= modulusLen)
+ return (RE_DATA);
+
+ *outputLen = modulusLen - i;
+
+ if (*outputLen + 11 > modulusLen)
+ return (RE_DATA);
+
+ R_memcpy ((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen);
+
+ /**
+ * Zeroize sensitive information.
+ */
+ R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
+
+ return (0);
+}
+
+
+/**
+ * Raw RSA private-key operation. Output has same length as modulus.
+ *
+ * Assumes inputLen < length of modulus.
+ * Requires input < modulus.
+ */
+int RSAPrivateBlock (
+ unsigned char *output, /* output block */
+ unsigned int *outputLen, /* length of output block */
+ unsigned char *input, /* input block */
+ unsigned int inputLen, /* length of input block */
+ R_RSA_PRIVATE_KEY *privateKey) /* RSA private key */
+{
+ NN_DIGIT c[MAX_NN_DIGITS], cP[MAX_NN_DIGITS], cQ[MAX_NN_DIGITS],
+ dP[MAX_NN_DIGITS], dQ[MAX_NN_DIGITS], mP[MAX_NN_DIGITS],
+ mQ[MAX_NN_DIGITS], n[MAX_NN_DIGITS], p[MAX_NN_DIGITS],
+ q[MAX_NN_DIGITS], qInv[MAX_NN_DIGITS], t[MAX_NN_DIGITS] ;
+
+ unsigned int cDigits, nDigits, pDigits;
+ unsigned int len_Mod, len_Prime ;
+
+ len_Mod = (privateKey->bits + 7) / 8 ;
+ len_Prime = (((privateKey->bits + 1) / 2) + 7) / 8 ;
+
+ NN_Decode (c, MAX_NN_DIGITS, input, inputLen);
+ NN_Decode (n, MAX_NN_DIGITS, privateKey->modulus, len_Mod);
+ NN_Decode (p, MAX_NN_DIGITS, privateKey->prime[0], len_Prime);
+ NN_Decode (q, MAX_NN_DIGITS, privateKey->prime[1], len_Prime);
+ NN_Decode (dP, MAX_NN_DIGITS, privateKey->primeExponent[0], len_Prime);
+ NN_Decode (dQ, MAX_NN_DIGITS, privateKey->primeExponent[1], len_Prime);
+ NN_Decode (qInv, MAX_NN_DIGITS, privateKey->coefficient, len_Prime);
+
+ cDigits = NN_Digits (c, MAX_NN_DIGITS);
+ nDigits = NN_Digits (n, MAX_NN_DIGITS);
+ pDigits = NN_Digits (p, MAX_NN_DIGITS);
+
+ if (NN_Cmp (c, n, nDigits) >= 0)
+ return (RE_DATA);
+
+ /**
+ * Compute mP = cP^dP mod p and mQ = cQ^dQ mod q. (Assumes q has
+ * length at most pDigits, i.e., p > q.)
+ */
+ NN_Mod (cP, c, cDigits, p, pDigits);
+ NN_Mod (cQ, c, cDigits, q, pDigits);
+ NN_ModExp (mP, cP, dP, pDigits, p, pDigits);
+ NN_AssignZero (mQ, nDigits);
+ NN_ModExp (mQ, cQ, dQ, pDigits, q, pDigits);
+
+ /**
+ * Chinese Remainder Theorem:
+ * m = ((((mP - mQ) mod p) * qInv) mod p) * q + mQ.
+ */
+ if (NN_Cmp (mP, mQ, pDigits) >= 0)
+ {
+ NN_Sub (t, mP, mQ, pDigits);
+ }
+ else
+ {
+ NN_Sub (t, mQ, mP, pDigits);
+ NN_Sub (t, p, t, pDigits);
+ }
+ NN_ModMult (t, t, qInv, p, pDigits);
+ NN_Mult (t, t, q, pDigits);
+ NN_Add (t, t, mQ, nDigits);
+
+ *outputLen = (privateKey->bits + 7) / 8;
+ NN_Encode (output, *outputLen, t, nDigits);
+
+ /**
+ * Zeroize sensitive information.
+ */
+ R_memset ((POINTER)c, 0, sizeof (c));
+ R_memset ((POINTER)cP, 0, sizeof (cP));
+ R_memset ((POINTER)cQ, 0, sizeof (cQ));
+ R_memset ((POINTER)dP, 0, sizeof (dP));
+ R_memset ((POINTER)dQ, 0, sizeof (dQ));
+ R_memset ((POINTER)mP, 0, sizeof (mP));
+ R_memset ((POINTER)mQ, 0, sizeof (mQ));
+ R_memset ((POINTER)p, 0, sizeof (p));
+ R_memset ((POINTER)q, 0, sizeof (q));
+ R_memset ((POINTER)qInv, 0, sizeof (qInv));
+ R_memset ((POINTER)t, 0, sizeof (t));
+
+ return (0);
+}
+
+
+/**
+ * RSA public-key encryption, according to PKCS #1.
+ */
+int RSAPublicEncrypt(
+ unsigned char *output, /* output block */
+ unsigned int *outputLen, /* length of output block */
+ unsigned char *input, /* input block */
+ unsigned int inputLen, /* length of input block */
+ R_RSA_PUBLIC_KEY *publicKey, /* RSA public key */
+ R_RANDOM_STRUCT *randomStruct) /* random structure */
+{
+ int status;
+ unsigned char byte, pkcsBlock[MAX_RSA_MODULUS_LEN];
+ unsigned int i, modulusLen;
+
+ modulusLen = (publicKey->bits + 7) / 8;
+ if (inputLen + 11 > modulusLen)
+ {
+ return (RE_LEN);
+ }
+
+ /**
+ * block type 2
+ */
+ pkcsBlock[0] = 0;
+ pkcsBlock[1] = 2;
+
+ for (i = 2; i < modulusLen - inputLen - 1; i++)
+ {
+ /**
+ * Find nonzero random byte.
+ */
+ do {
+ R_GenerateBytes (&byte, 1, randomStruct);
+ } while (byte == 0);
+
+ pkcsBlock[i] = byte;
+ }
+
+ /**
+ * separator
+ */
+ pkcsBlock[i++] = 0;
+ R_memcpy ((POINTER)&pkcsBlock[i], (POINTER)input, inputLen);
+ status = RSAPublicBlock(output, outputLen, pkcsBlock, modulusLen, publicKey);
+
+ /**
+ * Zeroize sensitive information.
+ */
+ byte = 0;
+ R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
+
+ return (status);
+}
+
+
+/**
+ * Raw RSA public-key operation. Output has same length as modulus.
+ *
+ * Assumes inputLen < length of modulus.
+ * Requires input < modulus.
+ */
+int RSAPublicBlock(
+ unsigned char *output, /* output block */
+ unsigned int *outputLen, /* length of output block */
+ unsigned char *input, /* input block */
+ unsigned int inputLen, /* length of input block */
+ R_RSA_PUBLIC_KEY *publicKey) /* RSA public key */
+{
+ unsigned int eDigits, nDigits;
+ NN_DIGIT c[MAX_NN_DIGITS],
+ e[MAX_NN_DIGITS],
+ m[MAX_NN_DIGITS],
+ n[MAX_NN_DIGITS] ;
+
+ unsigned int len_Mod ;
+
+ len_Mod = (publicKey->bits + 7) / 8 ;
+
+ NN_Decode (m, MAX_NN_DIGITS, input, inputLen);
+ NN_Decode (n, MAX_NN_DIGITS, publicKey->modulus, len_Mod);
+ NN_Decode (e, MAX_NN_DIGITS, publicKey->exponent, len_Mod);
+ nDigits = NN_Digits (n, MAX_NN_DIGITS);
+ eDigits = NN_Digits (e, MAX_NN_DIGITS);
+
+ if (NN_Cmp (m, n, nDigits) >= 0)
+ {
+ return (RE_DATA);
+ }
+
+ /**
+ * Compute c = m^e mod n.
+ */
+ NN_ModExp (c, m, e, eDigits, n, nDigits);
+
+ *outputLen = (publicKey->bits + 7) / 8;
+ NN_Encode (output, *outputLen, c, nDigits);
+
+ /**
+ * Zeroize sensitive information.
+ */
+ R_memset ((POINTER)c, 0, sizeof (c));
+ R_memset ((POINTER)m, 0, sizeof (m));
+
+ return (0);
+}
+
+
+/**
+ * RSA public-key decryption, according to PKCS #1.
+ */
+int RSAPublicDecrypt(
+ unsigned char *output, /* output block */
+ unsigned int *outputLen, /* length of output block */
+ unsigned char *input, /* input block */
+ unsigned int inputLen, /* length of input block */
+ R_RSA_PUBLIC_KEY *publicKey) /* RSA public key */
+{
+ int status;
+ unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
+ unsigned int i, modulusLen, pkcsBlockLen;
+
+ modulusLen = (publicKey->bits + 7) / 8;
+ if (inputLen > modulusLen)
+ return (RE_LEN);
+
+ status = RSAPublicBlock(pkcsBlock, &pkcsBlockLen, input, inputLen, publicKey) ;
+ if (status)
+ return (status);
+
+ if (pkcsBlockLen != modulusLen)
+ return (RE_LEN);
+
+ /**
+ * Require block type 1.
+ */
+ if ((pkcsBlock[0] != 0) || (pkcsBlock[1] != 1))
+ return (RE_DATA);
+
+ for (i = 2; i < modulusLen-1; i++)
+ {
+ if (pkcsBlock[i] != 0xff)
+ break;
+ }
+
+ /* separator */
+ if (pkcsBlock[i++] != 0)
+ return (RE_DATA);
+
+ *outputLen = modulusLen - i;
+
+ if (*outputLen + 11 > modulusLen)
+ return (RE_DATA);
+
+ R_memcpy((POINTER)output, (POINTER)&pkcsBlock[i], *outputLen);
+
+ /**
+ * Zeroize potentially sensitive information.
+ */
+ R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
+
+ return (0);
+}
+
+/* RSA private-key encryption, according to PKCS #1.
+ */
+int RSAPrivateEncrypt(
+ unsigned char *output, /* output block */
+ unsigned int *outputLen, /* length of output block */
+ unsigned char *input, /* input block */
+ unsigned int inputLen, /* length of input block */
+ R_RSA_PRIVATE_KEY *privateKey) /* RSA private key */
+{
+ int status;
+ unsigned char pkcsBlock[MAX_RSA_MODULUS_LEN];
+ unsigned int i, modulusLen;
+
+ modulusLen = (privateKey->bits + 7) / 8;
+ if (inputLen + 11 > modulusLen)
+ return (RE_LEN);
+
+ pkcsBlock[0] = 0;
+ /* block type 1 */
+ pkcsBlock[1] = 1;
+
+ for (i = 2; i < modulusLen - inputLen - 1; i++)
+ pkcsBlock[i] = 0xff;
+
+ /* separator */
+ pkcsBlock[i++] = 0;
+
+ R_memcpy ((POINTER)&pkcsBlock[i], (POINTER)input, inputLen);
+
+ status = RSAPrivateBlock(output, outputLen, pkcsBlock, modulusLen, privateKey);
+
+ /* Zeroize potentially sensitive information.
+ */
+ R_memset ((POINTER)pkcsBlock, 0, sizeof (pkcsBlock));
+
+ return (status);
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/cr_rsa.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,157 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _CR_RSA_H_
+#define _CR_RSA_H_
+
+#include "cr_random.h"
+
+/**
+ * RSA key lengths.
+ */
+#define MIN_RSA_MODULUS_BITS 512
+#define MAX_RSA_MODULUS_BITS 2048
+#define MAX_RSA_MODULUS_LEN ((MAX_RSA_MODULUS_BITS + 7) / 8)
+#define MAX_RSA_PRIME_BITS ((MAX_RSA_MODULUS_BITS + 1) / 2)
+#define MAX_RSA_PRIME_LEN ((MAX_RSA_PRIME_BITS + 7) / 8)
+
+
+/**
+ * RSA public key struct.
+ */
+typedef struct {
+ unsigned int bits; /* length in bits of modulus */
+ unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */
+ unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* public exponent */
+} R_RSA_PUBLIC_KEY;
+
+
+/**
+ * RSA private key struct.
+ *
+ * The size of arrays for key should be:
+ *
+ * modulus [MAX_RSA_MODULUS_LEN]
+ * publicExponent [MAX_RSA_MODULUS_LEN]
+ * exponent [MAX_RSA_MODULUS_LEN]
+ * prime[2] [MAX_RSA_PRIME_LEN]
+ * primeExponent[2] [MAX_RSA_PRIME_LEN]
+ * coefficient [MAX_RSA_PRIME_LEN]
+ */
+typedef struct {
+ unsigned int bits; /* length in bits of modulus */
+ unsigned char modulus[MAX_RSA_MODULUS_LEN]; /* modulus */
+ unsigned char publicExponent[MAX_RSA_MODULUS_LEN]; /* public exponent */
+ unsigned char exponent[MAX_RSA_MODULUS_LEN]; /* private exponent */
+ unsigned char prime[2][MAX_RSA_PRIME_LEN]; /* prime factors */
+ unsigned char primeExponent[2][MAX_RSA_PRIME_LEN]; /* exponents for CRT */
+ unsigned char coefficient[MAX_RSA_PRIME_LEN]; /* CRT coefficient */
+} R_RSA_PRIVATE_KEY;
+
+
+/**
+ * RSA prototype key.
+ */
+typedef struct {
+ unsigned int bits; /* length in bits of modulus */
+ int useFermat4; /* public exponent (1 = F4, 0 = 3) */
+} R_RSA_PROTO_KEY;
+
+
+ /**
+ * ------------------------------------------------------------------------
+ * RSA Interfaces
+ * ------------------------------------------------------------------------
+ */
+
+typedef struct
+{
+ DWORD modulusLength; /* length (bits) of modulus */
+ BYTE* modulus; /* modulus */
+ DWORD publicExponentLength; /* length (bits) of public exponent */
+ BYTE* publicExponent; /* public exponent */
+} rsaPublicKey_t ;
+
+typedef struct
+{
+ DWORD modulusLength; /* length (bits) of modulus */
+ BYTE* modulus; /* modulus */
+ DWORD publicExponentLength; /* length (bits) of public exponent */
+ BYTE* publicExponent; /* public exponent */
+ BYTE* privateExponent; /* private exponent */
+ BYTE* prime[2]; /* prime factors */
+ BYTE* primeExponent[2]; /* exponents for CRT */
+ BYTE* coefficient; /* CRT coefficient */
+} rsaPrivateKey_t ;
+
+
+/**
+ * RSA function declaration for private/public key operation
+ */
+
+int RSAPrivateDecrypt(
+ unsigned char *output, /* output block */
+ unsigned int *outputLen, /* length of output block */
+ unsigned char *input, /* input block */
+ unsigned int inputLen, /* length of input block */
+ R_RSA_PRIVATE_KEY *privateKey); /* RSA private key */
+
+int RSAPrivateEncrypt(
+ unsigned char *output, /* output block */
+ unsigned int *outputLen, /* length of output block */
+ unsigned char *input, /* input block */
+ unsigned int inputLen, /* length of input block */
+ R_RSA_PRIVATE_KEY *privateKey) ; /* RSA private key */
+
+int RSAPrivateBlock(
+ unsigned char *output, /* output block */
+ unsigned int *outputLen, /* length of output block */
+ unsigned char *input, /* input block */
+ unsigned int inputLen, /* length of input block */
+ R_RSA_PRIVATE_KEY *privateKey) ; /* RSA private key */
+
+
+int RSAPublicEncrypt(
+ unsigned char *output, /* output block */
+ unsigned int *outputLen, /* length of output block */
+ unsigned char *input, /* input block */
+ unsigned int inputLen, /* length of input block */
+ R_RSA_PUBLIC_KEY *publicKey, /* RSA public key */
+ R_RANDOM_STRUCT *randomStruct) ; /* random structure */
+
+
+int RSAPublicBlock(
+ unsigned char *output, /* output block */
+ unsigned int *outputLen, /* length of output block */
+ unsigned char *input, /* input block */
+ unsigned int inputLen, /* length of input block */
+ R_RSA_PUBLIC_KEY *publicKey) ; /* RSA public key */
+
+
+int RSAPublicDecrypt(
+ unsigned char *output, /* output block */
+ unsigned int *outputLen, /* length of output block */
+ unsigned char *input, /* input block */
+ unsigned int inputLen, /* length of input block */
+ R_RSA_PUBLIC_KEY *publicKey) ; /* RSA public key */
+
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/ha_config.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/ha_config.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsa/ha_config.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,42 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _HA_CONFIG_H_
+#define _HA_CONFIG_H_
+
+/**
+ * Global typedefs for use in various Host Agent components.
+ * TODO: Choose a single set and use it consistently.
+ */
+
+typedef signed char s8_t;
+typedef signed short s16_t;
+typedef signed long s32_t;
+
+typedef unsigned char u8_t ;
+typedef unsigned short u16_t ;
+typedef unsigned long u32_t ;
+
+typedef unsigned char u1 ;
+typedef unsigned short u2 ;
+typedef unsigned int u4 ;
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,282 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "rsaprivatekeyobject.h"
+
+RSAPrivateKeyObject :: RSAPrivateKeyObject() : PrivateKeyObject()
+{
+ this->_modulus = NULL_PTR;
+ this->_publicExponent = NULL_PTR;
+ this->_d = NULL_PTR;
+ this->_p = NULL_PTR;
+ this->_q = NULL_PTR;
+ this->_dp = NULL_PTR;
+ this->_dq = NULL_PTR;
+ this->_inverseQ = NULL_PTR;
+
+ this->_keyType = CKK_RSA;
+
+}
+
+RSAPrivateKeyObject :: ~RSAPrivateKeyObject()
+{
+ if(this->_modulus != NULL_PTR){
+ delete this->_modulus;
+ }
+
+ if(this->_publicExponent != NULL_PTR){
+ delete this->_publicExponent;
+ }
+
+ if(this->_d != NULL_PTR){
+ delete this->_d;
+ }
+
+ if(this->_p != NULL_PTR){
+ delete this->_p;
+ }
+
+ if(this->_q != NULL_PTR){
+ delete this->_q;
+ }
+
+ if(this->_dp != NULL_PTR){
+ delete this->_dp;
+ }
+
+ if(this->_dq != NULL_PTR){
+ delete this->_dq;
+ }
+
+ if(this->_inverseQ != NULL_PTR){
+ delete this->_inverseQ;
+ }
+}
+
+CK_BBOOL RSAPrivateKeyObject ::Compare(CK_ATTRIBUTE attribute)
+{
+ switch(attribute.type){
+
+ case CKA_MODULUS:
+ return Util::CompareU1Arrays(this->_modulus,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_PUBLIC_EXPONENT:
+ return Util::CompareU1Arrays(this->_publicExponent,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_PRIVATE_EXPONENT:
+ return Util::CompareU1Arrays(this->_d,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_PRIME_1:
+ return Util::CompareU1Arrays(this->_p,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_PRIME_2:
+ return Util::CompareU1Arrays(this->_q,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_EXPONENT_1:
+ return Util::CompareU1Arrays(this->_dp,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_EXPONENT_2:
+ return Util::CompareU1Arrays(this->_dq,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_COEFFICIENT:
+ return Util::CompareU1Arrays(this->_inverseQ,attribute.pValue,attribute.ulValueLen);
+
+ default:
+ return PrivateKeyObject::Compare(attribute);
+ }
+}
+
+CK_RV RSAPrivateKeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+ if( 0 == attribute.ulValueLen )
+ {
+ return CKR_OK;
+ }
+
+ if(objCreation == CK_FALSE){
+ switch(attribute.type){
+ case CKA_PUBLIC_EXPONENT:
+ case CKA_MODULUS:
+ case CKA_PRIVATE_EXPONENT:
+ case CKA_PRIME_1:
+ case CKA_PRIME_2:
+ case CKA_EXPONENT_1:
+ case CKA_EXPONENT_2:
+ case CKA_COEFFICIENT:
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ switch(attribute.type){
+
+ case CKA_MODULUS:
+ if(this->_modulus != NULL_PTR){
+ delete this->_modulus;
+ }
+ this->_modulus = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ case CKA_PUBLIC_EXPONENT:
+ if(this->_publicExponent != NULL_PTR){
+ delete this->_publicExponent;
+ }
+ this->_publicExponent = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ case CKA_PRIVATE_EXPONENT:
+ if(this->_d != NULL_PTR){
+ delete this->_d;
+ }
+ this->_d = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ case CKA_EXPONENT_1:
+ if(this->_dp != NULL_PTR){
+ delete this->_dp;
+ }
+ this->_dp = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+
+ case CKA_EXPONENT_2:
+ if(this->_dq != NULL_PTR){
+ delete this->_dq;
+ }
+ this->_dq = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+
+ case CKA_PRIME_1:
+ if(this->_p != NULL_PTR){
+ delete this->_p;
+ }
+ this->_p = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+
+ case CKA_PRIME_2:
+ if(this->_q != NULL_PTR){
+ delete this->_q;
+ }
+ this->_q = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+
+ case CKA_COEFFICIENT:
+ if( this->_inverseQ != NULL_PTR )
+ {
+ delete this->_inverseQ;
+ }
+ this->_inverseQ = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ default:
+ return PrivateKeyObject::SetAttribute(attribute,objCreation);
+
+ }
+
+ return CKR_OK;
+}
+
+CK_RV RSAPrivateKeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+ switch(attribute->type){
+
+ case CKA_MODULUS:
+ return StorageObject::PutU1ArrayInAttribute(this->_modulus,attribute);
+
+ case CKA_PUBLIC_EXPONENT:
+ return StorageObject::PutU1ArrayInAttribute(this->_publicExponent,attribute);
+
+ case CKA_PRIVATE_EXPONENT:
+ if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+ attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+ return CKR_ATTRIBUTE_SENSITIVE;
+ }
+ return StorageObject::PutU1ArrayInAttribute(this->_d,attribute);
+
+ case CKA_PRIME_1:
+ if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+ attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+ return CKR_ATTRIBUTE_SENSITIVE;
+ }
+ return StorageObject::PutU1ArrayInAttribute(this->_p,attribute);
+
+ case CKA_PRIME_2:
+ if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+ attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+ return CKR_ATTRIBUTE_SENSITIVE;
+ }
+ return StorageObject::PutU1ArrayInAttribute(this->_q,attribute);
+
+ case CKA_EXPONENT_1:
+ if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+ attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+ return CKR_ATTRIBUTE_SENSITIVE;
+ }
+ return StorageObject::PutU1ArrayInAttribute(this->_dp,attribute);
+
+ case CKA_EXPONENT_2:
+ if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+ attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+ return CKR_ATTRIBUTE_SENSITIVE;
+ }
+ return StorageObject::PutU1ArrayInAttribute(this->_dq,attribute);
+
+ case CKA_COEFFICIENT:
+ if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+ attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+ return CKR_ATTRIBUTE_SENSITIVE;
+ }
+ return StorageObject::PutU1ArrayInAttribute(this->_inverseQ,attribute);
+
+ default:
+ return PrivateKeyObject::GetAttribute(attribute);
+ }
+}
+
+void RSAPrivateKeyObject::Serialize(std::vector<u1> *to)
+{
+ PrivateKeyObject::Serialize(to);
+
+ // since keys will reside in the key container we are not going
+ // to marshal the key values except modulus and public exponent
+
+ Util::PushByteArrayInVector(to,this->_modulus);
+
+ Util::PushByteArrayInVector(to,this->_publicExponent);
+}
+
+void RSAPrivateKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+ PrivateKeyObject::Deserialize(from,idx);
+
+ this->_modulus = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_publicExponent = Util::ReadByteArrayFromVector(from,idx);
+}
+
+
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsaprivatekeyobject.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,53 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_rsaprivatekeyobject_h
+#define _include_rsaprivatekeyobject_h
+
+#include "privatekeyobject.h"
+
+class RSAPrivateKeyObject : public PrivateKeyObject
+{
+
+public:
+ u1Array* _publicExponent;
+ u1Array* _modulus;
+ u1Array* _d;
+ u1Array* _p;
+ u1Array* _q;
+ u1Array* _dp;
+ u1Array* _dq;
+ u1Array* _inverseQ;
+
+public:
+ RSAPrivateKeyObject();
+ virtual ~RSAPrivateKeyObject();
+
+ CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+ CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+ CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+ void Serialize(vector<u1>* to);
+ void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,152 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "rsapublickeyobject.h"
+
+RSAPublicKeyObject :: RSAPublicKeyObject() : PublicKeyObject()
+{
+ this->_modulus = NULL_PTR;
+ this->_modulusLen = 0;
+ this->_exponent = NULL_PTR;
+
+ this->_keyType = CKK_RSA;
+}
+
+RSAPublicKeyObject :: ~RSAPublicKeyObject()
+{
+ if(this->_modulus != NULL_PTR)
+ delete this->_modulus;
+
+ if(this->_exponent != NULL_PTR)
+ delete this->_exponent;
+}
+
+CK_BBOOL RSAPublicKeyObject ::Compare(CK_ATTRIBUTE attribute)
+{
+ switch(attribute.type){
+
+ case CKA_MODULUS:
+ return Util::CompareU1Arrays(this->_modulus,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_MODULUS_BITS:
+ return (this->_modulusLen == *(CK_ULONG*)attribute.pValue);
+
+ case CKA_PUBLIC_EXPONENT:
+ return Util::CompareU1Arrays(this->_modulus,attribute.pValue,attribute.ulValueLen);
+
+ default:
+ return PublicKeyObject::Compare(attribute);
+ }
+}
+
+CK_RV RSAPublicKeyObject ::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+ switch(attribute->type){
+
+ case CKA_MODULUS:
+ return StorageObject::PutU1ArrayInAttribute(this->_modulus,attribute);
+
+ case CKA_MODULUS_BITS:
+ return StorageObject::PutULongInAttribute(this->_modulusLen,attribute);
+
+ case CKA_PUBLIC_EXPONENT:
+ return StorageObject::PutU1ArrayInAttribute(this->_exponent,attribute);
+
+ default:
+ return PublicKeyObject::GetAttribute(attribute);
+ }
+}
+
+CK_RV RSAPublicKeyObject ::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+ if( 0 == attribute.ulValueLen )
+ {
+ return CKR_OK;
+ }
+
+ CK_RV rv = CKR_OK;
+
+ if(objCreation == CK_FALSE){
+ switch(attribute.type){
+ case CKA_PUBLIC_EXPONENT:
+ case CKA_MODULUS:
+ case CKA_MODULUS_BITS:
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ switch(attribute.type){
+
+ case CKA_MODULUS:
+ if(this->_modulus != NULL_PTR){
+ delete this->_modulus;
+ }
+ this->_modulus = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ this->_modulusLen = _modulus->GetLength()*8;
+ break;
+
+ case CKA_PUBLIC_EXPONENT:
+ if(this->_exponent != NULL_PTR){
+ delete this->_exponent;
+ }
+ this->_exponent = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ case CKA_MODULUS_BITS:
+ {
+ CK_ULONG utemp = StorageObject::ReadULongFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_modulusLen = utemp;}
+ }
+ break;
+
+ default:
+ return PublicKeyObject::SetAttribute(attribute,objCreation);
+ }
+
+ return rv;
+}
+
+void RSAPublicKeyObject ::Serialize(std::vector<u1> *to)
+{
+ PublicKeyObject::Serialize(to);
+
+ Util::PushByteArrayInVector(to,this->_modulus);
+
+ Util::PushByteArrayInVector(to,this->_exponent);
+
+ Util::PushULongInVector(to,this->_modulusLen);
+}
+
+void RSAPublicKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+ PublicKeyObject::Deserialize(from,idx);
+
+ this->_modulus = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_exponent = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_modulusLen = Util::ReadULongFromVector(from,idx);
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/rsapublickeyobject.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,49 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_rsapublickeyobject_h
+#define _include_rsapublickeyobject_h
+
+#include "publickeyobject.h"
+
+class RSAPublicKeyObject : public PublicKeyObject
+{
+
+public:
+ u1Array* _modulus;
+ CK_ULONG _modulusLen;
+ u1Array* _exponent;
+
+public:
+ RSAPublicKeyObject();
+ virtual ~RSAPublicKeyObject();
+
+ CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+ CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+ CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+ void Serialize(vector<u1>* to);
+ void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,4667 @@
+
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include <winscard.h>
+#include <stdexcept>
+#include "cardmoduleservice.h"
+#include <Except.h>
+#include <string>
+#include <list>
+#include <vector>
+#include <map>
+#include <memory>
+#include "session.h"
+#include "symmalgo.h"
+#include "tdes.h"
+#include "util.h"
+#include "zlib.h"
+#include "x509cert.h"
+#include "attrcert.h"
+#include "dataobject.h"
+#include "secretkeyobject.h"
+#include "transaction.h"
+#include "cardcache.h"
+#include "error.h"
+#include "timer.h"
+#include "md5.h"
+#include "log.h"
+
+
+#ifdef WIN32
+#include "BioMan.h"
+#else
+#define SCARD_CTL_CODE(code) (0x42000000 + (code))
+#endif
+
+// Helper functions to manage contents of cmapfile
+
+static void CMapFileClear(u1Array & file, u1 index);
+static void CMapFileSetName(u1Array & file, u1 index, string const & name);
+static u1 CMapFileGetFlag(u1Array const & file, u1 index);
+static void CMapFileSetFlag(u1Array & file, u1 index, u1 flag);
+static u2 CMapFileGetSignSize(u1Array const & file, u1 index);
+static void CMapFileSetSignSize(u1Array & file, u1 index, u2 size);
+static u2 CMapFileGetExchSize(u1Array const & file, u1 index);
+static void CMapFileSetExchSize(u1Array & file, u1 index, u2 size);
+
+// software RSA specific inclusion [they would be refined once I go and re-factor RSA algo as per Cryptoki naming convention]
+//#include "crypto_public.h"
+//#include "cr_rsa.h"
+
+#include "sctoken.h"
+
+#define BITS_0_7(l) ((BYTE)(l & 0xff))
+#define BITS_8_15(l) ((BYTE)(((WORD)l & 0xff00) >> 8))
+
+#define MAX_RETRY 2
+
+#define CARD_PROPERTY_PIN_INFO_EX 0x87
+#define CARD_PROPERTY_PIN_INFO 0x07
+#define CARD_PROPERTY_EXTERNAL_PIN 0x01
+#define CARD_ROLE_USER 0x01
+
+#define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400)
+//#define FEATURE_VERIFY_PIN_START 0x01
+//#define FEATURE_VERIFY_PIN_FINISH 0x02
+//#define FEATURE_MODIFY_PIN_START 0x03
+//#define FEATURE_MODIFY_PIN_FINISH 0x04
+//#define FEATURE_GET_KEY_PRESSED 0x05
+#define FEATURE_VERIFY_PIN_DIRECT 0x06
+//#define FEATURE_MODIFY_PIN_DIRECT 0x07
+//#define FEATURE_MCT_READERDIRECT 0x08
+//#define FEATURE_MCT_UNIVERSAL 0x09
+//#define FEATURE_IFD_PIN_PROP 0x0A
+//#define FEATURE_ABORT 0x0B
+
+#define UVM_PIN_ONLY 1
+#define UVM_FP_ONLY 2
+#define UVM_PIN_OR_FP 3
+#define UVM_PIN_AND_FP 4
+
+#define PIN_TYPE_REGULAR 0
+#define PIN_TYPE_EXTERNAL 1
+
+#define AUTHENTICATE_ERROR 0
+#define AUTHENTICATE_REGULAR 1
+#define AUTHENTICATE_PINPAD 2
+#define AUTHENTICATE_BIO 3
+
+
+#pragma pack(push, mdnet, 1)
+
+typedef struct PIN_VERIFY_STRUCTURE
+{
+ BYTE bTimerOut; /* timeout is seconds (00 means use default timeout) */
+ BYTE bTimerOut2; /* timeout in seconds after first key stroke */
+ BYTE bmFormatString; /* formatting options */
+ BYTE bmPINBlockString; /* bits 7-4 bit size of PIN length in APDU,
+ * bits 3-0 PIN block size in bytes after
+ * justification and formatting */
+ BYTE bmPINLengthFormat; /* bits 7-5 RFU,
+ * bit 4 set if system units are bytes, clear if
+ * system units are bits,
+ * bits 3-0 PIN length position in system units
+ */
+ BYTE bPINMaxExtraDigit1; /* Max PIN size*/
+ BYTE bPINMaxExtraDigit2; /* Min PIN size*/
+ BYTE bEntryValidationCondition; /* Conditions under which PIN entry should
+ * be considered complete */
+ BYTE bNumberMessage; /* Number of messages to display for PIN
+ verification */
+ USHORT wLangId; /* Language for messages */
+ BYTE bMsgIndex; /* Message index (should be 00) */
+ BYTE bTeoPrologue[3]; /* T=1 block prologue field to use (fill with 00) */
+ ULONG ulDataLength; /* length of Data to be sent to the ICC */
+ BYTE abData[13]; /* Data to send to the ICC */
+} PIN_VERIFY_STRUCTURE;
+
+#pragma pack(pop, mdnet)
+
+// Try/catch macros for all public methods
+#define TOKEN_TRY try
+#define TOKEN_CATCH(rv) \
+ catch(CkError & err) { rv = err.Error(); } \
+ catch(PcscError & ) { rv = CKR_FUNCTION_FAILED; } \
+ catch(Marshaller::Exception & exc) { rv = CkError::CheckMarshallerException(exc); } \
+ catch(...) { rv = CKR_GENERAL_ERROR; } \
+ if(rv==CKR_USER_NOT_LOGGED_IN || rv==CKR_PIN_INCORRECT || rv==CKR_PIN_LOCKED) \
+ _roleLogged = CKU_NONE; \
+
+namespace {
+ class CardTransaction
+ {
+ private:
+ Token * _token;
+
+ public:
+ CardTransaction(Token * token) : _token(token)
+ {
+ _token->CardBeginTransaction();
+ }
+
+ ~CardTransaction() throw()
+ {
+ try
+ {
+ _token->CardEndTransaction();
+ }
+ catch(...) {}
+ }
+ };
+}
+
+Token :: Token(std::string* reader) : _mscm(0),
+_supportGarbageCollection(true),
+_cardCache(0),
+_fPinChanged(false),
+_fContainerChanged(false),
+_fFileChanged(false),
+_version(0)
+{
+ //Log::begin( "Token::Token" );
+
+ m_dwIoctlVerifyPIN = 0;
+
+ m_sReaderName = "";
+ if( NULL != reader )
+ {
+ m_sReaderName = (*reader).c_str( );
+ }
+
+ //Log::log( "Token::Token - new CardModuleService..." );
+ std::string svcname("MSCM");
+ _mscm = new CardModuleService( reader, 5, &svcname );
+ //Log::log( "Token::Token - new CardModuleService ok" );
+
+ _mscm->DoSCardTransact(false); // Turn off transaction handling since it is performed at application level
+
+ // Transact card
+ //Log::log( "Token::Token - CardTransaction..." );
+ CardTransaction ct(this);
+ //Log::log( "Token::Token - CardTransaction ok" );
+
+ //Log::log( "Token::Token - new CardCache..." );
+ _cardCache = new CardCache(_mscm);
+ //Log::log( "Token::Token - new CardCache ok" );
+
+ // Get seed for RNG from card. This is the first command to
+ // card. If it fails, assume the card is not a .NET card.
+ try
+ {
+ //Log::log( "Token::Token - GetChallenge ..." );
+ auto_ptr<u1Array> challange(_mscm->GetChallenge());
+ //Log::log( "Token::Token - GetChallenge ok" );
+
+ Util::SeedRandom(*challange);
+ }
+ catch(...)
+ {
+ Log::error( "Token::Token", "GetChallenge - CKR_TOKEN_NOT_RECOGNIZED" );
+ throw CkError(CKR_TOKEN_NOT_RECOGNIZED);
+ }
+
+ this->_roleLogged = CKU_NONE;
+
+ // flush TokenInfo
+ memset(&this->_tokenInfo, 0x00, sizeof(this->_tokenInfo));
+
+ this->_tokenInfo.ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
+ this->_tokenInfo.ulSessionCount = CK_UNAVAILABLE_INFORMATION;
+ this->_tokenInfo.ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE;
+ this->_tokenInfo.ulRwSessionCount = CK_UNAVAILABLE_INFORMATION;
+ this->_tokenInfo.ulMaxPinLen = MAX_PIN_LEN;
+ this->_tokenInfo.ulMinPinLen = MIN_PIN_LEN;
+
+ this->_tokenInfo.ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
+ this->_tokenInfo.ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
+ this->_tokenInfo.ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
+ this->_tokenInfo.ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
+
+ // Version of the Card Operating system
+ this->_tokenInfo.hardwareVersion.major = 2;
+ this->_tokenInfo.hardwareVersion.minor = 0;
+
+ // (TBD) Version of Card Module application
+ // there is mess which have been created by reading it from file etc ?
+ this->_tokenInfo.firmwareVersion.major = 2;
+ this->_tokenInfo.firmwareVersion.minor = 0;
+
+ this->_tokenInfo.flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED;
+
+ // Check if the smart card is in SSO mode
+ if( ( true == this->isSSO( ) ) && ( true == this->isAuthenticated( ) ) )
+ {
+ this->_tokenInfo.flags &= ~CKF_LOGIN_REQUIRED;
+ }
+ /*else
+ {
+ this->_tokenInfo.flags |= CKF_LOGIN_REQUIRED;
+ }*/
+
+
+ // Check if the CKF_PROTECTED_AUTHENTICATION_PATH flag must be raised
+ m_isPinPadSupported = isPinPadSupported( );
+ //m_isPinExternal = isPinExternalSupported( );
+ BYTE bCardMode = UVM_PIN_ONLY;
+ BYTE bTypePIN = PIN_TYPE_REGULAR;
+ getCardConfiguration( bCardMode, bTypePIN );
+ Log::log( "Token::Token - PIN type <%ld> (0 = regular ; 1 = external)", bTypePIN );
+ Log::log( "Token::Token - Card mode <%ld> (1 = pin only ; 2 = fp only ; 3 = fp or pin ; 4 = fp and pin)", bCardMode );
+ if( ( bTypePIN == PIN_TYPE_EXTERNAL ) && ( ( ( bCardMode == UVM_PIN_ONLY ) && m_isPinPadSupported ) || ( bCardMode != UVM_PIN_ONLY ) ) )
+ {
+ Log::log( "Token::Token - Enable CKF_PROTECTED_AUTHENTICATION_PATH" );
+ this->_tokenInfo.flags |= CKF_PROTECTED_AUTHENTICATION_PATH;
+ }
+
+ // we need to check if token is initialized or not.
+ // Initialization would essentially mean that we create
+ // the necessary file structure.
+
+ // Get current value of \cardcf file
+ std::string sCardcf("cardcf");
+
+ //Log::log( "Token::Token - ReadFile ..." );
+ auto_ptr<u1Array> fileData(_mscm->ReadFile(&sCardcf,0));
+ //Log::log( "Token::Token - ReadFile ..." );
+
+ if(fileData->GetLength() < 6)
+ {
+ Log::error( "Token::Token", " (fileData->GetLength() < 6) - CKR_TOKEN_NOT_RECOGNIZED" );
+ throw CkError(CKR_TOKEN_NOT_RECOGNIZED);
+ }
+ CK_ULONG cardCf = LittleEndianToInt<CK_ULONG>(fileData->GetBuffer()+2);
+
+ this->_initialized = this->IsInitialized();
+
+ if(_initialized)
+ {
+ //Log::log( "Token::Token - DeserializeTokenInfo ..." );
+ this->DeserializeTokenInfo();
+ //Log::log( "Token::Token - DeserializeTokenInfo ok" );
+ }
+ else
+ {
+ //Log::log( "Token::Token - PopulateDefaultTokenInfo ..." );
+ // fill up the tokenInfo
+ this->PopulateDefaultTokenInfo();
+ //Log::log( "Token::Token - PopulateDefaultTokenInfo ok" );
+ }
+
+ // Set current values unequal to the stored to force the initial syncronization
+ _cardCfTimer = 0;
+ _cardCf = cardCf;
+ _publCardCf = ~cardCf;
+ _privCardCf = ~cardCf;
+ _cacheCardCf = ~cardCf;
+
+ //Log::end( "Token::Token" );
+}
+
+Token :: ~Token()
+{
+ delete _cardCache;
+ delete this->_mscm;
+
+ Clear();
+}
+
+
+
+void Token::ManageGC()
+{
+ if(!_supportGarbageCollection)
+ return;
+ try
+ {
+ s4 freeMemory = _mscm->GetMemory();
+ if (freeMemory < 6000)
+ {
+ Log::log( "Token::ManageGC - ForceGarbageCollector" );
+ _mscm->ForceGarbageCollector( );
+ }
+ }
+ catch(...)
+ {
+ _supportGarbageCollection = false;
+ }
+}
+
+
+void Token::Clear()
+{
+ for(size_t i=0;i<_objects.size();i++)
+ delete _objects[i];
+ _objects.clear();
+}
+
+
+void Token::BeginTransaction()
+{
+ // To improve performance, avoid checking cardcf unless there could possibly
+ // have been an update by external application, based on the time it was last
+ // known to be up-do-date, which means at end of previous transaction.
+
+ static const unsigned long maximumCardCfCheckInterval = 100; // 100 milliseconds.
+
+ CardBeginTransaction();
+ try
+ {
+ _fPinChanged = false;
+ _fContainerChanged = false;
+ _fFileChanged = false;
+
+ unsigned long tick = CTimer::ClockTicks();
+
+ // First check d.t possible timer wrap around every ~50 days.
+ if(_cardCfTimer > tick || _cardCfTimer + maximumCardCfCheckInterval < tick)
+ {
+ // Read cache file.
+ std::string sCardcf("cardcf");
+ ManageGC( );
+ auto_ptr<u1Array> fileData(_mscm->ReadFile(&sCardcf,0));
+ if(fileData->GetLength() < 6)
+ throw CkError(CKR_TOKEN_NOT_RECOGNIZED);
+
+ _cardCf = LittleEndianToInt<CK_ULONG>(fileData->GetBuffer()+2);
+ }
+
+ if((_publCardCf != _cardCf) ||
+ ((_privCardCf != _cardCf) && (_roleLogged == CKU_USER)))
+ {
+ // Card changed, so re-synchronize
+ Resynchronize();
+ }
+ }
+ catch(...)
+ {
+ CardEndTransaction();
+ throw;
+ }
+}
+
+void Token::EndTransaction( )
+{
+ try
+ {
+ // Update \cardcf if card has changed.
+ if(_fPinChanged || _fContainerChanged || _fFileChanged)
+ {
+ // cardcf format:
+ // typedef struct _CARD_CACHE_FILE_FORMAT
+ // {
+ // BYTE bVersion;
+ // BYTE bPinsFreshness;
+ // WORD wContainersFreshness;
+ // WORD wFilesFreshness;
+ // } CARD_CACHE_FILE_FORMAT, *PCARD_CACHE_FILE_FORMAT;
+
+ // Read cache file.
+ std::string sCardCf("cardcf");
+ auto_ptr<u1Array> fileData(_mscm->ReadFile(&sCardCf,0));
+
+ BYTE bPinsFreshness = fileData->ReadU1At(1);
+ WORD wContainersFreshness = LittleEndianToInt<WORD>(fileData->GetBuffer(),2);
+ WORD wFilesFreshness = LittleEndianToInt<WORD>(fileData->GetBuffer(),4);
+
+ if(_fPinChanged)
+ bPinsFreshness++;
+ if(_fContainerChanged)
+ wContainersFreshness++;
+ if(_fFileChanged)
+ wFilesFreshness++;
+
+ fileData->SetU1At(1, bPinsFreshness);
+ IntToLittleEndian<WORD>(wContainersFreshness, fileData->GetBuffer(),2);
+ IntToLittleEndian<WORD>(wFilesFreshness, fileData->GetBuffer(),4);
+
+ ManageGC( );
+
+ // Write cache file back
+ _mscm->WriteFile(&sCardCf, fileData.get());
+
+ // As a result of own update, our own cache is still valid
+ // as long as it was valid before.
+ CK_ULONG newCardCf = LittleEndianToInt<CK_ULONG>(fileData->GetBuffer()+2);
+
+ if(_publCardCf == _cardCf)
+ _publCardCf = newCardCf;
+ if(_privCardCf == _cardCf)
+ _privCardCf = newCardCf;
+ if(_cacheCardCf == _cardCf)
+ _cacheCardCf = newCardCf;
+
+ _cardCf = newCardCf;
+ _cardCfTimer = CTimer::ClockTicks();
+ }
+ else
+ _cardCfTimer = CTimer::ClockTicks();
+ }
+ catch( CkError x )
+ {
+ CK_RV rv = x.Error( );
+ Log::log( "## Error ## Token::EndTransaction - WriteFile failed <%ld>\n", rv );
+ }
+ catch( ... )
+ {
+ }
+
+ CardEndTransaction( );
+}
+
+void Token::Resynchronize()
+{
+ // To be called at initial creation and also whenever
+ // it is detected that card has been changed.
+ // When re-sync, one have to maintain the object handles
+ // of the objects that have not been deleted. Therefore,
+ // build a new object list and compare with the existing.
+
+ if(_cacheCardCf != _cardCf)
+ {
+ _cardCache->ClearAll();
+ _cacheCardCf = _cardCf;
+ }
+
+ map<int, ContainerInfo> contMap;
+ BuildContainerInfoMap(contMap);
+
+ vector<StorageObject*> newObjects;
+ vector<string> toDelete;
+
+ SynchronizePublicObjects(newObjects, toDelete, contMap);
+ SynchronizeCertificates(newObjects, contMap);
+
+ _publCardCf = _cardCf;
+
+ if(_roleLogged == CKU_USER)
+ {
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+ SynchronizePrivateObjects(newObjects, toDelete, contMap);
+ SynchronizePrivateKeys(newObjects, contMap);
+ _privCardCf = _cardCf;
+ }
+ TOKEN_CATCH(rv);
+ }
+
+ // Build the new list with new objects occupying the
+ // position as the old objects. StorageObject::IsEqual
+ // is used to compare two objects.
+ vector<StorageObject*> objects(_objects.size(), 0);
+ for(size_t iobj = 0; iobj<_objects.size(); ++iobj)
+ {
+ if(!_objects[iobj])
+ continue;
+ for(size_t inew = 0; inew < newObjects.size(); ++inew)
+ {
+ if(newObjects[inew] && newObjects[inew]->IsEqual(_objects[iobj]))
+ {
+ // Transfer ownership
+ objects[iobj] = newObjects[inew];
+ newObjects[inew] = 0;
+ break;
+ }
+ }
+ }
+
+ // Add the potential new objects, which are those left in
+ // newObjects. Add them to the end of the list
+ for(size_t inew = 0; inew < newObjects.size(); ++inew)
+ {
+ if(newObjects[inew])
+ objects.push_back(newObjects[inew]);
+ }
+
+ // Delete the objects in the old object list
+ for(size_t iobj = 0; iobj<_objects.size(); ++iobj)
+ delete _objects[iobj];
+
+ // Store the new list as current
+ _objects = objects;
+
+ // Store the list of files to delete, then delete these if logged in.
+ _toDelete = toDelete;
+
+ if(_roleLogged == CKU_USER)
+ PerformDeferredDelete();
+
+}
+
+u1Array* Token::ComputeCryptogram(u1Array* challenge,u1Array* pin)
+{
+
+ // time to prepare the master key.
+ // Only accept correct length, otherwise
+ // return a zero valued response that is
+ // sure to fail authentication.
+
+ CK_BYTE expectedCryptogram[8];
+ memset(expectedCryptogram,0x00,8); // Default
+
+ if(pin->GetLength() == 24)
+ {
+ // compute the response
+ CK_BYTE iv[8];
+ memset(iv,0,8);
+
+ CTripleDES tdes;
+
+ tdes.SetEncryptMode(ENCRYPT);
+ tdes.SetIV(iv);
+ tdes.SetCipherMode(CIPHER_MODE_ECB);
+ tdes.SetPaddingMode(PADDING_MODE_NONE);
+ tdes.SetKey(pin->GetBuffer(),24);
+ tdes.TransformFinalBlock(challenge->GetBuffer(),0,8,expectedCryptogram,0);
+ }
+ u1Array* response = new u1Array(8);
+ response->SetBuffer(expectedCryptogram);
+
+ return response;
+}
+
+CK_RV Token::DoPINValidityChecks(u1Array* pin, bool fCheckCharaceters){
+
+ if((pin->GetLength() < MIN_PIN_LEN) || (pin->GetLength() > MAX_PIN_LEN)){
+ return CKR_PIN_LEN_RANGE;
+ }
+
+ if(fCheckCharaceters)
+ {
+ // check if pin is valid
+ for (u4 i = 0; i < pin->GetLength(); i++){
+ if ((pin->GetBuffer()[i] < 0x20) ||
+ (pin->GetBuffer()[i] > 0x7D) ||
+ (pin->GetBuffer()[i] == 0x24)||
+ (pin->GetBuffer()[i] == 0x40)||
+ (pin->GetBuffer()[i] == 0x60))
+ {
+ return CKR_PIN_INVALID;
+ }
+ }
+ }
+ return CKR_OK;
+}
+
+CK_RV Token::InitPIN(u1Array* soPIN,u1Array* userPIN)
+{
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+ rv = Token::DoPINValidityChecks(userPIN);
+
+ if(rv != CKR_OK){
+ throw CkError(rv);
+ }
+
+ auto_ptr<u1Array> challenge(_mscm->GetChallenge());
+ auto_ptr<u1Array> cryptogram(ComputeCryptogram(challenge.get(), soPIN));
+
+ try{
+
+ this->_mscm->ChangeReferenceData(MODE_UNBLOCK_PIN,CARD_ROLE_USER,cryptogram.get(),userPIN,MAX_USER_PIN_TRIES);
+ this->RegisterPinUpdate();
+
+ // Log in user to update token info
+ this->_mscm->VerifyPin(CARD_ROLE_USER, userPIN);
+
+ if(_initialized)
+ DeserializeTokenInfo();
+ else
+ Initialize();
+
+ // Save User PIN Initialized flag, the other PIN flags are not stored
+ this->_tokenInfo.flags |= CKF_USER_PIN_INITIALIZED;
+ SerializeTokenInfo();
+ this->_mscm->LogOut(CARD_ROLE_USER);
+
+ // Reset some User PIN flags
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+
+ }
+ catch(Marshaller::RemotingException&){
+ rv = CKR_TOKEN_NOT_PRESENT;
+ }
+ catch(Marshaller::UnauthorizedAccessException&){
+
+ // incorrect pin
+ s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_ADMIN);
+
+ // blocked
+ if(triesRemaining == 0){
+ // update tokeninfo flahs
+ this->_tokenInfo.flags |= CKF_SO_PIN_LOCKED;
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+ }else if(triesRemaining == 1){
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+ this->_tokenInfo.flags |= CKF_SO_PIN_FINAL_TRY;
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+ }else if(triesRemaining < MAX_SO_PIN_TRIES){
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+ this->_tokenInfo.flags |= CKF_SO_PIN_COUNT_LOW;
+ }
+
+ rv = CKR_PIN_INCORRECT;
+
+ }
+ catch(std::runtime_error&){
+ rv = CKR_DEVICE_ERROR;
+ }
+ }
+ TOKEN_CATCH(rv)
+ return rv;
+}
+
+CK_RV Token::SetPIN(u1Array* oldPIN,u1Array* newPIN)
+{
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+
+ bool fCheckCharacters = (_roleLogged != CKU_SO);
+ rv = Token::DoPINValidityChecks(newPIN, fCheckCharacters);
+
+ if(rv != CKR_OK){
+ throw CkError(rv);
+ }
+
+ CK_BYTE role = 0;
+ s4 maxTries = 0;
+
+ auto_ptr<u1Array> oldPINTemp;
+ auto_ptr<u1Array> newPINTemp;
+
+ if(this->_roleLogged == CKU_SO){
+
+ role = CARD_ROLE_ADMIN;
+ maxTries = MAX_SO_PIN_TRIES;
+
+ u1Array* challenge = this->_mscm->GetChallenge();
+
+ oldPINTemp = auto_ptr<u1Array>(this->ComputeCryptogram(challenge,oldPIN));
+
+ delete challenge;
+
+ // new PIN has to be 24 bytes
+ // if not we just pad rest of bytes as zeros
+ newPINTemp = auto_ptr<u1Array>(new u1Array(24));
+ memset(newPINTemp->GetBuffer(),0,24);
+ memcpy(newPINTemp->GetBuffer(),newPIN->GetBuffer(),newPIN->GetLength());
+
+ }else{
+
+ role = CARD_ROLE_USER;
+ maxTries = MAX_USER_PIN_TRIES;
+
+ oldPINTemp = auto_ptr<u1Array>(new u1Array(oldPIN->GetLength()));
+ oldPINTemp->SetBuffer(oldPIN->GetBuffer());
+
+ newPINTemp = auto_ptr<u1Array>(new u1Array(newPIN->GetLength()));
+ newPINTemp->SetBuffer(newPIN->GetBuffer());
+ }
+
+ try{
+ this->_mscm->ChangeReferenceData(MODE_CHANGE_PIN,role,oldPINTemp.get(),newPINTemp.get(),maxTries);
+ this->RegisterPinUpdate();
+ }
+ catch(Marshaller::RemotingException&){
+ rv = CKR_TOKEN_NOT_PRESENT;
+ }
+ catch(Marshaller::UnauthorizedAccessException&){
+
+ // incorrect pin
+ s4 triesRemaining = this->_mscm->GetTriesRemaining(role);
+
+ if(role == CARD_ROLE_ADMIN){
+
+ // blocked
+ if(triesRemaining == 0){
+ // update tokeninfo flahs
+ this->_tokenInfo.flags |= CKF_SO_PIN_LOCKED;
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+ }else if(triesRemaining == 1){
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+ this->_tokenInfo.flags |= CKF_SO_PIN_FINAL_TRY;
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+ }else if(triesRemaining < MAX_SO_PIN_TRIES){
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+ this->_tokenInfo.flags |= CKF_SO_PIN_COUNT_LOW;
+ }
+
+ }else{
+
+ // blocked
+ if(triesRemaining == 0){
+ // update tokeninfo flahs
+ this->_tokenInfo.flags |= CKF_USER_PIN_LOCKED;
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+ }else if(triesRemaining == 1){
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+ this->_tokenInfo.flags |= CKF_USER_PIN_FINAL_TRY;
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+ }else if(triesRemaining < MAX_USER_PIN_TRIES){
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+ this->_tokenInfo.flags |= CKF_USER_PIN_COUNT_LOW;
+ }
+ }
+
+ rv = triesRemaining ? CKR_PIN_INCORRECT : CKR_PIN_LOCKED;
+
+
+ }
+ catch(std::runtime_error&){
+ rv = CKR_DEVICE_ERROR;
+ }
+ }
+ TOKEN_CATCH(rv)
+ return rv;
+}
+
+CK_RV Token::InitToken(u1Array* pin,u1Array* label)
+{
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+
+ // Check that label does not contain null-characters
+ PKCS11_ASSERT(label->GetLength() == 32);
+ for(u4 i = 0; i<label->GetLength(); ++i)
+ {
+ if(!label->ReadU1At(i))
+ throw CkError(CKR_ARGUMENTS_BAD);
+ }
+
+ // first check if pin is locked or not
+ s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_ADMIN);
+
+ // blocked
+ if(triesRemaining == 0){
+ throw CkError(CKR_PIN_LOCKED);
+ }
+
+ // Change User PIN to random
+ R_RANDOM_STRUCT & randomStruc = Util::RandomStruct();
+ u1Array randomPin(MAX_PIN_LEN);
+ R_GenerateBytes(randomPin.GetBuffer(), MAX_PIN_LEN, &randomStruc);
+ // Make a number to comply with rules in DoPINValidityChecks
+ for(u4 i = 0; i < MAX_PIN_LEN; ++i)
+ randomPin.SetU1At(i, '0' + randomPin.ReadU1At(i)%10); // Not 100% random any more....
+
+ rv = InitPIN(pin, &randomPin);
+ if(rv != CKR_OK)
+ throw CkError(rv);
+
+ // actual authentication
+ rv = this->AuthenticateAdmin(pin);
+ if(rv != CKR_OK){
+ throw CkError(rv);
+ }
+
+ // this seems strange the reason,
+ // I am doing this is to use DeleteObject
+ // method which expects the user to be logged
+ // in
+ this->_roleLogged = CKU_USER;
+
+ // TODO: InitToken should not care to do the regular token initialization
+ // in particular if it needs to clean up a token that will not load.....
+ // It should delete files directly as well as containers.
+ BeginTransaction();
+ try
+ {
+ if(!_initialized)
+ Initialize();
+
+ //Log::log("Deleting all token objects....");
+
+ // destroy all the token objects
+ for(size_t t=0; t<_objects.size(); t++){
+ if(this->_objects[t] != NULL_PTR){
+ // what if DeleteObject has failed for any reason ?
+ this->DeleteObject(CO_TOKEN_OBJECT | static_cast<CK_OBJECT_HANDLE>(t+1));
+ }
+ }
+
+ // Update the token's label and flags attribute.
+ // Re-fetch first to be sure _tokenInfo is valid
+ DeserializeTokenInfo();
+ _tokenInfo.flags |= CKF_TOKEN_INITIALIZED;
+ _tokenInfo.flags &= ~CKF_USER_PIN_INITIALIZED;
+ memcpy(_tokenInfo.label, label->GetBuffer(), 32);
+ SerializeTokenInfo();
+
+ _mscm->LogOut(CARD_ROLE_ADMIN);
+ _roleLogged = CKU_NONE;
+ }
+ catch(...)
+ {
+ _roleLogged = CKU_NONE;
+ try { _mscm->LogOut(CARD_ROLE_ADMIN); } catch(...) {}
+ EndTransaction();
+ throw;
+ }
+ EndTransaction();
+
+ }
+ TOKEN_CATCH(rv)
+ return rv;
+}
+
+bool Token::IsInitialized()
+{
+ bool result = false;
+
+ // the way we determine that token is not initialized
+ // is to check for the existence of p11 directory in the root
+ // since GetFiles() does not return directory I have base my judgement
+ // on the IOException or DirectoryNotFoundException for tinfo
+ std::string tinfo("p11\\tinfo");
+
+ try{
+ //ManageGC( );
+ _cardCache->ReadFile(tinfo);
+ result = true;
+ }
+ catch(...){}
+
+ return result;
+
+}
+
+void Token::CreateDirIfNotPresent(std::string* /*parent*/,std::string* dir,u1Array* acls)
+{
+
+ try{
+ this->_mscm->CreateDirectory(dir,acls);
+ }
+ catch(std::runtime_error&){
+ // ignore the exception as the directory may already be present
+ // TBD : May it more robust
+ }
+}
+
+void Token::Initialize()
+{
+ PKCS11_ASSERT(!_initialized);
+
+ std::string root("");
+ std::string p11("p11");
+
+ u1Array acls(3);
+ acls.GetBuffer()[0] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE; // admin acl
+ acls.GetBuffer()[1] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE; // usr acl
+ acls.GetBuffer()[2] = CARD_PERMISSION_READ; // everyone acl
+
+ // create p11 directory
+ this->CreateDirIfNotPresent(&root,&p11,&acls);
+
+ // create token info
+ std::string tinfo("p11\\tinfo");
+ _cardCache->ClearFileList("p11");
+ this->_mscm->CreateFile(&tinfo,&acls,0);
+
+ // Serialize default token Info
+ this->SerializeTokenInfo();
+
+ this->RegisterFileUpdate();
+
+ this->_initialized = true;
+
+}
+
+void Token::ReadAndPopulateObjects(vector<StorageObject*> & objects, vector<string> & toDelete,
+ string const & prefix, map<int, ContainerInfo> & contMap)
+{
+
+ CK_ULONG cls;
+
+ vector<string> files(_cardCache->FileList("p11"));
+
+ for(u4 i=0;i<files.size();i++)
+ {
+ std::string aFile(files[i]);
+
+ if(aFile.find(prefix) != 0) // Must start with <prefix>
+ continue;
+
+ std::string filePath("p11\\");
+
+ filePath.append(aFile);
+ const u1Array & fileData = _cardCache->ReadFile(filePath);
+
+ if (aFile.substr(prefix.size(), 3) == "dat")
+ {
+ cls = CKO_DATA;
+ }
+ //else if (aFile.substr(prefix.size(), 3) == "cer")
+ //{
+ // cls = CKO_CERTIFICATE;
+ //}
+ else if (aFile.substr(prefix.size(), 3) == "kxc")
+ {
+ cls = CKO_CERTIFICATE;
+ }
+ else if (aFile.substr(prefix.size(), 3) == "ksc")
+ {
+ cls = CKO_CERTIFICATE;
+ }
+ else if (aFile.substr(prefix.size(), 3) == "puk")
+ {
+ cls = CKO_PUBLIC_KEY;
+ }
+ else if (aFile.substr(prefix.size(), 3) == "prk")
+ {
+ cls = CKO_PRIVATE_KEY;
+ }
+ else if (aFile.substr(prefix.size(), 3) == "sec")
+ {
+ cls = CKO_SECRET_KEY;
+ }
+ else
+ {
+ cls = CKO_VENDOR_DEFINED;
+ }
+
+ StorageObject* object = NULL_PTR;
+
+ switch(cls){
+
+ case CKO_DATA:
+ object = new DataObject();
+ break;
+
+ case CKO_PUBLIC_KEY:
+ object = new RSAPublicKeyObject();
+ break;
+
+ case CKO_PRIVATE_KEY:
+ object = new RSAPrivateKeyObject();
+ break;
+
+ case CKO_SECRET_KEY:
+ object = new SecretKeyObject();
+ break;
+
+ case CKO_CERTIFICATE:
+ object = new X509PubKeyCertObject();
+ ((X509PubKeyCertObject*)object)->_certName = aFile.substr(prefix.size(), aFile.size()-prefix.size());
+ break;
+
+ default:
+ continue;
+ }
+
+ vector<u1> from;
+ for(u4 u=0;u<fileData.GetLength();u++){
+ from.push_back(fileData.GetBuffer()[u]);
+ }
+
+ CK_ULONG idx = 0;
+
+ object->Deserialize(from,&idx);
+
+ // put the fileName for the object
+ // as it is not deserialized
+ object->_fileName = filePath;
+
+ bool fAddObject = true;
+
+ // For CKO_PRIVATE_KEY and CKO_CERTIFICATE, check that the objects
+ // actually exists in the container. If they don't, flag that the
+ // file shall be deleted.
+ if(cls == CKO_PRIVATE_KEY)
+ {
+ PrivateKeyObject * privKey = static_cast<PrivateKeyObject*>(object);
+ map<int, ContainerInfo>::iterator icont = contMap.find(privKey->_ctrIndex);
+ if(icont != contMap.end() && icont->second._cmapEntry)
+ {
+ KeyPair & keyPair = (privKey->_keySpec == KEYSPEC_KEYEXCHANGE) ?
+ icont->second._exchKP : icont->second._signKP;
+ if(keyPair._checkValue == privKey->_checkValue)
+ {
+ // Object exist in the container. Flag that there exists a P11 private
+ // key for this key pair so that it will not be instantiated twice.
+ keyPair._fP11PrivKeyExists = true;
+ }
+ else
+ fAddObject = false;
+ }
+ else
+ fAddObject = false;
+ }
+ else if(cls == CKO_CERTIFICATE)
+ {
+ X509PubKeyCertObject * cert = static_cast<X509PubKeyCertObject*>(object);
+ map<int, ContainerInfo>::iterator icont = contMap.find(cert->_ctrIndex);
+ if(icont != contMap.end() && icont->second._cmapEntry)
+ {
+ u1Array certValue;
+ KeyPair & keyPair = (cert->_keySpec == KEYSPEC_KEYEXCHANGE) ?
+ icont->second._exchKP : icont->second._signKP;
+
+ certValue = keyPair._cert;
+ if(certValue.GetLength())
+ {
+ u8 checkValue = 0;
+ try
+ {
+ X509Cert x509cert(certValue.GetBuffer(), certValue.GetLength());
+ BEROctet::Blob modulus(x509cert.Modulus());
+ checkValue = Util::MakeCheckValue(modulus.data(), static_cast<unsigned int>(modulus.size()));
+ if(cert->_checkValue == checkValue)
+ {
+ // Correct certificate! Assign the value and register it.
+ // Flag that there exists a P11 certificate object for this
+ // key pair so that it will not be instantiated twice.
+ cert->_value = new u1Array();
+ *cert->_value = certValue;
+ keyPair._fP11CertExists = true;
+ }
+ else
+ fAddObject = false;
+ }
+ catch(...)
+ {
+ // Not valid X509 certificate, ignore it.
+ fAddObject = false;
+ }
+ }
+ else
+ fAddObject = false;
+ }
+ else
+ fAddObject = false;
+ }
+
+ if(fAddObject)
+ objects.push_back(object);
+ else
+ {
+ delete object;
+ toDelete.push_back(filePath);
+ }
+ }
+}
+
+void Token::SynchronizePublicObjects(vector<StorageObject*> & objects, vector<string> & toDelete, map<int, ContainerInfo> & contMap)
+{
+ //Log::log("Synchrnoizing Public Objects...");
+
+ if(!_initialized){
+ //Log::log("Token not initialized, hence no objects.");
+ return;
+ }
+
+ ReadAndPopulateObjects(objects, toDelete, "pub", contMap);
+ //ManageGC();
+}
+
+void Token::SynchronizePrivateObjects(vector<StorageObject*> & objects, vector<string> & toDelete, map<int, ContainerInfo> & contMap)
+{
+ //Log::log("Synchronizing Private Objects...");
+
+ if(!_initialized){
+ //Log::log("Token not initialized, hence no objects.");
+ return;
+ }
+
+ ReadAndPopulateObjects(objects, toDelete, "pri", contMap);
+ //ManageGC();
+}
+
+void Token::BuildContainerInfoMap(map<int, ContainerInfo> & contMap)
+{
+ contMap.clear();
+
+ // Step 1: Populate map from existence of files named mscp\kxc## and mscp\ksc##
+ string mscpDir("mscp");
+ vector<string> mscpFiles(_cardCache->FileList(mscpDir));
+
+ for(u4 ifile = 0; ifile < mscpFiles.size(); ++ifile)
+ {
+ std::string aFile(mscpFiles[ifile]);
+ if(aFile.size() != 5 || aFile[0] != 'k' || aFile[2] != 'c')
+ continue;
+
+ u1 keySpec;
+ if(aFile[1] == 'x')
+ keySpec = KEYSPEC_KEYEXCHANGE;
+ else if(aFile[1] == 's')
+ keySpec = KEYSPEC_SIGNATURE;
+ else
+ continue;
+
+ int ctrIndex;
+ if(sscanf(aFile.substr(3, 2).c_str(), "%d", &ctrIndex) != 1)
+ continue;
+ if(ctrIndex <0)
+ continue;
+
+ // Read certificate file
+
+ std::string aFilePath = mscpDir + "\\" + aFile;
+
+ auto_ptr<u1Array> value(ReadCertificateFile(aFilePath));
+
+ if(keySpec == KEYSPEC_SIGNATURE)
+ {
+ contMap[ctrIndex]._signKP._cert = *value;
+ contMap[ctrIndex]._signKP._certName = aFile;
+ }
+ else
+ {
+ contMap[ctrIndex]._exchKP._cert = *value;
+ contMap[ctrIndex]._exchKP._certName = aFile;
+ }
+ }
+
+ // Step 2: Update map from valid cmapfile entries
+
+ std::string nameCMapFile("mscp\\cmapfile");
+ const u1Array & fileData = _cardCache->ReadFile(nameCMapFile);
+ u4 contentLen = fileData.GetLength();
+ s4 entries = contentLen / SIZE_CONTAINERMAPRECORD;
+
+ vector<ContainerInfo> vContInfo;
+ for(int ctrIndex = 0; ctrIndex < entries; ++ctrIndex)
+ {
+ if(!(CMapFileGetFlag(fileData, ctrIndex) & 0x01))
+ continue; // Skip not valid containers.
+
+ // Valid cmapfile entry for this ctrIndex
+ contMap[ctrIndex]._cmapEntry = true;
+
+ if(CMapFileGetSignSize(fileData, ctrIndex) || CMapFileGetExchSize(fileData, ctrIndex))
+ {
+ // Exchange
+ const CardCache::Container & cont = _cardCache->ReadContainer(ctrIndex);
+ u4 modulusLength = cont.exchModulus.GetLength();
+ if(modulusLength && CMapFileGetExchSize(fileData, ctrIndex) == modulusLength*8)
+ {
+ contMap[ctrIndex]._exchKP._modulus = cont.exchModulus;
+ contMap[ctrIndex]._exchKP._publicExponent = cont.exchPublicExponent;
+ contMap[ctrIndex]._exchKP._checkValue = Util::MakeCheckValue(cont.exchModulus.GetBuffer(), modulusLength);
+ }
+
+ // Signature
+ modulusLength = cont.signModulus.GetLength();
+ if(modulusLength && CMapFileGetSignSize(fileData, ctrIndex) == modulusLength*8)
+ {
+ contMap[ctrIndex]._signKP._modulus = cont.signModulus;
+ contMap[ctrIndex]._signKP._publicExponent = cont.signPublicExponent;
+ contMap[ctrIndex]._signKP._checkValue = Util::MakeCheckValue(cont.signModulus.GetBuffer(), modulusLength);
+ }
+ }
+ }
+}
+
+void Token::SynchronizeCertificates(vector<StorageObject*> & objects, map<int, ContainerInfo> & contMap)
+{
+ //Log::log("Synchronizing Certificates...");
+
+ // Look for certificates in mscp that are not represented by P11 objects
+ for(map<int, ContainerInfo>::const_iterator icont = contMap.begin(); icont != contMap.end(); ++icont)
+ {
+ if(!icont->second._cmapEntry)
+ continue; // Not corresponding to a valid cmapfile entry, ignore it.
+
+ u1 ctrIndex = static_cast<u1>(icont->first);
+
+ for(int ikeySpec = 0; ikeySpec < 2; ++ikeySpec)
+ {
+ u1 keySpec = (ikeySpec == 0) ? KEYSPEC_KEYEXCHANGE : KEYSPEC_SIGNATURE;
+ const KeyPair & keyPair = (ikeySpec == 0) ? icont->second._exchKP : icont->second._signKP;
+
+ // Certificates that have already been represented by object
+ // stored under p11 directory shall not be instantiated again.
+ if(keyPair._fP11CertExists)
+ continue;
+
+ if(keyPair._cert.GetLength())
+ {
+ if(!FindCertificate(objects, ctrIndex, keySpec))
+ {
+ //Log::log("Handling enrollement done from CSP...");
+
+ u8 checkValue = 0;
+ string strLabel;
+ BEROctet::Blob blId;
+ try
+ {
+ CAttributedCertificate attrCert(keyPair._cert.GetBuffer(), keyPair._cert.GetLength());
+
+ strLabel = attrCert.DerivedName();
+ blId = attrCert.DerivedId();
+
+ BEROctet::Blob modulus(attrCert.Modulus());
+ checkValue = Util::MakeCheckValue(modulus.data(), static_cast<unsigned int>(modulus.size()));
+ }
+ catch(...)
+ {
+ // Not valid X509 certificate, ignore it
+ continue;
+ }
+
+ X509PubKeyCertObject* cert = new X509PubKeyCertObject();
+ cert->_value = new u1Array();
+ *cert->_value = keyPair._cert;
+ cert->_checkValue = checkValue;
+ cert->_certName = keyPair._certName;
+ cert->_keySpec = keySpec;
+ cert->_ctrIndex = ctrIndex;
+
+ cert->_tokenObject = CK_TRUE;
+ cert->_private = CK_FALSE;
+
+ cert->_label = new u1Array(static_cast<s4>(strLabel.size()));
+ cert->_label->SetBuffer(reinterpret_cast<const u1*>(strLabel.c_str()));
+
+ // If there is already a corresponding private key, assign
+ // the same id attribute, otherwise use the one derived from cert.
+ RSAPrivateKeyObject * priv = static_cast<RSAPrivateKeyObject*>(FindPrivateKey(objects, ctrIndex, keySpec));
+ if(priv && priv->_id->GetLength())
+ {
+ cert->_id = new u1Array();
+ *cert->_id = *priv->_id;
+ }
+ else
+ {
+ cert->_id = new u1Array(static_cast<s4>(blId.size()));
+ cert->_id->SetBuffer(reinterpret_cast<const u1*>(blId.c_str()));
+ }
+
+ // prepare object attributes from the parsed certificate
+ this->PrepareCertAttributesFromRawData(cert);
+
+ // Register this object
+ objects.push_back(cert);
+ }
+ }
+ }
+ }
+}
+
+void Token::SynchronizePrivateKeys(vector<StorageObject*> & objects, map<int, ContainerInfo> & contMap)
+{
+ //Log::log("Synchronizing Private Keys...");
+
+ // Look for private keys in cmapfile that are not represented by P11 objects
+ for(map<int, ContainerInfo>::const_iterator icont = contMap.begin(); icont != contMap.end(); ++icont)
+ {
+ if(!icont->second._cmapEntry)
+ continue; // Not corresponding to a valid cmapfile entry, ignore it.
+
+ u1 ctrIndex = static_cast<u1>(icont->first);
+
+ for(int ikeySpec = 0; ikeySpec < 2; ++ikeySpec)
+ {
+ u1 keySpec = (ikeySpec == 0) ? KEYSPEC_KEYEXCHANGE : KEYSPEC_SIGNATURE;
+ const KeyPair & keyPair = (ikeySpec == 0) ? icont->second._exchKP : icont->second._signKP;
+
+ // Private keys that have already been represented by object
+ // stored under p11 directory shall not be instantiated again.
+ if(keyPair._fP11PrivKeyExists)
+ continue;
+
+ if(keyPair._checkValue)
+ {
+ if(!FindPrivateKey(objects, ctrIndex, keySpec))
+ {
+ //Log::log("Handling enrollement done from CSP...");
+
+ RSAPrivateKeyObject* priv = new RSAPrivateKeyObject();
+
+ // If there is a corresponding certificate, use its label, id and subject attribute
+
+ // TODO: Should check type before cast, however since there
+ // are no other certificate types than X509 here, this is safe
+ X509PubKeyCertObject * cert = static_cast<X509PubKeyCertObject*>(FindCertificate(objects, ctrIndex, keySpec));
+ if(cert)
+ {
+ // If cert exist, inherit label and id from cert
+ priv->_label = new u1Array();
+ *priv->_label = *cert->_label;
+ priv->_id = new u1Array();
+ *priv->_id = *cert->_id;
+ priv->_subject = new u1Array();
+ *priv->_subject = *cert->_subject;
+ }
+ else
+ {
+ BEROctet::Blob blId(CAttributedCertificate::DerivedId(keyPair._modulus.GetBuffer(),
+ keyPair._modulus.GetLength()));
+ priv->_id = new u1Array(static_cast<s4>(blId.size()));
+ priv->_id->SetBuffer(blId.c_str());
+ }
+
+ priv->_ctrIndex = ctrIndex;
+ priv->_keySpec = keySpec;
+ priv->_tokenObject = CK_TRUE;
+ priv->_private = CK_TRUE;
+ priv->_decrypt = CK_TRUE;
+ priv->_unwrap = CK_TRUE;
+ priv->_derive = CK_FALSE;
+ priv->_sign = CK_TRUE;
+ priv->_signRecover = CK_FALSE;
+ priv->_publicExponent = new u1Array();
+ *priv->_publicExponent = keyPair._publicExponent;
+ priv->_modulus = new u1Array();
+ *priv->_modulus = keyPair._modulus;
+ priv->_checkValue = keyPair._checkValue;
+
+ // add this in the token object list
+ objects.push_back(priv);
+ }
+ }
+ }
+ }
+}
+
+void Token::PrepareCertAttributesFromRawData(X509PubKeyCertObject* certObject)
+{
+
+ u1* pCertValue = NULL;
+ unsigned long dwCertLen = 0;
+ u1Array* sernbP = NULL;
+ u1Array* issuerP = NULL;
+ u1Array* subjectP = NULL;
+
+ pCertValue = certObject->_value->GetBuffer();
+ dwCertLen = certObject->_value->GetLength();
+
+ // Parse Certifcate to extract SerNB, Issuer & Subject
+ // Create check value from modulus
+
+ try {
+ X509Cert x509cert(pCertValue, dwCertLen);
+
+ BEROctet::Blob blSerNum(x509cert.SerialNumber());
+ BEROctet::Blob blIssuer(x509cert.Issuer());
+ BEROctet::Blob blSubject(x509cert.Subject());
+ BEROctet::Blob modulus(x509cert.Modulus());
+
+ sernbP = new u1Array(static_cast<s4>(blSerNum.size()));
+ sernbP->SetBuffer(const_cast<u1*>(blSerNum.data()));
+
+ issuerP = new u1Array(static_cast<s4>(blIssuer.size()));
+ issuerP->SetBuffer(const_cast<u1*>(blIssuer.data()));
+
+ subjectP = new u1Array(static_cast<s4>(blSubject.size()));
+ subjectP->SetBuffer(const_cast<u1*>(blSubject.data()));
+
+ certObject->_serialNumber = sernbP;
+ certObject->_issuer = issuerP;
+ certObject->_subject = subjectP;
+ }
+ catch(...) {} // On parse error, these attributes can't be set.
+
+}
+
+
+CK_RV Token::AuthenticateUser(Marshaller::u1Array *pin)
+{
+ CK_RV rv = CKR_FUNCTION_NOT_SUPPORTED;
+
+ try
+ {
+ // first check if pin is locked or not
+ s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_USER);
+
+ // blocked
+ if(triesRemaining == 0)
+ {
+ // update tokeninfo flahs
+ this->_tokenInfo.flags |= CKF_USER_PIN_LOCKED;
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+
+ return CKR_PIN_LOCKED;
+ }
+
+ int iCase = howToAuthenticate( pin->GetLength( ) );
+ switch( iCase )
+ {
+ case AUTHENTICATE_REGULAR:
+ Log::log( "Token::AuthenticateUser - Normal login" );
+ this->_mscm->VerifyPin( CARD_ROLE_USER, pin );
+ rv = CKR_OK;
+ break;
+
+ case AUTHENTICATE_PINPAD:
+ Log::log( "Token::AuthenticateUser - PinPad" );
+ rv = verifyPinWithPinPad( );
+ break;
+
+ case AUTHENTICATE_BIO:
+#ifdef WIN32
+ Log::log( "Token::AuthenticateUser - BIO" );
+ rv = verifyPinWithBio( /*pin*/ );
+#else
+ Log::log( "Token::AuthenticateUser - BIO not supported !!" );
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+#endif
+ break;
+
+ default:
+ Log::log( "Token::AuthenticateUser - Unknown !!" );
+ rv = CKR_FUNCTION_NOT_SUPPORTED;
+ break;
+ }
+ }
+ catch(Marshaller::RemotingException&)
+ {
+ rv = CKR_TOKEN_NOT_PRESENT;
+ }
+ catch(Marshaller::UnauthorizedAccessException&)
+ {
+ rv = CKR_PIN_INCORRECT;
+ }
+ catch(std::runtime_error&)
+ {
+ rv = CKR_DEVICE_ERROR;
+ }
+
+ if( CKR_OK == rv )
+ {
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+ this->_roleLogged = CKU_USER;
+ }
+ else
+ {
+ // incorrect pin
+ s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_USER);
+
+ // blocked
+ if(triesRemaining == 0)
+ {
+ // update tokeninfo flahs
+ this->_tokenInfo.flags |= CKF_USER_PIN_LOCKED;
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+ }
+ else if(triesRemaining == 1)
+ {
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+ this->_tokenInfo.flags |= CKF_USER_PIN_FINAL_TRY;
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+ }
+ else if(triesRemaining < MAX_USER_PIN_TRIES)
+ {
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+ this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+ this->_tokenInfo.flags |= CKF_USER_PIN_COUNT_LOW;
+ }
+ }
+
+ return rv;
+}
+
+
+/*
+*/
+BYTE Token::howToAuthenticate( BYTE bPinLen )
+{
+ BYTE bRet = AUTHENTICATE_REGULAR;
+
+ // Get the card mode (1=PIN, 2=FingerPrint, 3=PIN or FP, 4=PIN and FP)
+ // The default mode is PIN
+ BYTE bCardMode = UVM_PIN_ONLY;
+ BYTE bTypePIN = PIN_TYPE_REGULAR;
+ getCardConfiguration( bCardMode, bTypePIN );
+ Log::log( "Token::AuthenticateUser - PIN type <%ld> (0 = regular ; 1 = external)", bTypePIN );
+ Log::log( "Token::AuthenticateUser - Card mode <%ld> (1 = pin only ; 2 = fp only ; 3 = fp or pin ; 4 = fp and pin)", bCardMode );
+ Log::log( "Token::AuthenticateUser - PIN len <%ld>", bPinLen );
+
+ if( PIN_TYPE_EXTERNAL == bTypePIN )
+ {
+ if( UVM_PIN_ONLY == bCardMode )
+ {
+ if( true == m_isPinPadSupported )
+ {
+ if( 0 == bPinLen )
+ {
+ Log::log( "Token::AuthenticateUser - External PIN && UVM1 && PINpad support && null len -> PIN pad" );
+ bRet = AUTHENTICATE_PINPAD;
+ }
+ else
+ {
+ Log::log( "Token::AuthenticateUser - External PIN && UVM1 && PINpad support && valid len -> PIN normal" );
+ bRet = AUTHENTICATE_REGULAR;
+ }
+ }
+ else
+ {
+ Log::log( "Token::AuthenticateUser - External PIN && UVM1 && NO PINpad support -> ERROR !!!" );
+ bRet = AUTHENTICATE_ERROR;
+ }
+ }
+ else
+ {
+ Log::log( "Token::AuthenticateUser - External PIN && (UVM2 || UVM3 || UVM4) -> Bio" );
+ bRet = AUTHENTICATE_BIO;
+ }
+ }
+ else
+ {
+ if( ( 0 != bPinLen ) && ( ( UVM_PIN_ONLY == bCardMode ) || ( UVM_PIN_OR_FP == bCardMode ) ) )
+ {
+ Log::log( "Token::AuthenticateUser - Regular PIN && (UVM1 || UVM3) && valid len -> PIN normal" );
+ bRet = AUTHENTICATE_REGULAR;
+ }
+ else
+ {
+ Log::log( "Token::AuthenticateUser - Regular PIN && (UVM2 || UVM4) && NO valid len -> ERROR !!!" );
+ bRet = AUTHENTICATE_ERROR;
+ }
+ }
+
+ return bRet;
+}
+
+
+CK_RV Token::AuthenticateAdmin(Marshaller::u1Array *pin)
+{
+ //Log::log("Logging as Admin...");
+
+ CK_RV rv = CKR_OK;
+
+ u1Array* challenge = NULL_PTR;
+ u1Array* response = NULL_PTR;
+
+ try{
+
+ // first check if pin is locked or not
+ s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_ADMIN);
+
+ // blocked
+ if(triesRemaining == 0){
+ // update tokeninfo flahs
+ this->_tokenInfo.flags |= CKF_SO_PIN_LOCKED;
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+
+ return CKR_PIN_LOCKED;
+ }
+
+ challenge = this->_mscm->GetChallenge();
+
+ response = this->ComputeCryptogram(challenge,pin);
+
+ this->_mscm->ExternalAuthenticate(response);
+
+ this->_roleLogged = CKU_SO;
+ }
+ catch(Marshaller::RemotingException&){
+ rv = CKR_TOKEN_NOT_PRESENT;
+ }
+ catch(Marshaller::UnauthorizedAccessException&){
+
+ // incorrect pin
+ s4 triesRemaining = this->_mscm->GetTriesRemaining(CARD_ROLE_ADMIN);
+
+ // blocked
+ if(triesRemaining == 0){
+ // update tokeninfo flahs
+ this->_tokenInfo.flags |= CKF_SO_PIN_LOCKED;
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+ }else if(triesRemaining == 1){
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+ this->_tokenInfo.flags |= CKF_SO_PIN_FINAL_TRY;
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_COUNT_LOW;
+ }else if(triesRemaining < MAX_SO_PIN_TRIES){
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_LOCKED;
+ this->_tokenInfo.flags &= ~CKF_SO_PIN_FINAL_TRY;
+ this->_tokenInfo.flags |= CKF_SO_PIN_COUNT_LOW;
+ }
+
+ return CKR_PIN_INCORRECT;
+
+ }
+ catch(std::runtime_error&)
+ {
+ rv = CKR_DEVICE_ERROR;
+ }
+
+ if(challenge != NULL_PTR)
+ delete challenge;
+
+ if(response != NULL_PTR)
+ delete response;
+
+ return rv;
+}
+
+CK_RV Token::Logout()
+{
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+
+ if(this->_roleLogged == CKU_NONE)
+ {
+ throw CkError(CKR_USER_NOT_LOGGED_IN);
+ }
+
+ u1 role = (this->_roleLogged == CKU_USER) ? CARD_ROLE_USER : CARD_ROLE_ADMIN;
+
+ try
+ {
+ // For the user
+ if( CARD_ROLE_USER == role )
+ {
+ // We log out if the SSO mode is not activated
+ if( false == isSSO( ) )
+ {
+ this->_mscm->LogOut( role );
+ }
+ }
+ // For the admin
+ else
+ {
+ // We always log out
+ this->_mscm->LogOut( role );
+ }
+
+ this->_roleLogged = CKU_NONE;
+ }
+ catch(Marshaller::RemotingException&)
+ {
+ rv = CKR_TOKEN_NOT_PRESENT;
+ }
+ catch(std::runtime_error&)
+ {
+ rv = CKR_DEVICE_ERROR;
+ }
+
+ }
+ TOKEN_CATCH(rv)
+
+ return rv;
+}
+
+CK_RV Token::Login(CK_ULONG userType,u1Array* pin)
+{
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+ if(userType == CKU_USER){
+ if((this->_tokenInfo.flags & CKF_USER_PIN_INITIALIZED) != CKF_USER_PIN_INITIALIZED){
+ throw CkError(CKR_USER_PIN_NOT_INITIALIZED);
+ }
+
+ if(this->_roleLogged == CKU_SO){
+ throw CkError(CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+ }else if(this->_roleLogged == CKU_USER){
+ throw CkError(CKR_USER_ALREADY_LOGGED_IN);
+ }
+
+ rv = AuthenticateUser(pin);
+
+ }else if(userType == CKU_SO){
+
+ if(this->_roleLogged == CKU_SO){
+ throw CkError(CKR_USER_ALREADY_LOGGED_IN);
+ }else if(this->_roleLogged == CKU_USER){
+ throw CkError(CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+ }
+
+ rv = AuthenticateAdmin(pin);
+ }
+ else
+ rv = CKR_USER_TYPE_INVALID;
+ }
+ TOKEN_CATCH(rv)
+ return rv;
+}
+
+
+/* SerializeTokenInfo
+*/
+void Token::SerializeTokenInfo()
+{
+
+ vector<u1> dataToSerialize;
+
+ // Version
+ Util::PushBBoolInVector(&dataToSerialize, _version);
+
+ // label
+ u1Array* label = new u1Array(32);
+ label->SetBuffer(this->_tokenInfo.label);
+ Util::PushByteArrayInVector(&dataToSerialize,label);
+ delete label;
+
+ // manufacturerId
+ u1Array* manuId = new u1Array(32);
+ manuId->SetBuffer(this->_tokenInfo.manufacturerID);
+ Util::PushByteArrayInVector(&dataToSerialize,manuId);
+ delete manuId;
+
+ // model
+ u1Array* model = new u1Array(16);
+ model->SetBuffer(this->_tokenInfo.model);
+ Util::PushByteArrayInVector(&dataToSerialize,model);
+ delete model;
+
+ // serial Number
+ u1Array* serialNumber = new u1Array(16);
+ serialNumber->SetBuffer(this->_tokenInfo.serialNumber);
+ Util::PushByteArrayInVector(&dataToSerialize,serialNumber);
+ delete serialNumber;
+
+ // rest of the tokenInfo struct (flags)
+ CK_FLAGS flags;
+
+ flags = this->_tokenInfo.flags;
+ flags &= ~CKF_PROTECTED_AUTHENTICATION_PATH;
+
+ Util::PushULongInVector(&dataToSerialize, flags);
+
+ std::string tinfo("p11\\tinfo");
+
+ u1Array objData((s4)dataToSerialize.size());
+
+ for(u4 i=0;i<dataToSerialize.size();i++){
+ objData.SetU1At(i,dataToSerialize.at(i));
+ }
+
+ //ManageGC( );
+
+ try
+ {
+ _cardCache->WriteFile(tinfo,objData);
+ RegisterFileUpdate();
+ }
+ catch( CkError x )
+ {
+ CK_RV rv = x.Error( );
+ Log::log( "## Error ## Token::SerializeTokenInfo - WriteFile failed <%ld>\n", rv );
+ throw;
+ }
+}
+
+void Token::DeserializeTokenInfo()
+{
+ std::string tinfo("p11\\tinfo");
+
+ const u1Array & fileData = this->_cardCache->ReadFile(tinfo);
+
+ vector<u1> from;
+ for(u4 u=0;u<fileData.GetLength();u++){
+ from.push_back(fileData.GetBuffer()[u]);
+ }
+
+ CK_ULONG idx = 0;
+
+ // Format version. Shall be 0 for this version
+ _version = Util::ReadBBoolFromVector(from,&idx);
+
+ // label
+ u1Array* label = Util::ReadByteArrayFromVector(from,&idx);
+ memcpy(this->_tokenInfo.label,label->GetBuffer(),label->GetLength());
+ delete label;
+
+ // manuid
+ u1Array* manuId = Util::ReadByteArrayFromVector(from,&idx);
+ memcpy(this->_tokenInfo.manufacturerID,manuId->GetBuffer(),manuId->GetLength());
+ delete manuId;
+
+ // model
+ u1Array* model = Util::ReadByteArrayFromVector(from,&idx);
+ memcpy(this->_tokenInfo.model,model->GetBuffer(),model->GetLength());
+ delete model;
+
+ // serial number
+ u1Array* serialNum = Util::ReadByteArrayFromVector(from,&idx);
+ memcpy(this->_tokenInfo.serialNumber,serialNum->GetBuffer(),serialNum->GetLength());
+ delete serialNum;
+
+ // Check MSCM's serial number. If this is larger than 8 bytes, do not
+ // use stored value since serial number may already have been truncated
+ // if the card was P11 enabled prior to this fix in revision 548361.
+ auto_ptr<u1Array> serialNumber(_mscm->get_SerialNumber());
+ if(serialNumber->GetLength() > 8)
+ {
+ CMD5 md5;
+ CK_BYTE hash[16];
+ md5.HashCore(serialNumber->GetBuffer(), 0, serialNumber->GetLength());
+ md5.HashFinal(hash);
+ Util::ConvAscii(hash, 8, _tokenInfo.serialNumber);
+ }
+
+ // flags
+ CK_FLAGS flags;
+
+ flags = this->_tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH;
+
+ this->_tokenInfo.flags = Util::ReadULongFromVector(from,&idx);
+
+ this->_tokenInfo.flags |= flags;
+}
+
+void Token::PopulateDefaultTokenInfo()
+{
+ CK_ULONG idx;
+
+ // initialize the token information
+
+ this->_version = 0;
+
+ for(idx=0;idx<32;idx++){
+ this->_tokenInfo.label[idx] = ' ';
+ }
+
+ this->_tokenInfo.label[0] = 'C';
+ this->_tokenInfo.label[1] = 'F';
+ this->_tokenInfo.label[2] = '.';
+ this->_tokenInfo.label[3] = 'N';
+ this->_tokenInfo.label[4] = 'E';
+ this->_tokenInfo.label[5] = 'T';
+ this->_tokenInfo.label[6] = ' ';
+ this->_tokenInfo.label[7] = 'P';
+ this->_tokenInfo.label[8] = '1';
+ this->_tokenInfo.label[9] = '1';
+
+ this->_tokenInfo.manufacturerID[0] = 'G';
+ this->_tokenInfo.manufacturerID[1] = 'e';
+ this->_tokenInfo.manufacturerID[2] = 'm';
+ this->_tokenInfo.manufacturerID[3] = 'a';
+ this->_tokenInfo.manufacturerID[4] = 'l';
+ this->_tokenInfo.manufacturerID[5] = 't';
+ this->_tokenInfo.manufacturerID[6] = 'o';
+
+ for(idx=7;idx<32;idx++){
+ this->_tokenInfo.manufacturerID[idx] = ' ';
+ }
+
+ this->_tokenInfo.model[0] = '.';
+ this->_tokenInfo.model[1] = 'N';
+ this->_tokenInfo.model[2] = 'E';
+ this->_tokenInfo.model[3] = 'T';
+ this->_tokenInfo.model[4] = ' ';
+ this->_tokenInfo.model[5] = 'C';
+ this->_tokenInfo.model[6] = 'a';
+ this->_tokenInfo.model[7] = 'r';
+ this->_tokenInfo.model[8] = 'd';
+
+ for(idx=9;idx<16;idx++){
+ this->_tokenInfo.model[idx] = ' ';
+ }
+
+ for(idx=0;idx<16;idx++){
+ this->_tokenInfo.serialNumber[idx] = ' ';
+ }
+
+ // If serial number length is too big to fit in 16 (hex) digit field,
+ // then use the 8 first bytes of MD5 hash of the original serial number.
+ auto_ptr<u1Array> serialNumber(_mscm->get_SerialNumber());
+ if(serialNumber->GetLength() > 8)
+ {
+ CMD5 md5;
+ CK_BYTE hash[16];
+ md5.HashCore(serialNumber->GetBuffer(), 0, serialNumber->GetLength());
+ md5.HashFinal(hash);
+ Util::ConvAscii(hash, 8, _tokenInfo.serialNumber);
+ }
+ else
+ Util::ConvAscii(serialNumber->GetBuffer(),serialNumber->GetLength(),this->_tokenInfo.serialNumber);
+
+}
+
+CK_RV Token::GenerateRandom(CK_BYTE_PTR randomData,CK_ULONG len)
+{
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+ // usng the challenge as the random data
+ u1Array* random = NULL_PTR;
+
+ random = this->_mscm->GetChallenge();
+
+ // now requested length can be more or less than the
+ // 8 bytes which challenge generates.
+ CK_ULONG minLen = len < 8 ? len : 8;
+ memcpy(randomData,random->GetBuffer(),minLen);
+
+ // lets put soft ramdom as the rest of the bytes
+ unsigned int uSeed;
+
+ memcpy((BYTE *)&uSeed, random->GetBuffer(), sizeof(unsigned int));
+ srand(uSeed);
+
+ if(len > 8)
+ {
+ for(u4 i=8;i<len;i++)
+ {
+ randomData[i] = (BYTE)(rand() % RAND_MAX);
+ }
+ }
+
+ delete random;
+ }
+ TOKEN_CATCH(rv)
+ return rv;
+}
+
+CK_ULONG Token::FindObjects(Session* session,CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG ulMaxObjectCount,CK_ULONG_PTR pulObjectCount)
+{
+ CK_RV rv = CKR_OK;
+ CK_ULONG idx = 0;
+ TOKEN_TRY
+ {
+
+ for(s4 i=0;(i < static_cast<s4>(_objects.size())) && (idx < ulMaxObjectCount);i++){
+
+ if(this->_objects[i] == NULL_PTR){
+ continue;
+ }
+
+ if(session->_tokenObjectsReturnedInSearch[i+1]){
+ continue;
+ }
+
+ if((this->_objects[i]->_private == CK_TRUE) &&
+ (this->_roleLogged != CKU_USER))
+ {
+ continue;
+ }
+
+ if(session->_searchTempl == NULL_PTR){
+ phObject[idx++] = CO_TOKEN_OBJECT | (i+1);
+ *pulObjectCount = *pulObjectCount + 1;
+ session->_tokenObjectsReturnedInSearch[i+1] = true;
+ }
+ else{
+ CK_BBOOL match = CK_TRUE;
+
+ vector<CK_ATTRIBUTE> attributes = session->_searchTempl->_attributes;
+ for(CK_ULONG a=0;a<attributes.size();a++){
+ if(this->_objects[i]->Compare(attributes.at(a)) == CK_FALSE){
+ match = CK_FALSE;
+ break;
+ }
+ }
+
+ if(match == CK_TRUE){
+ phObject[idx++] = CO_TOKEN_OBJECT | (i+1);
+ *pulObjectCount = *pulObjectCount + 1;
+ session->_tokenObjectsReturnedInSearch[i+1] = true;
+ }
+ }
+ }
+ }
+ TOKEN_CATCH(rv)
+ return idx;
+}
+
+
+string Token::FindFreeFileName(StorageObject* object)
+{
+ std::string fileName(object->_private ? "pri" : "pub");
+
+ switch(object->_class){
+ case CKO_DATA:
+ fileName.append("dat");
+ break;
+
+ case CKO_PUBLIC_KEY:
+ fileName.append("puk");
+ break;
+
+ case CKO_PRIVATE_KEY:
+ fileName.append("prk");
+ break;
+
+ case CKO_CERTIFICATE:
+ fileName.append(((X509PubKeyCertObject*)object)->_certName);
+ break;
+
+ case CKO_SECRET_KEY:
+ fileName.append("sec");
+ break;
+
+ default:
+ throw CkError(CKR_FUNCTION_FAILED);
+ }
+
+ if(object->_class != CKO_CERTIFICATE)
+ {
+
+
+ // Find free name
+ map<CK_LONG, bool> occupied;
+
+ if(_initialized)
+ {
+ // get the file names in above dir
+ vector<string> files(_cardCache->FileList("p11"));
+
+ for(u4 i=0;i<files.size();i++)
+ {
+ std::string fn(files[i]);
+ if(fn.find(fileName) == 0)
+ {
+ CK_LONG idx = atoi(fn.substr(fileName.size(), 2).c_str());
+ occupied[idx] = true;
+ }
+ }
+ }
+
+ s4 i = 0;
+ while(occupied.find(i) != occupied.end())
+ i++;
+ fileName.append(Util::MakeIntString(i, 2));
+ }
+
+ return fileName;
+
+}
+
+
+/* WriteObject
+*/
+CK_RV Token::WriteObject( StorageObject* object )
+{
+ //ManageGC( );
+
+ CK_RV rv = CKR_OK;
+
+ std::string fileName( "p11\\" + FindFreeFileName( object ) );
+
+ // This object is stored under p11 directory, assign a unique ID for future identification.
+ object->_uniqueId = Util::MakeUniqueId( );
+
+ vector<u1> to;
+ object->Serialize( &to );
+
+ u1Array objData( (s4)to.size( ) );
+ for( u4 i = 0 ; i < to.size( ) ; i++ )
+ {
+ objData.SetU1At( i, to.at( i ) );
+ }
+
+ u1Array acls( 3 );
+ acls.GetBuffer( )[ 0 ] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE; // admin acl
+ acls.GetBuffer( )[ 1 ] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE; // usr acl
+
+ if( object->_private )
+ {
+ acls.GetBuffer( )[ 2 ] = 0; // everyone acl
+ }
+ else
+ {
+ // public objects can be written or read by everyone provide the session is correct
+
+ // NOTE: Breaking PKCS#11 Compliance
+ // In the card you can not create public objects unless you are logged in
+ // even for R/W Pulblic session
+
+ acls.GetBuffer( )[ 2 ] = CARD_PERMISSION_READ; // everyone acl
+ }
+
+ if( !_initialized )
+ {
+ Initialize( );
+ }
+
+ _cardCache->ClearFileList( "p11" );
+
+ // No try/catch. It is managed by the calling method.
+ //ManageGC( );
+ this->_mscm->CreateFile( &fileName, &acls, 0 );
+
+ try
+ {
+ //ManageGC( );
+ this->_cardCache->WriteFile( fileName, objData );
+
+ RegisterFileUpdate( );
+ object->_fileName = fileName;
+ }
+ catch( CkError x )
+ {
+ rv = x.Error( );
+ Log::log( "## ERROR ## Token::WriteObject - WriteFile failed <%ld>\n", rv );
+ }
+
+ if( CKR_OK != rv )
+ {
+ try
+ {
+ _mscm->DeleteFile( &fileName );
+ }
+ catch( ... )
+ {
+ Log::log( "## ERROR ## Token::WriteObject - DeleteFile failed\n" );
+ }
+ }
+
+ return rv;
+}
+
+
+CK_RV Token::AddObject(auto_ptr<StorageObject> & stobj, CK_OBJECT_HANDLE_PTR phObject)
+{
+ //ManageGC();
+
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+ // from the class field we will be able to determine proper type
+ // and hence the corresponding file
+ //CheckAvailableSpace( );
+
+ CK_RV rv = WriteObject(stobj.get());
+ if(rv == CKR_OK)
+ {
+ *phObject = CO_TOKEN_OBJECT | RegisterStorageObject(stobj.get());
+ stobj.release();
+ }
+ }
+ TOKEN_CATCH(rv)
+ return rv;
+}
+
+
+/* AddPrivateKeyObject
+*/
+CK_RV Token::AddPrivateKeyObject( auto_ptr< StorageObject > &stobj, CK_OBJECT_HANDLE_PTR phObject )
+{
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+ RSAPrivateKeyObject *object = static_cast< RSAPrivateKeyObject* >( stobj.get( ) );
+ if( !object->_private )
+ {
+ throw CkError( CKR_ATTRIBUTE_VALUE_INVALID );
+ }
+
+ // Public key modulus is mandatory, so unless provided by the template,
+ // see if there is a public key with matching CKA_ID. Otherwise return
+ // CKR_TEMPLATE_INCOMPLETE.
+
+ RSAPublicKeyObject* rsaPub = NULL_PTR;
+ if( !object->_modulus )
+ {
+ // Search for corresponding public key to make criteria that is used here is to match the CKA_ID
+ CK_BBOOL foundPub = CK_FALSE;
+ for( s4 i = 0 ; i < static_cast< s4 >( _objects.size( ) ) ; i++ )
+ {
+ if( this->_objects[ i ] != NULL_PTR )
+ {
+ if( this->_objects[ i ]->_class == CKO_PUBLIC_KEY )
+ {
+ rsaPub = (RSAPublicKeyObject*)this->_objects[ i ];
+ foundPub = Util::CompareByteArrays( rsaPub->_id->GetBuffer( ), object->_id->GetBuffer( ), rsaPub->_id->GetLength( ) );
+ if( foundPub == CK_TRUE )
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ if( !foundPub )
+ {
+ throw CkError(CKR_TEMPLATE_INCOMPLETE); // Sorry, now other choice...
+ }
+ }
+
+ u1Array publExp;
+ u4 modLength = 0;
+ if( object->_modulus != NULL_PTR )
+ {
+ publExp = *object->_publicExponent;
+ modLength = object->_modulus->GetLength( );
+ object->_checkValue = Util::MakeCheckValue( object->_modulus->GetBuffer( ), modLength );
+ }
+ else
+ {
+ PKCS11_ASSERT( rsaPub );
+ publExp = *rsaPub->_exponent;
+ modLength = rsaPub->_modulus->GetLength();
+ object->_checkValue = Util::MakeCheckValue(rsaPub->_modulus->GetBuffer(), modLength);
+ }
+ if(publExp.GetLength() < 1 || publExp.GetLength() > 4)
+ throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+
+ if( (modLength*8 < RSA_KEY_MIN_LENGTH) ||
+ (modLength*8 > RSA_KEY_MAX_LENGTH) )
+ throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+
+ if(publExp.GetLength() < 4)
+ {
+ // Pad with zeros in the front since big endian
+ u1Array exp(4);
+ memset(exp.GetBuffer(), 0, exp.GetLength());
+ size_t i = 4 - publExp.GetLength();
+ memcpy(exp.GetBuffer()+i, publExp.GetBuffer(), publExp.GetLength());
+ publExp = exp;
+ }
+
+ // Look for existing matching certificate
+ // First, read the container map record file
+ std::string nameCMapFile("mscp\\cmapfile");
+ const u1Array & fileData(_cardCache->ReadFile(nameCMapFile));
+
+ object->_keySpec = KEYSPEC_KEYEXCHANGE; // Default
+
+ // NOTE: If it finds a matching certificate, the keySpec
+ // will be modified to match that of the certificate.
+ CK_BYTE ctrIdx = GetContainerForPrivateKey(fileData, object->_checkValue, &object->_keySpec);
+ if(ctrIdx > 99)
+ {
+ Log::error( "Token::AddPrivateKeyObject", "ctrIdx > 99 - Return CKR_DEVICE_MEMORY" );
+ throw CkError(CKR_DEVICE_MEMORY);
+ }
+ object->_ctrIndex = ctrIdx;
+
+ auto_ptr<u1Array> keyValue;
+
+ //
+ /*
+ if( object->_modulus->GetLength( ) != object->_d->GetLength( ) )
+ {
+ }
+ if( ( object->_modulus->GetLength( ) / 2 ) != object->_p->GetLength( ) )
+ {
+ }
+ if( ( object->_modulus->GetLength( ) / 2 ) != object->_q->GetLength( ) )
+ {
+ }
+ if( ( object->_modulus->GetLength( ) / 2 ) != object->_dp->GetLength( ) )
+ {
+ }
+ if( ( object->_modulus->GetLength( ) / 2 ) != object->_dq->GetLength( ) )
+ {
+ }
+ */
+ if( ( object->_modulus->GetLength( ) / 2 ) != object->_inverseQ->GetLength( ) )
+ {
+ // Pad with zeros in the front since big endian
+ u1Array val( (s4)( object->_modulus->GetLength( ) / 2 ) );
+ memset( val.GetBuffer( ), 0, val.GetLength( ) );
+ size_t i = val.GetLength( )- object->_inverseQ->GetLength( );
+ memcpy( val.GetBuffer( ) + i, object->_inverseQ->GetBuffer(), object->_inverseQ->GetLength( ) );
+ *(object->_inverseQ) = val;
+ /*
+ // Create a new buffer with the a correct size
+ u1Array val( (s4)( object->_modulus->GetLength( ) / 2 ) );
+ //auto_ptr<u1Array> val = auto_ptr<u1Array>(new u1Array(keyLength));
+
+ // Fill the buffer with zero
+ for( size_t i = 0; i < val.GetLength( ) ; i++ )
+ {
+ val.SetU1At( i, 0 );
+ }
+
+ // Fill the buffer with the old value
+ u4 j = 0;
+ for( size_t i = ( val.GetLength( )- object->_inverseQ->GetLength( ) ) ; i < object->_inverseQ->GetLength( ) ; i++ )
+ {
+ val.SetU1At( i, object->_inverseQ->ReadU1At( j ) );
+ j++;
+ }
+
+ object->_inverseQ = &val;
+ */
+ }
+
+ // compute the total length;
+ s4 keyLength = object->_p->GetLength() +
+ object->_q->GetLength() +
+ object->_inverseQ->GetLength() +
+ object->_dp->GetLength() +
+ object->_dq->GetLength() +
+ object->_d->GetLength();
+
+ if(object->_modulus != NULL_PTR){
+ keyLength += object->_modulus->GetLength();
+ //keyLength += object->_publicExponent->GetLength();
+ keyLength += 4; // public exponent expected by card is on 4 bytes
+ }else{
+ keyLength += rsaPub->_modulus->GetLength();
+ //keyLength += rsaPub->_exponent->GetLength();
+ keyLength += 4; // public exponent expected by card is on 4 bytes
+ }
+
+ s4 offset = 0;
+
+ // Prepare the keyValue
+ keyValue = auto_ptr<u1Array>(new u1Array(keyLength));
+ memset(keyValue->GetBuffer(),0,keyValue->GetLength()); // let's zeroed it
+
+ memcpy(keyValue->GetBuffer(),object->_p->GetBuffer(),object->_p->GetLength());
+
+ offset += object->_p->GetLength();
+
+ memcpy((u1*)&keyValue->GetBuffer()[offset],object->_q->GetBuffer(),object->_q->GetLength());
+
+ offset += object->_q->GetLength();
+
+ memcpy((u1*)&keyValue->GetBuffer()[offset],object->_inverseQ->GetBuffer(),object->_inverseQ->GetLength());
+
+ offset += object->_inverseQ->GetLength();
+
+ memcpy((u1*)&keyValue->GetBuffer()[offset],object->_dp->GetBuffer(),object->_dp->GetLength());
+
+ offset += object->_dp->GetLength();
+
+ memcpy((u1*)&keyValue->GetBuffer()[offset],object->_dq->GetBuffer(),object->_dq->GetLength());
+
+ offset += object->_dq->GetLength();
+
+ memcpy((u1*)&keyValue->GetBuffer()[offset],object->_d->GetBuffer(),object->_d->GetLength());
+
+ offset += object->_d->GetLength();
+
+ u4 modulusLen = 0;
+
+ string contName;
+ if(object->_modulus != NULL_PTR){
+
+ memcpy((u1*)&keyValue->GetBuffer()[offset],object->_modulus->GetBuffer(),object->_modulus->GetLength());
+
+ offset += object->_modulus->GetLength();
+
+ memcpy((u1*)&keyValue->GetBuffer()[offset],publExp.GetBuffer(),publExp.GetLength());
+
+ modulusLen = object->_modulus->GetLength();
+
+ contName = CAttributedCertificate::DerivedUniqueName(object->_modulus->GetBuffer(),
+ object->_modulus->GetLength());
+
+ }else{
+
+ memcpy((u1*)&keyValue->GetBuffer()[offset],rsaPub->_modulus->GetBuffer(),rsaPub->_modulus->GetLength());
+
+ offset += rsaPub->_modulus->GetLength();
+
+ memcpy((u1*)&keyValue->GetBuffer()[offset],publExp.GetBuffer(),publExp.GetLength());
+
+ modulusLen = rsaPub->_modulus->GetLength();
+
+ contName = CAttributedCertificate::DerivedUniqueName(rsaPub->_modulus->GetBuffer(),
+ rsaPub->_modulus->GetLength());
+
+ }
+
+ //try
+ //{
+ this->_cardCache->ClearContainer(ctrIdx); // Invalidate cache
+ //this->_mscm->CreateCAPIContainer(ctrIdx,CK_TRUE,object->_keySpec,(modulusLen*8),keyValue.get());
+ int ntry = 0;
+ while( ntry < MAX_RETRY )
+ {
+ try
+ {
+ ManageGC( );
+ ntry++;
+ this->_mscm->CreateCAPIContainer(ctrIdx,CK_TRUE,object->_keySpec,(modulusLen*8),keyValue.get());
+ break;
+ }
+ catch( Marshaller::Exception & x )
+ {
+ CK_RV rv = CkError::CheckMarshallerException( x );
+ if( CKR_DEVICE_MEMORY == rv )
+ {
+ Log::error( "Token::AddPrivateKeyObject", "ForceGarbageCollector" );
+ _mscm->ForceGarbageCollector( );
+ if( ntry >= MAX_RETRY )
+ {
+ Log::error( "Token::AddPrivateKeyObject", "Throw Exception CKR_DEVICE_MEMORY" );
+ throw CkError( rv );
+ }
+ }
+ else
+ {
+ throw CkError( rv );
+ }
+ }
+ }
+
+ this->RegisterContainerUpdate();
+ /*}
+ catch(...)
+ {
+ Log::error( "Token::AddPrivateKeyObject", "ctrIdx > 99 - Return CKR_DEVICE_MEMORY" );
+
+ throw CkError(CKR_DEVICE_MEMORY);
+ }*/
+
+ object->_ctrIndex = ctrIdx;
+
+ rv = this->AddObject(stobj,phObject);
+ if(rv == CKR_OK)
+ {
+ try
+ {
+ auto_ptr<u1Array> newCMap( UpdateCMap( ctrIdx, fileData, (modulusLen*8), object->_keySpec, CK_TRUE, contName ) );
+ this->_cardCache->WriteFile( nameCMapFile, *newCMap );
+ this->RegisterFileUpdate( );
+ }
+ catch( CkError x )
+ {
+ rv = x.Error( );
+ Log::log( "## Error ## Token::AddPrivateKeyObject - WriteFile <%ld>\n", rv );
+
+ try
+ {
+ DeleteObject( *phObject );
+ }
+ catch( ... )
+ {
+ }
+
+ throw CkError( rv );
+ }
+ }
+ }
+ TOKEN_CATCH( rv )
+
+ return rv;
+}
+
+
+/* DeleteCMapRecord
+*/
+void Token::DeleteCMapRecord( CK_BYTE ctrIndex )
+{
+ // Read the container map record file
+ std::string nameCMapFile( "mscp\\cmapfile" );
+
+ try
+ {
+ u1Array fileData( _cardCache->ReadFile( nameCMapFile ) );
+
+ s4 entries = ( fileData.GetLength( ) / SIZE_CONTAINERMAPRECORD );
+ if( ctrIndex >= entries )
+ {
+ return; // Silently ignore if doesn't exist
+ }
+
+ // Nullify the entries at ctrIndex
+ CMapFileClear( fileData, ctrIndex );
+
+ // Set default container
+ SetDefaultContainer( fileData, 0xFF );
+
+ //ManageGC( );
+
+ // Write the updated content back to cmap
+ this->_cardCache->WriteFile( nameCMapFile, fileData );
+ this->RegisterFileUpdate( );
+ }
+ catch( CkError x )
+ {
+ /*CK_RV rv =*/ x.Error( );
+ Log::error( "Token::DeleteCMapRecord", "WriteFile failed" );
+ throw;
+ }
+ /*
+ catch(Marshaller::RemotingException&){
+ // TBD
+ }
+ catch(Marshaller::UnauthorizedAccessException&){
+ // TBD
+ }
+ catch(std::runtime_error&){
+ // TBD
+ }
+ */
+}
+
+void Token::RemoveKeyFromCMapRecord(CK_BYTE ctrIndex, u1 keySpec)
+{
+
+ try{
+ // read the container map record file
+ std::string nameCMapFile("mscp\\cmapfile");
+ u1Array fileData(_cardCache->ReadFile(nameCMapFile));
+
+ s4 entries = (fileData.GetLength() / SIZE_CONTAINERMAPRECORD);
+ if(ctrIndex >= entries)
+ {
+ PKCS11_ASSERT(0);
+ return; // Silently ignore if doesn't exist
+ }
+
+ // Clear the key size corresponding to keyspec
+ if(keySpec == KEYSPEC_KEYEXCHANGE)
+ CMapFileSetExchSize(fileData, ctrIndex, 0);
+ else if(keySpec == KEYSPEC_SIGNATURE)
+ CMapFileSetSignSize(fileData, ctrIndex, 0);
+ else
+ return; // unknown key spec
+
+ //ManageGC();
+
+ // now write the updated content back to cmap
+ this->_cardCache->WriteFile(nameCMapFile,fileData);
+ this->RegisterFileUpdate();
+
+ }
+ catch( CkError x )
+ {
+ /*CK_RV rv =*/ x.Error( );
+ Log::error( "Token::RemoveKeyFromCMapRecord", "WriteFile failed" );
+ }
+ /*
+ catch(Marshaller::RemotingException&){
+ // TBD
+ }
+ catch(Marshaller::UnauthorizedAccessException&){
+ // TBD
+ }
+ catch(std::runtime_error&){
+ // TBD
+ }
+ */
+}
+
+void Token::SetDefaultContainer(u1Array & contents, CK_BYTE ctrIndex)
+{
+
+ s4 entries = (contents.GetLength() / SIZE_CONTAINERMAPRECORD);
+
+ if(ctrIndex == 0xFF)
+ {
+ for (s4 i=0;i<entries;i++)
+ {
+ if((CMapFileGetFlag(contents, i) & 0x03) == 0x03)
+ return; // A valid container already default, finished
+ }
+
+ // Find first best suitable. Look for one with keys
+ for (s4 i=0;i<entries;i++)
+ {
+ u1 flags = CMapFileGetFlag(contents, i);
+ if((flags & 0x01) && (CMapFileGetExchSize(contents, i) || CMapFileGetSignSize(contents, i)))
+ {
+ CMapFileSetFlag(contents, i, (flags | 0x02));
+ return;
+ }
+ }
+
+ // If no container with keys, then assign any valid container as default
+ for (s4 i=0;i<entries;i++)
+ {
+ u1 flags = CMapFileGetFlag(contents, i);
+ if(flags & 0x01)
+ {
+ CMapFileSetFlag(contents, i, (flags | 0x02));
+ return;
+ }
+ }
+ }
+ else
+ {
+ // Assign specific container as default
+ PKCS11_ASSERT(ctrIndex < entries);
+ if(ctrIndex >= entries)
+ return;
+ // Remove existing default container
+ for (s4 i=0;i<entries;i++)
+ {
+ u1 flags = CMapFileGetFlag(contents, i);
+ CMapFileSetFlag(contents, i, (flags & ~0x02));
+ }
+ CMapFileSetFlag(contents, ctrIndex, CMapFileGetFlag(contents, ctrIndex) | 0x02);
+ }
+}
+
+CK_RV Token::AddCertificateObject(auto_ptr<StorageObject> & stobj, CK_OBJECT_HANDLE_PTR phObject)
+{
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+ X509PubKeyCertObject * object = static_cast<X509PubKeyCertObject*>(stobj.get());
+
+ if(object->_private)
+ throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+
+ //CheckAvailableSpace();
+
+ // Make check value and look for possibly existing private key(s)
+
+ BEROctet::Blob modulus;
+ try
+ {
+ X509Cert x509cert(object->_value->GetBuffer(), object->_value->GetLength());
+ modulus =x509cert.Modulus();
+ }
+ catch(...)
+ {
+ throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+ }
+
+ object->_checkValue = Util::MakeCheckValue(modulus.data(), static_cast<unsigned int>(modulus.size()));
+ string contName(CAttributedCertificate::DerivedUniqueName(modulus));
+
+ std::string nameCMapFile("mscp\\cmapfile");
+ const u1Array & fileData(_cardCache->ReadFile(nameCMapFile));
+
+ object->_keySpec = KEYSPEC_KEYEXCHANGE; // Default
+
+ // NOTE: If it finds a matching private key, the keySpec
+ // will be modified to match that of the private key.
+ CK_BYTE ctrIdx = GetContainerForCert(fileData, object->_checkValue, &object->_keySpec);
+ if(ctrIdx > 99)
+ {
+ Log::error( "Token::AddCertificateObject", "ctrIdx > 99 - Return CKR_DEVICE_MEMORY" );
+
+ throw CkError(CKR_DEVICE_MEMORY);
+ }
+ object->_ctrIndex = ctrIdx;
+
+ if(object->_keySpec == KEYSPEC_KEYEXCHANGE)
+ object->_certName = "kxc";
+ else
+ object->_certName = "ksc";
+ object->_certName.append(Util::MakeIntString(ctrIdx, 2));
+
+ string fileName("mscp\\");
+ fileName.append(object->_certName);
+
+ unsigned long ccLen = object->_value->GetLength();
+ autoarray<u1> cc(new u1[ccLen+4]);
+
+ cc[0] = 0x01;
+ cc[1] = 0x00;
+ cc[2] = BITS_0_7(ccLen);
+ cc[3] = BITS_8_15(ccLen);
+
+ // compress the certificate
+ // compress((u1*)&cc[4],&ccLen,object->_value->GetBuffer(),ccLen);
+ compress2((u1*)&cc[4],&ccLen,object->_value->GetBuffer(),ccLen, 6); // Set level=6, same as Minidriver
+
+ auto_ptr<u1Array> compressedCert(new u1Array((ccLen + 4)));
+ compressedCert->SetBuffer(cc.get());
+
+ auto_ptr<u1Array> acls(new u1Array(3));
+ acls->GetBuffer()[0] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE; // admin acl
+ acls->GetBuffer()[1] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE; // usr acl
+ acls->GetBuffer()[2] = CARD_PERMISSION_READ; // everyone acl
+
+ //ManageGC();
+
+ _cardCache->ClearFileList("mscp");
+ this->_mscm->CreateFile(&fileName,acls.get(),0);
+ try
+ {
+ this->_cardCache->WriteFile(fileName,*compressedCert);
+ this->RegisterFileUpdate();
+ }
+ catch( CkError x )
+ {
+ rv = x.Error( );
+ Log::error( "Token::AddCertificateObject", "WriteFile failed" );
+ }
+
+ if( CKR_OK != rv )
+ {
+ try
+ {
+ _mscm->DeleteFile( &fileName );
+ }
+ catch( ... )
+ {
+ }
+
+ throw CkError( rv );
+ }
+
+ rv = AddObject(stobj ,phObject);
+ if(rv == CKR_OK)
+ {
+ //ManageGC();
+
+ try
+ {
+ auto_ptr<u1Array> newCMap(UpdateCMap(ctrIdx,fileData, contName));
+ _cardCache->WriteFile(nameCMapFile,*newCMap);
+ RegisterFileUpdate();
+ }
+ catch( CkError x )
+ {
+ rv = x.Error( );
+ Log::error( "Token::AddCertificateObject", "WriteFile 2 failed" );
+ }
+
+ if( CKR_OK != rv )
+ {
+ try
+ {
+ _mscm->DeleteFile( &fileName );
+ }
+ catch( ... )
+ {
+ }
+
+ try
+ {
+ DeleteObject( *phObject );
+ }
+ catch( ... )
+ {
+ }
+
+ throw CkError( rv );
+ }
+ }
+ }
+ TOKEN_CATCH(rv)
+ return rv;
+}
+
+CK_RV Token::DeleteObject( CK_OBJECT_HANDLE hObject )
+{
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+ StorageObject * obj = GetObject(hObject);
+
+ // some more checks
+ if((this->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE)){
+ throw CkError(CKR_USER_NOT_LOGGED_IN);
+ }
+
+ if(obj->_class == CKO_CERTIFICATE){
+
+ //Log::log("Deleting the certificate.");
+
+ CertificateObject * cert = static_cast<CertificateObject*>(obj);
+ CK_BYTE ctrIdx = cert->_ctrIndex;
+
+ if(ctrIdx != 0xFF){
+
+ // Delete the file under mscp
+
+ string fileName("mscp\\");
+ fileName.append(cert->_certName);
+ _cardCache->ClearFile(fileName);
+ try
+ {
+ _cardCache->ClearFileList("mscp");
+ _mscm->DeleteFile(&fileName);
+ RegisterFileUpdate();
+ }
+ catch(FileNotFoundException &) {}
+
+ // Check if there exist private key(s) or other
+ // certificate (with different key spec) in the container
+ u1 otherKeySpec = (cert->_keySpec == KEYSPEC_KEYEXCHANGE) ? KEYSPEC_SIGNATURE : KEYSPEC_KEYEXCHANGE;
+
+ bool fOtherCertExist = (FindCertificate(_objects, ctrIdx, otherKeySpec) != 0);
+
+ bool fPrivKeysExist = false;
+ if(FindPrivateKey(_objects, ctrIdx, KEYSPEC_KEYEXCHANGE) || FindPrivateKey(_objects, ctrIdx, KEYSPEC_SIGNATURE))
+ fPrivKeysExist = true;
+
+ // If there are no longer any objects associated with this
+ // container, then free this CMap record
+ if(!fOtherCertExist && !fPrivKeysExist)
+ {
+ //Log::log("Deleting container ",ctrIdx);
+ DeleteCMapRecord(ctrIdx);
+ }
+ }
+ }
+ if(obj->_class == CKO_PRIVATE_KEY){
+
+ //Log::log("Deleting the private key.");
+
+ RSAPrivateKeyObject * privKey = static_cast<RSAPrivateKeyObject*>(obj);
+ CK_BYTE ctrIdx = privKey->_ctrIndex;
+
+ if(ctrIdx != 0xFF){
+
+
+ // Check if there exist certificate(s) or other
+ // private key (with different key spec) in the container
+ u1 otherKeySpec = (privKey->_keySpec == KEYSPEC_KEYEXCHANGE) ? KEYSPEC_SIGNATURE : KEYSPEC_KEYEXCHANGE;
+
+ bool fOtherKeyExist = (FindPrivateKey(_objects, ctrIdx, otherKeySpec) != 0);
+
+ bool fCertsExist = false;
+ if(FindCertificate(_objects, ctrIdx, KEYSPEC_KEYEXCHANGE) || FindCertificate(_objects, ctrIdx, KEYSPEC_SIGNATURE))
+ fCertsExist = true;
+
+ if(fOtherKeyExist)
+ {
+ // To not delete the other key, overwrite this one with dummy data
+ // TODO
+ // this->_mscm->CreateCAPIContainer(ctrIdx,.....);
+ RegisterContainerUpdate();
+ }
+ else
+ {
+ _cardCache->ClearContainer(ctrIdx); // Invalidate cache
+ _mscm->DeleteCAPIContainer(ctrIdx);
+ RegisterContainerUpdate();
+ }
+
+ // Check if the record in cmapfile shall be cleared,
+ // depending on if there are other keys in it.
+ // empty the corresponding record in cmapfile
+
+ if(fOtherKeyExist || fCertsExist)
+ {
+ //Log::log("Removing key from container ",ctrIdx);
+ RemoveKeyFromCMapRecord(ctrIdx, privKey->_keySpec);
+ }
+ else
+ {
+ //Log::log("Deleting container ",ctrIdx);
+ DeleteCMapRecord(ctrIdx);
+ }
+ }
+ }
+
+ // delete the file from card
+ if(!obj->_fileName.empty())
+ {
+ _cardCache->ClearFile(obj->_fileName);
+ try
+ {
+ _cardCache->ClearFileList("p11");
+ this->_mscm->DeleteFile(&obj->_fileName);
+ this->RegisterFileUpdate();
+ }
+ catch(FileNotFoundException &) {}
+ }
+
+ UnregisterStorageObject(obj);
+ delete obj;
+ }
+ TOKEN_CATCH(rv)
+ return rv;
+}
+
+CK_RV Token::GetAttributeValue(CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount)
+{
+ CK_RV rv = CKR_OK;
+ CK_RV arv = CKR_OK;
+ TOKEN_TRY
+ {
+
+ //Log::log("Get Attributes of token object..");
+
+ StorageObject * obj = GetObject(hObject);
+
+ if((this->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE)){
+ for(u4 i=0;i<ulCount;i++){
+ pTemplate[i].ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+ }
+ throw CkError(CKR_USER_NOT_LOGGED_IN);
+ }
+
+ for(u4 i=0;i<ulCount;i++){
+ rv = obj->GetAttribute(&pTemplate[i]);
+ if(rv != CKR_OK){
+ arv = rv;
+ }
+ }
+ }
+ TOKEN_CATCH(arv)
+ return arv;
+}
+
+
+CK_RV Token::SetAttributeValue( CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+{
+ CK_RV rv = CKR_OK;
+ CK_RV arv = CKR_OK;
+ TOKEN_TRY
+ {
+ StorageObject* pObj = GetObject( hObject );
+ // ??? pObj == NULL_PTR
+
+ // Check if we have a proper session
+ if( ( this->_roleLogged != CKU_USER ) && ( pObj->_private == CK_TRUE ) )
+ {
+ throw CkError( CKR_USER_NOT_LOGGED_IN );
+ }
+
+ if( pObj->_modifiable == CK_FALSE )
+ {
+ throw CkError(CKR_ATTRIBUTE_READ_ONLY);
+ }
+
+ for( u4 i = 0 ; i < ulCount ; i++ )
+ {
+ rv = pObj->SetAttribute( pTemplate[ i ], CK_FALSE );
+ if( rv != CKR_OK )
+ {
+ arv = rv;
+ }
+ }
+
+ if( arv == CKR_OK )
+ {
+ // If the object is not yet represented by a file under
+ // "p11" directory, this file must be created first.
+
+ bool fCreate = false;
+
+ // The object is represented by a P11 file if and only if
+ // the _uniqueId has been assigned a value.
+ if( pObj->_uniqueId == 0 )
+ {
+ fCreate = true;
+ if(!_initialized)
+ Initialize();
+
+ u1Array acls(3);
+ acls.GetBuffer( )[ 0 ] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE; // admin acl
+ acls.GetBuffer( )[ 1 ] = CARD_PERMISSION_READ | CARD_PERMISSION_WRITE; // usr acl
+
+ if(pObj->_private)
+ acls.GetBuffer()[2] = 0; // everyone acl
+ else
+ acls.GetBuffer()[2] = CARD_PERMISSION_READ; // everyone acl
+
+ string fileName("p11\\" + FindFreeFileName(pObj));
+ _cardCache->ClearFileList("p11");
+ _mscm->CreateFile(&fileName,&acls,0);
+ RegisterFileUpdate();
+ pObj->_fileName = fileName;
+ pObj->_uniqueId = Util::MakeUniqueId();
+ }
+
+ // marshall this object back to the card
+ vector<u1> to;
+ pObj->Serialize(&to);
+
+ u1Array objData((s4)to.size());
+
+ for(u4 i=0;i<to.size();i++){
+ objData.SetU1At(i,to.at(i));
+ }
+
+ //ManageGC();
+
+ try
+ {
+ this->_cardCache->WriteFile(pObj->_fileName,objData);
+ this->RegisterFileUpdate();
+ }
+ catch( CkError x )
+ {
+ arv = x.Error( );
+ Log::error( "Token::SetAttributeValue", "WriteFile failed" );
+ }
+
+ if( CKR_OK != arv )
+ {
+ /*try
+ {
+ _mscm->DeleteFile(&obj->_fileName);
+ }
+ catch( ... )
+ {
+ }*/
+
+ if(fCreate) // Restore state of object prior to update attempt.
+ {
+ pObj->_fileName.clear();
+ pObj->_uniqueId = 0;
+ }
+ }
+ }
+ }
+ TOKEN_CATCH(arv)
+ return arv;
+}
+
+
+CK_BYTE Token::GetAvailableContainerIndex(u1Array const & cmapContents)
+{
+ u4 contentLen = cmapContents.GetLength();
+
+ // cmap file does not contain anything
+ // so index is 0
+ if(contentLen == 0){
+ return 0;
+ }
+
+ s4 entries = contentLen / SIZE_CONTAINERMAPRECORD;
+
+ for(s4 i=0;i<entries;i++){
+ // lets find out which entry has all zeros
+ // which denotes available index
+
+ // as per minidriver specification
+ // if bit 0 of flags should be set for it to be
+ // a valid entry
+ if((CMapFileGetFlag(cmapContents, i) & 0x01) != 0x01){
+ return i;
+ }
+ }
+
+ // reaching here means that cmap file has entries
+ // which are all occupied, in that the available
+ // index would be entries
+ return entries;
+}
+
+CK_BYTE Token::GetContainerForCert(u1Array const & cmapContents, u8 checkValue, u1 * keySpec)
+{
+ // Look for existing matching private key
+ vector <PrivateKeyObject*> vPriv(FindPrivateKeys(_objects, checkValue));
+ for(size_t ipriv = 0; ipriv < vPriv.size(); ++ipriv)
+ {
+ // See it the corresponding container/keyspec is already occupied by a certificate.
+ // If it isn't, this is free for use.
+ if(!FindCertificate(_objects, vPriv[ipriv]->_ctrIndex, vPriv[ipriv]->_keySpec))
+ {
+ *keySpec = vPriv[ipriv]->_keySpec;
+ return vPriv[ipriv]->_ctrIndex;
+ }
+ }
+ // No matching private key, find new container
+
+ return GetAvailableContainerIndex(cmapContents);
+}
+
+CK_BYTE Token::GetContainerForPrivateKey(u1Array const & cmapContents, u8 checkValue, u1 * keySpec)
+{
+ // Look for existing matching certificate
+ vector <CertificateObject*> vCert(FindCertificates(_objects, checkValue));
+ for(size_t icert = 0; icert < vCert.size(); ++icert)
+ {
+ // See it the corresponding container/keyspec is already occupied by a key.
+ // If it isn't, this is free for use.
+ if(!FindPrivateKey(_objects, vCert[icert]->_ctrIndex, vCert[icert]->_keySpec))
+ {
+ *keySpec = vCert[icert]->_keySpec;
+ return vCert[icert]->_ctrIndex;
+ }
+ }
+ // No matching certificate, find new container
+
+ return GetAvailableContainerIndex(cmapContents);
+}
+
+auto_ptr<u1Array> Token::UpdateCMap(CK_BYTE ctrIdx, u1Array const & contents, string const & contName )
+{
+ u4 contentLen = contents.GetLength();
+ s4 entries = contentLen / SIZE_CONTAINERMAPRECORD;
+
+ u4 newCMapSize = SIZE_CONTAINERMAPRECORD * entries;
+
+ if(ctrIdx >= entries){
+ entries = ctrIdx + 1;
+ newCMapSize = entries * SIZE_CONTAINERMAPRECORD;
+ }
+
+ //autoarray<u1> updatedContents(new u1[newCMapSize]);
+
+ auto_ptr<u1Array> updatedContents(new u1Array(newCMapSize));
+
+ memset(updatedContents->GetBuffer(), 0, newCMapSize);
+ memcpy(updatedContents->GetBuffer(), contents.GetBuffer(), contentLen);
+
+ u1 flags = CMapFileGetFlag(*updatedContents, ctrIdx);
+ if(!(flags & 0x01))
+ {
+ // Container record is new, set container Name (UNICODE string)
+ CMapFileSetName(*updatedContents, ctrIdx, contName);
+ CMapFileSetFlag(*updatedContents, ctrIdx, flags | 0x01);
+ }
+
+ SetDefaultContainer(*updatedContents, 0xFF);
+
+ return updatedContents;
+}
+
+auto_ptr<u1Array> Token::UpdateCMap(CK_BYTE ctrIdx,u1Array const & contents,u4 keySize,u1 keySpec,CK_BBOOL isDefault, string const & contName)
+{
+ u4 contentLen = contents.GetLength();
+ s4 entries = contentLen / SIZE_CONTAINERMAPRECORD;
+
+ u4 newCMapSize = SIZE_CONTAINERMAPRECORD * entries;
+
+ if(ctrIdx >= entries){
+ entries = ctrIdx + 1;
+ newCMapSize = entries * SIZE_CONTAINERMAPRECORD;
+ }
+
+ auto_ptr<u1Array> updatedContents(new u1Array(newCMapSize));
+
+ memset(updatedContents->GetBuffer(), 0, newCMapSize);
+ memcpy(updatedContents->GetBuffer(), contents.GetBuffer(), contentLen);
+
+ u1 flags = CMapFileGetFlag(*updatedContents, ctrIdx);
+ if(!(flags & 0x01))
+ {
+ // Container record is new, set container Name (UNICODE string)
+ CMapFileSetName(*updatedContents, ctrIdx, contName);
+ CMapFileSetFlag(*updatedContents, ctrIdx, flags | 0x01);
+ }
+
+ // Default container
+ SetDefaultContainer(*updatedContents, isDefault ? ctrIdx : 0xFF);
+
+ // Container Key Size
+ if (keySpec == KEYSPEC_SIGNATURE){
+ CMapFileSetSignSize(*updatedContents, ctrIdx, keySize);
+ }else{
+ CMapFileSetExchSize(*updatedContents, ctrIdx, keySize);
+ }
+
+ return updatedContents;
+}
+
+vector <PrivateKeyObject*> Token::FindPrivateKeys(vector<StorageObject*> const & objects, u8 checkValue)
+{
+ // checkValue is derived from the modulus and is sufficiently
+ // long (8 bytes) to be a unique handle to the key pair / certificate
+ vector <PrivateKeyObject*> vPriv;
+
+ for(s4 i = 0; i < static_cast<s4>(objects.size()); i++){
+ if(objects[i] && objects[i]->_class == CKO_PRIVATE_KEY){
+ PrivateKeyObject * privObject = (PrivateKeyObject*)objects[i];
+ if(privObject->_checkValue == checkValue)
+ vPriv.push_back(privObject);
+ }
+ }
+ return vPriv;
+}
+
+PrivateKeyObject * Token::FindPrivateKey(vector<StorageObject*> const & objects, CK_BYTE ctrdIdx, u1 keySpec)
+{
+ vector <PrivateKeyObject*> vPriv;
+
+ for(s4 i = 0; i < static_cast<s4>(objects.size()); i++)
+ {
+ if(objects[i] && objects[i]->_class == CKO_PRIVATE_KEY)
+ {
+ PrivateKeyObject * privObject = (PrivateKeyObject*)objects[i];
+ if(privObject->_ctrIndex == ctrdIdx && privObject->_keySpec == keySpec)
+ return privObject; // Is supposed to be only one.
+ }
+ }
+ return 0;
+}
+
+vector <CertificateObject*> Token::FindCertificates(vector<StorageObject*> const & objects, u8 checkValue)
+{
+ // checkValue is derived from the modulus and is sufficiently
+ // long (8 bytes) to be a unique handle to the key pair / certificate
+ vector <CertificateObject*> vCert;
+
+ for(s4 i = 0; i < static_cast<s4>(objects.size()); i++)
+ {
+ if(objects[i] && objects[i]->_class == CKO_CERTIFICATE)
+ {
+ CertificateObject * certObject = (CertificateObject*)objects[i];
+ if(certObject->_checkValue == checkValue)
+ vCert.push_back(certObject);
+ }
+ }
+ return vCert;
+}
+
+CertificateObject * Token::FindCertificate(vector<StorageObject*> const & objects, CK_BYTE ctrdIdx, u1 keySpec)
+{
+ for(s4 i = 0; i < static_cast<s4>(objects.size()); i++)
+ {
+ if(objects[i] && objects[i]->_class == CKO_CERTIFICATE)
+ {
+ CertificateObject * certObject = (CertificateObject*)objects[i];
+ if(certObject->_ctrIndex == ctrdIdx && certObject->_keySpec == keySpec)
+ return certObject;
+ }
+ }
+ return 0;
+}
+
+CK_RV Token::GenerateKeyPair(auto_ptr<StorageObject> & stobjRsaPub, auto_ptr<StorageObject> & stobjRsaPriv,
+ CK_OBJECT_HANDLE_PTR phPubKey,CK_OBJECT_HANDLE_PTR phPrivKey)
+{
+
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+ RSAPublicKeyObject * rsaPubObject = static_cast<RSAPublicKeyObject*>(stobjRsaPub.get());
+ RSAPrivateKeyObject * rsaPrivObject = static_cast<RSAPrivateKeyObject*>(stobjRsaPriv.get());
+
+ if( (rsaPubObject->_modulusLen < RSA_KEY_MIN_LENGTH) ||
+ (rsaPubObject->_modulusLen > RSA_KEY_MAX_LENGTH) )
+ throw CkError(CKR_ATTRIBUTE_VALUE_INVALID);
+
+ //CheckAvailableSpace(); // HACK !!
+
+ //Log::log("Generating KeyPair on the smartcard...");
+
+ std::string nameCMapFile;
+
+ // TBD (Start a pc/sc transaction here)
+
+ // let's first read the container record file to
+ // see which container is available.
+ // No need to search for matching certificate,
+ // since this can not exist one yet!! ;)
+ nameCMapFile = "mscp\\cmapfile";
+ const u1Array & fileData = this->_cardCache->ReadFile(nameCMapFile);
+
+ CK_BYTE ctrIdx = this->GetAvailableContainerIndex(fileData);
+ if(ctrIdx == 0xFF)
+ throw CkError(CKR_DEVICE_MEMORY);
+
+ // create a capi container.
+ // KEYSPEC_KEYEXCHANGE by default.
+ this->_cardCache->ClearContainer(ctrIdx); // Invalidate cache
+ //this->_mscm->CreateCAPIContainer(ctrIdx,CK_FALSE,KEYSPEC_KEYEXCHANGE,rsaPubObject->_modulusLen,NULL_PTR);
+ int ntry = 0;
+ while( ntry < MAX_RETRY )
+ {
+ try
+ {
+ ManageGC( );
+ ntry++;
+ this->_mscm->CreateCAPIContainer(ctrIdx,CK_FALSE,KEYSPEC_KEYEXCHANGE,rsaPubObject->_modulusLen,NULL_PTR);
+ break;
+ }
+ catch( Marshaller::Exception & x )
+ {
+ CK_RV rv = CkError::CheckMarshallerException( x );
+ if( CKR_DEVICE_MEMORY == rv )
+ {
+ Log::error( "Token::GenerateKeyPair", "ForceGarbageCollector" );
+ _mscm->ForceGarbageCollector( );
+ if( ntry >= MAX_RETRY )
+ {
+ Log::error( "Token::GenerateKeyPair", "Throw Exception CKR_DEVICE_MEMORY" );
+ throw CkError( rv );
+ }
+ }
+ else
+ {
+ throw CkError( rv );
+ }
+ }
+ }
+
+ this->RegisterContainerUpdate();
+
+ rsaPubObject->_ctrIndex = ctrIdx;
+ rsaPubObject->_keySpec = KEYSPEC_KEYEXCHANGE;
+
+ rsaPrivObject->_ctrIndex = ctrIdx;
+ rsaPrivObject->_keySpec = KEYSPEC_KEYEXCHANGE;
+
+ // populate these objects with the key material
+ const CardCache::Container & cont = _cardCache->ReadContainer(ctrIdx);
+
+ rsaPubObject->_exponent = new u1Array();
+ *rsaPubObject->_exponent = cont.exchPublicExponent;
+ rsaPubObject->_modulus = new u1Array();
+ *rsaPubObject->_modulus = cont.exchModulus;
+ rsaPubObject->_local = CK_TRUE;
+
+
+ // Copy these modulus and exponent in the private key component also
+ rsaPrivObject->_publicExponent = new u1Array();
+ *rsaPrivObject->_publicExponent = cont.exchPublicExponent;
+
+ rsaPrivObject->_modulus = new u1Array();
+ *rsaPrivObject->_modulus = cont.exchModulus;
+ rsaPrivObject->_checkValue = Util::MakeCheckValue(cont.exchModulus.GetBuffer(),
+ cont.exchModulus.GetLength());
+ rsaPrivObject->_local = CK_TRUE;
+
+ string contName(CAttributedCertificate::DerivedUniqueName(cont.exchModulus.GetBuffer(),
+ cont.exchModulus.GetLength()));
+
+ // now its time to add the corresponding objects to
+ // the card (as files)
+
+ // The public key may be a session object, in that case, don't save it.
+
+ if( rsaPubObject->_tokenObject )
+ {
+ rv = this->AddObject( stobjRsaPub, phPubKey );
+ }
+
+ if( CKR_OK == rv )
+ {
+ rv = this->AddObject( stobjRsaPriv, phPrivKey );
+
+ if( CKR_OK == rv )
+ {
+ try
+ {
+ auto_ptr<u1Array> newCMap( UpdateCMap( ctrIdx, fileData, rsaPubObject->_modulusLen, KEYSPEC_KEYEXCHANGE, CK_TRUE, contName ) );
+ _cardCache->WriteFile( nameCMapFile, *newCMap );
+ RegisterFileUpdate( );
+ }
+ catch( CkError x )
+ {
+ rv = x.Error( );
+ Log::error( "Token::SetAttributeValue", "WriteFile failed" );
+ }
+
+ if( CKR_OK != rv )
+ {
+ if( rsaPubObject->_tokenObject )
+ {
+ DeleteObject( *phPubKey );
+ // ???
+ }
+ DeleteObject( *phPrivKey );
+
+ throw CkError( rv );
+ }
+ }
+ else if( rsaPubObject->_tokenObject )
+ {
+ DeleteObject( *phPubKey );
+ }
+ }
+ }
+ TOKEN_CATCH(rv)
+
+ return rv;
+}
+
+
+CK_RV Token::GetObject(CK_OBJECT_HANDLE hObject,StorageObject** object)
+{
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+ *object = GetObject(hObject);
+ }
+ TOKEN_CATCH(rv)
+ return rv;
+}
+
+CK_RV Token::Encrypt(StorageObject* pubObj,u1Array* dataToEncrypt,CK_ULONG mechanism,CK_BYTE_PTR pEncryptedData)
+{
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+ RSAPublicKeyObject* object = (RSAPublicKeyObject*)pubObj;
+
+ if(mechanism == CKM_RSA_PKCS){
+ // first do the length checks
+ if(dataToEncrypt->GetLength() > (object->_modulus->GetLength() - 11)){
+ throw CkError(CKR_DATA_LEN_RANGE);
+ }
+
+ rsaPublicKey_t key;
+
+ key.modulus = object->_modulus->GetBuffer() ;
+ key.modulusLength = object->_modulus->GetLength() * 8 ;
+ key.publicExponent = object->_exponent->GetBuffer();
+ key.publicExponentLength = object->_exponent->GetLength() * 8;
+
+ u4 outLength = object->_modulus->GetLength();
+
+ DWORD rv ;
+ DWORD size ;
+ DWORD pubSize ;
+ R_RSA_PUBLIC_KEY rsaKeyPublic ;
+
+ rsaKeyPublic.bits = key.modulusLength ;
+
+ size = (key.modulusLength + 7) / 8 ;
+ memcpy(rsaKeyPublic.modulus, key.modulus, size) ;
+
+ pubSize = (key.publicExponentLength + 7) / 8 ;
+ memset(rsaKeyPublic.exponent, 0, size) ;
+ memcpy(&rsaKeyPublic.exponent[size - pubSize], key.publicExponent, pubSize) ;
+
+ R_RANDOM_STRUCT & randomStruct = Util::RandomStruct();
+
+ rv = RSAPublicEncrypt(
+ pEncryptedData,
+ &outLength,
+ dataToEncrypt->GetBuffer(),
+ dataToEncrypt->GetLength(),
+ &rsaKeyPublic,
+ &randomStruct);
+
+ }else{
+
+ u4 modulusLen = object->_modulus->GetLength();
+
+ if(dataToEncrypt->GetLength() > (modulusLen)){
+ throw CkError(CKR_DATA_LEN_RANGE);
+ }
+
+ // pre-pad with zeros
+ u1Array* messageToEncrypt = new u1Array(modulusLen);
+ memset(messageToEncrypt->GetBuffer(),0,modulusLen);
+
+ s4 offsetMsgToEncrypt = modulusLen - dataToEncrypt->GetLength();
+
+ for(u4 i=0,j=offsetMsgToEncrypt;i<dataToEncrypt->GetLength();i++,j++){
+ messageToEncrypt->GetBuffer()[j] = dataToEncrypt->GetBuffer()[i];
+ }
+
+ // just block transform now
+ s4 size ;
+ s4 pubSize ;
+ R_RSA_PUBLIC_KEY rsaKeyPublic ;
+
+ //Build the RSA public key context
+ rsaKeyPublic.bits = object->_modulus->GetLength() * 8;
+
+ size = (rsaKeyPublic.bits + 7) / 8 ;
+ memcpy(rsaKeyPublic.modulus,object->_modulus->GetBuffer(),size) ;
+
+ pubSize = ((object->_exponent->GetLength() * 8) + 7) / 8 ;
+ memset(rsaKeyPublic.exponent, 0, size) ;
+ memcpy(&rsaKeyPublic.exponent[size - pubSize], object->_exponent->GetBuffer(), pubSize) ;
+
+ u4 outputLen = size;
+
+ rv = RSAPublicBlock(pEncryptedData,&outputLen,messageToEncrypt->GetBuffer(),size,&rsaKeyPublic);
+ }
+ }
+ TOKEN_CATCH(rv)
+ return rv;
+}
+
+CK_RV Token::Decrypt(StorageObject* privObj,u1Array* dataToDecrypt,CK_ULONG mechanism,CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
+{
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+ u1Array* data = NULL_PTR;
+
+ RSAPrivateKeyObject * rsaKey = static_cast<RSAPrivateKeyObject*>(privObj);
+
+ //data = this->_mscm->PrivateKeyDecrypt(rsaKey->_ctrIndex, rsaKey->_keySpec, dataToDecrypt);
+ int ntry = 0;
+ while( ntry < MAX_RETRY )
+ {
+ try
+ {
+ ManageGC( );
+ ntry++;
+ data = this->_mscm->PrivateKeyDecrypt( rsaKey->_ctrIndex, rsaKey->_keySpec, dataToDecrypt );
+ break;
+ }
+ catch( Marshaller::Exception & x )
+ {
+ CK_RV rv = CkError::CheckMarshallerException( x );
+ if( CKR_DEVICE_MEMORY == rv )
+ {
+ Log::error( "Token::Decrypt", "ForceGarbageCollector" );
+ _mscm->ForceGarbageCollector( );
+ if( ntry >= MAX_RETRY )
+ {
+ throw CkError( rv );
+ }
+ }
+ else
+ {
+ throw CkError( rv );
+ }
+ }
+ }
+
+
+
+
+
+ if(mechanism == CKM_RSA_PKCS){
+
+ u1* decryptedMessage = (u1*)data->GetBuffer();
+
+#define PKCS_EMEV15_PADDING_TAG 0x2
+
+ if ((decryptedMessage[0] != 0x00) || (decryptedMessage[1] != PKCS_EMEV15_PADDING_TAG))
+ {
+ // TBD: Lookup correct error message
+ // invalid message padding
+ rv = CKR_ENCRYPTED_DATA_INVALID;
+ }else{
+
+ // seach message padding separator
+ u4 mPos = 2 + 8;
+ while ((decryptedMessage[mPos] != 0x00) && (mPos < data->GetLength()))
+ {
+ mPos++;
+ }
+
+ // point on message itself.
+ mPos++;
+ u1Array* finalDecryptedMessage = new u1Array(data->GetLength() - mPos);
+ memcpy(finalDecryptedMessage->GetBuffer(),(u1*)&decryptedMessage[mPos],finalDecryptedMessage->GetLength());
+
+ delete data;
+
+ data = finalDecryptedMessage;
+ }
+ }
+ // else... CKM_RSA_X_509: Ignore padding
+
+ if(data){
+ if(*pulDataLen >= data->GetLength())
+ memcpy(pData,data->GetBuffer(),data->GetLength());
+ else
+ rv = CKR_BUFFER_TOO_SMALL;
+ *pulDataLen = data->GetLength();
+ delete data;
+ }
+ }
+ TOKEN_CATCH(rv)
+ return rv;
+}
+
+CK_RV Token::Verify(StorageObject* pubObj,u1Array* dataToVerify,CK_ULONG mechanism,u1Array* signature)
+{
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+ RSAPublicKeyObject* object = (RSAPublicKeyObject*)pubObj;
+
+ if(((mechanism == CKM_RSA_PKCS) && (dataToVerify->GetLength() > (object->_modulus->GetLength() - 11))) ||
+ ((mechanism == CKM_RSA_X_509) && (dataToVerify->GetLength() > object->_modulus->GetLength())))
+ {
+ throw CkError(CKR_DATA_LEN_RANGE);
+ }
+
+ if(signature->GetLength() != object->_modulus->GetLength()){
+ throw CkError(CKR_SIGNATURE_LEN_RANGE);
+ }
+
+ s4 size ;
+ s4 pubSize ;
+ R_RSA_PUBLIC_KEY rsaKeyPublic ;
+
+ //Build the RSA public key context
+ rsaKeyPublic.bits = object->_modulus->GetLength() * 8;
+
+ size = (rsaKeyPublic.bits + 7) / 8 ;
+ memcpy(rsaKeyPublic.modulus,object->_modulus->GetBuffer(),size) ;
+
+ pubSize = ((object->_exponent->GetLength() * 8) + 7) / 8 ;
+ memset(rsaKeyPublic.exponent, 0, size) ;
+ memcpy(&rsaKeyPublic.exponent[size - pubSize], object->_exponent->GetBuffer(), pubSize) ;
+
+ u4 messageToVerifyLen = size;
+ u1Array* messageToVerify = new u1Array(messageToVerifyLen);
+
+ RSAPublicBlock(messageToVerify->GetBuffer(),&messageToVerifyLen,signature->GetBuffer(),size,&rsaKeyPublic);
+
+ switch(mechanism){
+
+ case CKM_RSA_PKCS:
+ rv = VerifyRSAPKCS1v15(messageToVerify,dataToVerify,size);
+ break;
+
+ case CKM_RSA_X_509:
+ rv = VerifyRSAX509(messageToVerify,dataToVerify,size);
+ break;
+
+
+ case CKM_SHA1_RSA_PKCS:
+ rv = VerifyHash(messageToVerify,dataToVerify,size,CKM_SHA_1);
+ break;
+
+ case CKM_SHA256_RSA_PKCS:
+ rv = VerifyHash(messageToVerify,dataToVerify,size,CKM_SHA256);
+ break;
+
+ case CKM_MD5_RSA_PKCS:
+ rv = VerifyHash(messageToVerify,dataToVerify,size,CKM_MD5);
+ break;
+
+ default:
+ PKCS11_ASSERT(CK_FALSE);
+ rv = CKR_GENERAL_ERROR;
+ break;
+ }
+
+ delete messageToVerify;
+ }
+ TOKEN_CATCH(rv)
+ return rv;
+}
+
+CK_RV Token::VerifyHash(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen,CK_ULONG hashAlgo)
+{
+ u1 DER_SHA1_Encoding[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14};
+ u1 DER_SHA256_Encoding[] = {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
+ u1 DER_MD5_Encoding[] = {0x30,0x20,0x30,0x0C,0x06,0x08,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05,0x05,0x00,0x04,0x10};
+
+ s4 DER_Encoding_Len = 0;
+
+ switch(hashAlgo){
+ case CKM_SHA_1:
+ DER_Encoding_Len = sizeof(DER_SHA1_Encoding);
+ break;
+
+ case CKM_SHA256:
+ DER_Encoding_Len = sizeof(DER_SHA256_Encoding);
+ break;
+
+ case CKM_MD5:
+ DER_Encoding_Len = sizeof(DER_MD5_Encoding);
+ break;
+
+ }
+
+ u1* msg = messageToVerify->GetBuffer();
+ u1* hash = dataToVerify->GetBuffer();
+
+ // Check the decoded value against the expected data.
+ if ((msg[0] != 0x00) || (msg[1] != 0x01)){
+ return CKR_SIGNATURE_INVALID;
+ }
+
+ s4 posn = modulusLen - DER_Encoding_Len - dataToVerify->GetLength();
+
+ for(s4 i = 2; i < (posn - 1); i++)
+ {
+ if(msg[i] != 0xFF){
+ return CKR_SIGNATURE_INVALID;
+ }
+ }
+
+ if(msg[posn - 1] != 0x00){
+ return CKR_SIGNATURE_INVALID;
+ }
+
+ for (u4 i = 0; i < dataToVerify->GetLength(); i++){
+ if (msg[posn + i + DER_Encoding_Len] != hash[i]){
+ return CKR_SIGNATURE_INVALID;
+ }
+ }
+
+ return CKR_OK;
+}
+
+CK_RV Token::VerifyRSAX509(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen)
+{
+ // reach the first non-zero bytes in decrypted signature
+ // and data
+ u4 pos1=0;
+ u4 pos2=0;
+
+ for(;pos1<dataToVerify->GetLength();pos1++){
+ if(dataToVerify->GetBuffer()[pos1] != 0)
+ break;
+ }
+
+ for(;pos2<messageToVerify->GetLength();pos2++){
+ if(messageToVerify->GetBuffer()[pos2] != 0)
+ break;
+ }
+
+ if((dataToVerify->GetLength() - pos1) != (modulusLen - pos2)){
+ return CKR_SIGNATURE_INVALID;
+ }
+
+ for(u4 i=pos1,j=pos2;i<(modulusLen - pos2);i++,j++){
+ if(dataToVerify->GetBuffer()[i] != messageToVerify->GetBuffer()[j]){
+ return CKR_SIGNATURE_INVALID;
+ }
+ }
+
+ return CKR_OK;
+}
+
+CK_RV Token::VerifyRSAPKCS1v15(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen)
+{
+ // skip past the pkcs block formatting data
+ u4 pos = 2;
+ for(;pos<modulusLen;pos++)
+ {
+ if(messageToVerify->GetBuffer()[pos] == 0x00)
+ {
+ pos++;
+ break;
+ }
+ }
+
+ if(dataToVerify->GetLength() != (modulusLen - pos)){
+ return CKR_SIGNATURE_INVALID;
+ }
+
+ for(u4 i=0, j=pos;i< (modulusLen - pos); i++,j++){
+ if(dataToVerify->GetBuffer()[i] != messageToVerify->GetBuffer()[j]){
+ return CKR_SIGNATURE_INVALID;
+ }
+ }
+
+ return CKR_OK;
+}
+
+
+CK_RV Token::Sign(StorageObject* privObj,u1Array* dataToSign,CK_ULONG mechanism,CK_BYTE_PTR pSignature)
+{
+ CK_RV rv = CKR_OK;
+ TOKEN_TRY
+ {
+ u1Array* messageToSign = NULL_PTR;
+
+ // TODO: Should check if cast is safe
+ RSAPrivateKeyObject * rsaKey = static_cast<RSAPrivateKeyObject*>(privObj);
+ CK_ULONG modulusLen = rsaKey->_modulus->GetLength();
+
+ if(((mechanism == CKM_RSA_PKCS) && (dataToSign->GetLength() > modulusLen - 11)) ||
+ ((mechanism == CKM_RSA_X_509) && (dataToSign->GetLength() > modulusLen)))
+ {
+ throw CkError(CKR_DATA_LEN_RANGE);
+ }
+
+ switch(mechanism){
+
+ case CKM_RSA_PKCS:
+ messageToSign = PadRSAPKCS1v15(dataToSign,modulusLen);
+ break;
+
+ case CKM_RSA_X_509:
+ messageToSign = PadRSAX509(dataToSign,modulusLen);
+ break;
+
+ case CKM_SHA1_RSA_PKCS:
+ messageToSign = EncodeHashForSigning(dataToSign,modulusLen,CKM_SHA_1);
+ break;
+
+ case CKM_SHA256_RSA_PKCS:
+ messageToSign = EncodeHashForSigning(dataToSign,modulusLen,CKM_SHA256);
+ break;
+
+ case CKM_MD5_RSA_PKCS:
+ messageToSign = EncodeHashForSigning(dataToSign,modulusLen,CKM_MD5);
+ break;
+ }
+
+ u1Array* signatureData = NULL_PTR;
+
+ //signatureData = this->_mscm->PrivateKeyDecrypt(rsaKey->_ctrIndex, rsaKey->_keySpec, messageToSign);
+
+ int ntry = 0;
+ while( ntry < MAX_RETRY )
+ {
+ try
+ {
+ ManageGC( );
+ ntry++;
+ signatureData = this->_mscm->PrivateKeyDecrypt(rsaKey->_ctrIndex, rsaKey->_keySpec, messageToSign);
+ break;
+ }
+ catch( Marshaller::Exception & x )
+ {
+ CK_RV rv = CkError::CheckMarshallerException( x );
+ if( CKR_DEVICE_MEMORY == rv )
+ {
+ Log::error( "Token::Sign", "ForceGarbageCollector" );
+ _mscm->ForceGarbageCollector( );
+ if( ntry >= MAX_RETRY )
+ {
+ throw CkError( rv );
+ }
+ }
+ else
+ {
+ throw CkError( rv );
+ }
+ }
+ }
+
+ memcpy(pSignature,signatureData->GetBuffer(),signatureData->GetLength());
+
+ delete signatureData;
+ delete messageToSign;
+ }
+ TOKEN_CATCH(rv)
+ return rv;
+}
+
+// these methods should be moved to rsa library
+// once we have it
+u1Array* Token::PadRSAPKCS1v15(u1Array* dataToSign,CK_ULONG modulusLen)
+{
+ u1Array* messageToSign = new u1Array(modulusLen);
+ memset(messageToSign->GetBuffer(),0,modulusLen);
+
+ messageToSign->SetU1At(1,1);
+
+ s4 offsetMessageToSign = modulusLen - dataToSign->GetLength() - 3;
+
+ for(s4 i=0;i<offsetMessageToSign;i++){
+ messageToSign->SetU1At(2+i,0xFF);
+ }
+
+ offsetMessageToSign += 3;
+
+ memcpy((u1*)&messageToSign->GetBuffer()[offsetMessageToSign],dataToSign->GetBuffer(),dataToSign->GetLength());
+
+ return messageToSign;
+}
+
+u1Array* Token::PadRSAX509(u1Array* dataToSign,CK_ULONG modulusLen)
+{
+
+ u1Array* messageToSign = new u1Array(modulusLen);
+ memset(messageToSign->GetBuffer(),0,modulusLen);
+
+ s4 offsetMessageToSign = modulusLen - dataToSign->GetLength();
+
+ memcpy((u1*)&messageToSign->GetBuffer()[offsetMessageToSign],dataToSign->GetBuffer(),dataToSign->GetLength());
+
+ return messageToSign;
+}
+
+u1Array* Token::EncodeHashForSigning(u1Array* hashedData,CK_ULONG modulusLen,CK_ULONG hashAlgo)
+{
+ u1 DER_SHA1_Encoding[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14};
+ u1 DER_SHA256_Encoding[] = {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
+ u1 DER_MD5_Encoding[] = {0x30,0x20,0x30,0x0C,0x06,0x08,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05,0x05,0x00,0x04,0x10};
+
+ u1* DER_Encoding = NULL_PTR;
+ s4 DER_Encoding_Len = 0;
+
+ switch(hashAlgo){
+ case CKM_SHA_1:
+ DER_Encoding_Len = sizeof(DER_SHA1_Encoding);
+ DER_Encoding = new u1[DER_Encoding_Len]; //(u1*)malloc(DER_Encoding_Len);
+ memcpy(DER_Encoding,DER_SHA1_Encoding,DER_Encoding_Len);
+ break;
+
+ case CKM_SHA256:
+ DER_Encoding_Len = sizeof(DER_SHA256_Encoding);
+ DER_Encoding = new u1[DER_Encoding_Len]; //(u1*)malloc(DER_Encoding_Len);
+ memcpy(DER_Encoding,DER_SHA256_Encoding,DER_Encoding_Len);
+ break;
+
+ case CKM_MD5:
+ DER_Encoding_Len = sizeof(DER_MD5_Encoding);
+ DER_Encoding = new u1[DER_Encoding_Len]; //(u1*)malloc(DER_Encoding_Len);
+ memcpy(DER_Encoding,DER_MD5_Encoding,DER_Encoding_Len);
+ break;
+
+ }
+
+ u1Array* messageToSign = new u1Array(modulusLen);
+ memset(messageToSign->GetBuffer(),0,modulusLen);
+
+ messageToSign->SetU1At(1,1);
+
+ // caluclate pos
+ s4 pos = modulusLen - DER_Encoding_Len - hashedData->GetLength();
+
+ for(s4 i=2;i<(pos - 1);i++){
+ messageToSign->SetU1At(i,0xFF);
+ }
+
+ memcpy((u1*)&messageToSign->GetBuffer()[pos],DER_Encoding,DER_Encoding_Len);
+ memcpy((u1*)&messageToSign->GetBuffer()[pos+DER_Encoding_Len],hashedData->GetBuffer(),hashedData->GetLength());
+
+ delete DER_Encoding;
+
+ return messageToSign;
+}
+
+bool Token::PerformDeferredDelete()
+{
+ bool fSync = true;
+ PKCS11_ASSERT(this->_roleLogged != CKU_NONE);
+
+ if(_toDelete.empty())
+ return fSync;
+
+ _cardCache->ClearFileList("mscp");
+ _cardCache->ClearFileList("p11");
+
+ // Delete files that are pending to be deleted
+ vector<string>::iterator ifile = _toDelete.begin();
+ while(ifile != _toDelete.end())
+ {
+ try
+ {
+ _cardCache->ClearFile(*ifile);
+ _mscm->DeleteFile(&(*ifile));
+ RegisterFileUpdate();
+ ifile = _toDelete.erase(ifile);
+ }
+ catch(FileNotFoundException &)
+ {
+ ifile = _toDelete.erase(ifile);
+ }
+ catch(...)
+ {
+ // Failed to delete, keep it in the list.
+ fSync = false;
+ ++ifile;
+ }
+ }
+ return fSync;
+}
+
+s4 Token::RegisterStorageObject(StorageObject * object)
+{
+ // add this in the token object list
+
+ for(size_t k = 0; k<_objects.size(); k++)
+ {
+ PKCS11_ASSERT(_objects[k] != object);
+ }
+
+
+ size_t t = 0;
+ while(t < _objects.size())
+ {
+ if(!_objects[t])
+ {
+ _objects[t] = object;
+ return static_cast<s4>(t+1);
+ }
+ ++t;
+ }
+ // Expand list
+ _objects.push_back(object);
+ return static_cast<s4>(_objects.size());
+}
+
+void Token::UnregisterStorageObject(StorageObject * object)
+{
+ size_t t = 0;
+ while(t<_objects.size())
+ {
+ if(_objects[t] == object)
+ {
+ _objects[t] = 0;
+ break;
+ }
+ ++t;
+ }
+}
+
+auto_ptr<u1Array> Token::ReadCertificateFile(string const & path)
+{
+ // Read certificate file
+
+ const u1Array & compressedCert = _cardCache->ReadFile(path);
+
+ // Decompress
+ unsigned long origLen = compressedCert.ReadU1At(3) * 256 + compressedCert.ReadU1At(2);
+ autoarray<u1> origData(new u1[origLen]);
+ auto_ptr<u1Array> value(new u1Array(origLen));
+ uncompress(value->GetBuffer(), &origLen, compressedCert.GetBuffer()+4, compressedCert.GetLength() - 4);
+ return value;
+
+}
+
+void Token::RegisterPinUpdate()
+{
+ _fPinChanged = true;
+}
+
+void Token::RegisterContainerUpdate()
+{
+ _fContainerChanged = true;
+}
+
+void Token::RegisterFileUpdate()
+{
+ _fFileChanged = true;
+}
+
+//void Token::CheckAvailableSpace()
+//{
+// return;
+//
+// //u4 highWaterMark = 20000;
+// //auto_ptr<u4Array> freeSpace(_mscm->QueryFreeSpace());
+//
+// //u4 availSpace = freeSpace->ReadU4At(2);
+// //if(availSpace < highWaterMark)
+// // throw CkError(CKR_DEVICE_MEMORY);
+//
+//}
+
+
+/*
+*/
+bool Token::isAuthenticated( void )
+{
+ bool bRet = false;
+ try
+ {
+ bRet = (bool)(_mscm->IsAuthenticated( CARD_ROLE_USER ));
+ }
+ catch( ... )
+ {
+ Log::error( "Token::isAuthenticated", "isAuthenticated" );
+ bRet = false;
+ }
+ return bRet;
+}
+
+
+/*
+*/
+bool Token::isSSO( void )
+{
+ bool bRet = false;
+ u1Array* ba = 0;
+ try
+ {
+ ba = _mscm->GetCardProperty( 0x80, 0 );
+ }
+ catch( ... )
+ {
+ //Log::error( "Token::isSSO", "GetCardProperty" );
+ Log::log( "Token::isSSO - GetCardProperty failed !" );
+ bRet = false;
+ }
+ if( 0 != ba )
+ {
+ bRet = (bool)(ba->GetBuffer( )[9]);
+
+ /*
+ log2( "Max Attempts <%d>", ba->GetBuffer( )[0] );
+ log2( "Min Length <%d>", ba->GetBuffer( )[1] );
+ log2( "Max Length <%d>", ba->GetBuffer( )[2] );
+ log2( "Char Set <0x%02X>", ba->GetBuffer( )[3] );
+ log2( "Complexity rule 1 <%d>", ba->GetBuffer( )[4] );
+ log2( "Complexity rule 2 <%d>", ba->GetBuffer( )[5] );
+ log2( "Adjacent allowed <%s>", ba->GetBuffer( )[6] ? "Yes" : "No" );
+ log2( "History <%d>", ba->GetBuffer( )[7] );
+ log2( "Unblock allowed <%s>", ba->GetBuffer( )[8] ? "Yes" : "No" );
+ log2( "SSO allowed <%s>", ba->GetBuffer( )[9] ? "Yes" : "No" );
+
+ std::string s6 = ba->GetBuffer( )[6] ? "YES" : "NO";
+ std::string s8 = ba->GetBuffer( )[8] ? "YES" : "NO";
+ std::string s9 = ba->GetBuffer( )[9] ? "YES" : "NO";
+ std::string s3 = "";
+ translateToHex( ba->GetBuffer( )[3], s3 );
+
+ if( ( ba->GetBuffer( )[0] != m_iMaxAttemps )
+ || ( ba->GetBuffer( )[1] != m_iMinLength )
+ || ( ba->GetBuffer( )[2] != m_iMaxLength )
+ || ( s3 != m_stCharSet )
+ || ( ba->GetBuffer( )[4] != m_iComplexityRule1 )
+ || ( ba->GetBuffer( )[5] != m_iComplexityRule2 )
+ || ( s6 != m_stAdjacentAllowed )
+ || ( ba->GetBuffer( )[7] != m_iHistory )
+ || ( s8 != m_stAllowUnblock )
+ || ( s9 != m_stAllowSSO ) )
+ {
+ bRet = false;
+ error( "check pin policy" );
+ }
+ */
+
+ delete ba;
+ }
+ return bRet;
+}
+
+
+/*
+*/
+void Token::CardBeginTransaction( )
+{
+ //Log::begin( "Token::CardBeginTransaction" );
+
+ //Log::log( "Token::CardBeginTransaction - _mscm->GetPcscCardHandle..." );
+ SCARDHANDLE hCard = _mscm->GetPcscCardHandle( );
+ //Log::log( "Token::CardBeginTransaction - hCard <%#02x>", hCard );
+
+ if( !hCard )
+ {
+ Log::error( "Token::CardBeginTransaction", "CKR_FUNCTION_FAILED" );
+ throw CkError( CKR_FUNCTION_FAILED );
+ }
+
+ LONG hResult = SCardBeginTransaction( hCard );
+ while( SCARD_W_RESET_CARD == hResult )
+ {
+ _roleLogged = CKU_NONE;
+ DWORD dwActiveProtocol;
+
+ //Log::log( "Token::CardBeginTransaction - SCardReconnect..." );
+ LONG hr = SCardReconnect( hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD, &dwActiveProtocol );
+ //Log::log( "Token::CardBeginTransaction - hr <%#02x>", hr );
+ if( SCARD_S_SUCCESS == hr )
+ {
+ //Log::log( "Token::CardBeginTransaction - SCardBeginTransaction..." );
+ hResult = SCardBeginTransaction( hCard );
+ //Log::log( "Token::CardBeginTransaction - hResult <%#02x>", hResult );
+ }
+ else
+ {
+ Log::log( "Token::CardBeginTransaction - ## ERROR ## PcscError <%#02x>", hr );
+ Log::error( "Token::CardBeginTransaction", "PcscError" );
+ throw PcscError( hr );
+ }
+ };
+
+
+ if( hResult != SCARD_S_SUCCESS )
+ {
+ Log::log( "Token::CardBeginTransaction - ## ERROR ## hResult <%#02x>", hResult );
+ Log::error( "Token::CardBeginTransaction", "PcscError" );
+ throw PcscError( hResult );
+ }
+
+ //Log::end( "Token::CardBeginTransaction" );
+}
+
+
+void Token::CardEndTransaction()
+{
+ //Log::begin( "Token::CardEndTransaction" );
+
+ SCARDHANDLE hCard = _mscm->GetPcscCardHandle( );//_mscm->GetSCardHandle();
+ if(!hCard)
+ throw CkError(CKR_FUNCTION_FAILED);
+
+ LONG hResult = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
+#ifdef __APPLE__
+ while((hResult == SCARD_W_RESET_CARD) || (hResult == SCARD_W_REMOVED_CARD))
+#else
+ while(hResult == SCARD_W_RESET_CARD)
+#endif
+ {
+ _roleLogged = CKU_NONE;
+ DWORD dwActiveProtocol;
+ LONG hr = SCardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1,SCARD_LEAVE_CARD,&dwActiveProtocol);
+ if(hr == SCARD_S_SUCCESS)
+ hResult = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
+ else
+ throw PcscError(hr);
+ }
+ if(hResult != SCARD_S_SUCCESS && hResult != SCARD_E_NOT_TRANSACTED) // SCARD_E_NOT_TRANSACTED shouldn't occur, still ignore it.
+ throw PcscError(hResult);
+
+ //Log::end( "Token::CardEndTransaction" );
+}
+
+StorageObject * Token::GetObject(CK_OBJECT_HANDLE hObject)
+{
+ CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+
+ if((idx < 1) || (idx > static_cast<CK_LONG>(_objects.size())) || !_objects[idx-1])
+ throw CkError(CKR_OBJECT_HANDLE_INVALID);
+
+ return _objects[idx-1];
+}
+
+
+void CMapFileClear(u1Array & file, u1 index)
+{
+ u4 idx = index * SIZE_CONTAINERMAPRECORD;
+ memset(file.GetBuffer()+idx, 0, SIZE_CONTAINERMAPRECORD);
+}
+
+void CMapFileSetName(u1Array & file, u1 index, string const & name)
+{
+ u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_GUID_INFO;
+ memset(file.GetBuffer()+idx, 0, 80);
+ const size_t length = name.size() > 39 ? 39 : name.size();
+ for(size_t i = 0; i<length; i++)
+ file.SetU1At(idx + 2*i, name[i]); // Convert to wchar, little endian.
+}
+
+u1 CMapFileGetFlag(u1Array const & file, u1 index)
+{
+ u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_FLAGS;
+ return file.ReadU1At(idx);
+}
+
+void CMapFileSetFlag(u1Array & file, u1 index, u1 flag)
+{
+ u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_FLAGS;
+ file.SetU1At(idx, flag);
+}
+
+u2 CMapFileGetSignSize(u1Array const & file, u1 index)
+{
+ u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_SIG_KEY_SIZE;
+ return LittleEndianToInt<u2>(file.GetBuffer(), idx);
+}
+
+void CMapFileSetSignSize(u1Array & file, u1 index, u2 size)
+{
+ u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_SIG_KEY_SIZE;
+ IntToLittleEndian<u2>(size, file.GetBuffer(), idx);
+}
+
+u2 CMapFileGetExchSize(u1Array const & file, u1 index)
+{
+ u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_EXC_KEY_SIZE;
+ return LittleEndianToInt<u2>(file.GetBuffer(), idx);
+}
+
+void CMapFileSetExchSize(u1Array & file, u1 index, u2 size)
+{
+ u4 idx = index * SIZE_CONTAINERMAPRECORD + IDX_EXC_KEY_SIZE;
+ IntToLittleEndian<u2>(size, file.GetBuffer(), idx);
+}
+
+
+/*
+*/
+bool Token::isPinPadSupported( void )
+{
+ // Get Reader Features
+ BYTE outBuffer[256];
+ memset( outBuffer, 0, sizeof( outBuffer ) );
+ DWORD dwLen = 0;
+ LONG lRet = SCardControl( _mscm->GetPcscCardHandle( ), CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, outBuffer, sizeof(outBuffer), &dwLen );
+
+ // Search IOCTL of Verify PIN feature
+ int i = 0;
+ bool isVerifyPin = false;
+ m_dwIoctlVerifyPIN = 0;
+ if ( ( SCARD_S_SUCCESS == lRet ) && ( dwLen > 0 ) )
+ {
+ while( ( i + 6 ) <= (int)dwLen )
+ {
+ // Search Verify PIN feature Tag
+ if ( (outBuffer[i] == FEATURE_VERIFY_PIN_DIRECT)
+ &&(outBuffer[i+1] == 4)
+ )
+ {
+ m_dwIoctlVerifyPIN += (outBuffer[i+2] << 24);
+ m_dwIoctlVerifyPIN += (outBuffer[i+3] << 16);
+ m_dwIoctlVerifyPIN += (outBuffer[i+4] << 8);
+ m_dwIoctlVerifyPIN += outBuffer[i+5];
+
+ isVerifyPin = true;
+
+ break;
+ }
+ else
+ {
+ i += (outBuffer[i+1] + 2);
+ }
+ }
+ }
+
+ return (isVerifyPin);
+}
+
+
+/*
+*/
+bool Token::isPinExternalSupported( void )
+{
+ bool bIsPinExternalSupported = false;
+
+ u1Array* pinProperties = new u1Array( 0 );
+ try
+ {
+ pinProperties = _mscm->GetCardProperty( CARD_PROPERTY_PIN_INFO, CARD_ROLE_USER );
+
+ if( CARD_PROPERTY_EXTERNAL_PIN == pinProperties->GetBuffer( )[ 0 ] )
+ {
+ bIsPinExternalSupported = true;
+ }
+ }
+ catch( ... )
+ {
+ }
+
+ delete pinProperties;
+
+ return bIsPinExternalSupported;
+}
+
+/*
+*/
+CK_RV Token::verifyPinWithPinPad( void )
+{
+ DWORD PinId = CARD_ROLE_USER;
+ LONG lRet;
+ BYTE offset;
+ DWORD dwSendLen;
+ PIN_VERIFY_STRUCTURE pin_verify;
+ BYTE inBuffer[256];
+ DWORD dwInLen = 0;
+ BYTE outBuffer[256];
+ DWORD dwOutLen = 0;
+
+ pin_verify.bTimerOut = 30; /* Time out between key stroke = max(bTimerOut, bTimerOut2). Must be between 15 and 40 sec.*/
+ pin_verify.bTimerOut2 = 00;
+
+ pin_verify.bmFormatString = 0x82; /* Padding V2=0x82 */
+
+ pin_verify.bmPINBlockString = 0x06;
+ pin_verify.bmPINLengthFormat = 0x00;
+ pin_verify.bPINMaxExtraDigit1 = 0x08; /* Max */
+ pin_verify.bPINMaxExtraDigit2 = 0x04; /* Min */
+ pin_verify.bEntryValidationCondition = 0x02; /* validation key pressed */
+ pin_verify.bNumberMessage = 0x01;
+ pin_verify.wLangId = 0x0904;
+ pin_verify.bMsgIndex = 0x00;
+ pin_verify.bTeoPrologue[0] = 0x00;
+ pin_verify.bTeoPrologue[1] = 0x00;
+ pin_verify.bTeoPrologue[2] = 0x00; /* pin_verify.ulDataLength = 0x00; we don't know the size yet */
+
+ offset = 0;
+ pin_verify.abData[offset++] = 0x00; /* CLA */ /*********************************/
+ pin_verify.abData[offset++] = 0x20; /* INS: VERIFY */
+ pin_verify.abData[offset++] = 0x00; /* P1: always 0 */
+ pin_verify.abData[offset++] = (BYTE)PinId; /* P2: PIN reference */
+ pin_verify.abData[offset++] = 0x08; /* Lc: 8 data bytes */
+
+ pin_verify.abData[offset++] = 0xFF; /* 'FF' */
+ pin_verify.abData[offset++] = 0xFF; /* 'FF' */
+ pin_verify.abData[offset++] = 0xFF; /* 'FF' */
+ pin_verify.abData[offset++] = 0xFF; /* 'FF' */
+ pin_verify.abData[offset++] = 0xFF; /* 'FF' */
+ pin_verify.abData[offset++] = 0xFF; /* 'FF' */
+ pin_verify.abData[offset++] = 0xFF; /* 'FF' */
+ pin_verify.abData[offset++] = 0xFF; /* 'FF' */
+
+ pin_verify.ulDataLength = offset; /* APDU size */
+ dwSendLen = sizeof(PIN_VERIFY_STRUCTURE);
+
+ // Select MSCM Application
+ inBuffer[0] = 0x00; //CLA
+ inBuffer[1] = 0xA4; //INS
+ inBuffer[2] = 0x04; //P1
+ inBuffer[3] = 0x00; //P2
+ inBuffer[4] = 0x04; //Li
+
+ memcpy(&inBuffer[5], "MSCM", 4);
+
+ dwInLen = 5 + inBuffer[4];
+
+ dwOutLen = sizeof(outBuffer);
+ memset(outBuffer, 0x00, sizeof(outBuffer));
+
+ lRet = SCardTransmit(_mscm->GetPcscCardHandle(),
+ SCARD_PCI_T0,
+ inBuffer,
+ dwInLen,
+ NULL,
+ outBuffer,
+ &dwOutLen
+ );
+
+ // Send Verify command to the reader
+ dwOutLen = 0;
+ memset(outBuffer, 0x00, sizeof(outBuffer));
+
+ lRet = SCardControl(_mscm->GetPcscCardHandle(),
+ m_dwIoctlVerifyPIN,
+ (BYTE *)&pin_verify,
+ dwSendLen,
+ outBuffer,
+ sizeof(outBuffer),
+ &dwOutLen
+ );
+
+ Log::log( "Token::verifyPinWithPinPad - sw <%#02x %#02x>", outBuffer[ 0 ], outBuffer[ 1 ] );
+
+ CK_RV rv = CKR_FUNCTION_FAILED;
+ if( ( 0x90 == outBuffer[ 0 ] ) && ( 0x00 == outBuffer[ 1 ] ) )
+ {
+ //this->_tokenInfo.flags &= ~CKF_USER_PIN_LOCKED;
+ //this->_tokenInfo.flags &= ~CKF_USER_PIN_FINAL_TRY;
+ //this->_tokenInfo.flags &= ~CKF_USER_PIN_COUNT_LOW;
+ //this->_roleLogged = CKU_USER;
+ rv = CKR_OK;
+ }
+ else if( ( 0x63 == outBuffer[ 0 ] ) && ( 0x00 == outBuffer[ 1 ] ) )
+ {
+ rv = CKR_PIN_INCORRECT;
+ }
+ // operation was cancelled by the \x91Cancel\x92 button
+ else if( ( 0x64 == outBuffer[ 0 ] ) && ( 0x01 == outBuffer[ 1 ] ) )
+ {
+ //return SCARD_W_CANCELLED_BY_USER;
+ rv = CKR_FUNCTION_CANCELED;
+ }
+ // operation timed out
+ else if( ( 0x64 == outBuffer[ 0 ] ) && ( 0x00 == outBuffer[ 1 ] ) )
+ {
+ //return SCARD_E_TIMEOUT;
+ rv = CKR_FUNCTION_CANCELED;
+ }
+ // operation timed out
+ else if( ( 0x64 == outBuffer[ 0 ] ) && ( 0x03 == outBuffer[ 1 ] ) )
+ {
+ //return SCARD_E_TIMEOUT;
+ rv = CKR_PIN_INCORRECT;
+ }
+
+ Log::log( "Token::verifyPinWithPinPad - rv <%#02x>", rv );
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Token::verifyPinWithBio( void /*Marshaller::u1Array *pin*/ )
+{
+ Log::log( "Token::verifyPinWithBio - <BEGIN>" );
+
+ CK_RV rv = CKR_GENERAL_ERROR;
+
+#ifdef WIN32
+ // Get the current OS version
+ OSVERSIONINFO osvi;
+ memset( &osvi, 0, sizeof( OSVERSIONINFO ) );
+ osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
+ GetVersionEx(&osvi);
+ // Check if the Os is W7 or W2K8R2
+ if( ( 6 == osvi.dwMajorVersion ) && ( osvi.dwMinorVersion >= 1 ) )
+ {
+ Log::log( "Token::verifyPinWithBio - Os is W7 or W2K8R2" );
+
+ CardEndTransaction( );
+
+ // The OS is W7 or W2K8R2
+ HMODULE hDll = NULL;
+ LRESULT lRes = GSC_OK;
+ LRESULT (WINAPI *ptr_SetUITitles) (WCHAR*, WCHAR*);
+ LRESULT (WINAPI *ptr_AuthenticateUserCard) ();
+
+ // Load DLL
+ hDll = LoadLibraryA("GemSelCert.dll");
+ Log::log( "Token::verifyPinWithBio - load lib" );
+
+ if( 0 != hDll )
+ {
+ // Set UI Titles
+ ptr_SetUITitles = (LRESULT (WINAPI *) (WCHAR*, WCHAR*))GetProcAddress(hDll,"SetUITitles");
+ if( NULL != ptr_SetUITitles )
+ {
+ ptr_SetUITitles(L"Smartcard Security", L"User authentication");
+ Log::log( "Token::verifyPinWithBio - ptr_SetUITitles" );
+
+ // Authenticate Card User
+ ptr_AuthenticateUserCard = (LRESULT (WINAPI *)())GetProcAddress(hDll,"AuthenticateUserCard");
+ if( NULL != ptr_AuthenticateUserCard )
+ {
+ lRes = ptr_AuthenticateUserCard();
+ Log::log( "Token::verifyPinWithBio - ptr_AuthenticateUserCard" );
+
+ switch(lRes)
+ {
+ case GSC_OK:
+ rv = CKR_OK;
+ Log::log( "Token::verifyPinWithBio - CKR_OK" );
+ break;
+
+ case GSC_CANCEL:
+ rv = CKR_FUNCTION_CANCELED;
+ Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_CANCELED" );
+ break;
+
+ case GSC_NO_CERT:
+ rv = CKR_KEY_NEEDED;
+ Log::log( "Token::verifyPinWithBio - CKR_KEY_NEEDED" );
+ break;
+
+ case GSC_NO_CARD:
+ rv = CKR_TOKEN_NOT_RECOGNIZED;
+ Log::log( "Token::verifyPinWithBio - CKR_TOKEN_NOT_RECOGNIZED" );
+ break;
+
+ case GSC_WRONG_PIN:
+ rv = CKR_PIN_INCORRECT;
+ Log::log( "Token::verifyPinWithBio - CKR_PIN_INCORRECT" );
+ break;
+
+ case GSC_READ_CARD:
+ rv = CKR_FUNCTION_FAILED;
+ Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_FAILED" );
+ break;
+
+ case GSC_WRITE_CARD:
+ rv = CKR_FUNCTION_FAILED;
+ Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_FAILED" );
+ break;
+
+ default:
+ Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_FAILED" );
+ rv = CKR_FUNCTION_FAILED;
+ break;
+ }
+ }
+ }
+
+ // Release DLL
+ FreeLibrary(hDll);
+ Log::log( "Token::verifyPinWithBio - FreeLibrary" );
+ }
+
+ CardBeginTransaction( );
+ }
+ // The OS is Vista or XP
+ else
+ {
+ Log::log( "Token::verifyPinWithBio - Os is Vista or XP" );
+
+ CBioMan* pBioMan = NULL;
+ DWORD dwRes = BIO_ERR_NOT_SUPPORTED;
+
+ // Init BioMan helper
+ pBioMan = new CBioMan( );
+ Log::log( "Token::verifyPinWithBio - new" );
+ pBioMan->Connect( this->_mscm );
+ Log::log( "Token::verifyPinWithBio - connect" );
+
+ // Biometrics Verification
+ dwRes = pBioMan->VerifyBio( );
+ Log::log( "Token::verifyPinWithBio - verify bio" );
+
+ delete pBioMan;
+ Log::log( "Token::verifyPinWithBio - delete" );
+
+ // Error ?
+ switch( dwRes )
+ {
+ case BIO_ERR_SUCCESS:
+ Log::log( "Token::verifyPinWithBio - CKR_OK" );
+ rv = CKR_OK;
+ break;
+
+ case BIO_ERR_NO_CARD:
+ Log::log( "Token::verifyPinWithBio - CKR_TOKEN_NOT_PRESENT" );
+ rv = CKR_TOKEN_NOT_PRESENT;
+ break;
+
+ case BIO_ERR_NOT_SUPPORTED:
+ case BIO_ERR_NO_FINGER:
+ Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_NOT_SUPPORTED" );
+ //this->_mscm->VerifyPin( CARD_ROLE_USER, pin );
+ rv = CKR_FUNCTION_NOT_SUPPORTED; //CKR_OK;
+ break;
+
+ case BIO_ERR_BIO_NOT_CHECKED:
+ case BIO_ERR_PIN_NOT_CHECKED:
+ Log::log( "Token::verifyPinWithBio - CKR_PIN_INCORRECT" );
+ rv = CKR_PIN_INCORRECT;
+ break;
+
+ case BIO_ERR_BIO_LAST:
+ case BIO_ERR_PIN_LAST:
+ Log::log( "Token::verifyPinWithBio - CKR_PIN_INCORRECT" );
+ rv = CKR_PIN_INCORRECT;
+ break;
+
+ case BIO_ERR_BLOCKED:
+ Log::log( "Token::verifyPinWithBio - CKR_PIN_INCORRECT" );
+ rv = CKR_PIN_INCORRECT;
+ break;
+
+ case BIO_ERR_ABORT:
+ Log::log( "Token::verifyPinWithBio - CKR_FUNCTION_FAILED" );
+ rv = CKR_FUNCTION_FAILED;
+ break;
+
+ default:
+ Log::log( "Token::verifyPinWithBio - CKR_GENERAL_ERROR" );
+ rv = CKR_GENERAL_ERROR;
+ break;
+ }
+ }
+#endif
+
+ Log::log( "Token::verifyPinWithBio - <END>" );
+
+ return rv;
+}
+
+
+/*
+*/
+void Token::getCardConfiguration( BYTE& a_bMode, BYTE &a_bTypePIN )
+{
+ a_bMode = UVM_PIN_ONLY;
+ a_bTypePIN = PIN_TYPE_REGULAR;
+
+ u1Array* ba = new u1Array( 0 );
+
+ try
+ {
+ ba = _mscm->GetCardProperty( CARD_PROPERTY_PIN_INFO_EX, CARD_ROLE_USER );
+
+ DWORD dwFlagsEx = (DWORD)(
+ ba->GetBuffer( )[ 12 ] +
+ ( ( ba->GetBuffer( )[ 13 ] ) << 8 ) +
+ ( ( ba->GetBuffer( )[ 14 ] ) << 16 ) +
+ ( ( ba->GetBuffer( )[ 15 ] ) << 24 )
+ );
+ Log::log( "Token::getCardMode - dwFlagsEx <%#08x>", dwFlagsEx );
+
+ WORD wActiveMode = (WORD)( ba->GetBuffer( )[ 12 ] + ( ( ba->GetBuffer( )[ 13 ] ) << 8 ) );
+ Log::log( "Token::getCardMode - Active mode <%ld>", wActiveMode );
+
+ a_bMode = (BYTE)wActiveMode;
+
+ a_bTypePIN = (BYTE)ba->GetBuffer( )[ 0 ];
+ }
+ catch( ... )
+ {
+ Log::log( "Token::getCardMode - PIN_INFO_EX not supported - Default values used" );
+ a_bMode = UVM_PIN_ONLY;
+ a_bTypePIN = PIN_TYPE_REGULAR;
+ }
+
+ delete ba;
+}
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sctoken.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,251 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_token_h
+#define _include_token_h
+
+#include <memory>
+#include <string>
+#include <list>
+#include <map>
+#include "cardmoduleservice.h"
+#include "rsapublickeyobject.h"
+#include "rsaprivatekeyobject.h"
+#include "x509pubkeycertobject.h"
+#include "cr_rsa.h"
+
+// This class represents the data in the card/token
+
+#define FILE_TYPE_RAW_CERT 0
+#define FILE_TYPE_DATA 1
+#define FILE_TYPE_CERT 2
+#define FILE_TYPE_SECRETKEY 3
+#define FILE_TYPE_PUBLICKEY 4
+#define FILE_TYPE_PRIVATEKEY 5
+
+#define CARD_ROLE_EVERYONE 0x00
+#define CARD_ROLE_USER 0x01
+#define CARD_ROLE_ADMIN 0x02
+
+#define CARD_PERMISSION_READ 0x04
+#define CARD_PERMISSION_WRITE 0x02
+#define CARD_PERMISSION_EXECUTE 0x01
+
+#define KEYSPEC_KEYEXCHANGE 0x01
+#define KEYSPEC_SIGNATURE 0x02
+
+#define KEY_TAG_UNKNOWN 0x00
+#define KEY_TAG_EXPONENT 0x01
+#define KEY_TAG_MODULUS 0x02
+#define KEY_TAG_KEYSPEC 0x03
+#define KEY_TAG_MINBITLEN 0x04
+#define KEY_TAG_MAXBITLEN 0x05
+#define KEY_TAG_DEFAULTBITLEN 0x06
+#define KEY_TAG_INCREMENTBITLEN 0x07
+
+#define MODE_CHANGE_PIN 0x00
+#define MODE_UNBLOCK_PIN 0x01
+
+#define MAX_USER_PIN_TRIES 0x05
+#define MAX_SO_PIN_TRIES 0x05
+
+#define MIN_PIN_LEN 4
+#define MAX_PIN_LEN 24
+
+#define RSA_KEY_MIN_LENGTH 512
+#define RSA_KEY_MAX_LENGTH 2048
+
+// Constants defining layout of the records in cmapfile
+#define SIZE_CONTAINERMAPRECORD 86
+#define IDX_GUID_INFO 0
+#define IDX_FLAGS 80
+#define IDX_SIG_KEY_SIZE 82
+#define IDX_EXC_KEY_SIZE 84
+
+// Helper structs used when sync'ing CAPI containers
+// against P11 data.
+
+struct KeyPair
+{
+ KeyPair() : _checkValue(0), _fP11PrivKeyExists(false), _fP11CertExists(false) {}
+
+ u1Array _publicExponent;
+ u1Array _modulus;
+ u8 _checkValue;
+ u1Array _cert;
+ string _certName;
+ bool _fP11PrivKeyExists;
+ bool _fP11CertExists;
+};
+
+struct ContainerInfo
+{
+ ContainerInfo() : _cmapEntry(false) {}
+
+ bool _cmapEntry; // True if it represents a valid entry in cmapfile
+ KeyPair _signKP;
+ KeyPair _exchKP;
+};
+
+class CardCache;
+
+class Token {
+
+private:
+ CardModuleService* _mscm;
+
+ bool _initialized;
+ bool _supportGarbageCollection;
+ vector<StorageObject*> _objects;
+ vector<string> _toDelete; // List of files to be deleted at next login
+ CardCache * _cardCache;
+ unsigned long _cardCfTimer; // Timer indicating when _cardCf was last known to be up-to-date
+ CK_ULONG _cardCf; // Current state from \cardcf
+ CK_ULONG _publCardCf; // Reflects state of public cached objects
+ CK_ULONG _privCardCf; // Reflects state of private cached objects
+ CK_ULONG _cacheCardCf; // Reflects state of card cache (_cardCache)
+
+ bool _fPinChanged;
+ bool _fContainerChanged;
+ bool _fFileChanged;
+
+public:
+ CK_BBOOL _version;
+ CK_TOKEN_INFO _tokenInfo;
+ CK_ULONG _roleLogged;
+ //bool m_isPinExternal;
+ bool m_isPinPadSupported;
+
+public:
+ Token(std::string* reader);
+ ~Token();
+
+ CardModuleService* /*const*/ GetMiniDriverService( void ) { return _mscm; };
+
+ void Clear();
+ void BeginTransaction();
+ void EndTransaction();
+ void CardBeginTransaction();
+ void CardEndTransaction();
+ void ManageGC();
+
+ CK_RV Login(CK_ULONG userType,u1Array* pin);
+ CK_RV Logout();
+ CK_RV GenerateRandom(CK_BYTE_PTR randomData,CK_ULONG len);
+ CK_RV AddObject(auto_ptr<StorageObject> & stobj, CK_OBJECT_HANDLE_PTR phObject);
+ CK_RV AddPrivateKeyObject(auto_ptr<StorageObject> & stobj,CK_OBJECT_HANDLE_PTR phObject);
+ CK_RV AddCertificateObject(auto_ptr<StorageObject> & stobj,CK_OBJECT_HANDLE_PTR phObject);
+ CK_RV DeleteObject(CK_OBJECT_HANDLE hObject);
+ CK_ULONG FindObjects(Session* session,CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG ulMaxObjectCount,CK_ULONG_PTR pulObjectCount);
+
+ CK_RV GetAttributeValue(CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+ CK_RV SetAttributeValue(CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+
+ CK_RV GenerateKeyPair(auto_ptr<StorageObject> & stobjRsaPub, auto_ptr<StorageObject> & stobjRsaPriv,
+ CK_OBJECT_HANDLE_PTR phPubKey,CK_OBJECT_HANDLE_PTR phPrivKey);
+
+ CK_RV GetObject(CK_OBJECT_HANDLE hObject,StorageObject** object);
+
+ CK_RV Sign(StorageObject* privObj,u1Array* dataToSign,CK_ULONG mechanism,CK_BYTE_PTR pSignature);
+ CK_RV Decrypt(StorageObject* privObj,u1Array* dataToDecrypt,CK_ULONG mechanism,CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen);
+ CK_RV Verify(StorageObject* pubObj,u1Array* dataToVerify,CK_ULONG mechanism,u1Array* signature);
+ CK_RV Encrypt(StorageObject* pubObj,u1Array* dataToEncrypt,CK_ULONG mechanism,CK_BYTE_PTR pEncryptedData);
+
+ CK_RV InitToken(u1Array* pin,u1Array* label);
+ CK_RV InitPIN(u1Array* soPIN,u1Array* userPIN);
+ CK_RV SetPIN(u1Array* oldPIN,u1Array* newPIN);
+
+ bool isAuthenticated( void );
+ bool isSSO( void );
+
+private:
+
+ void getCardConfiguration( BYTE& a_bMode, BYTE &a_bTypePIN );
+ BYTE howToAuthenticate( BYTE bPinLen );
+ bool isPinPadSupported( void );
+ bool isPinExternalSupported( void );
+ CK_RV verifyPinWithPinPad( void );
+ CK_RV verifyPinWithBio( void /*Marshaller::u1Array *pin*/ );
+ DWORD m_dwIoctlVerifyPIN;
+
+ std::string m_sReaderName;
+ void Initialize();
+ void Resynchronize();
+ CK_RV AuthenticateUser(u1Array* pin);
+ CK_RV AuthenticateAdmin(u1Array* key);
+ void CreateDirIfNotPresent(std::string* parent,std::string* dir,u1Array* acls);
+ bool IsInitialized();
+ void PopulateDefaultTokenInfo();
+ void SerializeTokenInfo();
+ void DeserializeTokenInfo();
+ CK_BYTE GetAvailableContainerIndex(u1Array const & cmapContents);
+ CK_BYTE GetContainerForCert(u1Array const & cmapContents, u8 checkValue, u1 * keySpec);
+ CK_BYTE GetContainerForPrivateKey(u1Array const & cmapContents, u8 checkValue, u1 * keySpec);
+
+ auto_ptr<u1Array> UpdateCMap(CK_BYTE ctrIdx,u1Array const & contents,string const & contName);
+ auto_ptr<u1Array> UpdateCMap(CK_BYTE ctrIdx,u1Array const & contents,u4 keySize,u1 keySpec,
+ CK_BBOOL isDefault, string const & contName);
+
+ vector <PrivateKeyObject*> FindPrivateKeys(vector<StorageObject*> const & objects, u8 checkValue);
+ PrivateKeyObject* FindPrivateKey(vector<StorageObject*> const & objects, CK_BYTE ctrdIdx, u1 keySpec);
+ vector <CertificateObject*> FindCertificates(vector<StorageObject*> const & objects, u8 checkValue);
+ CertificateObject* FindCertificate(vector<StorageObject*> const & objects, CK_BYTE ctrdIdx, u1 keySpec);
+
+ u1Array* PadRSAPKCS1v15(u1Array* dataToSign,CK_ULONG modulusLen);
+ u1Array* PadRSAX509(u1Array* dataToSign,CK_ULONG modulusLen);
+ u1Array* EncodeHashForSigning(u1Array* hashedData,CK_ULONG modulusLen,CK_ULONG hashAlgo);
+
+ CK_BBOOL IsSynchronized();
+ void SynchronizeCertificates(vector<StorageObject*> & objects, map<int, ContainerInfo> & contMap);
+ void SynchronizePrivateKeys(vector<StorageObject*> & objects, map<int, ContainerInfo> & contMap);
+ void PrepareCertAttributesFromRawData(X509PubKeyCertObject* certObject);
+ bool PerformDeferredDelete();
+ string FindFreeFileName(StorageObject* object);
+ CK_RV WriteObject(StorageObject* object);
+
+ void ReadAndPopulateObjects(vector<StorageObject*> & objects, vector<string> & toDelete,
+ std::string const & prefix, map<int, ContainerInfo> & contMap);
+ void SynchronizePublicObjects(vector<StorageObject*> & objects, vector<string> & toDelete, map<int, ContainerInfo> & contMap);
+ void SynchronizePrivateObjects(vector<StorageObject*> & objects, vector<string> & toDelete, map<int, ContainerInfo> & contMap);
+ void BuildContainerInfoMap(map<int, ContainerInfo> & contMap);
+ void DeleteCMapRecord(CK_BYTE ctrdIdx);
+ void RemoveKeyFromCMapRecord(CK_BYTE ctrIndex, u1 keySpec);
+ void SetDefaultContainer(u1Array & contents, CK_BYTE ctrIndex);
+ u1Array* ComputeCryptogram(u1Array* challenge,u1Array* pin);
+ CK_RV VerifyRSAPKCS1v15(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen);
+ CK_RV VerifyRSAX509(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen);
+ CK_RV VerifyHash(u1Array* messageToVerify,u1Array* dataToVerify,u4 modulusLen,CK_ULONG hashAlgo);
+
+ static CK_RV DoPINValidityChecks(u1Array* pin, bool fCheckCharaceters = true);
+ s4 RegisterStorageObject(StorageObject * object);
+ void UnregisterStorageObject(StorageObject * object);
+ auto_ptr<u1Array> ReadCertificateFile(string const & path);
+ void RegisterPinUpdate();
+ void RegisterContainerUpdate();
+ void RegisterFileUpdate();
+ //void CheckAvailableSpace();
+ StorageObject * GetObject(CK_OBJECT_HANDLE hObject);
+
+};
+
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,308 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "secretkeyobject.h"
+
+SecretKeyObject::SecretKeyObject() : KeyObject()
+{
+ this->_sensitive = CK_FALSE;
+ this->_encrypt = CK_FALSE;
+ this->_decrypt = CK_FALSE;
+ this->_sign = CK_FALSE;
+ this->_verify = CK_FALSE;
+ this->_wrap = CK_FALSE;
+ this->_unwrap = CK_FALSE;
+ this->_extractable = CK_FALSE;
+ this->_alwaysSensitive = CK_FALSE;
+ this->_neverExtractable = CK_FALSE;
+ this->_checkSum = NULL_PTR;
+ this->_wrapWithTrusted = CK_FALSE;
+ this->_trusted = CK_FALSE;
+
+ this->_value = NULL_PTR;
+ this->_valueLength = 0;
+
+ this->_class = CKO_SECRET_KEY;
+}
+
+SecretKeyObject::~SecretKeyObject(){
+
+ if(this->_value != NULL_PTR){
+ delete this->_value;
+ }
+}
+
+CK_BBOOL SecretKeyObject::Compare(CK_ATTRIBUTE attribute)
+{
+ switch(attribute.type){
+
+ case CKA_SENSITIVE:
+ return (this->_sensitive == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_ENCRYPT:
+ return (this->_encrypt == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_DECRYPT:
+ return (this->_decrypt == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_SIGN:
+ return (this->_sign == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_VERIFY:
+ return (this->_verify == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_UNWRAP:
+ return (this->_unwrap == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_EXTRACTABLE:
+ return (this->_extractable == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_ALWAYS_SENSITIVE:
+ return (this->_alwaysSensitive == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_NEVER_EXTRACTABLE:
+ return (this->_neverExtractable == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_CHECK_VALUE:
+ return Util::CompareU1Arrays(this->_checkSum,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_WRAP_WITH_TRUSTED:
+ return (this->_wrapWithTrusted == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_TRUSTED:
+ return (this->_trusted == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_VALUE:
+ return Util::CompareU1Arrays(this->_value,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_VALUE_LEN:
+ return (this->_valueLength == *(CK_ULONG*)attribute.pValue);
+
+ default:
+ return KeyObject::Compare(attribute);
+ }
+}
+
+CK_RV SecretKeyObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+ switch(attribute->type)
+ {
+ case CKA_SENSITIVE:
+ return StorageObject::PutBBoolInAttribute(this->_sensitive,attribute);
+
+ case CKA_ENCRYPT:
+ return StorageObject::PutBBoolInAttribute(this->_encrypt,attribute);
+
+ case CKA_DECRYPT:
+ return StorageObject::PutBBoolInAttribute(this->_decrypt,attribute);
+
+ case CKA_SIGN:
+ return StorageObject::PutBBoolInAttribute(this->_sign,attribute);
+
+ case CKA_VERIFY:
+ return StorageObject::PutBBoolInAttribute(this->_verify,attribute);
+
+ case CKA_UNWRAP:
+ return StorageObject::PutBBoolInAttribute(this->_unwrap,attribute);
+
+ case CKA_EXTRACTABLE:
+ return StorageObject::PutBBoolInAttribute(this->_extractable,attribute);
+
+ case CKA_ALWAYS_SENSITIVE:
+ return StorageObject::PutBBoolInAttribute(this->_alwaysSensitive,attribute);
+
+ case CKA_NEVER_EXTRACTABLE:
+ return StorageObject::PutBBoolInAttribute(this->_neverExtractable,attribute);
+
+ case CKA_CHECK_VALUE:
+ return StorageObject::PutU1ArrayInAttribute(this->_checkSum,attribute);
+
+ case CKA_WRAP_WITH_TRUSTED:
+ return StorageObject::PutBBoolInAttribute(this->_wrapWithTrusted,attribute);
+
+ case CKA_TRUSTED:
+ return StorageObject::PutBBoolInAttribute(this->_trusted,attribute);
+
+ case CKA_VALUE:
+ if(this->_sensitive == CK_TRUE || this->_extractable == CK_FALSE){
+ attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+ return CKR_ATTRIBUTE_SENSITIVE;
+ }
+ return StorageObject::PutU1ArrayInAttribute(this->_value,attribute);
+
+ case CKA_VALUE_LEN:
+ return StorageObject::PutULongInAttribute(this->_valueLength,attribute);
+
+ default:
+ return KeyObject::GetAttribute(attribute);
+ }
+}
+
+CK_RV SecretKeyObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+ if( 0 == attribute.ulValueLen )
+ {
+ return CKR_OK;
+ }
+
+ switch(attribute.type)
+ {
+ case CKA_SENSITIVE:
+ this->_sensitive = *(CK_BBOOL*)attribute.pValue;
+ break;
+
+ case CKA_ENCRYPT:
+ this->_encrypt = *(CK_BBOOL*)attribute.pValue;
+ break;
+
+ case CKA_DECRYPT:
+ this->_decrypt = *(CK_BBOOL*)attribute.pValue;
+ break;
+
+ case CKA_SIGN:
+ this->_sign = *(CK_BBOOL*)attribute.pValue;
+ break;
+
+ case CKA_VERIFY:
+ this->_verify = *(CK_BBOOL*)attribute.pValue;
+ break;
+
+ case CKA_UNWRAP:
+ this->_unwrap = *(CK_BBOOL*)attribute.pValue;
+ break;
+
+ case CKA_EXTRACTABLE:
+ this->_extractable = *(CK_BBOOL*)attribute.pValue;
+ break;
+
+ case CKA_ALWAYS_SENSITIVE:
+ this->_alwaysSensitive = *(CK_BBOOL*)attribute.pValue;
+ break;
+
+ case CKA_NEVER_EXTRACTABLE:
+ this->_neverExtractable = *(CK_BBOOL*)attribute.pValue;
+ break;
+
+ case CKA_CHECK_VALUE:
+ if(this->_checkSum != NULL_PTR){
+ delete this->_checkSum;
+ }
+ this->_checkSum = new u1Array(attribute.ulValueLen);
+ memcpy((u1*)this->_checkSum->GetBuffer(),(CK_BYTE_PTR)attribute.pValue,attribute.ulValueLen);
+ break;
+
+ case CKA_WRAP_WITH_TRUSTED:
+ this->_wrapWithTrusted = *(CK_BBOOL*)attribute.pValue;
+ break;
+
+ case CKA_TRUSTED:
+ this->_trusted = *(CK_BBOOL*)attribute.pValue;
+ break;
+
+ case CKA_VALUE:
+ if(this->_value != NULL_PTR){
+ delete this->_value;
+ }
+ this->_value = new u1Array(attribute.ulValueLen);
+ memcpy((u1*)this->_value->GetBuffer(),(CK_BYTE_PTR)attribute.pValue,attribute.ulValueLen);
+ break;
+
+ case CKA_VALUE_LEN:
+ this->_valueLength = *(CK_ULONG*)attribute.pValue;
+ break;
+
+ default:
+ return KeyObject::SetAttribute(attribute,objCreation);
+ }
+
+ return CKR_OK;
+}
+
+void SecretKeyObject::Serialize(std::vector<u1> *to)
+{
+ KeyObject::Serialize(to);
+
+ Util::PushBBoolInVector(to,this->_sensitive);
+
+ Util::PushBBoolInVector(to,this->_encrypt);
+
+ Util::PushBBoolInVector(to,this->_decrypt);
+
+ Util::PushBBoolInVector(to,this->_sign);
+
+ Util::PushBBoolInVector(to,this->_verify);
+
+ Util::PushBBoolInVector(to,this->_unwrap);
+
+ Util::PushBBoolInVector(to,this->_extractable);
+
+ Util::PushBBoolInVector(to,this->_alwaysSensitive);
+
+ Util::PushBBoolInVector(to,this->_neverExtractable);
+
+ Util::PushByteArrayInVector(to,this->_checkSum);
+
+ Util::PushBBoolInVector(to,this->_wrapWithTrusted);
+
+ Util::PushBBoolInVector(to,this->_trusted);
+
+ Util::PushByteArrayInVector(to,this->_value);
+
+ Util::PushULongInVector(to,this->_valueLength);
+}
+
+void SecretKeyObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+ KeyObject::Deserialize(from,idx);
+
+ this->_sensitive = Util::ReadBBoolFromVector(from,idx);
+
+ this->_encrypt = Util::ReadBBoolFromVector(from,idx);
+
+ this->_decrypt = Util::ReadBBoolFromVector(from,idx);
+
+ this->_sign = Util::ReadBBoolFromVector(from,idx);
+
+ this->_verify = Util::ReadBBoolFromVector(from,idx);
+
+ this->_unwrap = Util::ReadBBoolFromVector(from,idx);
+
+ this->_extractable = Util::ReadBBoolFromVector(from,idx);
+
+ this->_alwaysSensitive = Util::ReadBBoolFromVector(from,idx);
+
+ this->_neverExtractable = Util::ReadBBoolFromVector(from,idx);
+
+ this->_checkSum = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_wrapWithTrusted = Util::ReadBBoolFromVector(from,idx);
+
+ this->_trusted = Util::ReadBBoolFromVector(from,idx);
+
+ this->_value = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_valueLength = Util::ReadULongFromVector(from,idx);
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/secretkeyobject.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,61 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_secretkeyobject_h
+#define _include_secretkeyobject_h
+
+#include "keyobject.h"
+
+class SecretKeyObject : public KeyObject
+{
+
+public:
+ CK_BBOOL _sensitive;
+ CK_BBOOL _encrypt;
+ CK_BBOOL _decrypt;
+ CK_BBOOL _sign;
+ CK_BBOOL _verify;
+ CK_BBOOL _wrap;
+ CK_BBOOL _unwrap;
+ CK_BBOOL _extractable;
+ CK_BBOOL _alwaysSensitive;
+ CK_BBOOL _neverExtractable;
+ u1Array* _checkSum;
+ CK_BBOOL _wrapWithTrusted;
+ CK_BBOOL _trusted;
+
+ u1Array* _value;
+ CK_ULONG _valueLength;
+
+public:
+ SecretKeyObject();
+ ~SecretKeyObject();
+
+ CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+ CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+ CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+ void Serialize(vector<u1>* to);
+ void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,534 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include <winscard.h> // inclusion needed for linux
+#include "platconfig.h"
+#include "config.h"
+#include "thread.h"
+#include "event.h"
+#include "template.h"
+#include "session.h"
+#include "slot.h"
+
+Session::Session(CK_BBOOL isReadWrite){
+ this->_isReadWrite = isReadWrite;
+ this->_searchTempl = NULL_PTR;
+ this->_isSearchActive = CK_FALSE;
+
+ this->_digest = NULL_PTR;
+ this->_digestRSA = NULL_PTR;
+ this->_digestRSAVerification = NULL_PTR;
+
+ this->_isDigestActive = CK_FALSE;
+ this->_isDigestRSAActive = CK_FALSE;
+ this->_isDigestRSAVerificationActive = CK_FALSE;
+
+ this->_signature = NULL_PTR;
+ this->_decryption = NULL_PTR;
+ this->_encryption = NULL_PTR;
+ this->_verification = NULL_PTR;
+
+ this->_soPIN = NULL_PTR;
+
+ this->_accumulatedDataToSign = NULL_PTR;
+ this->_accumulatedDataToVerify = NULL_PTR;
+
+ _objects.clear();
+ _sessionObjectsReturnedInSearch.clear();
+ _tokenObjectsReturnedInSearch.clear();
+}
+
+Session::~Session(){
+
+ for(size_t i = 0; i < _objects.size(); i++){
+ delete _objects[i];
+ _objects[i] = NULL_PTR;
+ }
+
+ if(this->_digest != NULL_PTR){
+ delete this->_digest;
+ }
+
+ if(this->_digestRSA != NULL_PTR){
+ delete this->_digestRSA;
+ }
+
+ if(this->_digestRSAVerification != NULL_PTR){
+ delete this->_digestRSAVerification;
+ }
+
+ if(this->_signature != NULL_PTR){
+ delete this->_signature;
+ }
+
+ if(this->_decryption != NULL_PTR){
+ delete this->_decryption;
+ }
+
+ if(this->_encryption != NULL_PTR){
+ delete this->_encryption;
+ }
+
+ if(this->_verification != NULL_PTR){
+ delete this->_verification;
+ }
+
+ if(this->_soPIN != NULL_PTR){
+ delete this->_soPIN;
+ }
+
+ if(this->_accumulatedDataToSign != NULL_PTR){
+ delete this->_accumulatedDataToSign;
+ }
+
+ if(this->_accumulatedDataToVerify != NULL_PTR){
+ delete this->_accumulatedDataToVerify;
+ }
+}
+
+void Session::SetSearchTemplate(Template* templ)
+{
+ PKCS11_ASSERT(this->_isSearchActive == CK_FALSE);
+
+ this->_searchTempl = templ;
+ this->_isSearchActive = CK_TRUE;
+
+ _tokenObjectsReturnedInSearch.clear();
+ _sessionObjectsReturnedInSearch.clear();
+}
+
+void Session::RemoveSearchTemplate()
+{
+ if(this->_searchTempl != NULL_PTR){
+ delete this->_searchTempl;
+ this->_searchTempl = NULL_PTR;
+ }
+
+ this->_isSearchActive = CK_FALSE;
+}
+
+void Session::UpdateState(CK_ULONG roleLogged)
+{
+ if(this->_isReadWrite)
+ {
+ switch(roleLogged)
+ {
+ case CKU_NONE:
+ this->_state = CKS_RW_PUBLIC_SESSION;
+ break;
+
+ case CKU_SO:
+ this->_state = CKS_RW_SO_FUNCTIONS;
+ break;
+
+ case CKU_USER:
+ this->_state = CKS_RW_USER_FUNCTIONS;
+ break;
+ }
+ }
+ else
+ {
+ switch(roleLogged)
+ {
+ case CKU_NONE:
+ this->_state = CKS_RO_PUBLIC_SESSION;
+ break;
+
+ case CKU_USER:
+ this->_state = CKS_RO_USER_FUNCTIONS;
+ break;
+ }
+ }
+}
+
+CK_BBOOL Session::IsSearchActive()
+{
+ return this->_isSearchActive;
+}
+
+void Session::SetId(CK_ULONG id)
+{
+ this->_id = id;
+}
+
+void Session::SetSlot(Slot* slot)
+{
+ this->_slot = slot;
+}
+
+CK_ULONG Session::MakeObjectHandle(CK_ULONG idx)
+{
+ CK_ULONG objHandle = CO_SESSION_OBJECT | idx;
+ objHandle = (this->_id << 16) | objHandle;
+
+ return objHandle;
+}
+
+CK_ULONG Session::FindObjects(CK_ULONG idx,CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG ulMaxObjectCount,CK_ULONG_PTR pulObjectCount)
+{
+
+ PKCS11_ASSERT(this->_isSearchActive);
+
+ for(CK_LONG i=0;i<static_cast<CK_LONG>(_objects.size()) && (idx < ulMaxObjectCount);i++){
+
+ if(this->_objects[i] == NULL_PTR){
+ continue;
+ }
+
+ if(this->_sessionObjectsReturnedInSearch[i] == CK_TRUE){
+ continue;
+ }
+
+ if((this->_objects[i]->_private == CK_TRUE) &&
+ (this->_slot->_token->_roleLogged != CKU_USER))
+ {
+ continue;
+ }
+
+ if(this->_searchTempl == NULL_PTR){
+ phObject[idx++] = MakeObjectHandle(i+1);
+ *pulObjectCount = *pulObjectCount + 1;
+ this->_sessionObjectsReturnedInSearch[i] = CK_TRUE;
+ }
+ else{
+ CK_BBOOL match = CK_TRUE;
+
+ vector<CK_ATTRIBUTE> attributes = this->_searchTempl->_attributes;
+ for(CK_ULONG a=0;a<attributes.size();a++){
+ if(this->_objects[i]->Compare(attributes.at(a)) == CK_FALSE){
+ match = CK_FALSE;
+ break;
+ }
+ }
+
+ if(match == CK_TRUE){
+ phObject[idx++] = MakeObjectHandle(i+1);
+ *pulObjectCount = *pulObjectCount + 1;
+ this->_sessionObjectsReturnedInSearch[i] = CK_TRUE;
+ }
+
+ }
+ }
+
+ return idx;
+}
+
+CK_RV Session::AddObject(StorageObject* obj,CK_OBJECT_HANDLE_PTR phObject)
+{
+ for(CK_ULONG i = 0; i < static_cast<CK_ULONG>(_objects.size()); i++)
+ {
+ if(this->_objects[i] == NULL_PTR)
+ {
+ this->_objects[i] = obj;
+ *phObject = MakeObjectHandle(i+1);
+
+ return CKR_OK;
+ }
+ }
+
+ _objects.push_back(obj);
+
+ *phObject = MakeObjectHandle(static_cast<CK_ULONG>(_objects.size()));
+
+ return CKR_OK;
+}
+
+CK_RV Session::DeleteObject(CK_OBJECT_HANDLE hObject)
+{
+ // object handle also encodes the session to which it
+ // belongs, it is also possible to delete object of one
+ // session from other
+
+ CK_SESSION_HANDLE encodedSId = ((hObject >> 16) & 0x0000FFFF);
+
+ if ((encodedSId < 1) || (encodedSId >= _slot->_sessions.size())){
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ if(this->_slot->_sessions[encodedSId] == NULL_PTR){
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ // determine the index
+ CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+ if(idx < 1 || idx > static_cast<CK_LONG>(_slot->_sessions[encodedSId]->_objects.size()))
+ return CKR_OBJECT_HANDLE_INVALID;
+
+ StorageObject* obj = this->_slot->_sessions[encodedSId]->_objects[idx-1];
+
+ if(obj == NULL_PTR){
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ // if this is a readonly session and
+ // user is not logged then only public session objects
+ // can be created
+ if(this->_isReadWrite == CK_FALSE)
+ {
+ if(obj->_tokenObject)
+ return CKR_SESSION_READ_ONLY;
+ }
+
+ if ((this->_slot->_token->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE)){
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ delete obj;
+
+ this->_slot->_sessions[encodedSId]->_objects[idx-1] = NULL_PTR;
+
+ return CKR_OK;
+}
+
+CK_RV Session::GetAttributeValue(CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount)
+{
+ CK_RV rv = CKR_OK;
+ CK_RV arv = CKR_OK;
+
+ CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+
+ // lets see if the object handle provided is a correct handle or not
+ if((idx < 1) || (idx > static_cast<CK_LONG>(_objects.size())) || (this->_objects[idx-1] == NULL_PTR)){
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ StorageObject* obj = this->_objects[idx-1];
+
+ if((this->_slot->_token->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE)){
+ for(u4 i=0;i<ulCount;i++){
+ pTemplate[i].ulValueLen = (CK_ULONG)-1;
+ }
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ for(u4 i=0;i<ulCount;i++){
+ rv = obj->GetAttribute(&pTemplate[i]);
+ if(rv != CKR_OK){
+ arv = rv;
+ }
+ }
+
+ return arv;
+}
+
+CK_RV Session::SetAttributeValue(CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount)
+{
+ CK_RV rv = CKR_OK;
+ CK_RV arv = CKR_OK;
+
+ CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+
+ // lets see if the object handle provided is a correct handle or not
+ if((idx < 1) || (idx > static_cast<CK_LONG>(_objects.size())) || (this->_objects[idx-1] == NULL_PTR)){
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ StorageObject* obj = this->_objects[idx-1];
+
+ if ((this->_slot->_token->_roleLogged != CKU_USER) && (obj->_private == CK_TRUE)){
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ for(u4 i=0;i<ulCount;i++){
+ rv = obj->SetAttribute(pTemplate[i],CK_FALSE);
+ if(rv != CKR_OK){
+ arv = rv;
+ }
+ }
+
+ return arv;
+}
+
+void Session::SetDigest(CDigest *digest)
+{
+ this->_digest = digest;
+ this->_isDigestActive = CK_TRUE;
+}
+
+void Session::RemoveDigest()
+{
+ if(this->_digest != NULL_PTR){
+ delete this->_digest;
+ this->_digest = NULL_PTR;
+ }
+
+ this->_isDigestActive = CK_FALSE;
+}
+
+CK_BBOOL Session::IsDigestActive()
+{
+ return this->_isDigestActive;
+}
+
+void Session::SetDigestRSA(CDigest *digest)
+{
+ this->_digestRSA = digest;
+ this->_isDigestRSAActive = CK_TRUE;
+}
+
+void Session::RemoveDigestRSA()
+{
+ if(this->_digestRSA != NULL_PTR){
+ delete this->_digestRSA;
+ this->_digestRSA = NULL_PTR;
+ }
+
+ this->_isDigestRSAActive = CK_FALSE;
+}
+
+CK_BBOOL Session::IsDigestRSAActive()
+{
+ return this->_isDigestRSAActive;
+}
+
+void Session::SetDigestRSAVerification(CDigest *digest)
+{
+ this->_digestRSAVerification = digest;
+ this->_isDigestRSAVerificationActive = CK_TRUE;
+}
+
+void Session::RemoveDigestRSAVerification()
+{
+ if(this->_digestRSAVerification != NULL_PTR){
+ delete this->_digestRSAVerification;
+ this->_digestRSAVerification = NULL_PTR;
+ }
+
+ this->_isDigestRSAVerificationActive = CK_FALSE;
+}
+
+CK_BBOOL Session::IsDigestRSAVerificationActive()
+{
+ return this->_isDigestRSAVerificationActive;
+}
+
+CK_RV Session::GetObject(CK_OBJECT_HANDLE hObject,StorageObject** object)
+{
+ if(hObject == 0){
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ CK_SESSION_HANDLE encodedSId = ((hObject >> 16) & 0x0000FFFF);
+
+ if ((encodedSId < 1) || (encodedSId >= _slot->_sessions.size())){
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ if(this->_slot->_sessions[encodedSId] == NULL_PTR){
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ // determine the index
+ CK_LONG idx = (CK_LONG)(hObject & CO_OBJECT_HANDLE_MASK);
+
+ StorageObject* obj = this->_slot->_sessions[encodedSId]->_objects[idx-1];
+
+ if(obj == NULL_PTR){
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+
+ *object = obj;
+
+ return CKR_OK;
+}
+
+void Session::SetEncryptionOperation(CryptoOperation *encryption)
+{
+ this->_encryption = encryption;
+}
+
+void Session::RemoveEncryptionOperation()
+{
+ if(this->_encryption != NULL_PTR){
+ delete this->_encryption;
+ }
+
+ this->_encryption = NULL_PTR;
+}
+
+CK_BBOOL Session::IsEncryptionActive(){
+
+ return (this->_encryption != NULL_PTR);
+}
+
+void Session::SetVerificationOperation(CryptoOperation *verification)
+{
+ this->_verification = verification;
+}
+
+void Session::RemoveVerificationOperation()
+{
+ if(this->_verification != NULL_PTR){
+ delete this->_verification;
+ }
+
+ this->_verification = NULL_PTR;
+}
+
+CK_BBOOL Session::IsVerificationActive(){
+
+ return (this->_verification != NULL_PTR);
+}
+
+void Session::SetDecryptionOperation(CryptoOperation *decryption)
+{
+ this->_decryption = decryption;
+}
+
+void Session::RemoveDecryptionOperation()
+{
+ if(this->_decryption != NULL_PTR){
+ delete this->_decryption;
+ }
+
+ this->_decryption = NULL_PTR;
+}
+
+CK_BBOOL Session::IsDecryptionActive(){
+
+ return (this->_decryption != NULL_PTR);
+}
+
+void Session::SetSignatureOperation(CryptoOperation* signature)
+{
+ this->_signature = signature;
+}
+
+void Session::RemoveSignatureOperation()
+{
+ if(this->_signature != NULL_PTR){
+ delete this->_signature;
+ }
+
+ this->_signature = NULL_PTR;
+}
+
+CK_BBOOL Session::IsSignatureActive(){
+
+ return (this->_signature != NULL_PTR);
+
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/session.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,144 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_session_h
+#define _include_session_h
+
+#include "template.h"
+#include "digest.h"
+#include "storageobject.h"
+#include <map>
+
+class Slot;
+
+class CryptoOperation{
+ CK_ULONG _mechanism;
+ StorageObject* _object;
+
+public:
+ CryptoOperation(CK_ULONG mechanism,StorageObject* obj){
+ this->_mechanism = mechanism;
+ this->_object = obj;
+ }
+
+ ~CryptoOperation(){}
+
+public:
+ CK_ULONG GetMechanism() { return this->_mechanism;}
+ StorageObject* GetObject() { return this->_object;}
+};
+
+class Session{
+
+public:
+ CK_BBOOL _isReadWrite;
+ CK_ULONG _state;
+ vector<StorageObject*> _objects;
+ Template* _searchTempl;
+ CDigest* _digest;
+ CDigest* _digestRSA;
+ CDigest* _digestRSAVerification;
+
+ map<CK_ULONG, bool> _sessionObjectsReturnedInSearch;
+ map<CK_ULONG, bool> _tokenObjectsReturnedInSearch;
+
+ CryptoOperation* _signature;
+ CryptoOperation* _decryption;
+ CryptoOperation* _verification;
+ CryptoOperation* _encryption;
+
+ CK_BBOOL _isSearchActive;
+ CK_BBOOL _isDigestActive;
+ CK_BBOOL _isDigestRSAActive;
+ CK_BBOOL _isDigestRSAVerificationActive;
+
+ CK_ULONG _id;
+ Slot* _slot;
+
+ u1Array* _accumulatedDataToSign;
+ u1Array* _accumulatedDataToVerify;
+
+
+ // Looks scary huh, the problem is that CardModule interface require
+ // cryptogram as part of ChangeReferenceData method whereas
+ // PKCS#11 first log SO in and then call InitPIN. InitPIN does not have any
+ // information about SO PIN so what we do here is to cache it momentarily.
+ // Basically during Login (as SO) we cache it and destroy it during closing
+ // of session
+ u1Array* _soPIN;
+
+public:
+ Session(CK_BBOOL isReadWrite);
+ ~Session();
+
+ void SetSearchTemplate(Template* templ);
+ void RemoveSearchTemplate();
+
+ void SetDigest(CDigest* digest);
+ void RemoveDigest();
+
+ void SetEncryptionOperation(CryptoOperation* encryption);
+ void RemoveEncryptionOperation();
+ CK_BBOOL IsEncryptionActive();
+
+ void SetVerificationOperation(CryptoOperation* verification);
+ void RemoveVerificationOperation();
+ CK_BBOOL IsVerificationActive();
+
+ void SetDecryptionOperation(CryptoOperation* decryption);
+ void RemoveDecryptionOperation();
+ CK_BBOOL IsDecryptionActive();
+
+ void SetSignatureOperation(CryptoOperation* signature);
+ void RemoveSignatureOperation();
+ CK_BBOOL IsSignatureActive();
+
+ void SetDigestRSA(CDigest* digest);
+ void RemoveDigestRSA();
+
+ void SetDigestRSAVerification(CDigest* digest);
+ void RemoveDigestRSAVerification();
+
+ void UpdateState(CK_ULONG roleLogged);
+ CK_BBOOL IsSearchActive();
+ CK_BBOOL IsDigestActive();
+ CK_BBOOL IsDigestRSAActive();
+ CK_BBOOL IsDigestRSAVerificationActive();
+
+ CK_RV AddObject(StorageObject* object,CK_OBJECT_HANDLE_PTR phObject);
+ CK_RV DeleteObject(CK_OBJECT_HANDLE hObject);
+
+ CK_ULONG FindObjects(CK_ULONG idx,CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG ulMaxObjectCount,CK_ULONG_PTR pulObjectCount);
+
+ CK_RV GetAttributeValue(CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+ CK_RV SetAttributeValue(CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+
+ void SetId(CK_ULONG id);
+ void SetSlot(Slot* slot);
+
+ CK_RV GetObject(CK_OBJECT_HANDLE hObject,StorageObject** object);
+
+private:
+ CK_ULONG MakeObjectHandle(CK_ULONG idx);
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,73 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "digest.h"
+#include "sha1.h"
+
+CSHA1::CSHA1(){
+ this->_hashValue = (CK_BYTE_PTR)malloc(SHA1_HASH_LENGTH);
+ this->_workingBuffer = (CK_BYTE_PTR)malloc(SHA1_BLOCK_LENGTH);
+ this->_hashLength = SHA1_HASH_LENGTH;
+ this->_blockLength = SHA1_BLOCK_LENGTH;
+}
+
+CSHA1::~CSHA1(){
+}
+
+void CSHA1::TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result)
+{
+ algo_sha1_context ctx;
+
+ ctx.digest = (u4*)result;
+
+ if (counter == 0) {
+ algo_sha1_starts(&ctx);
+ } else {
+ ctx.total[0] = counter;
+ ctx.total[1] = 0;
+ }
+
+ algo_sha1_update(&ctx, data, SHA1_BLOCK_LENGTH);
+}
+
+void CSHA1::TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result)
+{
+ algo_sha1_context ctx;
+
+ ctx.digest = (u4*)result;
+
+ if (counter == 0) {
+ algo_sha1_starts(&ctx);
+ } else {
+ ctx.total[0] = counter;
+ ctx.total[1] = 0;
+ }
+
+ ctx.input = (u1*)malloc(SHA1_BLOCK_LENGTH);
+ memset(ctx.input,0,SHA1_BLOCK_LENGTH);
+
+ algo_sha1_update(&ctx, data, length);
+ algo_sha1_finish(&ctx);
+
+ free(ctx.input);
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha1.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,39 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_sha1_h
+#define _include_sha1_h
+
+#include "MarshallerCfg.h"
+#include "algo_sha1.h"
+
+class CSHA1 : public CDigest
+{
+private:
+ void TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result);
+ void TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result);
+
+public:
+ CSHA1();
+ ~CSHA1();
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,78 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "digest.h"
+#include "sha256.h"
+
+CSHA256::CSHA256(){
+ this->_hashValue = (CK_BYTE_PTR)malloc(SHA256_HASH_LENGTH);
+ this->_workingBuffer = (CK_BYTE_PTR)malloc(SHA256_BLOCK_LENGTH);
+ this->_hashLength = SHA256_HASH_LENGTH;
+ this->_blockLength = SHA256_BLOCK_LENGTH;
+}
+
+CSHA256::~CSHA256(){
+}
+
+void CSHA256::TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result)
+{
+ algo_sha256_context* ctx = (algo_sha256_context*)malloc(sizeof(algo_sha256_context));
+
+ ctx->digest = (u4*)result;
+
+ if (counter == 0) {
+ algo_sha256_starts(ctx);
+ } else {
+ ctx->total[0] = counter;
+ ctx->total[1] = 0;
+ }
+
+ algo_sha256_update(ctx, data, SHA256_BLOCK_LENGTH);
+
+ free((u1*)ctx);
+}
+
+void CSHA256::TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result)
+{
+ algo_sha256_context* ctx = (algo_sha256_context*)malloc(sizeof(algo_sha256_context));
+
+ ctx->digest = (u4*)result;
+
+ if (counter == 0) {
+ algo_sha256_starts(ctx);
+ } else {
+ ctx->total[0] = counter;
+ ctx->total[1] = 0;
+ }
+
+ // allocate tempory working buffer
+ ctx->input = (u1*)malloc(SHA256_BLOCK_LENGTH);
+ memset(ctx->input, 0,SHA256_BLOCK_LENGTH);
+
+ // warning: algo_sha1_update must not throw any exception.
+ algo_sha256_update(ctx, data, length);
+ algo_sha256_finish(ctx);
+
+ free(ctx->input);
+ free((u1*)ctx);
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/sha256.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,39 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_sha256_h
+#define _include_sha256_h
+
+#include "MarshallerCfg.h"
+#include "algo_sha256.h"
+
+class CSHA256 : public CDigest
+{
+private:
+ void TransformBlock(CK_BYTE_PTR data,CK_LONG counter,CK_BYTE_PTR result);
+ void TransformFinalBlock(CK_BYTE_PTR data,CK_LONG length,CK_LONG counter,CK_BYTE_PTR result);
+
+public:
+ CSHA256();
+ ~CSHA256();
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,2836 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <winscard.h>
+#include "cardmoduleservice.h"
+
+#include <assert.h>
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "thread.h"
+#include "event.h"
+#include "template.h"
+#include "digest.h"
+#include "sha1.h"
+#include "sha256.h"
+#include "md5.h"
+#include "session.h"
+#include "slot.h"
+#include "dataobject.h"
+#include "secretkeyobject.h"
+#include "rsaprivatekeyobject.h"
+#include "rsapublickeyobject.h"
+#include "x509pubkeycertobject.h"
+#include "application.h"
+#include "transaction.h"
+#include "log.h"
+#include "error.h"
+
+#ifdef _XCL_
+#include "xcl_utils.h"
+#endif // _XCL_
+
+CK_MECHANISM_TYPE MechanismList[] = {
+ CKM_RSA_PKCS_KEY_PAIR_GEN, // 0
+ CKM_RSA_PKCS, // 1
+ CKM_RSA_X_509, // 2
+ CKM_MD5_RSA_PKCS, // 3
+ CKM_SHA1_RSA_PKCS, // 4
+ CKM_SHA256_RSA_PKCS, // 5
+#ifdef ENABLE_DIGEST
+ CKM_MD5, // 6
+ CKM_SHA_1, // 7
+ CKM_SHA256, // 8
+#endif
+#ifdef ENABLE_SYMMETRIC
+ CKM_AES_KEY_GEN, // 9
+ CKM_AES_ECB, // 10
+ CKM_AES_CBC, // 11
+ CKM_AES_CBC_PAD, // 12
+ CKM_DES_KEY_GEN, // 13
+ CKM_DES_ECB, // 14
+ CKM_DES_CBC, // 15
+ CKM_DES_CBC_PAD, // 16
+ CKM_DES2_KEY_GEN, // 17
+ CKM_DES3_KEY_GEN, // 18
+ CKM_DES3_ECB, // 19
+ CKM_DES3_CBC, // 20
+ CKM_DES3_CBC_PAD // 21
+#endif
+};
+
+CK_MECHANISM_INFO MechanismInfo[] = {
+ {/* 0 */ RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_GENERATE_KEY_PAIR},
+#ifdef ENABLE_SYMMETRIC
+ {/* 1 */ RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY | CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER | CKF_WRAP | CKF_UNWRAP},
+ {/* 2 */ RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY | CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER | CKF_WRAP | CKF_UNWRAP},
+#else
+ {/* 1 */ RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | /*CKF_SIGN_RECOVER |*/ CKF_VERIFY /*| CKF_VERIFY_RECOVER*/},
+ {/* 2 */ RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | /*CKF_SIGN_RECOVER |*/ CKF_VERIFY /*| CKF_VERIFY_RECOVER*/},
+#endif
+ {/* 3 */ RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_SIGN | CKF_VERIFY},
+ {/* 4 */ RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_SIGN | CKF_VERIFY},
+ {/* 5 */ RSA_KEY_MIN_LENGTH,RSA_KEY_MAX_LENGTH, CKF_HW | CKF_SIGN | CKF_VERIFY},
+#ifdef ENABLE_DIGEST
+ {/* 6 */ 0,0, CKF_SW | CKF_DIGEST},
+ {/* 7 */ 0,0, CKF_SW | CKF_DIGEST},
+ {/* 8 */ 0,0, CKF_SW | CKF_DIGEST},
+#endif
+#ifdef ENABLE_SYMMETRIC
+ {/* 9 */ 16,32, CKF_HW | CKF_GENERATE},
+ {/* 10 */ 0,0, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+ {/* 11 */ 0,0, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+ {/* 12 */ 0,0, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+ {/* 13 */ 0,0, CKF_HW | CKF_GENERATE},
+ {/* 14 */ 0,0, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+ {/* 15 */ 0,0, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+ {/* 16 */ 0,0, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+ {/* 17 */ 0,0, CKF_HW | CKF_GENERATE},
+ {/* 18 */ 0,0, CKF_HW | CKF_GENERATE},
+ {/* 19 */ 0,0, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+ {/* 20 */ 0,0, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP},
+ {/* 21 */ 0,0, CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}
+#endif
+};
+
+#define MAKE_SESSIONHANDLE(H,S) (H | (S << 24))
+#define GET_SESSIONID(H) (H & 0x00FFFFFF)
+#define GET_SLOTID(H) ((H & 0xFF000000) >> 24)
+
+//#define CHECK_IF_NULL_SESSION(A,S) if(A->_sessions[S] == NULL_PTR){return CKR_SESSION_HANDLE_INVALID;}
+#define CHECK_IF_NULL_SESSION(A,S) try \
+ { \
+ if( A->_sessions.at( S ) == NULL_PTR ) \
+ { \
+ return CKR_SESSION_HANDLE_INVALID; \
+ } \
+ } \
+ catch( ... ) \
+ { \
+ return CKR_SESSION_HANDLE_INVALID; \
+ } \
+
+#define CHECK_IF_TOKEN_IS_PRESENT(S) if(S->_token == NULL_PTR){return CKR_TOKEN_NOT_PRESENT;}
+
+Slot::Slot()
+{
+ // initialize the fields
+
+ CK_ULONG idx;
+
+ this->_token = NULL_PTR;
+ this->_readerName = NULL_PTR;
+
+ _sessions.resize(1,NULL_PTR); // First element is dummy
+
+ // initialize this slot
+ this->_slotId = 0;
+ this->_slotInfo.firmwareVersion.major = 0;
+ this->_slotInfo.firmwareVersion.minor = 0;
+ this->_slotInfo.flags = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;
+ this->_slotInfo.hardwareVersion.major = 0;
+ this->_slotInfo.hardwareVersion.minor = 0;
+
+ for(idx=0;idx<64;idx++)
+ this->_slotInfo.slotDescription[idx] = ' ';
+
+ this->_slotInfo.manufacturerID[0] = 'U';
+ this->_slotInfo.manufacturerID[1] = 'n';
+ this->_slotInfo.manufacturerID[2] = 'k';
+ this->_slotInfo.manufacturerID[3] = 'n';
+ this->_slotInfo.manufacturerID[4] = 'o';
+ this->_slotInfo.manufacturerID[5] = 'w';
+ this->_slotInfo.manufacturerID[6] = 'n';
+
+ for(idx=7;idx<32;idx++){
+ this->_slotInfo.manufacturerID[idx] = ' ';
+ }
+
+#ifdef INCLUDE_EVENTING
+ this->_tracker = NULL_PTR;
+ this->_event = CK_FALSE;
+#endif
+
+}
+
+Slot::~Slot(){
+
+ if(this->_token != NULL_PTR)
+ {
+ delete this->_token;
+ this->_token = NULL_PTR;
+ }
+
+#ifdef INCLUDE_EVENTING
+ if(this->_tracker != NULL_PTR)
+ {
+ delete this->_tracker;
+ this->_tracker = NULL_PTR;
+ }
+#endif
+
+ if(this->_readerName != NULL_PTR)
+ {
+ delete this->_readerName;
+ this->_readerName = NULL_PTR;
+ }
+
+ // destroy all opened sessions
+ for(size_t i=1;i<_sessions.size();i++)
+ {
+ if( this->_sessions[i] != NULL_PTR)
+ {
+ delete this->_sessions[i];
+ this->_sessions[i] = NULL_PTR;
+ }
+ }
+}
+
+
+#ifdef INCLUDE_EVENTING
+
+void Slot::SetEvent(CK_BBOOL event)
+{
+ this->_event = event;
+}
+
+CK_BBOOL Slot::GetEvent()
+{
+ return this->_event;
+}
+
+void Slot::Clear()
+{
+ // close all the sessions when card is removed
+ this->CloseAllSessions();
+
+ if(this->_token != NULL_PTR)
+ {
+ delete this->_token;
+ this->_token = NULL_PTR;
+ }
+}
+
+#endif
+
+CK_RV Slot::GetInfo(CK_SLOT_INFO_PTR pInfo)
+{
+ CK_BYTE idx;
+
+ // Check Parameters
+ if(pInfo == NULL_PTR)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ for(idx=0;idx<64;idx++)
+ {
+ pInfo->slotDescription[idx] = this->_slotInfo.slotDescription[idx];
+ }
+
+ for(idx=0;idx<32;idx++)
+ {
+ pInfo->manufacturerID[idx] = this->_slotInfo.manufacturerID[idx];
+ }
+
+ pInfo->hardwareVersion.major = this->_slotInfo.hardwareVersion.major;
+ pInfo->hardwareVersion.minor = this->_slotInfo.hardwareVersion.minor;
+ pInfo->firmwareVersion.major = this->_slotInfo.firmwareVersion.major;
+ pInfo->firmwareVersion.minor = this->_slotInfo.firmwareVersion.minor;
+
+ // it turns out that we need to dynamically poll if
+ // token is present or not. rest of the information should not
+ // change since we enumerated
+ SCARD_READERSTATE readerStates;
+
+ readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+ readerStates.szReader = this->_readerName->c_str();
+
+ // lets check if token is present
+#ifndef _XCL_
+
+ if (SCardGetStatusChange(Application::_hContext, 0, &readerStates, 1) == SCARD_S_SUCCESS)
+ {
+ if ((readerStates.dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT)
+ {
+ // we found a card in this reader
+ this->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+ }
+ else
+ {
+ // No card in reader
+ this->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+ CloseAllSessions();
+ }
+ }
+
+#else // _XCL_
+
+ PRINT_MSG("IN Slot::GetInfo");
+ if (xCL_IsTokenPresent())
+ {
+ // we found a card in this reader
+ this->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+ }
+ else
+ {
+ // No card in reader
+ this->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+ }
+
+#endif // _XCL_
+
+ pInfo->flags = this->_slotInfo.flags;
+
+ return CKR_OK;
+}
+
+
+CK_RV Slot::GetTokenInfo( CK_TOKEN_INFO_PTR pInfo )
+{
+ Log::begin( "Slot::GetTokenInfo" );
+
+ checkConnection( this );
+
+ // Check Parameters
+ if( NULL_PTR == pInfo )
+ {
+ Log::error( "Slot::GetTokenInfo", "CKR_ARGUMENTS_BAD" );
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ //Log::log( "Slot::GetTokenInfo - BuildToken..." );
+ CK_RV rv = this->BuildToken( );
+ //Log::log( "Slot::GetTokenInfo - BuildToken <%#02x>", rv );
+ if( CKR_OK == rv )
+ {
+ Transaction trans(this);
+
+ CK_BYTE idx;
+
+ pInfo->firmwareVersion.major = this->_token->_tokenInfo.firmwareVersion.major;
+ pInfo->firmwareVersion.minor = this->_token->_tokenInfo.firmwareVersion.minor;
+ pInfo->flags = this->_token->_tokenInfo.flags;
+ pInfo->hardwareVersion.major = this->_token->_tokenInfo.hardwareVersion.major;
+ pInfo->hardwareVersion.minor = this->_token->_tokenInfo.hardwareVersion.minor;
+
+ // label
+ for(idx=0;idx<32;idx++)
+ {
+ pInfo->label[idx] = this->_token->_tokenInfo.label[idx];
+ }
+
+ // manufacturerID
+ for(idx=0;idx<32;idx++)
+ {
+ pInfo->manufacturerID[idx] = this->_token->_tokenInfo.manufacturerID[idx];
+ }
+
+ // model
+ for(idx=0;idx<16;idx++)
+ {
+ pInfo->model[idx] = this->_token->_tokenInfo.model[idx];
+ }
+
+ // serial number
+ for(idx=0;idx<16;idx++)
+ {
+ pInfo->serialNumber[idx] = this->_token->_tokenInfo.serialNumber[idx];
+ }
+
+ pInfo->ulFreePrivateMemory = this->_token->_tokenInfo.ulFreePrivateMemory;
+ pInfo->ulFreePublicMemory = this->_token->_tokenInfo.ulFreePublicMemory;
+ pInfo->ulMaxPinLen = this->_token->_tokenInfo.ulMaxPinLen;
+ pInfo->ulMinPinLen = this->_token->_tokenInfo.ulMinPinLen;
+ pInfo->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE;
+ pInfo->ulSessionCount = 0;
+ pInfo->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
+ pInfo->ulRwSessionCount = 0;
+ pInfo->ulTotalPrivateMemory = this->_token->_tokenInfo.ulTotalPrivateMemory;
+ pInfo->ulTotalPublicMemory = this->_token->_tokenInfo.ulTotalPublicMemory;
+
+ for(size_t i=1;i<_sessions.size();i++)
+ {
+ if(_sessions[i])
+ {
+ ++pInfo->ulSessionCount;
+ if(_sessions[i]->_isReadWrite)
+ ++pInfo->ulRwSessionCount;
+ }
+ }
+
+ // utcTime
+ for(idx=0;idx<16;idx++)
+ {
+ pInfo->utcTime[idx] = this->_token->_tokenInfo.utcTime[idx];
+ }
+
+ // Check if the smart card is in SSO mode
+ if( ( true == this->_token->isSSO( ) ) && ( true == this->_token->isAuthenticated( ) ) )
+ {
+ this->_token->_tokenInfo.flags &= ~CKF_LOGIN_REQUIRED;
+ }
+ else
+ {
+ this->_token->_tokenInfo.flags |= CKF_LOGIN_REQUIRED;
+ }
+
+ Log::log( "Slot::GetTokenInfo - tokenInfo formated ok" );
+ }
+
+ Log::logCK_RV( "Slot::GetTokenInfo", rv );
+ Log::end( "Slot::GetTokenInfo" );
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::GetMechanismList(CK_MECHANISM_TYPE_PTR pMechanismList,CK_ULONG_PTR pulCount)
+{
+ if(pulCount == NULL_PTR)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if(pMechanismList == NULL_PTR)
+ {
+ *pulCount = (sizeof(MechanismList)/sizeof(CK_ULONG));
+ }
+ else
+ {
+ if(*pulCount < (sizeof(MechanismList)/sizeof(CK_ULONG)))
+ {
+ *pulCount = (sizeof(MechanismList)/sizeof(CK_ULONG));
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ for(size_t i=0;i<(sizeof(MechanismList)/sizeof(CK_ULONG));i++)
+ {
+ pMechanismList[i] = MechanismList[i];
+ }
+ *pulCount = (sizeof(MechanismList)/sizeof(CK_ULONG));
+ }
+
+ return CKR_OK;
+}
+
+
+/*
+*/
+CK_RV Slot::GetMechanismInfo(CK_MECHANISM_TYPE type,CK_MECHANISM_INFO_PTR pInfo)
+{
+ if(pInfo == NULL_PTR)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ size_t i = 0;
+ CK_BBOOL found = CK_FALSE;
+ for( ;i<(sizeof(MechanismList)/sizeof(CK_ULONG));i++)
+ {
+ if(MechanismList[i] == type)
+ {
+ found = CK_TRUE;
+ break;
+ }
+ }
+
+ if(found == CK_FALSE)
+ {
+ return CKR_MECHANISM_INVALID;
+ }
+
+ pInfo->ulMinKeySize = MechanismInfo[i].ulMinKeySize;
+ pInfo->ulMaxKeySize = MechanismInfo[i].ulMaxKeySize;
+ pInfo->flags = MechanismInfo[i].flags;
+
+ return CKR_OK;
+}
+
+
+CK_RV Slot::InitToken(CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen,CK_UTF8CHAR_PTR pLabel)
+{
+ CK_RV rv = CKR_OK;
+
+ checkConnection( this );
+
+ if(pPin == NULL_PTR || ulPinLen == 0 || pLabel == NULL_PTR){
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ // check if we have an open session
+ for(size_t i=1;i<_sessions.size();i++){
+ if(this->_sessions[i] != NULL_PTR){
+ return CKR_SESSION_EXISTS;
+ }
+ }
+
+ rv = this->BuildToken();
+
+ if(rv != CKR_OK){
+ return rv;
+ }
+
+ u1Array* pin = new u1Array(ulPinLen);
+ pin->SetBuffer(pPin);
+
+ u1Array* label = new u1Array(32);
+ label->SetBuffer(pLabel);
+
+ // Don't do the Transaction here.
+
+ rv = this->_token->InitToken(pin,label);
+
+ delete pin;
+ delete label;
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::OpenSession( CK_FLAGS flags, CK_VOID_PTR, CK_NOTIFY, CK_SESSION_HANDLE_PTR phSession )
+{
+ checkConnection( this );
+
+ if(phSession == NULL_PTR)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if( ( flags & CKF_SERIAL_SESSION ) != CKF_SERIAL_SESSION )
+ {
+ return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
+ }
+
+ CK_RV rv = this->BuildToken( );
+ if( rv != CKR_OK )
+ {
+ return rv;
+ }
+
+ Transaction trans( this );
+
+ // if admin is logged we can not open RO session
+ CK_BBOOL rwSession = ((flags & CKF_RW_SESSION) == CKF_RW_SESSION);
+
+ if( ( this->_token->_roleLogged == CKU_SO ) && ( !rwSession ) )
+ {
+ return CKR_SESSION_READ_WRITE_SO_EXISTS;
+ }
+
+ // Create the session instance
+ Session* session = new Session( rwSession );
+
+ // lets create a session
+ s4 sessionId = this->AddSession( session );
+ if( 0 == sessionId )
+ {
+ return CKR_SESSION_COUNT;
+ }
+
+ session->SetId(sessionId);
+ session->SetSlot(this);
+
+ // Refresh the state of the session if the SSO mode is enabled
+ UpdateAuthenticationState( );
+
+ // prepare a unique session id
+ *phSession = MAKE_SESSIONHANDLE(sessionId,this->_slotId);
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::CloseSession( CK_SESSION_HANDLE hSession )
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ checkConnection( pSlot );
+
+ //CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ //Slot* pSlot = NULL_PTR;
+ //GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ //checkConnection( pSlot );
+
+ //hSessionId = CK_INVALID_HANDLE;
+ //pSlot = NULL_PTR;
+ //CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+
+ if( CKR_OK == rv )
+ {
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+
+ pSlot->RemoveSession( hSessionId );
+
+ // Refresh the state of the session if the SSO mode is enabled
+ pSlot->UpdateAuthenticationState( );
+ }
+
+ return rv;
+}
+
+
+/*
+Check first if the card is in SSO mode then update the state of all sessions
+*/
+void Slot::UpdateAuthenticationState( void )
+{
+ // Check if the smart card is in SSO mode
+ if( true == _token->isSSO( ) )
+ {
+ // Affect the role to the token if the user is authenticated
+ _token->_roleLogged = CKU_NONE;
+ if( true == _token->isAuthenticated( ) )
+ {
+ _token->_roleLogged = CKU_USER;
+ }
+
+ // Update the state of all sessions
+ UpdateSessionState( );
+ }
+}
+
+
+/*
+*/
+CK_RV Slot::CloseAllSessions(void)
+{
+ // remove all sessions
+ for( size_t i = 1 ; i < _sessions.size( ) ; i++ )
+ {
+ if( NULL_PTR != this->_sessions[ i ] )
+ {
+ delete this->_sessions[ i ];
+ }
+
+ this->_sessions[ i ] = NULL_PTR;
+ }
+
+ _sessions.resize( 1 );
+
+ CHECK_IF_TOKEN_IS_PRESENT( this );
+
+ this->_token->_roleLogged = CKU_NONE;
+
+ // Refresh the state of the session if the SSO mode is enabled
+ UpdateAuthenticationState( );
+
+ return CKR_OK;
+}
+
+
+/*
+*/
+CK_RV Slot::GetSessionInfo( CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo )
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ checkConnection( pSlot );
+
+ if( CKR_OK != rv )
+ {
+ return rv;
+ }
+
+ if(pInfo == NULL_PTR)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId);
+
+ Transaction trans( pSlot );
+
+ pInfo->slotID = pSlot->_slotId;
+ pInfo->ulDeviceError = CKR_OK;
+
+ // Check if the smart card is in SSO mode
+ pSlot->UpdateAuthenticationState( );
+
+ pInfo->flags = ( ( pSlot->_sessions[ hSessionId ]->_isReadWrite ) ? CKF_RW_SESSION : 0 ) | (CKF_SERIAL_SESSION);
+ pInfo->state = pSlot->_sessions[ hSessionId ]->_state;
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::Login( CK_SESSION_HANDLE hSession,
+ CK_USER_TYPE userType,
+ CK_UTF8CHAR_PTR pPin,
+ CK_ULONG ulPinLen )
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ checkConnection( pSlot );
+
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ if(userType == CKU_SO)
+ {
+ if(pSlot->HasReadOnlySession())
+ {
+ return CKR_SESSION_READ_ONLY_EXISTS;
+ }
+ }
+
+ if( NULL_PTR == pPin )
+ {
+ ulPinLen = 0;
+ }
+
+ u1Array* pinValue = new u1Array(ulPinLen);
+ u1* pinValueBuffer = pinValue->GetBuffer();
+ CK_BYTE idx = 0;
+ for(idx=0;idx<ulPinLen;idx++)
+ {
+ pinValueBuffer[idx] = pPin[idx];
+ }
+ rv = pSlot->_token->Login(userType,pinValue);
+
+ if(rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN)
+ {
+ if(userType == CKU_SO)
+ {
+ // cache SO PIN for the duration of this session
+ pSlot->_sessions[ hSessionId ]->_soPIN = new u1Array(pinValue->GetLength());
+ pSlot->_sessions[ hSessionId ]->_soPIN->SetBuffer(pinValue->GetBuffer());
+ }
+ }
+
+ if(rv == CKR_OK)
+ {
+ pSlot->UpdateSessionState();
+ }
+
+ delete pinValue;
+
+ return rv;
+}
+
+
+
+CK_RV Slot::Logout( CK_SESSION_HANDLE hSession )
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ checkConnection( pSlot );
+
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ rv = pSlot->_token->Logout( );
+
+ pSlot->UpdateSessionState( );
+
+ return rv;
+}
+
+
+CK_RV Slot::InitPIN(CK_SESSION_HANDLE hSession,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen)
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ checkConnection( pSlot );
+
+ if(rv != CKR_OK){
+ return rv;
+ }
+
+ if(pPin == NULL_PTR || ulPinLen == 0){
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+ if(session->_state != CKS_RW_SO_FUNCTIONS)
+ {
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ PKCS11_ASSERT(session->_soPIN != NULL_PTR);
+
+ u1Array* pin = new u1Array(ulPinLen);
+ pin->SetBuffer(pPin);
+
+ rv = pSlot->_token->InitPIN(session->_soPIN,pin);
+
+ delete pin;
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::SetPIN( CK_SESSION_HANDLE hSession,
+ CK_UTF8CHAR_PTR pOldPin,
+ CK_ULONG ulOldLen,
+ CK_UTF8CHAR_PTR pNewPin,
+ CK_ULONG ulNewLen )
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ if(pOldPin == NULL_PTR || ulOldLen == 0 || pNewPin == NULL_PTR || ulNewLen == 0)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ CK_ULONG state = pSlot->_sessions[ hSessionId ]->_state;
+
+ if((state != CKS_RW_PUBLIC_SESSION) &&
+ (state != CKS_RW_SO_FUNCTIONS)&&
+ (state != CKS_RW_USER_FUNCTIONS))
+ {
+ return CKR_SESSION_READ_ONLY;
+ }
+
+ u1Array* oldPin = new u1Array(ulOldLen);
+ oldPin->SetBuffer(pOldPin);
+
+ u1Array* newPin = new u1Array(ulNewLen);
+ newPin->SetBuffer(pNewPin);
+
+ rv = pSlot->_token->SetPIN(oldPin,newPin);
+
+ delete oldPin;
+ delete newPin;
+
+ return rv;
+}
+
+
+CK_RV Slot::FindObjectsInit(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ if((pTemplate == NULL_PTR) && (ulCount != 0))
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+ // check if search is active for this session or not
+ if(session->IsSearchActive() == CK_TRUE)
+ {
+ return CKR_OPERATION_ACTIVE;
+ }
+
+ Template* searchTmpl = NULL_PTR;
+ if(ulCount != 0)
+ {
+ searchTmpl = new Template(pTemplate,ulCount);
+ }
+
+ session->SetSearchTemplate(searchTmpl);
+
+ return rv;
+}
+
+
+
+CK_RV Slot::FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG ulMaxObjectCount,CK_ULONG_PTR pulObjectCount)
+{
+ Log::begin( "Slot::FindObjects" );
+
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ checkConnection( pSlot );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+
+ if((phObject == NULL_PTR) || (pulObjectCount == NULL_PTR))
+ {
+ Log::error( "Slot::FindObjects", "CKR_ARGUMENTS_BAD" );
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ Log::log( "Slot::FindObjects - CHECK_IF_TOKEN_IS_PRESENT" );
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ Log::log( "Slot::FindObjects - CHECK_IF_TOKEN_IS_PRESENT" );
+
+ Log::log( "Slot::FindObjects - CHECK_IF_NULL_SESSION" );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Log::log( "Slot::FindObjects - CHECK_IF_NULL_SESSION" );
+
+ // Not needed here...
+ Log::log( "Slot::FindObjects - Transaction" );
+ Transaction trans( pSlot );
+ Log::log( "Slot::FindObjects - Transaction" );
+
+ Log::log( "Slot::FindObjects - session" );
+ Session* session = pSlot->_sessions[ hSessionId ];
+ Log::log( "Slot::FindObjects - session" );
+
+ // check if search is active for this session or not
+ Log::log( "Slot::FindObjects - IsSearchActive" );
+ if(session->IsSearchActive() == CK_FALSE)
+ {
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+ Log::log( "Slot::FindObjects - IsSearchActive" );
+
+ *pulObjectCount = 0;
+
+ // find the token objects matching the template
+ // count will tell how much of the phObject buffer was written
+ Log::log( "Slot::FindObjects - FindObjects" );
+ CK_ULONG count = pSlot->_token->FindObjects( session, phObject, ulMaxObjectCount, pulObjectCount );
+ Log::log( "Slot::FindObjects - FindObjects" );
+
+ if(count < ulMaxObjectCount)
+ {
+ // find the session objects matching the template
+ Log::log( "Slot::FindObjects - (count < ulMaxObjectCount)" );
+ count = session->FindObjects(count,phObject,ulMaxObjectCount,pulObjectCount);
+ Log::log( "Slot::FindObjects - (count < ulMaxObjectCount)" );
+ }
+
+ Log::logCK_RV( "Slot::FindObjects", rv );
+ Log::end( "Slot::FindObjects" );
+
+ return rv;
+}
+
+
+
+CK_RV Slot::FindObjectsFinal(CK_SESSION_HANDLE hSession)
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ checkConnection( pSlot );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+
+ // Not needed here
+ // Transaction trans(slot);
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+ // check if search is active for this session or not
+ if(session->IsSearchActive() == CK_FALSE)
+ {
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ session->RemoveSearchTemplate();
+
+ return rv;
+}
+
+CK_RV Slot::GenerateRandom(CK_SESSION_HANDLE hSession,CK_BYTE_PTR randomData,CK_ULONG ulRandomLen)
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ checkConnection( pSlot );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+
+ if((randomData == NULL_PTR) || (ulRandomLen == 0))
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ return pSlot->_token->GenerateRandom(randomData,ulRandomLen);
+}
+
+
+
+CK_RV Slot::CreateObject( CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject )
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ checkConnection( pSlot );
+
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ // check the pointer arguments
+ if((pTemplate == NULL_PTR) || (ulCount == 0) || (phObject == NULL_PTR))
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ // Check Template Consitency
+ rv = Template::CheckTemplate(pTemplate, ulCount, MODE_CREATE);
+ if (rv != CKR_OK)
+ {
+ return rv;
+ }
+
+ CK_ULONG classVal = Template::FindClassFromTemplate(pTemplate,ulCount);
+ PKCS11_ASSERT(classVal != -1);
+
+ auto_ptr<StorageObject> object;
+
+ switch(classVal){
+
+ case CKO_DATA:
+ object = auto_ptr<StorageObject>(new DataObject());
+ break;
+
+ case CKO_SECRET_KEY:
+ object = auto_ptr<StorageObject>(new SecretKeyObject());
+ break;
+
+ case CKO_PUBLIC_KEY:
+ object = auto_ptr<StorageObject>(new RSAPublicKeyObject());
+ break;
+
+ case CKO_PRIVATE_KEY:
+ object = auto_ptr<StorageObject>(new RSAPrivateKeyObject());
+ break;
+
+ case CKO_CERTIFICATE:
+ object = auto_ptr<StorageObject>(new X509PubKeyCertObject());
+ break;
+
+ default:
+ PKCS11_ASSERT(CK_FALSE);
+ break;
+ }
+
+ CK_BBOOL objCreationFailed = CK_FALSE;
+ CK_BYTE idx;
+ for(idx = 0; idx < ulCount; idx++)
+ {
+ if((rv = object->SetAttribute(pTemplate[idx],CK_TRUE)) != CKR_OK){
+ objCreationFailed = CK_TRUE;
+ break;
+ }
+ }
+
+ if(objCreationFailed)
+ {
+ return rv;
+ }
+
+ switch(object->_class)
+ {
+ case CKO_PUBLIC_KEY:
+ if(((RSAPublicKeyObject*)object.get())->_keyType != CKK_RSA)
+ {
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ break;
+
+ case CKO_PRIVATE_KEY:
+ if(((RSAPrivateKeyObject*)object.get())->_keyType != CKK_RSA)
+ {
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ break;
+ }
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+ // if this is a readonly session and
+ // user is not logged then only public session objects
+ // can be created
+ if(session->_isReadWrite == CK_FALSE)
+ {
+ if(object->_tokenObject)
+ {
+ return CKR_SESSION_READ_ONLY;
+ }
+ }
+
+ if ((pSlot->_token->_roleLogged != CKU_USER) && (object->_private == CK_TRUE))
+ {
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ if(object->_tokenObject)
+ {
+
+ // any type of token object cannot be created
+ // unless user is logged in
+
+ // NOTE : Not PKCS#11 compilance
+ // CardModule service does not allow 'deletion' of any file unless user is logged in. We can create a file
+ // when nobody is logged in but we can not delete. In order to be symmetrical we do not also allow
+ // the creation.
+ if(pSlot->_token->_roleLogged != CKU_USER)
+ {
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ // some sanity checks
+ if(object->_class == CKO_PRIVATE_KEY)
+ {
+ rv = pSlot->_token->AddPrivateKeyObject(object, phObject);
+ }
+ else if(object->_class == CKO_CERTIFICATE)
+ {
+ rv = pSlot->_token->AddCertificateObject(object, phObject);
+ }
+ else
+ {
+ rv = pSlot->_token->AddObject(object, phObject);
+ }
+ }
+ else
+ {
+ rv = session->AddObject(object.get(),phObject);
+ if(rv == CKR_OK)
+ object.release();
+ }
+
+ return rv;
+}
+
+
+
+CK_RV Slot::DestroyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject)
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+ // from object handle we can determine
+ // if it is a token object or session object
+ CK_BBOOL istoken = ((hObject & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+ // if this is a readonly session and
+ // user is not logged then only public session objects
+ // can be created
+ if(session->_isReadWrite == CK_FALSE)
+ {
+ if(istoken)
+ {
+ return CKR_SESSION_READ_ONLY;
+ }
+ }
+
+ if(istoken)
+ {
+ rv = pSlot->_token->DeleteObject(hObject);
+ }
+ else
+ {
+ rv = session->DeleteObject(hObject);
+ }
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::GetAttributeValue( CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulCount )
+{
+ if(pTemplate == NULL_PTR || ulCount == 0)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+ // from object handle we can determine
+ // if it is a token object or session object
+ CK_BBOOL istoken = ((hObject & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+ // TBD : Attributes of types such as Array which have not be initialized ?
+ // for eg label
+
+ if(istoken)
+ {
+ rv = pSlot->_token->GetAttributeValue(hObject,pTemplate,ulCount);
+ }
+ else
+ {
+ rv = session->GetAttributeValue(hObject,pTemplate,ulCount);
+ }
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::SetAttributeValue( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount )
+{
+ if(pTemplate == NULL_PTR || ulCount == 0)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* pSession = pSlot->_sessions[ hSessionId ];
+
+ // From object handle we can determine if it is a token object or session object
+ CK_BBOOL istoken = ( ( hObject & CO_TOKEN_OBJECT ) == CO_TOKEN_OBJECT );
+ if( TRUE == istoken )
+ {
+ if( CK_FALSE == pSession->_isReadWrite )
+ {
+ return CKR_SESSION_READ_ONLY;
+ }
+
+ rv = pSlot->_token->SetAttributeValue( hObject, pTemplate, ulCount );
+ }
+ else
+ {
+ rv = pSession->SetAttributeValue( hObject, pTemplate, ulCount );
+ }
+
+ return rv;
+}
+
+
+CK_RV Slot::GenerateKeyPair(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,CK_OBJECT_HANDLE_PTR phPrivateKey)
+{
+ // Since MODULUS_BITS is an essential attribute pPublicKeyTemplate should never be NULL or ulPublicKeyAttributeCount
+ // should not be zero. For private key template there is not compuslary attributes to be specified so it can be
+ // NULL_PTR
+
+ if((pMechanism == NULL_PTR) || (pPublicKeyTemplate == NULL_PTR) ||
+ (ulPublicKeyAttributeCount == 0) || (phPublicKey == NULL_PTR) ||
+ (phPrivateKey == NULL_PTR))
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if(pMechanism->mechanism != CKM_RSA_PKCS_KEY_PAIR_GEN)
+ return CKR_MECHANISM_INVALID;
+
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ //Session* session = pSlot->_sessions[ hSessionId ];
+
+ // Check Public Template Consitency
+ rv = Template::CheckTemplate(pPublicKeyTemplate, ulPublicKeyAttributeCount, MODE_GENERATE_PUB);
+ if (rv != CKR_OK)
+ return rv;
+
+ // Check Private Template Consitency
+ rv = Template::CheckTemplate(pPrivateKeyTemplate, ulPrivateKeyAttributeCount, MODE_GENERATE_PRIV);
+ if (rv != CKR_OK)
+ return rv;
+
+ auto_ptr<StorageObject> rsaPubKey(new RSAPublicKeyObject());
+ for(u4 i=0;i<ulPublicKeyAttributeCount;i++){
+ rv = rsaPubKey->SetAttribute(pPublicKeyTemplate[i],CK_TRUE);
+ if(rv != CKR_OK){
+ return rv;
+ }
+ }
+
+ auto_ptr<StorageObject> rsaPrivKey(new RSAPrivateKeyObject());
+ for(u4 i=0;i<ulPrivateKeyAttributeCount;i++){
+ rv = rsaPrivKey->SetAttribute(pPrivateKeyTemplate[i],CK_TRUE);
+ if(rv != CKR_OK){
+ return rv;
+ }
+ }
+
+ if(rsaPrivKey->_tokenObject){
+ rv = pSlot->_token->GenerateKeyPair(rsaPubKey,rsaPrivKey,phPublicKey,phPrivateKey);
+ }else{
+
+ // We do not support generation of key pair in the software
+ // TBD: Should we ?. I have noticed that during the import of
+ // p12 file using firefox it asks you to generate it in session
+
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ if(rv == CKR_OK)
+ {
+ if(rsaPubKey.get() && !rsaPubKey->_tokenObject)
+ {
+ pSlot->_sessions[ hSessionId ]->AddObject(rsaPubKey.get(),phPublicKey);
+ rsaPubKey.release();
+ }
+ }
+ return rv;
+}
+
+// ------------------------------------------------------------------------------------------------
+// DIGEST RELATED FUNCTIONS
+// ------------------------------------------------------------------------------------------------
+CK_RV Slot::DigestInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism)
+{
+ if(pMechanism == NULL_PTR)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ // Not needed
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+ if(session->IsDigestActive()){
+ return CKR_OPERATION_ACTIVE;
+ }
+
+ switch(pMechanism->mechanism){
+
+ case CKM_SHA_1:
+ session->SetDigest(new CSHA1());
+ break;
+
+ case CKM_SHA256:
+ session->SetDigest(new CSHA256());
+ break;
+
+ case CKM_MD5:
+ session->SetDigest(new CMD5());
+ break;
+
+ default:
+ return CKR_MECHANISM_INVALID;
+
+ }
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::Digest(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,
+ CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)
+{
+ if((pData == NULL_PTR) || (ulDataLen == 0) || (pulDigestLen == NULL_PTR)){
+ return CKR_ARGUMENTS_BAD;
+ }
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+
+ if(session->IsDigestActive() == CK_FALSE){
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ CDigest* digest = session->_digest;
+
+ if((*pulDigestLen < (CK_ULONG)digest->HashLength()) && (pDigest != NULL_PTR)){
+ *pulDigestLen = (CK_ULONG)digest->HashLength();
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else if(!pDigest){
+ *pulDigestLen = digest->HashLength();
+ return CKR_OK;
+ }
+
+ digest->HashCore(pData, 0, ulDataLen);
+
+ *pulDigestLen = (CK_ULONG)digest->HashLength();
+
+ if (pDigest != NULL_PTR)
+ {
+ digest->HashFinal(pDigest);
+ session->RemoveDigest();
+ }
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)
+{
+ if(pPart == NULL_PTR || ulPartLen == 0)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+
+ if(session->IsDigestActive() == CK_FALSE)
+ {
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ session->_digest->HashCore(pPart,0,ulPartLen);
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)
+{
+ if(pulDigestLen == NULL_PTR)
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+ if(session->IsDigestActive() == CK_FALSE){
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ CDigest* digest = session->_digest;
+
+ if((*pulDigestLen < (CK_ULONG)digest->HashLength()) && (pDigest != NULL_PTR)){
+ *pulDigestLen = (CK_ULONG)digest->HashLength();
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ else if(!pDigest){
+ *pulDigestLen = digest->HashLength();
+ return CKR_OK;
+ }
+
+ *pulDigestLen = (CK_ULONG)digest->HashLength();
+
+ if (pDigest != NULL_PTR){
+ digest->HashFinal(pDigest);
+ session->RemoveDigest();
+ }
+
+ return rv;
+}
+
+// ------------------------------------------------------------------------------------------------
+// SIGNATURE RELATED FUNCTIONS
+// ------------------------------------------------------------------------------------------------
+CK_RV Slot::SignInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
+{
+ if(pMechanism == NULL_PTR){
+ return CKR_ARGUMENTS_BAD;
+ }
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+ if(session->IsSignatureActive() == CK_TRUE){
+ return CKR_OPERATION_ACTIVE;
+ }
+
+ rv = Slot::IsValidMechanism(pMechanism->mechanism,CKF_SIGN);
+
+ if(rv != CKR_OK){
+ return rv;
+ }
+
+ if(pSlot->_token->_roleLogged != CKU_USER){
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ // get the corresponding object
+ StorageObject* object = NULL_PTR;
+
+ // from object handle we can determine
+ // if it is a token object or session object
+ CK_BBOOL istoken = ((hKey & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+ if(istoken){
+ rv = pSlot->_token->GetObject(hKey,&object);
+ }else{
+ rv = session->GetObject(hKey,&object);
+ }
+
+ if(rv != CKR_OK){
+
+ if(rv == CKR_OBJECT_HANDLE_INVALID){
+ return CKR_KEY_HANDLE_INVALID;
+ }
+
+ return rv;
+ }
+
+ rv = Slot::IsValidCryptoOperation(object,CKF_SIGN);
+
+ if(rv != CKR_OK){
+ return rv;
+ }
+
+ // let's initialize this crypto operation
+ session->SetSignatureOperation(new CryptoOperation(pMechanism->mechanism,object));
+
+ if(pMechanism->mechanism == CKM_SHA1_RSA_PKCS){
+ session->SetDigestRSA(new CSHA1());
+ }else if(pMechanism->mechanism == CKM_SHA256_RSA_PKCS){
+ session->SetDigestRSA(new CSHA256());
+ }else if(pMechanism->mechanism == CKM_MD5_RSA_PKCS){
+ session->SetDigestRSA(new CMD5());
+ }
+
+ return rv;
+}
+
+
+
+CK_RV Slot::Sign(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,
+ CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen)
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+
+ if(session->IsSignatureActive() == CK_FALSE){
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ if(pData == NULL_PTR || ulDataLen == 0 || pulSignatureLen == NULL_PTR){
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ StorageObject* object = session->_signature->GetObject();
+
+ PKCS11_ASSERT(object->_class == CKO_PRIVATE_KEY);
+
+ CK_ULONG mechanism = session->_signature->GetMechanism();
+
+ // TBD : Private key may not necessarily have the modulus or modulus bits
+ // if that is the case then we need to locate the corresponding public key
+ // or may be I should always put the modulus bits in private key attributes
+
+ u1Array* modulus = ((RSAPrivateKeyObject*)object)->_modulus;
+
+ PKCS11_ASSERT(modulus != NULL_PTR);
+
+ if(((mechanism == CKM_RSA_PKCS) && (ulDataLen > modulus->GetLength() - 11)) ||
+ ((mechanism == CKM_RSA_X_509) && (ulDataLen > modulus->GetLength())))
+ {
+ return CKR_DATA_LEN_RANGE;
+ }
+
+ if(pSignature == NULL_PTR){
+ *pulSignatureLen = modulus->GetLength();
+ return CKR_OK;
+ }else{
+ if(*pulSignatureLen < modulus->GetLength()){
+ *pulSignatureLen = modulus->GetLength();
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ }
+
+ u1Array* dataToSign = NULL_PTR;
+
+ if(session->IsDigestRSAActive() == CK_TRUE){
+ // require hashing also
+ CK_BYTE_PTR hash = NULL_PTR;
+ CDigest* digest = session->_digestRSA;
+
+ hash = (CK_BYTE_PTR)malloc(digest->HashLength());
+
+ digest->HashCore(pData,0,ulDataLen);
+ digest->HashFinal(hash);
+
+ dataToSign = new u1Array(digest->HashLength());
+ dataToSign->SetBuffer(hash);
+
+ free(hash);
+ }
+ // Sign Only
+ else {
+ dataToSign = new u1Array(ulDataLen);
+ dataToSign->SetBuffer(pData);
+ }
+
+ rv = pSlot->_token->Sign(session->_signature->GetObject(),dataToSign,session->_signature->GetMechanism(),pSignature);
+
+ if(rv == CKR_OK){
+ *pulSignatureLen = modulus->GetLength();
+ }
+
+ session->RemoveDigestRSA();
+ session->RemoveSignatureOperation();
+
+ delete dataToSign;
+
+ return rv;
+}
+
+
+
+CK_RV Slot::SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
+{
+ // what we do here is to update the hash or
+ // if hashing is not getting used we just accumulate it
+
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+
+ if(session->IsSignatureActive() == CK_FALSE){
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ if(pPart == NULL_PTR || ulPartLen == 0){
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if(session->IsDigestRSAActive() == CK_TRUE){
+ CDigest* digest = session->_digestRSA;
+ digest->HashCore(pPart,0,ulPartLen);
+ }
+ // Sign Only
+ else {
+
+ if(session->_accumulatedDataToSign != NULL_PTR){
+ // just accumulate the data
+ u1Array* updatedData = new u1Array(session->_accumulatedDataToSign->GetLength() + ulPartLen);
+ memcpy(updatedData->GetBuffer(),session->_accumulatedDataToSign->GetBuffer(),session->_accumulatedDataToSign->GetLength());
+
+ memcpy((u1*)&updatedData->GetBuffer()[session->_accumulatedDataToSign->GetLength()],pPart,ulPartLen);
+
+ delete session->_accumulatedDataToSign;
+
+ session->_accumulatedDataToSign = updatedData;
+ }else{
+
+ session->_accumulatedDataToSign = new u1Array(ulPartLen);
+ session->_accumulatedDataToSign->SetBuffer(pPart);
+ }
+
+ CK_ULONG mech = session->_signature->GetMechanism();
+ u1Array* modulus = ((RSAPrivateKeyObject*)session->_signature->GetObject())->_modulus;
+
+ if(((mech == CKM_RSA_PKCS) && (session->_accumulatedDataToSign->GetLength() > modulus->GetLength() - 11)) ||
+ ((mech == CKM_RSA_X_509) && (session->_accumulatedDataToSign->GetLength() > modulus->GetLength())))
+ {
+ return CKR_DATA_LEN_RANGE;
+ }
+ }
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen)
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+
+ if(session->IsSignatureActive() == CK_FALSE){
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ if(pulSignatureLen == NULL_PTR){
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ StorageObject* object = session->_signature->GetObject();
+
+ PKCS11_ASSERT(object->_class == CKO_PRIVATE_KEY);
+
+
+ // TBD : Private key may not necessarily have the modulus or modulus bits
+ // if that is the case then we need to locate the corresponding public key
+ // or may be I should always put the modulus bits in private key attributes
+
+ u1Array* modulus = ((RSAPrivateKeyObject*)object)->_modulus;
+
+ PKCS11_ASSERT(modulus != NULL_PTR);
+
+ if(pSignature == NULL_PTR){
+ *pulSignatureLen = modulus->GetLength();
+ return CKR_OK;
+ }else{
+ if(*pulSignatureLen < modulus->GetLength()){
+ *pulSignatureLen = modulus->GetLength();
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ }
+
+ u1Array* dataToSign = NULL_PTR;
+
+ if(session->IsDigestRSAActive() == CK_TRUE){
+ // require hashing also
+ CK_BYTE_PTR hash = NULL_PTR;
+ CDigest* digest = session->_digestRSA;
+
+ hash = (CK_BYTE_PTR)malloc(digest->HashLength());
+
+ digest->HashFinal(hash);
+
+ dataToSign = new u1Array(digest->HashLength());
+ dataToSign->SetBuffer(hash);
+
+ free(hash);
+ }
+ // Sign Only
+ else {
+ dataToSign = session->_accumulatedDataToSign;
+ }
+
+ rv = pSlot->_token->Sign(session->_signature->GetObject(),dataToSign,session->_signature->GetMechanism(),pSignature);
+
+ if(rv == CKR_OK){
+ *pulSignatureLen = modulus->GetLength();
+ }
+
+ session->RemoveDigestRSA();
+ session->RemoveSignatureOperation();
+
+ delete dataToSign;
+ session->_accumulatedDataToSign = NULL_PTR;
+
+ return rv;
+}
+
+
+
+CK_RV Slot::EncryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
+{
+ if(pMechanism == NULL_PTR){
+ return CKR_ARGUMENTS_BAD;
+ }
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+
+ if(session->IsEncryptionActive() == CK_TRUE){
+ return CKR_OPERATION_ACTIVE;
+ }
+
+ rv = Slot::IsValidMechanism(pMechanism->mechanism,CKF_ENCRYPT);
+
+ if(rv != CKR_OK){
+ return rv;
+ }
+
+ if(pSlot->_token->_roleLogged != CKU_USER){
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ // get the corresponding object
+ StorageObject* object = NULL_PTR;
+
+ // from object handle we can determine
+ // if it is a token object or session object
+ CK_BBOOL istoken = ((hKey & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+ if(istoken){
+ rv = pSlot->_token->GetObject(hKey,&object);
+ }else{
+ rv = session->GetObject(hKey,&object);
+ }
+
+ if(rv != CKR_OK){
+ if(rv == CKR_OBJECT_HANDLE_INVALID){
+ return CKR_KEY_HANDLE_INVALID;
+ }
+
+ return rv;
+ }
+
+ rv = Slot::IsValidCryptoOperation(object,CKF_ENCRYPT);
+
+ if(rv != CKR_OK){
+ return rv;
+ }
+
+ // let's initialize this crypto operation
+ session->SetEncryptionOperation(new CryptoOperation(pMechanism->mechanism,object));
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::Encrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,
+ CK_BYTE_PTR pEncryptedData,CK_ULONG_PTR pulEncryptedDataLen)
+{
+ if(pData == NULL_PTR || ulDataLen == 0 || pulEncryptedDataLen == NULL_PTR){
+ return CKR_ARGUMENTS_BAD;
+ }
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+
+ if(session->IsEncryptionActive() == CK_FALSE){
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ StorageObject* object = session->_encryption->GetObject();
+
+ PKCS11_ASSERT(object->_class == CKO_PUBLIC_KEY);
+
+ //CK_ULONG mechanism = session->_encryption->GetMechanism();
+
+ u1Array* modulus = ((RSAPublicKeyObject*)object)->_modulus;
+
+ PKCS11_ASSERT(modulus != NULL_PTR);
+
+ if(pEncryptedData == NULL_PTR){
+ *pulEncryptedDataLen = modulus->GetLength();
+ return CKR_OK;
+ }else{
+ if(*pulEncryptedDataLen < modulus->GetLength()){
+ *pulEncryptedDataLen = modulus->GetLength();
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ }
+
+ u1Array* dataToEncrypt = new u1Array(ulDataLen);
+ dataToEncrypt->SetBuffer(pData);
+
+ rv = pSlot->_token->Encrypt(session->_encryption->GetObject(),dataToEncrypt,session->_encryption->GetMechanism(),pEncryptedData);
+
+ if(rv == CKR_OK){
+ *pulEncryptedDataLen = modulus->GetLength();
+ }
+
+ session->RemoveEncryptionOperation();
+
+ delete dataToEncrypt;
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::DecryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
+{
+ if(pMechanism == NULL_PTR){
+ return CKR_ARGUMENTS_BAD;
+ }
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+
+ if(session->IsDecryptionActive() == CK_TRUE){
+ return CKR_OPERATION_ACTIVE;
+ }
+
+ rv = Slot::IsValidMechanism(pMechanism->mechanism,CKF_DECRYPT);
+
+ if(rv != CKR_OK){
+ return rv;
+ }
+
+ if(pSlot->_token->_roleLogged != CKU_USER){
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ // get the corresponding object
+ StorageObject* object = NULL_PTR;
+
+ // from object handle we can determine
+ // if it is a token object or session object
+ CK_BBOOL istoken = ((hKey & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+ if(istoken){
+ rv = pSlot->_token->GetObject(hKey,&object);
+ }else{
+ rv = session->GetObject(hKey,&object);
+ }
+
+ if(rv != CKR_OK){
+ if(rv == CKR_OBJECT_HANDLE_INVALID){
+ return CKR_KEY_HANDLE_INVALID;
+ }
+
+ return rv;
+ }
+
+ rv = Slot::IsValidCryptoOperation(object,CKF_DECRYPT);
+
+ if(rv != CKR_OK){
+ return rv;
+ }
+
+ // let's initialize this crypto operation
+ session->SetDecryptionOperation(new CryptoOperation(pMechanism->mechanism,object));
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::Decrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,
+ CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)
+{
+ if(pEncryptedData == NULL_PTR || ulEncryptedDataLen == 0 ||pulDataLen == NULL_PTR){
+ return CKR_ARGUMENTS_BAD;
+ }
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+
+ if(session->IsDecryptionActive() == CK_FALSE){
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ StorageObject* object = session->_decryption->GetObject();
+
+ PKCS11_ASSERT(object->_class == CKO_PRIVATE_KEY);
+
+ CK_ULONG mechanism = session->_decryption->GetMechanism();
+
+ // TBD : Private key may not necessarily have the modulus or modulus bits
+ // if that is the case then we need to locate the corresponding public key
+ // or may be I should always put the modulus bits in private key attributes
+
+ u1Array* modulus = ((RSAPrivateKeyObject*)object)->_modulus;
+
+ PKCS11_ASSERT(modulus != NULL_PTR);
+
+ // [HB]: Fix length of return value
+ if(mechanism == CKM_RSA_PKCS){
+ // Can't know exact size of returned value before decryption has been done
+ if(pData == NULL_PTR){
+ *pulDataLen = modulus->GetLength() - 11;
+ return CKR_OK;
+ }
+ }
+ else if(mechanism == CKM_RSA_X_509){
+ if(pData == NULL_PTR){
+ *pulDataLen = modulus->GetLength();
+ return CKR_OK;
+ }else{
+ if(*pulDataLen < modulus->GetLength()){
+ *pulDataLen = modulus->GetLength();
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ }
+ }
+ else
+ return CKR_MECHANISM_INVALID;
+
+ if(ulEncryptedDataLen != modulus->GetLength()){
+ return CKR_ENCRYPTED_DATA_LEN_RANGE;
+ }
+
+ u1Array* dataToDecrypt = new u1Array(ulEncryptedDataLen);
+ dataToDecrypt->SetBuffer(pEncryptedData);
+
+ rv = pSlot->_token->Decrypt(session->_decryption->GetObject(),dataToDecrypt,session->_decryption->GetMechanism(),pData, pulDataLen);
+
+ session->RemoveDecryptionOperation();
+
+ delete dataToDecrypt;
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::VerifyInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
+{
+ if(pMechanism == NULL_PTR){
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+
+ if(session->IsVerificationActive() == CK_TRUE){
+ return CKR_OPERATION_ACTIVE;
+ }
+
+ rv = Slot::IsValidMechanism(pMechanism->mechanism,CKF_VERIFY);
+
+ if(rv != CKR_OK){
+ return rv;
+ }
+
+ if(pSlot->_token->_roleLogged != CKU_USER){
+ return CKR_USER_NOT_LOGGED_IN;
+ }
+
+ // get the corresponding object
+ StorageObject* object = NULL_PTR;
+
+ // from object handle we can determine
+ // if it is a token object or session object
+ CK_BBOOL istoken = ((hKey & CO_TOKEN_OBJECT) == CO_TOKEN_OBJECT);
+
+ if(istoken){
+ rv = pSlot->_token->GetObject(hKey,&object);
+ }else{
+ rv = session->GetObject(hKey,&object);
+ }
+
+ if(rv != CKR_OK){
+
+ if(rv == CKR_OBJECT_HANDLE_INVALID){
+ return CKR_KEY_HANDLE_INVALID;
+ }
+
+ return rv;
+ }
+
+ rv = Slot::IsValidCryptoOperation(object,CKF_VERIFY);
+
+ if(rv != CKR_OK){
+ return rv;
+ }
+
+ // let's initialize this crypto operation
+ session->SetVerificationOperation(new CryptoOperation(pMechanism->mechanism,object));
+
+ if(pMechanism->mechanism == CKM_SHA1_RSA_PKCS){
+ session->SetDigestRSAVerification(new CSHA1());
+ }else if(pMechanism->mechanism == CKM_SHA256_RSA_PKCS){
+ session->SetDigestRSAVerification(new CSHA256());
+ }else if(pMechanism->mechanism == CKM_MD5_RSA_PKCS){
+ session->SetDigestRSAVerification(new CMD5());
+ }
+
+ return CKR_OK;
+
+}
+
+
+/*
+*/
+CK_RV Slot::Verify(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,
+ CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+
+ if(session->IsVerificationActive() == CK_FALSE){
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ if((pData == NULL_PTR) || (ulDataLen == 0) ||
+ (pSignature == NULL_PTR) || (ulSignatureLen == 0))
+ {
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ CK_ULONG mechanism = session->_verification->GetMechanism();
+
+
+ // I am doubtful regarding these 3 lines as
+ // the object could be privatekey which contains
+ // the public components
+ StorageObject* object = session->_verification->GetObject();
+ PKCS11_ASSERT(object->_class == CKO_PUBLIC_KEY);
+ u1Array* modulus = ((RSAPublicKeyObject*)object)->_modulus;
+
+ PKCS11_ASSERT(modulus != NULL_PTR);
+
+ if(((mechanism == CKM_RSA_PKCS) && (ulDataLen > modulus->GetLength() - 11)) ||
+ ((mechanism == CKM_RSA_X_509) && (ulDataLen > modulus->GetLength())))
+ {
+ return CKR_DATA_LEN_RANGE;
+ }
+
+ u1Array* dataToVerify = NULL_PTR;
+
+ if(session->IsDigestRSAVerificationActive() == CK_TRUE){
+ // require hashing also
+ CK_BYTE_PTR hash = NULL_PTR;
+ CDigest* digest = session->_digestRSAVerification;
+
+ hash = (CK_BYTE_PTR)malloc(digest->HashLength());
+
+ digest->HashCore(pData,0,ulDataLen);
+ digest->HashFinal(hash);
+
+ dataToVerify = new u1Array(digest->HashLength());
+ dataToVerify->SetBuffer(hash);
+
+ free(hash);
+ }
+ // Sign Only
+ else {
+ dataToVerify = new u1Array(ulDataLen);
+ dataToVerify->SetBuffer(pData);
+ }
+
+ u1Array* signature = new u1Array(ulSignatureLen);
+ signature->SetBuffer(pSignature);
+
+ rv = pSlot->_token->Verify(session->_verification->GetObject(),dataToVerify,session->_verification->GetMechanism(),signature);
+
+ delete signature;
+
+ session->RemoveDigestRSAVerification();
+ session->RemoveVerificationOperation();
+
+ delete dataToVerify;
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::VerifyUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)
+{
+
+ // what we do here is to update the hash or
+ // if hashing is not getting used we just accumulate it
+
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+
+ if(session->IsVerificationActive() == CK_FALSE){
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ if(pPart == NULL_PTR || ulPartLen == 0){
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ if(session->IsDigestRSAVerificationActive() == CK_TRUE){
+ CDigest* digest = session->_digestRSAVerification;
+ digest->HashCore(pPart,0,ulPartLen);
+ }
+ // Sign Only
+ else {
+
+ if(session->_accumulatedDataToVerify != NULL_PTR){
+ // just accumulate the data
+ u1Array* updatedData = new u1Array(session->_accumulatedDataToVerify->GetLength() + ulPartLen);
+ memcpy(updatedData->GetBuffer(),session->_accumulatedDataToVerify->GetBuffer(),session->_accumulatedDataToVerify->GetLength());
+
+ memcpy((u1*)&updatedData->GetBuffer()[session->_accumulatedDataToVerify->GetLength()],pPart,ulPartLen);
+
+ delete session->_accumulatedDataToVerify;
+
+ session->_accumulatedDataToVerify = updatedData;
+ }else{
+
+ session->_accumulatedDataToVerify = new u1Array(ulPartLen);
+ session->_accumulatedDataToVerify->SetBuffer(pPart);
+ }
+
+ CK_ULONG mech = session->_verification->GetMechanism();
+ u1Array* modulus = ((RSAPublicKeyObject*)session->_verification->GetObject())->_modulus;
+
+ if(((mech == CKM_RSA_PKCS) && (session->_accumulatedDataToVerify->GetLength() > modulus->GetLength() - 11)) ||
+ ((mech == CKM_RSA_X_509) && (session->_accumulatedDataToVerify->GetLength() > modulus->GetLength())))
+ {
+ return CKR_DATA_LEN_RANGE;
+ }
+ }
+
+ return rv;
+}
+
+
+/*
+*/
+CK_RV Slot::VerifyFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)
+{
+ CK_SESSION_HANDLE hSessionId = CK_INVALID_HANDLE;
+ Slot* pSlot = NULL_PTR;
+ CK_RV rv = GetSlotAndSessionIdFromSessionHandle( hSession, &pSlot, &hSessionId );
+ if(rv != CKR_OK)
+ {
+ return rv;
+ }
+ checkConnection( pSlot );
+
+ CHECK_IF_TOKEN_IS_PRESENT( pSlot );
+ CHECK_IF_NULL_SESSION( pSlot, hSessionId );
+ Transaction trans( pSlot );
+
+ Session* session = pSlot->_sessions[ hSessionId ];
+
+
+ if(session->IsVerificationActive() == CK_FALSE){
+ return CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ if((pSignature == NULL_PTR) || (ulSignatureLen == 0)){
+ return CKR_ARGUMENTS_BAD;
+ }
+
+ //StorageObject* object = session->_verification->GetObject();
+ //PKCS11_ASSERT(object->_class == CKO_PUBLIC_KEY);
+
+ u1Array* dataToVerify = NULL_PTR;
+
+ if(session->IsDigestRSAVerificationActive() == CK_TRUE){
+ // require hashing also
+ CK_BYTE_PTR hash = NULL_PTR;
+ CDigest* digest = session->_digestRSAVerification;
+
+ hash = (CK_BYTE_PTR)malloc(digest->HashLength());
+
+ digest->HashFinal(hash);
+
+ dataToVerify = new u1Array(digest->HashLength());
+ dataToVerify->SetBuffer(hash);
+
+ free(hash);
+ }
+ // Sign Only
+ else {
+ dataToVerify = session->_accumulatedDataToVerify;
+ }
+
+ u1Array* signature = new u1Array(ulSignatureLen);
+ signature->SetBuffer(pSignature);
+
+ rv = pSlot->_token->Verify(session->_verification->GetObject(),dataToVerify,session->_verification->GetMechanism(),signature);
+
+ session->RemoveDigestRSAVerification();
+ session->RemoveVerificationOperation();
+
+ delete dataToVerify;
+ delete signature;
+ session->_accumulatedDataToVerify = NULL_PTR;
+
+ return rv;
+}
+
+
+
+// --------------
+
+
+
+/* Return true if the connection is aware
+*/
+/*bool*/ void Slot::checkConnection( Slot* a_pSlot )
+{
+ Log::begin( "Slot::checkConnection" );
+
+ //bool bRet = false;
+
+ if( NULL_PTR != a_pSlot )
+ {
+ char readers[ 1024 ];
+ memset( readers, 0, sizeof( readers ) );
+ memcpy( readers, a_pSlot->_readerName->c_str( ), a_pSlot->_readerName->length( ) );
+ DWORD dwLen = sizeof( readers );
+ DWORD dwState = 0;
+ DWORD dwProtocol = 0;
+ BYTE Atr[32];
+ memset( Atr, 0, sizeof( Atr ) );
+ DWORD dwLenAtr = sizeof( Atr );
+ if( NULL != a_pSlot->_token )
+ {
+ CardModuleService* pMSCM = a_pSlot->_token->GetMiniDriverService( );
+ if( NULL != pMSCM )
+ {
+ SCARDHANDLE hCard = pMSCM->GetPcscCardHandle( );
+ DWORD hResult = SCardStatus( hCard, readers, &dwLen, &dwState, &dwProtocol, &Atr[0], &dwLenAtr );
+ Log::log( "Slot::checkConnection - SCardStatus <%#02x>", hResult );
+ if( ( SCARD_W_RESET_CARD == hResult ) || ( SCARD_W_REMOVED_CARD == hResult ) )
+ {
+ Log::error( "Slot::checkConnection", "Connection is broken" );
+
+ // Close all session
+ a_pSlot->CloseAllSessions( );
+
+ // Rebuild the token to restablish the CardModule communication
+ delete a_pSlot->_token;
+ a_pSlot->_token = NULL_PTR;
+ a_pSlot->BuildToken( );
+
+ // bRet = false;
+ }
+ }
+ }
+ }
+
+ Log::end( "Slot::checkConnection" );
+
+ //return bRet;
+}
+
+
+CK_LONG Slot::AddSession(Session* session)
+{
+ // 0 is an invalid session handle
+ for(size_t i=1;i<_sessions.size();i++){
+ if(this->_sessions[i] == NULL_PTR){
+ this->_sessions[i] = session;
+ session->UpdateState(this->_token->_roleLogged);
+ return (CK_LONG)i;
+ }
+ }
+
+ // No free elements, add a new
+ _sessions.push_back(session);
+ return (CK_LONG)(_sessions.size()-1);
+}
+
+
+/*
+*/
+void Slot::RemoveSession( CK_LONG sessionId )
+{
+ delete this->_sessions[ sessionId ];
+ this->_sessions[sessionId] = NULL_PTR;
+
+ // If this was the upper element in the vector, reduce size
+ size_t maxId = 0;
+ for( size_t i = 1 ; i < _sessions.size( ) ; i++ )
+ {
+ if( _sessions[ i ] )
+ {
+ maxId = i;
+ }
+ }
+ if( maxId < _sessions.size( ) - 1 )
+ {
+ _sessions.resize( maxId + 1 );
+ }
+
+ // if this was the last session to be removed
+ // then the login state of token for application
+ // returns to public sessions
+ if( 0 == maxId )
+ {
+ // TBD : Should I call logout here or merely set the flag ?
+ // if I logged the user out from this application
+ // what happens to another application
+ // This is where on-card implementation helps
+
+ PKCS11_ASSERT(this->_token != NULL_PTR);
+
+ this->_token->_roleLogged = CKU_NONE;
+ }
+}
+
+void Slot::UpdateSessionState()
+{
+ // update the state of all sessions
+ for(size_t i=1;i<_sessions.size();i++){
+ if(this->_sessions[i] != NULL_PTR){
+ this->_sessions[i]->UpdateState(this->_token->_roleLogged);
+ }
+ }
+}
+
+CK_BBOOL Slot::HasReadOnlySession()
+{
+ for(size_t i=1;i<_sessions.size();i++){
+ if(this->_sessions[i] != NULL_PTR){
+ if(this->_sessions[i]->_isReadWrite == CK_FALSE){
+ return CK_TRUE;
+ }
+ }
+ }
+
+ return CK_FALSE;
+}
+
+CK_RV Slot::GetSlotAndSessionIdFromSessionHandle(CK_SESSION_HANDLE hSession,
+ Slot** slot,
+ CK_ULONG_PTR sessionId)
+{
+ CK_SLOT_ID slotId = GET_SLOTID(hSession);
+ *sessionId = GET_SESSIONID(hSession);
+
+ if(((int)slotId < 0) || (slotId >= CONFIG_MAX_SLOT)){
+ // we return here invalid session handle as
+ // app does not have a notion of slot at this time
+ return CKR_SESSION_HANDLE_INVALID;
+ }
+
+ if (Application::_slotCache[slotId] != NULL_PTR){
+ *slot = Application::_slotCache[slotId];
+
+ if((*sessionId < 1) || (*sessionId >= ((*slot)->_sessions.size()))){
+ return CKR_SESSION_HANDLE_INVALID;
+ }
+ if((*slot)->_sessions[*sessionId]) {
+ return CKR_OK;
+ }
+ }
+
+ return CKR_SESSION_HANDLE_INVALID;
+}
+
+CK_RV Slot::BuildToken(void)
+{
+ Log::begin( "Slot::BuildToken" );
+
+ if(this->_token == NULL_PTR)
+ {
+ SCARD_READERSTATE readerStates;
+ memset( &readerStates, 0, sizeof( SCARD_READERSTATE ) );
+ readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+ readerStates.szReader = this->_readerName->c_str( );
+
+#ifndef _XCL_
+
+ if( SCardGetStatusChange(Application::_hContext, 0, &readerStates, 1) == SCARD_S_SUCCESS)
+ {
+ if ((readerStates.dwEventState & SCARD_STATE_PRESENT) != SCARD_STATE_PRESENT)
+ {
+ // we not found a card in this reader
+ this->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+ Log::log( "Slot::BuildToken - ((readerStates.dwEventState & SCARD_STATE_PRESENT) != SCARD_STATE_PRESENT)" );
+ Log::logCK_RV( "Slot::BuildToken", CKR_TOKEN_NOT_PRESENT );
+ return CKR_TOKEN_NOT_PRESENT;
+ }
+ else
+ {
+ // we found a card in this reader
+ this->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+ }
+ }
+
+#else // _XCL_
+
+ if (xCL_IsTokenPresent())
+ {
+ // we found a card in this reader
+ this->_slotInfo.flags |= CKF_TOKEN_PRESENT;
+ }
+ else
+ {
+ // we not found a card in this reader
+ this->_slotInfo.flags &= ~CKF_TOKEN_PRESENT;
+ return CKR_TOKEN_NOT_PRESENT;
+ }
+
+#endif // _XCL_
+
+ // TBD: Check if token is a .net smart card
+
+ // token is present in the slot
+ Log::log( "Slot::BuildToken - new Token..." );
+ this->_token = new Token( this->_readerName );
+ Log::log( "Slot::BuildToken - new Token ok" );
+
+ Log::logCK_RV( "Slot::BuildToken", CKR_OK );
+ Log::end( "Slot::BuildToken" );
+ }
+
+ return CKR_OK;
+}
+
+
+CK_RV Slot::IsValidMechanism(CK_ULONG mechanism,CK_ULONG operation)
+{
+ size_t i = 0;
+
+ CK_BBOOL found = CK_FALSE;
+
+ for(;i<sizeof(MechanismList)/sizeof(CK_ULONG);i++){
+ if(MechanismList[i] == mechanism){
+ found = CK_TRUE;
+ break;
+ }
+ }
+
+ if(found == CK_FALSE){
+ return CKR_MECHANISM_INVALID;
+ }
+
+ if((MechanismInfo[i].flags & operation) != operation){
+ return CKR_MECHANISM_INVALID;
+ }
+
+ return CKR_OK;
+}
+
+CK_RV Slot::IsValidCryptoOperation(StorageObject* object,CK_ULONG operation)
+{
+ // Check if key is consistent
+ switch(operation)
+ {
+ case CKF_ENCRYPT:
+ case CKF_VERIFY:
+ case CKF_VERIFY_RECOVER:
+ if(object->_class != CKO_PUBLIC_KEY && object->_class != CKO_SECRET_KEY){
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ break;
+
+ case CKF_DECRYPT:
+ case CKF_SIGN:
+ case CKF_SIGN_RECOVER:
+ if(object->_class != CKO_PRIVATE_KEY && object->_class != CKO_SECRET_KEY){
+ return CKR_KEY_TYPE_INCONSISTENT;
+ }
+ break;
+ }
+
+ // Check if key supports the operation
+ switch(operation)
+ {
+ case CKF_ENCRYPT:
+ if(((object->_class == CKO_PUBLIC_KEY)&&(!((RSAPublicKeyObject*)object)->_encrypt))
+#ifdef ENABLE_SYMMETRIC
+ ||((object->_class == CKO_SECRET_KEY)&&(!((SecretKeyObject*)object)->_encrypt))
+#endif
+ ){
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ break;
+
+ case CKF_DECRYPT:
+ if(((object->_class == CKO_PRIVATE_KEY)&&(!((RSAPrivateKeyObject*)object)->_decrypt))
+#ifdef ENABLE_SYMMETRIC
+ ||((object->_class == CKO_SECRET_KEY)&&(!((SecretKeyObject*)object)->_decrypt))
+#endif
+ ){
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ break;
+
+ case CKF_VERIFY:
+ if(((object->_class == CKO_PUBLIC_KEY)&&(!((RSAPublicKeyObject*)object)->_verify))
+#ifdef ENABLE_SYMMETRIC
+ ||((object->_class == CKO_SECRET_KEY)&&(!((SecretKeyObject*)object)->_verify))
+#endif
+ ){
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ break;
+
+
+ case CKF_VERIFY_RECOVER:
+ if(((object->_class == CKO_PUBLIC_KEY)&&(!((RSAPublicKeyObject*)object)->_verifyRecover))){
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ break;
+
+
+ case CKF_SIGN:
+ if(((object->_class == CKO_PRIVATE_KEY)&&(!((RSAPrivateKeyObject*)object)->_sign))
+#ifdef ENABLE_SYMMETRIC
+ ||((object->_class == CKO_SECRET_KEY)&&(!((SecretKeyObject*)object)->_sign))
+#endif
+ ){
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ break;
+
+ case CKF_SIGN_RECOVER:
+ if(((object->_class == CKO_PRIVATE_KEY)&&(!((RSAPrivateKeyObject*)object)->_signRecover))){
+ return CKR_KEY_FUNCTION_NOT_PERMITTED;
+ }
+ break;
+
+ }
+
+ return CKR_OK;
+}
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/slot.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,413 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_slot_h
+#define _include_slot_h
+
+#include "sctoken.h"
+#include "critsect.h"
+
+#ifdef _XCL_
+#include "xcl_public.h"
+#include <xcl_utils.h>
+#endif // _XCL
+
+class CardMonitoringThread;
+
+class Slot {
+
+public:
+ CK_SLOT_ID _slotId;
+ CK_SLOT_INFO _slotInfo;
+ std::string* _readerName;
+ CK_BBOOL _event;
+ CardMonitoringThread* _tracker;
+ vector<Session*> _sessions;
+ Token* _token;
+
+private:
+ CK_LONG AddSession(Session* session);
+ void RemoveSession(CK_LONG sessionId);
+ CK_BBOOL HasReadOnlySession();
+ static /*bool*/ void checkConnection( Slot* a_pSlot );
+
+public:
+ Slot();
+ virtual ~Slot();
+
+ void UpdateSessionState();
+ void UpdateAuthenticationState( void );
+
+ static void ClearCache(void);
+ static CK_RV GetSlotAndSessionIdFromSessionHandle(CK_SESSION_HANDLE hSession,
+ Slot** slot,CK_ULONG_PTR sessionId);
+
+ static CK_RV IsValidMechanism(CK_ULONG mechanism,CK_ULONG operation);
+ static CK_RV IsValidCryptoOperation(StorageObject* object,CK_ULONG operation);
+
+ CK_BBOOL GetEvent();
+ void SetEvent(CK_BBOOL event);
+ CK_SLOT_ID GetSlotId() { return _slotId;}
+ CK_BBOOL IsCardPresent() { return ((_slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT);}
+ void Clear(void);
+
+ CK_RV BuildToken(void);
+
+ CK_RV GetInfo(CK_SLOT_INFO_PTR pInfo);
+ CK_RV GetTokenInfo(CK_TOKEN_INFO_PTR pInfo);
+ CK_RV GetMechanismList(CK_MECHANISM_TYPE_PTR pMechanismList,CK_ULONG_PTR pulCount);
+ CK_RV GetMechanismInfo(CK_MECHANISM_TYPE type,CK_MECHANISM_INFO_PTR pInfo);
+ CK_RV OpenSession(CK_FLAGS flags,CK_VOID_PTR pApplication,CK_NOTIFY Notify,CK_SESSION_HANDLE_PTR phSession);
+ static CK_RV CloseSession(CK_SESSION_HANDLE hSession);
+ CK_RV CloseAllSessions(void);
+ static CK_RV GetSessionInfo(CK_SESSION_HANDLE hSession,CK_SESSION_INFO_PTR pInfo);
+
+ static CK_RV Login(CK_SESSION_HANDLE hSession,CK_USER_TYPE userType,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen);
+ static CK_RV Logout(CK_SESSION_HANDLE hSession);
+
+ CK_RV InitToken(CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen,CK_UTF8CHAR_PTR pLabel);
+ static CK_RV InitPIN(CK_SESSION_HANDLE hSession,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen);
+ static CK_RV SetPIN(CK_SESSION_HANDLE hSession,CK_UTF8CHAR_PTR pOldPin,CK_ULONG ulOldLen,
+ CK_UTF8CHAR_PTR pNewPin,CK_ULONG ulNewLen);
+
+ static CK_RV CreateObject(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phObject);
+ static CK_RV DestroyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject);
+ static CK_RV GetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+ static CK_RV SetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+ static CK_RV FindObjectsInit(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+ static CK_RV FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,CK_ULONG ulMaxObjectCount,CK_ULONG_PTR pulObjectCount);
+ static CK_RV FindObjectsFinal(CK_SESSION_HANDLE hSession);
+
+ static CK_RV GenerateRandom(CK_SESSION_HANDLE hSession,CK_BYTE_PTR RandomData,CK_ULONG ulRandomLen);
+
+ static CK_RV GenerateKeyPair(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPublicKey,CK_OBJECT_HANDLE_PTR phPrivateKey);
+
+ //static CK_RV WrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,
+ // CK_OBJECT_HANDLE hWrappingKey,CK_OBJECT_HANDLE hKey,
+ // CK_BYTE_PTR pWrappedKey,CK_ULONG_PTR pulWrappedKeyLen);
+
+ //static CK_RV UnwrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,
+ // CK_OBJECT_HANDLE hUnwrappingKey,CK_BYTE_PTR pWrappedKey,
+ // CK_ULONG ulWrappedKeyLen,CK_ATTRIBUTE_PTR pTemplate,
+ // CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey);
+
+ static CK_RV EncryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey);
+ static CK_RV Encrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pEncryptedData,CK_ULONG_PTR pulEncryptedDataLen);
+
+ static CK_RV DecryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey);
+ static CK_RV Decrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen);
+
+ static CK_RV SignInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey);
+ static CK_RV Sign(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen);
+ static CK_RV SignUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen);
+ static CK_RV SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen);
+
+ static CK_RV VerifyInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey);
+ static CK_RV Verify(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen);
+ static CK_RV VerifyUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen);
+ static CK_RV VerifyFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen);
+ //static CK_RV VerifyRecoverInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey);
+ //static CK_RV VerifyRecover(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen);
+
+ static CK_RV DigestInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism);
+ static CK_RV Digest(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen);
+ static CK_RV DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen);
+ static CK_RV DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen);
+};
+
+#define CARD_PRESENT 1
+#define CARD_ABSENT 2
+
+#define CARD_DETECTION_INSERTED 1
+#define CARD_DETECTION_REMOVED 2
+
+
+#ifdef INCLUDE_EVENTING
+
+extern CCriticalSection _critSect;
+
+class CardMonitoringThread : public CThread
+{
+
+private:
+ CK_BYTE m_bCardState;
+ Slot* m_slot;
+ SCARDCONTEXT m_hMonitoringContext;
+
+public:
+ // CThread override
+ void stop()
+ {
+ //printf( "%s - %d - %s - m_monitoringContext <%ld>\n", __FILE__, __LINE__, __FUNCTION__, m_hMonitoringContext );
+
+#ifndef _XCL_
+
+ if( 0 != m_hMonitoringContext )
+ {
+ SCardCancel(m_hMonitoringContext);
+ //printf( "%s - %d - %s - SCardCancel\n", __FILE__, __LINE__, __FUNCTION__);
+
+ /*
+ printf( "%s - %d - %s - SCardReleaseContext -->\n", __FILE__, __LINE__, __FUNCTION__);
+ SCardReleaseContext(m_hMonitoringContext);
+ printf( "%s - %d - %s - SCardReleaseContext <--\n", __FILE__, __LINE__, __FUNCTION__);
+ m_hMonitoringContext = 0;
+ */
+ }
+
+#endif // _XCL_
+
+ CThread::stop();
+ }
+
+ //------------------------------------------------------------------------------
+ //------------------------------------------------------------------------------
+ CardMonitoringThread(const char* nm) //: m_hMonitoringContext(0)
+ {
+ m_hMonitoringContext = 0;
+ m_bCardState = CARD_ABSENT;
+ CThread::setName(nm);
+ }
+
+ //------------------------------------------------------------------------------
+ //------------------------------------------------------------------------------
+ void SetSlot(Slot* slot)
+ {
+ m_slot = slot;
+
+ if(slot->IsCardPresent() == CK_FALSE)
+ {
+ m_bCardState = CARD_ABSENT;
+ }
+ else
+ {
+ m_bCardState = CARD_PRESENT;
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ //------------------------------------------------------------------------------
+ void run()
+ {
+ bool bTrue = true;
+ while( bTrue )
+ {
+ switch(m_bCardState)
+ {
+ case CARD_PRESENT:
+ if(Monitor(CARD_DETECTION_REMOVED) == false)
+ {
+ return;
+ }
+ m_bCardState = CARD_ABSENT;
+
+ // clean the slot, lock during session deletion
+ {
+ CCriticalSectionLocker cslock(_critSect);
+ m_slot->Clear();
+ }
+ break;
+
+ case CARD_ABSENT:
+ if(Monitor(CARD_DETECTION_INSERTED) == false)
+ {
+ return;
+ }
+ m_bCardState = CARD_PRESENT;
+ break;
+ }
+
+ // we fire the event from here
+ m_slot->SetEvent(CK_TRUE);
+ CryptokiEvent.Signal();
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ //------------------------------------------------------------------------------
+
+#ifndef _XCL_
+
+ bool Monitor(BYTE detectionType)
+ {
+
+ // establish monitoring context
+ LONG lReturn = SCardEstablishContext( SCARD_SCOPE_USER, NULL, NULL, &m_hMonitoringContext );
+ //printf( "%s - %d - %s - SCardEstablishContext --> m_hMonitoringContext <%ld>\n", __FILE__, __LINE__, __FUNCTION__, m_hMonitoringContext);
+
+ //LONG lReturn = SCardEstablishContext(0, NULL, NULL, (LPSCARDCONTEXT)&m_monitoringContext);
+
+ if(lReturn != SCARD_S_SUCCESS)
+ {
+ return false;
+ }
+
+ SCARD_READERSTATE readerStates;
+ readerStates.dwCurrentState = SCARD_STATE_UNAWARE;
+ readerStates.szReader = this->getName()->c_str();
+ readerStates.pvUserData = NULL;
+ readerStates.dwEventState = 0; // TO INSPECT THIS STATE
+
+ bool bTrue = true;
+ while( bTrue )
+ {
+
+ if((lReturn = SCardGetStatusChange( m_hMonitoringContext, 60*1000, &readerStates, 1 )) != SCARD_S_SUCCESS)
+ {
+ if(lReturn == (LONG)SCARD_E_TIMEOUT)
+ {
+ if(this->isStopRequested() == CK_TRUE)
+ {
+ SCardReleaseContext(m_hMonitoringContext);
+ //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+ m_hMonitoringContext = 0;
+ return false;
+ }
+
+ goto resume;
+ }
+
+ SCardReleaseContext(m_hMonitoringContext);
+ //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+ m_hMonitoringContext = 0;
+ return false;
+ }
+
+resume:
+ if((readerStates.dwEventState & SCARD_STATE_CHANGED) == SCARD_STATE_CHANGED)
+ {
+ if((readerStates.dwEventState & SCARD_STATE_UNAVAILABLE) == SCARD_STATE_UNAVAILABLE)
+ {
+ // reader removed
+ SCardReleaseContext(m_hMonitoringContext);
+ //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+ m_hMonitoringContext = 0;
+ return true;
+ }
+ else if(((readerStates.dwCurrentState & SCARD_STATE_EMPTY) == SCARD_STATE_EMPTY) &&
+ ((readerStates.dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT))
+ {
+ if(detectionType == CARD_PRESENT)
+ {
+ // card is inserted
+ SCardReleaseContext(m_hMonitoringContext);
+ //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+ m_hMonitoringContext = 0;
+ return true;
+ }
+ }
+ else if(((readerStates.dwCurrentState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT) &&
+ ((readerStates.dwEventState & SCARD_STATE_EMPTY) == SCARD_STATE_EMPTY))
+ {
+ if(detectionType == CARD_ABSENT)
+ {
+ // card is removed
+ SCardReleaseContext(m_hMonitoringContext);
+ //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+ m_hMonitoringContext = 0;
+ return true;
+ }
+ }
+ }
+
+ readerStates.dwCurrentState = readerStates.dwEventState ;
+ }
+
+ SCardReleaseContext(m_hMonitoringContext);
+ //printf( "%s - %d - %s - SCardReleaseContext\n", __FILE__, __LINE__, __FUNCTION__ );
+ m_hMonitoringContext = 0;
+ return false;
+ }
+
+#else // _XCL_
+
+ bool Monitor(BYTE detectionType)
+ {
+ BOOL initialTokenPresent;
+ BOOL currentTokenPresent;
+ UINT rv;
+ UINT deviceID2;
+ xCL_DeviceHandle deviceHandle2;
+
+ PRINT_MSG("IN Monitor top");
+
+ initialTokenPresent = false;
+ currentTokenPresent = false;
+
+ deviceHandle2 = 0;
+ deviceID2 = 0;
+ rv = xCL_CreateHandleFromDeviceID(deviceID2, &deviceHandle2);
+ if (rv == 0)
+ {
+ initialTokenPresent = true;
+ currentTokenPresent = true;
+ }
+ rv = xCL_CloseHandle(deviceHandle2);
+
+ while(true)
+ {
+ PRINT_MSG("IN Monitor loop");
+
+ // sleep for some time
+ sleep(500);
+
+ // See if token is present now
+ deviceHandle2 = 0;
+ deviceID2 = 0;
+ rv = xCL_CreateHandleFromDeviceID(deviceID2, &deviceHandle2);
+ if (rv == 0)
+ {
+ currentTokenPresent = true;
+ rv = xCL_CloseHandle(deviceHandle2);
+ }
+ else
+ {
+ currentTokenPresent = false;
+ }
+
+ if (initialTokenPresent == currentTokenPresent)
+ {
+ PRINT_MSG("IN Monitor no change");
+
+ // No change in token state
+ if(this->isStopRequested() == CK_TRUE)
+ {
+ PRINT_MSG("IN Monitor no change exit");
+ return false;
+ }
+ }
+ else
+ {
+ PRINT_MSG("IN Monitor yes change");
+ // There is a change ...
+ return true;
+ }
+ }
+ }
+
+#endif // _XCL_
+
+};
+#endif
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,41 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+
+// Determine Processor Endianess
+#include <limits.h>
+#if (UINT_MAX == 0xffffffffUL)
+ typedef unsigned int _u4;
+#else
+# if (ULONG_MAX == 0xffffffffUL)
+ typedef unsigned long _u4;
+# else
+# if (USHRT_MAX == 0xffffffffUL)
+ typedef unsigned short _u4;
+# endif
+# endif
+#endif
+
+_u4 endian = 1;
+
+bool IS_LITTLE_ENDIAN = (*((unsigned char *)(&endian))) ? true : false;
+bool IS_BIG_ENDIAN = (*((unsigned char *)(&endian))) ? false : true;
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/stdafx.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,50 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_stadfx_h
+#define _include_stadfx_h
+
+#ifdef WIN32
+ #include <windows.h>
+ #include <wincrypt.h>
+ #include <assert.h>
+#else
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #ifdef __APPLE__
+ #include <wintypes.h>
+ #endif
+ #include <winscard.h>
+ typedef BYTE *PBYTE;
+#ifndef HAVE_LPCTSTR
+ typedef const char *LPCTSTR;
+#endif
+#ifndef HAVE_LPCSTR
+ typedef LPCTSTR LPCSTR;
+#endif
+
+#endif
+
+extern bool IS_BIG_ENDIAN;
+extern bool IS_LITTLE_ENDIAN;
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,373 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+#include "storageobject.h"
+#include "error.h"
+
+StorageObject::StorageObject()
+{
+ this->_version = 0;
+ this->_uniqueId = 0;
+ this->_tokenObject = CK_FALSE;
+ this->_private = CK_FALSE;
+ this->_modifiable = CK_TRUE;
+ this->_label = NULL_PTR;
+}
+
+StorageObject::~StorageObject(){
+
+ if(this->_label != NULL_PTR)
+ delete this->_label;
+
+}
+
+bool StorageObject::IsEqual(const StorageObject * that) const
+{
+ if(_uniqueId != 0 && that->_uniqueId != 0)
+ return (_uniqueId == that->_uniqueId);
+
+ // Only objects that have been stored under p11 directory
+ // will have a non-zero _uniqueId. For other objects, do
+ // a deep comparison based on other attributes. In the base
+ // class, only negative comparison based on _class can be performed.
+ if(_class != that->_class)
+ return false;
+ else
+ throw CkError(CKR_FUNCTION_FAILED);
+}
+
+CK_BBOOL StorageObject::Compare(CK_ATTRIBUTE attribute)
+{
+ switch(attribute.type){
+ case CKA_CLASS:
+ return (this->_class == *(CK_ULONG*)attribute.pValue);
+
+ case CKA_PRIVATE:
+ return (this->_private == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_TOKEN:
+ return (this->_tokenObject == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_MODIFIABLE:
+ return (this->_modifiable == *(CK_BBOOL*)attribute.pValue);
+
+ case CKA_LABEL:
+ if(this->_label->GetLength() == attribute.ulValueLen){
+ return Util::CompareByteArrays(this->_label->GetBuffer(),(CK_BYTE_PTR)attribute.pValue,attribute.ulValueLen);
+ }
+ return CK_FALSE;
+
+ default:
+ return CK_FALSE;
+
+ }
+}
+
+CK_RV StorageObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+ if( 0 == attribute.ulValueLen )
+ {
+ return CKR_OK;
+ }
+
+ CK_RV rv = CKR_OK;
+
+ if(objCreation == CK_FALSE){
+ switch(attribute.type){
+ case CKA_CLASS:
+ case CKA_PRIVATE:
+ case CKA_TOKEN:
+ case CKA_MODIFIABLE:
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ switch(attribute.type){
+ case CKA_CLASS:
+ break;
+
+ case CKA_PRIVATE:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_private = btemp; }
+ }
+ break;
+
+ case CKA_TOKEN:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_tokenObject = btemp; }
+ }
+ break;
+
+ case CKA_MODIFIABLE:
+ {
+ CK_BBOOL btemp = StorageObject::ReadBBoolFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){ this->_modifiable = btemp; }
+ }
+ break;
+
+ case CKA_LABEL:
+ {
+ u1Array* stemp = StorageObject::ReadStringFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){
+ if(this->_label != NULL_PTR){
+ delete this->_label;
+ }
+ this->_label = stemp;
+ }
+ }
+ break;
+
+ default:
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+
+ }
+
+ return rv;
+}
+
+CK_RV StorageObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+ CK_RV ulRet = CKR_OK;
+
+ switch(attribute->type)
+ {
+ case CKA_CLASS:
+ ulRet = StorageObject::PutULongInAttribute(this->_class,attribute);
+ break;
+
+ case CKA_PRIVATE:
+ ulRet = StorageObject::PutBBoolInAttribute(this->_private,attribute);
+ break;
+
+ case CKA_TOKEN:
+ ulRet = StorageObject::PutBBoolInAttribute(this->_tokenObject,attribute);
+ break;
+
+ case CKA_MODIFIABLE:
+ ulRet = StorageObject::PutBBoolInAttribute(this->_modifiable,attribute);
+ break;
+
+ case CKA_LABEL:
+ ulRet = StorageObject::PutU1ArrayInAttribute(this->_label,attribute);
+ break;
+
+ default:
+ attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+ ulRet = CKR_ATTRIBUTE_TYPE_INVALID;
+ break;
+ }
+
+ return ulRet;
+}
+
+void StorageObject::Serialize(std::vector<u1>* to)
+{
+ // serialize format version
+ Util::PushBBoolInVector(to,this->_version);
+
+ // serialize unique id
+ Util::PushULongLongInVector(to,this->_uniqueId);
+
+ // serialize class attribute
+ Util::PushULongInVector(to,this->_class);
+
+ // serialize private attribute
+ Util::PushBBoolInVector(to,this->_private);
+
+ // serialize token attribute
+ Util::PushBBoolInVector(to,this->_tokenObject);
+
+ // serialize modifiable attribute
+ Util::PushBBoolInVector(to,this->_modifiable);
+
+ // serialize label attribute
+ Util::PushByteArrayInVector(to,this->_label);
+}
+
+void StorageObject::Deserialize(std::vector<u1> from,CK_ULONG_PTR idx)
+{
+ this->_version = Util::ReadBBoolFromVector(from,idx);
+
+ this->_uniqueId = Util::ReadULongLongFromVector(from, idx);
+
+ this->_class = Util::ReadULongFromVector(from,idx);
+
+ this->_private = Util::ReadBBoolFromVector(from,idx);
+
+ this->_tokenObject = Util::ReadBBoolFromVector(from,idx);
+
+ this->_modifiable = Util::ReadBBoolFromVector(from,idx);
+
+ this->_label = Util::ReadByteArrayFromVector(from,idx);
+}
+
+CK_RV StorageObject::PutU1ArrayInAttribute(u1Array* value,CK_ATTRIBUTE_PTR attribute)
+{
+ if(attribute->pValue == NULL_PTR){
+ if(value == NULL_PTR){
+ attribute->ulValueLen = 0;
+ }else{
+ attribute->ulValueLen = value->GetLength();
+ }
+ return CKR_OK;
+ }
+ if(value == NULL_PTR){
+ // I am not sure about it (TBD: Check)
+ attribute->ulValueLen = 0;
+ return CKR_OK;
+ }
+ if(attribute->ulValueLen < value->GetLength()){
+ attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ attribute->ulValueLen = value->GetLength();
+ memcpy((CK_BYTE_PTR)attribute->pValue,value->GetBuffer(),attribute->ulValueLen);
+
+ return CKR_OK;
+}
+
+CK_RV StorageObject::PutU4ArrayInAttribute(u4Array* value,CK_ATTRIBUTE_PTR attribute)
+{
+ if(attribute->pValue == NULL_PTR){
+ if(value == NULL_PTR){
+ attribute->ulValueLen = 0;
+ }else{
+ attribute->ulValueLen = (value->GetLength() * 4);
+ }
+ return CKR_OK;
+ }
+ if(value == NULL_PTR){
+ // I am not sure about it (TBD: Check)
+ attribute->ulValueLen = 0;
+ return CKR_OK;
+ }
+ if(attribute->ulValueLen < (value->GetLength() * 4)){
+ attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+
+ attribute->ulValueLen = value->GetLength() * 4;
+ memcpy((CK_BYTE_PTR)attribute->pValue,(u1*)value->GetBuffer(),attribute->ulValueLen);
+
+ return CKR_OK;
+}
+
+CK_RV StorageObject::PutBBoolInAttribute(CK_BBOOL value, CK_ATTRIBUTE_PTR attribute)
+{
+ if(attribute->pValue == NULL_PTR){
+ attribute->ulValueLen = sizeof(CK_BBOOL);
+ return CKR_OK;
+ }
+ if(attribute->ulValueLen < sizeof(CK_BBOOL)){
+ attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ attribute->ulValueLen = sizeof(CK_BBOOL);
+ *(CK_BBOOL*)attribute->pValue = value;
+
+ return CKR_OK;
+}
+
+CK_RV StorageObject::PutULongInAttribute(CK_ULONG value, CK_ATTRIBUTE_PTR attribute)
+{
+ if(attribute->pValue == NULL_PTR){
+ attribute->ulValueLen = sizeof(CK_ULONG);
+ return CKR_OK;
+ }
+ if(attribute->ulValueLen < sizeof(CK_ULONG)){
+ attribute->ulValueLen = CK_UNAVAILABLE_INFORMATION; //(CK_LONG)-1;
+ return CKR_BUFFER_TOO_SMALL;
+ }
+ attribute->ulValueLen = sizeof(CK_ULONG);
+ *(CK_ULONG*)attribute->pValue = value;
+
+ return CKR_OK;
+}
+
+CK_ULONG StorageObject::ReadULongFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv)
+{
+ if(attribute.ulValueLen != sizeof(CK_ULONG)){
+ *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+ return 0;
+ }
+
+ return *(CK_ULONG*)attribute.pValue;
+}
+
+CK_BBOOL StorageObject::ReadBBoolFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv)
+{
+ if(attribute.ulValueLen != sizeof(CK_BBOOL)){
+ *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+ return 0;
+ }
+
+ CK_BBOOL val = *(CK_BBOOL*)attribute.pValue;
+
+ if(val != 0x00 && val != 0x01){
+ *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+ return 0;
+ }
+
+ return val;
+}
+
+u1Array* StorageObject::ReadU1ArrayFromAttribute(CK_ATTRIBUTE attribute)
+{
+ u1Array* val = new u1Array(attribute.ulValueLen);
+ val->SetBuffer((CK_BYTE_PTR)attribute.pValue);
+
+ return val;
+}
+
+u1Array* StorageObject::ReadDateFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv)
+{
+ if(attribute.ulValueLen != 8){
+ *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+ return NULL_PTR;
+ }
+
+ return StorageObject::ReadU1ArrayFromAttribute(attribute);
+}
+
+u1Array* StorageObject::ReadStringFromAttribute(CK_ATTRIBUTE attribute,CK_RV* /*rv*/)
+{
+
+ // [HB]: Shall support UTF-8
+
+ //for(u4 i=0;i<attribute.ulValueLen;i++){
+
+ // CK_BYTE bval = ((CK_BYTE_PTR)attribute.pValue)[i];
+
+ // if((bval < 0x20)||(bval > 0x7D)||(bval == 0x24)||(bval == 0x40)||(bval == 0x60)){
+ // *rv = CKR_ATTRIBUTE_VALUE_INVALID;
+ // return NULL_PTR;
+ // }
+ //}
+
+ return StorageObject::ReadU1ArrayFromAttribute(attribute);
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/storageobject.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,74 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_storageobject_h
+#define _include_storageobject_h
+
+#include <string>
+#include <MarshallerCfg.h>
+#include <Array.h>
+#include <vector>
+
+using namespace std;
+using namespace Marshaller;
+
+class StorageObject {
+
+
+public:
+ CK_BBOOL _version; // Version is used to manage evolution of the storage.
+ u8 _uniqueId; // A random number that identifies this object
+ CK_ULONG _class;
+ CK_BBOOL _tokenObject;
+ CK_BBOOL _private;
+ CK_BBOOL _modifiable;
+ u1Array* _label;
+
+ // extra fields (not part of PKCS#11 spec
+ std::string _fileName; // name of the file in the card which contains this object
+
+ StorageObject();
+ virtual ~StorageObject();
+
+ virtual bool IsEqual(const StorageObject * that) const;
+ virtual CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+ virtual CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+ virtual CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+ virtual void Serialize(vector<u1>* to);
+ virtual void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+protected:
+ static CK_RV PutU1ArrayInAttribute(u1Array* value,CK_ATTRIBUTE_PTR attribute);
+ static CK_RV PutU4ArrayInAttribute(u4Array* value,CK_ATTRIBUTE_PTR attribute);
+ static CK_RV PutULongInAttribute(CK_ULONG value, CK_ATTRIBUTE_PTR attribute);
+ static CK_RV PutBBoolInAttribute(CK_BBOOL value, CK_ATTRIBUTE_PTR attribute);
+
+ static CK_BBOOL ReadBBoolFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv);
+ static CK_ULONG ReadULongFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv);
+ static u1Array* ReadU1ArrayFromAttribute(CK_ATTRIBUTE attribute);
+ static u1Array* ReadDateFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv);
+ static u1Array* ReadStringFromAttribute(CK_ATTRIBUTE attribute,CK_RV* rv);
+};
+
+
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,224 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "symmalgo.h"
+
+CSymmAlgo::CSymmAlgo(){
+ this->_cipherMode = CIPHER_MODE_CBC;
+ this->_paddingMode = PADDING_MODE_PKCS7;
+ this->_iv = NULL_PTR;
+ this->_key = NULL_PTR;
+}
+
+CSymmAlgo::~CSymmAlgo(){
+ if(this->_key != NULL_PTR)
+ free(this->_key);
+}
+
+void CSymmAlgo::SetKey(CK_BYTE_PTR key,CK_LONG keyLength){
+ this->_key = (CK_BYTE_PTR)malloc(keyLength);
+ this->_keyLength = keyLength;
+
+ memcpy(this->_key,key,keyLength);
+}
+
+void CSymmAlgo::SetIV(CK_BYTE_PTR iv){
+ this->_iv = iv;
+}
+
+void CSymmAlgo::SetEncryptMode(CK_LONG mode){
+ this->_encryptMode = mode;
+}
+
+void CSymmAlgo::SetCipherMode(CK_LONG cmode){
+ this->_cipherMode = cmode;
+}
+
+void CSymmAlgo::SetPaddingMode(CK_LONG pmode){
+ this->_paddingMode = pmode;
+}
+
+CK_LONG CSymmAlgo::GetOutputLength(CK_LONG input_count){
+
+ CK_LONG outputLen;
+
+ if(this->_encryptMode == ENCRYPT){
+ outputLen = input_count & -this->_blockSize;
+
+ switch(this->_paddingMode){
+
+ case PADDING_MODE_ISO9797M2:
+ case PADDING_MODE_PKCS7:
+ // atleast 1 padding byte will be needed
+ if(input_count >= outputLen){
+ outputLen += this->_blockSize;
+ }
+ break;
+
+ case PADDING_MODE_ZEROS:
+ if(input_count > outputLen){
+ outputLen += this->_blockSize;
+ }
+ break;
+
+ case PADDING_MODE_NONE:
+ outputLen = input_count;
+ break;
+ }
+ }else{
+ outputLen = input_count;
+ }
+
+ return outputLen;
+}
+
+CK_LONG CSymmAlgo::TransformBlock(CK_BYTE_PTR input,CK_LONG input_offset,CK_LONG input_count,
+ CK_BYTE_PTR output,CK_LONG output_offset)
+{
+ CK_LONG res = 0;
+ while (res != input_count)
+ {
+ TransformBlockInternal(_iv,_key,_encryptMode,input,input_offset,output,output_offset);
+
+ if (_cipherMode == CIPHER_MODE_CBC)
+ {
+ if (_encryptMode == ENCRYPT){
+ // last block of output becomes icv for next round.
+ memcpy(_iv,&output[output_offset],_blockSize);
+ }
+ else {
+ // last block of input becomes icv for next round.
+ memcpy(_iv,&input[input_offset],_blockSize);
+ }
+ }
+
+ // adjust offsets
+ input_offset += _blockSize;
+ res += _blockSize;
+ output_offset += _blockSize;
+ }
+
+ return res;
+}
+
+CK_LONG CSymmAlgo::TransformFinalBlock(CK_BYTE_PTR input,CK_LONG input_offset,CK_LONG input_count,
+ CK_BYTE_PTR output,CK_LONG output_offset)
+{
+ CK_LONG workingLength;
+
+ if (((this->_paddingMode == PADDING_MODE_NONE) ||
+ (this->_encryptMode == DECRYPT)) &&
+ (input_count % _blockSize != 0))
+ {
+ PKCS11_ASSERT(CK_FALSE);
+ }
+
+ // prepare outbuffer in case of encryption
+ if (this->_encryptMode == ENCRYPT)
+ {
+ // ~ round_down(inputCount, _blockSizeByte)
+ workingLength = input_count & -_blockSize;
+ }
+ else
+ {
+ // we're in Decrypt mode, hence workingLength is % _blockSizeByte
+ workingLength = input_count;
+ }
+
+ if (workingLength > 0)
+ {
+ // compute the workingLength length part (% _blockSizeByte)
+ TransformBlock(input,input_offset, workingLength,output,output_offset);
+
+ input_offset += workingLength;
+ output_offset += workingLength;
+ input_count -= workingLength;
+ }
+
+ if (this->_encryptMode == DECRYPT)
+ {
+ switch (this->_paddingMode)
+ {
+ case PADDING_MODE_PKCS7:
+ // check the padding value make sense
+ if (output[output_offset - 1] > _blockSize){
+ PKCS11_ASSERT(CK_FALSE);
+ }
+ workingLength -= output[output_offset - 1];
+ break;
+
+ case PADDING_MODE_ISO9797M2:
+ // remove trailing zeros
+ while (output[output_offset - 1] == 0x00){
+ workingLength--;
+ output_offset--;
+ }
+ // check initial byte is 0x80
+ if (output[output_offset - 1] != 0x80){
+ PKCS11_ASSERT(CK_FALSE);
+ }
+ workingLength--;
+ break;
+
+ // note when PaddingMode.Zeros is used, we do not remove the 0s (no way to differentiate from the actual data)
+ }
+ }
+ else
+ {
+ if ((this->_paddingMode == PADDING_MODE_PKCS7)
+ || (this->_paddingMode == PADDING_MODE_ISO9797M2)
+ || ((this->_paddingMode == PADDING_MODE_ZEROS) && (input_count > 0)))
+ {
+ CK_BYTE_PTR paddedIntput = (CK_BYTE_PTR)malloc(_blockSize);
+ memset(paddedIntput,0,_blockSize);
+
+ memcpy(paddedIntput,&input[input_offset],input_count);
+
+ // add padding information in buffer if relevant
+ switch (this->_paddingMode)
+ {
+ // set first bit to 1, all other bits already set to 0
+ case PADDING_MODE_ISO9797M2:
+ paddedIntput[input_count] = 0x80;
+ break;
+
+ case PADDING_MODE_PKCS7:
+ CK_BYTE paddingValue = (CK_BYTE)(_blockSize - input_count);
+ for (CK_LONG i = input_count; i < _blockSize; i++){
+ paddedIntput[i] = paddingValue;
+ }
+ break;
+ }
+
+ // compute last block
+ TransformBlock(paddedIntput, 0, _blockSize, output, output_offset);
+
+ workingLength += _blockSize;
+
+ free(paddedIntput);
+ }
+ }
+
+ // over, let's return.
+ return workingLength;
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/symmalgo.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,72 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_symmalgo_h
+#define _include_symmalgo_h
+
+#define PADDING_MODE_ISO9797M2 1
+#define PADDING_MODE_NONE 2
+#define PADDING_MODE_PKCS7 3
+#define PADDING_MODE_ZEROS 4
+
+#define ENCRYPT 1
+#define DECRYPT 2
+
+#define CIPHER_MODE_CBC 1
+#define CIPHER_MODE_ECB 2
+
+class CSymmAlgo
+{
+
+protected:
+ CK_BYTE_PTR _iv;
+ CK_BYTE_PTR _key;
+ CK_LONG _keyLength;
+ CK_LONG _blockSize;
+ CK_LONG _cipherMode;
+ CK_LONG _paddingMode;
+ CK_LONG _encryptMode;
+
+protected:
+ virtual void TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+ CK_BYTE_PTR input,CK_LONG input_offset,
+ CK_BYTE_PTR output,CK_LONG output_offset) = 0;
+
+public:
+ CSymmAlgo();
+ virtual ~CSymmAlgo();
+
+ void SetKey(CK_BYTE_PTR key,CK_LONG keyLength);
+ void SetIV(CK_BYTE_PTR iv);
+ void SetEncryptMode(CK_LONG mode);
+ void SetCipherMode(CK_LONG cmode);
+ void SetPaddingMode(CK_LONG pmode);
+
+ CK_LONG GetOutputLength(CK_LONG input_count);
+
+ CK_LONG TransformBlock(CK_BYTE_PTR input,CK_LONG input_offset,CK_LONG input_count,
+ CK_BYTE_PTR output,CK_LONG output_offset);
+
+ CK_LONG TransformFinalBlock(CK_BYTE_PTR input,CK_LONG input_offset,CK_LONG input_count,
+ CK_BYTE_PTR output,CK_LONG output_offset);
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,53 @@
+
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+#include "stdafx.h"
+#include "platconfig.h"
+#include "symmalgo.h"
+#include "tdes.h"
+
+CTripleDES::CTripleDES(){
+ this->_blockSize = 8;
+}
+
+CTripleDES::~CTripleDES(){
+}
+
+void CTripleDES::TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+ CK_BYTE_PTR input,CK_LONG input_offset,
+ CK_BYTE_PTR output,CK_LONG output_offset)
+{
+ // encryprtMode == ENCRYPT then we need to XOR input with iv
+ if(iv != NULL_PTR && this->_encryptMode == ENCRYPT){
+ for(CK_LONG i=0;i<8;i++){
+ input[input_offset+i] ^= iv[i];
+ }
+ }
+
+ algo_DES_3DESProcess((u1)_keyLength,key,&input[input_offset],&output[output_offset],(u1)encryptMode);
+
+ if(iv != NULL_PTR && this->_encryptMode == DECRYPT){
+ for(CK_LONG i=0;i<8;i++){
+ output[output_offset+i] ^= iv[i];
+ }
+ }
+}
+
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/tdes.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,42 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_tdes_h
+#define _include_tdes_h
+
+#include "MarshallerCfg.h"
+#include "algo_des.h"
+
+class CTripleDES : public CSymmAlgo
+{
+
+public:
+ CTripleDES();
+ ~CTripleDES();
+
+private:
+ void TransformBlockInternal(CK_BYTE_PTR iv,CK_BYTE_PTR key,CK_LONG encryptMode,
+ CK_BYTE_PTR input,CK_LONG input_offset,
+ CK_BYTE_PTR output,CK_LONG output_offset);
+
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,303 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "template.h"
+
+Template::Template(CK_ATTRIBUTE_PTR attrTemplate,CK_ULONG ulCount){
+
+
+ for(CK_ULONG i=0;i<ulCount;i++){
+ CK_ATTRIBUTE attribute;
+
+ attribute.type = attrTemplate[i].type;
+ attribute.ulValueLen = attrTemplate[i].ulValueLen;
+ attribute.pValue = NULL_PTR;
+
+ if(attribute.ulValueLen > 0) {
+ attribute.pValue = malloc(attribute.ulValueLen);
+ memcpy(attribute.pValue, attrTemplate[i].pValue, attribute.ulValueLen);
+ }
+
+ this->_attributes.push_back(attribute);
+ }
+}
+
+
+Template::~Template( )
+{
+ std::vector<CK_ATTRIBUTE>::size_type sz = _attributes.size( );
+ for( std::vector<CK_ATTRIBUTE>::size_type i = 0 ; i < sz ; i++ )
+ {
+ if( NULL_PTR != _attributes[ i ].pValue )
+ {
+ free( _attributes[ i ].pValue );
+ }
+ }
+}
+
+
+void Template::FixEndianness(CK_ATTRIBUTE attrTemplate)
+{
+ // Only for Little Endian processors
+ if (IS_LITTLE_ENDIAN)
+ {
+ // we need to fix the endianness if
+ // we are dealing with data on 2 or 4 or 8 bytes
+ switch(attrTemplate.ulValueLen)
+ {
+ case 2:
+ case 4:
+ case 8:
+ {
+ // fix up needs to be done for specific
+ // attributes. Byte arrays may have sizes of 2,4 or 8
+ switch(attrTemplate.type)
+ {
+ // CK_ULONG data types
+ case CKA_CLASS:
+ case CKA_CERTIFICATE_TYPE:
+ case CKA_JAVA_MIDP_SECURITY_DOMAIN:
+ case CKA_KEY_TYPE:
+ case CKA_KEY_GEN_MECHANISM:
+ case CKA_MODULUS_BITS:
+ {
+ PKCS11_ASSERT(attrTemplate.ulValueLen == sizeof(CK_ULONG));
+ CK_BYTE b1 = ((CK_BYTE_PTR)attrTemplate.pValue)[0];
+ CK_BYTE b2 = ((CK_BYTE_PTR)attrTemplate.pValue)[1];
+ CK_BYTE b3 = ((CK_BYTE_PTR)attrTemplate.pValue)[2];
+ CK_BYTE b4 = ((CK_BYTE_PTR)attrTemplate.pValue)[3];
+ ((CK_BYTE_PTR)attrTemplate.pValue)[3] = b1;
+ ((CK_BYTE_PTR)attrTemplate.pValue)[2] = b2;
+ ((CK_BYTE_PTR)attrTemplate.pValue)[1] = b3;
+ ((CK_BYTE_PTR)attrTemplate.pValue)[0] = b4;
+ }
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+CK_ULONG Template::FindClassFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)
+{
+ CK_ULONG idx = 0;
+
+ for(idx=0;idx<ulCount;idx++)
+ {
+ if(pTemplate[idx].type == CKA_CLASS)
+ {
+ return *(CK_ULONG*)pTemplate[idx].pValue;
+ }
+ }
+
+ return (CK_ULONG)-1;
+}
+
+CK_ULONG Template::FindCertTypeFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)
+{
+ CK_ULONG idx = 0;
+
+ for(idx=0;idx<ulCount;idx++)
+ {
+ if(pTemplate[idx].type == CKA_CERTIFICATE_TYPE)
+ {
+ return *(CK_ULONG*)pTemplate[idx].pValue;
+ }
+ }
+
+ return (CK_ULONG)-1;
+}
+
+CK_BBOOL Template::FindTokenFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)
+{
+ CK_ULONG idx = 0;
+
+ for(idx=0;idx<ulCount;idx++)
+ {
+ if(pTemplate[idx].type == CKA_TOKEN)
+ {
+ return *(CK_BBOOL*)pTemplate[idx].pValue;
+ }
+ }
+
+ return CK_FALSE;
+}
+
+CK_BBOOL Template::IsAttrInTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, CK_ATTRIBUTE_TYPE AttrType)
+{
+ CK_ULONG idx = 0;
+
+ for(idx=0;idx<ulCount;idx++)
+ {
+ if(pTemplate[idx].type == AttrType)
+ {
+ return CK_TRUE;
+ }
+ }
+
+ return CK_FALSE;
+}
+
+CK_RV Template::CheckTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, CK_BYTE bMode)
+{
+ CK_OBJECT_CLASS ObjClass = (CK_ULONG)-1;
+ CK_CERTIFICATE_TYPE CertType = (CK_ULONG)-1;
+
+ // Get Object Class
+ ObjClass = FindClassFromTemplate(pTemplate, ulCount);
+
+ // Get Cert Type
+ if (ObjClass == CKO_CERTIFICATE)
+ {
+ CertType = FindCertTypeFromTemplate(pTemplate, ulCount);
+ }
+
+ // Check Creation Template
+ if (bMode == MODE_CREATE)
+ {
+ switch (ObjClass)
+ {
+ case CKO_DATA:
+ {
+ if (IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+ {
+ return CKR_OK;
+ }
+ }
+ break;
+
+ case CKO_CERTIFICATE:
+ {
+ if (CertType == CKC_X_509)
+ {
+ if ( (IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+ &&(IsAttrInTemplate(pTemplate, ulCount, CKA_SUBJECT))
+ &&(IsAttrInTemplate(pTemplate, ulCount, CKA_VALUE))
+ )
+ {
+ return CKR_OK;
+ }
+ }
+
+ else if (CertType == CKC_X_509_ATTR_CERT)
+ {
+ if ( (IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+ &&(IsAttrInTemplate(pTemplate, ulCount, CKA_OWNER))
+ &&(IsAttrInTemplate(pTemplate, ulCount, CKA_VALUE))
+ )
+ {
+ return CKR_OK;
+ }
+ }
+
+ else
+ {
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+ }
+ break;
+
+ case CKO_PUBLIC_KEY:
+ {
+ if ( ( IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+ &&( IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_TYPE))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_LOCAL))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_GEN_MECHANISM))
+ &&( IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS_BITS))
+ &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PUBLIC_EXPONENT))
+ )
+ {
+ return CKR_OK;
+ }
+ }
+ break;
+
+ case CKO_PRIVATE_KEY:
+ {
+ if ( ( IsAttrInTemplate(pTemplate, ulCount, CKA_CLASS))
+ &&( IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_TYPE))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_LOCAL))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_GEN_MECHANISM))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_ALWAYS_SENSITIVE))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_NEVER_EXTRACTABLE))
+ &&( IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS))
+ &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PRIVATE_EXPONENT))
+ &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PRIME_1))
+ &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PRIME_2))
+ &&( IsAttrInTemplate(pTemplate, ulCount, CKA_EXPONENT_1))
+ &&( IsAttrInTemplate(pTemplate, ulCount, CKA_EXPONENT_2))
+ &&( IsAttrInTemplate(pTemplate, ulCount, CKA_COEFFICIENT))
+ )
+ {
+ return CKR_OK;
+ }
+ }
+ break;
+
+ default:
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+ }
+
+ // Check Public Key Generation Template
+ else if (bMode == MODE_GENERATE_PUB)
+ {
+ if ( (!IsAttrInTemplate(pTemplate, ulCount, CKA_LOCAL))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_GEN_MECHANISM))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS))
+ &&( IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS_BITS))
+ &&( IsAttrInTemplate(pTemplate, ulCount, CKA_PUBLIC_EXPONENT))
+ )
+ {
+ return CKR_OK;
+ }
+ }
+
+ // Check Private Key Generation Template
+ else if (bMode == MODE_GENERATE_PRIV)
+ {
+ if ( (!IsAttrInTemplate(pTemplate, ulCount, CKA_LOCAL))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_KEY_GEN_MECHANISM))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_ALWAYS_SENSITIVE))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_NEVER_EXTRACTABLE))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_MODULUS))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_PUBLIC_EXPONENT))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_PRIVATE_EXPONENT))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_PRIME_1))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_PRIME_2))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_EXPONENT_1))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_EXPONENT_2))
+ &&(!IsAttrInTemplate(pTemplate, ulCount, CKA_COEFFICIENT))
+ )
+ {
+ return CKR_OK;
+ }
+ }
+
+ return CKR_TEMPLATE_INCONSISTENT;
+}
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/template.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,56 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_template_h
+#define _include_template_h
+
+#include <list>
+#include <vector>
+
+using namespace std;
+
+#define MODE_CREATE 0x01
+#define MODE_GENERATE_PUB 0x02
+#define MODE_GENERATE_PRIV 0x03
+
+class Template
+{
+
+public:
+ vector<CK_ATTRIBUTE> _attributes;
+
+public:
+ Template(CK_ATTRIBUTE_PTR temp,CK_ULONG ulCount);
+ ~Template();
+
+ static void FixEndianness(CK_ATTRIBUTE attrTemplate);
+
+ static CK_ULONG FindClassFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+ static CK_ULONG FindCertTypeFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+ static CK_BBOOL FindTokenFromTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount);
+ static CK_BBOOL IsAttrInTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, CK_ATTRIBUTE_TYPE AttrType);
+ static CK_RV CheckTemplate(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount, CK_BYTE bMode);
+
+};
+
+
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,312 @@
+
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+#ifdef INCLUDE_EVENTING
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include <string>
+#ifndef WIN32
+#include <pthread.h>
+#endif
+#include "thread.h"
+
+#ifdef WIN32
+const CK_LONG CThread::P_ABOVE_NORMAL = THREAD_PRIORITY_ABOVE_NORMAL;
+const CK_LONG CThread::P_BELOW_NORMAL = THREAD_PRIORITY_BELOW_NORMAL;
+const CK_LONG CThread::P_HIGHEST = THREAD_PRIORITY_HIGHEST;
+const CK_LONG CThread::P_IDLE = THREAD_PRIORITY_IDLE;
+const CK_LONG CThread::P_LOWEST = THREAD_PRIORITY_LOWEST;
+const CK_LONG CThread::P_NORMAL = THREAD_PRIORITY_NORMAL;
+const CK_LONG CThread::P_CRITICAL = THREAD_PRIORITY_TIME_CRITICAL;
+#endif
+
+CThread::CThread()
+{
+#ifdef WIN32
+ m_hThread = NULL;
+#endif
+ m_strName = NULL;
+ m_stopRequested = false;
+}
+
+CThread::CThread(const char* nm)
+{
+#ifdef WIN32
+ m_hThread = NULL;
+#endif
+ m_strName = new std::string(nm);
+}
+
+CThread::~CThread()
+{
+#ifdef WIN32
+ if(m_hThread != NULL)
+ {
+ if(m_strName != NULL)
+ {
+ delete m_strName;
+ }
+ stop();
+ }
+#else
+
+#endif
+}
+
+void CThread::setName(const char* nm)
+{
+ m_strName = new std::string(nm);
+}
+
+std::string* CThread::getName() const
+{
+ return m_strName;
+}
+
+void CThread::run()
+{
+ // Base run
+}
+
+void CThread::sleep(CK_LONG ms)
+{
+#ifdef WIN32
+ Sleep(ms);
+#else
+ usleep(ms*1000);
+#endif
+}
+
+void CThread::start()
+{
+
+#ifdef WIN32
+ DWORD tid = 0;
+ m_hThread = (unsigned long*)CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)_ou_thread_proc,(CThread*)this,0,&tid);
+
+ if(m_hThread == NULL)
+ {
+ assert(FALSE);
+ //throw ThreadException("Failed to create thread");
+ }
+ else
+ {
+ setPriority(CThread::P_NORMAL);
+ }
+
+#else
+
+ pthread_create(&m_hThread,0,_ou_thread_proc,(CThread*)this);
+
+#endif
+
+}
+
+void CThread::stop()
+{
+#ifdef WIN32
+ if(m_hThread == NULL) return;
+
+ m_stopRequested = true;
+
+ DWORD dwTimeout = 1000;
+ DWORD dwSleepTime = 10;
+ DWORD dwExitCode = STILL_ACTIVE;
+
+ for(DWORD i=0; i< dwTimeout/dwSleepTime; i++)
+ {
+ if(GetExitCodeThread(m_hThread, &dwExitCode))
+ {
+ if(dwExitCode!=STILL_ACTIVE)
+ break;
+ }
+ else
+ break; // Some error
+ Sleep(dwSleepTime);
+ }
+
+ if( dwExitCode == STILL_ACTIVE )
+ TerminateThread(m_hThread, 0);
+
+ // Never do this.
+ ///WaitForSingleObject(m_hThread,INFINITE);
+ CloseHandle(m_hThread);
+ m_hThread = NULL;
+
+ m_stopRequested = false;
+
+#else
+
+ m_stopRequested = true;
+
+ pthread_join(m_hThread,NULL);
+
+ m_stopRequested = false;
+
+#endif
+}
+
+CK_BBOOL CThread::isStopRequested()
+{
+ return m_stopRequested;
+}
+
+#ifdef WIN32
+void CThread::setPriority(CK_LONG tp)
+#else
+void CThread::setPriority( CK_LONG )
+#endif
+{
+#ifdef WIN32
+ if(m_hThread == NULL)
+ {
+ assert(FALSE);
+ //throw ThreadException("Thread object is null");
+ }
+ else
+ {
+ if(SetThreadPriority(m_hThread,tp) == 0)
+ {
+ assert(FALSE);
+ //throw ThreadException("Failed to set priority");
+ }
+ }
+#else
+#endif
+}
+
+void CThread::suspend()
+{
+
+#ifdef WIN32
+ if(m_hThread == NULL)
+ {
+ assert(FALSE);
+ //throw ThreadException("Thread object is null");
+ }
+ else
+ {
+ if((int)SuspendThread(m_hThread) < 0)
+ {
+ assert(FALSE);
+ //throw ThreadException("Failed to suspend thread");
+ }
+ }
+#else
+#endif
+}
+
+void CThread::resume()
+{
+#ifdef WIN32
+ if(m_hThread == NULL)
+ {
+ assert(FALSE);
+ //throw ThreadException("Thread object is null");
+ }
+ else
+ {
+ if((int)ResumeThread(m_hThread) < 0)
+ {
+ assert(FALSE);
+ //throw ThreadException("Failed to resume thread");
+ }
+ }
+#else
+#endif
+}
+
+#ifdef WIN32
+CK_BBOOL CThread::wait(const char* m,CK_LONG ms)
+#else
+CK_BBOOL CThread::wait( const char*, CK_LONG )
+#endif
+{
+#ifdef WIN32
+ HANDLE h = OpenMutex(MUTEX_ALL_ACCESS,FALSE,m);
+
+ if(h == NULL)
+ {
+ assert(FALSE);
+ //throw ThreadException("Mutex not found");
+ }
+ DWORD d = WaitForSingleObject(h,ms);
+
+ switch(d)
+ {
+ case WAIT_ABANDONED:
+ assert(FALSE);
+ //throw ThreadException("Mutex not signaled");
+ break;
+ case WAIT_OBJECT_0:
+ return true;
+ case WAIT_TIMEOUT:
+ assert(FALSE);
+ //throw ThreadException("Wait timed out");
+ break;
+ }
+ return false;
+#else
+ return false;
+#endif
+}
+
+#ifdef WIN32
+void CThread::release(const char* m)
+#else
+void CThread::release( const char* )
+#endif
+{
+#ifdef WIN32
+ HANDLE h = OpenMutex(MUTEX_ALL_ACCESS,FALSE,m);
+ if(h == NULL)
+ {
+ assert(FALSE);
+ //throw ThreadException("Invalid mutex handle");
+ }
+ if(ReleaseMutex(h) == 0)
+ {
+ assert(FALSE);
+ //throw ThreadException("Failed to release mutex");
+ }
+#else
+#endif
+}
+
+#ifdef WIN32
+// global thread caallback
+unsigned int _ou_thread_proc(void* param)
+{
+ CThread* tp = (CThread*)param;
+ tp->run();
+ return 0;
+}
+#else
+void* _ou_thread_proc(void* param)
+{
+ CThread* tp = (CThread*)param;
+ tp->run();
+ return NULL;
+}
+#endif
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/thread.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,91 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_thread_h
+#define _include_thread_h
+
+#include <string>
+
+#ifdef INCLUDE_EVENTING
+
+using namespace std;
+
+class CThread
+{
+
+private:
+ // unsigned long* to the low-level thread object
+#ifdef WIN32
+ CK_ULONG_PTR m_hThread;
+#else
+ pthread_t m_hThread;
+#endif
+
+ // a name to identify the thread
+ std::string* m_strName;
+ CK_BBOOL m_stopRequested;
+
+public:
+ CThread();
+ CThread(const char* nm);
+ virtual ~CThread();
+
+ void setName(const char* nm);
+ std::string* getName() const;
+
+ void start();
+ virtual void run();
+ void sleep(CK_LONG ms);
+ void suspend();
+ void resume();
+ virtual void stop();
+
+ void setPriority(CK_LONG p);
+ CK_BBOOL isStopRequested();
+
+ CK_BBOOL wait(const char* m,CK_LONG ms=5000);
+ void release(const char* m);
+
+public:
+ // Thread priorities
+ static const CK_LONG P_ABOVE_NORMAL;
+ static const CK_LONG P_BELOW_NORMAL;
+ static const CK_LONG P_HIGHEST;
+ static const CK_LONG P_IDLE;
+ static const CK_LONG P_LOWEST;
+ static const CK_LONG P_NORMAL;
+ static const CK_LONG P_CRITICAL;
+};
+
+// global function called by the thread object.
+// this in turn calls the overridden run()
+extern "C"
+{
+#ifdef WIN32
+ unsigned int _ou_thread_proc(void* param);
+#else
+ void* _ou_thread_proc(void* param);
+#endif
+}
+
+#endif
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,49 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "timer.h"
+
+#if defined(_WIN32)
+#include "Windows.h"
+#else
+#include <inttypes.h>
+#include <sys/time.h>
+#endif
+
+unsigned long CTimer::ClockTicks()
+{
+#if defined(_WIN32)
+ return GetTickCount();
+#else
+ static uint64_t startuptime = 0;
+ struct timeval t;
+
+ if(!startuptime) {
+ gettimeofday(&t,0);
+ startuptime = t.tv_sec*1000 + t.tv_usec/1000;
+ }
+
+ gettimeofday(&t,0);
+ uint64_t time = t.tv_sec*1000 + t.tv_usec/1000 - startuptime;
+ return (unsigned long)(time & 0xFFFFFFFF);
+
+#endif
+
+}
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/timer.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,31 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_timer_h
+#define _include_timer_h
+
+class CTimer
+{
+public:
+ static unsigned long ClockTicks();
+};
+
+#endif // _include_timer_h
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,57 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "transaction.h"
+#include "cardmoduleservice.h"
+
+#include "platconfig.h"
+#include "config.h"
+#include "thread.h"
+#include "event.h"
+#include "session.h"
+#include "slot.h"
+#include "sctoken.h"
+#include "error.h"
+
+
+Transaction::Transaction(Slot * slot) : _slot(slot)
+{
+
+ if(!slot || !slot->_token)
+ throw CkError(CKR_FUNCTION_FAILED);
+
+ _slot->_token->BeginTransaction();
+
+ // As a result of card re-set, user may have been logged out
+ _slot->UpdateSessionState();
+}
+
+Transaction::~Transaction() throw()
+{
+ if(!_slot || !_slot->_token)
+ return;
+
+ try
+ {
+ _slot->_token->EndTransaction();
+ }
+ catch(...) {}
+}
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/transaction.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,37 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_transaction_h
+#define _include_transaction_h
+
+class Slot;
+
+/** Class that manages token transaction */
+class Transaction
+{
+public:
+ Transaction(Slot * slot);
+ ~Transaction() throw();
+
+private:
+ Slot * _slot;
+};
+
+#endif
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,373 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "digest.h"
+#include "sha1.h"
+#include "error.h"
+#include "util.h"
+
+R_RANDOM_STRUCT Util::_randomStruct;
+
+void Util::SeedRandom(u1Array const & seed)
+{
+ InitRandomStruct(&_randomStruct);
+ R_RandomUpdate(&_randomStruct, const_cast<unsigned char*>(seed.GetBuffer()), seed.GetLength());
+}
+
+R_RANDOM_STRUCT & Util::RandomStruct()
+{
+ return _randomStruct;
+}
+
+CK_ULONG Util::MakeULong(CK_BYTE_PTR buffer,CK_ULONG offset)
+{
+ return (CK_ULONG)(((CK_ULONG)buffer[offset] << 24) | ((CK_ULONG)buffer[offset+1] << 16) | ((CK_ULONG)buffer[offset+2] << 8) | buffer[offset+3]);
+}
+
+CK_BBOOL Util::CompareByteArrays(CK_BYTE_PTR abuffer,CK_BYTE_PTR bbuffer,CK_ULONG len)
+{
+ for(CK_ULONG i=0;i<len;i++){
+ if(abuffer[i] != bbuffer[i])
+ return CK_FALSE;
+ }
+
+
+ return CK_TRUE;
+}
+
+CK_BBOOL Util::CompareU1Arrays(u1Array* abuffer,CK_VOID_PTR bbuffer,CK_ULONG len)
+{
+ if((abuffer == NULL_PTR) && (bbuffer == NULL_PTR)){
+ return CK_TRUE;
+ }
+
+ if((abuffer != NULL_PTR) && (bbuffer != NULL_PTR)){
+ if(len == abuffer->GetLength()){
+ return Util::CompareByteArrays(abuffer->GetBuffer(),(CK_BYTE_PTR)bbuffer,len);
+ }
+ }
+
+ return CK_FALSE;
+}
+
+
+CK_BBOOL Util::CompareU4Arrays(u4Array* abuffer,CK_VOID_PTR bbuffer,CK_ULONG len)
+{
+ if((abuffer == NULL_PTR) && (bbuffer == NULL_PTR)){
+ return CK_TRUE;
+ }
+
+ if((abuffer != NULL_PTR) && (bbuffer != NULL_PTR)){
+ if(len == abuffer->GetLength()){
+ return Util::CompareByteArrays((u1*)abuffer->GetBuffer(),(CK_BYTE_PTR)bbuffer,len);
+ }
+ }
+
+ return CK_FALSE;
+}
+
+void Util::PushULongInVector(vector<u1>* to, CK_ULONG value)
+{
+ to->push_back((u1)(value >> 24));
+ to->push_back((u1)(value >> 16));
+ to->push_back((u1)(value >> 8));
+ to->push_back((u1)(value));
+}
+
+void Util::PushULongLongInVector(vector<u1>* to, u8 value)
+{
+ to->push_back((u1)(value >> 56));
+ to->push_back((u1)(value >> 48));
+ to->push_back((u1)(value >> 40));
+ to->push_back((u1)(value >> 32));
+ to->push_back((u1)(value >> 24));
+ to->push_back((u1)(value >> 16));
+ to->push_back((u1)(value >> 8));
+ to->push_back((u1)(value));
+}
+
+void Util::PushBBoolInVector(std::vector<u1>* to, CK_BBOOL value)
+{
+ // push the value
+ to->push_back(value);
+}
+
+void Util::PushByteArrayInVector(std::vector<u1>* to, u1Array *value)
+{
+ if((value == NULL_PTR) || value->GetLength() == 0){
+ to->push_back(0);
+ }else{
+ Util::PushLengthInVector(to,value->GetLength());
+ for(u4 i=0;i<value->GetLength();i++){
+ to->push_back(value->GetBuffer()[i]);
+ }
+ }
+}
+
+void Util::PushIntArrayInVector(std::vector<u1>* to, u4Array *value)
+{
+ if((value == NULL_PTR) || value->GetLength() == 0){
+ to->push_back(0);
+ }else{
+ Util::PushLengthInVector(to,(value->GetLength() * 4));
+ u1* buffer = (u1*)value->GetBuffer();
+ for(u4 i=0;i<(value->GetLength() * 4);i++){
+ to->push_back(buffer[i]);
+ }
+ }
+}
+
+u1Array* Util::ReadByteArrayFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+ CK_ULONG len = Util::ReadLengthFromVector(from,idx);
+
+ if(len == 0){
+ return NULL_PTR;
+ }
+
+ u1Array* val = new u1Array(len);
+
+ for(u4 i=0;i<len;i++){
+ val->SetU1At(i,from.at(*idx));
+ *idx = *idx + 1;
+ }
+
+ return val;
+}
+
+u4Array* Util::ReadIntArrayFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+ CK_ULONG len = Util::ReadLengthFromVector(from,idx);
+
+ if(len == 0){
+ return NULL_PTR;
+ }
+
+ u4Array* val = new u4Array(len/4);
+
+ for(u4 i=0;i<(len/4);i++){
+
+ u1 a = from.at(*idx);
+ u1 b = from.at(*idx + 1);
+ u1 c = from.at(*idx + 2);
+ u1 d = from.at(*idx + 3);
+
+ // make an int
+ u4 anInt = (u4)(((u4)a << 24) | ((u4)b << 16) | ((u4)c << 8) | d);
+
+ val->SetU4At(i,anInt);
+
+ *idx = *idx + 4;
+ }
+
+ return val;
+}
+
+void Util::PushLengthInVector(std::vector<u1>* to, CK_USHORT len)
+{
+ if(len < (CK_USHORT)0x80){
+ to->push_back(len & 0x7F);
+ }else if(len <= (CK_USHORT)0xFF){
+ to->push_back(0x81);
+ to->push_back(len & 0xFF);
+ }else{
+ to->push_back(0x82);
+ to->push_back((u1)((len >> 8) & 0x00FF));
+ to->push_back((u1)(len));
+ }
+}
+
+CK_ULONG Util::ReadLengthFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+ CK_USHORT val = (CK_USHORT)from.at(*idx);
+
+ if(val < (CK_USHORT)0x80){
+ *idx = *idx + 1;
+ return val;
+ }else if(val == 0x81){
+ *idx = *idx + 1;
+ val = from.at(*idx);
+ *idx = *idx + 1;
+ return val;
+ }else if(val == 0x82){
+ *idx = *idx + 1;
+ val = (u2)(((u2)from.at(*idx)) << 8);
+ *idx = *idx + 1;
+ val = val | (u2)from.at(*idx);
+ *idx = *idx + 1;
+ return val;
+ }
+
+ PKCS11_ASSERT(CK_FALSE);
+
+ return 0;
+}
+
+CK_BBOOL Util::ReadBBoolFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+ CK_BBOOL val = (CK_BBOOL)from.at(*idx);
+ *idx = *idx + 1;
+
+ return val;
+}
+
+CK_ULONG Util::ReadULongFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+ CK_ULONG offset = *idx;
+
+ CK_ULONG val = (CK_ULONG)(((CK_ULONG)from.at(offset) << 24) | ((CK_ULONG)from.at(offset+1) << 16) | ((CK_ULONG)from.at(offset+2) << 8) | from.at(offset+3));
+
+ *idx = *idx + 4;
+
+ return val;
+}
+
+u8 Util::ReadULongLongFromVector(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+ CK_ULONG offset = *idx;
+
+ u8 val = (u8)(((u8)from.at(offset ) << 56) | ((u8)from.at(offset+1) << 48) |
+ ((u8)from.at(offset+2) << 40) | ((u8)from.at(offset+3) << 32) |
+ ((u8)from.at(offset+4) << 24) | ((u8)from.at(offset+5) << 16) |
+ ((u8)from.at(offset+6) << 8) | from.at(offset+7));
+
+ *idx = *idx + 8;
+
+ return val;
+}
+
+void Util::ConvAscii(u1 *pIn, u4 dwLen,u1 *pOut)
+{
+ #define tohex(x) (((x) >= 0xA) ? ((x) - 0xA + 'A') : ((x) + '0'))
+ register u4 i;
+
+ for(i=0; i < dwLen; i++)
+ {
+ pOut[i*2] = tohex((pIn[i] >> 4) & 0xF);
+ pOut[i*2+1] = tohex(pIn[i] & 0xF);
+ }
+ #undef tohex
+}
+
+char* Util::ItoA(s4 value, char* str, s4 radix)
+{
+
+#ifdef WIN32
+
+ return _itoa(value,str,radix);
+
+#else
+
+ s4 rem = 0;
+ s4 pos = 0;
+ char ch = '!' ;
+
+ do
+ {
+ rem = value % radix ;
+ value /= radix;
+ if ( 16 == radix )
+ {
+ if( rem >= 10 && rem <= 15 )
+ {
+ switch( rem )
+ {
+ case 10:
+ ch = 'a' ;
+ break;
+ case 11:
+ ch ='b' ;
+ break;
+ case 12:
+ ch = 'c' ;
+ break;
+ case 13:
+ ch ='d' ;
+ break;
+ case 14:
+ ch = 'e' ;
+ break;
+ case 15:
+ ch ='f' ;
+ break;
+ }
+ }
+ }
+ if( '!' == ch )
+ {
+ str[pos++] = (char) ( rem + 0x30 );
+ }
+ else
+ {
+ str[pos++] = ch ;
+ }
+ }while( value != 0 );
+
+ str[pos] = '\0' ;
+
+ int i = strlen(str);
+ int t = !(i%2)? 1 : 0; // check the length of the string .
+
+ for(int j = i-1 , k = 0 ; j > (i/2 -t) ; j-- )
+ {
+ char ch2 = str[j];
+ str[j] = str[k];
+ str[k++] = ch2;
+ }
+
+ return str;
+
+#endif
+
+}
+
+u8 Util::MakeCheckValue(const unsigned char * pBuf, unsigned int length)
+{
+ CSHA1 sha1;
+ u1 hash[20];
+ sha1.HashCore(const_cast<unsigned char *>(pBuf), 0, length);
+ sha1.HashFinal(hash);
+ u8 val = 0;
+ for(size_t i = 0; i< sizeof(u8); ++i)
+ val = (val << 8) | hash[i];
+ return val;
+}
+
+u8 Util::MakeUniqueId()
+{
+ unsigned char buf[8];
+ if(R_GenerateBytes(buf, 8, &_randomStruct))
+ throw CkError(CKR_FUNCTION_FAILED);
+ u8 * value = reinterpret_cast<u8*>(buf);
+ return *value;
+}
+
+string Util::MakeIntString(unsigned int number, int width)
+{
+ if(width < 1)
+ return string();
+ char temp[16];
+ sprintf(temp, "%011d", number);
+ string s(temp);
+ return s.substr(s.size()-width, width);
+}
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/util.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,107 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_util_h
+#define _include_util_h
+
+#include <string>
+#include <vector>
+
+#include <MarshallerCfg.h>
+#include <Array.h>
+#include <cr_random.h>
+
+using namespace std;
+using namespace Marshaller;
+
+// Very simple class similar to auto_ptr, but for arrays.
+// It means that it calls delete[] instead of delete.
+template<class T> class autoarray
+{
+public:
+ autoarray(T* t) : _t(t) {}
+ ~autoarray() { delete [] _t; }
+ T * get() { return _t; }
+ T & operator[](size_t index) { return _t[index]; }
+ const T & operator[](size_t index) const { return _t[index]; }
+
+private:
+ T * _t;
+};
+
+template<typename T> void IntToLittleEndian(T t, unsigned char * buf, size_t offset = 0)
+{
+ size_t n = sizeof(T);
+ for(size_t i = 0; i < n; i++)
+ {
+ buf[offset+i] = static_cast<unsigned char>(t & 0xFF);
+ t >>= 8;
+ }
+}
+
+template<typename T> T LittleEndianToInt(const unsigned char * buf, size_t offset = 0)
+{
+ size_t n = sizeof(T);
+ T t = 0;
+ for(size_t i = 0; i < n; i++)
+ {
+ t <<= 8;
+ t |= buf[offset+n-i-1];
+ }
+ return t;
+}
+
+class Util{
+
+public:
+ static void SeedRandom(u1Array const & seed);
+ static R_RANDOM_STRUCT & RandomStruct();
+
+ static CK_ULONG MakeULong(CK_BYTE_PTR pValue,CK_ULONG offset);
+ static CK_BBOOL CompareByteArrays(CK_BYTE_PTR abuffer,CK_BYTE_PTR bbuffer,CK_ULONG len);
+ static void PushULongInVector(vector<u1>* to,CK_ULONG value);
+ static void PushULongLongInVector(vector<u1>* to,u8 value);
+ static void PushBBoolInVector(vector<u1>* to,CK_BBOOL value);
+ static void PushByteArrayInVector(vector<u1>* to,u1Array* value);
+ static void PushIntArrayInVector(vector<u1>* to,u4Array* value);
+ static void PushLengthInVector(vector<u1>* to,CK_USHORT len);
+ static CK_ULONG ReadLengthFromVector(vector<u1> from,CK_ULONG_PTR idx);
+ static CK_ULONG ReadULongFromVector(vector<u1> from,CK_ULONG_PTR idx);
+ static u8 ReadULongLongFromVector(vector<u1> from,CK_ULONG_PTR idx);
+ static CK_BBOOL ReadBBoolFromVector(vector<u1> from,CK_ULONG_PTR idx);
+ static u1Array* ReadByteArrayFromVector(vector<u1> from,CK_ULONG_PTR idx);
+ static u4Array* ReadIntArrayFromVector(vector<u1> from,CK_ULONG_PTR idx);
+
+ static CK_BBOOL CompareU1Arrays(u1Array* abuffer,CK_VOID_PTR bbuffer,CK_ULONG len);
+ static CK_BBOOL CompareU4Arrays(u4Array* abuffer,CK_VOID_PTR bbuffer,CK_ULONG len);
+ static void ConvAscii(u1 *pIn, u4 dwLen,u1 *pOut);
+ static char* ItoA(s4 value, char* str, s4 radix);
+ static u8 MakeCheckValue(const unsigned char * pBuf, unsigned int length);
+ static u8 MakeUniqueId();
+ static std::string MakeIntString(unsigned int number, int width);
+
+private:
+ static R_RANDOM_STRUCT _randomStruct;
+
+};
+
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,564 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+// This implementation is based on RFC 2459 which can be fetched from
+// http://www.ietf.org.
+
+// This code is based on class in ACS baseline.
+
+//#include "slbPki.h"
+#include "x509cert.h"
+
+using namespace std;
+
+X509Cert::X509Cert()
+{
+}
+
+X509Cert::X509Cert(const X509Cert &cert)
+{
+ *this = cert;
+}
+
+X509Cert::X509Cert(const BEROctet::Blob &buffer)
+{
+ *this = buffer;
+}
+
+X509Cert::X509Cert(const unsigned char *buffer, const unsigned long size)
+{
+ m_Cert = BEROctet(BEROctet::Blob(buffer,size));
+ if(size != m_Cert.Octet().size())
+ throw runtime_error("X509CertFormatError");
+
+ Decode();
+}
+
+X509Cert& X509Cert::operator=(const X509Cert &cert)
+{
+ m_Cert = cert.m_Cert;
+ Decode();
+
+ return *this;
+}
+
+X509Cert& X509Cert::operator=(const BEROctet::Blob &buffer)
+{
+ m_Cert = BEROctet(buffer);
+ if(buffer.size() != m_Cert.Octet().size())
+ throw runtime_error("X509CertFormatError");
+ Decode();
+
+ return *this;
+}
+
+// Returns whole DER string of Serial Number.
+
+BEROctet::Blob X509Cert::SerialNumber() const
+{
+ return m_SerialNumber.Octet();
+}
+
+// Returns whole DER string of Issuer
+
+BEROctet::Blob X509Cert::Issuer() const
+{
+ return m_Issuer.Octet();
+}
+
+// Returns whole string of Issuer in UTF8.
+
+BEROctet::Blob X509Cert::UTF8Issuer() const
+{
+ return ToUTF8(m_Issuer.Tag(), m_Issuer.Octet() );
+}
+
+
+// Returns list of attributes in Issuer matching id-at-organizationName.
+// List will be invalidated when object changes.
+
+std::vector<std::string> X509Cert::IssuerOrg() const
+{
+
+ std::vector<std::string> orgNames;
+ std::vector<BEROctet const*> orgOcts;
+
+ m_Issuer.SearchOIDNext(OID_id_at_organizationName,orgOcts);
+
+ for(unsigned long i=0; i<orgOcts.size(); i++)
+ orgNames.push_back(string((char*)orgOcts[i]->Data().data(),orgOcts[i]->Data().size()));
+
+ return orgNames;
+
+}
+
+// Returns list of attributes in Issuer matching id-at-organizationName.
+// List will be invalidated when object changes.
+// the string in the list is in UTF8 format.
+
+std::vector<std::string> X509Cert::UTF8IssuerOrg() const
+{
+
+ std::vector<std::string> orgNames;
+ std::vector<BEROctet const*> orgOcts;
+
+ m_Issuer.SearchOIDNext(OID_id_at_organizationName,orgOcts);
+
+ for(unsigned long i=0; i<orgOcts.size(); i++)
+ {
+ BEROctet::Blob blbData = ToUTF8(orgOcts[i]->Tag(), orgOcts[i]->Data());
+ orgNames.push_back(string((char*)blbData.data(),blbData.size()));
+ }
+
+ return orgNames;
+}
+
+
+// Returns Validity notBefore attribute as "YYYYMMDDHHMMSS"
+
+string X509Cert::ValidityNotBefore() const
+{
+
+ if(m_Validity.SubOctetList().size()!=2)
+ throw runtime_error("X509CertFormatError");
+
+ return m_Validity.SubOctetList()[0]->Time();
+
+}
+
+// Returns Validity notAfter attribute as "YYYYMMDDHHMMSS"
+
+string X509Cert::ValidityNotAfter() const
+{
+
+ if(m_Validity.SubOctetList().size()!=2)
+ throw runtime_error("X509CertFormatError");
+
+ return m_Validity.SubOctetList()[1]->Time();
+
+}
+
+
+// Returns whole DER string of Subject
+
+BEROctet::Blob X509Cert::Subject() const
+{
+ return m_Subject.Octet();
+}
+
+// Returns Subject in UTF8 format.
+
+BEROctet::Blob X509Cert::UTF8Subject() const
+{
+ return ToUTF8(m_Subject.Tag(), m_Subject.Octet());
+}
+
+// Returns list of attributes in Subject matching id-at-commonName
+// List will be invalidated when object changes.
+
+std::vector<std::string> X509Cert::SubjectCommonName() const
+{
+
+ std::vector<std::string> cnNames;
+ std::vector<BEROctet const*> cnOcts;
+
+ m_Subject.SearchOIDNext(OID_id_at_commonName,cnOcts);
+
+ for(std::vector<BEROctet const*>::size_type i=0; i<cnOcts.size(); i++)
+ cnNames.push_back(string((char*)cnOcts[i]->Data().data(),cnOcts[i]->Data().size()));
+
+ return cnNames;
+
+}
+
+// Returns list of attributes in Subject matching id-at-commonName
+// List will be invalidated when object changes.
+// string in list is in UTF8.
+
+std::vector<std::string> X509Cert::UTF8SubjectCommonName() const
+{
+
+ std::vector<std::string> cnNames;
+ std::vector<BEROctet const*> cnOcts;
+
+ m_Subject.SearchOIDNext(OID_id_at_commonName,cnOcts);
+
+ for(std::vector<BEROctet const*>::size_type i=0; i<cnOcts.size(); i++)
+ {
+ BEROctet::Blob blbData = ToUTF8(cnOcts[i]->Tag(), cnOcts[i]->Data());
+ cnNames.push_back(string((char*)blbData.data(),blbData.size()));
+ }
+
+ return cnNames;
+
+}
+
+// Returns modulus from SubjectPublicKeyInfo, stripped for any leading zero(s).
+
+BEROctet::Blob X509Cert::Modulus() const
+{
+
+ BEROctet::Blob RawMod = RawModulus();
+
+ unsigned long i = 0;
+ while(!RawMod[i] && i<RawMod.size()) i++; // Skip leading zero(s).
+
+ return BEROctet::Blob(&RawMod[i],RawMod.size()-i);
+
+}
+
+// Returns public exponent from SubjectPublicKeyInfo, possibly with leading zero(s).
+
+BEROctet::Blob X509Cert::RawModulus() const
+{
+
+ if(m_SubjectPublicKeyInfo.SubOctetList().size()!=2)
+ throw runtime_error("X509CertFormatError");
+
+ BEROctet PubKeyString = *(m_SubjectPublicKeyInfo.SubOctetList()[1]);
+
+ BEROctet::Blob KeyBlob = PubKeyString.Data();
+
+ if(KeyBlob[0]) // Expect number of unused bits in
+ throw runtime_error("X509CertFormatError"); // last octet to be zero.
+
+
+
+ BEROctet PubKeyOct(KeyBlob.substr(1,BEROctet::Blob::npos));
+
+ if(PubKeyOct.SubOctetList().size()!=2) throw runtime_error("X509CertFormatError");
+
+ return PubKeyOct.SubOctetList()[0]->Data();
+
+}
+
+// Returns public exponent from SubjectPublicKeyInfo, stripped for any leading zero(s).
+
+BEROctet::Blob X509Cert::PublicExponent() const
+{
+
+ BEROctet::Blob RawPubExp = RawPublicExponent();
+
+ unsigned long i = 0;
+ while(!RawPubExp[i] && i<RawPubExp.size()) i++; // Skip leading zero(s).
+
+ return BEROctet::Blob(&RawPubExp[i],RawPubExp.size()-i);
+
+}
+// Returns public exponent from SubjectPublicKeyInfo, possibly with leading zero(s).
+
+BEROctet::Blob X509Cert::RawPublicExponent() const
+{
+
+ if(m_SubjectPublicKeyInfo.SubOctetList().size()!=2)
+ throw runtime_error("X509CertFormatError");
+
+ BEROctet PubKeyString = *(m_SubjectPublicKeyInfo.SubOctetList()[1]);
+
+ BEROctet::Blob KeyBlob = PubKeyString.Data();
+
+ if(KeyBlob[0]) // Expect number of unused bits
+ throw runtime_error("X509CertFormatError"); // in last octet to be zero.
+
+
+ BEROctet PubKeyOct(KeyBlob.substr(1,BEROctet::Blob::npos));
+
+ if(PubKeyOct.SubOctetList().size()!=2) throw runtime_error("X509CertFormatError");
+
+ return PubKeyOct.SubOctetList()[1]->Data();
+
+}
+
+// Returns KeyUsage attribute, left justified with most significant bit as first bit (BER convention)
+
+unsigned long X509Cert::KeyUsage() const
+{
+
+ if(!m_Extensions.Data().size())
+ throw runtime_error("X509CertExtensionNotPresent");
+
+ unsigned long ReturnKeyUsage = 0;
+
+ const unsigned char UnusedBitsMask[] = {0xFF,0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80};
+
+ std::vector<BEROctet const*> ExtensionList;
+
+ m_Extensions.SearchOID(OID_id_ce_keyUsage,ExtensionList);
+
+ if(ExtensionList.size()!=1)
+ throw runtime_error("X509CertExtensionNotPresent"); // One and only one instance
+
+ BEROctet const* Extension = ExtensionList[0];
+ BEROctet* extnValue = 0;
+ if(Extension->SubOctetList().size()==2)
+ extnValue = Extension->SubOctetList()[1]; // No "critical" attribute present
+
+ else if(Extension->SubOctetList().size()==3)
+ extnValue = Extension->SubOctetList()[2]; // A "critical" attribute present
+
+ else
+ throw runtime_error("X509CertFormatError"); // "Extensions" must contain either 2 or 3 octets
+
+ BEROctet KeyUsage(extnValue->Data());
+ BEROctet::Blob KeyUsageBitString = KeyUsage.Data();
+
+ unsigned char UnusedBits = KeyUsageBitString[0];
+ size_t NumBytes = KeyUsageBitString.size()-1;
+ if(NumBytes>4)
+ {
+ NumBytes = 4; // Truncate to fit the ulong, should be plenty though
+ UnusedBits = 0;
+ }
+
+ unsigned long Shift = 24;
+ for(unsigned long i=0; i<NumBytes-1; i++)
+ {
+ ReturnKeyUsage |= (((unsigned long)KeyUsageBitString[i+1]) << Shift);
+ Shift -= 8;
+ }
+
+ ReturnKeyUsage |= ( (KeyUsageBitString[NumBytes] & UnusedBitsMask[UnusedBits]) << Shift );
+
+ return ReturnKeyUsage;
+
+}
+
+bool X509Cert::ExtendedKeyUsage(string const &strOID) const
+{
+ if(!m_Extensions.Data().size())
+ return false;
+
+ vector<BEROctet const*> veku;
+
+ m_Extensions.SearchOIDNext(OID_id_ce_extKeyUsage, veku);
+ if(veku.size() != 1)
+ return false;
+
+ try
+ {
+ BEROctet berEKU(veku[0]->Data());
+ vector<BEROctet const*> ekuOcts;
+ berEKU.SearchOID(strOID,ekuOcts);
+ if(ekuOcts.size() > 0)
+ return true;
+ else
+ return false;
+ }
+ catch(...)
+ {
+ return false;
+ }
+}
+
+bool X509Cert::IsCACert() const
+{
+ return m_bCACert;
+}
+
+bool X509Cert::IsRootCert() const
+{
+ return m_bRootCert;
+}
+
+void X509Cert::Decode()
+{
+
+ const unsigned int dwTagVersion = 0;
+ //const unsigned int dwTagIssuerUniqueID = 1;
+ //const unsigned int dwTagSubjectUniqueID = 2;
+ const unsigned int dwTagExtensions = 3;
+
+ if(m_Cert.SubOctetList().size()!=3) throw runtime_error("X509CertFormatError");
+
+ BEROctet *tbsCert = m_Cert.SubOctetList()[0];
+ size_t Size = tbsCert->SubOctetList().size();
+ if(!Size) throw runtime_error("X509CertFormatError");
+
+ std::vector<BEROctet const*>::size_type i = 0;
+ BEROctet *first = tbsCert->SubOctetList()[i];
+ if((first->Class()==tcContext) && (first->Tag()==dwTagVersion)) i++; // Version
+
+ if(Size < static_cast<unsigned long>(6+i))
+ throw runtime_error("X509CertFormatError");
+
+ m_SerialNumber = *(tbsCert->SubOctetList()[i]); i++; // SerialNumber
+ i++; // Signature (algorithm)
+ m_Issuer = *(tbsCert->SubOctetList()[i]); i++; // Issuer
+ m_Validity = *(tbsCert->SubOctetList()[i]); i++; // Validity
+ m_Subject = *(tbsCert->SubOctetList()[i]); i++; // Subject
+ m_SubjectPublicKeyInfo = *(tbsCert->SubOctetList()[i]); i++; // SubjectPublicKeyInfo
+
+ m_Extensions = BEROctet();
+ while(i<Size) {
+ BEROctet *oct = tbsCert->SubOctetList()[i];
+ if((oct->Class()==tcContext) && (oct->Tag()==dwTagExtensions)) {
+ m_Extensions = *oct;
+ break;
+ }
+ i++;
+ }
+
+ m_bCACert = false;
+ std::vector<BEROctet const*> ExtensionList;
+ m_Extensions.SearchOID(OID_id_ce_basicConstraints, ExtensionList);
+
+
+ if(1 == ExtensionList.size())
+ {
+ BEROctet const* Extension = ExtensionList[0];
+ BEROctet* extnValue = 0;
+ if(Extension->SubOctetList().size()==2)
+ extnValue = Extension->SubOctetList()[1]; // No "critical" attribute present
+
+ else if(Extension->SubOctetList().size()==3)
+ extnValue = Extension->SubOctetList()[2]; // A "critical" attribute present
+
+ if (extnValue)
+ {
+ BEROctet BasicContrainsts(extnValue->Data());
+ std::vector<BEROctet*> bcMembers(BasicContrainsts.SubOctetList());
+ if(bcMembers.size()>0 && bcMembers[0]->Tag() == dwBerUnivBool)
+ {
+ BEROctet::Blob flag(bcMembers[0]->Data());
+ if(flag.size()==1)
+ m_bCACert = flag[0] ? true : false;
+ }
+ }
+ }
+
+ m_bRootCert = false;
+ if (Issuer() == Subject())
+ {
+ m_bRootCert = true;
+ }
+}
+
+
+BEROctet::Blob X509Cert::ToUTF8( unsigned int dwTag, const BEROctet::Blob &blbData ) const
+{
+ BEROctet::Blob blbReturn;
+ size_t cUnicode = 0;
+ bool bConvert = false;
+ switch(dwTag)
+ {
+ case dwBerBMPString:
+ //string in 2 byte Unicode Big Endian format.
+ cUnicode = 2;
+ bConvert = true;
+ break;
+ case dwBerUniversalString:
+ case dwBerCharacterString:
+ //string in ISO10646, 4 byte unicode big endian format.
+ //this is hardly used but we never know.
+ cUnicode = 4;
+ bConvert = true;
+ break;
+ default:
+ //return as is.
+ blbReturn = blbData;
+ }
+
+ if(bConvert)
+ {
+ unsigned char bAppend = 0;
+ for(size_t i = 0; i < blbData.size() / cUnicode; i++ )
+ {
+ unsigned int dwUnicode = 0;
+ unsigned int dwTemp = 0;
+ int nBytesInUTF8 = 0;
+
+ //first get the Unicode unsigned int from BIG ENDIAN BYTES.
+ for(size_t j = 0; j < cUnicode; j++)
+ {
+ dwTemp = blbData.at(i*cUnicode + j);
+ dwUnicode += dwTemp << (8*(cUnicode-(j+1)));
+ }
+
+ //now calculate the number of bytes required to represent
+ // the unicode value in UTF8
+ if( dwUnicode <= 0x0000007F )
+ {
+ nBytesInUTF8 = 1;
+ }
+ else if( dwUnicode <= 0x000007FF )
+ {
+ nBytesInUTF8 = 2;
+ }
+ else if( dwUnicode <= 0x0000FFFF )
+ {
+ nBytesInUTF8 = 3;
+ }
+ else if( dwUnicode <= 0x001FFFFF )
+ {
+ nBytesInUTF8 = 4;
+ }
+ else if( dwUnicode <= 0x03FFFFFF )
+ {
+ nBytesInUTF8 = 5;
+ }
+ else if( dwUnicode <= 0x7FFFFFFF )
+ {
+ nBytesInUTF8 = 6;
+ }
+
+ //The bitwise & code is 0x7F (7 bits) when there is only one byte
+ // Otherwise the & code is 0x3f ( 6 bits)
+ // when there are more that one UTF8 bytes required,
+ // Ideally the MS unsigned char has to be & with less than 6 bits,
+ // but it does not matter since the other bits
+ // will be zero, so it is safe to & 6 bits.
+
+ unsigned char bBitWiseAndCode = 0x3f;
+ if( nBytesInUTF8 == 1)
+ {
+ bBitWiseAndCode = 0x7f;
+ }
+
+
+ // Shift in the multiples of 6 starting with maximum.
+ // This way the MSB will be appended first and then the rest.
+ // Add to MS Byte the bits which indicates number of bytes coded for UTF8
+ // for all other bytes add 0x80.
+ for( int k = nBytesInUTF8 - 1; k >= 0; k--)
+ {
+ unsigned char bytAdd = 0;
+ if( nBytesInUTF8 > 1 )
+ {
+ if( k == nBytesInUTF8 - 1 )
+ {
+ bytAdd = ( 0xFF << (8 - nBytesInUTF8 ) );
+ }
+ else
+ {
+ bytAdd = 0x80;
+ }
+
+ }
+ bAppend = static_cast<unsigned char>( ((dwUnicode >> k*6) & bBitWiseAndCode));
+ bAppend += bytAdd;
+ blbReturn.append( &bAppend, 1);
+ }
+ }
+ //append the NULL char.
+ bAppend = 0;
+ blbReturn.append( &bAppend, 1);
+ }
+ return blbReturn;
+}
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509cert.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,95 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+// This code is based on class in ACS baseline.
+
+#ifndef _include_x509cert_h
+#define _include_x509cert_h
+
+#include <string>
+#include <vector>
+
+#include "beroctet.h"
+
+class X509Cert
+{
+
+public:
+ X509Cert();
+ X509Cert(const X509Cert &cert);
+ X509Cert(const BEROctet::Blob &buffer);
+ X509Cert(const unsigned char *buffer, const unsigned long size);
+ X509Cert& operator=(const X509Cert &cert);
+ X509Cert& operator=(const BEROctet::Blob &buffer);
+
+ BEROctet::Blob SerialNumber() const;
+ BEROctet::Blob Issuer() const;
+ BEROctet::Blob UTF8Issuer() const;
+ std::vector<std::string> IssuerOrg() const;
+ std::vector<std::string> UTF8IssuerOrg() const;
+ std::string ValidityNotBefore() const;
+ std::string ValidityNotAfter() const;
+ BEROctet::Blob Subject() const;
+ BEROctet::Blob UTF8Subject() const;
+ std::vector<std::string> SubjectCommonName() const;
+ std::vector<std::string> UTF8SubjectCommonName() const;
+ BEROctet::Blob Modulus() const;
+ BEROctet::Blob RawModulus() const;
+ BEROctet::Blob PublicExponent() const;
+ BEROctet::Blob RawPublicExponent() const;
+
+ unsigned long KeyUsage() const;
+ bool ExtendedKeyUsage(std::string const &strOID) const;
+ bool IsCACert() const;
+ bool IsRootCert() const;
+
+private:
+ void Decode();
+
+ BEROctet::Blob ToUTF8( unsigned int dwTag, const BEROctet::Blob &blbData ) const;
+
+private:
+ BEROctet m_Cert;
+ BEROctet m_SerialNumber;
+ BEROctet m_Issuer;
+ BEROctet m_Validity;
+ BEROctet m_Subject;
+ BEROctet m_SubjectPublicKeyInfo;
+ BEROctet m_Extensions;
+ bool m_bCACert;
+ bool m_bRootCert;
+
+
+};
+
+// Key Usage flags from X.509 spec
+
+const unsigned long digitalSignature = 0x80000000;
+const unsigned long nonRepudiation = 0x40000000;
+const unsigned long keyEncipherment = 0x20000000;
+const unsigned long dataEncipherment = 0x10000000;
+const unsigned long keyAgreement = 0x08000000;
+const unsigned long keyCertSign = 0x04000000;
+const unsigned long cRLSign = 0x02000000;
+const unsigned long encipherOnly = 0x01000000;
+const unsigned long decipherOnly = 0x00800000;
+
+
+#endif //_include_x509cert_h
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,265 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "stdafx.h"
+#include "platconfig.h"
+#include "config.h"
+#include "util.h"
+
+#include "x509pubkeycertobject.h"
+
+X509PubKeyCertObject::X509PubKeyCertObject() : CertificateObject()
+{
+ this->_subject = NULL_PTR;
+ this->_id = NULL_PTR;
+ this->_issuer = NULL_PTR;
+ this->_serialNumber = NULL_PTR;
+ this->_value = NULL_PTR;
+ this->_url = NULL_PTR;
+ this->_hashOfSubjectPubKey = NULL_PTR;
+ this->_hashOfIssuerPubKey = NULL_PTR;
+
+ this->_certType = CKC_X_509;
+ this->_trusted = CK_TRUE;
+}
+
+X509PubKeyCertObject::~X509PubKeyCertObject()
+{
+ if(this->_subject != NULL_PTR)
+ delete this->_subject;
+
+ if(this->_id != NULL_PTR)
+ delete this->_id;
+
+ if(this->_issuer != NULL_PTR)
+ delete this->_issuer;
+
+ if(this->_serialNumber != NULL_PTR)
+ delete this->_serialNumber;
+
+ if(this->_value != NULL_PTR)
+ delete this->_value;
+
+ if(this->_url != NULL_PTR)
+ delete this->_url;
+
+ if(this->_hashOfSubjectPubKey != NULL_PTR)
+ delete this->_hashOfSubjectPubKey;
+
+ if(this->_hashOfIssuerPubKey != NULL_PTR)
+ delete this->_hashOfIssuerPubKey;
+
+}
+
+CK_BBOOL X509PubKeyCertObject::Compare(CK_ATTRIBUTE attribute)
+{
+ switch(attribute.type){
+
+ case CKA_SUBJECT:
+ return Util::CompareU1Arrays(this->_subject,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_ID:
+ return Util::CompareU1Arrays(this->_id,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_ISSUER:
+ return Util::CompareU1Arrays(this->_issuer,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_SERIAL_NUMBER:
+ return Util::CompareU1Arrays(this->_serialNumber,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_VALUE:
+ return Util::CompareU1Arrays(this->_value,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_URL:
+ return Util::CompareU1Arrays(this->_url,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_HASH_OF_SUBJECT_PUBLIC_KEY:
+ return Util::CompareU1Arrays(this->_hashOfSubjectPubKey,attribute.pValue,attribute.ulValueLen);
+
+ case CKA_HASH_OF_ISSUER_PUBLIC_KEY:
+ return Util::CompareU1Arrays(this->_hashOfIssuerPubKey,attribute.pValue,attribute.ulValueLen);
+
+ default:
+ return CertificateObject::Compare(attribute);
+ }
+}
+
+CK_RV X509PubKeyCertObject::SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation)
+{
+ if( 0 == attribute.ulValueLen )
+ {
+ return CKR_OK;
+ }
+
+ CK_RV rv = CKR_OK;
+
+ if(objCreation == CK_FALSE){
+ switch(attribute.type){
+ case CKA_SUBJECT:
+ case CKA_VALUE:
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ switch(attribute.type){
+
+ case CKA_SUBJECT:
+ if(this->_subject != NULL_PTR){
+ delete this->_subject;
+ }
+ this->_subject = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ case CKA_ID:
+ if(this->_id != NULL_PTR){
+ delete this->_id;
+ }
+ this->_id = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ case CKA_ISSUER:
+ if(this->_issuer != NULL_PTR){
+ delete this->_issuer;
+ }
+ this->_issuer = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ case CKA_SERIAL_NUMBER:
+ if(this->_serialNumber != NULL_PTR){
+ delete this->_serialNumber;
+ }
+ this->_serialNumber = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ case CKA_VALUE:
+ if(this->_value != NULL_PTR){
+ delete this->_value;
+ }
+ this->_value = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ case CKA_URL:
+ {
+ u1Array* stemp = StorageObject::ReadStringFromAttribute(attribute,&rv);
+ if(rv == CKR_OK){
+ if(this->_url != NULL_PTR){
+ delete this->_url;
+ }
+ this->_url = stemp;
+ }
+ }
+ break;
+
+ case CKA_HASH_OF_SUBJECT_PUBLIC_KEY:
+ if(this->_hashOfSubjectPubKey != NULL_PTR){
+ delete this->_hashOfSubjectPubKey;
+ }
+ this->_hashOfSubjectPubKey = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ case CKA_HASH_OF_ISSUER_PUBLIC_KEY:
+ if(this->_hashOfIssuerPubKey != NULL_PTR){
+ delete this->_hashOfIssuerPubKey;
+ }
+ this->_hashOfIssuerPubKey = StorageObject::ReadU1ArrayFromAttribute(attribute);
+ break;
+
+ default:
+ return CertificateObject::SetAttribute(attribute,objCreation);
+ }
+
+ return rv;
+}
+
+CK_RV X509PubKeyCertObject::GetAttribute(CK_ATTRIBUTE_PTR attribute)
+{
+ switch(attribute->type){
+
+ case CKA_SUBJECT:
+ return StorageObject::PutU1ArrayInAttribute(this->_subject,attribute);
+
+ case CKA_ID:
+ return StorageObject::PutU1ArrayInAttribute(this->_id,attribute);
+
+ case CKA_ISSUER:
+ return StorageObject::PutU1ArrayInAttribute(this->_issuer,attribute);
+
+ case CKA_SERIAL_NUMBER:
+ return StorageObject::PutU1ArrayInAttribute(this->_serialNumber,attribute);
+
+ case CKA_VALUE:
+ return StorageObject::PutU1ArrayInAttribute(this->_value,attribute);
+
+ case CKA_URL:
+ return StorageObject::PutU1ArrayInAttribute(this->_url,attribute);
+
+ case CKA_HASH_OF_SUBJECT_PUBLIC_KEY:
+ return StorageObject::PutU1ArrayInAttribute(this->_hashOfSubjectPubKey,attribute);
+
+ case CKA_HASH_OF_ISSUER_PUBLIC_KEY:
+ return StorageObject::PutU1ArrayInAttribute(this->_hashOfIssuerPubKey,attribute);
+
+ default:
+ return CertificateObject::GetAttribute(attribute);
+ }
+}
+
+void X509PubKeyCertObject::Serialize(std::vector<u1> *to)
+{
+ CertificateObject::Serialize(to);
+
+ Util::PushByteArrayInVector(to,this->_subject);
+
+ Util::PushByteArrayInVector(to,this->_id);
+
+ Util::PushByteArrayInVector(to,this->_issuer);
+
+ Util::PushByteArrayInVector(to,this->_serialNumber);
+
+ Util::PushByteArrayInVector(to,this->_url);
+
+ Util::PushByteArrayInVector(to,this->_hashOfSubjectPubKey);
+
+ Util::PushByteArrayInVector(to,this->_hashOfIssuerPubKey);
+
+ PKCS11_ASSERT(!this->_certName.empty());
+
+}
+
+void X509PubKeyCertObject::Deserialize(std::vector<u1> from, CK_ULONG_PTR idx)
+{
+ CertificateObject::Deserialize(from,idx);
+
+ this->_subject = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_id = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_issuer = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_serialNumber = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_url = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_hashOfSubjectPubKey = Util::ReadByteArrayFromVector(from,idx);
+
+ this->_hashOfIssuerPubKey = Util::ReadByteArrayFromVector(from,idx);
+
+}
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/PKCS11Module2/x509pubkeycertobject.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,53 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_x509pubkeycertobject_h
+#define _include_x509pubkeycertobject_h
+
+#include "certificateobject.h"
+
+class X509PubKeyCertObject : public CertificateObject
+{
+
+public:
+ u1Array* _subject;
+ u1Array* _id;
+ u1Array* _issuer;
+ u1Array* _serialNumber;
+ u1Array* _value;
+ u1Array* _url;
+ u1Array* _hashOfSubjectPubKey;
+ u1Array* _hashOfIssuerPubKey;
+
+public:
+ X509PubKeyCertObject();
+ ~X509PubKeyCertObject();
+
+ CK_BBOOL Compare(CK_ATTRIBUTE attribute);
+ CK_RV SetAttribute(CK_ATTRIBUTE attribute,CK_BBOOL objCreation);
+ CK_RV GetAttribute(CK_ATTRIBUTE_PTR attribute);
+
+ void Serialize(vector<u1>* to);
+ void Deserialize(vector<u1> from,CK_ULONG_PTR idx);
+
+};
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/aclocal.m4
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/aclocal.m4 (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/aclocal.m4 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,8989 @@
+# generated automatically by aclocal 1.10.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program 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.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(AC_AUTOCONF_VERSION, [2.61],,
+[m4_warning([this file was generated for autoconf 2.61.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+# 2006, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gordon Matzigkeit, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+m4_define([_LT_COPYING], [dnl
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+# 2006, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gordon Matzigkeit, 1996
+#
+# This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING. If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+])
+
+# serial 56 LT_INIT
+
+
+# LT_PREREQ(VERSION)
+# ------------------
+# Complain and exit if this libtool version is less that VERSION.
+m4_defun([LT_PREREQ],
+[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+ [m4_default([$3],
+ [m4_fatal([Libtool version $1 or higher is required],
+ 63)])],
+ [$2])])
+
+
+# _LT_CHECK_BUILDDIR
+# ------------------
+# Complain if the absolute build directory name contains unusual characters
+m4_defun([_LT_CHECK_BUILDDIR],
+[case `pwd` in
+ *\ * | *\ *)
+ AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+esac
+])
+
+
+# LT_INIT([OPTIONS])
+# ------------------
+AC_DEFUN([LT_INIT],
+[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT
+AC_BEFORE([$0], [LT_LANG])dnl
+AC_BEFORE([$0], [LT_OUTPUT])dnl
+AC_BEFORE([$0], [LTDL_INIT])dnl
+m4_require([_LT_CHECK_BUILDDIR])dnl
+
+dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+dnl unless we require an AC_DEFUNed macro:
+AC_REQUIRE([LTOPTIONS_VERSION])dnl
+AC_REQUIRE([LTSUGAR_VERSION])dnl
+AC_REQUIRE([LTVERSION_VERSION])dnl
+AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+m4_require([_LT_PROG_LTMAIN])dnl
+
+dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+_LT_SETUP
+
+# Only expand once:
+m4_define([LT_INIT])
+])# LT_INIT
+
+# Old names:
+AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+m4_defun([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+ case $cc_temp in
+ compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+ distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+])
+
+
+# _LT_FILEUTILS_DEFAULTS
+# ----------------------
+# It is okay to use these file commands and assume they have been set
+# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'.
+m4_defun([_LT_FILEUTILS_DEFAULTS],
+[: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+])# _LT_FILEUTILS_DEFAULTS
+
+
+# _LT_SETUP
+# ---------
+m4_defun([_LT_SETUP],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+_LT_DECL([], [host_alias], [0], [The host system])dnl
+_LT_DECL([], [host], [0])dnl
+_LT_DECL([], [host_os], [0])dnl
+dnl
+_LT_DECL([], [build_alias], [0], [The build system])dnl
+_LT_DECL([], [build], [0])dnl
+_LT_DECL([], [build_os], [0])dnl
+dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+test -z "$LN_S" && LN_S="ln -s"
+_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+dnl
+AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+])
+if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+
+_LT_CHECK_OBJDIR
+
+m4_require([_LT_TAG_COMPILER])dnl
+_LT_PROG_ECHO_BACKSLASH
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ _LT_PATH_MAGIC
+ fi
+ ;;
+esac
+
+# Use C for the default configuration in the libtool script
+LT_SUPPORTED_TAG([CC])
+_LT_LANG_C_CONFIG
+_LT_LANG_DEFAULT_CONFIG
+_LT_CONFIG_COMMANDS
+])# _LT_SETUP
+
+
+# _LT_PROG_LTMAIN
+# ---------------
+# Note that this code is called both from `configure', and `config.status'
+# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably,
+# `config.status' has no value for ac_aux_dir unless we are using Automake,
+# so we pass a copy along to make sure it has a sensible value anyway.
+m4_defun([_LT_PROG_LTMAIN],
+[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+ltmain="$ac_aux_dir/ltmain.sh"
+])# _LT_PROG_LTMAIN
+
+
+
+# So that we can recreate a full libtool script including additional
+# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+# in macros and then make a single call at the end using the `libtool'
+# label.
+
+
+# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+# ----------------------------------------
+# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL_INIT],
+[m4_ifval([$1],
+ [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+ [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+
+
+# _LT_CONFIG_LIBTOOL([COMMANDS])
+# ------------------------------
+# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL],
+[m4_ifval([$1],
+ [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+ [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+
+
+# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+# -----------------------------------------------------
+m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+[_LT_CONFIG_LIBTOOL([$1])
+_LT_CONFIG_LIBTOOL_INIT([$2])
+])
+
+
+# _LT_FORMAT_COMMENT([COMMENT])
+# -----------------------------
+# Add leading comment marks to the start of each line, and a trailing
+# full-stop to the whole comment if one is not present already.
+m4_define([_LT_FORMAT_COMMENT],
+[m4_ifval([$1], [
+m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+ [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+)])
+
+
+
+
+
+# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+# -------------------------------------------------------------------
+# CONFIGNAME is the name given to the value in the libtool script.
+# VARNAME is the (base) name used in the configure script.
+# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+# VARNAME. Any other value will be used directly.
+m4_define([_LT_DECL],
+[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+ [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+ [m4_ifval([$1], [$1], [$2])])
+ lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+ m4_ifval([$4],
+ [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+ lt_dict_add_subkey([lt_decl_dict], [$2],
+ [tagged?], [m4_ifval([$5], [yes], [no])])])
+])
+
+
+# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+# --------------------------------------------------------
+m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+
+
+# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_tag_varnames],
+[_lt_decl_filter([tagged?], [yes], $@)])
+
+
+# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+# ---------------------------------------------------------
+m4_define([_lt_decl_filter],
+[m4_case([$#],
+ [0], [m4_fatal([$0: too few arguments: $#])],
+ [1], [m4_fatal([$0: too few arguments: $#: $1])],
+ [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+ [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+ [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+])
+
+
+# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+# --------------------------------------------------
+m4_define([lt_decl_quote_varnames],
+[_lt_decl_filter([value], [1], $@)])
+
+
+# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_dquote_varnames],
+[_lt_decl_filter([value], [2], $@)])
+
+
+# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_varnames_tagged],
+[m4_assert([$# <= 2])dnl
+_$0(m4_quote(m4_default([$1], [[, ]])),
+ m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
+ m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
+m4_define([_lt_decl_varnames_tagged],
+[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
+
+
+# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_all_varnames],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+ m4_if([$2], [],
+ m4_quote(lt_decl_varnames),
+ m4_quote(m4_shift($@))))[]dnl
+])
+m4_define([_lt_decl_all_varnames],
+[lt_join($@, lt_decl_varnames_tagged([$1],
+ lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+])
+
+
+# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+# ------------------------------------
+# Quote a variable value, and forward it to `config.status' so that its
+# declaration there will have the same value as in `configure'. VARNAME
+# must have a single quote delimited value for this to work.
+m4_define([_LT_CONFIG_STATUS_DECLARE],
+[$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`'])
+
+
+# _LT_CONFIG_STATUS_DECLARATIONS
+# ------------------------------
+# We delimit libtool config variables with single quotes, so when
+# we write them to config.status, we have to be sure to quote all
+# embedded single quotes properly. In configure, this macro expands
+# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+#
+# <var>='`$ECHO "X$<var>" | $Xsed -e "$delay_single_quote_subst"`'
+m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+ [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAGS
+# ----------------
+# Output comment and list of tags supported by the script
+m4_defun([_LT_LIBTOOL_TAGS],
+[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+available_tags="_LT_TAGS"dnl
+])
+
+
+# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+# -----------------------------------
+# Extract the dictionary values for VARNAME (optionally with TAG) and
+# expand to a commented shell variable setting:
+#
+# # Some comment about what VAR is for.
+# visible_name=$lt_internal_name
+m4_define([_LT_LIBTOOL_DECLARE],
+[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+ [description])))[]dnl
+m4_pushdef([_libtool_name],
+ m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+ [0], [_libtool_name=[$]$1],
+ [1], [_libtool_name=$lt_[]$1],
+ [2], [_libtool_name=$lt_[]$1],
+ [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+])
+
+
+# _LT_LIBTOOL_CONFIG_VARS
+# -----------------------
+# Produce commented declarations of non-tagged libtool config variables
+# suitable for insertion in the LIBTOOL CONFIG section of the `libtool'
+# script. Tagged libtool config variables (even for the LIBTOOL CONFIG
+# section) are produced by _LT_LIBTOOL_TAG_VARS.
+m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+[m4_foreach([_lt_var],
+ m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+ [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAG_VARS(TAG)
+# -------------------------
+m4_define([_LT_LIBTOOL_TAG_VARS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+ [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+
+
+# _LT_TAGVAR(VARNAME, [TAGNAME])
+# ------------------------------
+m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+
+
+# _LT_CONFIG_COMMANDS
+# -------------------
+# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of
+# variables for single and double quote escaping we saved from calls
+# to _LT_DECL, we can put quote escaped variables declarations
+# into `config.status', and then the shell code to quote escape them in
+# for loops in `config.status'. Finally, any additional code accumulated
+# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+m4_defun([_LT_CONFIG_COMMANDS],
+[AC_PROVIDE_IFELSE([LT_OUTPUT],
+ dnl If the libtool generation code has been placed in $CONFIG_LT,
+ dnl instead of duplicating it all over again into config.status,
+ dnl then we will have config.status run $CONFIG_LT later, so it
+ dnl needs to know what name is stored there:
+ [AC_CONFIG_COMMANDS([libtool],
+ [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+ dnl If the libtool generation code is destined for config.status,
+ dnl expand the accumulated commands and init code now:
+ [AC_CONFIG_COMMANDS([libtool],
+ [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+])#_LT_CONFIG_COMMANDS
+
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+[
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+_LT_CONFIG_STATUS_DECLARATIONS
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+ case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+ *[[\\\\\\\`\\"\\\$]]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Double-quote double-evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_dquote_varnames); do
+ case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
+ *[[\\\\\\\`\\"\\\$]]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Fix-up fallback echo if it was mangled by the above quoting rules.
+case \$lt_ECHO in
+*'\\\[$]0 --fallback-echo"')dnl "
+ lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\`
+ ;;
+esac
+
+_LT_OUTPUT_LIBTOOL_INIT
+])
+
+
+# LT_OUTPUT
+# ---------
+# This macro allows early generation of the libtool script (before
+# AC_OUTPUT is called), incase it is used in configure for compilation
+# tests.
+AC_DEFUN([LT_OUTPUT],
+[: ${CONFIG_LT=./config.lt}
+AC_MSG_NOTICE([creating $CONFIG_LT])
+cat >"$CONFIG_LT" <<_LTEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate a libtool stub with the current configuration.
+
+lt_cl_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AS_SHELL_SANITIZE
+_AS_PREPARE
+
+exec AS_MESSAGE_FD>&1
+exec AS_MESSAGE_LOG_FD>>config.log
+{
+ echo
+ AS_BOX([Running $as_me.])
+} >&AS_MESSAGE_LOG_FD
+
+lt_cl_help="\
+\`$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $[0] [[OPTIONS]]
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+
+Report bugs to <bug-libtool at gnu.org>."
+
+lt_cl_version="\
+m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+configured by $[0], generated by m4_PACKAGE_STRING.
+
+Copyright (C) 2008 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test $[#] != 0
+do
+ case $[1] in
+ --version | --v* | -V )
+ echo "$lt_cl_version"; exit 0 ;;
+ --help | --h* | -h )
+ echo "$lt_cl_help"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --quiet | --q* | --silent | --s* | -q )
+ lt_cl_silent=: ;;
+
+ -*) AC_MSG_ERROR([unrecognized option: $[1]
+Try \`$[0] --help' for more information.]) ;;
+
+ *) AC_MSG_ERROR([unrecognized argument: $[1]
+Try \`$[0] --help' for more information.]) ;;
+ esac
+ shift
+done
+
+if $lt_cl_silent; then
+ exec AS_MESSAGE_FD>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AC_MSG_NOTICE([creating $ofile])
+_LT_OUTPUT_LIBTOOL_COMMANDS
+AS_EXIT(0)
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure. Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+if test "$no_create" != yes; then
+ lt_cl_success=:
+ test "$silent" = yes &&
+ lt_config_lt_args="$lt_config_lt_args --quiet"
+ exec AS_MESSAGE_LOG_FD>/dev/null
+ $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+ exec AS_MESSAGE_LOG_FD>>config.log
+ $lt_cl_success || AS_EXIT(1)
+fi
+])# LT_OUTPUT
+
+
+# _LT_CONFIG(TAG)
+# ---------------
+# If TAG is the built-in tag, create an initial libtool script with a
+# default configuration from the untagged config vars. Otherwise add code
+# to config.status for appending the configuration named by TAG from the
+# matching tagged config vars.
+m4_defun([_LT_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_CONFIG_SAVE_COMMANDS([
+ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+ m4_if(_LT_TAG, [C], [
+ # See if we are running on zsh, and set the options which allow our
+ # commands through without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+
+ cfgfile="${ofile}T"
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+ $RM "$cfgfile"
+
+ cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+ case $host_os in
+ aix3*)
+ cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+_LT_EOF
+ ;;
+ esac
+
+ _LT_PROG_LTMAIN
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ _LT_PROG_XSI_SHELLFNS
+
+ sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" ||
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+],
+[cat <<_LT_EOF >> "$ofile"
+
+dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+dnl in a comment (ie after a #).
+# ### BEGIN LIBTOOL TAG CONFIG: $1
+_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+# ### END LIBTOOL TAG CONFIG: $1
+_LT_EOF
+])dnl /m4_if
+],
+[m4_if([$1], [], [
+ PACKAGE='$PACKAGE'
+ VERSION='$VERSION'
+ TIMESTAMP='$TIMESTAMP'
+ RM='$RM'
+ ofile='$ofile'], [])
+])dnl /_LT_CONFIG_SAVE_COMMANDS
+])# _LT_CONFIG
+
+
+# LT_SUPPORTED_TAG(TAG)
+# ---------------------
+# Trace this macro to discover what tags are supported by the libtool
+# --tag option, using:
+# autoconf --trace 'LT_SUPPORTED_TAG:$1'
+AC_DEFUN([LT_SUPPORTED_TAG], [])
+
+
+# C support is built-in for now
+m4_define([_LT_LANG_C_enabled], [])
+m4_define([_LT_TAGS], [])
+
+
+# LT_LANG(LANG)
+# -------------
+# Enable libtool support for the given language if not already enabled.
+AC_DEFUN([LT_LANG],
+[AC_BEFORE([$0], [LT_OUTPUT])dnl
+m4_case([$1],
+ [C], [_LT_LANG(C)],
+ [C++], [_LT_LANG(CXX)],
+ [Java], [_LT_LANG(GCJ)],
+ [Fortran 77], [_LT_LANG(F77)],
+ [Fortran], [_LT_LANG(FC)],
+ [Windows Resource], [_LT_LANG(RC)],
+ [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+ [_LT_LANG($1)],
+ [m4_fatal([$0: unsupported language: "$1"])])])dnl
+])# LT_LANG
+
+
+# _LT_LANG(LANGNAME)
+# ------------------
+m4_defun([_LT_LANG],
+[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+ [LT_SUPPORTED_TAG([$1])dnl
+ m4_append([_LT_TAGS], [$1 ])dnl
+ m4_define([_LT_LANG_]$1[_enabled], [])dnl
+ _LT_LANG_$1_CONFIG($1)])dnl
+])# _LT_LANG
+
+
+# _LT_LANG_DEFAULT_CONFIG
+# -----------------------
+m4_defun([_LT_LANG_DEFAULT_CONFIG],
+[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [LT_LANG(CXX)],
+ [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_F77],
+ [LT_LANG(F77)],
+ [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_FC],
+ [LT_LANG(FC)],
+ [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+
+dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+dnl pulling things in needlessly.
+AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [m4_ifdef([AC_PROG_GCJ],
+ [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+ m4_ifdef([A][M_PROG_GCJ],
+ [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+ m4_ifdef([LT_PROG_GCJ],
+ [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+
+AC_PROVIDE_IFELSE([LT_PROG_RC],
+ [LT_LANG(RC)],
+ [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+])# _LT_LANG_DEFAULT_CONFIG
+
+# Obsolete macros:
+AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+
+
+# _LT_TAG_COMPILER
+# ----------------
+m4_defun([_LT_TAG_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_TAG_COMPILER
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+m4_defun([_LT_COMPILER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+m4_defun([_LT_LINKER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# -------------------------
+m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+ case $host_os in
+ rhapsody* | darwin*)
+ AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+ AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+ AC_CHECK_TOOL([LIPO], [lipo], [:])
+ AC_CHECK_TOOL([OTOOL], [otool], [:])
+ AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+ _LT_DECL([], [DSYMUTIL], [1],
+ [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+ _LT_DECL([], [NMEDIT], [1],
+ [Tool to change global to local symbols on Mac OS X])
+ _LT_DECL([], [LIPO], [1],
+ [Tool to manipulate fat objects and archives on Mac OS X])
+ _LT_DECL([], [OTOOL], [1],
+ [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+ _LT_DECL([], [OTOOL64], [1],
+ [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+
+ AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+ [lt_cv_apple_cc_single_mod=no
+ if test -z "${LT_MULTI_MODULE}"; then
+ # By default we will add the -single_module flag. You can override
+ # by either setting the environment variable LT_MULTI_MODULE
+ # non-empty at configure time, or by adding -multi_module to the
+ # link flags.
+ rm -rf libconftest.dylib*
+ echo "int foo(void){return 1;}" > conftest.c
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+ _lt_result=$?
+ if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
+ lt_cv_apple_cc_single_mod=yes
+ else
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ fi
+ rm -rf libconftest.dylib*
+ rm -f conftest.*
+ fi])
+ AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+ [lt_cv_ld_exported_symbols_list],
+ [lt_cv_ld_exported_symbols_list=no
+ save_LDFLAGS=$LDFLAGS
+ echo "_main" > conftest.sym
+ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [lt_cv_ld_exported_symbols_list=yes],
+ [lt_cv_ld_exported_symbols_list=no])
+ LDFLAGS="$save_LDFLAGS"
+ ])
+ case $host_os in
+ rhapsody* | darwin1.[[012]])
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+ darwin1.*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ darwin*) # darwin 5.x on
+ # if running on 10.5 or later, the deployment target defaults
+ # to the OS version, if on x86, and 10.4, the deployment
+ # target defaults to 10.4. Don't you love it?
+ case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+ 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ 10.[[012]]*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ 10.*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ esac
+ ;;
+ esac
+ if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+ _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+ else
+ _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+ if test "$DSYMUTIL" != ":"; then
+ _lt_dsymutil='~$DSYMUTIL $lib || :'
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES
+# --------------------------
+# Checks for linker and compiler features on darwin
+m4_defun([_LT_DARWIN_LINKER_FEATURES],
+[
+ m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
+ case $cc_basename in
+ ifort*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test "$_lt_dar_can_shared" = "yes"; then
+ output_verbose_link_cmd=echo
+ _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+ _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+ _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+ m4_if([$1], [CXX],
+[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then
+ _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
+ fi
+],[])
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+])
+
+# _LT_SYS_MODULE_PATH_AIX
+# -----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\(.*\)$/\1/
+ p
+ }
+ }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+ [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+ [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_SHELL_INIT
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[_LT_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$lt_ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+ ;;
+esac
+
+ECHO=${lt_ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X[$]1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $ECHO works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<_LT_EOF
+[$]*
+_LT_EOF
+ exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$lt_ECHO"; then
+ if test "X${echo_test_string+set}" != Xset; then
+ # find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
+ { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null
+ then
+ break
+ fi
+ done
+ fi
+
+ if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+ else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ ECHO="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$ECHO" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ ECHO='print -r'
+ elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+ else
+ # Try using printf.
+ ECHO='printf %s\n'
+ if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ ECHO="$CONFIG_SHELL [$]0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+ if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "[$]0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ ECHO=echo
+ fi
+ fi
+ fi
+ fi
+ fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+lt_ECHO=$ECHO
+if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+ lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(lt_ECHO)
+])
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1],
+ [An echo program that does not interpret backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _LT_ENABLE_LOCK
+# ---------------
+m4_defun([_LT_ENABLE_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+ [AS_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_i386_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_x86_64_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ ppc*-*linux*|powerpc*-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*|s390*-*tpf*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+ [AC_LANG_PUSH(C)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+ AC_LANG_POP])
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+sparc*-*solaris*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*) LD="${LD-ld} -m elf64_sparc" ;;
+ *)
+ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+ LD="${LD-ld} -64"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+esac
+
+need_locks="$enable_libtool_lock"
+])# _LT_ENABLE_LOCK
+
+
+# _LT_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[AC_CHECK_TOOL(AR, ar, false)
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+_LT_DECL([], [AR], [1], [The archiver])
+_LT_DECL([], [AR_FLAGS], [1])
+
+AC_CHECK_TOOL(STRIP, strip, :)
+test -z "$STRIP" && STRIP=:
+_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+test -z "$RANLIB" && RANLIB=:
+_LT_DECL([], [RANLIB], [1],
+ [Commands used to install an old-style archive])
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+_LT_DECL([], [old_postinstall_cmds], [2])
+_LT_DECL([], [old_postuninstall_cmds], [2])
+_LT_TAGDECL([], [old_archive_cmds], [2],
+ [Commands used to build an old-style archive])
+])# _LT_CMD_OLD_ARCHIVE
+
+
+# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([_LT_COMPILER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$3"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ fi
+ $RM conftest*
+])
+
+if test x"[$]$2" = xyes; then
+ m4_if([$5], , :, [$5])
+else
+ m4_if([$6], , :, [$6])
+fi
+])# _LT_COMPILER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+
+
+# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------
+# Check whether the given linker option works
+AC_DEFUN([_LT_LINKER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $3"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&AS_MESSAGE_LOG_FD
+ $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ else
+ $2=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+ m4_if([$4], , :, [$4])
+else
+ m4_if([$5], , :, [$5])
+fi
+])# _LT_LINKER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+
+
+# LT_CMD_MAX_LEN
+#---------------
+AC_DEFUN([LT_CMD_MAX_LEN],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw* | cegcc*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+ if test -n "$lt_cv_sys_max_cmd_len"; then
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ else
+ # Make teststring a little bigger before we do anything with it.
+ # a 1K string should be a reasonable start.
+ for i in 1 2 3 4 5 6 7 8 ; do
+ teststring=$teststring$teststring
+ done
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \
+ = "XX$teststring$teststring"; } >/dev/null 2>&1 &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ # Only check the string length outside the loop.
+ lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on
+ # massive amounts of additional arguments before passing them to the
+ # linker. It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ fi
+ ;;
+ esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+ AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+ AC_MSG_RESULT(none)
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+_LT_DECL([], [max_cmd_len], [0],
+ [What is the maximum length of a command?])
+])# LT_CMD_MAX_LEN
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+
+
+# _LT_HEADER_DLFCN
+# ----------------
+m4_defun([_LT_HEADER_DLFCN],
+[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+])# _LT_HEADER_DLFCN
+
+
+# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ----------------------------------------------------------------
+m4_defun([_LT_TRY_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+ [$4]
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}]
+_LT_EOF
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) $1 ;;
+ x$lt_dlneed_uscore) $2 ;;
+ x$lt_dlunknown|x*) $3 ;;
+ esac
+ else :
+ # compilation failed
+ $3
+ fi
+fi
+rm -fr conftest*
+])# _LT_TRY_DLOPEN_SELF
+
+
+# LT_SYS_DLOPEN_SELF
+# ------------------
+AC_DEFUN([LT_SYS_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32* | cegcc*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ])
+ ;;
+
+ *)
+ AC_CHECK_FUNC([shl_load],
+ [lt_cv_dlopen="shl_load"],
+ [AC_CHECK_LIB([dld], [shl_load],
+ [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"],
+ [AC_CHECK_FUNC([dlopen],
+ [lt_cv_dlopen="dlopen"],
+ [AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+ [AC_CHECK_LIB([svld], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+ [AC_CHECK_LIB([dld], [dld_link],
+ [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"])
+ ])
+ ])
+ ])
+ ])
+ ])
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ AC_CACHE_CHECK([whether a program can dlopen itself],
+ lt_cv_dlopen_self, [dnl
+ _LT_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+ lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+ ])
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+ lt_cv_dlopen_self_static, [dnl
+ _LT_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+ lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
+ ])
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+_LT_DECL([dlopen_support], [enable_dlopen], [0],
+ [Whether dlopen is supported])
+_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+ [Whether dlopen of programs is supported])
+_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+ [Whether dlopen of statically linked programs is supported])
+])# LT_SYS_DLOPEN_SELF
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+
+
+# _LT_COMPILER_C_O([TAGNAME])
+# ---------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler.
+# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+m4_defun([_LT_COMPILER_C_O],
+[m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+ [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+ [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+ fi
+ fi
+ chmod u+w . 2>&AS_MESSAGE_LOG_FD
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+])
+_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+ [Does compiler simultaneously support -c and -o options?])
+])# _LT_COMPILER_C_O
+
+
+# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+# ----------------------------------
+# Check to see if we can do hard links to lock some files if needed
+m4_defun([_LT_COMPILER_FILE_LOCKS],
+[m4_require([_LT_ENABLE_LOCK])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_COMPILER_C_O([$1])
+
+hard_links="nottested"
+if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ AC_MSG_CHECKING([if we can lock with hard links])
+ hard_links=yes
+ $RM conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ AC_MSG_RESULT([$hard_links])
+ if test "$hard_links" = no; then
+ AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+])# _LT_COMPILER_FILE_LOCKS
+
+
+# _LT_CHECK_OBJDIR
+# ----------------
+m4_defun([_LT_CHECK_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+_LT_DECL([], [objdir], [0],
+ [The name of the directory that contains temporary libtool files])dnl
+m4_pattern_allow([LT_OBJDIR])dnl
+AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/",
+ [Define to the sub-directory in which libtool stores uninstalled libraries.])
+])# _LT_CHECK_OBJDIR
+
+
+# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+# --------------------------------------
+# Check hardcoding attributes.
+m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+ test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+ test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+ # We can hardcode non-existent directories.
+ if test "$_LT_TAGVAR(hardcode_direct, $1)" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+ test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then
+ # Linking always hardcodes the temporary library directory.
+ _LT_TAGVAR(hardcode_action, $1)=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ _LT_TAGVAR(hardcode_action, $1)=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ _LT_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_TAGVAR(hardcode_action, $1)" = relink ||
+ test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+_LT_TAGDECL([], [hardcode_action], [0],
+ [How to hardcode a shared library path into an executable])
+])# _LT_LINKER_HARDCODE_LIBPATH
+
+
+# _LT_CMD_STRIPLIB
+# ----------------
+m4_defun([_LT_CMD_STRIPLIB],
+[m4_require([_LT_DECL_EGREP])
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ old_striplib="$STRIP -S"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ ;;
+ *)
+ AC_MSG_RESULT([no])
+ ;;
+ esac
+fi
+_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+_LT_DECL([], [striplib], [1])
+])# _LT_CMD_STRIPLIB
+
+
+# _LT_SYS_DYNAMIC_LINKER([TAG])
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+m4_defun([_LT_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_OBJDUMP])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+ [], [
+if test "$GCC" = yes; then
+ case $host_os in
+ darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+ *) lt_awk_arg="/^libraries:/" ;;
+ esac
+ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ # Ok, now we have the path, separated by spaces, we can step through it
+ # and add multilib dir if necessary.
+ lt_tmp_lt_search_path_spec=
+ lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+ for lt_sys_path in $lt_search_path_spec; do
+ if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+ else
+ test -d "$lt_sys_path" && \
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+ fi
+ done
+ lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+ lt_foo="";
+ lt_count=0;
+ for (lt_i = NF; lt_i > 0; lt_i--) {
+ if ($lt_i != "" && $lt_i != ".") {
+ if ($lt_i == "..") {
+ lt_count++;
+ } else {
+ if (lt_count == 0) {
+ lt_foo="/" $lt_i lt_foo;
+ } else {
+ lt_count--;
+ }
+ }
+ }
+ }
+ if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+ if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+ sys_lib_search_path_spec=`$ECHO $lt_search_path_spec`
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix[[4-9]]*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[[01]] | aix4.[[01]].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ case $host_cpu in
+ powerpc)
+ # Since July 2007 AmigaOS4 officially supports .so libraries.
+ # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ ;;
+ m68k)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+ esac
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[[45]]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+m4_if([$1], [],[
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[[123]]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ *) # from 4.6 on, and DragonFly
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix[[3-9]]*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # Some binutils ld are patched to set DT_RUNPATH
+ save_LDFLAGS=$LDFLAGS
+ save_libdir=$libdir
+ eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+ [shlibpath_overrides_runpath=yes])])
+ LDFLAGS=$save_LDFLAGS
+ libdir=$save_libdir
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsdelf*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='NetBSD ld.elf_so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+*nto* | *qnx*)
+ version_type=qnx
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='ldqnx.so'
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[[89]] | openbsd2.[[89]].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+rdos*)
+ dynamic_linker=no
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+tpf*)
+ # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+ sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+ sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+_LT_DECL([], [variables_saved_for_relink], [1],
+ [Variables whose values should be saved in libtool wrapper scripts and
+ restored at link time])
+_LT_DECL([], [need_lib_prefix], [0],
+ [Do we need the "lib" prefix for modules?])
+_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+_LT_DECL([], [version_type], [0], [Library versioning type])
+_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable])
+_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+_LT_DECL([], [shlibpath_overrides_runpath], [0],
+ [Is shlibpath searched before the hard-coded library search path?])
+_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+_LT_DECL([], [library_names_spec], [1],
+ [[List of archive names. First name is the real one, the rest are links.
+ The last name is the one that the linker finds with -lNAME]])
+_LT_DECL([], [soname_spec], [1],
+ [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [postinstall_cmds], [2],
+ [Command to use after installation of a shared archive])
+_LT_DECL([], [postuninstall_cmds], [2],
+ [Command to use after uninstallation of a shared archive])
+_LT_DECL([], [finish_cmds], [2],
+ [Commands used to finish a libtool library installation in a directory])
+_LT_DECL([], [finish_eval], [1],
+ [[As "finish_cmds", except a single script fragment to be evaled but
+ not shown]])
+_LT_DECL([], [hardcode_into_libs], [0],
+ [Whether we should hardcode library paths into libraries])
+_LT_DECL([], [sys_lib_search_path_spec], [2],
+ [Compile-time system search path for libraries])
+_LT_DECL([], [sys_lib_dlsearch_path_spec], [2],
+ [Run-time system search path for libraries])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program which can recognize shared library
+AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+[m4_require([_LT_DECL_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] | ?:[\\/]*])
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word. This closes a longstanding sh security hole.
+ ac_dummy="m4_if([$2], , $PATH, [$2])"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$1; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool at gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ AC_MSG_RESULT($MAGIC_CMD)
+else
+ AC_MSG_RESULT(no)
+fi
+_LT_DECL([], [MAGIC_CMD], [0],
+ [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+])# _LT_PATH_TOOL_PREFIX
+
+# Old name:
+AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+
+
+# _LT_PATH_MAGIC
+# --------------
+# find a file program which can recognize a shared library
+m4_defun([_LT_PATH_MAGIC],
+[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+ else
+ MAGIC_CMD=:
+ fi
+fi
+])# _LT_PATH_MAGIC
+
+
+# LT_PATH_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([LT_PATH_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+
+AC_ARG_WITH([gnu-ld],
+ [AS_HELP_STRING([--with-gnu-ld],
+ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+ [test "$withval" = no || with_gnu_ld=yes],
+ [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by $CC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]]* | ?:[[\\/]]*)
+ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+_LT_PATH_LD_GNU
+AC_SUBST([LD])
+
+_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
+])# LT_PATH_LD
+
+# Old names:
+AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
+AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_LD], [])
+dnl AC_DEFUN([AC_PROG_LD], [])
+
+
+# _LT_PATH_LD_GNU
+#- --------------
+m4_defun([_LT_PATH_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# _LT_PATH_LD_GNU
+
+
+# _LT_CMD_RELOAD
+# --------------
+# find reload flag for linker
+# -- PORTME Some linkers may need a different reload flag.
+m4_defun([_LT_CMD_RELOAD],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+ lt_cv_ld_reload_flag,
+ [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+_LT_DECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_DECL([], [reload_cmds], [2])dnl
+])# _LT_CMD_RELOAD
+
+
+# _LT_CHECK_MAGIC_METHOD
+# ----------------------
+# how to check for library dependencies
+# -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_MAGIC_METHOD],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[[45]]*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump',
+ # unless we find 'file', for example because we are cross-compiling.
+ if ( file / ) >/dev/null 2>&1; then
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ else
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ fi
+ ;;
+
+cegcc)
+ # use the weaker test based on 'objdump'. See mingw*.
+ lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | dragonfly*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix[[3-9]]*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+*nto* | *qnx*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+rdos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+tpf*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+_LT_DECL([], [deplibs_check_method], [1],
+ [Method to check whether dependent libraries are shared objects])
+_LT_DECL([], [file_magic_cmd], [1],
+ [Command to use when deplibs_check_method == "file_magic"])
+])# _LT_CHECK_MAGIC_METHOD
+
+
+# LT_PATH_NM
+# ----------
+# find the pathname to a BSD- or MS-compatible name lister
+AC_DEFUN([LT_PATH_NM],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+[if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_nm_to_check="${ac_tool_prefix}nm"
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/$lt_tmp_nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ done
+ : ${lt_cv_path_NM=no}
+fi])
+if test "$lt_cv_path_NM" != "no"; then
+ NM="$lt_cv_path_NM"
+else
+ # Didn't find any BSD compatible name lister, look for dumpbin.
+ AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :)
+ AC_SUBST([DUMPBIN])
+ if test "$DUMPBIN" != ":"; then
+ NM="$DUMPBIN"
+ fi
+fi
+test -z "$NM" && NM=nm
+AC_SUBST([NM])
+_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+
+AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+ [lt_cv_nm_interface="BSD nm"
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$ac_compile" 2>conftest.err)
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD)
+ cat conftest.out >&AS_MESSAGE_LOG_FD
+ if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+ lt_cv_nm_interface="MS dumpbin"
+ fi
+ rm -f conftest*])
+])# LT_PATH_NM
+
+# Old names:
+AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_NM], [])
+dnl AC_DEFUN([AC_PROG_NM], [])
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+ AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+ ;;
+*)
+ AC_CHECK_LIB(m, cos, LIBM="-lm")
+ ;;
+esac
+AC_SUBST([LIBM])
+])# LT_LIB_M
+
+# Old name:
+AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_CHECK_LIBM], [])
+
+
+# _LT_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------
+m4_defun([_LT_COMPILER_NO_RTTI],
+[m4_require([_LT_TAG_COMPILER])dnl
+
+_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+ _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+ lt_cv_prog_compiler_rtti_exceptions,
+ [-fno-rtti -fno-exceptions], [],
+ [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+ [Compiler flag to turn off builtin functions])
+])# _LT_COMPILER_NO_RTTI
+
+
+# _LT_CMD_GLOBAL_SYMBOLS
+# ----------------------
+m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[[BCDT]]'
+ ;;
+cygwin* | mingw* | pw32* | cegcc*)
+ symcode='[[ABCDGISTW]]'
+ ;;
+hpux*)
+ if test "$host_cpu" = ia64; then
+ symcode='[[ABCDEGRST]]'
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[[BCDEGRST]]'
+ ;;
+osf*)
+ symcode='[[BCDEGQRST]]'
+ ;;
+solaris*)
+ symcode='[[BDRT]]'
+ ;;
+sco3.2v5*)
+ symcode='[[DT]]'
+ ;;
+sysv4.2uw2*)
+ symcode='[[DT]]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[[ABDT]]'
+ ;;
+sysv4)
+ symcode='[[DFNSTU]]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Fake it for dumpbin and say T for any non-static function
+ # and D for any global variable.
+ # Also find C++ and __fastcall symbols from MSVC++,
+ # which start with @ or ?.
+ lt_cv_sys_global_symbol_pipe="$AWK ['"\
+" {last_section=section; section=\$ 3};"\
+" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+" s[1]~/^[@?]/{print s[1], s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+" ' prfx=^$ac_symprfx]"
+ else
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+ fi
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+ if AC_TRY_EVAL(ac_compile); then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+ if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<_LT_EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+ cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ void *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+ { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+ cat <<\_LT_EOF >> conftest.$ac_ext
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_save_LIBS="$LIBS"
+ lt_save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS="$lt_save_LIBS"
+ CFLAGS="$lt_save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+ cat conftest.$ac_ext >&5
+ fi
+ rm -rf conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ AC_MSG_RESULT(failed)
+else
+ AC_MSG_RESULT(ok)
+fi
+
+_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+ [Take the output of nm and produce a listing of raw symbols and C names])
+_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+ [Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_c_name_address],
+ [lt_cv_sys_global_symbol_to_c_name_address], [1],
+ [Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+ [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+ [Transform the output of nm in a C name address pair when lib prefix is needed])
+]) # _LT_CMD_GLOBAL_SYMBOLS
+
+
+# _LT_COMPILER_PIC([TAGNAME])
+# ---------------------------
+m4_defun([_LT_COMPILER_PIC],
+[m4_require([_LT_TAG_COMPILER])dnl
+_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_TAGVAR(lt_prog_compiler_static, $1)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+m4_if([$1], [CXX], [
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | cygwin* | os2* | pw32* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ interix[[3-9]]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix[[4-9]]*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | dragonfly*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ if test "$host_cpu" != ia64; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ fi
+ ;;
+ aCC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux* | k*bsd*-gnu)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ ecpc* )
+ # old Intel C++ for x86_64 which still supported -KPIC.
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ icpc* )
+ # Intel C++, used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ xlc* | xlC*)
+ # IBM XL 8.0 on PPC
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd* | netbsdelf*-gnu)
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+],
+[
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+
+ interix[[3-9]]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ enable_shared=no
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC (with -KPIC) is the default.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ linux* | k*bsd*-gnu)
+ case $cc_basename in
+ # old Intel for x86_64 which still supported -KPIC.
+ ecc*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ # icc used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ icc* | ifort*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ # Lahey Fortran 8.1.
+ lf95*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ ccc*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All Alpha code is PIC.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ xl*)
+ # IBM XL C 8.0/Fortran 10.1 on PPC
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C 5.9
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ *Sun\ F*)
+ # Sun Fortran 8.3 passes all unrecognized flags to the linker
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ newsos6)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+
+ osf3* | osf4* | osf5*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All OSF/1 code is PIC.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ rdos*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ solaris*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ unicos*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+
+ uts4*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *)
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+])
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t at m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+ ;;
+esac
+AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+ [How to pass a linker flag through the compiler])
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+ [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+ [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t at m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+ [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+ "" | " "*) ;;
+ *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+ esac],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+ [Additional compiler flags for building library objects])
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+ _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+ $lt_tmp_static_flag,
+ [],
+ [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+ [Compiler flag to prevent dynamic linking])
+])# _LT_COMPILER_PIC
+
+
+# _LT_LINKER_SHLIBS([TAGNAME])
+# ----------------------------
+# See if the linker supports building shared libraries.
+m4_defun([_LT_LINKER_SHLIBS],
+[AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+m4_if([$1], [CXX], [
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+ aix[[4-9]]*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+ ;;
+ cygwin* | mingw* | cegcc*)
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ linux* | k*bsd*-gnu)
+ _LT_TAGVAR(link_all_deplibs, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+], [
+ runpath_var=
+ _LT_TAGVAR(allow_undefined_flag, $1)=
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(archive_cmds, $1)=
+ _LT_TAGVAR(archive_expsym_cmds, $1)=
+ _LT_TAGVAR(compiler_needs_object, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(hardcode_automatic, $1)=no
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ _LT_TAGVAR(hardcode_minus_L, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_TAGVAR(inherit_rpath, $1)=no
+ _LT_TAGVAR(link_all_deplibs, $1)=unknown
+ _LT_TAGVAR(module_cmds, $1)=
+ _LT_TAGVAR(module_expsym_cmds, $1)=
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+ _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+ _LT_TAGVAR(thread_safe_flag_spec, $1)=
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ _LT_TAGVAR(include_expsyms, $1)=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>&1` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix[[3-9]]*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+_LT_EOF
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)=''
+ ;;
+ m68k)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3 at best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ interix[[3-9]]*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ gnu* | linux* | tpf* | k*bsd*-gnu)
+ tmp_diet=no
+ if test "$host_os" = linux-dietlibc; then
+ case $cc_basename in
+ diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
+ esac
+ fi
+ if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+ && test "$tmp_diet" = no
+ then
+ tmp_addflag=
+ tmp_sharedflag='-shared'
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ lf95*) # Lahey Fortran 8.1
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ tmp_sharedflag='--shared' ;;
+ xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+ tmp_sharedflag='-qmkshrobj'
+ tmp_addflag= ;;
+ esac
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*) # Sun C 5.9
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+ tmp_sharedflag='-G' ;;
+ *Sun\ F*) # Sun Fortran 8.3
+ tmp_sharedflag='-G' ;;
+ esac
+ _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test "x$supports_anon_versioning" = xyes; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+
+ case $cc_basename in
+ xlf*)
+ # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+ _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+ if test "x$supports_anon_versioning" = xyes; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ esac
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+
+ if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then
+ runpath_var=
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_TAGVAR(archive_cmds, $1)=''
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ _LT_TAGVAR(link_all_deplibs, $1)=no
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)=''
+ ;;
+ m68k)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ ;;
+
+ bsdi[[45]]*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+ # FIXME: Should let the user specify the lib program.
+ _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+ _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+
+ darwin* | rhapsody*)
+ _LT_DARWIN_LINKER_FEATURES($1)
+ ;;
+
+ dgux*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ freebsd1*)
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | dragonfly*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ # Try to use the -exported_symbol ld option, if it does not
+ # work, assume that -exports_file does not work either and
+ # implicitly export all symbols.
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+ AC_LINK_IFELSE(int foo(void) {},
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+ )
+ LDFLAGS="$save_LDFLAGS"
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(inherit_rpath, $1)=yes
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ newsos6)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *nto* | *qnx*)
+ ;;
+
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ else
+ case $host_os in
+ openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ os2*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ else
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ solaris*)
+ _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ else
+ case `$CC -V 2>&1` in
+ *"Compilers 5.0"*)
+ wlarc=''
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+ ;;
+ *)
+ wlarc='${wl}'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ ;;
+ esac
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands `-z linker_flag'. GCC discards it without `$wl',
+ # but is careful enough not to reorder.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+ fi
+ ;;
+ esac
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ ;;
+ motorola)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4.3*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+
+ if test x$host_vendor = xsni; then
+ case $host in
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym'
+ ;;
+ esac
+ fi
+ fi
+])
+AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+
+_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+_LT_DECL([], [extract_expsyms_cmds], [2],
+ [The commands to extract the exported symbol list from a shared archive])
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+ # Assume -lc should be added
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $_LT_TAGVAR(archive_cmds, $1) in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+ $RM conftest*
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+ pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+ _LT_TAGVAR(allow_undefined_flag, $1)=
+ if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+ then
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ else
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ fi
+ _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $RM conftest*
+ AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)])
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+ [Whether or not to add -lc for building shared libraries])
+_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+ [enable_shared_with_static_runtimes], [0],
+ [Whether or not to disallow shared libs when runtime libs are static])
+_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+ [Compiler flag to allow reflexive dlopens])
+_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+ [Compiler flag to generate shared objects directly from archives])
+_LT_TAGDECL([], [compiler_needs_object], [1],
+ [Whether the compiler copes with passing no objects directly])
+_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+ [Create an old-style archive from a shared archive])
+_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+ [Create a temporary old-style archive to link instead of a shared archive])
+_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+_LT_TAGDECL([], [archive_expsym_cmds], [2])
+_LT_TAGDECL([], [module_cmds], [2],
+ [Commands used to build a loadable module if different from building
+ a shared archive.])
+_LT_TAGDECL([], [module_expsym_cmds], [2])
+_LT_TAGDECL([], [with_gnu_ld], [1],
+ [Whether we are building with GNU ld or not])
+_LT_TAGDECL([], [allow_undefined_flag], [1],
+ [Flag that allows shared libraries with undefined symbols to be built])
+_LT_TAGDECL([], [no_undefined_flag], [1],
+ [Flag that enforces no undefined symbols])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+ [Flag to hardcode $libdir into a binary during linking.
+ This must work even if $libdir does not exist])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1],
+ [[If ld is used when linking, flag to hardcode $libdir into a binary
+ during linking. This must work even if $libdir does not exist]])
+_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+ [Whether we need a single "-rpath" flag with a separated argument])
+_LT_TAGDECL([], [hardcode_direct], [0],
+ [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+ DIR into the resulting binary])
+_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+ [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+ DIR into the resulting binary and the resulting library dependency is
+ "absolute", i.e impossible to change by setting ${shlibpath_var} if the
+ library is relocated])
+_LT_TAGDECL([], [hardcode_minus_L], [0],
+ [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+ into the resulting binary])
+_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+ [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+ into the resulting binary])
+_LT_TAGDECL([], [hardcode_automatic], [0],
+ [Set to "yes" if building a shared library automatically hardcodes DIR
+ into the library and all subsequent libraries and executables linked
+ against it])
+_LT_TAGDECL([], [inherit_rpath], [0],
+ [Set to yes if linker adds runtime paths of dependent libraries
+ to runtime path list])
+_LT_TAGDECL([], [link_all_deplibs], [0],
+ [Whether libtool must link a program against all its dependency libraries])
+_LT_TAGDECL([], [fix_srcfile_path], [1],
+ [Fix the shell variable $srcfile for the compiler])
+_LT_TAGDECL([], [always_export_symbols], [0],
+ [Set to "yes" if exported symbols are required])
+_LT_TAGDECL([], [export_symbols_cmds], [2],
+ [The commands to list exported symbols])
+_LT_TAGDECL([], [exclude_expsyms], [1],
+ [Symbols that should not be listed in the preloaded symbols])
+_LT_TAGDECL([], [include_expsyms], [1],
+ [Symbols that must always be exported])
+_LT_TAGDECL([], [prelink_cmds], [2],
+ [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [file_list_spec], [1],
+ [Specify filename containing input files])
+dnl FIXME: Not yet implemented
+dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+dnl [Compiler flag to generate thread safe objects])
+])# _LT_LINKER_SHLIBS
+
+
+# _LT_LANG_C_CONFIG([TAG])
+# ------------------------
+# Ensure that the configuration variables for a C compiler are suitably
+# defined. These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_C_CONFIG],
+[m4_require([_LT_DECL_EGREP])dnl
+lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_TAG_COMPILER
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+ LT_SYS_DLOPEN_SELF
+ _LT_CMD_STRIPLIB
+
+ # Report which library types will actually be built
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test "$can_build_shared" = "no" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test "$enable_shared" = yes || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC="$lt_save_CC"
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_PROG_CXX
+# ------------
+# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++
+# compiler, we have our own version here.
+m4_defun([_LT_PROG_CXX],
+[
+pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes])
+AC_PROG_CXX
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ AC_PROG_CXXCPP
+else
+ _lt_caught_CXX_error=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_CXX
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_CXX], [])
+
+
+# _LT_LANG_CXX_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a C++ compiler are suitably
+# defined. These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_CXX_CONFIG],
+[AC_REQUIRE([_LT_PROG_CXX])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+
+AC_LANG_PUSH(C++)
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(compiler_needs_object, $1)=no
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_caught_CXX_error" != yes; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="int some_variable = 0;"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC=$CC
+ lt_save_LD=$LD
+ lt_save_GCC=$GCC
+ GCC=$GXX
+ lt_save_with_gnu_ld=$with_gnu_ld
+ lt_save_path_LD=$lt_cv_path_LD
+ if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+ else
+ $as_unset lt_cv_prog_gnu_ld
+ fi
+ if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+ else
+ $as_unset lt_cv_path_LD
+ fi
+ test -z "${LDCXX+set}" || LD=$LDCXX
+ CC=${CXX-"c++"}
+ compiler=$CC
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+
+ if test -n "$compiler"; then
+ # We don't want -fno-exception when compiling C++ code, so set the
+ # no_builtin_flag separately
+ if test "$GXX" = yes; then
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+ else
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+ fi
+
+ if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+ LT_PATH_LD
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+ $GREP 'no-whole-archive' > /dev/null; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+
+ else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+ fi
+
+ # PORTME: fill in a description of your system's C++ link characteristics
+ AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aix[[4-9]]*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_TAGVAR(archive_cmds, $1)=''
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to
+ # export.
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an empty
+ # executable.
+ _LT_SYS_MODULE_PATH_AIX
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared
+ # libraries.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3 at best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ darwin* | rhapsody*)
+ _LT_DARWIN_LINKER_FEATURES($1)
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ freebsd[[12]]*)
+ # C++ shared libraries reported to be fairly broken before
+ # switch to ELF
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ freebsd-elf*)
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ ;;
+
+ freebsd* | dragonfly*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+
+ gnu*)
+ ;;
+
+ hpux9*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ interix[[3-9]]*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib'
+ fi
+ fi
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+ esac
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(inherit_rpath, $1)=yes
+ ;;
+
+ linux* | k*bsd*-gnu)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc* | ecpc* )
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ case `$CC -V` in
+ *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*)
+ _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+ compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"'
+ _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~
+ $RANLIB $oldlib'
+ _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ ;;
+ *) # Version 6 will use weak symbols
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ xl*)
+ # IBM XL 8.0 on PPC, with GNU ld
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ if test "x$supports_anon_versioning" = xyes; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+
+ # Not sure whether something based on
+ # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+ # would be better.
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ m88k*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+
+ *nto* | *qnx*)
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd=echo
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ case $host in
+ osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+ *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+ esac
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx*)
+ case $host in
+ osf3*)
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ ;;
+ *)
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~
+ $RM $lib.exp'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ case $host in
+ osf3*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ psos*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+ _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands `-z linker_flag'.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+ ;;
+ esac
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+ if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'
+ fi
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+
+ AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+ test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+ _LT_TAGVAR(GCC, $1)="$GXX"
+ _LT_TAGVAR(LD, $1)="$LD"
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_SYS_HIDDEN_LIBDEPS($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ CC=$lt_save_CC
+ LDCXX=$LD
+ LD=$lt_save_LD
+ GCC=$lt_save_GCC
+ with_gnu_ld=$lt_save_with_gnu_ld
+ lt_cv_path_LDCXX=$lt_cv_path_LD
+ lt_cv_path_LD=$lt_save_path_LD
+ lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+ lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test "$_lt_caught_CXX_error" != yes
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+# ---------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+# Dependencies to place before and after the object being linked:
+_LT_TAGVAR(predep_objects, $1)=
+_LT_TAGVAR(postdep_objects, $1)=
+_LT_TAGVAR(predeps, $1)=
+_LT_TAGVAR(postdeps, $1)=
+_LT_TAGVAR(compiler_lib_search_path, $1)=
+
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library. It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+int a;
+void foo (void) { a = 0; }
+_LT_EOF
+], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+_LT_EOF
+], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+ subroutine foo
+ implicit none
+ integer*4 a
+ a=0
+ return
+ end
+_LT_EOF
+], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+ subroutine foo
+ implicit none
+ integer a
+ a=0
+ return
+ end
+_LT_EOF
+], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+public class foo {
+ private int a;
+ public void bar (void) {
+ a = 0;
+ }
+};
+_LT_EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ for p in `eval "$output_verbose_link_cmd"`; do
+ case $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" ||
+ test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p in
+ -L* | -R*)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+ _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+ else
+ _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+ _LT_TAGVAR(postdeps, $1)="${prev}${p}"
+ else
+ _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}"
+ fi
+ fi
+ ;;
+
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+ _LT_TAGVAR(predep_objects, $1)="$p"
+ else
+ _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+ fi
+ else
+ if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+ _LT_TAGVAR(postdep_objects, $1)="$p"
+ else
+ _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$RM -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+m4_if([$1], [CXX],
+[case $host_os in
+interix[[3-9]]*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ _LT_TAGVAR(predep_objects,$1)=
+ _LT_TAGVAR(postdep_objects,$1)=
+ _LT_TAGVAR(postdeps,$1)=
+ ;;
+
+linux*)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ if test "$solaris_use_stlport4" != yes; then
+ _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC*)
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ if test "$solaris_use_stlport4" != yes; then
+ _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+esac
+])
+
+case " $_LT_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
+fi
+_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+ [The directories searched by this compiler when creating a shared library])
+_LT_TAGDECL([], [predep_objects], [1],
+ [Dependencies to place before and after the objects being linked to
+ create a shared library])
+_LT_TAGDECL([], [postdep_objects], [1])
+_LT_TAGDECL([], [predeps], [1])
+_LT_TAGDECL([], [postdeps], [1])
+_LT_TAGDECL([], [compiler_lib_search_path], [1],
+ [The library search path used internally by the compiler when linking
+ a shared library])
+])# _LT_SYS_HIDDEN_LIBDEPS
+
+
+# _LT_PROG_F77
+# ------------
+# Since AC_PROG_F77 is broken, in that it returns the empty string
+# if there is no fortran compiler, we have our own version here.
+m4_defun([_LT_PROG_F77],
+[
+pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes])
+AC_PROG_F77
+if test -z "$F77" || test "X$F77" = "Xno"; then
+ _lt_disable_F77=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_F77
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_F77], [])
+
+
+# _LT_LANG_F77_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a Fortran 77 compiler are
+# suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_F77_CONFIG],
+[AC_REQUIRE([_LT_PROG_F77])dnl
+AC_LANG_PUSH(Fortran 77)
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the F77 compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_F77" != yes; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="\
+ subroutine t
+ return
+ end
+"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code="\
+ program t
+ end
+"
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC="$CC"
+ lt_save_GCC=$GCC
+ CC=${F77-"f77"}
+ compiler=$CC
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+ GCC=$G77
+ if test -n "$compiler"; then
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test "$can_build_shared" = "no" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test "$enable_shared" = yes || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_TAGVAR(GCC, $1)="$G77"
+ _LT_TAGVAR(LD, $1)="$LD"
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ GCC=$lt_save_GCC
+ CC="$lt_save_CC"
+fi # test "$_lt_disable_F77" != yes
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_PROG_FC
+# -----------
+# Since AC_PROG_FC is broken, in that it returns the empty string
+# if there is no fortran compiler, we have our own version here.
+m4_defun([_LT_PROG_FC],
+[
+pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes])
+AC_PROG_FC
+if test -z "$FC" || test "X$FC" = "Xno"; then
+ _lt_disable_FC=yes
+fi
+popdef([AC_MSG_ERROR])
+])# _LT_PROG_FC
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([_LT_PROG_FC], [])
+
+
+# _LT_LANG_FC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for a Fortran compiler are
+# suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_FC_CONFIG],
+[AC_REQUIRE([_LT_PROG_FC])dnl
+AC_LANG_PUSH(Fortran)
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for fc test sources.
+ac_ext=${ac_fc_srcext-f}
+
+# Object file extension for compiled fc test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the FC compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_FC" != yes; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="\
+ subroutine t
+ return
+ end
+"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code="\
+ program t
+ end
+"
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC="$CC"
+ lt_save_GCC=$GCC
+ CC=${FC-"f95"}
+ compiler=$CC
+ GCC=$ac_cv_fc_compiler_gnu
+
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+
+ if test -n "$compiler"; then
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test "$can_build_shared" = "no" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test "$enable_shared" = yes || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu"
+ _LT_TAGVAR(LD, $1)="$LD"
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_SYS_HIDDEN_LIBDEPS($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ GCC=$lt_save_GCC
+ CC="$lt_save_CC"
+fi # test "$_lt_disable_FC" != yes
+
+AC_LANG_POP
+])# _LT_LANG_FC_CONFIG
+
+
+# _LT_LANG_GCJ_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Java Compiler compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_GCJ_CONFIG],
+[AC_REQUIRE([LT_PROG_GCJ])dnl
+AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)="$LD"
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC="$lt_save_CC"
+])# _LT_LANG_GCJ_CONFIG
+
+
+# _LT_LANG_RC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for the Windows resource compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_RC_CONFIG],
+[AC_REQUIRE([LT_PROG_RC])dnl
+AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+if test -n "$compiler"; then
+ :
+ _LT_CONFIG($1)
+fi
+
+GCC=$lt_save_GCC
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# _LT_LANG_RC_CONFIG
+
+
+# LT_PROG_GCJ
+# -----------
+AC_DEFUN([LT_PROG_GCJ],
+[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+ [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+ [AC_CHECK_TOOL(GCJ, gcj,)
+ test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+ AC_SUBST(GCJFLAGS)])])[]dnl
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+
+
+# LT_PROG_RC
+# ----------
+AC_DEFUN([LT_PROG_RC],
+[AC_CHECK_TOOL(RC, windres,)
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_RC], [])
+
+
+# _LT_DECL_EGREP
+# --------------
+# If we don't have a new enough Autoconf to choose the best grep
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_EGREP],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_REQUIRE([AC_PROG_FGREP])dnl
+test -z "$GREP" && GREP=grep
+_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+_LT_DECL([], [EGREP], [1], [An ERE matcher])
+_LT_DECL([], [FGREP], [1], [A literal string matcher])
+dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+AC_SUBST([GREP])
+])
+
+
+# _LT_DECL_OBJDUMP
+# --------------
+# If we don't have a new enough Autoconf to choose the best objdump
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_OBJDUMP],
+[AC_CHECK_TOOL(OBJDUMP, objdump, false)
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
+AC_SUBST([OBJDUMP])
+])
+
+
+# _LT_DECL_SED
+# ------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible. Prefer GNU sed if found.
+m4_defun([_LT_DECL_SED],
+[AC_PROG_SED
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+ [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+])# _LT_DECL_SED
+
+m4_ifndef([AC_PROG_SED], [
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_SED. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+
+m4_defun([AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f $lt_ac_sed && continue
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test $lt_ac_count -gt 10 && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test $lt_ac_count -gt $lt_ac_max; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])#AC_PROG_SED
+])#m4_ifndef
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_SED], [])
+
+
+# _LT_CHECK_SHELL_FEATURES
+# ------------------------
+# Find out whether the shell is Bourne or XSI compatible,
+# or has some other useful features.
+m4_defun([_LT_CHECK_SHELL_FEATURES],
+[AC_MSG_CHECKING([whether the shell understands some XSI constructs])
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+ test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+ = c,a/b,, \
+ && eval 'test $(( 1 + 1 )) -eq 2 \
+ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+ && xsi_shell=yes
+AC_MSG_RESULT([$xsi_shell])
+_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
+
+AC_MSG_CHECKING([whether the shell understands "+="])
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \
+ >/dev/null 2>&1 \
+ && lt_shell_append=yes
+AC_MSG_RESULT([$lt_shell_append])
+_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ lt_unset=unset
+else
+ lt_unset=false
+fi
+_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ lt_SP2NL='tr \040 \012'
+ lt_NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ lt_SP2NL='tr \100 \n'
+ lt_NL2SP='tr \r\n \100\100'
+ ;;
+esac
+_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+])# _LT_CHECK_SHELL_FEATURES
+
+
+# _LT_PROG_XSI_SHELLFNS
+# ---------------------
+# Bourne and XSI compatible variants of some useful shell functions.
+m4_defun([_LT_PROG_XSI_SHELLFNS],
+[case $xsi_shell in
+ yes)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+ case ${1} in
+ */*) func_dirname_result="${1%/*}${2}" ;;
+ * ) func_dirname_result="${3}" ;;
+ esac
+}
+
+# func_basename file
+func_basename ()
+{
+ func_basename_result="${1##*/}"
+}
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+# dirname: Compute the dirname of FILE. If nonempty,
+# add APPEND to the result, otherwise set result
+# to NONDIR_REPLACEMENT.
+# value returned in "$func_dirname_result"
+# basename: Compute filename of FILE.
+# value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+ case ${1} in
+ */*) func_dirname_result="${1%/*}${2}" ;;
+ * ) func_dirname_result="${3}" ;;
+ esac
+ func_basename_result="${1##*/}"
+}
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+func_stripname ()
+{
+ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+ # positional parameters, so assign one to ordinary parameter first.
+ func_stripname_result=${3}
+ func_stripname_result=${func_stripname_result#"${1}"}
+ func_stripname_result=${func_stripname_result%"${2}"}
+}
+
+# func_opt_split
+func_opt_split ()
+{
+ func_opt_split_opt=${1%%=*}
+ func_opt_split_arg=${1#*=}
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+ case ${1} in
+ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+ *) func_lo2o_result=${1} ;;
+ esac
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+ func_xform_result=${1%.*}.lo
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+ func_arith_result=$(( $[*] ))
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+ func_len_result=${#1}
+}
+
+_LT_EOF
+ ;;
+ *) # Bourne compatible functions.
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+ # Extract subdirectory from the argument.
+ func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+ if test "X$func_dirname_result" = "X${1}"; then
+ func_dirname_result="${3}"
+ else
+ func_dirname_result="$func_dirname_result${2}"
+ fi
+}
+
+# func_basename file
+func_basename ()
+{
+ func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+dnl func_dirname_and_basename
+dnl A portable version of this function is already defined in general.m4sh
+dnl so there is no need for it here.
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+ case ${2} in
+ .*) func_stripname_result=`$ECHO "X${3}" \
+ | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;;
+ *) func_stripname_result=`$ECHO "X${3}" \
+ | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;;
+ esac
+}
+
+# sed scripts:
+my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q'
+my_sed_long_arg='1s/^-[[^=]]*=//'
+
+# func_opt_split
+func_opt_split ()
+{
+ func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"`
+ func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"`
+}
+
+# func_lo2o object
+func_lo2o ()
+{
+ func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"`
+}
+
+# func_xform libobj-or-source
+func_xform ()
+{
+ func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'`
+}
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+ func_arith_result=`expr "$[@]"`
+}
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+ func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len`
+}
+
+_LT_EOF
+esac
+
+case $lt_shell_append in
+ yes)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+ eval "$[1]+=\$[2]"
+}
+_LT_EOF
+ ;;
+ *)
+ cat << \_LT_EOF >> "$cfgfile"
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+ eval "$[1]=\$$[1]\$[2]"
+}
+
+_LT_EOF
+ ;;
+ esac
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+#
+# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltoptions.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+
+
+# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+# ------------------------------------------
+m4_define([_LT_MANGLE_OPTION],
+[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+
+
+# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+# ---------------------------------------
+# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+# matching handler defined, dispatch to it. Other OPTION-NAMEs are
+# saved as a flag.
+m4_define([_LT_SET_OPTION],
+[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+ _LT_MANGLE_DEFUN([$1], [$2]),
+ [m4_warning([Unknown $1 option `$2'])])[]dnl
+])
+
+
+# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+# ------------------------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+m4_define([_LT_IF_OPTION],
+[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+
+
+# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+# -------------------------------------------------------
+# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+# are set.
+m4_define([_LT_UNLESS_OPTIONS],
+[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+ [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+ [m4_define([$0_found])])])[]dnl
+m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+])[]dnl
+])
+
+
+# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+# ----------------------------------------
+# OPTION-LIST is a space-separated list of Libtool options associated
+# with MACRO-NAME. If any OPTION has a matching handler declared with
+# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+# the unknown option and exit.
+m4_defun([_LT_SET_OPTIONS],
+[# Set options
+m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+ [_LT_SET_OPTION([$1], _LT_Option)])
+
+m4_if([$1],[LT_INIT],[
+ dnl
+ dnl Simply set some default values (i.e off) if boolean options were not
+ dnl specified:
+ _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+ ])
+ _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+ ])
+ dnl
+ dnl If no reference was made to various pairs of opposing options, then
+ dnl we run the default mode handler for the pair. For example, if neither
+ dnl `shared' nor `disable-shared' was passed, we enable building of shared
+ dnl archives by default:
+ _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+ _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+ _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+ _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+ [_LT_ENABLE_FAST_INSTALL])
+ ])
+])# _LT_SET_OPTIONS
+
+
+
+# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+# -----------------------------------------
+m4_define([_LT_MANGLE_DEFUN],
+[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+
+
+# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+# -----------------------------------------------
+m4_define([LT_OPTION_DEFINE],
+[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+])# LT_OPTION_DEFINE
+
+
+# dlopen
+# ------
+LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+])
+
+AU_DEFUN([AC_LIBTOOL_DLOPEN],
+[_LT_SET_OPTION([LT_INIT], [dlopen])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `dlopen' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+
+
+# win32-dll
+# ---------
+# Declare package support for building win32 dll's.
+LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+[enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*)
+ AC_CHECK_TOOL(AS, as, false)
+ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+ AC_CHECK_TOOL(OBJDUMP, objdump, false)
+ ;;
+esac
+
+test -z "$AS" && AS=as
+_LT_DECL([], [AS], [0], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl
+])# win32-dll
+
+AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+_LT_SET_OPTION([LT_INIT], [win32-dll])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `win32-dll' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+
+
+# _LT_ENABLE_SHARED([DEFAULT])
+# ----------------------------
+# implement the --enable-shared flag, and supports the `shared' and
+# `disable-shared' LT_INIT options.
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_SHARED],
+[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([shared],
+ [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+ [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+
+ _LT_DECL([build_libtool_libs], [enable_shared], [0],
+ [Whether or not to build shared libraries])
+])# _LT_ENABLE_SHARED
+
+LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+])
+
+AC_DEFUN([AC_DISABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], [disable-shared])
+])
+
+AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+
+
+
+# _LT_ENABLE_STATIC([DEFAULT])
+# ----------------------------
+# implement the --enable-static flag, and support the `static' and
+# `disable-static' LT_INIT options.
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_STATIC],
+[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([static],
+ [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+ [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+
+ _LT_DECL([build_old_libs], [enable_static], [0],
+ [Whether or not to build static libraries])
+])# _LT_ENABLE_STATIC
+
+LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+])
+
+AC_DEFUN([AC_DISABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], [disable-static])
+])
+
+AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+
+
+
+# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+# ----------------------------------
+# implement the --enable-fast-install flag, and support the `fast-install'
+# and `disable-fast-install' LT_INIT options.
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_FAST_INSTALL],
+[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([fast-install],
+ [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+ [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+
+_LT_DECL([fast_install], [enable_fast_install], [0],
+ [Whether or not to optimize for fast installation])dnl
+])# _LT_ENABLE_FAST_INSTALL
+
+LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+
+# Old names:
+AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `fast-install' option into LT_INIT's first parameter.])
+])
+
+AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `disable-fast-install' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+
+
+# _LT_WITH_PIC([MODE])
+# --------------------
+# implement the --with-pic flag, and support the `pic-only' and `no-pic'
+# LT_INIT options.
+# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
+m4_define([_LT_WITH_PIC],
+[AC_ARG_WITH([pic],
+ [AS_HELP_STRING([--with-pic],
+ [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+ [pic_mode="$withval"],
+ [pic_mode=default])
+
+test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
+
+_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+])# _LT_WITH_PIC
+
+LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+
+# Old name:
+AU_DEFUN([AC_LIBTOOL_PICMODE],
+[_LT_SET_OPTION([LT_INIT], [pic-only])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `pic-only' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+
+
+m4_define([_LTDL_MODE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+ [m4_define([_LTDL_MODE], [nonrecursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+ [m4_define([_LTDL_MODE], [recursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+ [m4_define([_LTDL_MODE], [subproject])])
+
+m4_define([_LTDL_TYPE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [installable],
+ [m4_define([_LTDL_TYPE], [installable])])
+LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+ [m4_define([_LTDL_TYPE], [convenience])])
+
+# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
+#
+# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltsugar.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+
+
+# lt_join(SEP, ARG1, [ARG2...])
+# -----------------------------
+# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+# associated separator.
+# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+# versions in m4sugar had bugs.
+m4_define([lt_join],
+[m4_if([$#], [1], [],
+ [$#], [2], [[$2]],
+ [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+m4_define([_lt_join],
+[m4_if([$#$2], [2], [],
+ [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+
+
+# lt_car(LIST)
+# lt_cdr(LIST)
+# ------------
+# Manipulate m4 lists.
+# These macros are necessary as long as will still need to support
+# Autoconf-2.59 which quotes differently.
+m4_define([lt_car], [[$1]])
+m4_define([lt_cdr],
+[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+ [$#], 1, [],
+ [m4_dquote(m4_shift($@))])])
+m4_define([lt_unquote], $1)
+
+
+# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+# ------------------------------------------
+# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
+# Note that neither SEPARATOR nor STRING are expanded; they are appended
+# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+# than defined and empty).
+#
+# This macro is needed until we can rely on Autoconf 2.62, since earlier
+# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+m4_define([lt_append],
+[m4_define([$1],
+ m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+
+
+
+# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+# ----------------------------------------------------------
+# Produce a SEP delimited list of all paired combinations of elements of
+# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
+# has the form PREFIXmINFIXSUFFIXn.
+# Needed until we can rely on m4_combine added in Autoconf 2.62.
+m4_define([lt_combine],
+[m4_if(m4_eval([$# > 3]), [1],
+ [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
+[[m4_foreach([_Lt_prefix], [$2],
+ [m4_foreach([_Lt_suffix],
+ ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
+ [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
+
+
+# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+# -----------------------------------------------------------------------
+# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+m4_define([lt_if_append_uniq],
+[m4_ifdef([$1],
+ [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+ [lt_append([$1], [$2], [$3])$4],
+ [$5])],
+ [lt_append([$1], [$2], [$3])$4])])
+
+
+# lt_dict_add(DICT, KEY, VALUE)
+# -----------------------------
+m4_define([lt_dict_add],
+[m4_define([$1($2)], [$3])])
+
+
+# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+# --------------------------------------------
+m4_define([lt_dict_add_subkey],
+[m4_define([$1($2:$3)], [$4])])
+
+
+# lt_dict_fetch(DICT, KEY, [SUBKEY])
+# ----------------------------------
+m4_define([lt_dict_fetch],
+[m4_ifval([$3],
+ m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+ m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+
+
+# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+# -----------------------------------------------------------------
+m4_define([lt_if_dict_fetch],
+[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+ [$5],
+ [$6])])
+
+
+# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+# --------------------------------------------------------------
+m4_define([lt_dict_filter],
+[m4_if([$5], [], [],
+ [lt_join(m4_quote(m4_default([$4], [[, ]])),
+ lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+ [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+])
+
+# ltversion.m4 -- version numbers -*- Autoconf -*-
+#
+# Copyright (C) 2004 Free Software Foundation, Inc.
+# Written by Scott James Remnant, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# Generated from ltversion.in.
+
+# serial 3012 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.2.6])
+m4_define([LT_PACKAGE_REVISION], [1.3012])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.2.6'
+macro_revision='1.3012'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
+
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
+#
+# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+# Written by Scott James Remnant, 2004.
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 4 lt~obsolete.m4
+
+# These exist entirely to fool aclocal when bootstrapping libtool.
+#
+# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
+# which have later been changed to m4_define as they aren't part of the
+# exported API, or moved to Autoconf or Automake where they belong.
+#
+# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
+# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+# using a macro with the same name in our local m4/libtool.m4 it'll
+# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+# and doesn't know about Autoconf macros at all.)
+#
+# So we provide this file, which has a silly filename so it's always
+# included after everything else. This provides aclocal with the
+# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+# because those macros already exist, or will be overwritten later.
+# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
+#
+# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+# Yes, that means every name once taken will need to remain here until
+# we give up compatibility with versions before 1.7, at which point
+# we need to keep only those names which we still refer to.
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+
+m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
+m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
+m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
+m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
+m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
+m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
+m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
+m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
+m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
+m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
+m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
+m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
+m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
+m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
+m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
+m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
+m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
+m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
+m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])])
+m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
+m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
+
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+#
+# Copyright © 2004 Scott James Remnant <scott at netsplit.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists. Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+#
+# Similar to PKG_CHECK_MODULES, make sure that the first instance of
+# this or PKG_CHECK_MODULES is called, or make sure to call
+# PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_ifval([$2], [$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$PKG_CONFIG"; then
+ if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ else
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+ [pkg_failed=yes])
+ fi
+else
+ pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ ifelse([$4], , [AC_MSG_ERROR(dnl
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT
+])],
+ [AC_MSG_RESULT([no])
+ $4])
+elif test $pkg_failed = untried; then
+ ifelse([$4], , [AC_MSG_FAILURE(dnl
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
+ [$4])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ ifelse([$3], , :, [$3])
+fi[]dnl
+])# PKG_CHECK_MODULES
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.10'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.10.1], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.10.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(AC_AUTOCONF_VERSION)])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
+ [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], UPC, [depcc="$UPC" am_compiler_list=],
+ [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 3
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 13
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.60])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES(OBJC)],
+ [define([AC_PROG_OBJC],
+ defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+ [[\\/$]]* | ?:[[\\/]]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([acx_pthread.m4])
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/acx_pthread.m4
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/acx_pthread.m4 (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/acx_pthread.m4 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,190 @@
+dnl Available from the GNU Autoconf Macro Archive at:
+dnl http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html
+dnl
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+ AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test x"$acx_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread pthread -pthread -pthreads -mthreads --thread-safe -mt"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+
+case "${host_cpu}-${host_os}" in
+ *solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthread or
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+
+ acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
+ ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+ case $flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $flag])
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$flag])
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ AC_TRY_LINK([#include <pthread.h>],
+ [pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+ [acx_pthread_ok=yes])
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test "x$acx_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: threads are created detached by default
+ # and the JOINABLE attribute has a nonstandard name (UNDETACHED).
+ AC_MSG_CHECKING([for joinable pthread attribute])
+ AC_TRY_LINK([#include <pthread.h>],
+ [int attr=PTHREAD_CREATE_JOINABLE;],
+ ok=PTHREAD_CREATE_JOINABLE, ok=unknown)
+ if test x"$ok" = xunknown; then
+ AC_TRY_LINK([#include <pthread.h>],
+ [int attr=PTHREAD_CREATE_UNDETACHED;],
+ ok=PTHREAD_CREATE_UNDETACHED, ok=unknown)
+ fi
+ if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then
+ AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok,
+ [Define to the necessary symbol if this constant
+ uses a non-standard name on your system.])
+ fi
+ AC_MSG_RESULT(${ok})
+ if test x"$ok" = xunknown; then
+ AC_MSG_WARN([we do not know how to create joinable pthreads])
+ fi
+
+ AC_MSG_CHECKING([if more special flags are required for pthreads])
+ flag=no
+ case "${host_cpu}-${host_os}" in
+ *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";;
+ *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+ esac
+ AC_MSG_RESULT(${flag})
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: must compile with cc_r
+ AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
+else
+ PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+ ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+ :
+else
+ acx_pthread_ok=no
+ $2
+fi
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/autogen.sh
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/autogen.sh (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/autogen.sh 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,11 @@
+set -x
+
+rm -f configure Makefile.in Makefile config.h.in
+
+aclocal -I .
+libtoolize --force --copy
+
+# we do not use AC_CONFIG_HEADERS
+#autoheader
+automake --add-missing --foreign
+autoconf
Property changes on: trunk/SmartCardServices/src/PKCS11dotNetV2/autogen.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/c-mac.sh
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/c-mac.sh (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/c-mac.sh 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,33 @@
+#! /bin/sh
+
+if [ -d /usr/local/include/PCSC ]
+then
+ echo "move /usr/local/include/PCSC away and try again"
+ exit
+fi
+
+# we define PKG_CONFIG so that pkg-config is not used and PCSC_CFLAGS
+# and PCSC_LIBS are used instead
+PKG_CONFIG="foobar"
+
+# find pcsc-lite header files in MacOSXCCID/
+PCSC_CFLAGS="-I/System/Library/Frameworks/PCSC.framework/Versions/A/Headers"
+PCSC_LIBS="-framework PCSC"
+
+# Build a Universal Binary
+CFLAGS="$CFLAGS -isysroot /Developer/SDKs/MacOSX10.6.sdk -arch i386 -arch x86_64"
+LDFLAGS="-arch i386 -arch x86_64"
+CONFIGURE_ARGS="--disable-dependency-tracking"
+
+# install in /usr
+CONFIGURE_ARGS="$CONFIGURE_ARGS --prefix=/usr"
+
+set -x
+./configure \
+ PKG_CONFIG="$PKG_CONFIG" \
+ CFLAGS="$CFLAGS" \
+ CXXFLAGS="$CFLAGS" \
+ PCSC_CFLAGS="$PCSC_CFLAGS" \
+ PCSC_LIBS="$PCSC_LIBS" \
+ $CONFIGURE_ARGS \
+ "$@"
Property changes on: trunk/SmartCardServices/src/PKCS11dotNetV2/c-mac.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/configure.in
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/configure.in (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/configure.in 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,74 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.59)
+AC_INIT(libgtop11dotnet, 2.1.2, hotline at gemalto.com)
+AM_INIT_AUTOMAKE
+AC_CONFIG_SRCDIR([PKCS11Module2/pkcs11.cpp])
+AC_CHECK_PROG([PKGCONFIG], [pkg-config], [yes])
+
+# Checks for programs.
+AC_PROG_CXX
+AC_PROG_CC
+AC_PROG_LN_S
+AC_PROG_MKDIR_P
+AC_PROG_MAKE_SET
+AC_PROG_CPP
+AC_PROG_LIBTOOL
+
+AC_C_BIGENDIAN
+
+# Select OS specific versions of source files.
+AC_SUBST(DYN_LIB_EXT)
+case "$host" in
+*-*-darwin*)
+ DYN_LIB_EXT="dylib"
+ ;;
+*)
+ DYN_LIB_EXT="so"
+esac
+
+# Special check for pthread support
+ACX_PTHREAD(
+[
+ AC_DEFINE(HAVE_PTHREAD, 1,
+ [Define if you have POSIX threads libraries and header files.])
+], [
+ AC_MSG_ERROR([POSIX thread support required])
+])
+
+CC="$PTHREAD_CC"
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+
+# check pcsc-lite version
+OLD_LIBS="$LIBS"
+PKG_CHECK_MODULES(PCSC, libpcsclite, [],
+ [ AC_MSG_WARN([install pcsc-lite]) ])
+LIBS="$OLD_LIBS"
+
+OLD_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $PCSC_CFLAGS"
+AC_CHECK_HEADER(winscard.h,,
+ [AC_MSG_ERROR([winscard.h not found, install pcsc-lite, or use PCSC_CFLAGS=... ./configure])])
+CPPFLAGS="$OLD_CPPFLAGS"
+
+OLD_LIBS="$LIBS"
+LIBS="$LIBS $PCSC_LIBS"
+AC_MSG_CHECKING([for SCardEstablishContext])
+AC_TRY_LINK_FUNC(SCardEstablishContext, [ AC_MSG_RESULT([yes]) ],
+ [AC_MSG_ERROR([SCardEstablishContext() not found, install pcsc-lite,or use PCSC_LDLIBS=... ./configure])])
+LIBS="$OLD_LIBS"
+
+CPPFLAGS="$CPPFLAGS $PCSC_CFLAGS"
+AC_CHECK_TYPES([LPCTSTR],,,[#include <winscard.h>])
+AC_CHECK_TYPES([LPCSTR],,,[#include <winscard.h>])
+CPPFLAGS="$OLD_CPPFLAGS"
+
+AC_CONFIG_FILES([
+ Makefile
+ PKCS11Module2/Makefile
+ ])
+AC_OUTPUT
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,970 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef WIN32
+#include <Windows.h>
+#pragma warning(push)
+#pragma warning(disable:4201)
+#endif
+
+#include <string.h>
+#include <winscard.h>
+#include <stdexcept>
+#include "MarshallerCfg.h"
+#include "Except.h"
+#include "Array.h"
+
+// Determine Processor Endianess
+#include <limits.h>
+#if (UINT_MAX == 0xffffffffUL)
+ typedef unsigned int _u4;
+#else
+# if (ULONG_MAX == 0xffffffffUL)
+ typedef unsigned long _u4;
+# else
+# if (USHRT_MAX == 0xffffffffUL)
+ typedef unsigned short _u4;
+# endif
+# endif
+#endif
+
+_u4 _endian = 1;
+
+bool isLittleEndian = (*((unsigned char *)(&_endian))) ? true : false;
+bool isBigEndian = (*((unsigned char *)(&_endian))) ? false : true;
+MARSHALLER_NS_BEGIN
+
+
+static u4 ToBigEndian(u4 val)
+{
+ if (isBigEndian)
+ {
+ return val;
+ }
+ else
+ {
+ u4 res;
+ res = val << 24;
+ res |= (val << 8) & 0x00FF0000;
+ res |= (val >> 8) & 0x0000FF00;
+ res |= val >> 24;
+
+ return res;
+ }
+}
+
+static u2 ToBigEndian(u2 val)
+{
+ if (isBigEndian)
+ {
+ return val;
+ }
+ else
+ {
+ return (u2)((val << 8) | (val >> 8));
+ }
+}
+
+static u8 ToBigEndian(u8 val)
+{
+ if (isBigEndian)
+ {
+ return val;
+ }
+ else
+ {
+ u4 val1 = (u4)(val >> 32);
+ u4 val2 = (u4)val;
+
+ val1 = ToBigEndian(val1);
+ val2 = ToBigEndian(val2);
+
+ return (u8)(((u8)val2 << 32) | val1);
+ }
+}
+
+u2 ComputeUTF8Length(M_SAL_IN lpCharPtr str)
+{
+ u4 nCharProcessed = 0;
+ u4 pair;
+ u4 count;
+ u2 leftOver;
+ u4 charIndex;
+
+ count = 0;
+ leftOver = 0;
+ charIndex = 0;
+
+ while (nCharProcessed < (u4)strlen(str)) {
+ u2 ch = (u2)str[charIndex++];
+
+ if (leftOver == 0) {
+ if ((ch >= 0xD800) && (ch <= 0xDBFF)) {
+ // This is a low-part of a surrogate pair.
+ leftOver = (u2)ch;
+ nCharProcessed++;
+ continue;
+ } else {
+ // This is a regular character.
+ pair = (u4)ch;
+ }
+ } else if ((ch >= 0xDC00) && (ch <= 0xDFFF)) {
+ // This is a high-part of a surrogate pair. We now have a complete surrogate pair.
+ pair = ((leftOver - (u4)0xD800) << 10) + (((u4)ch) - (u4)0xDC00) + (u4)0x10000;
+ leftOver = 0;
+ } else {
+ goto error;
+ }
+
+ // Encode the character pair value.
+ if (pair < (u4)0x0080) {
+ count++;
+ } else if (pair < (u4)0x0800) {
+ count += 2;
+ } else if (pair < (u4)0x10000) {
+ count += 3;
+ } else {
+ count += 4;
+ }
+
+ nCharProcessed++;
+ }
+
+ if (leftOver != 0) {
+ goto error;
+ }
+
+ return (u2)count;
+
+error:;
+ throw Exception("Error while compute UTF8 encoding length");
+}
+
+void UTF8Encode(M_SAL_IN lpCharPtr str, u1Array &utf8Data)
+{
+ u4 nCharProcessed = 0;
+ u4 pair;
+ u2 leftOver;
+ u1* bytes = utf8Data.GetBuffer();
+ u4 byteCount;
+ u4 byteIndex = 0;
+ u4 charIndex = 0;
+
+ byteCount = utf8Data.GetLength();
+
+ leftOver = 0;
+
+ while (nCharProcessed < (u4)strlen(str)) {
+ u2 ch = str[charIndex++];
+
+ if (leftOver == 0) {
+ if ((ch >= 0xD800) && (ch <= 0xDBFF)) {
+ // This is a low-part of a surrogate pair.
+ leftOver = (u2)ch;
+ nCharProcessed++;
+ continue;
+ } else {
+ // This is a regular character.
+ pair = (u4)ch;
+ }
+ } else if ((ch >= 0xDC00) && (ch <= 0xDFFF)) {
+ // This is a high-part of a surrogate pair. We now have a complete surrogate pair.
+ pair = ((leftOver - (u4)0xD800) << 10) + (((u4)ch) - (u4)0xDC00) + (u4)0x10000;
+ leftOver = 0;
+ } else {
+ goto error;
+ }
+
+ // Encode the character pair value.
+ if (pair < (u4)0x0080) {
+ if (byteIndex >= byteCount) {
+ goto end;
+ }
+ bytes[byteIndex++] = (u1)pair;
+ } else if (pair < (u4)0x0800) {
+ if ((byteIndex + 2) > byteCount) {
+ goto end;
+ }
+ bytes[byteIndex++] = (u1)(0xC0 | (pair >> 6));
+ bytes[byteIndex++] = (u1)(0x80 | (pair & 0x3F));
+ } else if (pair < (u4)0x10000) {
+ if ((byteIndex + 3) > byteCount) {
+ goto end;
+ }
+ bytes[byteIndex++] = (u1)(0xE0 | (pair >> 12));
+ bytes[byteIndex++] = (u1)(0x80 | ((pair >> 6) & 0x3F));
+ bytes[byteIndex++] = (u1)(0x80 | (pair & 0x3F));
+ } else {
+ if ((byteIndex + 4) > byteCount) {
+ goto end;
+ }
+ bytes[byteIndex++] = (u1)(0xF0 | (pair >> 18));
+ bytes[byteIndex++] = (u1)(0x80 | ((pair >> 12) & 0x3F));
+ bytes[byteIndex++] = (u1)(0x80 | ((pair >> 6) & 0x3F));
+ bytes[byteIndex++] = (u1)(0x80 | (pair & 0x3F));
+ }
+
+ nCharProcessed++;
+ }
+
+end:;
+ // we do accept byteIndex <= byteCount (dest buffer length > what is really necessary).
+ if (byteIndex > byteCount) {
+ goto error;
+ }
+
+ if (leftOver != 0) {
+ goto error;
+ }
+
+ return;
+
+error:;
+ throw Exception("Error while performing UTF8 encoding");
+}
+
+u2 ComputeLPSTRLength(u1Array &array, u4 offset, u4 len)
+{
+ if ((u8)(offset + len) > (u8)array.GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ } else {
+ u2 charlen = 0;
+ u4 i;
+ u1* buff = array.GetBuffer();
+
+ for (i = 0; i < len;) {
+ if ((buff[i + offset] & 0x80) == 0) {
+ i += 1;
+ }
+ else if ((buff[i + offset] & 0xE0) == 0xC0) {
+ i += 2;
+ }
+ else if ((buff[i + offset] & 0xF0) == 0xE0) {
+ i += 3;
+ }
+ else {
+ throw Exception("Error parsing UTF-8 bytes");
+ }
+ charlen++;
+ }
+ return charlen;
+ }
+}
+
+void UTF8Decode(u1Array &array, u4 offset, u4 len, M_SAL_INOUT lpCharPtr &charData)
+{
+ if ((u8)(offset + len) > (u8)array.GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ } else {
+ u4 i = 0;
+ u4 pos = 0;
+ u1* buff = array.GetBuffer();
+
+ for (i = 0; i < len;) {
+ if ((buff[i + offset] & 0x80) == 0) {
+ charData[pos] = buff[i + offset];
+ i += 1;
+ }
+ else if ((buff[i + offset] & 0xE0) == 0xC0) {
+ charData[pos] = ((buff[i + offset] & 0x1F) << 6) | (buff[i+1 + offset] & 0x3F);
+ i += 2;
+ }
+ else if ((buff[i + offset] & 0xF0) == 0xE0) {
+ charData[pos] = ((buff[i + offset] & 0x0F) << 12) | ((buff[i+1 + offset] & 0x3F) << 6) | (buff[i+2 + offset] & 0x3F);
+ i += 3;
+ }
+ else{
+ throw Exception("Error parsing UTF-8 bytes");
+ }
+ pos++;
+ }
+ }
+}
+
+// *******************
+// String Array class
+// *******************
+StringArray::StringArray(s4 nelement)
+{
+ this->_length = nelement;
+
+ if (nelement < 0) {
+ nelement = 0;
+ }
+
+ this->buffer = new std::string*[nelement];
+
+ // we need to initialize the buffer to zeros
+ for(s4 i=0;i<nelement;i++)
+ this->buffer[i] = NULL;
+
+}
+
+StringArray::StringArray(const StringArray &rhs)
+{
+ s4 len = rhs._length;
+ this->_length = len;
+ if (len < 0) {
+ len = 0;
+ }
+
+ this->buffer = new std::string*[len];
+
+ for(s4 i=0;i<len;i++)
+ this->buffer[i] = rhs.buffer[i];
+
+}
+
+StringArray::~StringArray(void)
+{
+ // delete the strings in the StringArray
+ for(u4 i = 0; i < GetLength(); i++){
+ if (buffer[i] != NULL) {
+ delete buffer[i];
+ buffer[i] = NULL;
+ }
+ }
+
+ delete[] buffer;
+}
+
+u1 StringArray::IsNull(void)
+{
+ return (this->_length < 0);
+}
+
+u4 StringArray::GetLength(void)
+{
+ if (IsNull()) {
+ return (u4)0;
+ } else {
+ return (u4)this->_length;
+ }
+}
+
+std::string* StringArray::GetStringAt(u4 index)
+{
+ if (index >= GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+ return this->buffer[index];
+}
+
+void StringArray::SetStringAt(u4 index, M_SAL_IN std::string* str)
+{
+ if (index >= GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+ this->buffer[index] = str;
+}
+
+// *******************
+// Byte Array class
+// *******************
+
+u1Array::u1Array()
+{
+ this->_length = 0;
+// JCD
+ this->buffer = NULL;//new u1[0];
+// JCD
+}
+
+u1Array::u1Array(s4 nelement)
+{
+ this->_length = nelement;
+ if (nelement < 0) {
+ nelement = 0;
+ }
+ this->buffer = new u1[nelement];
+}
+
+u1Array::u1Array(const u1Array &rhs)
+{
+ s4 len = rhs._length;
+ this->_length = len;
+ if (len < 0) {
+ len = 0;
+ }
+ this->buffer = new u1[len];
+ memcpy(this->buffer, rhs.buffer, len);
+}
+
+u1Array::u1Array(u1Array &array, u4 offset, u4 len)
+{
+ if ((u8)(offset + len) > array.GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ } else {
+ this->_length = len;
+ this->buffer = new u1[len];
+ memcpy(this->buffer, array.buffer + offset, len);
+ }
+}
+
+u1Array::~u1Array(void)
+{
+ if (this->buffer != NULL) {
+ delete[] this->buffer;
+ this->buffer = NULL;
+ }
+}
+
+u1 u1Array::IsNull(void) const
+{
+ return (this->_length < 0);
+}
+
+void u1Array::SetU1At(u4 pos, u1 val)
+{
+ if (pos >= GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+ this->buffer[pos] = val;
+}
+
+
+u1 u1Array::ReadU1At(u4 pos) const
+{
+ if (pos >= GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+ return this->buffer[pos];
+}
+
+u4 u1Array::GetLength(void) const
+{
+ if (IsNull()) {
+ return (u4)0;
+ } else {
+ return (u4)this->_length;
+ }
+}
+
+void u1Array::SetBuffer(const u1* buffer)
+{
+ memcpy(this->buffer, buffer, this->GetLength());
+}
+
+const u1* u1Array::GetBuffer(void) const
+{
+ return this->buffer;
+}
+
+u1* u1Array::GetBuffer(void)
+{
+ return this->buffer;
+}
+
+// 1 byte add
+u1Array& u1Array::operator +(u1 val)
+{
+ u1Array* newArray = new u1Array(this->GetLength() + sizeof(u1));
+ memcpy(newArray->buffer, this->buffer, this->GetLength());
+ memcpy(&newArray->buffer[this->GetLength()], &val, sizeof(u1));
+ return *newArray;
+}
+
+u1Array& u1Array::operator +=(u1 val)
+{
+ u1* tempBuffer = new u1[this->GetLength() + sizeof(u1)];
+ memcpy(tempBuffer, this->buffer, this->GetLength());
+ memcpy(&tempBuffer[this->GetLength()], &val, sizeof(u1));
+ delete[] this->buffer;
+ this->buffer = tempBuffer;
+ this->_length = this->GetLength() + sizeof(u1);
+ return *this;
+}
+
+// 2 bytes add
+u1Array& u1Array::operator +(u2 val)
+{
+ val = ToBigEndian(val);
+ u1Array* newArray = new u1Array(this->GetLength() + sizeof(u2));
+ memcpy(newArray->buffer, this->buffer, this->GetLength());
+ memcpy(&newArray->buffer[this->GetLength()], &val, sizeof(u2));
+ return *newArray;
+}
+
+u1Array& u1Array::operator +=(u2 val)
+{
+ val = ToBigEndian(val);
+ u1* tempBuffer = new u1[this->GetLength() + sizeof(u2)];
+ memcpy(tempBuffer, this->buffer, this->GetLength());
+ memcpy(&tempBuffer[this->GetLength()], &val, sizeof(u2));
+ delete[] this->buffer;
+ this->buffer = tempBuffer;
+ this->_length = this->GetLength() + sizeof(u2);
+ return *this;
+}
+
+// 4 bytes add
+u1Array& u1Array::operator +(u4 val)
+{
+ val = ToBigEndian(val);
+ u1Array* newArray = new u1Array(this->GetLength() + sizeof(u4));
+ memcpy(newArray->buffer, this->buffer, this->GetLength());
+ memcpy(&newArray->buffer[this->GetLength()], &val, sizeof(u4));
+ return *newArray;
+}
+
+u1Array& u1Array::operator +=(u4 val)
+{
+ val = ToBigEndian(val);
+ u1* tempBuffer = new u1[this->GetLength() + sizeof(u4)];
+ memcpy(tempBuffer, this->buffer, this->GetLength());
+ memcpy(&tempBuffer[this->GetLength()], &val, sizeof(u4));
+ delete[] this->buffer;
+ this->buffer = tempBuffer;
+ this->_length = this->GetLength() + sizeof(u4);
+ return *this;
+}
+
+// 8 bytes add
+u1Array& u1Array::operator +(u8 val)
+{
+ val = ToBigEndian(val);
+ u1Array* newArray = new u1Array(this->GetLength() + sizeof(u8));
+ memcpy(newArray->buffer, this->buffer, this->GetLength());
+ memcpy(&newArray->buffer[this->GetLength()], &val, sizeof(u8));
+ return *newArray;
+}
+
+u1Array& u1Array::operator +=(u8 val)
+{
+ val = ToBigEndian(val);
+ u1* tempBuffer = new u1[this->GetLength() + sizeof(u8)];
+ memcpy(tempBuffer, this->buffer, this->GetLength());
+ memcpy(&tempBuffer[this->GetLength()], &val, sizeof(u8));
+ delete[] this->buffer;
+ this->buffer = tempBuffer;
+ this->_length = this->GetLength() + sizeof(u8);
+ return *this;
+}
+
+
+// bytes array add
+u1Array& u1Array::operator =(const u1Array &bArray)
+{
+ delete[] buffer; buffer = 0;
+ _length = bArray._length;
+ buffer = new u1[_length > 0 ? _length : 0];
+ if(_length>0)
+ memcpy(buffer, bArray.buffer, _length);
+ return *this;
+}
+
+u1Array& u1Array::operator +(u1Array &bArray)
+{
+ s4 len;
+ if (IsNull() && bArray.IsNull()) {
+ len = -1;
+ } else {
+ len = this->GetLength() + bArray.GetLength();
+ }
+ u1Array* newArray = new u1Array(len);
+ memcpy(newArray->buffer, this->buffer, this->GetLength());
+ memcpy(&newArray->buffer[this->GetLength()], bArray.buffer, bArray.GetLength());
+ return *newArray;
+}
+
+u1Array& u1Array::operator +=(u1Array &bArray)
+{
+ u1* tempBuffer = new u1[this->GetLength() + bArray.GetLength()];
+ memcpy(tempBuffer, this->buffer, this->GetLength());
+ memcpy(&tempBuffer[this->GetLength()], bArray.buffer, bArray.GetLength());
+ delete[] this->buffer;
+ this->buffer = tempBuffer;
+ if (IsNull() && bArray.IsNull()) {
+ this->_length = -1;
+ } else {
+ this->_length = this->GetLength() + bArray.GetLength();
+ }
+ return *this;
+}
+
+u1Array& u1Array::Append(std::string* str)
+{
+ if (str == NULL) {
+ *this += (u2)0xFFFF;
+ } else {
+ u2 strLen = ComputeUTF8Length((lpCharPtr)str->c_str());
+ *this += strLen;
+ u1Array strArray(strLen);
+ UTF8Encode((lpCharPtr)str->c_str(), strArray);
+ *this += strArray;
+ }
+ return *this;
+}
+
+// *******************
+// UShort Array class
+// *******************
+u2Array::u2Array(s4 nelement)
+{
+ this->_length = nelement;
+ if (nelement < 0) {
+ nelement = 0;
+ }
+ this->buffer = new u2[nelement];
+}
+
+u2Array::u2Array(const u2Array &rhs)
+{
+ s4 len = rhs._length;
+ this->_length = len;
+ if (len < 0) {
+ len = 0;
+ }
+ this->buffer = new u2[len];
+ memcpy(this->buffer, rhs.buffer, len * sizeof(u2));
+}
+
+u2Array::~u2Array(void)
+{
+ delete[] this->buffer;
+}
+
+u1 u2Array::IsNull(void)
+{
+ return (this->_length < 0);
+}
+
+void u2Array::SetU2At(u4 pos, u2 val)
+{
+ if (pos >= GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+ this->buffer[pos] = val;
+}
+
+u2 u2Array::ReadU2At(u4 pos)
+{
+ if (pos >= GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+ return this->buffer[pos];
+}
+
+u4 u2Array::GetLength(void)
+{
+ if (IsNull()) {
+ return (u4)0;
+ } else {
+ return (u4)this->_length;
+ }
+}
+
+void u2Array::SetBuffer(u2* buffer)
+{
+ memcpy(this->buffer, buffer, this->GetLength() * sizeof(u2));
+}
+
+u2* u2Array::GetBuffer(void)
+{
+ return this->buffer;
+}
+
+// 2 bytes add
+u2Array& u2Array::operator +(u2 val)
+{
+ u2Array* newArray = new u2Array(this->GetLength() + 1);
+ memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u2));
+ newArray->buffer[this->GetLength()] = val;
+ return *newArray;
+}
+
+u2Array& u2Array::operator +=(u2 val)
+{
+ u2* tempBuffer = new u2[this->GetLength() + 1];
+ memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u2));
+ tempBuffer[this->GetLength()] = val;
+ delete[] this->buffer;
+ this->buffer = tempBuffer;
+ this->_length = this->GetLength() + 1;
+ return *this;
+}
+
+// Char array add
+u2Array& u2Array::operator +(u2Array &cArray)
+{
+ s4 len;
+ if (IsNull() && cArray.IsNull()) {
+ len = -1;
+ } else {
+ len = this->GetLength() + cArray.GetLength();
+ }
+ u2Array* newArray = new u2Array(len);
+ memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u2));
+ memcpy(&newArray->buffer[this->GetLength() * sizeof(u2)], cArray.buffer, cArray.GetLength() * sizeof(u2));
+ return *newArray;
+}
+
+u2Array& u2Array::operator +=(u2Array &cArray)
+{
+ u2* tempBuffer = new u2[this->GetLength() + cArray.GetLength()];
+ memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u2));
+ memcpy(&tempBuffer[this->GetLength() * sizeof(u2)], cArray.buffer, cArray.GetLength() * sizeof(u2));
+ delete[] this->buffer;
+ this->buffer = tempBuffer;
+ if (IsNull() && cArray.IsNull()) {
+ this->_length = -1;
+ } else {
+ this->_length = this->GetLength() + cArray.GetLength();
+ }
+ return *this;
+}
+
+// *******************
+// Int Array class
+// *******************
+u4Array::u4Array(s4 nelement)
+{
+ this->_length = nelement;
+ if (nelement < 0) {
+ nelement = 0;
+ }
+ this->buffer = new u4[nelement];
+}
+
+u4Array::u4Array(const u4Array &rhs)
+{
+ s4 len = rhs._length;
+ this->_length = len;
+ if (len < 0) {
+ len = 0;
+ }
+ this->buffer = new u4[len];
+ memcpy(this->buffer, rhs.buffer, len * sizeof(u4));
+}
+
+u4Array::~u4Array(void)
+{
+ delete[] this->buffer;
+}
+
+u1 u4Array::IsNull(void)
+{
+ return (this->_length < 0);
+}
+
+void u4Array::SetU4At(u4 pos, u4 val)
+{
+ if (pos >= GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+ this->buffer[pos] = val;
+}
+
+u4 u4Array::ReadU4At(u4 pos)
+{
+ if (pos >= GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+ return this->buffer[pos];
+}
+
+u4 u4Array::GetLength(void)
+{
+ if (IsNull()) {
+ return (u4)0;
+ } else {
+ return (u4)this->_length;
+ }
+}
+
+void u4Array::SetBuffer(u4* buffer)
+{
+ memcpy(this->buffer, buffer, this->GetLength() * sizeof(u4));
+}
+
+u4* u4Array::GetBuffer(void)
+{
+ return this->buffer;
+}
+
+// 4 bytes add
+u4Array& u4Array::operator +(u4 val)
+{
+ u4Array* newArray = new u4Array(this->GetLength() + 1);
+ memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u4));
+ newArray->buffer[this->GetLength()] = val;
+ return *newArray;
+}
+
+u4Array& u4Array::operator +=(u4 val)
+{
+ u4* tempBuffer = new u4[this->GetLength() + 1];
+ memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u4));
+ tempBuffer[this->GetLength()] = val;
+ delete[] this->buffer;
+ this->buffer = tempBuffer;
+ this->_length = this->GetLength() + 1;
+ return *this;
+}
+
+// UInt array add
+u4Array& u4Array::operator +(u4Array &iArray)
+{
+ s4 len;
+ if (IsNull() && iArray.IsNull()) {
+ len = -1;
+ } else {
+ len = this->GetLength() + iArray.GetLength();
+ }
+ u4Array* newArray = new u4Array(len);
+ memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u4));
+ memcpy(&newArray->buffer[this->GetLength() * sizeof(u4)], iArray.buffer, iArray.GetLength() * sizeof(u4));
+ return *newArray;
+}
+
+u4Array& u4Array::operator +=(u4Array &iArray)
+{
+ u4* tempBuffer = new u4[this->GetLength() + iArray.GetLength()];
+ memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u4));
+ memcpy(&tempBuffer[this->GetLength() * sizeof(u4)], iArray.buffer, iArray.GetLength() * sizeof(u4));
+ delete[] this->buffer;
+ this->buffer = tempBuffer;
+ if (IsNull() && iArray.IsNull()) {
+ this->_length = -1;
+ } else {
+ this->_length = this->GetLength() + iArray.GetLength();
+ }
+ return *this;
+}
+
+
+// *******************
+// Long Array class
+// *******************
+u8Array::u8Array(s4 nelement)
+{
+ this->_length = nelement;
+ if (nelement < 0) {
+ nelement = 0;
+ }
+ this->buffer = new u8[nelement];
+}
+
+u8Array::u8Array(const u8Array &rhs)
+{
+ s4 len = rhs._length;
+ this->_length = len;
+ if (len < 0) {
+ len = 0;
+ }
+ this->buffer = new u8[len];
+ memcpy(this->buffer, rhs.buffer, len * sizeof(u8));
+}
+
+u8Array::~u8Array(void)
+{
+ delete[] this->buffer;
+}
+
+u1 u8Array::IsNull(void)
+{
+ return (this->_length < 0);
+}
+
+void u8Array::SetU8At(u4 pos, u8 val)
+{
+ if (pos >= GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+ this->buffer[pos] = val;
+}
+
+u8 u8Array::ReadU8At(u4 pos)
+{
+ if (pos >= GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+ return this->buffer[pos];
+}
+
+u4 u8Array::GetLength(void)
+{
+ if (IsNull()) {
+ return (u4)0;
+ } else {
+ return (u4)this->_length;
+ }
+}
+
+void u8Array::SetBuffer(u8* buffer)
+{
+ memcpy(this->buffer, buffer, this->GetLength() * sizeof(u8));
+}
+
+u8* u8Array::GetBuffer(void)
+{
+ return this->buffer;
+}
+
+u8Array& u8Array::operator +(u8 val)
+{
+ u8Array* newArray = new u8Array(this->GetLength() + 1);
+ memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u8));
+ newArray->buffer[this->GetLength()] = val;
+ return *newArray;
+}
+
+u8Array& u8Array::operator +=(u8 val)
+{
+ u8* tempBuffer = new u8[this->GetLength() + 1];
+ memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u8));
+ tempBuffer[this->GetLength()] = val;
+ delete[] this->buffer;
+ this->buffer = tempBuffer;
+ this->_length = this->GetLength() + 1;
+ return *this;
+}
+
+u8Array& u8Array::operator +(u8Array &iArray)
+{
+ s4 len;
+ if (IsNull() && iArray.IsNull()) {
+ len = -1;
+ } else {
+ len = this->GetLength() + iArray.GetLength();
+ }
+ u8Array* newArray = new u8Array(len);
+ memcpy(newArray->buffer, this->buffer, this->GetLength() * sizeof(u8));
+ memcpy(&newArray->buffer[this->GetLength() * sizeof(u8)], iArray.buffer, iArray.GetLength() * sizeof(u8));
+ return *newArray;
+}
+
+u8Array& u8Array::operator +=(u8Array &iArray)
+{
+ u8* tempBuffer = new u8[this->GetLength() + iArray.GetLength()];
+ memcpy(tempBuffer, this->buffer, this->GetLength() * sizeof(u8));
+ memcpy(&tempBuffer[this->GetLength() * sizeof(u8)], iArray.buffer, iArray.GetLength() * sizeof(u8));
+ delete[] this->buffer;
+ this->buffer = tempBuffer;
+ if (IsNull() && iArray.IsNull()) {
+ this->_length = -1;
+ } else {
+ this->_length = this->GetLength() + iArray.GetLength();
+ }
+ return *this;
+}
+
+MARSHALLER_NS_END
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Array.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,180 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_marshaller_array_h
+#define _include_marshaller_array_h
+
+MARSHALLER_NS_BEGIN
+
+class SMARTCARDMARSHALLER_DLLAPI StringArray
+{
+
+private:
+ std::string** buffer;
+ s4 _length;
+
+public:
+ StringArray(s4 nelement);
+ StringArray(const StringArray &rhs);
+ ~StringArray(void);
+
+ u1 IsNull(void);
+ u4 GetLength(void);
+
+ std::string* GetStringAt(u4 index);
+ void SetStringAt(u4 index,M_SAL_IN std::string* str);
+};
+
+#define s8Array u8Array
+class SMARTCARDMARSHALLER_DLLAPI u8Array
+{
+
+private:
+ u8* buffer;
+ s4 _length;
+
+public:
+ u8Array(s4 nelement);
+ u8Array(const u8Array &rhs);
+ ~u8Array(void);
+
+ u1 IsNull(void);
+ u4 GetLength(void);
+
+ void SetBuffer(u8* buffer);
+ u8* GetBuffer(void);
+
+ u8 ReadU8At(u4 pos);
+ void SetU8At(u4 pos, u8 val);
+
+ u8Array& operator +(u8 val);
+ u8Array& operator +=(u8 val);
+ u8Array& operator +(u8Array &cArray);
+ u8Array& operator +=(u8Array &cArray);
+
+};
+
+#define s4Array u4Array
+class SMARTCARDMARSHALLER_DLLAPI u4Array
+{
+
+private:
+ u4* buffer;
+ s4 _length;
+
+public:
+ u4Array(s4 nelement);
+ u4Array(const u4Array &rhs);
+ ~u4Array(void);
+
+ u1 IsNull(void);
+ u4 GetLength(void);
+
+ void SetBuffer(u4* buffer);
+ u4* GetBuffer(void);
+
+ u4 ReadU4At(u4 pos);
+ void SetU4At(u4 pos, u4 val);
+
+ u4Array& operator +(u4 val);
+ u4Array& operator +=(u4 val);
+ u4Array& operator +(u4Array &cArray);
+ u4Array& operator +=(u4Array &cArray);
+};
+
+#define s2Array u2Array
+#define charArray u2Array
+class SMARTCARDMARSHALLER_DLLAPI u2Array
+{
+
+private:
+ u2* buffer;
+ s4 _length;
+
+public:
+ u2Array(s4 nelement);
+ u2Array(const u2Array &rhs);
+ ~u2Array(void);
+
+ u1 IsNull(void);
+ u4 GetLength(void);
+
+ void SetBuffer(u2* buffer);
+ u2* GetBuffer(void);
+
+ u2 ReadU2At(u4 pos);
+ void SetU2At(u4 pos, u2 val);
+
+ u2Array& operator +(u2 val);
+ u2Array& operator +=(u2 val);
+ u2Array& operator +(u2Array &cArray);
+ u2Array& operator +=(u2Array &cArray);
+};
+
+#define s1Array u1Array
+#define MemoryStream u1Array
+class SMARTCARDMARSHALLER_DLLAPI u1Array
+{
+
+private:
+ u1* buffer;
+ s4 _length;
+
+public:
+ u1Array();
+ u1Array(s4 nelement);
+ u1Array(const u1Array &rhs);
+ u1Array(u1Array &array, u4 offset, u4 len);
+ ~u1Array(void);
+
+ u1 IsNull(void) const;
+ u4 GetLength(void) const;
+
+ void SetBuffer(const u1* buffer);
+ const u1* GetBuffer(void) const;
+ u1* GetBuffer(void);
+
+ u1 ReadU1At(u4 pos) const;
+ void SetU1At(u4 pos, u1 val);
+
+ u1Array& Append(std::string* str);
+
+ u1Array& operator +(u1 val);
+ u1Array& operator +=(u1 val);
+ u1Array& operator +(u2 val);
+ u1Array& operator +=(u2 val);
+ u1Array& operator +(u4 val);
+ u1Array& operator +=(u4 val);
+ u1Array& operator +(u8 val);
+ u1Array& operator +=(u8 val);
+ u1Array& operator =(const u1Array &bArray);
+ u1Array& operator +(u1Array &bArray);
+ u1Array& operator +=(u1Array &bArray);
+};
+
+extern u2 ComputeUTF8Length(M_SAL_IN lpCharPtr str);
+extern void UTF8Encode(M_SAL_IN lpCharPtr str, u1Array &utf8Data);
+extern u2 ComputeLPSTRLength(u1Array &array, u4 offset, u4 len);
+extern void UTF8Decode(u1Array &array, u4 offset, u4 len, M_SAL_INOUT lpCharPtr &charData);
+
+MARSHALLER_NS_END
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Except.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Except.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Except.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,338 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_marshaller_except_h
+#define _include_marshaller_except_h
+
+MARSHALLER_NS_BEGIN
+
+// .NET specific exception classes
+class Exception : public std::runtime_error{
+
+public:
+ explicit Exception(std::string msg): std::runtime_error(msg) { }
+ const char *what() const throw(){
+ return std::runtime_error::what();
+ }
+};
+
+class SystemException : public Exception{
+
+public:
+ explicit SystemException(std::string msg) : Exception(msg) { }
+ explicit SystemException(char *msg) : Exception(NULL != msg ? msg : "") { }
+};
+
+class ArgumentException : public Exception{
+
+public:
+ explicit ArgumentException(std::string msg) : Exception(msg) { }
+ explicit ArgumentException();
+ explicit ArgumentException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ArgumentNullException : public Exception{
+
+public:
+ explicit ArgumentNullException(std::string msg) : Exception(msg) { }
+ explicit ArgumentNullException();
+ explicit ArgumentNullException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ArgumentOutOfRangeException : public Exception{
+
+public:
+ explicit ArgumentOutOfRangeException(std::string msg) : Exception(msg) { }
+ explicit ArgumentOutOfRangeException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class IndexOutOfRangeException : public Exception{
+
+public:
+ explicit IndexOutOfRangeException(std::string msg) : Exception(msg) { }
+ explicit IndexOutOfRangeException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class InvalidCastException : public Exception{
+
+public:
+ explicit InvalidCastException(std::string msg) : Exception(msg) { }
+ explicit InvalidCastException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class InvalidOperationException : public Exception{
+
+public:
+ explicit InvalidOperationException(std::string msg) : Exception(msg) { }
+ explicit InvalidOperationException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class NotImplementedException : public Exception{
+
+public:
+ explicit NotImplementedException(std::string msg) : Exception(msg) { }
+ explicit NotImplementedException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class NotSupportedException : public Exception{
+
+public:
+ explicit NotSupportedException(std::string msg) : Exception(msg) { }
+ explicit NotSupportedException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class NullReferenceException : public Exception{
+
+public:
+ explicit NullReferenceException(std::string msg) : Exception(msg) { }
+ explicit NullReferenceException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class OutOfMemoryException : public Exception{
+
+public:
+ explicit OutOfMemoryException(std::string msg) : Exception(msg) { }
+ explicit OutOfMemoryException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class UnauthorizedAccessException : public Exception{
+
+public:
+ explicit UnauthorizedAccessException(std::string msg) : Exception(msg) { }
+ explicit UnauthorizedAccessException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ObjectDisposedException : public Exception{
+
+public:
+ explicit ObjectDisposedException(std::string msg) : Exception(msg) { }
+ explicit ObjectDisposedException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ApplicationException : public Exception{
+
+public:
+ explicit ApplicationException(std::string msg) : Exception(msg) { }
+ explicit ApplicationException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ArithmeticException : public Exception{
+
+public:
+ explicit ArithmeticException(std::string msg) : Exception(msg) { }
+ explicit ArithmeticException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class ArrayTypeMismatchException : public Exception{
+
+public:
+ explicit ArrayTypeMismatchException(std::string msg) : Exception(msg) { }
+ explicit ArrayTypeMismatchException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class BadImageFormatException : public Exception{
+
+public:
+ explicit BadImageFormatException(std::string msg) : Exception(msg) { }
+ explicit BadImageFormatException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class CryptographicException : public Exception{
+
+public:
+ explicit CryptographicException(std::string msg) : Exception(msg) { }
+ explicit CryptographicException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class DirectoryNotFoundException : public Exception{
+
+public:
+ explicit DirectoryNotFoundException(std::string msg) : Exception(msg) { }
+ explicit DirectoryNotFoundException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class DivideByZeroException : public Exception{
+
+public:
+ explicit DivideByZeroException(std::string msg) : Exception(msg) { }
+ explicit DivideByZeroException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class FileNotFoundException : public Exception{
+
+public:
+ explicit FileNotFoundException(std::string msg) : Exception(msg) { }
+ explicit FileNotFoundException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class FormatException : public Exception{
+
+public:
+ explicit FormatException(std::string msg) : Exception(msg) { }
+ explicit FormatException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class IOException : public Exception{
+
+public:
+ explicit IOException(std::string msg) : Exception(msg) { }
+ explicit IOException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class RankException : public Exception{
+
+public:
+ explicit RankException(std::string msg) : Exception(msg) { }
+ explicit RankException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class RemotingException : public Exception{
+
+private:
+ s4 resultCode; // this code is for PCSC releated error/success codes
+
+public:
+ explicit RemotingException(std::string msg) : Exception(msg) {
+ this->resultCode = 0;
+ }
+ explicit RemotingException(char *msg) : Exception(NULL != msg ? msg : "") {
+ this->resultCode = 0;
+ }
+ explicit RemotingException(std::string msg,s4 resultCode) : Exception(msg){
+ this->resultCode = resultCode;
+ }
+ explicit RemotingException(char *msg,s4 resultCode) : Exception(NULL != msg ? msg : ""){
+ this->resultCode = resultCode;
+ }
+ explicit RemotingException(s4 resultCode) : Exception(""){
+ this->resultCode = resultCode;
+ }
+ s4 getResultCode(){
+ return this->resultCode;
+ }
+};
+
+class StackOverflowException : public Exception{
+
+public:
+ explicit StackOverflowException(std::string msg) : Exception(msg) { }
+ explicit StackOverflowException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class TypeLoadException : public Exception{
+
+public:
+ explicit TypeLoadException(std::string msg) : Exception(msg) { }
+ explicit TypeLoadException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class MemberAccessException : public Exception{
+
+public:
+ explicit MemberAccessException(std::string msg) : Exception(msg) { }
+ explicit MemberAccessException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class MissingFieldException : public Exception{
+
+public:
+ explicit MissingFieldException(std::string msg) : Exception(msg) { }
+ explicit MissingFieldException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class MissingMemberException : public Exception{
+
+public:
+ explicit MissingMemberException(std::string msg) : Exception(msg) { }
+ explicit MissingMemberException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class MissingMethodException : public Exception{
+
+public:
+ explicit MissingMethodException(std::string msg) : Exception(msg) { }
+ explicit MissingMethodException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class OverflowException : public Exception{
+
+public:
+ explicit OverflowException(std::string msg) : Exception(msg) { }
+ explicit OverflowException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class SecurityException : public Exception{
+
+public:
+ explicit SecurityException(std::string msg) : Exception(msg) { }
+ explicit SecurityException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class VerificationException : public Exception{
+
+public:
+ explicit VerificationException(std::string msg) : Exception(msg) { }
+ explicit VerificationException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+class SerializationException : public Exception{
+
+public:
+ explicit SerializationException(std::string msg) : Exception(msg) { }
+ explicit SerializationException(char *msg) : Exception(NULL != msg ? msg : "") { }
+
+};
+
+MARSHALLER_NS_END
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,1781 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef WIN32
+#include <Windows.h>
+#pragma warning(push)
+#pragma warning(disable:4201)
+#else
+#define DBG_UNREFERENCED_LOCAL_VARIABLE(a)
+#endif
+
+#ifdef INCLUDE_VLD
+#include <vld.h>
+#endif
+
+#ifdef __APPLE__
+#include <pcsclite.h>
+#endif
+
+#ifndef WIN32
+#include <strings.h>
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdexcept>
+#include <winscard.h>
+#include "MarshallerCfg.h"
+#include "Array.h"
+#ifndef _XCL_
+#include "PCSC.h"
+#else // _XCL_
+#include "xcl_broker.h"
+#endif // _XCL_
+#include "Marshaller.h"
+#include "Except.h"
+
+#include "log.h"
+
+MARSHALLER_NS_BEGIN
+
+#define SUPPORT_BETA_VERSION
+
+#define APDU_TO_CARD_MAX_SIZE 0xFF
+
+#define HIVECODE_NAMESPACE_SYSTEM 0x00D25D1C
+#define HIVECODE_NAMESPACE_SYSTEM_IO 0x00D5E6DB
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_CHANNELS 0x0000886E
+#define HIVECODE_NAMESPACE_NETCARD_FILESYSTEM 0x00A1AC39
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING 0x00EB3DD9
+#define HIVECODE_NAMESPACE_SYSTEM_SECURITY_CRYPTOGRAPHY 0x00ACF53B
+#define HIVECODE_NAMESPACE_SYSTEM_COLLECTIONS 0x00C5A010
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_CONTEXTS 0x001F4994
+#define HIVECODE_NAMESPACE_SYSTEM_SECURITY 0x00964145
+#define HIVECODE_NAMESPACE_SYSTEM_REFLECTION 0x0008750F
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_SERIALIZATION 0x008D3B3D
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING_MESSAGING 0x00DEB940
+#define HIVECODE_NAMESPACE_SYSTEM_DIAGNOSTICS 0x0097995F
+#define HIVECODE_NAMESPACE_SYSTEM_RUNTIME_COMPILERSERVICES 0x00F63E11
+#define HIVECODE_NAMESPACE_SYSTEM_TEXT 0x00702756
+
+#define HIVECODE_TYPE_SYSTEM_VOID 0xCE81
+#define HIVECODE_TYPE_SYSTEM_INT32 0x61C0
+#define HIVECODE_TYPE_SYSTEM_INT32_ARRAY 0x61C1
+#define HIVECODE_TYPE_SYSTEM_BOOLEAN 0x2227
+#define HIVECODE_TYPE_SYSTEM_BOOLEAN_ARRAY 0x2228
+#define HIVECODE_TYPE_SYSTEM_SBYTE 0x767E
+#define HIVECODE_TYPE_SYSTEM_SBYTE_ARRAY 0x767F
+#define HIVECODE_TYPE_SYSTEM_UINT16 0xD98B
+#define HIVECODE_TYPE_SYSTEM_UINT16_ARRAY 0xD98C
+#define HIVECODE_TYPE_SYSTEM_UINT32 0x95E7
+#define HIVECODE_TYPE_SYSTEM_UINT32_ARRAY 0x95E8
+#define HIVECODE_TYPE_SYSTEM_BYTE 0x45A2
+#define HIVECODE_TYPE_SYSTEM_BYTE_ARRAY 0x45A3
+#define HIVECODE_TYPE_SYSTEM_CHAR 0x958E
+#define HIVECODE_TYPE_SYSTEM_CHAR_ARRAY 0x958F
+#define HIVECODE_TYPE_SYSTEM_INT16 0xBC39
+#define HIVECODE_TYPE_SYSTEM_INT16_ARRAY 0xBC3A
+#define HIVECODE_TYPE_SYSTEM_STRING 0x1127
+#define HIVECODE_TYPE_SYSTEM_STRING_ARRAY 0x1128
+#define HIVECODE_TYPE_SYSTEM_INT64 0xDEFB
+#define HIVECODE_TYPE_SYSTEM_INT64_ARRAY 0xDEFC
+#define HIVECODE_TYPE_SYSTEM_UINT64 0x71AF
+#define HIVECODE_TYPE_SYSTEM_UINT64_ARRAY 0x71B0
+
+#define HIVECODE_TYPE_SYSTEM_IO_MEMORYSTREAM 0xFED7
+
+// for port discovery lookup.
+#define CARDMANAGER_SERVICE_PORT 1
+#define CARDMANAGER_SERVICE_NAME "ContentManager"
+#define HIVECODE_NAMESPACE_SMARTCARD 0x00F5EFBF
+#define HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER 0xB18C
+#define HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT 0x7616
+
+#define HIVECODE_TYPE_SYSTEM_EXCEPTION 0xD4B0
+#define HIVECODE_TYPE_SYSTEM_SYSTEMEXCEPTION 0x28AC
+#define HIVECODE_TYPE_SYSTEM_OUTOFMEMORYEXCEPTION 0xE14E
+#define HIVECODE_TYPE_SYSTEM_ARGUMENTEXCEPTION 0xAB8C
+#define HIVECODE_TYPE_SYSTEM_ARGUMENTNULLEXCEPTION 0x2138
+#define HIVECODE_TYPE_SYSTEM_NULLREFERENCEEXCEPTION 0xC5B8
+#define HIVECODE_TYPE_SYSTEM_ARGUMENTOUTOFRANGEEXCEPTION 0x6B11
+#define HIVECODE_TYPE_SYSTEM_NOTSUPPORTEDEXCEPTION 0xAA74
+#define HIVECODE_TYPE_SYSTEM_INVALIDCASTEXCEPTION 0xD24F
+#define HIVECODE_TYPE_SYSTEM_INVALIDOPERATIONEXCEPTION 0xFAB4
+#define HIVECODE_TYPE_SYSTEM_NOTIMPLEMENTEDEXCEPTION 0x3CE5
+#define HIVECODE_TYPE_SYSTEM_OBJECTDISPOSEDEXCEPTION 0x0FAC
+#define HIVECODE_TYPE_SYSTEM_UNAUTHORIZEDACCESSEXCEPTION 0x4697
+#define HIVECODE_TYPE_SYSTEM_INDEXOUTOFRANGEEXCEPTION 0xBF1D
+#define HIVECODE_TYPE_SYSTEM_FORMATEXCEPTION 0xF3BF
+#define HIVECODE_TYPE_SYSTEM_ARITHMETICEXCEPTION 0x6683
+#define HIVECODE_TYPE_SYSTEM_OVERFLOWEXCEPTION 0x20A0
+#define HIVECODE_TYPE_SYSTEM_BADIMAGEFORMATEXCEPTION 0x530A
+#define HIVECODE_TYPE_SYSTEM_APPLICATIONEXCEPTION 0xB1EA
+#define HIVECODE_TYPE_SYSTEM_ARRAYTYPEMISMATCHEXCEPTION 0x3F88
+#define HIVECODE_TYPE_SYSTEM_DIVIDEBYZEROEXCEPTION 0xDFCF
+#define HIVECODE_TYPE_SYSTEM_MEMBERACCESSEXCEPTION 0xF5F3
+#define HIVECODE_TYPE_SYSTEM_MISSINGMEMBEREXCEPTION 0x20BB
+#define HIVECODE_TYPE_SYSTEM_MISSINGFIELDEXCEPTION 0x7366
+#define HIVECODE_TYPE_SYSTEM_MISSINGMETHODEXCEPTION 0x905B
+#define HIVECODE_TYPE_SYSTEM_RANKEXCEPTION 0xB2AE
+#define HIVECODE_TYPE_SYSTEM_STACKOVERFLOWEXCEPTION 0x0844
+#define HIVECODE_TYPE_SYSTEM_TYPELOADEXCEPTION 0x048E
+#define HIVECODE_TYPE_SYSTEM_IO_IOEXCEPTION 0x3BBE
+#define HIVECODE_TYPE_SYSTEM_IO_DIRECTORYNOTFOUNDEXCEPTION 0x975A
+#define HIVECODE_TYPE_SYSTEM_IO_FILENOTFOUNDEXCEPTION 0x07EB
+#define HIVECODE_TYPE_SYSTEM_RUNTIME_REMOTING_REMOTINGEXCEPTION 0xD52A
+#define HIVECODE_TYPE_SYSTEM_RUNTIME_SERIALIZATION_SERIALIZATIONEXCEPTION 0xA1D2
+#define HIVECODE_TYPE_SYSTEM_SECURITY_SECURITYEXCEPTION 0x31AF
+#define HIVECODE_TYPE_SYSTEM_SECURITY_VERIFICATIONEXCEPTION 0x67F1
+#define HIVECODE_TYPE_SYSTEM_SECURITY_CRYPTOGRAPHY_CRYPTOGRAPHICEXCEPTION 0x8FEB
+
+#ifdef SMARTCARDMARSHALLER_EXPORTS
+
+BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+{
+ UNREFERENCED_PARAMETER(hModule);
+ UNREFERENCED_PARAMETER(lpReserved);
+
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
+#endif
+
+static u2 ComReadU2At(u1Array &array, u4 pos)
+{
+ if ((u8)(pos + sizeof(u2)) > (u8)array.GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+ u1* buff = array.GetBuffer();
+ return (u2)((((u2)buff[pos]) << 8) + buff[pos + 1]);
+}
+
+u4 ComReadU4At(u1Array &array, u4 pos);
+u4 ComReadU4At(u1Array &array, u4 pos)
+{
+ if ((u8)(pos + sizeof(u4)) > (u8)array.GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+ u1* buff = array.GetBuffer();
+ return (u4)((((u4)buff[pos]) << 24) + (((u4)buff[pos + 1]) << 16) + (((u4)buff[pos + 2]) << 8) + buff[pos + 3]);
+}
+
+static u8 ComReadU8At(u1Array &array, u4 pos)
+{
+ if ((u8)(pos + sizeof(u8)) > (u8)array.GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+ u1* buff = array.GetBuffer();
+
+ u1 b1 = buff[pos];
+ u1 b2 = buff[pos + 1];
+ u1 b3 = buff[pos + 2];
+ u1 b4 = buff[pos + 3];
+ u1 b5 = buff[pos + 4];
+ u1 b6 = buff[pos + 5];
+ u1 b7 = buff[pos + 6];
+ u1 b8 = buff[pos + 7];
+
+ return (((u8)b1 << 56) | ((u8)b2 << 48) | ((u8)b3 << 40) | ((u8)b4 << 32) | ((u8)b5 << 24) | ((u8)b6 << 16) | ((u8)b7 << 8) | b8);
+}
+
+static void ProcessException(u1Array answer, u4 protocolOffset)
+{
+ u4 exceptionNamespace;
+ u4 exceptionName;
+ char* chst = NULL;
+
+ try {
+ exceptionNamespace = ComReadU4At(answer, protocolOffset + 0);
+ exceptionName = ComReadU2At(answer, protocolOffset + 4);
+
+ if (answer.GetLength() > (protocolOffset + 6)) {
+ u2 strLen = ComReadU2At(answer, protocolOffset + 6);
+ if ((strLen > 0) && (strLen != 0xFFFF)) {
+ u2 len = ComputeLPSTRLength(answer, protocolOffset + 8, strLen);
+ chst = new char[len + 1];
+ chst[len] = '\0';
+ UTF8Decode(answer, protocolOffset + 8, strLen, chst);
+ }
+ }
+ } catch (...) {
+ // someone is messing with the protocol
+ if (chst != NULL) {
+ delete[] chst;
+ }
+ throw RemotingException((lpCharPtr)"");
+ }
+
+ if (chst == NULL) {
+ // prepare empty string
+ chst = new char[1];
+ chst[0] = '\0';
+ }
+
+ // create a string object on the stack.
+ // when exception is thrown the exception object is copied on
+ // a temporary location and live till used by catch block
+ //
+ // it is not a good idea to pass chst as a parameter of exception object
+ // as there will be no way to delete it.
+ std::string chstr(chst);
+
+ delete[] chst;
+
+ switch (exceptionNamespace)
+ {
+ case HIVECODE_NAMESPACE_SYSTEM:
+ {
+ switch(exceptionName){
+
+ case (u2)HIVECODE_TYPE_SYSTEM_EXCEPTION:
+ throw Exception(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_SYSTEMEXCEPTION:
+ throw SystemException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_OUTOFMEMORYEXCEPTION:
+ throw OutOfMemoryException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_ARGUMENTEXCEPTION:
+ throw ArgumentException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_ARGUMENTNULLEXCEPTION:
+ throw ArgumentNullException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_NULLREFERENCEEXCEPTION:
+ throw NullReferenceException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_ARGUMENTOUTOFRANGEEXCEPTION:
+ throw ArgumentOutOfRangeException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_NOTSUPPORTEDEXCEPTION:
+ throw NotSupportedException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_INVALIDCASTEXCEPTION:
+ throw InvalidCastException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_INVALIDOPERATIONEXCEPTION:
+ throw InvalidOperationException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_NOTIMPLEMENTEDEXCEPTION:
+ throw NotImplementedException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_OBJECTDISPOSEDEXCEPTION:
+ throw ObjectDisposedException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_UNAUTHORIZEDACCESSEXCEPTION:
+ throw UnauthorizedAccessException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_INDEXOUTOFRANGEEXCEPTION:
+ throw IndexOutOfRangeException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_FORMATEXCEPTION:
+ throw FormatException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_ARITHMETICEXCEPTION:
+ throw ArithmeticException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_OVERFLOWEXCEPTION:
+ throw OverflowException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_BADIMAGEFORMATEXCEPTION:
+ throw BadImageFormatException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_APPLICATIONEXCEPTION:
+ throw ApplicationException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_ARRAYTYPEMISMATCHEXCEPTION:
+ throw ArrayTypeMismatchException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_DIVIDEBYZEROEXCEPTION:
+ throw DivideByZeroException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_MEMBERACCESSEXCEPTION:
+ throw MemberAccessException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_MISSINGMEMBEREXCEPTION:
+ throw MissingMemberException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_MISSINGFIELDEXCEPTION:
+ throw MissingFieldException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_MISSINGMETHODEXCEPTION:
+ throw MissingMethodException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_RANKEXCEPTION:
+ throw RankException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_STACKOVERFLOWEXCEPTION:
+ throw StackOverflowException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_TYPELOADEXCEPTION:
+ throw TypeLoadException(chstr);
+ }
+ }
+ break;
+
+ case HIVECODE_NAMESPACE_SYSTEM_IO:
+ {
+ switch(exceptionName){
+ case (u2)HIVECODE_TYPE_SYSTEM_IO_IOEXCEPTION:
+ throw IOException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_IO_DIRECTORYNOTFOUNDEXCEPTION:
+ throw DirectoryNotFoundException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_IO_FILENOTFOUNDEXCEPTION:
+ throw FileNotFoundException(chstr);
+ }
+ }
+ break;
+
+ case HIVECODE_NAMESPACE_SYSTEM_SECURITY:
+ {
+ switch(exceptionName){
+ case (u2)HIVECODE_TYPE_SYSTEM_SECURITY_SECURITYEXCEPTION:
+ throw SecurityException(chstr);
+
+ case (u2)HIVECODE_TYPE_SYSTEM_SECURITY_VERIFICATIONEXCEPTION:
+ throw VerificationException(chstr);
+ }
+ }
+ break;
+
+ case HIVECODE_NAMESPACE_SYSTEM_RUNTIME_REMOTING:
+ {
+ switch(exceptionName){
+ case (u2)HIVECODE_TYPE_SYSTEM_RUNTIME_REMOTING_REMOTINGEXCEPTION:
+ throw RemotingException(chstr);
+ }
+ }
+ break;
+
+ case HIVECODE_NAMESPACE_SYSTEM_RUNTIME_SERIALIZATION:
+ {
+ switch(exceptionName){
+ case (u2)HIVECODE_TYPE_SYSTEM_RUNTIME_SERIALIZATION_SERIALIZATIONEXCEPTION:
+ throw SerializationException(chstr);
+ }
+ }
+ break;
+
+ case HIVECODE_NAMESPACE_SYSTEM_SECURITY_CRYPTOGRAPHY:
+ {
+ switch(exceptionName){
+ case (u2)HIVECODE_TYPE_SYSTEM_SECURITY_CRYPTOGRAPHY_CRYPTOGRAPHICEXCEPTION:
+ throw CryptographicException(chstr);
+ }
+ }
+ break;
+ }
+
+ // custom exception from the card application or someone is messing with the protocol
+ // no means of translation.
+ throw Exception(chstr);
+}
+
+u4 CheckForException(u1Array answer, u4 nameSpace, u2 type);
+u4 CheckForException(u1Array answer, u4 nameSpace, u2 type)
+{
+ u1 protocolAnswerPrefix = answer.ReadU1At(0);
+
+#ifdef SUPPORT_BETA_VERSION
+ if (protocolAnswerPrefix == 0) {
+ // beta version protocol (namespace & type systematically returned)
+ if ((ComReadU4At(answer, 0) != nameSpace) || (ComReadU2At(answer, 4) != type)) {
+ ProcessException(answer, 0);
+ }
+ // skip namespace & type
+ return (4 + 2);
+ }
+#endif
+
+ // new protocol
+ if (protocolAnswerPrefix != 0x01) {
+ if (protocolAnswerPrefix == 0xFF) {
+ // exception info expected in the buffer
+ ProcessException(answer, 1);
+ } else {
+ // someone is messing with the protocol
+ throw RemotingException((lpCharPtr)"");
+ }
+ }
+
+ // skip return type info (protocolAnswerPrefix: 0x01 = ok, 0xFF = exception)
+ return 1;
+}
+
+SmartCardMarshaller::SmartCardMarshaller(SCARDHANDLE cardHandle, u2 portNumber, M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode)
+{
+ this->uri = NULL;
+ this->pcsc = NULL;
+ this->portNumber = portNumber;
+ this->nameSpaceHivecode = nameSpaceHivecode;
+ this->typeHivecode = typeHivecode;
+ this->ProcessInputStream = NULL;
+ this->ProcessOutputStream = NULL;
+
+#ifndef _XCL_
+ this->pcsc = new PCSC(cardHandle);
+#else // _XCL_
+ this->pcsc = new XCLBroker(cardHandle);
+#endif // _XCL_
+
+ try {
+ this->uri = new std::string(uri->c_str());
+ } catch (...) {
+ delete this->pcsc;
+ throw;
+ }
+}
+
+SmartCardMarshaller::SmartCardMarshaller(M_SAL_IN std::string* readerName, u2 portNumber, M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode, u4 index)
+{
+ Log::begin( "SmartCardMarshaller::SmartCardMarshaller" );
+
+ this->uri = NULL;
+ this->pcsc = NULL;
+ this->portNumber = portNumber;
+ this->nameSpaceHivecode = nameSpaceHivecode;
+ this->typeHivecode = typeHivecode;
+ this->ProcessInputStream = NULL;
+ this->ProcessOutputStream = NULL;
+
+#ifdef WIN32
+ if ((readerName == NULL) || (_stricmp("selfdiscover", readerName->c_str()) == 0))
+ {
+#else
+ if ((readerName == NULL) || (strncasecmp("selfdiscover", readerName->c_str(),readerName->length()) == 0))
+ {
+#endif
+ Log::log( "SmartCardMarshaller::SmartCardMarshaller - new PCSC( readerName, &portNumber, uri, nameSpaceHivecode, typeHivecode, index) ..." );
+#ifndef _XCL_
+ this->pcsc = new PCSC( readerName, &portNumber, uri, nameSpaceHivecode, typeHivecode, index);
+#else // _XCL
+ this->pcsc = new XCLBroker(readerName, &portNumber, uri, nameSpaceHivecode, typeHivecode, index);
+#endif // _XCL_
+ Log::log( "SmartCardMarshaller::SmartCardMarshaller - new PCSC( readerName, &portNumber, uri, nameSpaceHivecode, typeHivecode, index) ok" );
+ }
+ else
+ {
+ Log::log( "SmartCardMarshaller::SmartCardMarshaller - new PCSC( readerName ) ..." );
+#ifndef _XCL_
+ this->pcsc = new PCSC( readerName );
+#else // _XCL_
+ this->pcsc = new XCLBroker(readerName);
+#endif // _XCL_
+ Log::log( "SmartCardMarshaller::SmartCardMarshaller - new PCSC( readerName ) ok" );
+ }
+
+ try
+ {
+ Log::log( "SmartCardMarshaller::SmartCardMarshaller - new std::string(uri->c_str()) ..." );
+ this->uri = new std::string(uri->c_str());
+ Log::log( "SmartCardMarshaller::SmartCardMarshaller - new std::string(uri->c_str()) ok" );
+ }
+ catch (...)
+ {
+ Log::error( "SmartCardMarshaller::SmartCardMarshaller", "(...)" );
+ delete this->pcsc;
+ throw;
+ }
+
+ Log::end( "SmartCardMarshaller::SmartCardMarshaller" );
+}
+
+std::string* SmartCardMarshaller::GetReaderName(void)
+{
+ return this->pcsc->GetReaderName();
+}
+
+SCARDHANDLE SmartCardMarshaller::GetCardHandle(void)
+{
+ return this->pcsc->GetCardHandle();
+}
+
+void SmartCardMarshaller::DoTransact(bool flag)
+{
+ this->pcsc->DoTransact(flag);
+}
+
+SmartCardMarshaller::~SmartCardMarshaller(void)
+{
+ if (this->uri != NULL) {
+ delete this->uri;
+ this->uri = NULL;
+ }
+
+ if (this->pcsc != NULL) {
+ delete this->pcsc;
+ this->pcsc = NULL;
+ }
+}
+
+void SmartCardMarshaller::UpdatePCSCCardHandle(SCARDHANDLE hCard)
+{
+ this->pcsc->SetCardHandle(hCard);
+}
+
+static void ProcessByReferenceArguments(u1 type, u1Array* dataArray, u4* offsetPtr, va_list* markerPtr, u1 isIn)
+{
+ //va_list marker = *markerPtr;
+ u4 offset = *offsetPtr;
+
+ switch (type) {
+
+ case MARSHALLER_TYPE_REF_BOOL:
+ case MARSHALLER_TYPE_REF_U1:
+ case MARSHALLER_TYPE_REF_S1:
+ {
+ u1* val = va_arg(/*marker*/*markerPtr, u1*);
+ if (val == NULL) {
+ throw NullReferenceException((lpCharPtr)"");
+ }
+ if (isIn == TRUE) {
+ *dataArray += *val;
+ }
+ else {
+ *val = (*dataArray).ReadU1At(offset);
+ }
+ offset += sizeof(u1);
+ }
+ break;
+
+ case MARSHALLER_TYPE_REF_CHAR:
+ case MARSHALLER_TYPE_REF_U2:
+ case MARSHALLER_TYPE_REF_S2:
+ {
+ u2* val = va_arg(/*marker*/*markerPtr, u2*);
+ if (val == NULL) {
+ throw NullReferenceException((lpCharPtr)"");
+ }
+ if (isIn == TRUE) {
+ *dataArray += *val;
+ }
+ else {
+ *val = ComReadU2At(*dataArray, offset);
+ }
+ offset += sizeof(u2);
+ }
+ break;
+
+ case MARSHALLER_TYPE_REF_U4:
+ case MARSHALLER_TYPE_REF_S4:
+ {
+ u4* val = va_arg(/*marker*/*markerPtr, u4*);
+ if (val == NULL) {
+ throw NullReferenceException((lpCharPtr)"");
+ }
+ if (isIn == TRUE) {
+ *dataArray += *val;
+ }
+ else {
+ *val = ComReadU4At(*dataArray, offset);
+ }
+ offset += sizeof(u4);
+ }
+ break;
+
+ case MARSHALLER_TYPE_REF_U8:
+ case MARSHALLER_TYPE_REF_S8:
+ {
+ u8* val = va_arg(/*marker*/*markerPtr, u8*);
+ if (val == NULL) {
+ throw NullReferenceException((lpCharPtr)"");
+ }
+ if (isIn == TRUE) {
+ *dataArray += *val;
+ }
+ else {
+ *val = ComReadU8At(*dataArray, offset);
+ }
+ offset += sizeof(u8);
+ }
+ break;
+
+ case MARSHALLER_TYPE_REF_STRING:
+ {
+ std::string** val = va_arg(/*marker*/*markerPtr, std::string**);
+ if (val == NULL) {
+ throw NullReferenceException((lpCharPtr)"");
+ }
+ if (isIn == TRUE) {
+ offset += sizeof(u2);
+ if (*val != NULL) {
+ offset += ComputeUTF8Length((lpCharPtr)((*val)->c_str()));
+ }
+ (*dataArray).Append(*val);
+ } else {
+ u2 len = ComReadU2At(*dataArray, offset);
+ offset += sizeof(u2);
+ if (len == 0xFFFF) {
+ *val = NULL;
+ } else {
+ // store result
+ u2 l = ComputeLPSTRLength(*dataArray, offset, len);
+ char* chstr = new char[l + 1];
+ try {
+ chstr[l] = '\0';
+ UTF8Decode(*dataArray, offset, len, chstr);
+ *val = new std::string(chstr);
+ } catch (...) {
+ delete[] chstr;
+ throw;
+ }
+ delete[] chstr;
+ offset += len;
+ }
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_REF_S1ARRAY:
+ case MARSHALLER_TYPE_REF_BOOLARRAY:
+ case MARSHALLER_TYPE_REF_U1ARRAY:
+ {
+ u1Array** val = va_arg(/*marker*/*markerPtr, u1Array**);
+ if (val == NULL) {
+ throw NullReferenceException((lpCharPtr)"");
+ }
+
+ if (isIn == TRUE) {
+ offset += sizeof(u4);
+ if ((*val)->IsNull() == FALSE) {
+ u4 valLen = (*val)->GetLength();
+ u1* valBuf = (*val)->GetBuffer();
+ *dataArray += valLen;
+ for(u4 v = 0; v < valLen; v++) {
+ *dataArray += valBuf[v];
+ }
+ offset += (sizeof(u1) * valLen);
+ } else {
+ *dataArray += 0xFFFFFFFF;
+ }
+ } else {
+
+ u4 len = ComReadU4At(*dataArray, offset);
+ offset += sizeof(u4);
+
+ u1Array* refArray = NULL;
+
+ try {
+ if (len == 0xFFFFFFFF) {
+ refArray = new u1Array(-1);
+ } else {
+ refArray = new u1Array(len);
+ for (u4 i = 0; i < len; i++) {
+ refArray->SetU1At(i, dataArray->ReadU1At(offset));
+ offset += sizeof(u1);
+ }
+ }
+ } catch (...) {
+ if (refArray != NULL) {
+ delete refArray;
+ }
+ throw;
+ }
+
+ if (*val != NULL) {
+ // perform cleanup
+ delete *val;
+ }
+
+ *val = refArray;
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_REF_S2ARRAY:
+ case MARSHALLER_TYPE_REF_U2ARRAY:
+ {
+ u2Array** val = va_arg(/*marker*/*markerPtr, u2Array**);
+ if (val == NULL) {
+ throw NullReferenceException((lpCharPtr)"");
+ }
+
+ if (isIn == TRUE) {
+ offset += sizeof(u4);
+ if ((*val)->IsNull() == FALSE) {
+ u4 valLen = (*val)->GetLength();
+ u2* valBuf = (*val)->GetBuffer();
+ *dataArray += valLen;
+ for(u4 v = 0; v < valLen; v++) {
+ *dataArray += valBuf[v];
+ }
+ offset += (sizeof(u2) * valLen);
+ } else {
+ *dataArray += 0xFFFFFFFF;
+ }
+ } else {
+
+ u4 len = ComReadU4At(*dataArray, offset);
+ offset += sizeof(u4);
+
+ u2Array* refArray = NULL;
+
+ try {
+ if (len == 0xFFFFFFFF) {
+ refArray = new u2Array(-1);
+ } else {
+ refArray = new u2Array(len);
+ for (u4 i = 0; i < len; i++) {
+ refArray->SetU2At(i, ComReadU2At(*dataArray, offset));
+ offset += sizeof(u2);
+ }
+ }
+ } catch (...) {
+ if (refArray != NULL) {
+ delete refArray;
+ }
+ throw;
+ }
+
+ if (*val != NULL) {
+ // perform cleanup
+ delete *val;
+ }
+
+ *val = refArray;
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_REF_S4ARRAY:
+ case MARSHALLER_TYPE_REF_U4ARRAY:
+ {
+ u4Array** val = va_arg(/*marker*/*markerPtr, u4Array**);
+ if (val == NULL) {
+ throw NullReferenceException((lpCharPtr)"");
+ }
+
+ if (isIn == TRUE) {
+ offset += sizeof(u4);
+ if ((*val)->IsNull() == FALSE) {
+ u4 valLen = (*val)->GetLength();
+ u4* valBuf = (*val)->GetBuffer();
+ *dataArray += valLen;
+ for(u4 v = 0; v < valLen; v++) {
+ *dataArray += valBuf[v];
+ }
+ offset += (sizeof(u4) * valLen);
+ } else {
+ *dataArray += 0xFFFFFFFF;
+ }
+ } else {
+
+ u4 len = ComReadU4At(*dataArray, offset);
+ offset += sizeof(u4);
+
+ u4Array* refArray = NULL;
+
+ try {
+ if (len == 0xFFFFFFFF) {
+ refArray = new u4Array(-1);
+ } else {
+ refArray = new u4Array(len);
+ for (u4 i = 0; i < len; i++) {
+ refArray->SetU4At(i, ComReadU4At(*dataArray, offset));
+ offset += sizeof(u4);
+ }
+ }
+ } catch (...) {
+ if (refArray != NULL) {
+ delete refArray;
+ }
+ throw;
+ }
+
+ if (*val != NULL) {
+ // perform cleanup
+ delete *val;
+ }
+
+ *val = refArray;
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_REF_S8ARRAY:
+ case MARSHALLER_TYPE_REF_U8ARRAY:
+ {
+ u8Array** val = va_arg(/*marker*/*markerPtr, u8Array**);
+ if (val == NULL) {
+ throw NullReferenceException((lpCharPtr)"");
+ }
+
+ if (isIn == TRUE) {
+ offset += sizeof(u4);
+ if ((*val)->IsNull() == FALSE) {
+ u4 valLen = (*val)->GetLength();
+ u8* valBuf = (*val)->GetBuffer();
+ *dataArray += valLen;
+ for(u4 v = 0; v < valLen; v++) {
+ *dataArray += valBuf[v];
+ }
+ offset += (sizeof(u8) * valLen);
+ } else {
+ *dataArray += 0xFFFFFFFF;
+ }
+ } else {
+
+ u4 len = ComReadU4At(*dataArray, offset);
+ offset += sizeof(u4);
+
+ u8Array* refArray = NULL;
+
+ try {
+ if (len == 0xFFFFFFFF) {
+ refArray = new u8Array(-1);
+ } else {
+ refArray = new u8Array(len);
+ for (u4 i = 0; i < len; i++) {
+ refArray->SetU8At(i, ComReadU8At(*dataArray, offset));
+ offset += sizeof(u4);
+ }
+ }
+ } catch (...) {
+ if (refArray != NULL) {
+ delete refArray;
+ }
+ throw;
+ }
+
+ if (*val != NULL) {
+ // perform cleanup
+ delete *val;
+ }
+
+ *val = refArray;
+ }
+ }
+ break;
+
+ default:
+ {
+ if (isIn == TRUE) {
+ throw Exception("Un-recognized input argument type");
+ } else {
+ throw Exception("Un-recognized byref argument type");
+ }
+ }
+ break;
+ }
+
+ //*markerPtr = marker;
+ *offsetPtr = offset;
+}
+
+
+static void ProcessOutputArguments(u1 type, u1Array* answerPtr, u4* offsetPtr, va_list* markerPtr)
+{
+ switch (type) {
+
+ case MARSHALLER_TYPE_IN_BOOL:
+ case MARSHALLER_TYPE_IN_S1:
+ case MARSHALLER_TYPE_IN_U1:
+ case MARSHALLER_TYPE_IN_CHAR:
+ case MARSHALLER_TYPE_IN_S2:
+ case MARSHALLER_TYPE_IN_U2:
+ case MARSHALLER_TYPE_IN_S4:
+ case MARSHALLER_TYPE_IN_U4:
+ case MARSHALLER_TYPE_IN_STRING:
+ case MARSHALLER_TYPE_IN_MEMORYSTREAM:
+ case MARSHALLER_TYPE_IN_BOOLARRAY:
+ case MARSHALLER_TYPE_IN_S1ARRAY:
+ case MARSHALLER_TYPE_IN_U1ARRAY:
+ case MARSHALLER_TYPE_IN_CHARARRAY:
+ case MARSHALLER_TYPE_IN_S2ARRAY:
+ case MARSHALLER_TYPE_IN_U2ARRAY:
+ case MARSHALLER_TYPE_IN_S4ARRAY:
+ case MARSHALLER_TYPE_IN_U4ARRAY:
+ case MARSHALLER_TYPE_IN_S8ARRAY:
+ case MARSHALLER_TYPE_IN_U8ARRAY:
+ case MARSHALLER_TYPE_IN_STRINGARRAY:
+ {
+ // ignore input argument (slot size = 4 bytes)
+ //va_list marker = *markerPtr;
+ /*u4 v = */va_arg(/*marker*/*markerPtr, u4);
+ //*markerPtr = marker;
+
+ /*DBG_UNREFERENCED_LOCAL_VARIABLE(v);*/
+ }
+ break;
+
+ case MARSHALLER_TYPE_IN_S8:
+ case MARSHALLER_TYPE_IN_U8:
+ {
+ // ignore input argument (slot size = 8 bytes)
+ //va_list marker = *markerPtr;
+ /*u8 v = */va_arg(/*marker*/*markerPtr, u8);
+ //*markerPtr = marker;
+
+ /*DBG_UNREFERENCED_LOCAL_VARIABLE(v);*/
+ }
+ break;
+
+ default:
+ ProcessByReferenceArguments(type, answerPtr, offsetPtr, markerPtr, FALSE);
+ break;
+ }
+}
+
+static u4 ProcessReturnType(u1 type, u1Array* answerPtr, va_list* markerPtr)
+{
+ u1Array answer = *answerPtr;
+ u4 offset = 0;
+ //va_list marker = *markerPtr;
+
+ switch (type) {
+
+ // void (can happen for the method return param)
+ case MARSHALLER_TYPE_RET_VOID:
+ {
+ if (answer.GetLength() > 0) {
+#ifdef SUPPORT_BETA_VERSION
+ if (answer.ReadU1At(0) == 0x00) {
+ // beta version protocol
+ ProcessException(answer, 0);
+ }
+#endif
+ // new protocol
+ ProcessException(answer, 1);
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_BOOL:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_BOOLEAN);
+ u1* valToReturn = va_arg(/*marker*/*markerPtr, u1*);
+ if (answer.ReadU1At(offset) == 0) {
+ *valToReturn = FALSE;
+ } else {
+ *valToReturn = TRUE;
+ }
+ offset += sizeof(u1);
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_S1:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_SBYTE);
+ s1* valToReturn = va_arg(/*marker*/*markerPtr, s1*);
+ *valToReturn = answer.ReadU1At(offset);
+ offset += sizeof(u1);
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_U1:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_BYTE);
+ u1* valToReturn = va_arg(/*marker*/*markerPtr, u1*);
+ *valToReturn = answer.ReadU1At(offset);
+ offset += sizeof(u1);
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_CHAR:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_CHAR);
+ char* valToReturn = va_arg(/*marker*/*markerPtr, char*);
+ *valToReturn = (char)ComReadU2At(answer, offset);
+ offset += sizeof(u2);
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_S2:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT16);
+ s2* valToReturn = va_arg(/*marker*/*markerPtr, s2*);
+ *valToReturn = ComReadU2At(answer, offset);
+ offset += sizeof(u2);
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_U2:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT16);
+ u2* valToReturn = va_arg(/*marker*/*markerPtr, u2*);
+ *valToReturn = ComReadU2At(answer, offset);
+ offset += sizeof(u2);
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_S4:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT32);
+ s4* valToReturn = va_arg(/*marker*/*markerPtr, s4*);
+ *valToReturn = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_U4:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT32);
+ u4* valToReturn = va_arg(/*marker*/*markerPtr, u4*);
+ *valToReturn = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_S8:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT64);
+ s8* valToReturn = va_arg(/*marker*/*markerPtr, s8*);
+ *valToReturn = ComReadU8At(answer, offset);
+ offset += sizeof(u8);
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_U8:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT64);
+ u8* valToReturn = va_arg(/*marker*/*markerPtr, u8*);
+ *valToReturn = ComReadU8At(answer, offset);
+ offset += sizeof(u8);
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_STRING:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_STRING);
+ std::string** valToReturn = va_arg(/*marker*/*markerPtr, std::string**);
+ u2 len = ComReadU2At(answer, offset);
+ offset += sizeof(u2);
+ if (len == 0xFFFF) {
+ *valToReturn = NULL;
+ } else {
+ // store result
+ u2 l = ComputeLPSTRLength(answer, offset, len);
+ char* chstr = new char[l + 1];
+ try {
+ chstr[l] = '\0';
+ UTF8Decode(answer, offset, len, chstr);
+ *valToReturn = new std::string(chstr);
+ } catch (...) {
+ delete[] chstr;
+ throw;
+ }
+ delete[] chstr;
+ offset += len;
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_BOOLARRAY:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_BOOLEAN_ARRAY);
+ u1Array** valToReturn = va_arg(/*marker*/*markerPtr, u1Array**);
+ u4 len = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ if (len == 0xFFFFFFFF) {
+ *valToReturn = new u1Array(-1);
+ } else {
+ // store result
+ *valToReturn = new u1Array(answer, offset, len);
+ offset += len;
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_S1ARRAY:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_SBYTE_ARRAY);
+ s1Array** valToReturn = va_arg(/*marker*/*markerPtr, s1Array**);
+ u4 len = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ if (len == 0xFFFFFFFF) {
+ *valToReturn = new s1Array(-1);
+ } else {
+ // store result
+ *valToReturn = new s1Array(answer, offset, len);
+ offset += len;
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_U1ARRAY:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_BYTE_ARRAY);
+ u1Array** valToReturn = va_arg(/*marker*/*markerPtr, u1Array**);
+ u4 len = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ if (len == 0xFFFFFFFF) {
+ *valToReturn = new u1Array(-1);
+ } else {
+ // store result
+ *valToReturn = new u1Array(answer, offset, len);
+ offset += len;
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_CHARARRAY:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_CHAR_ARRAY);
+ charArray** valToReturn = va_arg(/*marker*/*markerPtr, charArray**);
+ u4 len = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ if (len == 0xFFFFFFFF) {
+ *valToReturn = new charArray(-1);
+ } else {
+ // store result
+ *valToReturn = new charArray(len);
+ try {
+ for (u4 j = 0; j < len; j++) {
+ (*valToReturn)->GetBuffer()[j] = ComReadU2At(answer, offset);
+ offset += sizeof(s2);
+ }
+ } catch (...) {
+ delete *valToReturn;
+ throw;
+ }
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_S2ARRAY:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT16_ARRAY);
+ s2Array** valToReturn = va_arg(/*marker*/*markerPtr, s2Array**);
+ u4 len = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ if (len == 0xFFFFFFFF) {
+ *valToReturn = new s2Array(-1);
+ } else {
+ // store result
+ *valToReturn = new s2Array(len);
+ try {
+ for (u4 j = 0; j < len; j++) {
+ (*valToReturn)->GetBuffer()[j] = ComReadU2At(answer, offset);
+ offset += sizeof(s2);
+ }
+ } catch (...) {
+ delete *valToReturn;
+ throw;
+ }
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_U2ARRAY:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT16_ARRAY);
+ u2Array** valToReturn = va_arg(/*marker*/*markerPtr, u2Array**);
+ u4 len = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ if (len == 0xFFFFFFFF) {
+ *valToReturn = new u2Array(-1);
+ } else {
+ // store result
+ *valToReturn = new u2Array(len);
+ try {
+ for (u4 j = 0; j < len; j++) {
+ (*valToReturn)->GetBuffer()[j] = ComReadU2At(answer, offset);
+ offset += sizeof(u2);
+ }
+ } catch (...) {
+ delete *valToReturn;
+ throw;
+ }
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_S4ARRAY:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT32_ARRAY);
+ s4Array** valToReturn = va_arg(/*marker*/*markerPtr, s4Array**);
+ u4 len = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ if (len == 0xFFFFFFFF) {
+ *valToReturn = new s4Array(-1);
+ } else {
+ // store result
+ *valToReturn = new s4Array(len);
+ try {
+ for (u4 j = 0; j < len; j++) {
+ (*valToReturn)->GetBuffer()[j] = ComReadU4At(answer, offset);
+ offset += sizeof(s4);
+ }
+ } catch (...) {
+ delete *valToReturn;
+ throw;
+ }
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_U4ARRAY:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT32_ARRAY);
+ u4Array** valToReturn = va_arg(/*marker*/*markerPtr, u4Array**);
+ u4 len = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ if (len == 0xFFFFFFFF) {
+ *valToReturn = new u4Array(-1);
+ } else {
+ // store result
+ *valToReturn = new u4Array(len);
+ try {
+ for (u4 j = 0; j < len; j++) {
+ (*valToReturn)->GetBuffer()[j] = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ }
+ } catch (...) {
+ delete *valToReturn;
+ throw;
+ }
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_S8ARRAY:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT64_ARRAY);
+ s8Array** valToReturn = va_arg(/*marker*/*markerPtr, s8Array**);
+ u4 len = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ if (len == 0xFFFFFFFF) {
+ *valToReturn = new s8Array(-1);
+ } else {
+ // store result
+ *valToReturn = new s8Array(len);
+ try {
+ for (u4 j = 0; j < len; j++) {
+ (*valToReturn)->GetBuffer()[j] = ComReadU8At(answer, offset);
+ offset += sizeof(s8);
+ }
+ } catch (...) {
+ delete *valToReturn;
+ throw;
+ }
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_U8ARRAY:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_UINT64_ARRAY);
+ u8Array** valToReturn = va_arg(/*marker*/*markerPtr, u8Array**);
+ u4 len = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ if (len == 0xFFFFFFFF) {
+ *valToReturn = new u8Array(-1);
+ } else {
+ // store result
+ *valToReturn = new u8Array(len);
+ try {
+ for (u4 j = 0; j < len; j++) {
+ (*valToReturn)->GetBuffer()[j] = ComReadU8At(answer, offset);
+ offset += sizeof(u8);
+ }
+ } catch (...) {
+ delete *valToReturn;
+ throw;
+ }
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_STRINGARRAY:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_STRING_ARRAY);
+ StringArray** valToReturn = va_arg(/*marker*/*markerPtr, StringArray**);
+ u4 len = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ if (len == 0xFFFFFFFF) {
+ *valToReturn = new StringArray(-1);
+ } else {
+ // store result
+ *valToReturn = new StringArray(len);
+ try {
+ for (u4 j = 0; j < len; j++) {
+ u2 lenStr = ComReadU2At(answer, offset);
+ offset += sizeof(u2);
+ if (lenStr != 0xFFFF) {
+ u2 blen = ComputeLPSTRLength(answer, offset, lenStr);
+ char* lpstr = new char[blen + 1];
+ try {
+ lpstr[blen] = '\0';
+ UTF8Decode(answer, offset, lenStr, lpstr);
+ offset += lenStr;
+
+ (*valToReturn)->SetStringAt(j, new std::string(lpstr));
+ } catch (...) {
+ delete[] lpstr;
+ throw;
+ }
+ delete[] lpstr;
+ }
+ }
+ } catch (...) {
+ delete *valToReturn;
+ throw;
+ }
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_RET_MEMORYSTREAM:
+ {
+ offset += CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM_IO, HIVECODE_TYPE_SYSTEM_IO_MEMORYSTREAM);
+ MemoryStream** valToReturn = va_arg(/*marker*/*markerPtr, MemoryStream**);
+ u4 len = ComReadU4At(answer, offset);
+ offset += sizeof(u4);
+ if (len == 0xFFFFFFFF) {
+ *valToReturn = new MemoryStream(-1);
+ } else {
+ // store result
+ *valToReturn = new MemoryStream(answer, offset, len);
+ offset += len;
+ }
+ }
+ break;
+
+ default:
+ {
+ throw Exception("Un-recognized return type");
+ }
+ break;
+ }
+
+ //*markerPtr = marker;
+ return offset;
+}
+
+static void ProcessInputArguments(u1 type, u1Array* invokeAPDU_data, va_list* markerPtr)
+{
+ //va_list marker = *markerPtr;
+
+ switch (type) {
+
+ case MARSHALLER_TYPE_IN_BOOL:
+ case MARSHALLER_TYPE_IN_S1:
+ case MARSHALLER_TYPE_IN_U1:
+ {
+ u1 val = (u1)va_arg(/*marker*/*markerPtr, s4);
+ *invokeAPDU_data += val;
+ }
+ break;
+
+ case MARSHALLER_TYPE_IN_CHAR:
+ case MARSHALLER_TYPE_IN_S2:
+ case MARSHALLER_TYPE_IN_U2:
+ {
+ u2 val = (u2)va_arg(/*marker*/*markerPtr, s4);
+ *invokeAPDU_data += val;
+ }
+ break;
+
+ case MARSHALLER_TYPE_IN_S4:
+ case MARSHALLER_TYPE_IN_U4:
+ {
+ u4 val = (u4)va_arg(/*marker*/*markerPtr, s4);
+ *invokeAPDU_data += val;
+ }
+ break;
+
+ case MARSHALLER_TYPE_IN_S8:
+ case MARSHALLER_TYPE_IN_U8:
+ {
+ u8 val = (u8)va_arg(/*marker*/*markerPtr,u8);
+ *invokeAPDU_data += val;
+ }
+ break;
+
+ case MARSHALLER_TYPE_IN_STRING:
+ {
+ std::string* val = va_arg(/*marker*/*markerPtr, std::string*);
+ (*invokeAPDU_data).Append(val);
+ }
+ break;
+
+ case MARSHALLER_TYPE_IN_MEMORYSTREAM:
+ case MARSHALLER_TYPE_IN_BOOLARRAY:
+ case MARSHALLER_TYPE_IN_S1ARRAY:
+ case MARSHALLER_TYPE_IN_U1ARRAY:
+ {
+ u1Array* val = va_arg(/*marker*/*markerPtr, u1Array*);
+ if ((val != NULL) && (val->IsNull() == FALSE)) {
+ u4 valLen = val->GetLength();
+ u1* valBuf = val->GetBuffer();
+ // add length
+ *invokeAPDU_data += valLen;
+ // add data
+ for(u4 v = 0; v < valLen; v++)
+ *invokeAPDU_data += valBuf[v];
+ } else {
+ // add null pointer
+ *invokeAPDU_data += (u4)0xFFFFFFFF;
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_IN_CHARARRAY:
+ case MARSHALLER_TYPE_IN_S2ARRAY:
+ case MARSHALLER_TYPE_IN_U2ARRAY:
+ {
+ u2Array* val = va_arg(/*marker*/*markerPtr, u2Array*);
+ if ((val != NULL) && (val->IsNull() == FALSE)) {
+ u4 valLen = val->GetLength();
+ u2* valBuf = val->GetBuffer();
+ *invokeAPDU_data += valLen;
+ for(u4 v = 0; v < valLen; v++) {
+ *invokeAPDU_data += valBuf[v];
+ }
+ } else {
+ // add null pointer
+ *invokeAPDU_data += (u4)0xFFFFFFFF;
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_IN_S4ARRAY:
+ case MARSHALLER_TYPE_IN_U4ARRAY:
+ {
+ u4Array* val = va_arg(/*marker*/*markerPtr, u4Array*);
+ if ((val != NULL) && (val->IsNull() == FALSE)) {
+ u4 valLen = val->GetLength();
+ u4* valBuf = val->GetBuffer();
+ *invokeAPDU_data += valLen;
+ for(u4 v = 0; v < valLen; v++) {
+ *invokeAPDU_data += valBuf[v];
+ }
+ } else {
+ // add null pointer
+ *invokeAPDU_data += (u4)0xFFFFFFFF;
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_IN_S8ARRAY:
+ case MARSHALLER_TYPE_IN_U8ARRAY:
+ {
+ u8Array* val = va_arg(/*marker*/*markerPtr, u8Array*);
+ if ((val != NULL) && (val->IsNull() == FALSE)) {
+ u4 valLen = val->GetLength();
+ u8* valBuf = val->GetBuffer();
+ *invokeAPDU_data += valLen;
+ for(u4 v = 0; v < valLen; v++) {
+ *invokeAPDU_data += valBuf[v];
+ }
+ } else {
+ // add null pointer
+ *invokeAPDU_data += (u4)0xFFFFFFFF;
+ }
+ }
+ break;
+
+ case MARSHALLER_TYPE_IN_STRINGARRAY:
+ {
+ StringArray* val = va_arg(/*marker*/*markerPtr, StringArray*);
+ if ((val != NULL) && (val->IsNull() == FALSE)) {
+ u4 valLen = val->GetLength();
+ *invokeAPDU_data += valLen;
+ // add data
+ for (u4 j = 0; j < valLen; j++) {
+ std::string* str = val->GetStringAt(j);
+ if(str == NULL){ // add null pointer
+ *invokeAPDU_data += (u2)0xFFFF;
+ }else{
+ (*invokeAPDU_data).Append(str);
+ }
+ }
+ } else {
+ // add null pointer
+ *invokeAPDU_data += (u4)0xFFFFFFFF;
+ }
+ }
+ break;
+
+ default:
+ u4 offset = 0;
+ ProcessByReferenceArguments(type, invokeAPDU_data, &offset, /*markerPtr*/markerPtr, TRUE);
+ // do not adjust markerPtr.
+ return;
+
+ }
+
+ //*markerPtr = marker;
+}
+
+void SmartCardMarshaller::Invoke(s4 nParam, ...)
+{
+ // Allow selfdiscovery of port
+ if (this->portNumber == 0) {
+ s4 _s4 = 0;
+ u4 nameSpaceHivecode = this->nameSpaceHivecode;
+ u2 typeHivecode = this->typeHivecode;
+ std::string* uri = this->uri;
+
+ this->portNumber = CARDMANAGER_SERVICE_PORT;
+ this->nameSpaceHivecode = HIVECODE_NAMESPACE_SMARTCARD;
+ this->typeHivecode = HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER;
+ this->uri = new std::string(CARDMANAGER_SERVICE_NAME);
+
+ try {
+
+ // call the GetAssociatedPort method.
+ Invoke(3, HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT, MARSHALLER_TYPE_IN_S4, nameSpaceHivecode, MARSHALLER_TYPE_IN_S2, typeHivecode, MARSHALLER_TYPE_IN_STRING, uri, MARSHALLER_TYPE_RET_S4, &_s4);
+
+ } catch (...) {
+
+ delete this->uri;
+
+ this->portNumber = (u2)_s4;
+ this->nameSpaceHivecode = nameSpaceHivecode;
+ this->typeHivecode = typeHivecode;
+ this->uri = uri;
+
+ throw;
+ }
+
+ delete this->uri;
+
+ this->portNumber = (u2)_s4;
+ this->nameSpaceHivecode = nameSpaceHivecode;
+ this->typeHivecode = typeHivecode;
+ this->uri = uri;
+ }
+
+ u1Array invokeAPDU(0);
+
+ va_list marker;
+
+ va_start(marker, nParam);
+
+ // add 0xD8
+ invokeAPDU += (u1)0xD8;
+
+ // add port number
+ invokeAPDU += (u2)this->portNumber;
+
+ // add 0x6F
+ invokeAPDU += (u1)0x6F;
+
+ // add namespace Hivecode
+ invokeAPDU += this->nameSpaceHivecode;
+
+ // add type hivecode
+ invokeAPDU += this->typeHivecode;
+
+ // NOTE : va_arg(marker,type)
+ // As per ISO C++ if the pritives types
+ // char,short,byte are passed as argument to varidic method
+ // they are upcasted to int.
+ //
+ // On windows if you use va_arg(marker,u2), no warning will be issued
+ // and there will be no complain at run time, whereas
+ // On Linux (with g++) if you use va_arg(markey,u2), a warning will be issued
+ // saying that it is invalid to do this and run time will fail and it does fail
+ // with message "Segmentation fault".
+ //
+ // So va_arg for all int primitive types (char, short, byte and their unsigned values)
+ // should have s4 as the type.
+
+ // add method name
+ u2 methodID = (u2)va_arg(marker, s4);
+ invokeAPDU += methodID;
+
+ // add uri
+ u1Array uriArray(ComputeUTF8Length((lpCharPtr)this->uri->c_str()));
+ UTF8Encode((lpCharPtr)this->uri->c_str(), uriArray);
+ invokeAPDU += (u2)uriArray.GetLength();
+ invokeAPDU += uriArray;
+
+ u1Array invokeAPDU_data(0);
+
+ // process input arguments
+ for (s4 iParam = 0; iParam < nParam; iParam++) {
+ u1 type = (u1)va_arg(marker, s4);
+ ProcessInputArguments(type, &invokeAPDU_data, &marker);
+ }
+
+ if(ProcessInputStream != NULL){
+ u1Array invokeAPDU_data_Modified(0);
+ ProcessInputStream(invokeAPDU_data,invokeAPDU_data_Modified);
+ invokeAPDU += invokeAPDU_data_Modified;
+ }else{
+ invokeAPDU += invokeAPDU_data;
+ }
+
+ u1Array answer_o(0);
+
+ this->pcsc->BeginTransaction();
+
+ try {
+
+ if(invokeAPDU.GetLength() > (s4)APDU_TO_CARD_MAX_SIZE)
+ {
+ u4 offset = 0;
+ u4 size = invokeAPDU.GetLength() -1 - 2 - 1 - 4 - 2 - 2 - 2 - uriArray.GetLength();
+
+ u1 first = TRUE;
+
+ u4 dataToSendLength = invokeAPDU.GetLength();
+ u4 invokeApduStartOffset = 0;
+
+ while(dataToSendLength > 0){
+
+ u4 encodedSize = size;
+ u4 encodedOffset = (u4)offset;
+
+ u4 subCommandMaxAllowed = APDU_TO_CARD_MAX_SIZE -1 - 2 - 8;
+
+ u4 length = dataToSendLength > subCommandMaxAllowed ? subCommandMaxAllowed : dataToSendLength;
+
+ u1Array subApdu(0);
+
+ if(first == TRUE){
+ u4 usefulDataLength = length -1 - 2 -1 -4 -2 -2 -2 - uriArray.GetLength();
+
+ subApdu += (u1)0xD8;
+ subApdu += (u2)0xFFFF;
+ subApdu += encodedSize;
+ subApdu += usefulDataLength;
+
+ if ((u8)(invokeApduStartOffset + length) > (u8)invokeAPDU.GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+
+ for(u4 j = invokeApduStartOffset; j < (invokeApduStartOffset + length); j++) {
+ subApdu += invokeAPDU.GetBuffer()[j];
+ }
+
+ first = FALSE;
+ offset += usefulDataLength;
+
+ }else{
+
+ subApdu += (u1)0xD8;
+ subApdu += (u2)0xFFFF;
+ subApdu += encodedOffset;
+ subApdu += length;
+
+ if ((u8)(invokeApduStartOffset + length) > (u8)invokeAPDU.GetLength()) {
+ throw ArgumentOutOfRangeException((lpCharPtr)"");
+ }
+
+ for(u4 j = invokeApduStartOffset; j < (invokeApduStartOffset + length); j++) {
+ subApdu += invokeAPDU.GetBuffer()[j];
+ }
+
+ offset += length;
+ }
+
+ size = 0;
+ invokeApduStartOffset = invokeApduStartOffset + length;
+ dataToSendLength = dataToSendLength - length;
+
+ u1Array apduToSend(5);
+
+ apduToSend.GetBuffer()[0] = 0x80;
+ apduToSend.GetBuffer()[1] = 0xC2;
+ apduToSend.GetBuffer()[2] = 0x00;
+ apduToSend.GetBuffer()[3] = 0x00;
+ apduToSend.GetBuffer()[4] = (u1)subApdu.GetLength();
+ apduToSend += subApdu;
+
+ this->pcsc->ExchangeData(apduToSend, answer_o);
+ }
+ }else{
+
+ // construct call
+ u1Array apdu(5);
+ apdu.GetBuffer()[0] = 0x80;
+ apdu.GetBuffer()[1] = 0xC2;
+ apdu.GetBuffer()[2] = 0x00;
+ apdu.GetBuffer()[3] = 0x00;
+ apdu.GetBuffer()[4] = (u1)invokeAPDU.GetLength();
+ apdu += invokeAPDU;
+
+ this->pcsc->ExchangeData(apdu, answer_o);
+ }
+ } catch (...) {
+ this->pcsc->EndTransaction();
+ throw;
+ }
+
+ this->pcsc->EndTransaction();
+
+ u1Array answer(0);
+
+ if ((ProcessOutputStream != NULL) && (answer_o.GetLength() > 0) && (answer_o.ReadU1At(0) == 0x01)){
+ u1Array answerI(0);
+ u1Array answerM(0);
+
+ for(u4 i = 1; i < answer_o.GetLength(); i++){
+ answerI += answer_o.GetBuffer()[i];
+ }
+
+ ProcessOutputStream(answerI, answerM);
+
+ answer += answer_o.GetBuffer()[0];
+
+ for(u4 i=0;i<answerM.GetLength();i++){
+ answer += answerM.GetBuffer()[i];
+ }
+
+ } else {
+ for(u4 i=0;i<answer_o.GetLength();i++)
+ answer += answer_o.GetBuffer()[i];
+ }
+
+ // analyze return type
+ u4 offset = ProcessReturnType((u1)va_arg(marker, s4), &answer, &marker);
+
+ va_end(marker);
+
+ // process byref types
+ va_start(marker, nParam);
+
+ // skip method name param
+ u2 methodID2 = (u2)va_arg(marker, s4);
+
+ if (methodID2 == methodID) {
+ for (s4 iParam = 0; iParam < nParam; iParam++) {
+ u1 type = (u1)va_arg(marker, s4);
+ ProcessOutputArguments(type, &answer, &offset, &marker);
+ }
+ }
+
+ va_end(marker);
+}
+
+void SmartCardMarshaller::SetInputStream(pCommunicationStream inStream){
+ this->ProcessInputStream = inStream;
+}
+
+void SmartCardMarshaller::SetOutputStream(pCommunicationStream outStream){
+ this->ProcessOutputStream = outStream;
+}
+
+MARSHALLER_NS_END
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/Marshaller.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,77 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_marshaller_h
+#define _include_marshaller_h
+
+#ifdef _XCL_
+#include "xcl_broker.h"
+#endif // _XCL_
+
+MARSHALLER_NS_BEGIN
+
+typedef void (*pCommunicationStream)(u1Array& st,u1Array& stM);
+
+class SMARTCARDMARSHALLER_DLLAPI SmartCardMarshaller
+{
+
+private:
+ u4 nameSpaceHivecode;
+ u2 typeHivecode;
+ u2 portNumber;
+ std::string* uri;
+#ifndef _XCL_
+ PCSC* pcsc;
+#else // _XCL_
+ XCLBroker* pcsc;
+#endif // _XCL_
+
+ pCommunicationStream ProcessInputStream;
+ pCommunicationStream ProcessOutputStream;
+
+public:
+ // Existing PCSC connection
+ SmartCardMarshaller(SCARDHANDLE pcscCardHandle, u2 portNumber,M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode);
+
+ // PCSC compatible readers
+ SmartCardMarshaller(M_SAL_IN std::string* readerName, u2 portNumber,M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode, u4 index);
+
+ // destructor
+ ~SmartCardMarshaller(void);
+
+ // Remoting marshalling method
+ void Invoke(s4 nParam, ...);
+
+ void UpdatePCSCCardHandle(SCARDHANDLE hCard);
+
+ void SetInputStream(pCommunicationStream inStream);
+ void SetOutputStream(pCommunicationStream outStream);
+
+ std::string* GetReaderName();
+ SCARDHANDLE GetCardHandle();
+ void DoTransact(bool flag);
+
+};
+
+MARSHALLER_NS_END
+
+#endif
+
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/MarshallerCfg.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/MarshallerCfg.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/MarshallerCfg.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,167 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_marshallercfg_h
+#define _include_marshallercfg_h
+
+#ifdef SMARTCARDMARSHALLER_EXPORTS
+ #define SMARTCARDMARSHALLER_DLLAPI __declspec(dllexport)
+#else
+ #define SMARTCARDMARSHALLER_DLLAPI
+#endif
+
+#ifdef M_SAL_ANNOTATIONS
+#include <specstrings.h>
+#define M_SAL_IN __in
+#define M_SAL_OUT __out
+#define M_SAL_INOUT __inout
+#else
+#define M_SAL_IN
+#define M_SAL_OUT
+#define M_SAL_INOUT
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef WIN32
+#include <inttypes.h>
+#endif
+
+// data types
+typedef unsigned char u1;
+typedef unsigned short u2;
+typedef unsigned int u4;
+typedef char s1;
+typedef short s2;
+typedef int s4;
+
+#ifdef WIN32
+typedef unsigned __int64 u8;
+typedef __int64 s8;
+typedef LPSTR lpCharPtr;
+typedef LPTSTR lpTCharPtr;
+typedef LPBYTE lpByte;
+typedef const lpByte lpCByte;
+#else
+typedef uint64_t u8;
+typedef int64_t s8;
+typedef char* lpTCharPtr;
+typedef char* lpCharPtr;
+typedef unsigned char* lpByte;
+typedef const lpByte lpCByte;
+#endif
+
+// Marshaller argument type constants
+#define MARSHALLER_TYPE_IN_VOID 0
+#define MARSHALLER_TYPE_IN_BOOL 1
+#define MARSHALLER_TYPE_IN_S1 2
+#define MARSHALLER_TYPE_IN_U1 3
+#define MARSHALLER_TYPE_IN_CHAR 4
+#define MARSHALLER_TYPE_IN_S2 5
+#define MARSHALLER_TYPE_IN_U2 6
+#define MARSHALLER_TYPE_IN_S4 7
+#define MARSHALLER_TYPE_IN_U4 8
+#define MARSHALLER_TYPE_IN_S8 9
+#define MARSHALLER_TYPE_IN_U8 10
+#define MARSHALLER_TYPE_IN_STRING 11
+
+#define MARSHALLER_TYPE_IN_BOOLARRAY 21
+#define MARSHALLER_TYPE_IN_S1ARRAY 22
+#define MARSHALLER_TYPE_IN_U1ARRAY 23
+#define MARSHALLER_TYPE_IN_CHARARRAY 24
+#define MARSHALLER_TYPE_IN_S2ARRAY 25
+#define MARSHALLER_TYPE_IN_U2ARRAY 26
+#define MARSHALLER_TYPE_IN_S4ARRAY 27
+#define MARSHALLER_TYPE_IN_U4ARRAY 28
+#define MARSHALLER_TYPE_IN_S8ARRAY 29
+#define MARSHALLER_TYPE_IN_U8ARRAY 30
+#define MARSHALLER_TYPE_IN_STRINGARRAY 31
+
+#define MARSHALLER_TYPE_IN_MEMORYSTREAM 40
+
+#define MARSHALLER_TYPE_REF_BOOL 50
+#define MARSHALLER_TYPE_REF_S1 51
+#define MARSHALLER_TYPE_REF_U1 52
+#define MARSHALLER_TYPE_REF_CHAR 53
+#define MARSHALLER_TYPE_REF_S2 54
+#define MARSHALLER_TYPE_REF_U2 55
+#define MARSHALLER_TYPE_REF_S4 56
+#define MARSHALLER_TYPE_REF_U4 57
+#define MARSHALLER_TYPE_REF_S8 58
+#define MARSHALLER_TYPE_REF_U8 59
+#define MARSHALLER_TYPE_REF_STRING 60
+
+#define MARSHALLER_TYPE_REF_BOOLARRAY 61
+#define MARSHALLER_TYPE_REF_S1ARRAY 62
+#define MARSHALLER_TYPE_REF_U1ARRAY 63
+#define MARSHALLER_TYPE_REF_CHARARRAY 64
+#define MARSHALLER_TYPE_REF_S2ARRAY 65
+#define MARSHALLER_TYPE_REF_U2ARRAY 66
+#define MARSHALLER_TYPE_REF_S4ARRAY 67
+#define MARSHALLER_TYPE_REF_U4ARRAY 68
+#define MARSHALLER_TYPE_REF_S8ARRAY 69
+#define MARSHALLER_TYPE_REF_U8ARRAY 70
+#define MARSHALLER_TYPE_REF_STRINGARRAY 71
+
+// Marshaller return type arguments
+#define MARSHALLER_TYPE_RET_VOID MARSHALLER_TYPE_IN_VOID
+#define MARSHALLER_TYPE_RET_BOOL MARSHALLER_TYPE_IN_BOOL
+#define MARSHALLER_TYPE_RET_S1 MARSHALLER_TYPE_IN_S1
+#define MARSHALLER_TYPE_RET_U1 MARSHALLER_TYPE_IN_U1
+#define MARSHALLER_TYPE_RET_CHAR MARSHALLER_TYPE_IN_CHAR
+#define MARSHALLER_TYPE_RET_S2 MARSHALLER_TYPE_IN_S2
+#define MARSHALLER_TYPE_RET_U2 MARSHALLER_TYPE_IN_U2
+#define MARSHALLER_TYPE_RET_S4 MARSHALLER_TYPE_IN_S4
+#define MARSHALLER_TYPE_RET_U4 MARSHALLER_TYPE_IN_U4
+#define MARSHALLER_TYPE_RET_S8 MARSHALLER_TYPE_IN_S8
+#define MARSHALLER_TYPE_RET_U8 MARSHALLER_TYPE_IN_U8
+#define MARSHALLER_TYPE_RET_STRING MARSHALLER_TYPE_IN_STRING
+
+#define MARSHALLER_TYPE_RET_BOOLARRAY MARSHALLER_TYPE_IN_BOOLARRAY
+#define MARSHALLER_TYPE_RET_S1ARRAY MARSHALLER_TYPE_IN_S1ARRAY
+#define MARSHALLER_TYPE_RET_U1ARRAY MARSHALLER_TYPE_IN_U1ARRAY
+#define MARSHALLER_TYPE_RET_CHARARRAY MARSHALLER_TYPE_IN_CHARARRAY
+#define MARSHALLER_TYPE_RET_S2ARRAY MARSHALLER_TYPE_IN_S2ARRAY
+#define MARSHALLER_TYPE_RET_U2ARRAY MARSHALLER_TYPE_IN_U2ARRAY
+#define MARSHALLER_TYPE_RET_S4ARRAY MARSHALLER_TYPE_IN_S4ARRAY
+#define MARSHALLER_TYPE_RET_U4ARRAY MARSHALLER_TYPE_IN_U4ARRAY
+#define MARSHALLER_TYPE_RET_S8ARRAY MARSHALLER_TYPE_IN_S8ARRAY
+#define MARSHALLER_TYPE_RET_U8ARRAY MARSHALLER_TYPE_IN_U8ARRAY
+#define MARSHALLER_TYPE_RET_STRINGARRAY MARSHALLER_TYPE_IN_STRINGARRAY
+
+#define MARSHALLER_TYPE_RET_MEMORYSTREAM MARSHALLER_TYPE_IN_MEMORYSTREAM
+
+// namespace for the module
+// in case compiler does not support namespace, the defines can be undefined
+#define MARSHALLER_NS_BEGIN namespace Marshaller {
+#define MARSHALLER_NS_END }
+
+#endif
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.cpp
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.cpp (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.cpp 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,557 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef WIN32
+#include <Windows.h>
+#pragma warning(push)
+#pragma warning(disable : 4201)
+#else
+#define DBG_UNREFERENCED_LOCAL_VARIABLE(a)
+#endif
+
+//#ifdef _MAC_OS_X
+#ifdef __APPLE__
+#include <wintypes.h>
+#include <pcsclite.h>
+#endif
+
+#ifndef WIN32
+#include <strings.h>
+#endif
+#include <string.h>
+#include <winscard.h>
+#include <stdexcept>
+#include "MarshallerCfg.h"
+#include "Array.h"
+#include "PCSC.h"
+#include "Except.h"
+
+
+#ifdef __sun
+typedef LPSTR LPTSTR;
+#endif
+
+// JCD
+#include "log.h"
+
+
+
+MARSHALLER_NS_BEGIN
+
+extern u4 CheckForException(u1Array answer, u4 nameSpace, u2 type);
+extern u4 ComReadU4At(u1Array &array, u4 pos);
+
+#define SUPPORT_BETA_VERSION
+
+const u1 isNetCardAPDU[] = {0x80,0xC2,0x00,0x00,0x1C,0xD8,0x00,0x01,0x6F,0x00,0xF5,0xEF,0xBF,0xB1,0x8C,0xDD,0xC2,0x00,0x0E,0x43,0x6F,0x6E,0x74,0x65,0x6E,0x74,0x4D,0x61,0x6E,0x61,0x67,0x65,0x72};
+
+#define APDU_TO_CARD_MAX_SIZE 0xFF
+#define CARDMANAGER_SERVICE_PORT 1
+#define CARDMANAGER_SERVICE_NAME "ContentManager"
+
+#define HIVECODE_NAMESPACE_SMARTCARD 0x00F5EFBF
+#define HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER 0xB18C
+#define HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT 0x7616
+#define HIVECODE_NAMESPACE_SYSTEM 0x00D25D1C
+#define HIVECODE_TYPE_SYSTEM_INT32 0x61C0
+
+
+// *******************
+// PCSC class
+// *******************
+PCSC::PCSC(M_SAL_IN std::string* readerName)
+{
+ DWORD activeProtocol;
+ LONG lReturn;
+
+ this->hContext = 0;
+ this->hCard = 0;
+
+ lReturn = SCardEstablishContext(0, NULL, NULL, &this->hContext);
+ if(lReturn != SCARD_S_SUCCESS) {
+ throw RemotingException((lpCharPtr)"PCSC: SCardEstablishContext error",lReturn);
+ }
+
+ lReturn = SCardConnect(this->hContext, (LPTSTR)readerName->c_str(), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &this->hCard, &activeProtocol);
+ if (lReturn != SCARD_S_SUCCESS) {
+ throw RemotingException((lpCharPtr)"PCSC: SCardConnect error",lReturn);
+ }
+
+ this->readerName = new std::string(readerName->c_str());
+}
+
+PCSC::PCSC(M_SAL_IN std::string* inputReaderName, u2* portNumber, M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode, u4 index)
+{
+ Log::begin( "PCSC::PCSC" );
+
+ std::string selfDiscover("selfdiscover");
+ std::string* identifiedReaderName;
+ LPTSTR pReaderList = NULL;
+ LONG lReturn;
+
+ if (inputReaderName == NULL) {
+ inputReaderName = &selfDiscover;
+ }
+
+ identifiedReaderName = NULL;
+ this->hContext = 0;
+ this->hCard = 0;
+
+ lReturn = SCardEstablishContext(0, NULL, NULL, &this->hContext);
+ Log::log( "PCSC::PCSC - SCardEstablishContext <%#02x>", lReturn );
+ if(lReturn != SCARD_S_SUCCESS)
+ {
+ Log::log( "PCSC::PCSC - ## ERROR ## SCardEstablishContext <%#02x>", lReturn );
+ throw RemotingException((lpCharPtr)"PCSC: SCardEstablishContext error",lReturn);
+ }
+
+ // self-discovery mechanism
+#ifdef WIN32
+ if (_stricmp("selfdiscover", inputReaderName->c_str()) == 0) {
+#else
+ if (strncasecmp("selfdiscover", inputReaderName->c_str(),inputReaderName->length()) == 0) {
+#endif
+ // In Windows SCARD_AUTOALLOCATE (-1) as a value of readerListChatLength
+ // would signal the SCardListReaders to determine the size of reader string
+ // This is not available in Linux so we call the SCardListReaders twice. First
+ // to get the length and then the reader names.
+#ifdef WIN32
+ DWORD readerListCharLength = SCARD_AUTOALLOCATE;
+ lReturn = SCardListReaders(this->hContext, NULL, (LPTSTR)&pReaderList, &readerListCharLength);
+ Log::log( "PCSC::PCSC - SCardListReaders <%#02x>", lReturn );
+
+#else
+ DWORD readerListCharLength = 0;
+
+ lReturn = SCardListReaders(this->hContext,NULL,NULL,&readerListCharLength);
+ if(lReturn != SCARD_S_SUCCESS)
+ throw RemotingException((lpCharPtr)"PCSC: SCardListReaders error",lReturn);
+
+ pReaderList = (lpCharPtr)malloc(sizeof(char)*readerListCharLength);
+ lReturn = SCardListReaders(this->hContext, NULL,pReaderList, &readerListCharLength);
+#endif
+
+
+ if(lReturn != SCARD_S_SUCCESS)
+ {
+ Log::log( "PCSC::PCSC - ## ERROR ## SCardListReaders <%#02x>", lReturn );
+ throw RemotingException((lpCharPtr)"PCSC: SCardListReaders error",lReturn);
+ }
+ else
+ {
+ u4 count = 0;
+ u1 foundReader = FALSE;
+ SCARDHANDLE finalCardHandle = 0;
+ try
+ {
+ lpTCharPtr pReader = pReaderList;
+ while ('\0' != *pReader )
+ {
+ size_t readerNameLen = strlen((const char*)pReader);
+ SCARD_READERSTATE readerStates[1];
+ readerStates[0].dwCurrentState = SCARD_STATE_UNAWARE;
+ readerStates[0].szReader = pReader;
+ if (SCardGetStatusChange(this->hContext, 0, readerStates, 1) == SCARD_S_SUCCESS)
+ {
+ if ((readerStates[0].dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT)
+ {
+ // we found a card in this reader
+ if (identifiedReaderName != NULL)
+ {
+ delete identifiedReaderName;
+ identifiedReaderName = NULL;
+ }
+
+ identifiedReaderName = new std::string((lpCharPtr)pReader);
+ DWORD activeProtocol;
+
+ Log::log( "PCSC::PCSC SCardConnect..." );
+ lReturn = SCardConnect(this->hContext, (LPTSTR)identifiedReaderName->c_str(), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &this->hCard, &activeProtocol);
+ Log::log( "PCSC::PCSC - SCardConnect <%#02x>", lReturn );
+
+ if (lReturn == SCARD_S_SUCCESS)
+ {
+ // try to identify if we're dealing with a .NetCard
+ u1 answerData[258];
+ DWORD answerLen = 258;
+
+ Log::log( "PCSC::PCSC SCardTransmit..." );
+ lReturn = SCardTransmit(hCard, SCARD_PCI_T0, isNetCardAPDU, sizeof(isNetCardAPDU), NULL, (LPBYTE)answerData, &answerLen);
+ Log::log( "PCSC::PCSC - SCardTransmit <%#02x>", lReturn );
+
+ if (lReturn == SCARD_S_SUCCESS)
+ {
+ u1 rethrowException = FALSE;
+ try {
+ if (answerData[answerLen - 2] == 0x61)
+ {
+ if (answerData[answerLen - 1] > 10)
+ {
+ u1Array invokeAPDU(0);
+ invokeAPDU += (u1)0xD8;
+ invokeAPDU += (u2)CARDMANAGER_SERVICE_PORT;
+ invokeAPDU += (u1)0x6F;
+ invokeAPDU += (u4)HIVECODE_NAMESPACE_SMARTCARD;
+ invokeAPDU += (u2)HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER;
+ invokeAPDU += (u2)HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT;
+ std::string* cmServiceUri = new std::string(CARDMANAGER_SERVICE_NAME);
+ invokeAPDU.Append(cmServiceUri);
+ delete cmServiceUri;
+ invokeAPDU += (u4)nameSpaceHivecode;
+ invokeAPDU += (u2)typeHivecode;
+ invokeAPDU.Append(uri);
+
+ // construct call
+ if(invokeAPDU.GetLength() <= (s4)APDU_TO_CARD_MAX_SIZE) {
+ u1Array apdu(5);
+ apdu.GetBuffer()[0] = 0x80;
+ apdu.GetBuffer()[1] = 0xC2;
+ apdu.GetBuffer()[2] = 0x00;
+ apdu.GetBuffer()[3] = 0x00;
+ apdu.GetBuffer()[4] = (u1)invokeAPDU.GetLength();
+ apdu += invokeAPDU;
+
+ u1Array answer(0);
+
+ Log::log( "PCSC::PCSC - ExchangeData..." );
+ this->ExchangeData(apdu, answer);
+ Log::log( "PCSC::PCSC - ExchangeData ok" );
+
+ Log::log( "PCSC::PCSC - CheckForException..." );
+ u4 protocolOffset = CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT32);
+ Log::log( "PCSC::PCSC - CheckForException ok" );
+
+ u4 discoveredPortNumber = ComReadU4At(answer, protocolOffset);
+ if ((*portNumber == 0) || (discoveredPortNumber == *portNumber))
+ {
+ *portNumber = (u2)discoveredPortNumber;
+
+ if (foundReader == TRUE)
+ {
+ if (index == 0)
+ {
+ // this is the second reader/card/app that matches - we error at this point
+ rethrowException = TRUE;
+ char errorMessage[255];
+ strcpy(errorMessage, "At least 2 cards posses \"");
+ strcat(errorMessage, uri->c_str());
+ strcat(errorMessage, "\" service\r\nRemove conflicting cards from your system");
+
+ Log::error( "PCSC::PCSC", errorMessage );
+
+ throw RemotingException(errorMessage);
+ }
+ }
+
+ foundReader = TRUE;
+ finalCardHandle = this->hCard;
+
+ // Advance to the next value.
+ count++;
+
+ if (count == index)
+ {
+ // we enumerate one by one the valid readers - so stop here
+ break;
+ }
+
+ pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
+ continue;
+ }
+ }
+ }
+ }
+ }
+ catch (...)
+ {
+ if (rethrowException == TRUE)
+ {
+ throw;
+ }
+ else
+ {
+ // swallow exception
+ }
+ }
+
+ SCardDisconnect(this->hCard, SCARD_LEAVE_CARD);
+ this->hCard = 0;
+ }
+ // this is not a .NetCard, or the service was not found - let's try another reader/card
+ else
+ {
+ Log::error( "PCSC::PCSC", "SCardTransmit failed" );
+ }
+ }
+ else
+ {
+ Log::error( "PCSC::PCSC", "SCardConnect failed" );
+ }
+ }
+ else
+ {
+ Log::error( "PCSC::PCSC", "SCARD_STATE_PRESENT not present" );
+ }
+ }
+ else
+ {
+ Log::error( "PCSC::PCSC", "SCardGetStatusChange != SCARD_S_SUCCESS" );
+ }
+
+ // Advance to the next value.
+ pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1);
+ }
+ } catch (...) {
+ if (identifiedReaderName != NULL) {
+ delete identifiedReaderName;
+ }
+
+#ifdef WIN32
+ lReturn = SCardFreeMemory(this->hContext, pReaderList);
+ if(lReturn != SCARD_S_SUCCESS) {
+ throw RemotingException((lpCharPtr)"PCSC: SCardFreeMemory error",lReturn);
+ }
+#else
+ if(pReaderList != NULL)
+ free(pReaderList);
+#endif
+ throw;
+ }
+
+ // have we found anything ?
+ if (foundReader == FALSE) {
+ if (identifiedReaderName != NULL) {
+ delete identifiedReaderName;
+ }
+
+#ifdef WIN32
+ lReturn = SCardFreeMemory(this->hContext, pReaderList);
+ if(lReturn != SCARD_S_SUCCESS) {
+ throw RemotingException((lpCharPtr)"PCSC: SCardFreeMemory error",lReturn);
+ }
+#else
+ if(pReaderList != NULL)
+ free(pReaderList);
+#endif
+
+ throw RemotingException((lpCharPtr)"Could not find any Cryptoflex .NET smart card",SCARD_E_NO_SMARTCARD);
+ }
+
+ this->hCard = finalCardHandle;
+ }
+
+ this->readerName = new std::string(identifiedReaderName->c_str());
+
+ delete identifiedReaderName;
+
+ } else {
+ this->readerName = new std::string(inputReaderName->c_str());
+ }
+
+ Log::end( "PCSC::PCSC" );
+}
+
+PCSC::PCSC(SCARDHANDLE cardHandle)
+{
+ this->hContext = 0;
+ this->hCard = cardHandle;
+ this->readerName = NULL;
+ this->fDoTransact = true;
+}
+
+std::string* PCSC::GetReaderName(void)
+{
+ return this->readerName;
+}
+
+void PCSC::BeginTransaction(void)
+{
+ if(fDoTransact) // TODO: TEST RETURN CODE!!
+ SCardBeginTransaction(this->hCard);
+}
+
+void PCSC::EndTransaction(void)
+{
+ if(fDoTransact) // TODO: TEST RETURN CODE!!
+ SCardEndTransaction(this->hCard, SCARD_LEAVE_CARD);
+}
+
+SCARDHANDLE PCSC::GetCardHandle(void)
+{
+ return this->hCard;
+}
+
+void PCSC::SetCardHandle(SCARDHANDLE hCard)
+{
+ this->hCard = hCard;
+}
+
+void PCSC::DoTransact(bool flag)
+{
+ this->fDoTransact = flag;
+}
+
+void PCSC::ExchangeData(u1Array &dataIn, u1Array &dataout)
+{
+ u1 answerData[258];
+
+ // check validity of handle
+ if (this->hCard == 0) {
+ throw RemotingException((lpCharPtr)"PCSC: Invalid card handle", SCARD_E_INVALID_HANDLE);
+ }
+
+#ifdef __DEBUG_APDU__
+ FILE *pFile = fopen("C:\\AxaltoProtocolAnalyzer.txt","a");
+#endif
+
+ try {
+
+ BeginTransaction();
+
+ DWORD answerLen = sizeof(answerData);
+
+#ifdef __DEBUG_APDU__
+ fprintf(pFile, "APDU DataIn Buffer\n");
+ for(int i=0; i < (s4)dataIn.GetLength(); i++) {
+ fprintf(pFile, "%02x",dataIn.GetBuffer()[i]);
+ }
+ fprintf(pFile, "\n");
+#endif
+
+ s4 lReturn = SCardTransmit(hCard, SCARD_PCI_T0, dataIn.GetBuffer(), dataIn.GetLength(), NULL, (lpByte)answerData, &answerLen);
+ if (lReturn != SCARD_S_SUCCESS) {
+ throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error",lReturn);
+ }
+
+ if (answerLen < 2) {
+ throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error - Incorrect length returned",SCARD_F_COMM_ERROR);
+ }
+
+ if (answerLen > 2) {
+ u1Array temp(answerLen - 2);
+ temp.SetBuffer(answerData);
+ dataout += temp;
+#ifdef __DEBUG_APDU__
+ fprintf(pFile, "APDU DataOut Buffer\n");
+ for(int i=0; i< (s4)temp.GetLength(); i++) {
+ fprintf(pFile, "%02x",temp.GetBuffer()[i]);
+ }
+ fprintf(pFile, "\n");
+#endif
+ }
+
+ u1 sw1 = answerData[answerLen - 2];
+ u1 sw2 = answerData[answerLen - 1];
+
+#ifdef __DEBUG_APDU__
+ fprintf(pFile, "APDU Status Buffer\n");
+ fprintf(pFile, "%02x%02x",sw1,sw2);
+ fprintf(pFile, "\n");
+#endif
+
+ while ((sw1 == 0x61) || (sw1 == 0x9F))
+ {
+ u1 GetResponse[5];
+ if (sw1 == 0x9F) {
+ GetResponse[0] = 0xA0;
+ } else {
+ GetResponse[0] = 0x00;
+ }
+ GetResponse[1] = 0xC0;
+ GetResponse[2] = 0x00;
+ GetResponse[3] = 0x00;
+ GetResponse[4] = sw2;
+ answerLen = 258;
+
+#ifdef __DEBUG_APDU__
+ fprintf(pFile, "APDU DataIn Buffer\n");
+ for(int i=0; i<5; i++) {
+ fprintf(pFile, "%02x",GetResponse[i]);
+ }
+ fprintf(pFile, "\n");
+#endif
+
+ lReturn = SCardTransmit(hCard, SCARD_PCI_T0, (lpCByte)GetResponse, 5, NULL, (lpByte)answerData, &answerLen);
+ if (lReturn != SCARD_S_SUCCESS) {
+ throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error",lReturn);
+ }
+
+ if (answerLen < 2) {
+ throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error - Incorrect length returned",SCARD_F_COMM_ERROR);
+ }
+
+ if (answerLen > 2) {
+ u1Array temp(answerLen - 2);
+ temp.SetBuffer(answerData);
+ dataout += temp;
+#ifdef __DEBUG_APDU__
+ fprintf(pFile, "APDU DataOut Buffer\n");
+ for(int i=0; i< (s4)temp.GetLength(); i++) {
+ fprintf(pFile, "%02x",temp.GetBuffer()[i]);
+ }
+ fprintf(pFile, "\n");
+#endif
+ }
+ sw1 = answerData[answerLen - 2];
+ sw2 = answerData[answerLen - 1];
+
+#ifdef __DEBUG_APDU__
+ fprintf(pFile, "APDU Status Buffer\n");
+ fprintf(pFile, "%02x%02x",sw1,sw2);
+ fprintf(pFile, "\n");
+#endif
+ }
+ } catch (...) {
+#ifdef __DEBUG_APDU__
+ fflush(pFile);
+ fclose(pFile);
+#endif
+ EndTransaction();
+ throw;
+ }
+
+#ifdef __DEBUG_APDU__
+ fflush(pFile);
+ fclose(pFile);
+#endif
+
+ EndTransaction();
+}
+
+PCSC::~PCSC(void)
+{
+ // we cleanup the various context and card handle only if we allocated it (depends of constructor)
+ if (hContext != 0) {
+ if (hCard != 0) {
+ SCardDisconnect(hCard, SCARD_LEAVE_CARD);
+ hCard = 0;
+ }
+ SCardReleaseContext(hContext);
+ hContext = 0;
+ }
+
+ if (this->readerName != NULL) {
+ delete this->readerName;
+ this->readerName = NULL;
+ }
+}
+
+MARSHALLER_NS_END
+
Added: trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.h
===================================================================
--- trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.h (rev 0)
+++ trunk/SmartCardServices/src/PKCS11dotNetV2/cppMarshaller/PCSC.h 2009-12-17 08:49:36 UTC (rev 72)
@@ -0,0 +1,53 @@
+/*
+ * PKCS#11 library for .Net smart cards
+ * Copyright (C) 2007-2009 Gemalto <support at gemalto.com>
+ *
+ * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef _include_marshaller_pcsc_h
+#define _include_marshaller_pcsc_h
+
+MARSHALLER_NS_BEGIN
+
+class PCSC
+{
+
+private:
+ SCARDCONTEXT hContext;
+ SCARDHANDLE hCard;
+ std::string* readerName;
+ bool fDoTransact;
+
+public:
+ PCSC(SCARDHANDLE cardHandle);
+ PCSC(M_SAL_IN std::string* readerName);
+ PCSC(M_SAL_IN std::string* readerName, u2* portNumber, M_SAL_IN std::string* uri, u4 nameSpaceHivecode, u2 typeHivecode, u4 index);
+ SCARDHANDLE GetCardHandle(void);
+ void SetCardHandle(SCARDHANDLE hCard);
+ void DoTransact(bool flag);
+ std::string* GetReaderName(void);
+ void BeginTransaction(void);
+ void EndTransaction(void);
+ void ExchangeData(u1Array &dataIn, u1Array &dataout);
+ ~PCSC(void);
+
+};
+
+MARSHALLER_NS_END
+
+#endif
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/smartcardservices-changes/attachments/20091217/80e29782/attachment-0001.html>
More information about the SmartcardServices-Changes
mailing list